]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
Imported from ../bash-1.14.7.tar.gz.
authorJari Aalto <jari.aalto@cante.net>
Mon, 26 Aug 1996 18:22:31 +0000 (18:22 +0000)
committerJari Aalto <jari.aalto@cante.net>
Sat, 12 Sep 2009 16:46:49 +0000 (16:46 +0000)
402 files changed:
.distribution [new file with mode: 0644]
.patchlevel [new file with mode: 0644]
COPYING [new file with mode: 0644]
CWRU/PLATFORMS [new file with mode: 0644]
CWRU/POSIX.NOTES [new file with mode: 0644]
CWRU/README [new file with mode: 0644]
CWRU/changelog [new file with mode: 0644]
CWRU/misc/aux-mach-desc [new file with mode: 0644]
CWRU/misc/bison [new file with mode: 0755]
CWRU/misc/open-files.c [new file with mode: 0644]
CWRU/misc/pid.c [new file with mode: 0644]
CWRU/misc/sigs.c [new file with mode: 0644]
CWRU/misc/sigstat.c [new file with mode: 0644]
CWRU/sh-redir-hack [new file with mode: 0644]
INSTALL [new file with mode: 0644]
MANIFEST [new file with mode: 0644]
Makefile [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
RELEASE [new file with mode: 0644]
alias.c [new file with mode: 0644]
alias.h [new file with mode: 0644]
ansi_stdlib.h [new file with mode: 0644]
bashansi.h [new file with mode: 0644]
bashhist.c [new file with mode: 0644]
bashhist.h [new file with mode: 0644]
bashline.c [new file with mode: 0644]
bashtypes.h [new file with mode: 0644]
bracecomp.c [new file with mode: 0644]
braces.c [new file with mode: 0644]
builtins.h [new file with mode: 0644]
builtins/ChangeLog [new file with mode: 0644]
builtins/Makefile [new file with mode: 0644]
builtins/alias.def [new file with mode: 0644]
builtins/bashgetopt.c [new file with mode: 0644]
builtins/bashgetopt.h [new file with mode: 0644]
builtins/bind.def [new file with mode: 0644]
builtins/break.def [new file with mode: 0644]
builtins/builtin.def [new file with mode: 0644]
builtins/cd.def [new file with mode: 0644]
builtins/colon.def [new file with mode: 0644]
builtins/command.def [new file with mode: 0644]
builtins/common.c [new file with mode: 0644]
builtins/common.h [new file with mode: 0644]
builtins/declare.def [new file with mode: 0644]
builtins/echo.def [new file with mode: 0644]
builtins/enable.def [new file with mode: 0644]
builtins/eval.def [new file with mode: 0644]
builtins/exec.def [new file with mode: 0644]
builtins/exit.def [new file with mode: 0644]
builtins/fc.def [new file with mode: 0644]
builtins/fg_bg.def [new file with mode: 0644]
builtins/getopt.c [new file with mode: 0644]
builtins/getopt.h [new file with mode: 0644]
builtins/getopts.def [new file with mode: 0644]
builtins/hash.def [new file with mode: 0644]
builtins/hashcom.h [new file with mode: 0644]
builtins/help.def [new file with mode: 0644]
builtins/history.def [new file with mode: 0644]
builtins/inlib.def [new file with mode: 0644]
builtins/jobs.def [new file with mode: 0644]
builtins/kill.def [new file with mode: 0644]
builtins/let.def [new file with mode: 0644]
builtins/mkbuiltins.c [new file with mode: 0644]
builtins/psize.c [new file with mode: 0644]
builtins/psize.sh [new file with mode: 0755]
builtins/read.def [new file with mode: 0644]
builtins/reserved.def [new file with mode: 0644]
builtins/return.def [new file with mode: 0644]
builtins/set.def [new file with mode: 0644]
builtins/setattr.def [new file with mode: 0644]
builtins/shift.def [new file with mode: 0644]
builtins/source.def [new file with mode: 0644]
builtins/suspend.def [new file with mode: 0644]
builtins/test.def [new file with mode: 0644]
builtins/times.def [new file with mode: 0644]
builtins/trap.def [new file with mode: 0644]
builtins/type.def [new file with mode: 0644]
builtins/ulimit.def [new file with mode: 0644]
builtins/umask.def [new file with mode: 0644]
builtins/wait.def [new file with mode: 0644]
command.h [new file with mode: 0644]
config.h [new file with mode: 0644]
config.h.mini [new file with mode: 0644]
configure [new file with mode: 0755]
copy_cmd.c [new file with mode: 0644]
cpp-Makefile [new file with mode: 0644]
dispose_cmd.c [new file with mode: 0644]
dispose_cmd.h [new file with mode: 0644]
documentation/FAQ [new file with mode: 0644]
documentation/Makefile [new file with mode: 0644]
documentation/README [new file with mode: 0644]
documentation/article.ms [new file with mode: 0644]
documentation/article.ps [new file with mode: 0644]
documentation/article.txt [new file with mode: 0644]
documentation/bash.1 [new file with mode: 0644]
documentation/bash.ps [new file with mode: 0644]
documentation/bash.txt [new file with mode: 0644]
documentation/builtins.1 [new file with mode: 0644]
documentation/builtins.ps [new file with mode: 0644]
documentation/builtins.txt [new file with mode: 0644]
documentation/features.dvi [new file with mode: 0644]
documentation/features.info [new file with mode: 0644]
documentation/features.ps [new file with mode: 0644]
documentation/features.texi [new file with mode: 0644]
documentation/readline.3 [new file with mode: 0644]
documentation/readline.ps [new file with mode: 0644]
documentation/readline.txt [new file with mode: 0644]
documentation/texinfo.tex [new file with mode: 0644]
endian.c [new file with mode: 0644]
error.c [new file with mode: 0644]
error.h [new file with mode: 0644]
examples/alias-conv.sh [new file with mode: 0755]
examples/functions/autoload [new file with mode: 0644]
examples/functions/basename [new file with mode: 0644]
examples/functions/csh-compat [new file with mode: 0644]
examples/functions/dirfuncs [new file with mode: 0644]
examples/functions/dirname [new file with mode: 0644]
examples/functions/exitstat [new file with mode: 0644]
examples/functions/external [new file with mode: 0644]
examples/functions/fact [new file with mode: 0644]
examples/functions/fstty [new file with mode: 0644]
examples/functions/func [new file with mode: 0644]
examples/functions/jj.bash [new file with mode: 0644]
examples/functions/kshenv [new file with mode: 0644]
examples/functions/manpage [new file with mode: 0644]
examples/functions/notify.bash [new file with mode: 0644]
examples/functions/shcat [new file with mode: 0644]
examples/functions/substr [new file with mode: 0644]
examples/functions/substr2 [new file with mode: 0644]
examples/functions/term [new file with mode: 0644]
examples/functions/whatis [new file with mode: 0644]
examples/functions/whence [new file with mode: 0644]
examples/scripts/adventure.sh [new file with mode: 0755]
examples/scripts/bcsh.sh [new file with mode: 0644]
examples/scripts/precedence [new file with mode: 0644]
examples/scripts/shprompt [new file with mode: 0755]
examples/startup-files/Bash_aliases [new file with mode: 0644]
examples/startup-files/Bash_profile [new file with mode: 0644]
examples/startup-files/Bashrc [new file with mode: 0644]
examples/startup-files/bash-profile [new file with mode: 0644]
examples/startup-files/bashrc [new file with mode: 0644]
examples/suncmd.termcap [new file with mode: 0644]
execute_cmd.c [new file with mode: 0644]
execute_cmd.h [new file with mode: 0644]
expr.c [new file with mode: 0644]
externs.h [new file with mode: 0644]
filecntl.h [new file with mode: 0644]
flags.c [new file with mode: 0644]
flags.h [new file with mode: 0644]
general.c [new file with mode: 0644]
general.h [new file with mode: 0644]
getcwd.c [new file with mode: 0644]
hash.c [new file with mode: 0644]
hash.h [new file with mode: 0644]
input.c [new file with mode: 0644]
input.h [new file with mode: 0644]
jobs.c [new file with mode: 0644]
jobs.h [new file with mode: 0644]
lib/doc-support/Makefile [new file with mode: 0644]
lib/doc-support/getopt.h [new file with mode: 0644]
lib/doc-support/texindex.c [new file with mode: 0644]
lib/glob/ChangeLog [new file with mode: 0644]
lib/glob/Makefile [new file with mode: 0644]
lib/glob/doc/Makefile [new file with mode: 0644]
lib/glob/doc/glob.texi [new file with mode: 0644]
lib/glob/fnmatch.c [new file with mode: 0644]
lib/glob/fnmatch.h [new file with mode: 0644]
lib/glob/glob.c [new file with mode: 0644]
lib/glob/ndir.h [new file with mode: 0644]
lib/malloc/Makefile [new file with mode: 0644]
lib/malloc/alloca.c [new file with mode: 0644]
lib/malloc/getpagesize.h [new file with mode: 0644]
lib/malloc/i386-alloca.s [new file with mode: 0644]
lib/malloc/malloc.c [new file with mode: 0644]
lib/malloc/x386-alloca.s [new file with mode: 0644]
lib/malloc/xmalloc.c [new file with mode: 0644]
lib/malloclib/Makefile [new file with mode: 0644]
lib/malloclib/alloca.c [new file with mode: 0644]
lib/malloclib/calloc.c [new file with mode: 0644]
lib/malloclib/cfree.c [new file with mode: 0644]
lib/malloclib/free.c [new file with mode: 0644]
lib/malloclib/getpagesize.h [new file with mode: 0644]
lib/malloclib/i386-alloca.s [new file with mode: 0644]
lib/malloclib/malloc.c [new file with mode: 0644]
lib/malloclib/malloc.h [new file with mode: 0644]
lib/malloclib/mcheck.c [new file with mode: 0644]
lib/malloclib/memalign.c [new file with mode: 0644]
lib/malloclib/morecore.c [new file with mode: 0644]
lib/malloclib/mstats.c [new file with mode: 0644]
lib/malloclib/mtrace.awk [new file with mode: 0644]
lib/malloclib/mtrace.c [new file with mode: 0644]
lib/malloclib/realloc.c [new file with mode: 0644]
lib/malloclib/valloc.c [new file with mode: 0644]
lib/malloclib/x386-alloca.s [new file with mode: 0644]
lib/malloclib/xmalloc.c [new file with mode: 0644]
lib/posixheaders/ansi_stdlib.h [new file with mode: 0644]
lib/posixheaders/filecntl.h [new file with mode: 0644]
lib/posixheaders/memalloc.h [new file with mode: 0644]
lib/posixheaders/posixstat.h [new file with mode: 0644]
lib/posixheaders/stdc.h [new file with mode: 0644]
lib/readline/COPYING [new file with mode: 0644]
lib/readline/ChangeLog [new file with mode: 0644]
lib/readline/Makefile [new file with mode: 0644]
lib/readline/README [new file with mode: 0644]
lib/readline/STANDALONE [new file with mode: 0644]
lib/readline/ansi_stdlib.h [new file with mode: 0644]
lib/readline/bind.c [new file with mode: 0644]
lib/readline/chardefs.h [new file with mode: 0644]
lib/readline/complete.c [new file with mode: 0644]
lib/readline/display.c [new file with mode: 0644]
lib/readline/doc/Makefile [new file with mode: 0644]
lib/readline/doc/hist.texinfo [new file with mode: 0644]
lib/readline/doc/history.dvi [new file with mode: 0644]
lib/readline/doc/history.info [new file with mode: 0644]
lib/readline/doc/history.ps [new file with mode: 0644]
lib/readline/doc/hstech.texinfo [new file with mode: 0644]
lib/readline/doc/hsuser.texinfo [new file with mode: 0644]
lib/readline/doc/readline.dvi [new file with mode: 0644]
lib/readline/doc/readline.info [new file with mode: 0644]
lib/readline/doc/readline.ps [new file with mode: 0644]
lib/readline/doc/rlman.texinfo [new file with mode: 0644]
lib/readline/doc/rltech.texinfo [new file with mode: 0644]
lib/readline/doc/rluser.texinfo [new file with mode: 0644]
lib/readline/doc/texindex.c [new file with mode: 0644]
lib/readline/emacs_keymap.c [new file with mode: 0644]
lib/readline/examples/Inputrc [new file with mode: 0644]
lib/readline/examples/Makefile [new file with mode: 0644]
lib/readline/examples/fileman.c [new file with mode: 0644]
lib/readline/examples/histexamp.c [new file with mode: 0644]
lib/readline/examples/manexamp.c [new file with mode: 0644]
lib/readline/funmap.c [new file with mode: 0644]
lib/readline/history.c [new file with mode: 0644]
lib/readline/history.h [new file with mode: 0644]
lib/readline/isearch.c [new file with mode: 0644]
lib/readline/keymaps.c [new file with mode: 0644]
lib/readline/keymaps.h [new file with mode: 0644]
lib/readline/memalloc.h [new file with mode: 0644]
lib/readline/parens.c [new file with mode: 0644]
lib/readline/posixstat.h [new file with mode: 0644]
lib/readline/readline.c [new file with mode: 0644]
lib/readline/readline.h [new file with mode: 0644]
lib/readline/rlconf.h [new file with mode: 0644]
lib/readline/rldefs.h [new file with mode: 0644]
lib/readline/rltty.c [new file with mode: 0644]
lib/readline/search.c [new file with mode: 0644]
lib/readline/signals.c [new file with mode: 0644]
lib/readline/tilde.c [new file with mode: 0644]
lib/readline/tilde.h [new file with mode: 0644]
lib/readline/vi_keymap.c [new file with mode: 0644]
lib/readline/vi_mode.c [new file with mode: 0644]
lib/readline/xmalloc.c [new file with mode: 0644]
lib/termcap/Makefile [new file with mode: 0644]
lib/termcap/grot/COPYING [new file with mode: 0644]
lib/termcap/grot/ChangeLog [new file with mode: 0644]
lib/termcap/grot/INSTALL [new file with mode: 0644]
lib/termcap/grot/Makefile.in [new file with mode: 0644]
lib/termcap/grot/NEWS [new file with mode: 0644]
lib/termcap/grot/README [new file with mode: 0644]
lib/termcap/grot/configure [new file with mode: 0755]
lib/termcap/grot/configure.in [new file with mode: 0644]
lib/termcap/grot/termcap.info [new file with mode: 0644]
lib/termcap/grot/termcap.info-1 [new file with mode: 0644]
lib/termcap/grot/termcap.info-2 [new file with mode: 0644]
lib/termcap/grot/termcap.info-3 [new file with mode: 0644]
lib/termcap/grot/termcap.info-4 [new file with mode: 0644]
lib/termcap/grot/termcap.texi [new file with mode: 0644]
lib/termcap/grot/texinfo.tex [new file with mode: 0644]
lib/termcap/termcap.c [new file with mode: 0644]
lib/termcap/termcap.h [new file with mode: 0644]
lib/termcap/tparam.c [new file with mode: 0644]
lib/termcap/version.c [new file with mode: 0644]
lib/tilde/ChangeLog [new file with mode: 0644]
lib/tilde/Makefile [new file with mode: 0644]
lib/tilde/doc/Makefile [new file with mode: 0644]
lib/tilde/doc/tilde.texi [new file with mode: 0644]
lib/tilde/memalloc.h [new file with mode: 0644]
lib/tilde/tilde.c [new file with mode: 0644]
lib/tilde/tilde.h [new file with mode: 0644]
machines.h [new file with mode: 0644]
mailcheck.c [new file with mode: 0644]
make_cmd.c [new file with mode: 0644]
make_cmd.h [new file with mode: 0644]
maxpath.h [new file with mode: 0644]
memalloc.h [new file with mode: 0644]
newversion.c [new file with mode: 0644]
nojobs.c [new file with mode: 0644]
parse.y [new file with mode: 0644]
parser-built [new file with mode: 0644]
parser.h [new file with mode: 0644]
portbash/README [new file with mode: 0644]
portbash/libc.sh [new file with mode: 0644]
portbash/mkdesc.sh [new file with mode: 0644]
portbash/pgrp.c [new file with mode: 0644]
portbash/signals.sh [new file with mode: 0644]
portbash/stdio.sh [new file with mode: 0644]
portbash/strings.sh [new file with mode: 0644]
portbash/syscalls.sh [new file with mode: 0644]
posixstat.h [new file with mode: 0644]
print_cmd.c [new file with mode: 0644]
quit.h [new file with mode: 0644]
sh [new symlink]
shell.c [new file with mode: 0644]
shell.h [new file with mode: 0644]
siglist.c [new file with mode: 0644]
siglist.h [new file with mode: 0644]
signames.c [new file with mode: 0644]
stdc.h [new file with mode: 0644]
subst.c [new file with mode: 0644]
subst.h [new file with mode: 0644]
support/PORTING [new file with mode: 0644]
support/SYMLINKS [new file with mode: 0644]
support/bash.xbm [new file with mode: 0644]
support/bashbug.sh [new file with mode: 0644]
support/cat-s [new file with mode: 0644]
support/clone-bash [new file with mode: 0755]
support/cppmagic [new file with mode: 0755]
support/fixlinks [new file with mode: 0755]
support/getcppsyms.c [new file with mode: 0644]
support/inpath [new file with mode: 0755]
support/install.sh [new file with mode: 0755]
support/mkdirs [new file with mode: 0755]
support/mklinks [new file with mode: 0755]
support/mkmachtype [new file with mode: 0755]
support/mksysdefs [new file with mode: 0755]
support/printenv [new file with mode: 0755]
support/recho.c [new file with mode: 0644]
support/srcdir [new file with mode: 0755]
support/texi2dvi [new file with mode: 0755]
test.c [new file with mode: 0644]
tests/README [new file with mode: 0644]
tests/dollar-at.sh [new file with mode: 0755]
tests/dollar-star.sh [new file with mode: 0755]
tests/dollar.right [new file with mode: 0644]
tests/exp-tests [new file with mode: 0644]
tests/exp.right [new file with mode: 0644]
tests/glob-test [new file with mode: 0644]
tests/glob.right [new file with mode: 0644]
tests/ifs-test-1.sh [new file with mode: 0644]
tests/ifs-test-2.sh [new file with mode: 0644]
tests/ifs-test-3.sh [new file with mode: 0644]
tests/ifs.1.right [new file with mode: 0644]
tests/ifs.2.right [new file with mode: 0644]
tests/ifs.3.right [new file with mode: 0644]
tests/input-line.sh [new file with mode: 0644]
tests/input-line.sub [new file with mode: 0644]
tests/input.right [new file with mode: 0644]
tests/minus-e [new file with mode: 0644]
tests/minus-e.right [new file with mode: 0644]
tests/misc/chld-trap.sh [new file with mode: 0755]
tests/misc/dot-test-1.sh [new file with mode: 0644]
tests/misc/dot-test-1.sub [new file with mode: 0644]
tests/misc/gotest [new file with mode: 0644]
tests/misc/perf-script [new file with mode: 0644]
tests/misc/redir.t1.sh [new file with mode: 0644]
tests/misc/redir.t2.sh [new file with mode: 0644]
tests/misc/redir.t3.sh [new file with mode: 0755]
tests/misc/redir.t3.sub [new file with mode: 0644]
tests/misc/redir.t4.sh [new file with mode: 0644]
tests/misc/run.r1.sh [new file with mode: 0755]
tests/misc/run.r2.sh [new file with mode: 0755]
tests/misc/run.r3.sh [new file with mode: 0755]
tests/misc/sigint.t1.sh [new file with mode: 0755]
tests/misc/sigint.t2.sh [new file with mode: 0755]
tests/misc/sigint.t3.sh [new file with mode: 0755]
tests/misc/sigint.t4.sh [new file with mode: 0755]
tests/misc/test-minus-e.1 [new file with mode: 0644]
tests/misc/test-minus-e.2 [new file with mode: 0644]
tests/new-exp.right [new file with mode: 0644]
tests/new-exp.tests [new file with mode: 0644]
tests/prec.right [new file with mode: 0644]
tests/precedence [new file with mode: 0755]
tests/run-all [new file with mode: 0755]
tests/run-dollars [new file with mode: 0755]
tests/run-exp-tests [new file with mode: 0755]
tests/run-glob-test [new file with mode: 0755]
tests/run-ifs-tests [new file with mode: 0755]
tests/run-input-test [new file with mode: 0755]
tests/run-minus-e [new file with mode: 0755]
tests/run-new-exp [new file with mode: 0755]
tests/run-precedence [new file with mode: 0755]
tests/run-set-e-test [new file with mode: 0755]
tests/run-strip [new file with mode: 0755]
tests/run-varenv [new file with mode: 0755]
tests/set-e-test [new file with mode: 0644]
tests/set-e.right [new file with mode: 0644]
tests/strip.right [new file with mode: 0644]
tests/strip.tests [new file with mode: 0644]
tests/tilde-tests [new file with mode: 0644]
tests/tilde.right [new file with mode: 0644]
tests/varenv.right [new file with mode: 0644]
tests/varenv.sh [new file with mode: 0644]
trap.c [new file with mode: 0644]
trap.h [new file with mode: 0644]
unwind_prot.c [new file with mode: 0644]
unwind_prot.h [new file with mode: 0644]
variables.c [new file with mode: 0644]
variables.h [new file with mode: 0644]
version.c [new file with mode: 0644]
vprint.c [new file with mode: 0644]
y.tab.c [new file with mode: 0644]
y.tab.h [new file with mode: 0644]

diff --git a/.distribution b/.distribution
new file mode 100644 (file)
index 0000000..63738cc
--- /dev/null
@@ -0,0 +1 @@
+1.14
diff --git a/.patchlevel b/.patchlevel
new file mode 100644 (file)
index 0000000..7f8f011
--- /dev/null
@@ -0,0 +1 @@
+7
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..d642012
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,257 @@
+
+                   GNU GENERAL PUBLIC LICENSE
+                    Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+                   675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+The Free Software Foundation has exempted Bash from the requirement of
+Paragraph 2c of the General Public License.  This is to say, there is
+no requirement for Bash to print a notice when it is started
+interactively in the usual way.  We made this exception because users
+and standards expect shells not to print such messages.  This
+exception applies to any program that serves as a shell and that is
+based primarily on Bash as opposed to other GNU software.
+
+                           Preamble
+
+  The license agreements of most software companies try to keep users
+at the mercy of those companies.  By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must tell them their rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License.  The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications.  Each
+licensee is addressed as "you".
+
+  1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program.  You may charge a fee for the physical act of
+transferring a copy.
+
+  2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+    a) cause the modified files to carry prominent notices stating that
+    you changed the files and the date of any change; and
+
+    b) cause the whole of any work that you distribute or publish, that
+    in whole or in part contains the Program or any part thereof, either
+    with or without modifications, to be licensed at no charge to all
+    third parties under the terms of this General Public License (except
+    that you may choose to grant warranty protection to some or all
+    third parties, at your option).
+
+    c) If the modified program normally reads commands interactively when
+    run, you must cause it, when started running for such interactive use
+    in the simplest and most usual way, to print or display an
+    announcement including an appropriate copyright notice and a notice
+    that there is no warranty (or else, saying that you provide a
+    warranty) and that users may redistribute the program under these
+    conditions, and telling the user how to view a copy of this General
+    Public License.
+
+    d) You may charge a fee for the physical act of transferring a
+    copy, and you may at your option offer warranty protection in
+    exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+\f
+  3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+    a) accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    b) accompany it with a written offer, valid for at least three
+    years, to give any third party free (except for a nominal charge
+    for the cost of distribution) a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    c) accompany it with the information you received as to where the
+    corresponding source code may be obtained.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it.  For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+  4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License.  However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+  5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions.  You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+\f
+  7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+  8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+  To do so, attach the following notices to the program.  It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy <name of author>
+
+    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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19xx name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License.  Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  program `Gnomovision' (a program to direct compilers to make passes
+  at assemblers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/CWRU/PLATFORMS b/CWRU/PLATFORMS
new file mode 100644 (file)
index 0000000..a792966
--- /dev/null
@@ -0,0 +1,18 @@
+The version of bash in this directory has been compiled on the
+following systems:
+
+Sun 690                        SunOS 4.1.2
+Sparcstation           SunOS 5.3
+Sparcstation           NetBSD 0.9a
+386                    BSDI BSD/386 1.0, 1.1
+NeXTstation            NeXT OS 2.1
+IBM RT                 IBM/4.3 (AOS)
+Motorola Delta 88K     SVR3.2
+Decstation 3100                Ultrix 4.3
+Dec 4000 Alpha AXP     DEC OSF/1 V1.3
+386                    ISC UNIX 3.0.1
+386                    FreeBSD 1.1
+IBM RS/6000            AIX 3.2
+Amiga                  Amiga UNIX 2.1
+Sony NEWS 841          NEWS OS
+HP 9000/834            HP/UX 7.0
diff --git a/CWRU/POSIX.NOTES b/CWRU/POSIX.NOTES
new file mode 100644 (file)
index 0000000..bc9a969
--- /dev/null
@@ -0,0 +1,63 @@
+Starting bash with the `-posix' command-line option or setting the variable
+POSIXLY_CORRECT while bash is running will cause bash to conform more
+closely to the Posix.2 standard by changing the behavior to match that
+specified by Posix.2 in areas where the bash default differs.
+
+The following list is what's changed when `posixly_correct' is enabled:
+
+1.  When a command in the hash table no longer exists, bash will re-search
+    $PATH to find the new location.
+
+2.  The >& redirection does not redirect stdout and stderr.
+
+3.  The message printed by the job control code and builtins when a job
+    exits with a non-zero status is `Done(status)'.
+
+4.  The <> redirection does not open a file for both stdin and stdout, but
+    rather opens it for read-write on fd 0.
+
+5.  Reserved words may not be aliased.
+
+6.  The Posix.2 PS1 and PS2 expansions of `!' -> history number and `!!' -> `!'
+    are enabled.
+
+7.  Interactive comments are enabled by default.  (Note that this version has
+    them on by default anyway.)
+
+8.  The Posix.2 startup files are executed ($ENV) rather than the normal bash
+    files.
+
+9.  Tilde expansion is only performed on assignments preceding a command name,
+    rather than on all assignment statements on the line.
+
+10. The default history file is ~/.sh_history (default value of $HISTFILE).
+
+11. The output of `kill -l' prints all the signal names on a single line,
+    separated by spaces.
+
+12. Non-interactive shells exit if `file' in `. file' is not found.
+
+13. Redirection operators do not perform pathname expansion on the word
+    in the redirection unless the shell is interactive
+
+14. Function names must be valid shell identifiers.  That is, they may not
+    contain characters other than letters, digits, and underscores, and
+    may not start with a digit
+
+There is other Posix.2 behavior that bash does not implement.  Specifically:
+
+1.  There are no `special builtins' and `regular builtins'.  All builtins
+    are equivalent.  This means that:
+
+       o assignment statements affect the execution environment of all
+         builtins, not just special ones
+       o temporary assignments do not persist after Posix.2 special
+         builtins complete
+       o Functions are found before Posix.2 special builtins
+       o The shell does not exit upon errors while executing Posix.2
+         special builtins
+
+2.  $LINENO does not represent the line number of a command within a function
+
+3.  The arithmetic evaluator does not implement the `e ? e1 : e2' conditional
+    expression
diff --git a/CWRU/README b/CWRU/README
new file mode 100644 (file)
index 0000000..8e3398d
--- /dev/null
@@ -0,0 +1,26 @@
+Notes:
+
+ISC 386 machines must compile test.c without -O.  The resultant shell dumps
+core when test is invoked.
+
+There have been reports that SCO 3.2v4.2 requires -DPRGP_PIPE in SCO_CFLAGS,
+and that it has too many -D defines for SCO's cc (rcc works).
+
+Contents of this directory:
+
+CWRU.chlog             - my change log since the last release
+
+KSH.README             - list of similarities with ksh.  Slightly out of date
+
+PLATFORMS.113          - list of platforms I have built this release on
+
+POSIX.NOTES            - list of what changes for `posix mode'
+
+README                 - this file
+
+RSH.README             - explanation of the bash `restricted shell' mode
+
+
+misc                   - directory with some useful tools
+OS-BUGS                        - directory with messages detailing some OS bugs and
+                         the bash workarounds
diff --git a/CWRU/changelog b/CWRU/changelog
new file mode 100644 (file)
index 0000000..11d6775
--- /dev/null
@@ -0,0 +1,786 @@
+                                   6/2
+                                   ---
+lib/readline/readline.c
+       - fixed an off-by-one error in the kill ring reallocation code
+         in rl_kill_text
+
+Makefile
+       - replaced instances of /bin/sh with $(SHELL)
+
+Makefile, cpp-Makefile, documentation/Makefile
+       - added a working `uninstall' target
+
+[1.14.0 FCS release made available for FTP]
+
+                                   6/3
+                                   ---
+README
+       - added note about building with gcc, same as in Makefile
+
+documentation/Makefile
+       - some versions of make don't understand `$*' in a regular recipe;
+         replace with features.dvi in the recipe for features.ps
+
+                                   6/4
+                                   ---
+subst.c
+       - fix up the calls to string_extract_double_quoted and 
+         string_extract_single_quoted in char_is_quoted so the initial
+         value of the index is *after* the opening quote character
+       - make sure we only return 1 from char_is_quoted if the index
+         into the string after a call to string_extract_double_quoted or
+         string_extract_single_quoted is *greater than* `eindex'
+
+lib/readline/complete.c
+       - change the order and sense of the quoting tests in
+         rl_complete_internal so that the expensive char_is_quoted
+         is only called if `scan' actually is a word break character
+
+shell.c
+       - fixed a typo in the test for a restricted shell
+
+builtins/exec.def
+       - need to include flags.h
+
+                                   6/6
+                                   ---
+make_cmd.c
+       - make sure that we don't try to walk down a null command tree
+         in connect_async_list (tickled by `(command &) &')
+       - if a command has the CMD_WANT_SUBSHELL bit set in its flags,
+         don't even try to walk the command tree and move the `&';
+         just connect the command with a null command using `&'
+
+execute_cmd.c
+       - make sure we don't try to reference a command struct without
+         first checking it (case '&')
+
+                                   6/7
+                                   ---
+machines.h
+       - fix a typo in the NeXT/i386 description; change the NeXT description
+         to #define HAVE_RESOURCE if not already defined rather than putting
+         -DHAVE_RESOURCE into the SYSDEP_CFLAGS
+
+                                   6/9
+                                   ---
+Makefile
+       - make sure all of the rules that reinvoke `make' have the
+         `-f bash-Makefile' before the assignment statements; some
+         versions of make like it that way
+
+variables.c
+       - make sure that `interactive' is set to 0 before evaluating the
+         string containing an exported function obtained from the
+         environment, so that it does not try to execute PROMPT_COMMAND
+         (this may not be the best fix)
+
+                                  6/13
+                                  ----
+documentation/Makefile
+       - make sure all of the directories exist before trying to install
+         doc files into them
+
+lib/readline/history.c
+       - add a missing O_TRUNC to the open call for writing in
+         history_truncate_file
+
+trap.c
+       - run_interrupt_trap should only try to run the trap command if
+         the value is not IMPOSSIBLE_TRAP_HANDLER
+
+Makefile
+       - add `realclean'
+
+lib/readline/complete.c
+       - do the same kind of double-quoting a replacement string if the
+         user supplies the opening double quote as we would if we were
+         adding both quotes ourselves
+
+variables.c
+       - fixed the variable initialization so that history_control/HISTCONTROL
+         can be inherited from a parent shell
+
+INSTALL, README, cpp-Makefile, documentation/bash.1, documentation/readline.3
+       - ai.mit.edu -> prep.ai.mit.edu
+
+shell.c
+       - fixed a problem with setting no_line_editing to the result of the
+         check for running inside emacs, thereby losing any value
+         initialized by the `-nolineediting' flag
+
+cpp-Makefile
+       - `make distclean' will now remove the `installed-bash' link
+
+print_cmd.c
+       - fixed a problem with undefined variables when HAVE_VARARGS_H is
+         not defined
+
+                                  6/14
+                                  ----
+lib/readline/history.c
+       - fixed an error in the csh history expansion code so that the
+         `-y' word designator now expands to `0-y' rather than `1-y'
+
+lib/readline/isearch.c
+       - changed an absolute check for a character falling within the
+         ASCII 32-126 range (printable chars) with checks for CTRL_P
+         and META_CHAR and a check against the value RUBOUT
+       - changed a `break' to a `continue' so that the first non-matching
+         character in the search string does not cause the search to
+         end abruptly
+       - initialize prev_line_found to 0 at the top of rl_search_history
+         to avoid duplicate history lines being saved across searches
+
+lib/readline/rltty.c
+       - consolidated repeated code for setting special characters into
+         `SET_SPECIAL' defines
+
+lib/readline/readline.c
+       - include <sys/ioctl.h> if VSTATUS is defined
+       - add bindable command rl_tty_status (unbound by default)
+
+lib/readline/funmap.c
+       - assign bindable command name `tty-status' to rl_tty_status
+
+INSTALL
+       - add note about compiling with gcc, same text as README
+
+lib/readline/display.c
+       - many changes and tweaks to make redisplay work better when the
+         prompt has invisible characters.  These changes are non-optimal
+         in that the prompt is redrawn more than it needs to be, but
+         things are a hell of a lot better than they were
+
+                                  6/15
+                                  ----
+documentation/Makefile
+       - make a variable NROFF that people can set to `groff -Tascii' if
+         they don't have real nroff
+       - changed the suffix rules to use $<
+
+support/bashbug.sh
+       - if rmail doesn't exist or fails, save the bug report in
+         ~/dead.bashbug
+
+execute_cmd.c
+       - in setup_async_signals, only ignore SIGINT and SIGQUIT if job
+         control is not active.  If it is active and the job is restarted,
+         SIGINT remains ignored, and the now-foregrounded job is not
+         interruptible
+
+subst.c
+       - fixed up a problem with char_is_quoted that caused backslash-
+         escaped characters to cause incorrect results
+
+tests/run-dollars, tests/dollar-at.sh, tests/dollar-star.sh
+       - since the error messages produced by `cat' vary, changed `cat'
+         to `recho' and updated the correct answers file
+
+machines.h
+       - fixes to CRAY_STACKSEG_END definitions for different versions of
+         Unicos on the YMP (from Bill Jones)
+       - Motorola SVR4 machines have getcwd() and should not undef
+         HAVE_GETCWD
+       - on hpux 9.x, don't try to link with -lPW if compiling with gcc
+         (for alloca)
+
+parse.y
+       - an ugly fix for a compiler problem with structure assignment on
+         the cray
+
+                                  6/16
+                                  ----
+builtins/wait.def
+       - replaced a call to sscanf with a validity check using all_digits()
+         and a call to atoi, since a pid_t is not necessarily an int, and
+         the sscanf clobbered the stack frame on systems where it is shorter
+         than an int (e.g., SCO)
+
+lib/readline/display.c
+       - since META_CHAR and the other macros only work with unsigned
+         chars, make rl_character_len convert its argument to an unsigned
+         char before testing it
+
+documentation/Makefile
+       - use $(INSTALL_DATA) instead of $(CP) to install the man pages and
+         info files
+
+cpp-Makefile
+       - use INSTALL_PROGRAM and INSTALL_DATA to install binaries and
+         documentation; pass both values to installs in subdirectories
+
+                                  6/18
+                                  ----
+builtins/ulimit.def
+       - compensate for systems which define RLIMIT_OFILE instead of
+         RLIMIT_NOFILE, or don't provide such a compatibility define
+         themselves
+
+shell.c
+       - make maybe_execute_file check for directories and print an
+         appropriate error message, since it's doing an fstat anyway
+
+support/mksysdefs
+       - added support for a `-s srcdir' option so it can find
+         cpp-Makefile if ansi-Makefile is to be created
+
+Makefile
+       - call mksysdefs with -s $(srcdir)
+
+jobs.c
+       - add the magic #undef lines to avoid redefinition warnings on
+         SunOS 4 only
+
+                                  6/20
+                                  ----
+cpp-Makefile
+       - install `bashbug' with `make install'
+
+trap.c
+       - make sure that `interactive' is set to 0 when running trap
+         commands
+
+builtins/umask.c
+       - fixed typo in usage error message
+
+subst.c
+       - fix process_substitute to set subshell_environment
+
+jobs.c, nojobs.c
+       - only mess with the terminal settings for an interactive shell
+         that is not in a subshell environment
+
+                                  6/21
+                                  ----
+lib/readline/history.h
+       - add extern declaration of history_get
+
+builtins/fc.def
+       - make history replacement when using `r' or `fc -s' obey the
+         setting of HISTCONTROL
+
+general.c
+       - in canonicalize_pathname, preserve a double // at the start
+         of an absolute pathname, since that means something special
+         for the network directory system
+
+README, INSTALL
+       - updated information about submitting bug reports
+
+lib/readline/vi_mode.c, lib/readline/isearch.c
+       - make sure unistd.h is included before rldefs.h, if
+         HAVE_UNISTD_H is defined
+
+                                  6/24
+                                  ----
+lib/readline/complete.c
+       - add `#' to the list of characters which cause a completed filename
+         to be quoted
+
+execute_cmd.c
+       - be more careful about closing pipe file descriptors in do_piping;
+         don't want to have `dup2(i, i); close(i);' problem
+
+lib/readline/{keymaps,readline}.h
+       - include local copies of include files if READLINE_LIBRARY is
+         defined, otherwise include the `official, installed' versions
+         using #include <readline/xxx.h>
+
+lib/readline/*.c
+       - define READLINE_LIBRARY before including any files
+       - include only `local' copies of include files using #include "xxx.h"
+         rather than #include <readline/xxx.h>
+
+                                  6/26
+                                  ----
+execute_cmd.c
+       - check for clobbering the bash input stream before closing a file
+         descriptor due to an r_close_this redirection
+
+lib/readline/history.c
+       - made history_expand inhibit history expansion if the history
+         expansion char is set to 0
+
+lib/readline/chardefs.h
+       - moved savestring() definition to rldefs.h
+       - changed lowercase_p, uppercase_p, to_lower, to_upper defines to
+         use <ctype.h> macros rather than assume ASCII
+
+lib/readline/bind.c, general.c, general.h
+       - use strcasecmp, strncasecmp instead of str[n]icmp if
+         HAVE_STRCASECMP is defined
+
+cpp-Makefile
+       - pass -DHAVE_STRCASECMP to builds in the libraries, primarily
+         readline
+
+machines.h
+       - add HAVE_STRCASECMP to the entries for BSD/386, NetBSD, FreeBSD,
+         and 4.4 BSD
+
+builtins/hash.def
+       - add a fourth parameter to remember_filename, the initial value
+         of times_found (0 if we're just looking it up for `hash', 1
+         for the command execution code)
+
+execute_cmd.c
+       - call remember_filename with an initial value of 1 for times_found
+
+builtins/wait.def
+       - handle a null argument with an error message
+
+builtins/common.c
+       - parse_and_execute now takes a third parameter: the value for
+         `interactive' while it is executing commands
+
+bashline.c, jobs.c, parse.y, shell.c, subst.c, trap.c, variables.c
+       - set the new third argument to parse_and_execute appropriately
+
+builtins/eval.def, builtins/fc.def, builtins/source.def
+       - set the new third argument to parse_and_execute appropriately
+
+builtins/help.def
+       - changed a call to strnicmp to strncmp when trying to find what
+         to give help on; it seems more correct
+
+                                  6/27
+                                  ----
+machines.h
+       - cleaned up the SunOS section so it no longer relies on
+         HAVE_SHARED_LIBS being defined; it uses SunOS4 and SunOS5
+         instead
+
+support/mksysdefs
+       - define SYSDEF to be SunOS4 or SunOS5 depending on the output
+         of uname rather than looking for ld.so
+
+                                  6/29
+                                  ----
+machines.h
+       - minor change to the ardent titan machine description
+       - move the ardent and stardent descriptions before the
+         mips riscos description
+
+print_cmd.c
+       - ardent machines also need the extern declaration for printf
+
+make_cmd.c
+       - connect_async_list should do its work only if the lists to be
+         backgrounded are connected with `;'.  This makes `;' bind tighter
+         than `&', so only the last job in the list is backgrounded.  All
+         other lists should have the entire thing put in the background
+
+parse.y
+       - added a function `print_prompt' to take care of displaying the
+         prompt string if readline is not being used.  This fixes problems
+         with the prompt being displayed before the status of completed
+         jobs is printed
+
+                                  6/30
+                                  ----
+builtins/fg_bg.def
+       - `fg' and `bg' now print error messages if invoked when job control
+         is disabled
+
+lib/readline/rltty.c
+       - if not compiled into the shell, make get_tty_settings get and set
+         the window size.  This noop stops the process if it is started in
+         the background
+
+lib/readline/readline.c
+       - provide a function version of savestring, if not being compiled
+         into the shell, since the macro has been removed from the
+         `public' header files
+
+lib/readline/readline.h
+       - provide all extern function declarations without checking whether
+         VI_MODE or PAREN_MATCHING are defined.  It does not hurt to define
+         them if they are not used and not in the library, and other
+         applications using readline can't tell whether or not VI_MODE was
+         defined when the library was compiled anyway
+
+                                   7/1
+                                   ---
+machines.h
+       - add #undef HAVE_DIRENT_H to the ardent titan description
+
+                                   7/2
+                                   ---
+lib/readline/chardefs.h
+       - removed META_P define, renamed CTRL_P to CTRL_CHAR
+
+lib/readline/bind.c, lib/readline/isearch.c
+       - changed instances of CTRL_P to CTRL_CHAR
+
+lib/readline/search.c
+       - include <unistd.h> before rldefs.h, if HAVE_UNISTD_H is defined
+
+lib/readline/readline.c
+       - declare PC, UP, and BC as extern rather than `local' to the
+         readline library
+
+                                   7/5
+                                   ---
+bashline.c
+       - implement command word completion inside of command substitution
+         with a new function: `command_subst_completion_function'
+
+subst.c
+       - new function to help with command subst completion: unclosed_pair
+
+lib/readline/complete.c
+       - new variable rl_filename_quoting_desired, which can be set to 0
+         to inhibit the quoting of filenames after completion
+
+lib/readline/readline.h
+       - declare rl_filename_completion_desired and
+         rl_filename_quoting_desired
+
+builtins/bind.def
+       - don't save the old value of rl_outstream before initializing
+         readline -- it saves garbage values and screws up readline
+
+parse.y
+       - don't have private state telling whether or not readline has
+         been initialized -- use bash_readline_initialized like other
+         functions in bashline.c
+
+lib/readline/readline.c
+       - make the default 8-bit behavior be based on whether LC_CTYPE is
+         defined and its value (accept iso-8859-1 or iso_8859_1)
+
+                                   7/6
+                                   ---
+variables.c
+       - fix up the declaration of getenv() for convex machines
+
+                                   7/7
+                                   ---
+lib/readline/readline.c
+       - fixed up typos in the declaration of `savestring'
+
+lib/readline/history.c
+       - fixed an off-by-one error in the ADD_CHAR macro which caused one
+         extra character to be overwritten, causing the gnu malloc to abort
+         when that one character was at the end of an allocated block
+       - changed the ADD_STRING macro to avoid some unnecessary xreallocs
+
+lib/readline/display.c
+       - fixed a problem with move_cursor_relative -- function now returns
+         immediately if it has nothing to do
+       - fixed another problem with displaying prompts with invisible chars
+
+lib/readline/chardefs.h
+       - fixed the CTRL macro to be right (agree with the BSD kernel, for
+         example)
+
+cpp-Makefile
+       - fixed typo in the `install' recipe
+
+                                   7/8
+                                   ---
+support/srcdir
+       - fixed to handle srcdir when it begins with ./ or ../ to handle
+         $(srcdir) being a relative path better
+
+cpp-Makefile
+       - changed some include paths to $(BUILTIN_ABSSRC) when building in
+         `builtins' to handle $(srcdir) being a relative path
+       - change the `chmod' on bashbug to turn on read and execute for all
+       - added a couple of definitions to make it easier for a later
+         `configure' program
+
+support/mksysdefs
+       - added a -i option to specify an alternate set of directories to
+         search for include files
+
+lib/readline/bind.c
+       - in rl_read_init_file, when skipping whitespace at the start of
+         the line, decrement `i' so that we don't jump past the start
+         of the next line
+
+machines.h
+       - SCOv4 has a `robust' opendir that checks that you're actually
+         opening a directory
+
+                                  7/11
+                                  ----
+lib/readline/complete.c
+       - make sure a word break character is unquoted before using it to
+         separate out the current word for completing
+
+machines.h
+       - new machine description: NetBSD on motorola m68k machines like
+         the hp300
+       - undef HAVE_GETWD in the generic svr4 machine description, like
+         other svr4 descriptions
+
+lib/readline/rltty.c
+       - make sure to fflush (rl_outstream) after toggling the setting
+         of the keypad and meta key
+
+portbash/libc.sh
+       - add a test for OPENDIR_NOT_ROBUST
+
+support/getcppsyms.c
+       - output __svr4__ if we find __uxps__ (this makes the Fujitsu port of
+         SVR4 to the sparc build OK)
+
+                                  7/12
+                                  ----
+lib/readline/display.c
+       - more display-related fixes when the prompt has invisible chars;
+         this time for screen updates when moving between screen lines
+
+lib/readline/readline.c, lib/readline/display.c
+       - changes to make readline work with terminals that have auto-wrap
+         from Per Bothner (new function _rl_update_final, term_xn changes,
+         some efficiency speedups, new function space_to_eol)
+
+                                  7/13
+                                  ----
+lib/readline/display.c
+       - after moving up screen lines using term_up in _rl_move_vert, if
+         the new screen line is 0, _rl_last_c_pos needs to be adjusted
+         to take invisible characters into account.  This was the source
+         of many bugs
+
+                                  
+                                  7/14
+                                  ----
+documentation/Makefile
+       - change instances of `groff' to `${GROFF}', GROFF is set to
+         `groff' by default
+
+general.c, variables.c
+       - moved `qsort_string_compare' from variables.c to general.c
+
+general.h, variables.h
+       - moved declaration of `qsort_string_compare' from variables.h
+         to general.h
+
+alias.c, lib/readline/funmap.c
+       - moved qsort auxiliary functions after their use and added
+         forward declarations to avoid warnings from ANSI C compilers
+
+memalloc.h
+       - hpux_9 needs alloca declared as `extern void *' if __STDC__
+         is defined
+
+support/mksysdefs
+       - removed HAVE_SHARED_LIBS entirely
+       - make a call to /bin/uname -X for SCO machines to avoid running
+         a different uname from the $PATH
+
+machines.h
+       - new descriptions: Intel i860 running SVR4, Tahoe running 4.3 BSD
+       - changed descriptions: Mips/RiscOS, DG AViiON, unknown machine
+
+jobs.c
+       - changes to how the shell handles foreground jobs dying of SIGINT:
+               an interactive shell using job control will no longer
+               act as if it received a SIGINT if the foreground job
+               dies from a SIGINT
+
+               a non-interactive shell or shell without job control tries
+               to differentiate between SIGINTs it has seen (in
+               wait_sigint_handler) and a foreground job dying of a SIGINT
+               not sent from the keyboard, and runs the normal SIGINT code
+               only in the former case
+
+                                  7/15
+                                  ----
+support/mksysdefs
+       - check for ${UNAME}${RELEASE} expanding to `SunOS4*' or `SunOS5*'
+         to set SYSDEF to SunOS4 or SunOS5, respectively.  Apparently
+         this does not work for Solbourne
+
+                                  7/18
+                                  ----
+
+lib/readline/rltty.c
+       - if output is being flushed on termios systems, loop until the
+         FLUSHO bit is no longer set in the termios struct
+
+support/mksysdefs
+       - added a -A flag to force creation of ansi-Makefile
+
+machines.h
+       - new entry for Tandem machines running SVR3
+
+                                  7/19
+                                  ----
+lib/readline/rldefs.h
+       - include <termcap.h> if HAVE_TERMCAP_H is defined
+       - use <termio.h> stuff if HAVE_TERMIO_H is defined and _POSIX_VERSION
+         is not defined
+
+lib/readline/rldefs.h, lib/readline/history.c
+       - include "config.h" if HAVE_CONFIG_H is defined
+
+lib/readline/{rldefs.h,signals.c,readline.c}
+       - WINSIZE_IN_IOCTL_H -> GWINSZ_IN_SYS_IOCTL for compatibility with
+         other GNU programs
+
+lib/readline/doc/Makefile
+       - fixed up to create the readline and history manuals in dvi and
+         ps format
+
+lib/readline/Makefile
+       - changes inspired by the standalone readline-2.0 distribution
+
+                                  7/20
+                                  ----
+lib/readline/history.c
+       - new function, history_is_stifled (), returns history_stifled
+       - set history_state flags member in the history state functions
+
+lib/readline/history.h
+       - reorganized the function declarations, added missing declarations
+       - history_stifled is no longer exported by the library
+       - added a `flags' member to the HISTORY_STATE structure
+
+bashline.c
+       - use history_is_stifled () instead of history_stifled
+
+lib/readline/readline.c, lib/readline/vi_mode.c
+       - filled in correct argument declarations for functions called via
+         keymaps (count, key)
+
+lib/readline/complete.c
+       - efficiency improvement for compare_strings
+
+                                  7/21
+                                  ----
+examples/dirfuncs
+       - new directory functions from ksh book, contributed by
+         Ken Konecki (kenk@wfg.com)
+
+machines.h
+       - hpux_8 and hpux_9 should both #undef HAVE_ALLOCA unless gcc is
+         being used
+
+                                  7/22
+                                  ----
+bashline.c
+       - fixed up command_word_completion_function so that filenames with
+         leading tildes are completed correctly
+
+                                  7/26
+                                  ----
+builtins/read.def
+       - if -r not given, make sure CTLESC is removed from input string
+         when reading \<newline>
+
+lib/readline/readline.c
+       - new function bind_arrow_keys, which binds vt100/ansi arrow key
+         escape sequences after reading the termcap definition and the
+         inputrc file
+       - new function rl_yank_last_arg, which does what insert-last-arg
+         does in bash
+
+lib/readline/emacs_keymap.c
+       - remove default bindings to rl_arrow_keys for M-[ and M-O
+       - rl_yank_last_arg is now bound to `M-.' and `M-_' in
+         emacs_meta_keymap
+
+subst.c
+       - when performing process substitution on systems with /dev/fd,
+         make sure the child clears the slot in dev_fd_list it gets
+         from its parent so the file descriptor does not get closed
+         inappropriately if reallocated by, e.g., pipe(2)
+
+bashline.c
+       - removed insert_last_arg and the calls to bind in to `M-.' and `M-_'.
+         `insert-last-argument' is now bound to rl_yank_last_arg for
+         backwards compatibility
+
+lib/readline/funmap.c
+       - `yank-last-arg' is now a named command for rl_yank_last_arg
+
+
+documentation/bash.1, documentation/readline.3
+       - add description of yank-last-arg as one of the readline user
+         commands
+
+lib/readline/doc/rluser.texinfo
+       - added description of yank-last-arg
+
+builtins/getopts.def
+       - fixed a typo in the int-to-string code computing the value to set
+         OPTIND to: had '\0' instead of '0'
+       - made getopts handle the case where there are more than 9 dollar
+         variables (where rest_of_args is non-null) correctly
+
+                                  7/28
+                                  ----
+lib/readline/display.c
+       - fixes to the display code for single-line-display in the presence
+         of prompts containing invisible characters
+
+lib/readline/readline.c
+       - if we are using horizontal scrolling and we have term_xn, decrement
+         the screenwidth by 1, since we won't be doing any line wrapping
+
+                                  7/31
+                                  ----
+jobs.c
+       - new variable `freeze_jobs_list' to set when changes to the jobs
+         list or status of jobs in the list (other than calling something
+         like `jobs -n') are undesirable.  This is set when execuing traps
+         on SIGCHLD
+
+                                   8/1
+                                   ---
+subst.c
+       - check that `~' is unquoted before performing tilde expansion in
+         an assignment statement
+
+                                   8/3
+                                   ---
+bracecomp.c
+       - keep brace completion from dumping core if there is only one
+         match
+
+lib/readline/chardefs.h
+       - add a define for digit_p, which returns the value of isdigit()
+
+lib/readline/readline.c
+       - added function equivalents for uppercase_p, lowercase_p, to_upper,
+         to_lower, pure_alphabetic, digit_p, and digit_value
+       - replaced calls to numeric () with calls to digit_p, removed
+         definition of numeric ()
+
+lib/readline/history.c
+       - digit -> digit_p
+
+lib/readline/vi_mode.c
+       - replaced uses of the `isletter' define to use pure_alphabetic
+         from chartypes.h
+       - replaced uses of `numeric' with calls to digit_p
+       - added do...while(0) to `exchange' define
+
+                                   
+                                   8/4
+                                   ---
+execute_cmd.c
+       - make sure execute_function saves and restores the current loop
+         count with unwind_protect_int
+
+documentation/features.texi
+       - change the `Shell Command Line Options' section to `Invoking
+         Bash' to be closer to the GNU coding standards
+
+                                   8/5
+                                   ---
+builtins/read.def
+       - fixed up a memory leak and made behavior correct when no
+         variables given and backslash escaped at least one input char
+       - if we added CTLESC anywhere while reading the input string,
+         make sure we call dequote_string on each word of the input
+         before calling bind_variable with that string
+
+subst.c
+       - made an efficiency improvement to dequote_string -- don't
+         do anything when we see CTLESC, just `continue' the loop
diff --git a/CWRU/misc/aux-mach-desc b/CWRU/misc/aux-mach-desc
new file mode 100644 (file)
index 0000000..71a8dab
--- /dev/null
@@ -0,0 +1,20 @@
+/* ************************ */
+/*                        */
+/*    A/UX 3.0 System     */
+/*                        */
+/* ************************ */
+#if defined (mc68k32) && !defined (M_MACHINE)
+#  define M_MACHINE "Macintosh"
+#  define M_OS "AUX"
+#  define SYSDEP_CFLAGS -ZP -DUSG -DHAVE_BCOPY -DHAVE_UID_T -DNSIG=32 \
+                       -DHAVE_GETDTABLESIZE
+#  define SYSDEP_LDFLAGS -ZP
+#  define HAVE_DIRENT
+#  define HAVE_POSIX_SIGNALS
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define HAVE_GETGROUPS
+#  undef HAVE_RESOURCE
+#  undef HAVE_ALLOCA
+#  define REQUIRED_LIBRARIES -lc_s
+#endif /* A/UX */
diff --git a/CWRU/misc/bison b/CWRU/misc/bison
new file mode 100755 (executable)
index 0000000..b819c90
--- /dev/null
@@ -0,0 +1,7 @@
+#! /bin/sh
+
+if [ "$1" = '-y' ]; then
+       shift
+fi
+
+exec /usr/bin/yacc ${1+"$@"}
diff --git a/CWRU/misc/open-files.c b/CWRU/misc/open-files.c
new file mode 100644 (file)
index 0000000..8f4d18e
--- /dev/null
@@ -0,0 +1,16 @@
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <stdio.h>
+
+main()
+{
+       register int    i;
+
+       for (i = 0; i < getdtablesize(); i++) {
+               if (fcntl(i, F_GETFD, 0) != -1)
+                       fprintf(stderr, "fd %d: open\n", i);
+       }
+       exit(0);
+}
+
diff --git a/CWRU/misc/pid.c b/CWRU/misc/pid.c
new file mode 100644 (file)
index 0000000..458fde4
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+main()
+{
+       fprintf(stderr, "%d\n", getpid());
+       exit(0);
+}
diff --git a/CWRU/misc/sigs.c b/CWRU/misc/sigs.c
new file mode 100644 (file)
index 0000000..ea9f955
--- /dev/null
@@ -0,0 +1,27 @@
+#include <signal.h>
+#include <stdio.h>
+
+extern char    *sys_siglist[];
+
+typedef void   sighandler();
+
+main(argc, argv)
+int    argc;
+char   **argv;
+{
+       register int    i;
+       sighandler      *h;
+
+       for (i = 1; i < NSIG; i++) {
+               h = signal(i, SIG_DFL);
+               if (h != SIG_DFL) {
+                       if (h == SIG_IGN)
+                               fprintf(stderr, "%d: ignored (%s)\n", i, sys_siglist[i]);
+                       else
+                               fprintf(stderr, "%d: caught (%s)\n", i, sys_siglist[i]);
+               }
+       }
+       exit(0);
+}
+
+               
diff --git a/CWRU/misc/sigstat.c b/CWRU/misc/sigstat.c
new file mode 100644 (file)
index 0000000..f1ac557
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * sigstat - print out useful information about signal arguments
+ *
+ */
+
+#include <sys/types.h>
+#include <signal.h>
+#include <stdio.h>
+
+extern char    *strrchr();
+static char    *signames[NSIG];
+
+char   *progname;
+
+void   sigstat();
+
+main(argc, argv)
+int    argc;
+char   **argv;
+{
+       register int    i;
+       char    *t;
+
+       if (t = strrchr(argv[0], '/'))
+               progname = ++t;
+       else
+               progname = argv[0];
+       init_signames();
+       if (argc == 1) {
+               for (i = 1; i < NSIG; i++)
+                       sigstat(i);
+               exit(0);
+       }
+       for (i = 1; i < argc; i++)
+               sigstat(atoi(argv[i]));
+       exit(0);
+}
+
+void
+sigstat(sig)
+int    sig;
+{
+       struct sigaction oact;
+       char *signame;
+       sigset_t set, oset;
+       int blocked;
+
+       if (sig < 0 || sig >= NSIG) {
+               fprintf(stderr, "%s: %d: signal out of range\n", progname, sig);
+               return;
+       }
+       signame = signames[sig];
+       sigemptyset(&oset);
+       sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &oset);
+       if (sigismember(&oset, sig))
+               printf("%s: signal is blocked\n", signame);
+       sigaction(sig, (struct sigaction *)NULL, &oact);
+       if (oact.sa_handler == SIG_IGN)
+               printf("%s: signal is ignored\n", signame);
+       else if (oact.sa_handler == SIG_DFL)
+               printf("%s: signal is defaulted\n", signame);
+       else
+               printf("%s: signal is trapped (?)\n", signame);
+}
+
+init_signames()
+{
+       register int i;
+       bzero(signames, sizeof(signames));
+
+#if defined (SIGHUP)           /* hangup */
+       signames[SIGHUP] = "SIGHUP";
+#endif
+#if defined (SIGINT)           /* interrupt */
+       signames[SIGINT] = "SIGINT";
+#endif
+#if defined (SIGQUIT)          /* quit */
+       signames[SIGQUIT] = "SIGQUIT";
+#endif
+#if defined (SIGILL)           /* illegal instruction (not reset when caught) */
+       signames[SIGILL] = "SIGILL";
+#endif
+#if defined (SIGTRAP)          /* trace trap (not reset when caught) */
+       signames[SIGTRAP] = "SIGTRAP";
+#endif
+#if defined (SIGABRT)          /*  */
+       signames[SIGABRT] = "SIGABRT";
+#endif
+#if defined (SIGIOT)           /* IOT instruction */
+       signames[SIGIOT] = "SIGIOT";
+#endif
+#if defined (SIGEMT)           /* EMT instruction */
+       signames[SIGEMT] = "SIGEMT";
+#endif
+#if defined (SIGFPE)           /* floating point exception */
+       signames[SIGFPE] = "SIGFPE";
+#endif
+#if defined (SIGKILL)          /* kill (cannot be caught or ignored) */
+       signames[SIGKILL] = "SIGKILL";
+#endif
+#if defined (SIGBUS)           /* bus error */
+       signames[SIGBUS] = "SIGBUS";
+#endif
+#if defined (SIGSEGV)          /* segmentation violation */
+       signames[SIGSEGV] = "SIGSEGV";
+#endif
+#if defined (SIGSYS)           /* bad argument to system call */
+       signames[SIGSYS] = "SIGSYS";
+#endif
+#if defined (SIGPIPE)          /* write on a pipe with no one to read it */
+       signames[SIGPIPE] = "SIGPIPE";
+#endif
+#if defined (SIGALRM)          /* alarm clock */
+       signames[SIGALRM] = "SIGALRM";
+#endif
+#if defined (SIGTERM)          /* software termination signal from kill */
+       signames[SIGTERM] = "SIGTERM";
+#endif
+#if defined (SIGCLD)           /* Like SIGCHLD.  */
+       signames[SIGCLD] = "SIGCLD";
+#endif
+#if defined (SIGPWR)           /* Magic thing for some machines. */
+       signames[SIGPWR] = "SIGPWR";
+#endif
+#if defined (SIGPOLL)          /* For keyboard input?  */
+       signames[SIGPOLL] = "SIGPOLL";
+#endif
+#if defined (SIGURG)           /* urgent condition on IO channel */
+       signames[SIGURG] = "SIGURG";
+#endif
+#if defined (SIGSTOP)          /* sendable stop signal not from tty */
+       signames[SIGSTOP] = "SIGSTOP";
+#endif
+#if defined (SIGTSTP)          /* stop signal from tty */
+       signames[SIGTSTP] = "SIGTSTP";
+#endif
+#if defined (SIGCONT)          /* continue a stopped process */
+       signames[SIGCONT] = "SIGCONT";
+#endif
+#if defined (SIGCHLD)          /* to parent on child stop or exit */
+       signames[SIGCHLD] = "SIGCHLD";
+#endif
+#if defined (SIGTTIN)          /* to readers pgrp upon background tty read */
+       signames[SIGTTIN] = "SIGTTIN";
+#endif
+#if defined (SIGTTOU)          /* like TTIN for output if (tp->t_local&LTOSTOP) */
+       signames[SIGTTOU] = "SIGTTOU";
+#endif
+#if defined (SIGIO)            /* input/output possible signal */
+       signames[SIGIO] = "SIGIO";
+#endif
+#if defined (SIGXCPU)          /* exceeded CPU time limit */
+       signames[SIGXCPU] = "SIGXCPU";
+#endif
+#if defined (SIGXFSZ)          /* exceeded file size limit */
+       signames[SIGXFSZ] = "SIGXFSZ";
+#endif
+#if defined (SIGVTALRM)                /* virtual time alarm */
+       signames[SIGVTALRM] = "SIGVTALRM";
+#endif
+#if defined (SIGPROF)          /* profiling time alarm */
+       signames[SIGPROF] = "SIGPROF";
+#endif
+#if defined (SIGWINCH)         /* window changed */
+       signames[SIGWINCH] = "SIGWINCH";
+#endif
+#if defined (SIGLOST)          /* resource lost (eg, record-lock lost) */
+       signames[SIGLOST] = "SIGLOST";
+#endif
+#if defined (SIGUSR1)          /* user defined signal 1 */
+       signames[SIGUSR1] = "SIGUSR1";
+#endif
+#if defined (SIGUSR2)          /* user defined signal 2 */
+       signames[SIGUSR2] = "SIGUSR2";
+#endif
+#if defined (SIGMSG)   /* HFT input data pending */
+       signames[SIGMSG] = "SIGMSG";
+#endif
+#if defined (SIGPWR)   /* power failure imminent (save your data) */
+       signames[SIGPWR] = "SIGPWR";
+#endif
+#if defined (SIGDANGER)        /* system crash imminent */
+       signames[SIGDANGER] = "SIGDANGER";
+#endif
+#if defined (SIGMIGRATE)       /* migrate process to another CPU */
+       signames[SIGMIGRATE] = "SIGMIGRATE";
+#endif
+#if defined (SIGPRE)   /* programming error */
+       signames[SIGPRE] = "SIGPRE";
+#endif
+#if defined (SIGGRANT) /* HFT monitor mode granted */
+       signames[SIGGRANT] = "SIGGRANT";
+#endif
+#if defined (SIGRETRACT)       /* HFT monitor mode retracted */
+       signames[SIGRETRACT] = "SIGRETRACT";
+#endif
+#if defined (SIGSOUND) /* HFT sound sequence has completed */
+       signames[SIGSOUND] = "SIGSOUND";
+#endif
+
+       for (i = 0; i < NSIG; i++)
+               if (signames[i] == (char *)NULL) {
+                       signames[i] = (char *)malloc (16);;
+                       sprintf (signames[i], "signal %d", i);
+               }
+}
diff --git a/CWRU/sh-redir-hack b/CWRU/sh-redir-hack
new file mode 100644 (file)
index 0000000..413b297
--- /dev/null
@@ -0,0 +1,15 @@
+Add to `subshell' production in parse.y and recompile -DREDIRECTION_HACK to
+get `< xx (command)' sh compatibility.
+
+       |       redirections '(' list ')'
+                       {
+#if defined (REDIRECTION_HACK)
+                         /* XXX - C News sh compatibility hack - XXX */
+                         $3->redirects = $1;
+                         $3->flags |= CMD_WANT_SUBSHELL;
+                         $$ = $3;
+#else
+                         yyerror ();
+                         YYABORT;
+#endif
+                       }
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..e366406
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,212 @@
+File: bash.info,  Node: Install,  Next: Invoke,         Prev: Built-in,  Up: Top
+
+Installing BASH
+***************
+
+To install BASH you simply type `make'.         The BASH `Makefile' tries
+to dynamically figure out what kind of machine and operating system
+you are using. It makes an educated guess based on the information
+it finds.
+
+During the `make' process, a message is displayed describing what
+machine and operating system has been chosen for you.  This
+information is also saved in the file `.machine' so you can look at
+it later.
+
+Therefore, for most machines, simply follow this simple checklist
+to install BASH:
+
+  1. Type `make'.  If you want to use GCC to compile bash, type
+     `make CC=gcc CPPNAME='$(CC) -E''.
+
+  2. Wait for the compilation to finish.
+
+  3. Type `./bash' to see if the compile worked.
+
+  4. Type `make install prefix=/usr/gnu/' (or the appropriate root
+     of your local GNU software installation tree) to copy bash to
+     your binaries directory, assumed to be ${prefix}/bin.  This will
+     also attempt to install the manual pages under ${prefix}/man
+     and the info file under ${prefix}/info.
+
+* Menu:
+
+* Problems::  What to do if BASH doesn't install quite so easily.
+
+* Files::     Files used in the `make' process.
+
+* Porting::   Porting BASH to a new machine.
+
+* Bugs::      What to do if you Discover Bugs in BASH.
+
+File: bash.info,  Node: Problems,  Next: Files,         Prev: Install,  Up: Install
+
+What if it Doesn't Install so Easily?
+=====================================
+
+Sometimes BASH gets confused and will make the wrong assumptions
+about your machine or operating system.         If the displayed
+information (also found in `.machine') is incorrect, you will have
+to edit the file `machines.h' and provide the appropriate
+information so that BASH can be installed correctly.  The complete
+instructions for doing this are located in the `machines.h' file.
+
+However, if BASH says that your machine type is an
+"UNKNOWN_MACHINE", or BASH thought it knew something about your
+machine but was wrong, then reading the next few sections could
+be of use to you (*note Files::., and *note Porting::., for more
+information). 
+
+On the MIPSEB with the BSD universe, you must:
+
+1) Place /bsd43/bin in your PATH before /bin
+2) Use $(CC) -E instead of /lib/cpp to build cpp-Makefile.
+
+On SCO Xenix 386, you must:
+
+1) Use $(CC) -E instead of /lib/cpp to build cpp-Makefile.
+
+On Interactive Unix version 3 or 4, you must:
+
+1) Edit cpp-Makefile to remove either -O or -g from DEBUG_FLAGS
+
+File: bash.info,  Node: Files, Next: Porting,  Prev: Problems,  Up: Install
+
+Files Used in the `make' Process.
+=================================
+
+The following files are used during the installation of BASH, in
+the `make' process:
+
+`Makefile'
+     This is responsible for making the actual `Makefile' that is
+     used to create Bash.  It runs the C preprocessor (usually
+     located in `/lib/cpp') on the file `cpp-Makefile', producing
+     the output file `bash-Makefile'.
+
+`cpp-Makefile'
+     This is a file of C comments and text.  It contains a
+     reasonable number of `ifdefs' which control what files get
+     compiled and which flags are passed to the various C files
+     comprising BASH.  It includes files named `machines.h',
+     `sysdefs.h', and `config.h'.
+
+`machines.h'
+     This file contains the basic compilation parameters for all of
+     the machines to which BASH has been ported.  This file
+     consists of a series of conditional blocks, one per machine
+     type.
+
+     These conditional blocks are depend upon the unique identifier
+     that `cpp' has predefined for this machine.  In some cases,
+     additional information can be passed from `Makefile'.  It is
+     possible to pass information such as whether or not a
+     particular file is available on this system, and so on.
+
+`sysdefs.h'
+     This file is dynamically made at build time by running the shell
+     script `support/mksydefs'.  If there appears to be something wrong
+     in this file, then edit the `mksysdefs' script, and mail the
+     changes that you make to bash-maintainers@prep.ai.mit.edu.
+
+`bash-Makefile'
+     This is the output from the initial stage of `make'.  It is a
+     stripped down version of `cpp-Makefile' which is tailor-made
+     for your machine and operating system.  All subsequent `makes'
+     use this file.
+
+
+File: bash.info,  Node: Porting,  Next: Bugs,  Prev: Files,  Up: Install
+
+What if You Have to Port to a New Machine?
+==========================================
+
+Sometimes you may want to port BASH to a new, previously
+unsupported machine.  To do so you need to create a block in
+`machines.h' which is conditional based on a unique identifier
+present in your version of the C preprocessor.
+
+If you don't know what that symbol is, you might try the following
+simple test:
+
+     echo "main () { }" > foo.c
+     cc -v foo.c
+
+You are looking for `-DMACHINE', where `MACHINE' is an identifier
+for your machine.  If you are very unlucky and your machine's C
+preprocessor doesn't have a unique identifier, you will have to
+define the identifier in Makefile manually.
+
+Let's say you have a machine from Yoyodyne Industries, called the
+YoYo.  It runs a version of BSD, so it is reasonably compatible. 
+However, the `cpp' on this YoYo machine doesn't define any unique
+identifiers.  You should change the `Makefile' line for `CPPFLAGS'
+to:
+
+     CPPFLAGS = -P -DYoYo
+
+Then, in `machines.h', you copy the block for `UNKNOWN_MACHINE',
+and change the conditional to;
+
+     #if defined (YoYo)
+
+Inside of the YoYo block you define `M_MACHINE="YoYo"', and
+`M_OS=Bsd'.  You also modify the existing defines to match your
+machine's software.
+
+If BASH still won't compile, perhaps because of missing code that
+is required for your YoYo machine, you will have to write that code
+and place it within a conditional block based on YoYo.
+
+Most machines aren't that difficult; simply redefining a few of the
+default values is sufficient.  If you do run across a difficult
+machine, please send all fixes and changes to
+bash-maintainers@prep.ai.mit.edu in the form of context diffs:
+
+     diff -c orig-machines.h machines.h >machines.diffs
+
+Please include information about which version of the shell you have.
+
+For those machines which prove more difficult, or if you are not
+sure about where to start, the scripts in the `portbash' directory
+may prove helpful.
+
+File: bash.info,  Node: Bugs,  Prev: Porting,  Up: Install
+
+Reporting Bugs
+==============
+
+If you find a bug in bash, you should report it.  But first you
+should make sure that it really is a bug and that it appears in the
+latest version of BASH that is available.
+
+Once you have ascertained that a bug really exists, you are welcome
+to mail in a bug report.  If you have a fix, please mail that too!
+The program `bashbug' is used to submit bug reports.
+
+Suggestions and "philosophical" bug reports should be mailed to
+bug-bash@ai.mit.edu.  Genuine bug reports should be mailed to the
+same place, or to bash-maintainers@prep.ai.mit.edu.  The `bashbug'
+script sends its messages to bug-bash@prep.ai.mit.edu.
+
+*All* bug reports should include:
+
+   * The version number of BASH.
+
+   * The hardware and operating system used.
+
+   * The compiler used to compile BASH.
+
+   * A description of the bug's behavior.
+
+   * A short script or "recipe" which demonstrates the bug.
+
+The `bashbug' program includes much of this information
+automatically.  Without this information, it is generally not
+possible to successfully debug BASH.  Usually, without this
+information, the bug won't manifest itself! 
+
+Discussion and questions about BASH in general (including
+questions about this documentation) can be sent to
+bash-maintainers@prep.ai.mit.edu. 
diff --git a/MANIFEST b/MANIFEST
new file mode 100644 (file)
index 0000000..4307b2f
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,421 @@
+#
+# Master distribution manifest for bash
+#
+#
+# Filename     type
+#
+CWRU           d
+CWRU/misc      d
+builtins       d
+documentation  d
+examples       d
+examples/functions d
+examples/scripts d
+examples/startup-files d
+lib            d
+lib/doc-support        d
+lib/glob       d
+lib/glob/doc   d
+lib/malloc     d
+lib/malloclib  d
+lib/posixheaders d
+lib/readline   d
+lib/readline/doc d
+lib/readline/examples d
+lib/termcap    d
+lib/termcap/grot d
+lib/tilde      d
+lib/tilde/doc  d
+portbash       d
+support                d
+tests          d
+tests/misc     d
+README         f
+RELEASE                f
+INSTALL                f
+COPYING                f
+MANIFEST       f
+configure      f
+Makefile       f
+cpp-Makefile   f
+print_cmd.c    f
+general.c      f
+variables.c    f
+make_cmd.c     f
+copy_cmd.c     f
+unwind_prot.c  f
+dispose_cmd.c  f
+getcwd.c       f
+bashhist.c     f
+hash.c         f
+parse.y                f
+subst.c                f
+shell.c                f
+trap.c         f
+siglist.c      f
+version.c      f
+flags.c                f
+jobs.c         f
+newversion.c   f
+input.c                f
+mailcheck.c    f
+test.c         f
+expr.c         f
+alias.c                f
+execute_cmd.c  f
+bashline.c     f
+braces.c       f
+bracecomp.c    f
+nojobs.c       f
+vprint.c       f
+error.c                f
+signames.c     f
+endian.c       f
+alias.h                f
+config.h       f
+config.h.mini  f
+builtins.h     f
+parser.h       f
+variables.h    f
+machines.h     f
+jobs.h         f
+maxpath.h      f
+filecntl.h     f
+hash.h         f
+quit.h         f
+flags.h                f
+shell.h                f
+trap.h         f
+general.h      f
+unwind_prot.h  f
+input.h                f
+error.h                f
+command.h      f
+externs.h      f
+siglist.h      f
+subst.h        f
+dispose_cmd.h  f
+bashansi.h     f
+make_cmd.h     f
+bashhist.h     f
+execute_cmd.h  f
+bashtypes.h    f
+y.tab.c                f
+y.tab.h                f
+posixstat.h    f
+stdc.h         f
+ansi_stdlib.h  f
+memalloc.h     f
+parser-built   f
+builtins/ChangeLog     f
+builtins/Makefile      f
+builtins/alias.def     f
+builtins/bind.def      f
+builtins/break.def     f
+builtins/builtin.def   f
+builtins/cd.def                f
+builtins/colon.def     f
+builtins/command.def   f
+builtins/common.c      f
+builtins/declare.def   f
+builtins/echo.def      f
+builtins/enable.def    f
+builtins/eval.def      f
+builtins/exec.def      f
+builtins/exit.def      f
+builtins/fc.def                f
+builtins/fg_bg.def     f
+builtins/getopt.c      f
+builtins/getopt.h      f
+builtins/getopts.def   f
+builtins/hash.def      f
+builtins/hashcom.h     f
+builtins/help.def      f
+builtins/let.def       f
+builtins/history.def   f
+builtins/jobs.def      f
+builtins/kill.def      f
+builtins/mkbuiltins.c  f
+builtins/read.def      f
+builtins/reserved.def  f
+builtins/return.def    f
+builtins/set.def       f
+builtins/setattr.def   f
+builtins/shift.def     f
+builtins/source.def    f
+builtins/suspend.def   f
+builtins/test.def      f
+builtins/times.def     f
+builtins/trap.def      f
+builtins/type.def      f
+builtins/ulimit.def    f
+builtins/umask.def     f
+builtins/wait.def      f
+builtins/psize.c       f
+builtins/psize.sh      f
+builtins/inlib.def     f
+builtins/bashgetopt.c  f
+builtins/common.h      f
+builtins/bashgetopt.h  f
+lib/doc-support/texindex.c     f
+lib/doc-support/getopt.h       f
+lib/doc-support/Makefile       f
+lib/glob/ChangeLog     f
+lib/glob/Makefile      f
+lib/glob/fnmatch.c     f
+lib/glob/fnmatch.h     f
+lib/glob/glob.c                f
+lib/glob/doc/Makefile  f
+lib/glob/doc/glob.texi f
+lib/glob/ndir.h                f
+lib/malloc/Makefile    f
+lib/malloc/alloca.c    f
+lib/malloc/getpagesize.h       f
+lib/malloc/i386-alloca.s       f
+lib/malloc/malloc.c    f
+lib/malloc/x386-alloca.s       f
+lib/malloc/xmalloc.c   f
+lib/malloclib/Makefile f
+lib/malloclib/alloca.c f
+lib/malloclib/i386-alloca.s    f
+lib/malloclib/calloc.c f
+lib/malloclib/cfree.c  f
+lib/malloclib/x386-alloca.s    f
+lib/malloclib/morecore.c       f
+lib/malloclib/free.c   f
+lib/malloclib/getpagesize.h    f
+lib/malloclib/malloc.c f
+lib/malloclib/malloc.h f
+lib/malloclib/xmalloc.c        f
+lib/malloclib/mcheck.c f
+lib/malloclib/memalign.c       f
+lib/malloclib/mstats.c f
+lib/malloclib/mtrace.awk       f
+lib/malloclib/mtrace.c f
+lib/malloclib/realloc.c        f
+lib/malloclib/valloc.c f
+lib/posixheaders/posixstat.h   f
+lib/posixheaders/ansi_stdlib.h f
+lib/posixheaders/stdc.h        f
+lib/posixheaders/memalloc.h    f
+lib/posixheaders/filecntl.h    f
+lib/readline/COPYING   f
+lib/readline/readline.c        f
+lib/readline/readline.h        f
+lib/readline/ChangeLog f
+lib/readline/vi_mode.c f
+lib/readline/history.h f
+lib/readline/Makefile  f
+lib/readline/chardefs.h        f
+lib/readline/emacs_keymap.c    f
+lib/readline/keymaps.h f
+lib/readline/vi_keymap.c       f
+lib/readline/history.c f
+lib/readline/funmap.c  f
+lib/readline/keymaps.c f
+lib/readline/xmalloc.c f
+lib/readline/doc/Makefile      f
+lib/readline/doc/rlman.texinfo f
+lib/readline/doc/rltech.texinfo        f
+lib/readline/doc/rluser.texinfo        f
+lib/readline/doc/hist.texinfo  f
+lib/readline/doc/hstech.texinfo        f
+lib/readline/doc/hsuser.texinfo        f
+lib/readline/examples/Makefile f
+lib/readline/examples/fileman.c        f
+lib/readline/examples/manexamp.c       f
+lib/readline/examples/histexamp.c      f
+lib/readline/examples/Inputrc  f
+lib/readline/README    f
+lib/readline/STANDALONE f
+lib/readline/search.c  f
+lib/readline/isearch.c f
+lib/readline/rldefs.h  f
+lib/readline/rlconf.h  f
+lib/readline/parens.c  f
+lib/readline/rltty.c   f
+lib/readline/complete.c        f
+lib/readline/bind.c    f
+lib/readline/display.c f
+lib/readline/signals.c f
+lib/readline/doc/texindex.c    f
+lib/readline/tilde.c   f
+lib/readline/tilde.h   f
+lib/readline/posixstat.h       f
+lib/readline/ansi_stdlib.h     f
+lib/readline/memalloc.h        f
+lib/termcap/Makefile   f
+lib/termcap/termcap.c  f
+lib/termcap/termcap.h  f
+lib/termcap/tparam.c   f
+lib/termcap/version.c  f
+lib/termcap/grot/termcap.info  f
+lib/termcap/grot/termcap.info-1        f
+lib/termcap/grot/termcap.info-2        f
+lib/termcap/grot/termcap.info-3        f
+lib/termcap/grot/termcap.info-4        f
+lib/termcap/grot/NEWS  f
+lib/termcap/grot/INSTALL       f
+lib/termcap/grot/ChangeLog     f
+lib/termcap/grot/texinfo.tex   f
+lib/termcap/grot/termcap.texi  f
+lib/termcap/grot/Makefile.in   f
+lib/termcap/grot/configure     f
+lib/termcap/grot/configure.in  f
+lib/termcap/grot/COPYING       f
+lib/termcap/grot/README        f
+lib/tilde/ChangeLog    f
+lib/tilde/Makefile     f
+lib/tilde/doc/tilde.texi       f
+lib/tilde/doc/Makefile f
+lib/tilde/tilde.c      f
+lib/tilde/tilde.h      f
+lib/tilde/memalloc.h   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/aux-mach-desc        f
+CWRU/PLATFORMS         f
+CWRU/README            f
+CWRU/POSIX.NOTES       f
+CWRU/changelog         f
+CWRU/sh-redirection-hack f
+documentation/Makefile f
+documentation/bash.1   f
+documentation/bash.ps  f
+documentation/bash.txt f
+documentation/README   f
+documentation/readline.3       f
+documentation/readline.ps      f
+documentation/readline.txt     f
+documentation/texinfo.tex      f
+documentation/features.texi    f
+documentation/features.info    f
+documentation/features.dvi     f
+documentation/features.ps      f
+documentation/builtins.1       f
+documentation/builtins.ps      f
+documentation/builtins.txt     f
+documentation/article.ms       f
+documentation/article.ps       f
+documentation/article.txt      f
+support/cat-s          f
+support/mksysdefs      f
+support/printenv       f
+support/getcppsyms.c   f
+support/cppmagic       f
+support/bash.xbm       f
+support/FAQ            f
+support/PORTING                f
+support/mklinks                f
+support/mkdirs         f
+support/clone-bash     f
+support/bashbug.sh     f
+support/mkmachtype     f
+support/recho.c                f
+support/srcdir         f
+support/SYMLINKS       f
+support/fixlinks       f
+examples/functions/substr      f
+examples/functions/kshenv      f
+examples/functions/autoload    f
+examples/functions/csh-compat  f
+examples/functions/shcat       f
+examples/functions/substr2     f
+examples/functions/term                f
+examples/functions/whatis      f
+examples/functions/whence      f
+examples/functions/func                f
+examples/functions/dirname     f
+examples/functions/dirfuncs    f
+examples/functions/basename    f
+examples/functions/exitstat    f
+examples/functions/external    f
+examples/functions/fact                f
+examples/functions/manpage     f
+examples/functions/fstty       f
+examples/functions/jj.bash     f
+examples/functions/notify.bash f
+examples/scripts/shprompt      f
+examples/scripts/adventure.sh  f
+examples/scripts/precedence    f
+examples/scripts/bcsh.sh       f
+examples/startup-files/Bashrc  f
+examples/startup-files/Bash_aliases    f
+examples/startup-files/Bash_profile    f
+examples/startup-files/bash-profile    f
+examples/startup-files/bashrc  f
+examples/suncmd.termcap        f
+examples/alias-conv.sh f
+tests/README           f
+tests/dollar-at.sh     f
+tests/dollar-star.sh   f
+tests/dollar.right     f
+tests/exp-tests                f
+tests/exp.right                f
+tests/glob-test                f
+tests/glob.right       f
+tests/ifs-test-1.sh    f
+tests/ifs-test-2.sh    f
+tests/ifs-test-3.sh    f
+tests/ifs.1.right      f
+tests/ifs.2.right      f
+tests/ifs.3.right      f
+tests/input-line.sh    f
+tests/input-line.sub   f
+tests/input.right      f
+tests/minus-e          f
+tests/minus-e.right    f
+tests/new-exp.tests    f
+tests/new-exp.right    f
+tests/prec.right       f
+tests/precedence       f
+tests/run-all          f
+tests/run-dollars      f
+tests/run-exp-tests    f
+tests/run-glob-test    f
+tests/run-ifs-tests    f
+tests/run-input-test   f
+tests/run-minus-e      f
+tests/run-new-exp      f
+tests/run-precedence   f
+tests/run-set-e-test   f
+tests/run-strip                f
+tests/run-varenv       f
+tests/set-e-test       f
+tests/set-e.right      f
+tests/strip.tests      f
+tests/strip.right      f
+tests/tilde-tests      f
+tests/tilde.right      f
+tests/varenv.right     f
+tests/varenv.sh                f
+tests/misc/chld-trap.sh        f
+tests/misc/dot-test-1.sh       f
+tests/misc/dot-test-1.sub      f
+tests/misc/gotest              f
+tests/misc/perf-script         f
+tests/misc/redir.t1.sh         f
+tests/misc/redir.t2.sh         f
+tests/misc/redir.t3.sh         f
+tests/misc/redir.t3.sub                f
+tests/misc/redir.t4.sh         f
+tests/misc/run.r1.sh   f
+tests/misc/run.r2.sh   f
+tests/misc/run.r3.sh   f
+tests/misc/sigint.t1.sh                f
+tests/misc/sigint.t2.sh                f
+tests/misc/sigint.t3.sh                f
+tests/misc/sigint.t4.sh                f
+tests/misc/test-minus-e.1      f
+tests/misc/test-minus-e.2      f
+portbash/signals.sh    f
+portbash/stdio.sh      f
+portbash/libc.sh       f
+portbash/mkdesc.sh     f
+portbash/README                f
+portbash/strings.sh    f
+portbash/syscalls.sh   f
+portbash/pgrp.c                f
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..da50f7a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,115 @@
+# Hey Emacs, this Makefile is in -*- makefile -*- mode!
+#
+# Makefile for Bash.
+# If your cpp doesn't like -P, just get rid of it (the -P, not cpp).
+# If you wish to use Gcc, then type `make CC=gcc CPPNAME='$(CC) -E''.
+# If you wish to use GNU's Make, then change `MAKE'.
+# If you don't like the destination, then change `bindir'.
+# The file that you most likely want to look at is cpp-Makefile.
+#
+# If you haven't read README, now might be a good time.
+
+# Include some boilerplate Gnu makefile definitions.
+prefix = /usr/local
+exec_prefix = $(prefix)
+bindir = $(exec_prefix)/bin
+srcdir = .
+VPATH = $(srcdir)
+
+# MAKE    = make
+RM      = rm -f
+SHELL   = /bin/sh
+GAWK     = awk
+# GAWK     = gawk
+
+# Force CPPNAME to be the name of your C preprocesor if Bash can't
+# find it.  For instance, `CPPNAME=/usr/libexec/cpp' on 4.4 BSD.
+# If all else fails, set CPPNAME=$(CC) -E
+CPPNAME =
+CPP     = `$(SHELL) $(CPPMAGIC) $(GETCPPSYMS) "$(CPPNAME)"` -P
+
+CPP_MAKEFILE = $(srcdir)/cpp-Makefile
+ANSI_MAKEFILE = ansi-Makefile
+
+# CPPFLAGS = $(SYSTEM) $(CPP_DEFINES)
+CPPFLAGS = $(CPP_DEFINES) -I. -I$(srcdir)
+CPP_ARGS = -DCPP_CC="$(CC)"
+
+SUPPORTDIR     = ./support/
+SUPPORTSRC     = $(srcdir)/support/
+
+MKSYSDEFS      = $(SUPPORTSRC)mksysdefs
+CPPMAGIC       = $(SUPPORTSRC)cppmagic
+CAT_S          = $(SUPPORTSRC)cat-s
+GETCPPSYMS     = $(SUPPORTDIR)getcppsyms
+GETCPPSYMS_SRC = $(SUPPORTSRC)getcppsyms.c
+
+# Here is a command which compresses runs of multiple blank lines to a
+# single blank line.  "cat -s" works for BSD systems, but not for USG
+# systems.  You can use an awk script if you like.  If you have too
+# much trouble with this, just forget it.  It is for making
+# bash-Makefile pretty and readable; something that isn't strictly
+# necessary.
+# SQUASH_BLANKS = cat -s
+#
+SQUASH_BLANKS = $(GAWK) -f $(CAT_S)
+
+all:   .notified bash-Makefile
+       $(MAKE) -f bash-Makefile $(MFLAGS) $(MAKEARGS) srcdir=$(srcdir)
+
+bash-Makefile: $(CPP_MAKEFILE) Makefile machines.h sysdefs.h config.h
+       @-if [ -f ansi-Makefile ]; then \
+           echo "cp ansi-Makefile tmp-Makefile.c"; \
+           cp ansi-Makefile tmp-Makefile.c; else \
+           echo "cp $(CPP_MAKEFILE) tmp-Makefile.c"; \
+           cp $(CPP_MAKEFILE) tmp-Makefile.c; \
+         fi
+       $(RM) $(GETCPPSYMS)
+       $(SHELL) $(SUPPORTSRC)mkdirs support
+       $(CC) -o $(GETCPPSYMS) $(GETCPPSYMS_SRC)
+       rm -f bash-Makefile
+       @$(SHELL) -c 'echo $(CPP) $(CPPFLAGS) $(CPP_ARGS) tmp-Makefile.c \| $(SQUASH_BLANKS) \> bash-Makefile'
+       @$(SHELL) -c '$(CPP) $(CPPFLAGS) $(CPP_ARGS) tmp-Makefile.c | $(SQUASH_BLANKS) >bash-Makefile'
+       rm -f tmp-Makefile.c
+       @test -s bash-Makefile || { rm -f bash-Makefile ; exit 1; }
+
+sysdefs.h: $(MKSYSDEFS)
+       $(SHELL) $(MKSYSDEFS) -s $(srcdir)
+
+# This is also performed by support/mksysdefs, but there's no way to change
+# it if cpp-Makefile is changed without changing anything else, since there
+# are no dependencies.  This lets you run `make ansi-Makefile'.
+ansi-Makefile: $(CPP_MAKEFILE)
+       grep -v '/\*\*/' $(CPP_MAKEFILE) > $@
+
+# Subsequent lines contain targets that are correctly handled by an
+# existing bash-Makefile.
+
+install uninstall newversion architecture: bash-Makefile
+       $(MAKE) -f bash-Makefile $(MFLAGS) $(MAKEARGS) bindir=$(bindir) \
+               prefix=$(prefix) $@
+
+tests DEFINES tags documentation: bash-Makefile directory-frob
+       $(MAKE) -f bash-Makefile $(MFLAGS) $(MAKEARGS) $@
+
+clean distclean realclean mostlyclean maintainer-clean: bash-Makefile directory-frob
+       rm -f .notified
+       $(MAKE) -f bash-Makefile $(MFLAGS) $(MAKEARGS) $@
+
+directory-frob:
+
+.NOEXPORT:
+
+.notified:
+       @echo ""
+       @echo "   You are about to make this version of GNU Bash for"
+       @echo "   this architecture for the first time.  If you haven't"
+       @echo "   yet read the README file, you may want to do so.  If"
+       @echo "   you wish to report a bug in Bash, or in the installation"
+       @echo "   procedure, please run the bashbug script and include:"
+       @echo ""
+       @echo " * a description of the bug,"
+       @echo " * a recipe for recreating the bug reliably,"
+       @echo " * a fix for the bug if you have one!"
+       @echo ""
+       @touch .notified
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..783d193
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,10 @@
+This file documents the bugs fixed between this release, bash-1.14.7,
+and the last public bash release, 1.14.6.
+
+1.  Bugs fixed in Bash
+
+a.  A memory leak that caused long-running scripts to eventually consume
+    all available memory was fixed.
+
+b.  A sign-extension bug that caused a security hole for non-interactive
+    shells was fixed.
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..6638c6e
--- /dev/null
+++ b/README
@@ -0,0 +1,52 @@
+This README file is in -*- text -*- mode, because Emacs likes it that way.
+
+This is GNU Bash, version 1.14.  Bash is the GNU Project's Bourne
+Again SHell, an interactive shell with Bourne shell syntax (/bin/sh);
+but also with interactive command line editing, job control on
+architectures that support it, Csh-like history features and brace
+expansion, and a slew of other stuff.  For more information on the
+features of Bash that are new to this type of shell, see the file
+`documentation/features.texi'.  There is also a DVI file there, as
+well as a large man page.
+
+To compile it, try typing `make'.  Bash auto-configures the build
+process, so no intervention should be necessary.  If you want to
+use gcc, type `make CC=gcc CPPNAME='$(CC) -E''.
+
+You may want to read the file INSTALL in this directory for more
+information if the make fails.
+
+If you are a csh user and wish to convert your csh aliases to Bash
+aliases, you may wish to use the script in examples/alias-conv.sh
+as a starting point.
+
+Bug reports for 1.14 should be sent to:
+
+       bug-bash@prep.ai.mit.edu
+
+using the `bashbug' program that is built and installed at the same
+time as bash.
+
+The discussion list "bug-bash@prep.ai.mit.edu" often contains information
+about new ports of Bash, or discussions of new features or behavior
+changes that people would like.  This mailing list is also available
+as a usenet newsgroup: gnu.bash.bug.
+
+When you send a bug report to bash-maintainers@prep.ai.mit.edu, please
+include:
+
+       * the version number of Bash
+       * the machine and OS that it is running on (see .machine or .made)
+       * a description of the bug
+       * a recipe for recreating the bug reliably
+       * a fix for the bug if you have one!
+
+The `bashbug' program includes much of this automatically.
+
+While the Bash maintainers do not promise to fix all bugs, we would
+like this shell to be the best that we can make it.
+
+Enjoy!
+
+Chet Ramey
+chet@po.cwru.edu
diff --git a/RELEASE b/RELEASE
new file mode 100644 (file)
index 0000000..6a5167e
--- /dev/null
+++ b/RELEASE
@@ -0,0 +1,269 @@
+This file details the changes between the previous release of bash (1.13.5)
+and this release (1.14.0).
+
+1. New Features in Bash
+
+a.  The source has been reorganized:  nearly all extern function
+    declarations have been moved to header files, function prototypes
+    have been added to most header files, function declarations have
+    been moved to file scope, dead code has been removed, the
+    bash history code has been isolated in bashhist.[ch], and several
+    new header files have been created
+
+b.  `set -o posix' puts bash into Posix.2 mode
+
+c.  If $POSIX_PEDANTIC exists in the initial environment or is assigned
+    a value, bash enters Posix.2 mode
+
+d.  Bash sets $OSTYPE to a string describing the UNIX version
+
+e.  The features.info file was completely rewritten and now reflects
+    the current state of things
+
+f.  A manual page for readline is in documentation/readline.{3,ps}
+
+g.  The test builtin emulates /dev/fd/x for systems without /dev/fd
+
+h.  `dirs' has -n and +n options to access members of the directory stack
+
+i.  Prompt string expansion handles invisible characters in the prompt;
+    \[ and \] are used (and required) to start and end sequences of
+    invisible chars
+
+j.  NO_PROMPT_VARS has been removed
+
+k.  New machine descriptions have been added:  IBM AIX/ESA, NEC EWS, NetBSD,
+    FreeBSD, QNX 4.2, concurrent, MIPS SVR4.2, Lynx 2.1
+
+l.  RESTRICTED_SHELL is no longer defined by default in config.h
+
+m.  The version string in $BASH_VERSION has changed to dist.patch(build)
+
+n.  $history_control has been renamed to $HISTCONTROL and now takes the
+    value `ignoreboth' ($history_control is still accepted for backwards
+    compatibility)
+
+o.  There is a new program `bashbug' for reporting bugs.  Eventually I will
+    probably switch to gnats.
+
+p.  auto_resume can take the values `exact' and `substring'
+
+q.  `set -P' (`set -o physical') enables the same physical view of the
+    file system that `nolinks' enables (`nolinks' will remain for one
+    more release)
+
+r.  There is a `mkmachtype' program to generate a GNU-style machine type
+    string (e.g., `sparc-sun-sunos4.1.2') suitable for assigning to
+    $MACHTYPE
+
+s.  The variable $HISTCMD returns the current history number
+
+t.  Variables in directory names are now expanded while doing completion
+
+u.  The test suite has been expanded and is runnable as a regression test
+    with `make tests'
+
+v.  `bye' is no longer a builtin synonym for `exit'
+
+w.  The ksh `select' control construct has been implemented
+
+x.  The `ignoreeof' attribute can be inherited if $IGNOREEOF is exported
+
+y.  The `USG-style' echo is now a configuration option.  Define
+    DEFAULT_ECHO_TO_USG for default \-interpretation without the -e flag
+
+z.  There is a copy of an article I wrote about bash for the Linux
+    Journal in documentation/article.{ms,ps}
+
+aa. The `pwd' builtin now obeys the setting of `set -o physical' (`nolinks')
+
+bb. Process substitution is no longer performed when the shell is in
+    `posix mode'
+
+cc. Users may change the debugging and optimization flags to cc by specifying
+    CFLAGS to make
+
+2. New Features in Readline
+
+a.  Readline now understands sequences of invisible characters in the prompt
+    string, as long as they are escaped (e.g., by the bash \[ and \] escapes)
+
+b.  A `set keymap' variable assignment
+
+c.  A `bell-style' variable that can be set to `visible', `audio', or `none'
+
+d.  A `show-all-if-ambiguous' variable, which causes non-unique completion
+    to immediately list the possible completions
+
+e.  An `output-meta' variable to make readline directly output chars
+    with the eighth bit set
+
+f.  New bindable readline commands: kill-whole-line, tilde-expand,
+    vi-redo, vi-tilde-expand, emacs-editing-mode,
+    non-incremental-forward-search-history-again,
+    non-incremental-reverse-search-history-again
+
+g.  New history-search-forward and history-search-backward to search for
+    the characters between the start of the current line and point
+
+h.  Readline takes the name of the startup file from the INPUTRC variable
+    before defaulting to ~/.inputrc
+
+i.  isearch no longer finds identical lines multiple times in succession
+
+j.  M-C-H bound to backward-kill-word in emacs mode
+
+k.  M-~ bound to tilde-expand in emacs mode
+
+l.  History expansion is now fully csh-compatible: missing modifiers and
+    substitutions have been added, and bugs fixed
+
+m.  When asking whether or not to display the possible completions, readline
+    now accepts space as equivalent to `y' and rubout for `n'
+
+n.  Readline now attempts to find and bind the arrow keys into the vi mode
+    movement keymap
+
+3.  Bugs fixed in Bash
+
+a.  Portability fixes: `index' and `rindex' are gone completely, many
+    OS-specific defines have been replaced with feature-test macros,
+    the use of alloca has been reduced, and other platform-specific fixes
+    (e.g. cray) have been made
+
+b.  The man page has been fixed up and brought up to date
+
+c.  Speed improvements: here documents, variable expansion, history
+    expansion, command substitution
+
+d.  If history is stifled, the history list replaces the history file at
+    exit
+
+e.  Asynchronous jobs re-run with fc -s now print the job number
+
+f.  Output redirections do not perform filename expansion in Posix.2 mode
+    when the shell is not interactive
+
+g.  operate_and_get_next now works on the most recent line even if the
+    history is unstifled
+
+h.  $PROMPT_COMMAND execution no longer causes recursive invocations
+    of yyparse()
+
+i.  An error message is printed if job control initialization fails
+
+j.  A command found in $PATH from the temporary environment is not hashed
+
+k.  Errors display the name of the script if the shell is not interactive
+
+l.  Fixed expression evaluation so blank expressions return 0
+
+m.  Fixed a bug that caused SIGINT and SIGQUIT not to be ignored in some
+    asynchronous children
+
+n.  Pipes used for /dev/fd process substitution are now closed on errors
+
+o.  Fixed /dev/null redirection so that ( list ) subshells inherit the
+    `stdin-has-been-redirected' flag as in sh
+
+p.  Process substitution now works only when unquoted
+
+q.  Fixed a bug where the async flag was added inappropriately in a command
+    like `a;b;c;d &'
+
+r.  Fixed off-by-one bug which caused negative history offsets in `fc' to
+    be wrong
+
+s.  Shell now remembers mail dates at startup on all systems
+
+t.  Posix systems without job control no longer create so many zombies
+
+u.  $ENV is now sourced by shells forked to execute scripts without a
+    leading `#!' line
+
+v.  Non-root users can now use the `unlimited' argument to ulimit and have
+    the resource value set to the hard limit
+
+w.  Made bash more sh-compatible by assigning the first argument after
+    `-c command' to $0
+
+x.  Fixed mail checking bug to note that *new* mail has arrived
+
+y.  Fixed off-by-one error in mailcheck.c:free_mail_files()
+
+z.  Fixed a bug where command strings passed to `bash -c' would be truncated
+    after executing the first disk command in the string
+
+aa. Fixed a bug which caused redirections passed to executable commands with
+    input or output pipes to be closed before the command was executed
+
+bb. Fixed a bug which caused bash to search for files supplied on the command
+    line in the $PATH if the initial open failed, even if the names contained
+    a slash
+
+cc. The initial argument parsing was fixed up so that other options can
+    be supplied with -c (that is, `sh -ec command' now works as make
+    intends), and so `bash -o' lists all the shell options at startup.
+
+dd. Error messages are consistently prefixed with the name of the shell
+    or shell script when non-interactive.
+
+ee. Fixed up a problem with the `read' builtin that occurred when more
+    variables than arguments were supplied.
+
+ff. Unset the variables passed to `read' as arguments when EOF is
+    read from stdin (sh, Posix.2 compatibility).
+
+gg. Fixes to the command printing code to make the output of `type'
+    available as legal shell input.
+
+ii. Fixes so that command completion is attempted after all of the shell
+    command separator characters.
+
+jj. Fixes to the shell completion code so that it handles quoted characters
+    and substrings better.
+
+kk. Bash no longer looks through $PATH for a shell script passed as an
+    argument if the name contains slashes.
+
+ll. Bash now checks that the `name' in a `name[=value]' argument to `declare'
+    (and thus `typeset', `export', and `readonly') is a legal shell variable
+    name.
+
+4.  Bugs fixed in Readline
+
+a.  The ^W and ^U bindings in non-incremental search mode have been changed
+    to be closer to what Posix specifies
+
+b.  Tries to initialize the keypad to enable the arrow keys
+
+c.  Multiple words are now killed and yanked in the right order
+
+d.  rl_read_init_file now reads filenames in a more regular order:  the last
+    one read, $INPUTRC, then ~/.inputrc
+
+e.  yank_nth_arg inserts a space in the right place in vi mode
+
+f.  Fixed a bug in the history library that tried to write to a file opened
+    O_RDONLY
+
+g.  Binding of `0' in vi command mode is now right
+
+h.  The VISIBLE_STATS completion listing code now follows symlinks
+
+i.  Memory allocated with alloca() is no longer passed to other functions
+
+j.  Error messages are now printed for unrecognized history modifiers
+
+k.  Fixed a problem with history library and `!#'; now it is more csh-like.
+
+l.  Fixed a csh incompatibility in the history library: now only an end of
+    line or `?' terminates a ?string history search string.
+
+m.  Fixed a problem with readline completion that sometimes caused possible
+    matches to be listed one per line when `show-all-if-ambiguous' was set.
+
+n.  Fixed a problem in the readline display code that caused divide-by-zero
+    errors.
+
+o.  Fixed an off-by-one error in the kill ring reallocation code.
diff --git a/alias.c b/alias.c
new file mode 100644 (file)
index 0000000..f9be0b4
--- /dev/null
+++ b/alias.c
@@ -0,0 +1,535 @@
+/* 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.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "bashansi.h"
+#include "config.h"
+#include "command.h"
+#include "general.h"
+#include "hash.h"
+#include "alias.h"
+
+static int qsort_alias_compare ();
+
+/* Non-zero means expand all words on the line.  Otherwise, expand
+   after first expansion if the expansion ends in a space. */
+int alias_expand_all = 0;
+
+/* The list of aliases that we have. */
+HASH_TABLE *aliases = (HASH_TABLE *)NULL;
+
+void
+initialize_aliases ()
+{
+  if (!aliases)
+    aliases = make_hash_table (0);
+}
+
+/* Scan the list of aliases looking for one with NAME.  Return NULL
+   if the alias doesn't exist, else a pointer to the assoc. */
+ASSOC *
+find_alias (name)
+     char *name;
+{
+  BUCKET_CONTENTS *al;
+
+  if (!aliases)
+    return ((ASSOC *)NULL);
+  else
+    al = find_hash_item (name, aliases);
+
+  if (al)
+    return ((ASSOC *)al->data);
+  else
+    return ((ASSOC *)NULL);
+}
+
+/* Return the value of the alias for NAME, or NULL if there is none. */
+char *
+get_alias_value (name)
+     char *name;
+{
+  ASSOC *alias = find_alias (name);
+  if (alias)
+    return (alias->value);
+  else
+    return ((char *)NULL);
+}
+
+/* Make a new alias from NAME and VALUE.  If NAME can be found,
+   then replace its value. */
+void
+add_alias (name, value)
+     char *name, *value;
+{
+  ASSOC *temp = (ASSOC *)NULL;
+
+  if (!aliases)
+    initialize_aliases ();
+  else
+    temp = find_alias (name);
+
+  if (temp)
+    {
+      free (temp->value);
+      temp->value = savestring (value);
+    }
+  else
+    {
+      BUCKET_CONTENTS *elt;
+
+      temp = (ASSOC *)xmalloc (sizeof (ASSOC));
+      temp->name = savestring (name);
+      temp->value = savestring (value);
+
+      elt = add_hash_item (savestring (name), aliases);
+      elt->data = (char *)temp;
+    }
+}
+
+/* Remove the alias with name NAME from the alias table.  Returns
+   the number of aliases left in the table, or -1 if the alias didn't
+   exist. */
+int
+remove_alias (name)
+     char *name;
+{
+  BUCKET_CONTENTS *elt;
+
+  if (!aliases)
+    return (-1);
+
+  elt = remove_hash_item (name, aliases);
+  if (elt)
+    {
+      ASSOC *t;
+
+      t = (ASSOC *)elt->data;
+      free (t->name);
+      free (t->value);
+      free (elt->key);         /* alias name */
+      free (t);
+
+      return (aliases->nentries);
+    }
+  return (-1);
+}
+
+/* Delete a hash bucket chain of aliases. */
+static void
+delete_alias_list (alias_list)
+     BUCKET_CONTENTS *alias_list;
+{
+  register BUCKET_CONTENTS *bp, *temp;
+  register ASSOC *a;
+
+  for (bp = alias_list; bp; )
+    {
+      temp = bp->next;
+      a = (ASSOC *)bp->data;
+      free (a->value);
+      free (a->name);
+      free (bp->data);
+      free (bp->key);
+      free (bp);
+      bp = temp;
+    }
+}
+
+/* Delete all aliases. */
+void
+delete_all_aliases ()
+{
+  register int i;
+
+  if (!aliases)
+    return;
+
+  for (i = 0; i < aliases->nbuckets; i++)
+    {
+      register BUCKET_CONTENTS *bp;
+
+      bp = get_hash_bucket (i, aliases);
+      delete_alias_list (bp);
+    }
+  free (aliases);
+  aliases = (HASH_TABLE *)NULL;
+}
+
+/* Return an array of aliases that satisfy the conditions tested by FUNCTION.
+   If FUNCTION is NULL, return all aliases. */
+static ASSOC **
+map_over_aliases (function)
+     Function *function;
+{
+  register int i;
+  register BUCKET_CONTENTS *tlist;
+  ASSOC *alias, **list = (ASSOC **)NULL;
+  int list_index = 0, list_size = 0;
+
+  for (i = 0; i < aliases->nbuckets; i++)
+    {
+      tlist = get_hash_bucket (i, aliases);
+
+      while (tlist)
+       {
+         alias = (ASSOC *)tlist->data;
+
+         if (!function || (*function) (alias))
+           {
+             if (list_index + 1 >= list_size)
+               list = (ASSOC **)
+                 xrealloc ((char *)list, (list_size += 20) * sizeof (ASSOC *));
+
+             list[list_index++] = alias;
+             list[list_index] = (ASSOC *)NULL;
+           }
+         tlist = tlist->next;
+       }
+    }
+  return (list);
+}
+
+static void
+sort_aliases (array)
+     ASSOC **array;
+{
+  qsort (array, array_len ((char **)array), sizeof (ASSOC *), qsort_alias_compare);
+}
+
+static int
+qsort_alias_compare (as1, as2)
+     ASSOC **as1, **as2;
+{
+  int result;
+  
+  if ((result = (*as1)->name[0] - (*as2)->name[0]) == 0)
+    result = strcmp ((*as1)->name, (*as2)->name);
+
+  return (result);
+}
+        
+/* Return a sorted list of all defined aliases */     
+ASSOC **
+all_aliases ()
+{
+  ASSOC **list;
+
+  if (!aliases)
+    return ((ASSOC **)NULL);
+
+  list = map_over_aliases ((Function *)NULL);
+  if (list)
+    sort_aliases (list);
+  return (list);
+}
+
+char *
+alias_expand_word (s)
+     char *s;
+{
+  ASSOC *r = find_alias (s);
+
+  if (r)
+    return (savestring (r->value));
+  else
+    return ((char *)NULL);
+}
+
+/* Return non-zero if CHARACTER is a member of the class of characters
+   that are self-delimiting in the shell (this really means that these
+   characters delimit tokens). */
+#define self_delimiting(character) (member ((character), " \t\n\r;|&()"))
+
+/* Return non-zero if CHARACTER is a member of the class of characters
+   that delimit commands in the shell. */
+#define command_separator(character) (member ((character), "\r\n;|&("))
+
+/* If this is 1, we are checking the next token read for alias expansion
+   because it is the first word in a command. */
+static int command_word;
+
+/* This is for skipping quoted strings in alias expansions. */
+#define quote_char(c)  (((c) == '\'') || ((c) == '"'))
+
+/* Consume a quoted string from STRING, starting at string[START] (so
+   string[START] is the opening quote character), and return the index
+   of the closing quote character matching the opening quote character.
+   This handles single matching pairs of unquoted quotes; it could afford
+   to be a little smarter... This skips words between balanced pairs of
+   quotes, words where the first character is quoted with a `\', and other
+   backslash-escaped characters. */
+
+static int
+skipquotes (string, start)
+     char *string;
+     int start;
+{
+  register int i;
+  int delimiter = string[start];
+
+  /* i starts at START + 1 because string[START] is the opening quote
+     character. */
+  for (i = start + 1 ; string[i] ; i++)
+    {
+      if (string[i] == '\\')
+       {
+         i++;          /* skip backslash-quoted quote characters, too */
+         continue;
+       }
+
+      if (string[i] == delimiter)
+       return i;
+    }
+  return (i);
+}
+
+/* Skip the white space and any quoted characters in STRING, starting at
+   START.  Return the new index into STRING, after zero or more characters
+   have been skipped. */
+static int
+skipws (string, start)
+     char *string;
+     int start;
+{
+  register int i = 0;
+  int pass_next, backslash_quoted_word, peekc;
+
+  /* skip quoted strings, in ' or ", and words in which a character is quoted
+     with a `\'. */
+  backslash_quoted_word = pass_next = 0;
+
+  /* Skip leading whitespace (or separator characters), and quoted words.
+     But save it in the output.  */
+
+  for (i = start; string[i]; i++)
+    {
+      if (pass_next)
+       {
+         pass_next = 0;
+         continue;
+       }
+
+      if (whitespace (string[i]))
+       {
+         backslash_quoted_word = 0; /* we are no longer in a backslash-quoted word */
+         continue;
+       }
+
+      if (string[i] == '\\')
+       {
+         peekc = string[i+1];
+         if (isletter (peekc))
+           backslash_quoted_word++;    /* this is a backslash-quoted word */
+         else
+           pass_next++;
+         continue;
+       }
+
+      /* This only handles single pairs of non-escaped quotes.  This
+        overloads backslash_quoted_word to also mean that a word like
+        ""f is being scanned, so that the quotes will inhibit any expansion
+        of the word. */
+      if (quote_char(string[i]))
+       {
+         i = skipquotes (string, i);
+         /* This could be a line that contains a single quote character,
+            in which case skipquotes () terminates with string[i] == '\0'
+            (the end of the string).  Check for that here. */
+         if (string[i] == '\0')
+           break;
+
+         peekc = string[i + 1];
+         if (isletter (peekc))
+           backslash_quoted_word++;
+         continue;
+       }
+
+      /* If we're in the middle of some kind of quoted word, let it
+        pass through. */
+      if (backslash_quoted_word)
+       continue;
+
+      /* If this character is a shell command separator, then set a hint for
+        alias_expand that the next token is the first word in a command. */
+
+      if (command_separator (string[i]))
+       {
+         command_word++;
+         continue;
+       }
+      break;
+    }
+  return (i);
+}
+
+/* Characters that may appear in a token.  Basically, anything except white
+   space and a token separator. */
+#define token_char(c)  (!((whitespace (string[i]) || self_delimiting (string[i]))))
+
+/* Read from START in STRING until the next separator character, and return
+   the index of that separator.  Skip backslash-quoted characters.  Call
+   skipquotes () for quoted strings in the middle or at the end of tokens,
+   so all characters show up (e.g. foo'' and foo""bar) */
+static int
+rd_token (string, start)
+     char *string; 
+     int start;
+{
+  register int i;
+
+  /* From here to next separator character is a token. */
+  for (i = start; string[i] && token_char (string[i]); i++)
+    {
+      if (string[i] == '\\')
+       {
+         i++;  /* skip backslash-escaped character */
+         continue;
+       }
+
+      /* If this character is a quote character, we want to call skipquotes
+        to get the whole quoted portion as part of this word.  That word
+        will not generally match an alias, even if te unquoted word would
+        have.  The presence of the quotes in the token serves then to 
+        inhibit expansion. */
+      if (quote_char (string[i]))
+       {
+         i = skipquotes (string, i);
+         /* Now string[i] is the matching quote character, and the
+            quoted portion of the token has been scanned. */
+         continue;
+       }
+    }
+  return (i);
+}
+
+/* Return a new line, with any aliases substituted. */
+char *
+alias_expand (string)
+     char *string;
+{
+  int line_len = 1 + strlen (string);
+  char *line = (char *)xmalloc (line_len);
+  register int i, j, start;
+  char *token = xmalloc (line_len);
+  int tl, real_start, expand_next, expand_this_token;
+  ASSOC *alias;
+
+  line[0] = i = 0;
+  expand_next = 0;
+  command_word = 1; /* initialized to expand the first word on the line */
+
+  /* Each time through the loop we find the next word in line.  If it
+     has an alias, substitute
+     the alias value.  If the value ends in ` ', then try again
+     with the next word.  Else, if there is no value, or if
+     the value does not end in space, we are done. */
+
+  for (;;)
+    {
+
+      token[0] = 0;
+      start = i;
+
+      /* Skip white space and quoted characters */
+      i = skipws (string, start);
+
+      if (start == i && string[i] == '\0')
+       {
+         free (token);
+         return (line);
+       }
+
+      /* copy the just-skipped characters into the output string,
+        expanding it if there is not enough room. */
+      j = strlen (line);
+      tl = i - start;  /* number of characters just skipped */
+      if (1 + j + tl >= line_len)
+       line = (char *)xrealloc (line, line_len += (50 + tl));
+      strncpy (line + j, string + start, tl);
+      line[j + tl] = '\0';
+
+      real_start = i;
+
+      command_word = command_word || (command_separator (string[i]));
+      expand_this_token = (command_word || expand_next);
+      expand_next = 0;
+
+      /* Read the next token, and copy it into TOKEN. */
+      start = i;
+      i = rd_token (string, start);
+
+      tl = i - start;  /* token length */
+
+      /* If tl == 0, but we're not at the end of the string, then we have a
+        single-character token, probably a delimiter */
+      if (tl == 0 && string[i] != '\0')
+       {
+         tl = 1;
+         i++;          /* move past it */
+       }
+
+      strncpy (token, string + start, tl);
+      token [tl] = '\0';
+
+      /* 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, '\\'))
+       expand_this_token = 0;
+
+      /* If we should be expanding here, if we are expanding all words, or if
+        we are in a location in the string where an expansion is supposed to
+        take place, see if this word has a substitution.  If it does, then do
+        the expansion.  Note that we defer the alias value lookup until we
+        are sure we are expanding this token. */
+
+      if ((token[0]) &&
+         (expand_this_token || alias_expand_all) &&
+         (alias = find_alias (token)))
+       {
+         char *v = alias->value;
+         int l = strlen (v);
+      
+         /* +3 because we possibly add one more character below. */
+         if ((l + 3) > line_len - (int)strlen (line))
+           line = (char *)xrealloc (line, line_len += (50 + l));
+
+         strcat (line, v);
+
+         if ((expand_this_token && l && whitespace (v[l - 1])) ||
+             alias_expand_all)
+           expand_next = 1;
+       }
+      else
+       {
+         int ll = strlen (line);
+         int tlen = i - real_start; /* tlen == strlen(token) */
+
+         if (ll + tlen + 2 > line_len)
+           line = (char *)xrealloc (line, line_len += 50 + ll + tlen);
+
+         strncpy (line + ll, string + real_start, tlen);
+         line[ll + tlen] = '\0';
+       }
+      command_word = 0;
+    }
+}
diff --git a/alias.h b/alias.h
new file mode 100644 (file)
index 0000000..2a2d184
--- /dev/null
+++ b/alias.h
@@ -0,0 +1,75 @@
+/* alias.h -- structure definitions. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_ALIAS_)
+#define _ALIAS_
+
+#include "hash.h"
+
+extern char *xmalloc ();
+
+#if !defined (whitespace)
+#  define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#endif /* !whitespace */
+
+#if !defined (savestring)
+#  define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x))
+#endif /* !savestring */
+
+#if !defined (NULL)
+#  if defined (__STDC__)
+#    define NULL ((void *) 0)
+#  else
+#    define NULL 0x0
+#  endif /* !__STDC__ */
+#endif /* !NULL */
+
+typedef struct {
+  char *name;
+  char *value;
+} ASSOC;
+
+/* The list of known aliases. */
+extern HASH_TABLE *aliases;
+
+extern void initialize_aliases ();
+
+/* Scan the list of aliases looking for one with NAME.  Return NULL
+   if the alias doesn't exist, else a pointer to the assoc. */
+extern ASSOC *find_alias ();
+
+/* Return the value of the alias for NAME, or NULL if there is none. */
+extern char *get_alias_value ();
+
+/* Make a new alias from NAME and VALUE.  If NAME can be found,
+   then replace its value. */
+extern void add_alias ();
+
+/* Remove the alias with name NAME from the alias list.  Returns
+   the index of the removed alias, or -1 if the alias didn't exist. */
+extern int remove_alias ();
+
+/* Return a new line, with any aliases expanded. */
+extern char *alias_expand ();
+
+/* Return an array of all defined aliases. */
+extern ASSOC **all_aliases ();
+
+#endif /* _ALIAS_ */
diff --git a/ansi_stdlib.h b/ansi_stdlib.h
new file mode 100644 (file)
index 0000000..52339da
--- /dev/null
@@ -0,0 +1,41 @@
+/* ansi_stdlib.h -- An ANSI Standard stdlib.h. */
+/* A minimal stdlib.h containing extern declarations for those functions
+   that bash uses. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_STDLIB_H_)
+#define        _STDLIB_H_ 1
+
+/* String conversion functions. */
+extern int atoi ();
+extern long int atol ();
+
+/* Memory allocation functions. */
+extern char *malloc ();
+extern char *realloc ();
+extern void free ();
+
+/* Other miscellaneous functions. */
+extern void abort ();
+extern void exit ();
+extern char *getenv ();
+extern void qsort ();
+
+#endif /* _STDLIB_H  */
diff --git a/bashansi.h b/bashansi.h
new file mode 100644 (file)
index 0000000..4411970
--- /dev/null
@@ -0,0 +1,36 @@
+/* bashansi.h -- Typically included information required by picky compilers. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_BASHANSI_H_)
+#define _BASHANSI_H_
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* !HAVE_STDLIB_H */
+
+#endif /* !_BASHANSI_H_ */
diff --git a/bashhist.c b/bashhist.c
new file mode 100644 (file)
index 0000000..cd7134b
--- /dev/null
@@ -0,0 +1,390 @@
+/* bashhist.c -- bash interface to the GNU history library. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <errno.h>
+#include "bashansi.h"
+#include "posixstat.h"
+#include "filecntl.h"
+#include "shell.h"
+#include "flags.h"
+#include <readline/history.h>
+
+/* Declarations of bash history variables. */
+/* Non-zero means to remember lines typed to the shell on the history
+   list.  This is different than the user-controlled behaviour; this
+   becomes zero when we read lines from a file, for example. */
+int remember_on_history = 1;
+
+/* The number of lines that Bash has added to this history session. */
+int history_lines_this_session = 0;
+
+/* The number of lines that Bash has read from the history file. */
+int history_lines_in_file = 0;
+
+/* Non-zero means do no history expansion on this line, regardless
+   of what history_expansion says. */
+int history_expansion_inhibited = 0;
+
+/* By default, every line is saved in the history individually.  I.e.,
+   if the user enters:
+       bash$ for i in a b c
+        > do
+        > echo $i
+        > done
+   Each line will be individually saved in the history.
+       bash$ history
+       10  for i in a b c
+        11  do
+        12  echo $i
+        13  done
+        14  history
+   If the variable command_oriented_history is set, multiple lines
+   which form one command will be saved as one history entry.
+       bash$ for i in a b c
+        > do
+        > echo $i
+        > done
+        bash$ history
+       10  for i in a b c
+    do
+    echo $i
+    done
+        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.
+   */
+int command_oriented_history = 0;
+
+/* A nit for picking at history saving.
+   Value of 0 means save all lines parsed by the shell on the history.
+   Value of 1 means save all lines that do not start with a space.
+   Value of 2 means save all lines that do not match the last line saved. */
+int history_control = 0;
+
+/* Variables declared in other files used here. */
+extern int interactive;
+extern int current_command_line_count;
+extern int delimiter_depth;
+
+extern char *history_delimiting_chars ();
+extern void maybe_add_history ();      /* forward declaration */
+
+static void bash_add_history ();
+
+/* Load the history list from the history file. */
+void
+load_history ()
+{
+  char *hf;
+
+  /* Truncate history file for interactive shells which desire it.
+     Note that the history file is automatically truncated to the
+     size of HISTSIZE if the user does not explicitly set the size
+     differently. */
+  set_if_not ("HISTFILESIZE", get_string_value ("HISTSIZE"));
+  stupidly_hack_special_variables ("HISTFILESIZE");
+
+  /* Read the history in HISTFILE into the history list. */
+  hf = get_string_value ("HISTFILE");
+
+  if (hf && *hf)
+    {
+      struct stat buf;
+
+      if (stat (hf, &buf) == 0)
+       {
+         read_history (hf);
+         using_history ();
+         history_lines_in_file = where_history ();
+       }
+    }
+}
+
+/* Write the existing history out to the history file. */
+void
+save_history ()
+{
+  char *hf = get_string_value ("HISTFILE");
+
+  if (hf && *hf)
+    {
+      struct stat buf;
+
+      if (stat (hf, &buf) == 0)
+       {
+         /* Append only the lines that occurred this session to
+            the history file. */
+         using_history ();
+
+         if (history_lines_this_session < where_history ())
+           append_history (history_lines_this_session, hf);
+         else
+           write_history (hf);
+       }
+    }
+}
+
+/* If this is an interactive shell, then append the lines executed
+   this session to the history file. */
+int
+maybe_save_shell_history ()
+{
+  int result = 0;
+
+  if (history_lines_this_session)
+    {
+      char *hf = get_string_value ("HISTFILE");
+
+      if (hf && *hf)
+       {
+         struct stat buf;
+
+         /* If the file doesn't exist, then create it. */
+         if (stat (hf, &buf) == -1)
+           {
+             int file = open (hf, O_CREAT | O_TRUNC | O_WRONLY, 0666);
+             if (file != -1)
+               close (file);
+           }
+
+         /* Now actually append the lines if the history hasn't been
+            stifled.  If the history has been stifled, rewrite the
+            history file. */
+         using_history ();
+         if (history_lines_this_session <= where_history ())
+           {
+             result = append_history (history_lines_this_session, hf);
+             history_lines_in_file += history_lines_this_session;
+           }
+         else
+           {
+             result = write_history (hf);
+             history_lines_in_file = history_lines_this_session;
+           }
+         history_lines_this_session = 0;
+       }
+    }
+  return (result);
+}
+
+#if defined (HISTORY_REEDITING)
+/* Tell readline () that we have some text for it to edit. */
+static void
+re_edit (text)
+     char *text;
+{
+#if defined (READLINE)
+  if (strcmp (bash_input.name, "readline stdin") == 0)
+    bash_re_edit (text);
+#endif /* READLINE */
+}
+#endif /* HISTORY_REEDITING */
+
+/* Do pre-processing on LINE.  If PRINT_CHANGES is non-zero, then
+   print the results of expanding the line if there were any changes.
+   If there is an error, return NULL, otherwise the expanded line is
+   returned.  If ADDIT is non-zero the line is added to the history
+   list after history expansion.  ADDIT is just a suggestion;
+   REMEMBER_ON_HISTORY can veto, and does.
+   Right now this does history expansion. */
+char *
+pre_process_line (line, print_changes, addit)
+     char *line;
+     int print_changes, addit;
+{
+  char *history_value;
+  char *return_value;
+  int expanded = 0;
+
+  return_value = line;
+
+#  if defined (BANG_HISTORY)
+  /* History expand the line.  If this results in no errors, then
+     add that line to the history if ADDIT is non-zero. */
+  if (!history_expansion_inhibited && history_expansion)
+    {
+      expanded = history_expand (line, &history_value);
+
+      if (expanded)
+       {
+         if (print_changes)
+           {
+             if (expanded < 0)
+               internal_error (history_value);
+             else
+               fprintf (stderr, "%s\n", history_value);
+           }
+
+         /* If there was an error, return NULL. */
+         if (expanded < 0 || expanded == 2)    /* 2 == print only */
+           {
+             free (history_value);
+
+#    if defined (HISTORY_REEDITING)
+             /* New hack.  We can allow the user to edit the
+                failed history expansion. */
+             re_edit (line);
+#    endif /* HISTORY_REEDITING */
+             return ((char *)NULL);
+           }
+       }
+
+      /* Let other expansions know that return_value can be free'ed,
+        and that a line has been added to the history list.  Note
+        that we only add lines that have something in them. */
+      expanded = 1;
+      return_value = history_value;
+    }
+#  endif /* BANG_HISTORY */
+
+  if (addit && remember_on_history && *return_value)
+    maybe_add_history (return_value);
+
+  if (!expanded)
+    return_value = savestring (line);
+
+  return (return_value);
+}
+
+/* Add LINE to the history list depending on the value of HISTORY_CONTROL. */
+void
+maybe_add_history (line)
+     char *line;
+{
+  int h;
+
+  /* Don't use the value of history_control to affect the second
+     and subsequent lines of a multi-line command when
+     command_oriented_history is enabled. */
+  if (command_oriented_history && current_command_line_count > 1)
+    h = 0;
+  else
+    h = history_control;
+
+  switch (h)
+    {
+    case 0:
+      bash_add_history (line);
+      break;
+    case 1:
+      if (*line != ' ')
+        bash_add_history (line);
+      break;
+    case 3:
+      if (*line == ' ')
+        break;
+      /* FALLTHROUGH if case == 3 (`ignoreboth') */
+    case 2:
+      {
+       HIST_ENTRY *temp;
+
+       using_history ();
+       temp = previous_history ();
+
+       if (!temp || (STREQ (temp->line, line) == 0))
+         bash_add_history (line);
+
+       using_history ();
+      }
+      break;
+    }
+}
+
+/* Add a line to the history list.
+   The variable COMMAND_ORIENTED_HISTORY controls the style of history
+   remembering;  when non-zero, and LINE is not the first line of a
+   complete parser construct, append LINE to the last history line instead
+   of adding it as a new line. */
+static void
+bash_add_history (line)
+     char *line;
+{
+  int add_it = 1;
+
+  if (command_oriented_history && current_command_line_count > 1)
+    {
+      register int offset;
+      register HIST_ENTRY *current, *old;
+      char *chars_to_add, *new_line;
+
+      chars_to_add = history_delimiting_chars ();
+
+      using_history ();
+
+      current = previous_history ();
+
+      if (current)
+       {
+         /* If the previous line ended with an escaped newline (escaped
+            with backslash, but otherwise unquoted), then remove the quoted
+            newline, since that is what happens when the line is parsed. */
+         int curlen;
+
+         curlen = strlen (current->line);
+
+         if (!delimiter_depth && current->line[curlen - 1] == '\\' &&
+             current->line[curlen - 2] != '\\')
+           {
+             current->line[curlen - 1] = '\0';
+             curlen--;
+             chars_to_add = "";
+           }
+
+         offset = where_history ();
+         new_line = (char *) xmalloc (1
+                                      + curlen
+                                      + strlen (line)
+                                      + strlen (chars_to_add));
+         sprintf (new_line, "%s%s%s", current->line, chars_to_add, line);
+         old = replace_history_entry (offset, new_line, current->data);
+         free (new_line);
+
+         if (old)
+           {
+             /* Note that the old data is not freed, since it was simply
+                copied to the new history entry. */
+             if (old->line)
+               free (old->line);
+
+             free (old);
+           }
+         add_it = 0;
+       }
+    }
+
+  if (add_it)
+    {
+      add_history (line);
+      history_lines_this_session++;
+    }
+  using_history ();
+}
+
+int
+history_number ()
+{
+  using_history ();
+  if (get_string_value ("HISTSIZE"))
+    return (history_base + where_history ());
+  else
+    return (1);                /* default to command number 1 */
+}
diff --git a/bashhist.h b/bashhist.h
new file mode 100644 (file)
index 0000000..c1c24fc
--- /dev/null
@@ -0,0 +1,42 @@
+/* bashhist.h -- interface to the bash history functions in bashhist.c. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (__BASHHIST_H__)
+#define __BASHHIST_H__
+
+extern int remember_on_history;
+extern int history_lines_this_session;
+extern int history_lines_in_file;
+extern int history_expansion;
+extern int history_control;
+extern int command_oriented_history;
+
+#  if defined (BANG_HISTORY)
+extern int history_expansion_inhibited;
+#  endif /* BANG_HISTORY */
+
+extern void load_history ();
+extern void save_history ();
+extern int maybe_save_shell_history ();
+extern char *pre_process_line ();
+extern int history_number ();
+extern void maybe_add_history ();
+
+#endif /* __BASHHIST_H__ */
diff --git a/bashline.c b/bashline.c
new file mode 100644 (file)
index 0000000..a924b05
--- /dev/null
@@ -0,0 +1,1797 @@
+/* bashline.c -- Bash's interface to the readline library. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "bashtypes.h"
+#include "posixstat.h"
+
+#include <stdio.h>
+#include "bashansi.h"
+#include <readline/rlconf.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+#include "shell.h"
+#include "builtins.h"
+#include "builtins/common.h"
+#include "bashhist.h"
+#include "execute_cmd.h"
+
+#if defined (ALIAS)
+#  include "alias.h"
+#endif
+
+#if defined (BRACE_EXPANSION)
+#  define BRACE_COMPLETION
+#endif /* BRACE_EXPANSION */
+
+#if defined (BRACE_COMPLETION)
+extern void bash_brace_completion ();
+#endif /* BRACE_COMPLETION */
+
+/* Functions bound to keys in Readline for Bash users. */
+static void shell_expand_line ();
+static void display_shell_version (), operate_and_get_next ();
+static void history_expand_line (), bash_ignore_filenames ();
+
+/* Helper functions for Readline. */
+static int bash_directory_completion_hook ();
+static void filename_completion_ignore ();
+static void bash_push_line ();
+
+static char **attempt_shell_completion ();
+static char *variable_completion_function ();
+static char *hostname_completion_function ();
+static char *command_word_completion_function ();
+static char *command_subst_completion_function ();
+
+static void snarf_hosts_from_file (), add_host_name ();
+static void sort_hostname_list ();
+
+#define DYNAMIC_HISTORY_COMPLETION
+#if defined (DYNAMIC_HISTORY_COMPLETION)
+static void dynamic_complete_history ();
+#endif /* DYNAMIC_HISTORY_COMPLETION */
+
+/* Variables used here but defined in other files. */
+extern int posixly_correct, no_symbolic_links;
+extern int rl_explicit_arg;
+extern char *current_prompt_string, *ps1_prompt;
+extern STRING_INT_ALIST word_token_alist[];
+extern Function *rl_last_func;
+extern int rl_filename_completion_desired;
+
+/* SPECIFIC_COMPLETION_FUNCTIONS specifies that we have individual
+   completion functions which indicate what type of completion should be
+   done (at or before point) that can be bound to key sequences with
+   the readline library. */
+#define SPECIFIC_COMPLETION_FUNCTIONS
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+static void
+  bash_specific_completion (),
+  bash_complete_filename (), bash_possible_filename_completions (),
+  bash_complete_filename_internal (),
+  bash_complete_username (), bash_possible_username_completions (),
+  bash_complete_username_internal (),
+  bash_complete_hostname (), bash_possible_hostname_completions (),
+  bash_complete_hostname_internal (),
+  bash_complete_variable (), bash_possible_variable_completions (),
+  bash_complete_variable_internal (),
+  bash_complete_command (), bash_possible_command_completions (),
+  bash_complete_command_internal ();
+#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
+
+/* Non-zero once initalize_readline () has been called. */
+int bash_readline_initialized = 0;
+
+#if defined (VI_MODE)
+static void vi_edit_and_execute_command ();
+extern char *rl_vi_comment_begin;
+#endif
+
+static Function *old_rl_startup_hook = (Function *) NULL;
+
+/* Change the readline VI-mode keymaps into or out of Posix.2 compliance.
+   Called when the shell is put into or out of `posix' mode. */
+void
+posix_readline_initialize (on_or_off)
+     int on_or_off;
+{
+#if defined (VI_MODE)
+  if (on_or_off)
+    {
+      rl_bind_key_in_map (CTRL('I'), rl_insert, vi_insertion_keymap);
+      if (rl_vi_comment_begin)
+       free (rl_vi_comment_begin);
+      rl_vi_comment_begin = savestring ("#");
+    }
+  else
+    rl_bind_key_in_map (CTRL('I'), rl_complete, vi_insertion_keymap);
+#endif
+} 
+
+/* Called once from parse.y if we are going to use readline. */
+void
+initialize_readline ()
+{
+  if (bash_readline_initialized)
+    return;
+
+  rl_terminal_name = get_string_value ("TERM");
+  rl_instream = stdin;
+  rl_outstream = stderr;
+  rl_special_prefixes = "$@";
+
+  /* Allow conditional parsing of the ~/.inputrc file. */
+  rl_readline_name = "Bash";
+
+  /* Bind up our special shell functions. */
+  rl_add_defun ("shell-expand-line", (Function *)shell_expand_line, -1);
+  rl_bind_key_in_map
+    (CTRL('E'), (Function *)shell_expand_line, emacs_meta_keymap);
+
+  /* Bind up our special shell functions. */
+  rl_add_defun ("history-expand-line", (Function *)history_expand_line, -1);
+  rl_bind_key_in_map ('^', (Function *)history_expand_line, emacs_meta_keymap);
+
+  /* Backwards compatibility. */
+  rl_add_defun ("insert-last-argument", rl_yank_last_arg, -1);
+
+  rl_add_defun
+    ("operate-and-get-next", (Function *)operate_and_get_next, CTRL('O'));
+
+  rl_add_defun
+    ("display-shell-version", (Function *)display_shell_version, -1);
+
+  rl_bind_key_in_map
+    (CTRL ('V'), (Function *)display_shell_version, emacs_ctlx_keymap);
+
+  /* In Bash, the user can switch editing modes with "set -o [vi emacs]",
+     so it is not necessary to allow C-M-j for context switching.  Turn
+     off this occasionally confusing behaviour. */
+  rl_unbind_key_in_map (CTRL('J'), emacs_meta_keymap);
+  rl_unbind_key_in_map (CTRL('M'), emacs_meta_keymap);
+#if defined (VI_MODE)
+  rl_unbind_key_in_map (CTRL('E'), vi_movement_keymap);
+#endif
+  
+#if defined (BRACE_COMPLETION)
+  rl_add_defun ("complete-into-braces", bash_brace_completion, -1);
+  rl_bind_key_in_map ('{', bash_brace_completion, emacs_meta_keymap);
+#endif /* BRACE_COMPLETION */
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+  rl_add_defun ("complete-filename", bash_complete_filename, -1);
+  rl_bind_key_in_map ('/', bash_complete_filename, emacs_meta_keymap);
+  rl_add_defun ("possible-filename-completions",
+               bash_possible_filename_completions, -1);
+  rl_bind_key_in_map ('/', bash_possible_filename_completions,
+                     emacs_ctlx_keymap);
+
+  rl_add_defun ("complete-username", bash_complete_username, -1);
+  rl_bind_key_in_map ('~', bash_complete_username, emacs_meta_keymap);
+  rl_add_defun ("possible-username-completions",
+               bash_possible_username_completions, -1);
+  rl_bind_key_in_map ('~', bash_possible_username_completions,
+                     emacs_ctlx_keymap);
+
+  rl_add_defun ("complete-hostname", bash_complete_hostname, -1);
+  rl_bind_key_in_map ('@', bash_complete_hostname, emacs_meta_keymap);
+  rl_add_defun ("possible-hostname-completions",
+               bash_possible_hostname_completions, -1);
+  rl_bind_key_in_map ('@', bash_possible_hostname_completions,
+                     emacs_ctlx_keymap);
+
+  rl_add_defun ("complete-variable", bash_complete_variable, -1);
+  rl_bind_key_in_map ('$', bash_complete_variable, emacs_meta_keymap);
+  rl_add_defun ("possible-variable-completions",
+               bash_possible_variable_completions, -1);
+  rl_bind_key_in_map ('$', bash_possible_variable_completions,
+                     emacs_ctlx_keymap);
+
+  rl_add_defun ("complete-command", bash_complete_command, -1);
+  rl_bind_key_in_map ('!', bash_complete_command, emacs_meta_keymap);
+  rl_add_defun ("possible-command-completions",
+               bash_possible_command_completions, -1);
+  rl_bind_key_in_map ('!', bash_possible_command_completions,
+                     emacs_ctlx_keymap);
+
+#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
+
+#if defined (DYNAMIC_HISTORY_COMPLETION)
+  rl_add_defun ("dynamic-complete-history", dynamic_complete_history, -1);
+  rl_bind_key_in_map (TAB, dynamic_complete_history, emacs_meta_keymap);
+#endif /* DYNAMIC_HISTORY_COMPLETION */
+
+  /* Tell the completer that we want a crack first. */
+  rl_attempted_completion_function = (CPPFunction *)attempt_shell_completion;
+
+  /* Tell the completer that we might want to follow symbolic links or
+     do other expansion on directory names. */
+  rl_directory_completion_hook = bash_directory_completion_hook;
+
+  /* Tell the filename completer we want a chance to ignore some names. */
+  rl_ignore_some_completions_function = (Function *)filename_completion_ignore;
+
+#if defined (VI_MODE)
+  rl_bind_key_in_map ('v', vi_edit_and_execute_command, vi_movement_keymap);
+#endif
+
+  rl_completer_quote_characters = "'\"";
+  /* Need to modify this from the default; `$', `{', `\', and ``' are not
+     word break characters. */
+  rl_completer_word_break_characters = " \t\n\"'@><=;|&("; /**/
+
+  if (posixly_correct)
+    posix_readline_initialize (1);
+
+  bash_readline_initialized = 1;
+}
+
+/* On Sun systems at least, rl_attempted_completion_function can end up
+   getting set to NULL, and rl_completion_entry_function set to do command
+   word completion if Bash is interrupted while trying to complete a command
+   word.  This just resets all the completion functions to the right thing.
+   It's called from throw_to_top_level(). */
+void
+bashline_reinitialize ()
+{
+  tilde_initialize ();
+  rl_attempted_completion_function = attempt_shell_completion;
+  rl_completion_entry_function = (Function *)NULL;
+  rl_directory_completion_hook = bash_directory_completion_hook;
+  rl_ignore_some_completions_function = (Function *)filename_completion_ignore;
+}
+
+/* Contains the line to push into readline. */
+static char *push_to_readline = (char *)NULL;
+
+/* Push the contents of push_to_readline into the
+   readline buffer. */
+static void
+bash_push_line ()
+{
+  if (push_to_readline)
+    {
+      rl_insert_text (push_to_readline);
+      free (push_to_readline);
+      push_to_readline = (char *)NULL;
+      rl_startup_hook = old_rl_startup_hook;
+    }
+}
+
+/* Call this to set the initial text for the next line to read
+   from readline. */
+int
+bash_re_edit (line)
+     char *line;
+{
+  if (push_to_readline)
+    free (push_to_readline);
+
+  push_to_readline = savestring (line);
+  old_rl_startup_hook = rl_startup_hook;
+  rl_startup_hook = (Function *)bash_push_line;
+
+  return (0);
+}
+
+static void
+display_shell_version (count, c)
+     int count, c;
+{
+  crlf ();
+  show_shell_version ();
+  putc ('\r', rl_outstream);
+  fflush (rl_outstream);
+  rl_on_new_line ();
+  rl_redisplay ();
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                          Readline Stuff                         */
+/*                                                                 */
+/* **************************************************************** */
+
+/* If the user requests hostname completion, then simply build a list
+   of hosts, and complete from that forever more. */
+#if !defined (ETCHOSTS)
+#define ETCHOSTS "/etc/hosts"
+#endif
+
+/* The kept list of hostnames. */
+static char **hostname_list = (char **)NULL;
+
+/* The physical size of the above list. */
+static int hostname_list_size = 0;
+
+/* The length of the above list. */
+static int hostname_list_length = 0;
+
+/* Whether or not HOSTNAME_LIST has been initialized. */
+int hostname_list_initialized = 0;
+
+/* Non-zero means that HOSTNAME_LIST needs to be sorted. */
+static int hostname_list_needs_sorting = 0;
+
+/* Initialize the hostname completion table. */
+static void
+initialize_hostname_list ()
+{
+  char *temp;
+
+  temp = get_string_value ("HOSTFILE");
+  if (!temp)
+    temp = get_string_value ("hostname_completion_file");
+  if (!temp)
+    temp = ETCHOSTS;
+
+  snarf_hosts_from_file (temp);
+  sort_hostname_list ();
+
+  if (hostname_list)
+    hostname_list_initialized++;
+}
+
+/* Add NAME to the list of hosts. */
+static void
+add_host_name (name)
+     char *name;
+{
+  if (hostname_list_length + 2 > hostname_list_size)
+    {
+      hostname_list = (char **)
+       xrealloc (hostname_list,
+                 (1 + (hostname_list_size += 100)) * sizeof (char *));
+    }
+
+  hostname_list[hostname_list_length] = savestring (name);
+  hostname_list[++hostname_list_length] = (char *)NULL;
+  hostname_list_needs_sorting++;
+}
+
+/* After you have added some names, you should sort the list of names. */
+static void
+sort_hostname_list ()
+{
+  if (hostname_list_needs_sorting && hostname_list)
+    sort_char_array (hostname_list);
+  hostname_list_needs_sorting = 0;
+}
+
+#define cr_whitespace(c) ((c) == '\r' || (c) == '\n' || whitespace(c))
+
+static void
+snarf_hosts_from_file (filename)
+     char *filename;
+{
+  FILE *file = fopen (filename, "r");
+  char *temp, buffer[256], name[256];
+  register int i, start;
+
+  if (!file)
+    return;
+
+  while (temp = fgets (buffer, 255, file))
+    {
+      /* Skip to first character. */
+      for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++);
+
+      /* If comment, ignore. */
+      if (buffer[i] == '#')
+       continue;
+
+      /* If `preprocessor' directive, do the include. */
+      if (strncmp (&buffer[i], "$include ", 9) == 0)
+       {
+         char *includefile = &buffer[i + 9];
+         char *t;
+
+         /* Find start of filename. */
+         while (*includefile && whitespace (*includefile))
+           includefile++;
+
+         t = includefile;
+
+         /* Find end of filename. */
+         while (*t && !cr_whitespace (*t))
+           t++;
+
+         *t = '\0';
+
+         snarf_hosts_from_file (includefile);
+         continue;
+       }
+
+      /* Skip internet address. */
+      for (; buffer[i] && !cr_whitespace (buffer[i]); i++);
+
+      /* Gobble up names.  Each name is separated with whitespace. */
+      while (buffer[i] && buffer[i] != '#')
+       {
+         for (; i && cr_whitespace (buffer[i]); i++);
+         if (buffer[i] ==  '#')
+           continue;
+         for (start = i; buffer[i] && !cr_whitespace (buffer[i]); i++);
+         if ((i - start) == 0)
+           continue;
+         strncpy (name, buffer + start, i - start);
+         name[i - start] = '\0';
+         add_host_name (name);
+       }
+    }
+  fclose (file);
+}
+
+/* Return a NULL terminated list of hostnames which begin with TEXT.
+   Initialize the hostname list the first time if neccessary.
+   The array is malloc ()'ed, but not the individual strings. */
+static char **
+hostnames_matching (text)
+     char *text;
+{
+  register int i, len = strlen (text);
+  register int begin, end;
+  int last_search = -1;
+  char **result = (char **)NULL;
+
+  if (!hostname_list_initialized)
+    {
+      initialize_hostname_list ();
+
+      if (!hostname_list_initialized)
+       return ((char **)NULL);
+    }
+
+  sort_hostname_list ();
+
+  /* The list is sorted.  Do a binary search on it for the first character
+     in TEXT, and then grovel the names of interest. */
+  begin = 0; end = hostname_list_length;
+
+  /* Special case.  If TEXT consists of nothing, then the whole list is
+     what is desired. */
+  if (!*text)
+    {
+      result = (char **)xmalloc ((1 + hostname_list_length) * sizeof (char *));
+      for (i = 0; i < hostname_list_length; i++)
+       result[i] = hostname_list[i];
+      result[i] = (char *)NULL;
+      return (result);
+    }
+
+  /* Scan until found, or failure. */
+  while (end != begin)
+    {
+      int r = 0;
+
+      i = ((end - begin) / 2) + begin;
+      if (i == last_search)
+       break;
+
+      if (hostname_list[i] &&
+         (r = strncmp (hostname_list[i], text, len)) == 0)
+       {
+         while (strncmp (hostname_list[i], text, len) == 0 && i) i--;
+         if (strncmp (hostname_list[i], text, len) != 0) i++;
+
+         begin = i;
+         while (hostname_list[i] &&
+                strncmp (hostname_list[i], text, len) == 0) i++;
+         end = i;
+
+         result = (char **)xmalloc ((1 + (end - begin)) * sizeof (char *));
+         for (i = 0; i + begin < end; i++)
+           result[i] = hostname_list[begin + i];
+         result[i] = (char *)NULL;
+         return (result);
+       }
+
+      last_search = i;
+
+      if (r < 0)
+       begin = i;
+      else
+       end = i;
+    }
+  return ((char **)NULL);
+}
+
+/* The equivalent of the K*rn shell C-o operate-and-get-next-history-line
+   editing command. */
+static int saved_history_line_to_use = 0;
+
+static void
+set_saved_history ()
+{
+  if (saved_history_line_to_use)
+    rl_get_previous_history (history_length - saved_history_line_to_use);
+  saved_history_line_to_use = 0;
+  rl_startup_hook = old_rl_startup_hook;
+}  
+
+static void
+operate_and_get_next (count, c)
+     int count, c;
+{
+  int where;
+
+  /* Accept the current line. */
+  rl_newline ();       
+
+  /* Find the current line, and find the next line to use. */
+  where = where_history ();
+
+  if ((history_is_stifled () && (history_length >= max_input_history)) ||
+      (where >= history_length - 1))
+    saved_history_line_to_use = where;
+  else
+    saved_history_line_to_use = where + 1;
+
+  old_rl_startup_hook = rl_startup_hook;
+  rl_startup_hook = (Function *)set_saved_history;
+}
+
+#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}}"
+
+static void
+vi_edit_and_execute_command (count, c)
+{
+  char *command;
+
+  /* Accept the current line. */
+  rl_newline ();       
+
+  if (rl_explicit_arg)
+    {
+      command = xmalloc (strlen (VI_EDIT_COMMAND) + 8);
+      sprintf (command, "%s %d", VI_EDIT_COMMAND, count);
+    }
+  else
+    {
+      /* Take the command we were just editing, add it to the history file,
+        then call fc to operate on it.  We have to add a dummy command to
+        the end of the history because fc ignores the last command (assumes
+        it's supposed to deal with the command before the `fc'). */
+      using_history ();
+      add_history (rl_line_buffer);
+      add_history ("");
+      history_lines_this_session++;
+      using_history ();
+      command = savestring (VI_EDIT_COMMAND);
+    }
+  parse_and_execute (command, "v", -1);
+  rl_line_buffer[0] = '\0';    /* erase pre-edited command */
+}
+#endif /* VI_MODE */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     How To Do Shell Completion                  */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Do some completion on TEXT.  The indices of TEXT in RL_LINE_BUFFER are
+   at START and END.  Return an array of matches, or NULL if none. */
+static char **
+attempt_shell_completion (text, start, end)
+     char *text;
+     int start, end;
+{
+  int in_command_position, ti;
+  char **matches = (char **)NULL;
+  char *command_separator_chars = ";|&{(`";
+
+  rl_ignore_some_completions_function =
+    (Function *)filename_completion_ignore;
+
+  /* Determine if this could be a command word.  It is if it appears at
+     the start of the line (ignoring preceding whitespace), or if it
+     appears after a character that separates commands.  It cannot be a
+     command word if we aren't at the top-level prompt. */
+  ti = start - 1;
+
+  while ((ti > -1) && (whitespace (rl_line_buffer[ti])))
+    ti--;
+
+  in_command_position = 0;
+  if (ti < 0)
+    {
+      /* Only do command completion at the start of a line when we
+         are prompting at the top level. */
+      if (current_prompt_string == ps1_prompt)
+       in_command_position++;
+    }
+  else if (member (rl_line_buffer[ti], command_separator_chars))
+    {
+      register int this_char, prev_char;
+
+      in_command_position++;
+
+      /* Handle the two character tokens `>&', `<&', and `>|'.
+         We are not in a command position after one of these. */
+      this_char = rl_line_buffer[ti];
+      prev_char = rl_line_buffer[ti - 1];
+
+      if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
+         (this_char == '|' && prev_char == '>'))
+       in_command_position = 0;
+      else if (char_is_quoted (rl_line_buffer, ti))
+       in_command_position = 0;
+    }
+  else
+    {
+      /* This still could be in command position.  It is possible
+        that all of the previous words on the line are variable
+        assignments. */
+    }
+
+  /* Special handling for command substitution.  XXX - this should handle
+     `$(' as well. */
+  if (*text == '`' && unclosed_pair (rl_line_buffer, start, "`"))
+    matches = completion_matches (text, command_subst_completion_function);
+
+  /* Variable name? */
+  if (!matches && *text == '$')
+    matches = completion_matches (text, variable_completion_function);
+
+  /* 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, '/'))
+    matches = completion_matches (text, username_completion_function);
+
+  /* Another one.  Why not?  If the word starts in '@', then look through
+     the world of known hostnames for completion first. */
+  if (!matches && *text == '@')
+    matches = completion_matches (text, hostname_completion_function);
+
+  /* And last, (but not least) if this word is in a command position, then
+     complete over possible command names, including aliases, functions,
+     and command names. */
+  if (!matches && in_command_position)
+    {
+      matches = completion_matches (text, command_word_completion_function);
+      /* If we are attempting command completion and nothing matches, we
+        do not want readline to perform filename completion for us.  We
+        still want to be able to complete partial pathnames, so set the
+        completion ignore function to something which will remove filenames
+        and leave directories in the match list. */
+      if (!matches)
+       rl_ignore_some_completions_function = (Function *)bash_ignore_filenames;
+    }
+
+  return (matches);
+}
+
+/* This is the function to call when the word to complete is in a position
+   where a command word can be found.  It grovels $PATH, looking for commands
+   that match.  It also scans aliases, function names, and the shell_builtin
+   table. */
+static char *
+command_word_completion_function (hint_text, state)
+     char *hint_text;
+     int state;
+{
+  static char *hint = (char *)NULL;
+  static char *path = (char *)NULL;
+  static char *val = (char *)NULL;
+  static char *filename_hint = (char *)NULL;
+  static int path_index, hint_len, istate;
+  static int mapping_over, local_index;
+  static SHELL_VAR **varlist = (SHELL_VAR **)NULL;
+#if defined (ALIAS)
+  static ASSOC **alias_list = (ASSOC **)NULL;
+#endif /* ALIAS */
+
+  /* We have to map over the possibilities for command words.  If we have
+     no state, then make one just for that purpose. */
+
+  if (!state)
+    {
+      if (hint)
+       free (hint);
+
+      mapping_over = 0;
+      val = (char *)NULL;
+
+      /* If this is an absolute program name, do not check it against
+        aliases, reserved words, functions or builtins.  We must check
+        whether or not it is unique, and, if so, whether that filename
+        is executable. */
+      if (absolute_program (hint_text))
+       {
+         /* Perform tilde expansion on what's passed, so we don't end up
+            passing filenames with tildes directly to stat(). */
+         if (*hint_text == '~')
+           hint = tilde_expand (hint_text);
+         else
+           hint = savestring (hint_text);
+         hint_len = strlen (hint);
+
+         if (filename_hint)
+           free (filename_hint);
+         filename_hint = savestring (hint);
+
+         mapping_over = 4;
+         istate = 0;
+         goto inner;
+       }
+
+      hint = savestring (hint_text);
+      hint_len = strlen (hint);
+
+      path = get_string_value ("PATH");
+      path_index = 0;
+
+      /* Initialize the variables for each type of command word. */
+      local_index = 0;
+
+      if (varlist)
+       free (varlist);
+
+      varlist = all_visible_functions ();
+
+#if defined (ALIAS)
+      if (alias_list)
+       free (alias_list);
+
+      alias_list = all_aliases ();
+#endif /* ALIAS */
+    }
+
+  /* mapping_over says what we are currently hacking.  Note that every case
+     in this list must fall through when there are no more possibilities. */
+
+  switch (mapping_over)
+    {
+    case 0:                    /* Aliases come first. */
+#if defined (ALIAS)
+      while (alias_list && alias_list[local_index])
+       {
+         register char *alias;
+
+         alias = alias_list[local_index++]->name;
+
+         if (STREQN (alias, hint, hint_len))
+           return (savestring (alias));
+       }
+#endif /* ALIAS */
+      local_index = 0;
+      mapping_over++;
+
+    case 1:                    /* Then shell reserved words. */
+      {
+       while (word_token_alist[local_index].word)
+         {
+           register char *reserved_word;
+
+           reserved_word = word_token_alist[local_index++].word;
+
+           if (STREQN (reserved_word, hint, hint_len))
+             return (savestring (reserved_word));
+         }
+       local_index = 0;
+       mapping_over++;
+      }
+
+    case 2:                    /* Then function names. */
+      while (varlist && varlist[local_index])
+       {
+         register char *varname;
+
+         varname = varlist[local_index++]->name;
+
+         if (STREQN (varname, hint, hint_len))
+           return (savestring (varname));
+       }
+      local_index = 0;
+      mapping_over++;
+
+    case 3:                    /* Then shell builtins. */
+      for (; local_index < num_shell_builtins; local_index++)
+       {
+         /* Ignore it if it doesn't have a function pointer or if it
+            is not currently enabled. */
+         if (!shell_builtins[local_index].function ||
+             (shell_builtins[local_index].flags & BUILTIN_ENABLED) == 0)
+           continue;
+
+         if (STREQN (shell_builtins[local_index].name, hint, hint_len))
+           {
+             int i = local_index++;
+
+             return (savestring (shell_builtins[i].name));
+           }
+       }
+      local_index = 0;
+      mapping_over++;
+    }
+
+  /* Repeatedly call filename_completion_func<tion while we have
+     members of PATH left.  Question:  should we stat each file?
+     Answer: we call executable_file () on each file. */
+ outer:
+
+  istate = (val != (char *)NULL);
+
+  if (!istate)
+    {
+      char *current_path;
+
+      /* Get the next directory from the path.  If there is none, then we
+        are all done. */
+      if (!path || !path[path_index] ||
+         (current_path = extract_colon_unit (path, &path_index)) == 0)
+       return ((char *)NULL);
+
+      if (*current_path == 0)
+       {
+         free (current_path);
+         current_path = savestring (".");
+       }
+
+      if (*current_path == '~')
+       {
+         char *t;
+
+         t = tilde_expand (current_path);
+         free (current_path);
+         current_path = t;
+       }
+
+      if (filename_hint)
+       free (filename_hint);
+
+      filename_hint = xmalloc (2 + strlen (current_path) + hint_len);
+      sprintf (filename_hint, "%s/%s", current_path, hint);
+
+      free (current_path);
+    }
+
+ inner:
+  val = filename_completion_function (filename_hint, istate);
+  istate = 1;
+
+  if (!val)
+    {
+      /* If the hint text is an absolute program, then don't bother
+        searching through PATH. */
+      if (absolute_program (hint))
+       return ((char *)NULL);
+
+      goto outer;
+    }
+  else
+    {
+      int match;
+      char *temp;
+
+      if (absolute_program (hint))
+       {
+         match = strncmp (val, hint, hint_len) == 0;
+         /* If we performed tilde expansion, restore the original
+            filename. */
+         if (*hint_text == '~')
+           {
+             int l, tl, vl;
+             vl = strlen (val);
+             tl = strlen (hint_text);
+             l = vl - hint_len;        /* # of chars added */
+             temp = xmalloc (l + 2 + tl);
+             strcpy (temp, hint_text);
+             strcpy (temp + tl, val + vl - l);
+           }
+         else
+           temp = savestring (val);
+       }
+      else
+       {
+         temp = strrchr (val, '/');
+
+         if (temp)
+           {
+             temp++;
+             match = strncmp (temp, hint, hint_len) == 0;
+             if (match)
+               temp = savestring (temp);
+           }
+         else
+           match = 0;
+       }
+
+      /* If we have found a match, and it is an executable file, return it. */
+      if (match && executable_file (val))
+       {
+         free (val);
+         val = "";             /* So it won't be NULL. */
+         return (temp);
+       }
+      else
+       {
+         free (val);
+         goto inner;
+       }
+    }
+}
+
+static char *
+command_subst_completion_function (text, state)
+     int state;
+     char *text;
+{
+  static char **matches = (char **)NULL;
+  static char *orig_start, *filename_text = (char *)NULL;
+  static int cmd_index, start_len;
+
+  if (state == 0)
+    {
+      if (filename_text)
+       free (filename_text);
+      orig_start = text;
+      if (*text == '`')
+        text++;
+      else if (*text == '$' && text[1] == '(')
+        text += 2;
+      start_len = text - orig_start;
+      filename_text = savestring (text);
+      if (matches)
+       free (matches);
+      matches = completion_matches (filename_text, command_word_completion_function);
+      cmd_index = 0;
+    }
+
+  if (!matches || !matches[cmd_index])
+    {
+      rl_filename_quoting_desired = 0; /* disable quoting */
+      return ((char *)NULL);
+    }
+  else
+    {
+      char *value;
+
+      value = xmalloc (1 + start_len + strlen (matches[cmd_index]));
+
+      if (start_len == 1)
+        value[0] = *orig_start;
+      else
+        strncpy (value, orig_start, start_len);
+
+      strcpy (value + start_len, matches[cmd_index]);
+
+      cmd_index++;
+      return (value);
+    }
+}
+
+/* Okay, now we write the entry_function for variable completion. */
+static char *
+variable_completion_function (text, state)
+     int state;
+     char *text;
+{
+  register SHELL_VAR *var = (SHELL_VAR *)NULL;
+  static SHELL_VAR **varlist = (SHELL_VAR **)NULL;
+  static int varlist_index;
+  static char *varname = (char *)NULL;
+  static int namelen;
+  static int first_char, first_char_loc;
+
+  if (!state)
+    {
+      if (varname)
+       free (varname);
+
+      first_char_loc = 0;
+      first_char = text[0];
+
+      if (first_char == '$')
+       first_char_loc++;
+
+      varname = savestring (text + first_char_loc);
+
+      namelen = strlen (varname);
+      if (varlist)
+       free (varlist);
+      varlist = all_visible_variables ();
+      varlist_index = 0;
+    }
+
+  while (varlist && varlist[varlist_index])
+    {
+      var = varlist[varlist_index];
+
+      /* Compare.  You can't do better than Zayre.  No text is also
+        a match.  */
+      if (!*varname || (strncmp (varname, var->name, namelen) == 0))
+       break;
+      varlist_index++;
+    }
+
+  if (!varlist || !varlist[varlist_index])
+    {
+      return ((char *)NULL);
+    }
+  else
+    {
+      char *value = xmalloc (2 + strlen (var->name));
+
+      if (first_char_loc)
+       *value = first_char;
+
+      strcpy (&value[first_char_loc], var->name);
+
+      varlist_index++;
+      return (value);
+    }
+}
+
+/* How about a completion function for hostnames? */
+static char *
+hostname_completion_function (text, state)
+     int state;
+     char *text;
+{
+  static char **list = (char **)NULL;
+  static int list_index = 0;
+  static int first_char, first_char_loc;
+
+  /* If we don't have any state, make some. */
+  if (!state)
+    {
+      if (list)
+       free (list);
+
+      list = (char **)NULL;
+
+      first_char_loc = 0;
+      first_char = *text;
+
+      if (first_char == '@')
+       first_char_loc++;
+
+      list = hostnames_matching (&text[first_char_loc]);
+      list_index = 0;
+    }
+
+  if (list && list[list_index])
+    {
+      char *t = xmalloc (2 + strlen (list[list_index]));
+
+      *t = first_char;
+      strcpy (t + first_char_loc, list[list_index]);
+      list_index++;
+      return (t);
+    }
+  else
+    return ((char *)NULL);
+}
+
+/* History and alias expand the line. */
+static char *
+history_expand_line_internal (line)
+     char *line;
+{
+  char *new_line;
+
+  new_line = pre_process_line (line, 0, 0);
+  return new_line;
+}
+
+#if defined (ALIAS)
+/* Perform alias expansion on LINE and return the new line. */
+static char *
+alias_expand_line_internal (line)
+     char *line;
+{
+  char *alias_line;
+
+  alias_line = alias_expand (line);
+  return alias_line;
+}
+#endif
+
+/* There was an error in expansion.  Let the preprocessor print
+   the error here. */
+static void
+cleanup_expansion_error ()
+{
+  char *to_free;
+
+  fprintf (rl_outstream, "\r\n");
+  to_free = pre_process_line (rl_line_buffer, 1, 0);
+  free (to_free);
+  putc ('\r', rl_outstream);
+  rl_forced_update_display ();
+}
+
+/* If NEW_LINE differs from what is in the readline line buffer, add an
+   undo record to get from the readline line buffer contents to the new
+   line and make NEW_LINE the current readline line. */
+static void
+maybe_make_readline_line (new_line)
+     char *new_line;
+{
+  if (strcmp (new_line, rl_line_buffer) != 0)
+    {
+      rl_point = rl_end;
+
+      rl_add_undo (UNDO_BEGIN, 0, 0, 0);
+      rl_delete_text (0, rl_point);
+      rl_point = rl_end = 0;
+      rl_insert_text (new_line);
+      rl_add_undo (UNDO_END, 0, 0, 0);
+    }
+}
+
+/* Make NEW_LINE be the current readline line.  This frees NEW_LINE. */
+static void
+set_up_new_line (new_line)
+     char *new_line;
+{
+  int old_point = rl_point;
+  int at_end = rl_point == rl_end;
+
+  /* If the line was history and alias expanded, then make that
+     be one thing to undo. */
+  maybe_make_readline_line (new_line);
+  free (new_line);
+
+  /* Place rl_point where we think it should go. */
+  if (at_end)
+    rl_point = rl_end;
+  else if (old_point < rl_end)
+    {
+      rl_point = old_point;
+      if (!whitespace (rl_line_buffer[rl_point]))
+       rl_forward_word (1);
+    }
+}
+
+/* History expand the line. */
+static void
+history_expand_line (ignore)
+     int ignore;
+{
+  char *new_line;
+
+  new_line = history_expand_line_internal (rl_line_buffer);
+
+  if (new_line)
+    set_up_new_line (new_line);
+  else
+    cleanup_expansion_error ();
+}
+  
+/* History and alias expand the line. */
+static void
+history_and_alias_expand_line (ignore)
+     int ignore;
+{
+  char *new_line;
+
+  new_line = pre_process_line (rl_line_buffer, 0, 0);
+
+#if defined (ALIAS)
+  if (new_line)
+    {
+      char *alias_line;
+
+      alias_line = alias_expand (new_line);
+      free (new_line);
+      new_line = alias_line;
+    }
+#endif /* ALIAS */
+
+  if (new_line)
+    set_up_new_line (new_line);
+  else
+    cleanup_expansion_error ();
+}
+
+/* History and alias expand the line, then perform the shell word
+   expansions by calling expand_string. */
+static void
+shell_expand_line (ignore)
+     int ignore;
+{
+  char *new_line;
+
+  new_line = pre_process_line (rl_line_buffer, 0, 0);
+
+#if defined (ALIAS)
+  if (new_line)
+    {
+      char *alias_line;
+
+      alias_line = alias_expand (new_line);
+      free (new_line);
+      new_line = alias_line;
+    }
+#endif /* ALIAS */
+
+  if (new_line)
+    {
+      int old_point = rl_point;
+      int at_end = rl_point == rl_end;
+
+      /* If the line was history and alias expanded, then make that
+        be one thing to undo. */
+      maybe_make_readline_line (new_line);
+      free (new_line);
+
+      /* If there is variable expansion to perform, do that as a separate
+        operation to be undone. */
+      {
+       WORD_LIST *expanded_string;
+
+       expanded_string = expand_string (rl_line_buffer, 0);
+       if (!expanded_string)
+         new_line = savestring ("");
+       else
+         {
+           new_line = string_list (expanded_string);
+           dispose_words (expanded_string);
+         }
+
+       maybe_make_readline_line (new_line);
+       free (new_line);
+
+       /* Place rl_point where we think it should go. */
+       if (at_end)
+         rl_point = rl_end;
+       else if (old_point < rl_end)
+         {
+           rl_point = old_point;
+           if (!whitespace (rl_line_buffer[rl_point]))
+             rl_forward_word (1);
+         }
+      }
+    }
+  else
+    cleanup_expansion_error ();
+}
+
+/* Filename completion ignore.  Emulates the "fignore" facility of
+   tcsh.  If FIGNORE is set, then don't match files with the
+   given suffixes.  If only one of the possibilities has an acceptable
+   suffix, delete the others, else just return and let the completer
+   signal an error.  It is called by the completer when real
+   completions are done on filenames by the completer's internal
+   function, not for completion lists (M-?) and not on "other"
+   completion types, such as hostnames or commands.
+   It is passed a NULL-terminated array of (char *)'s that must be
+   free()'d if they are deleted.  The first element (names[0]) is the
+   least-common-denominator string of the matching patterns (i.e.
+   u<TAB> produces names[0] = "und", names[1] = "under.c", names[2] =
+   "undun.c", name[3] = NULL).  */
+
+struct ign {
+  char *val;
+  int len;
+};
+
+static struct ign *ignores;    /* Store the ignore strings here */
+static int num_ignores;                /* How many are there? */
+static char *last_fignore;     /* Last value of fignore - cached for speed */
+
+static void
+setup_ignore_patterns ()
+{
+  int numitems, maxitems, ptr;
+  char *colon_bit;
+  struct ign *p;
+  
+  char *this_fignore = get_string_value ("FIGNORE");
+
+  /* If nothing has changed then just exit now. */
+  if ((this_fignore &&
+       last_fignore &&
+       strcmp (this_fignore, last_fignore) == 0) ||
+      (!this_fignore && !last_fignore))
+    {
+      return;
+    }
+
+  /* Oops.  FIGNORE has changed.  Re-parse it. */
+  num_ignores = 0;
+
+  if (ignores)
+    {
+      for (p = ignores; p->val; p++) free(p->val);
+      free (ignores);
+      ignores = (struct ign*)NULL;
+    }
+
+  if (last_fignore)
+    {
+      free (last_fignore);
+      last_fignore = (char *)NULL;
+    }
+
+  if (!this_fignore || !*this_fignore)
+    return;
+
+  last_fignore = savestring (this_fignore);
+
+  numitems = maxitems = ptr = 0;
+
+  while (colon_bit = extract_colon_unit (this_fignore, &ptr))
+    {
+      if (numitems + 1 > maxitems)
+       ignores = (struct ign *)
+         xrealloc (ignores, (maxitems += 10) * sizeof (struct ign));
+
+      ignores[numitems].val = colon_bit;
+      ignores[numitems].len = strlen (colon_bit);
+      numitems++;
+    }
+  ignores[numitems].val = NULL;
+  num_ignores = numitems;
+}
+
+static int
+name_is_acceptable (name)
+     char *name;
+{
+  struct ign *p;
+  int nlen = strlen (name);
+
+  for (p = ignores; p->val; p++) 
+    {
+      if (nlen > p->len && p->len > 0 && 
+         strcmp (p->val, &name[nlen - p->len]) == 0)
+       return (0);
+    }
+
+  return (1);
+}
+
+/* Internal function to test whether filenames in NAMES should be
+   ignored.  NAME_FUNC is a pointer to a function to call with each
+   name.  It returns non-zero if the name is acceptable to the particular
+   ignore function which called _ignore_names; zero if the name should
+   be removed from NAMES. */
+static void
+_ignore_names (names, name_func)
+     char **names;
+     Function *name_func;
+{
+  char **newnames;
+  int idx, nidx;
+
+  /* If there is only one completion, see if it is acceptable.  If it is
+     not, free it up.  In any case, short-circuit and return.  This is a
+     special case because names[0] is not the prefix of the list of names
+     if there is only one completion; it is the completion itself. */
+  if (names[1] == (char *)0)
+    {
+      if ((*name_func) (names[0]) == 0)
+        {
+          free (names[0]);
+          names[0] = (char *)NULL;
+        }
+      return;
+    }
+
+  /* Allocate space for array to hold list of pointers to matching
+     filenames.  The pointers are copied back to NAMES when done. */
+  for (nidx = 1; names[nidx]; nidx++)
+    ;
+  newnames = (char **)xmalloc ((nidx + 1) * (sizeof (char *)));
+
+  newnames[0] = names[0];
+  for (idx = nidx = 1; names[idx]; idx++)
+    {
+      if ((*name_func) (names[idx]))
+       newnames[nidx++] = names[idx];
+      else
+       free (names[idx]);
+    }
+
+  newnames[nidx] = (char *)NULL;
+
+  /* If none are acceptable then let the completer handle it. */
+  if (nidx == 1)
+    {
+      free (names[0]);
+      names[0] = (char *)NULL;
+      free (newnames);
+      return;
+    }
+
+  /* If only one is acceptable, copy it to names[0] and return. */
+  if (nidx == 2)
+    {
+      free (names[0]);
+      names[0] = newnames[1];
+      names[1] = (char *)NULL;
+      free (newnames);
+      return;
+    }
+      
+  /* Copy the acceptable names back to NAMES, set the new array end,
+     and return. */
+  for (nidx = 1; newnames[nidx]; nidx++)
+    names[nidx] = newnames[nidx];
+  names[nidx] = (char *)NULL;
+}
+
+static void
+filename_completion_ignore (names)
+     char **names;
+{
+  setup_ignore_patterns ();
+
+  if (num_ignores == 0)
+    return;
+
+  _ignore_names (names, name_is_acceptable);
+}
+
+/* Return 1 if NAME is a directory. */
+static int
+test_for_directory (name)
+     char *name;
+{
+  struct stat finfo;
+  char *fn;
+
+  fn = tilde_expand (name);
+  if (stat (fn, &finfo) != 0)
+    {
+      free (fn);
+      return 0;
+    }
+  free (fn);
+  return (S_ISDIR (finfo.st_mode));
+}
+
+/* Remove files from NAMES, leaving directories. */
+static void
+bash_ignore_filenames (names)
+     char **names;
+{
+  _ignore_names (names, test_for_directory);
+}
+
+/* Handle symbolic link references and other directory name
+   expansions while hacking completion. */
+static int
+bash_directory_completion_hook (dirname)
+     char **dirname;
+{
+  char *local_dirname, *t;
+  int return_value = 0;
+  WORD_LIST *wl;
+
+  local_dirname = *dirname;
+  if (strchr (local_dirname, '$') || strchr (local_dirname, '`'))
+    {
+      wl = expand_string (local_dirname, 0);
+      if (wl)
+       {
+         *dirname = string_list (wl);
+         /* Tell the completer to replace the directory name only if we
+            actually expanded something. */
+         return_value = STREQ (local_dirname, *dirname) == 0;
+         free (local_dirname);
+         dispose_words (wl);
+         local_dirname = *dirname;
+       }
+      else
+       {
+         free (local_dirname);
+         *dirname = savestring ("");
+         return 1;
+       }
+    }
+
+  if (!no_symbolic_links && (local_dirname[0] != '.' || local_dirname[1]))
+    {
+      char *temp1, *temp2;
+      int len1, len2;
+
+      t = get_working_directory ("symlink-hook");
+      temp1 = make_absolute (local_dirname, t);
+      free (t);
+      temp2 = canonicalize_pathname (temp1);
+      len1 = strlen (temp1);
+      if (temp1[len1 - 1] == '/')
+        {
+         len2 = strlen (temp2);
+          temp2 = xrealloc (temp2, len2 + 2);
+          temp2[len2] = '/';
+          temp2[len2 + 1] = '\0';
+        }
+      free (local_dirname);
+      *dirname = temp2;
+      free (temp1);
+    }
+  return (return_value);
+}
+
+#if defined (DYNAMIC_HISTORY_COMPLETION)
+static char **history_completion_array = (char **)NULL;
+static int harry_size = 0;
+static int harry_len = 0;
+
+static void
+build_history_completion_array ()
+{
+  register int i;
+
+  /* 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);
+
+      history_completion_array = (char **)NULL;
+      harry_size = 0;
+      harry_len = 0;
+    }
+
+  /* Next, grovel each line of history, making each shell-sized token
+     a separate entry in the history_completion_array. */
+  {
+    HIST_ENTRY **hlist;
+
+    hlist = history_list ();
+
+    if (hlist)
+      {
+       register int j;
+
+       for (i = 0; hlist[i]; i++)
+         {
+           char **tokens;
+
+           /* Separate each token, and place into an array. */
+           tokens = history_tokenize (hlist[i]->line);
+
+           for (j = 0; tokens && tokens[j]; j++)
+             {
+               if (harry_len + 2 > harry_size)
+                 history_completion_array = (char **) xrealloc
+                   (history_completion_array,
+                    (harry_size += 10) * sizeof (char *));
+
+               history_completion_array[harry_len++] = tokens[j];
+               history_completion_array[harry_len] = (char *)NULL;
+             }
+           free (tokens);
+         }
+
+       /* Sort the complete list of tokens. */
+       qsort (history_completion_array, harry_len, sizeof (char *),
+              (Function *)qsort_string_compare);
+
+       /* Instead of removing the duplicate entries here, we let the
+          code in the completer handle it. */
+      }
+  }
+}
+
+static char *
+history_completion_generator (hint_text, state)
+     char *hint_text;
+     int state;
+{
+  static int local_index = 0;
+  static char *text = (char *)NULL;
+  static int len = 0;
+
+  /* If this is the first call to the generator, then initialize the
+     list of strings to complete over. */
+  if (!state)
+    {
+      local_index = 0;
+      build_history_completion_array ();
+      text = hint_text;
+      len = strlen (text);
+    }
+
+  while (history_completion_array && history_completion_array[local_index])
+    {
+      if (strncmp (text, history_completion_array[local_index++], len) == 0)
+       return (savestring (history_completion_array[local_index - 1]));
+    }
+  return ((char *)NULL);
+}
+
+static void
+dynamic_complete_history (count, key)
+     int count, key;
+{
+  Function *orig_func;
+  CPPFunction *orig_attempt_func;
+
+  orig_func = rl_completion_entry_function;
+  orig_attempt_func = rl_attempted_completion_function;
+  rl_completion_entry_function = (Function *)history_completion_generator;
+  rl_attempted_completion_function = (CPPFunction *)NULL;
+
+  if (rl_last_func == (Function *)dynamic_complete_history)
+    rl_complete_internal ('?');
+  else
+    rl_complete_internal (TAB);
+
+  rl_completion_entry_function = orig_func;
+  rl_attempted_completion_function = orig_attempt_func;
+}
+
+#endif /* DYNAMIC_HISTORY_COMPLETION */
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+static void
+bash_complete_username (ignore, ignore2)
+     int ignore, ignore2;
+{
+  bash_complete_username_internal (TAB);
+}
+
+static void
+bash_possible_username_completions (ignore, ignore2)
+     int ignore, ignore2;
+{
+  bash_complete_username_internal ('?');
+}
+
+static void
+bash_complete_username_internal (what_to_do)
+     int what_to_do;
+{
+  bash_specific_completion
+    (what_to_do, (Function *)username_completion_function);
+}
+
+static void
+bash_complete_filename (ignore, ignore2)
+     int ignore, ignore2;
+{
+  bash_complete_filename_internal (TAB);
+}
+
+static void
+bash_possible_filename_completions (ignore, ignore2)
+     int ignore, ignore2;
+{
+  bash_complete_filename_internal ('?');
+}
+
+static void
+bash_complete_filename_internal (what_to_do)
+     int what_to_do;
+{
+  Function  *orig_func, *orig_dir_func;
+  CPPFunction *orig_attempt_func;
+  char *orig_rl_completer_word_break_characters;
+
+  orig_func = rl_completion_entry_function;
+  orig_attempt_func = rl_attempted_completion_function;
+  orig_dir_func = rl_directory_completion_hook;
+  orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
+  rl_completion_entry_function = (Function *)filename_completion_function;
+  rl_attempted_completion_function = (CPPFunction *)NULL;
+  rl_directory_completion_hook = (Function *)NULL;
+  rl_completer_word_break_characters = " \t\n\"\'";
+
+  rl_complete_internal (what_to_do);
+
+  rl_completion_entry_function = orig_func;
+  rl_attempted_completion_function = orig_attempt_func;
+  rl_directory_completion_hook = orig_dir_func;
+  rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
+}
+
+static void
+bash_complete_hostname (ignore, ignore2)
+     int ignore, ignore2;
+{
+  bash_complete_hostname_internal (TAB);
+}
+
+static void
+bash_possible_hostname_completions (ignore, ignore2)
+     int ignore, ignore2;
+{
+  bash_complete_hostname_internal ('?');
+}
+
+static void
+bash_complete_variable (ignore, ignore2)
+     int ignore, ignore2;
+{
+  bash_complete_variable_internal (TAB);
+}
+
+static void
+bash_possible_variable_completions (ignore, ignore2)
+     int ignore, ignore2;
+{
+  bash_complete_variable_internal ('?');
+}
+
+static void
+bash_complete_command (ignore, ignore2)
+     int ignore, ignore2;
+{
+  bash_complete_command_internal (TAB);
+}
+
+static void
+bash_possible_command_completions (ignore, ignore2)
+     int ignore, ignore2;
+{
+  bash_complete_command_internal ('?');
+}
+
+static void
+bash_complete_hostname_internal (what_to_do)
+     int what_to_do;
+{
+  bash_specific_completion
+    (what_to_do, (Function *)hostname_completion_function);
+}
+
+static void
+bash_complete_variable_internal (what_to_do)
+     int what_to_do;
+{
+  bash_specific_completion
+    (what_to_do, (Function *)variable_completion_function);
+}
+
+static void
+bash_complete_command_internal (what_to_do)
+     int what_to_do;
+{
+  bash_specific_completion
+    (what_to_do, (Function *)command_word_completion_function);
+}
+
+static void
+bash_specific_completion (what_to_do, generator)
+     int what_to_do;
+     Function *generator;
+{
+  Function *orig_func;
+  CPPFunction *orig_attempt_func;
+
+  orig_func = rl_completion_entry_function;
+  orig_attempt_func = rl_attempted_completion_function;
+  rl_completion_entry_function = generator;
+  rl_attempted_completion_function = (CPPFunction *)NULL;
+
+  rl_complete_internal (what_to_do);
+
+  rl_completion_entry_function = orig_func;
+  rl_attempted_completion_function = orig_attempt_func;
+}
+
+#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
diff --git a/bashtypes.h b/bashtypes.h
new file mode 100644 (file)
index 0000000..a725d61
--- /dev/null
@@ -0,0 +1,34 @@
+/* bashtypes.h -- <sys/types.h> with special handling for crays. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (__BASHTYPES_H)
+#  define __BASHTYPES_H
+
+#if defined (CRAY)
+#  define word __word
+#endif
+
+#include <sys/types.h>
+
+#if defined (CRAY)
+#  undef word
+#endif
+
+#endif /* __BASHTYPES_H */
diff --git a/bracecomp.c b/bracecomp.c
new file mode 100644 (file)
index 0000000..c07e15d
--- /dev/null
@@ -0,0 +1,166 @@
+/* bracecomp.c -- Complete a filename with the possible completions enclosed
+   in csh-style braces such that the list of completions is available to the
+   shell. */
+
+/* Original version by tromey@cns.caltech.edu,  Fri Feb  7 1992. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "shell.h"
+#include <readline/readline.h>
+
+/* Find greatest common prefix of two strings. */
+static int
+string_gcd (s1, s2)
+     char *s1, *s2;
+{
+  register int i;
+
+  if (s1 == NULL || s2 == NULL)
+    return (0);
+
+  for (i = 0; *s1 && *s2; ++s1, ++s2, ++i)
+    {
+      if (*s1 != *s2)
+       break;
+    }
+
+  return (i);
+}
+
+static char *
+really_munge_braces (array, real_start, real_end, gcd_zero)
+     char **array;
+     int real_start, real_end, gcd_zero;
+{
+  int start, end, gcd;
+  char *result, *subterm;
+  int result_size, flag;
+
+  flag = 0;
+
+  if (real_start == real_end)
+    {
+      if (array[real_start])
+        return (savestring (array[real_start] + gcd_zero));
+      else
+        return (savestring (array[0]));
+    }
+
+  result = (char *) xmalloc (result_size = 1);
+  *result = '\0';
+
+  for (start = real_start; start < real_end; start = end + 1)
+    {
+      gcd = strlen (array[start]);
+      for (end = start + 1; end < real_end; end++)
+       {
+         int temp;
+
+         temp = string_gcd (array[start], array[end]);
+
+         if (temp <= gcd_zero)
+           break;
+
+         gcd = temp;
+       }
+      end--;
+
+      if (gcd_zero == 0 && start == real_start && end != (real_end - 1))
+       {
+         /* In this case, add in a leading '{', because we are at
+            top level, and there isn't a consistent prefix. */
+         result_size += 1;
+         result = (char *) xrealloc (result, result_size);
+         strcpy (result, "{");
+         flag++;
+       }
+
+      if (start == end)
+       subterm = savestring (array[start] + gcd_zero);
+      else
+       {
+         /* If there is more than one element in the subarray,
+            insert the prefix and an opening brace. */
+         result_size += gcd - gcd_zero + 1;
+         result = (char *) xrealloc (result, result_size);
+         strncat (result, array[start] + gcd_zero, gcd - gcd_zero);
+         strcat (result, "{");
+         subterm = really_munge_braces (array, start, end + 1, gcd);
+         subterm[strlen (subterm) - 1] = '}';
+       }
+
+      result_size += strlen (subterm) + 1;
+      result = (char *) xrealloc (result, result_size);
+      strcat (result, subterm);
+      strcat (result, ",");
+      free (subterm);
+    }
+
+  if (gcd_zero == 0)
+    result[strlen (result) - 1] = flag ? '}' : '\0';
+  return (result);
+}
+
+static void
+hack_braces_completion (names)
+     char **names;
+{
+  register int i;
+  char *temp;
+
+  temp = really_munge_braces (names, 1, array_len (names), 0);
+
+  for (i = 0; names[i]; ++i)
+    {
+      free (names[i]);
+      names[i] = NULL;
+    }
+  names[0] = temp;
+}
+
+void
+bash_brace_completion ()
+{
+  Function *orig_ignore_func;
+  Function *orig_entry_func;
+  CPPFunction *orig_attempt_func;
+
+  orig_ignore_func = rl_ignore_some_completions_function;
+  orig_attempt_func = rl_attempted_completion_function;
+  orig_entry_func = rl_completion_entry_function;
+
+  rl_completion_entry_function = (Function *) filename_completion_function;
+  rl_attempted_completion_function = NULL;
+  rl_ignore_some_completions_function = (Function *) hack_braces_completion;
+
+  rl_complete_internal (TAB);
+
+  rl_ignore_some_completions_function = orig_ignore_func;
+  rl_attempted_completion_function = orig_attempt_func;
+  rl_completion_entry_function = orig_entry_func;
+}
diff --git a/braces.c b/braces.c
new file mode 100644 (file)
index 0000000..2eb4de4
--- /dev/null
+++ b/braces.c
@@ -0,0 +1,371 @@
+/* braces.c -- code for doing word expansion in curly braces. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Stuff in curly braces gets expanded after variable and command
+   substitution, but before filename globbing.
+
+   (Actually, this should be true for the sake of efficiency, but it
+   isn't because of quoting hacks.  Once I rebuild quoting it will be
+   true. */
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#if defined (SHELL)
+#include "shell.h"
+#endif /* SHELL */
+
+#include "general.h"
+#define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
+
+/* Basic idea:
+
+   Segregate the text into 3 sections: preamble (stuff before an open brace),
+   postamble (stuff after the matching close brace) and amble (stuff after
+   preamble, and before postamble).  Expand amble, and then tack on the
+   expansions to preamble.  Expand postamble, and tack on the expansions to
+   the result so far.
+ */
+
+/* The character which is used to separate arguments. */
+int brace_arg_separator = ',';
+
+static int brace_gobbler ();
+static char **expand_amble (), **array_concat ();
+
+/* Return an array of strings; the brace expansion of TEXT. */
+char **
+brace_expand (text)
+     char *text;
+{
+  register int start;
+  char *preamble, *postamble, *amble;
+  char **tack, **result;
+  int i, c;
+
+  /* Find the text of the preamble. */
+  i = 0;
+  c = brace_gobbler (text, &i, '{');
+
+  preamble = (char *)xmalloc (i + 1);
+  strncpy (preamble, text, i);
+  preamble[i] = '\0';
+
+  result = (char **)xmalloc (2 * sizeof (char *));
+  result[0] = preamble;
+  result[1] = (char *)NULL;
+  
+  /* Special case.  If we never found an exciting character, then
+     the preamble is all of the text, so just return that. */
+  if (c != '{')
+    return (result);
+
+  /* Find the amble.  This is the stuff inside this set of braces. */
+  start = ++i;
+  c = brace_gobbler (text, &i, '}');
+
+  /* What if there isn't a matching close brace? */
+  if (!c)
+    {
+#if defined (NOTDEF)
+      register int j;
+
+      /* 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++)
+       {
+         if (text[j] == '\\')
+           {
+             j++;
+             continue;
+           }
+
+         if (text[j] == brace_arg_separator)
+           {
+             free_array (result);
+             report_error ("Missing `}'");
+             throw_to_top_level ();
+           }
+       }
+#endif
+      free (preamble);         /* Same as result[0]; see initialization. */
+      result[0] = savestring (text);
+      return (result);
+    }
+
+  amble = (char *)xmalloc (1 + (i - start));
+  strncpy (amble, &text[start], (i - start));
+  amble[i - start] = '\0';
+
+#if defined (SHELL)
+  /* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
+     just return without doing any expansion.  */
+  {
+    register int j;
+
+    for (j = 0; amble[j]; j++)
+      {
+       if (amble[j] == '\\')
+         {
+           j++;
+           continue;
+         }
+       if (amble[j] == brace_arg_separator)
+         break;
+      }
+
+    if (!amble[j])
+      {
+       free (amble);
+       free (preamble);
+       result[0] = savestring (text);
+       return (result);
+      }
+  }
+#endif /* SHELL */
+
+  postamble = &text[i + 1];
+
+  tack = expand_amble (amble);
+  result = array_concat (result, tack);
+  free (amble);
+  free_array (tack);
+
+  tack = brace_expand (postamble);
+  result = array_concat (result, tack);
+  free_array (tack);
+
+  return (result);
+}
+
+/* Expand the text found inside of braces.  We simply try to split the
+   text at BRACE_ARG_SEPARATORs into separate strings.  We then brace
+   expand each slot which needs it, until there are no more slots which
+   need it. */
+static char **
+expand_amble (text)
+     char *text;
+{
+  char **result, **partial;
+  char *tem;
+  int start, i, c;
+
+  result = (char **)NULL;
+
+  for (start = 0, i = 0, c = 1; c; start = ++i)
+    {
+      c = brace_gobbler (text, &i, brace_arg_separator);
+      tem = (char *)xmalloc (1 + (i - start));
+      strncpy (tem, &text[start], (i - start));
+      tem[i- start] = '\0';
+
+      partial = brace_expand (tem);
+
+      if (!result)
+       result = partial;
+      else
+       {
+         register int lr = array_len (result);
+         register int lp = array_len (partial);
+         register int j;
+
+         result = (char **)xrealloc (result, (1 + lp + lr) * sizeof (char *));
+
+         for (j = 0; j < lp; j++)
+           result[lr + j] = partial[j];
+
+         result[lr + j] = (char *)NULL;
+         free (partial);
+       }
+      free (tem);
+    }
+  return (result);
+}
+
+/* Start at INDEX, and skip characters in TEXT. Set INDEX to the
+   index of the character matching SATISFY.  This understands about
+   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)
+     char *text;
+     int *indx;
+     int satisfy;
+{
+  register int i, c, quoted, level, pass_next;
+
+  level = quoted = pass_next = 0;
+
+  for (i = *indx; c = text[i]; i++)
+    {
+      if (pass_next)
+       {
+         pass_next = 0;
+         continue;
+       }
+
+      /* A backslash escapes the next character.  This allows backslash to
+        escape the quote character in a double-quoted string. */
+      if (c == '\\' && (quoted == 0 || quoted == '"' || quoted == '`'))
+        {
+          pass_next = 1;
+          continue;
+        }
+
+      if (quoted)
+       {
+         if (c == quoted)
+           quoted = 0;
+         continue;
+       }
+
+      if (c == '"' || c == '\'' || c == '`')
+       {
+         quoted = c;
+         continue;
+       }
+      
+      if (c == satisfy && !level && !quoted)
+       {
+         /* We ignore an open brace surrounded by whitespace, and also
+            an open brace followed immediately by a close brace, that
+            was preceded with whitespace.  */
+         if (c == '{' &&
+             ((!i || brace_whitespace (text[i - 1])) &&
+              (brace_whitespace (text[i + 1]) || text[i + 1] == '}')))
+           continue;
+#if defined (SHELL)
+         /* If this is being compiled as part of bash, ignore the `{'
+            in a `${}' construct */
+         if ((c != '{') || !i || (text[i - 1] != '$'))
+#else /* !SHELL */
+         if ((c != '{') || !i)
+#endif /* !SHELL */
+           break;
+       }
+
+      if (c == '{')
+       level++;
+      else if (c == '}' && level)
+       level--;
+    }
+
+  *indx = i;
+  return (c);
+}
+
+/* Return a new array of strings which is the result of appending each
+   string in ARR2 to each string in ARR1.  The resultant array is
+   len (arr1) * len (arr2) long.  For convenience, ARR1 (and its contents)
+   are free ()'ed.  ARR1 can be NULL, in that case, a new version of ARR2
+   is returned. */
+static char **
+array_concat (arr1, arr2)
+     char **arr1, **arr2;
+{
+  register int i, j, len, len1, len2;
+  register char **result;
+
+  if (!arr1)
+    return (copy_array (arr2));
+
+  if (!arr2)
+    return (copy_array (arr1));
+
+  len1 = array_len (arr1);
+  len2 = array_len (arr2);
+
+  result = (char **)xmalloc ((1 + (len1 * len2)) * sizeof (char *));
+
+  len = 0;
+  for (i = 0; i < len1; i++)
+    {
+      int strlen_1 = strlen (arr1[i]);
+
+      for (j = 0; j < len2; j++)
+       {
+         result[len] =
+           (char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
+         strcpy (result[len], arr1[i]);
+         strcpy (result[len] + strlen_1, arr2[j]);
+         len++;
+       }
+      free (arr1[i]);
+    }
+  free (arr1);
+
+  result[len] = (char *)NULL;
+  return (result);
+}
+
+#if defined (TEST)
+#include <stdio.h>
+
+fatal_error (format, arg1, arg2)
+     char *format, *arg1, *arg2;
+{
+  report_error (format, arg1, arg2);
+  exit (1);
+}
+
+report_error (format, arg1, arg2)
+     char *format, *arg1, *arg2;
+{
+  fprintf (stderr, format, arg1, arg2);
+  fprintf (stderr, "\n");
+}
+
+main ()
+{
+  char example[256];
+
+  for (;;)
+    {
+      char **result;
+      int i;
+
+      fprintf (stderr, "brace_expand> ");
+
+      if ((!fgets (example, 256, stdin)) ||
+         (strncmp (example, "quit", 4) == 0))
+       break;
+
+      if (strlen (example))
+       example[strlen (example) - 1] = '\0';
+
+      result = brace_expand (example);
+
+      for (i = 0; result[i]; i++)
+       printf ("%s\n", result[i]);
+
+      free_array (result);
+    }
+}
+\f
+/*
+ * Local variables:
+ * compile-command: "gcc -g -Bstatic -DTEST -o brace_expand braces.c general.o"
+ * end:
+ */
+
+#endif /* TEST */
diff --git a/builtins.h b/builtins.h
new file mode 100644 (file)
index 0000000..6d4d8e8
--- /dev/null
@@ -0,0 +1,45 @@
+/* builtins.h -- What a builtin looks like, and where to find them. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "config.h"
+#include "command.h"
+#include "general.h"
+
+#if defined (ALIAS)
+#include "alias.h"
+#endif
+
+/* Flags describing various things about a builtin. */
+#define BUILTIN_ENABLED 0x1    /* This builtin is enabled. */
+#define STATIC_BUILTIN  0x2    /* This builtin is not dynamically loaded. */
+#define SPECIAL_BUILTIN 0x4    /* This is a Posix `special' builtin. */
+
+/* The thing that we build the array of builtins out of. */
+struct builtin {
+  char *name;                  /* The name that the user types. */
+  Function *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. */
+};
+
+/* Found in builtins.c, created by builtins/mkbuiltins. */
+extern int num_shell_builtins; /* Number of shell builtins. */
+extern struct builtin shell_builtins[];
diff --git a/builtins/ChangeLog b/builtins/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/builtins/Makefile b/builtins/Makefile
new file mode 100644 (file)
index 0000000..6472f7d
--- /dev/null
@@ -0,0 +1,267 @@
+# This Makefile for building libbuiltins.a is in -*- text -*- for Emacs.
+#
+MKBUILTINS = mkbuiltins
+RANLIB = /usr/bin/ranlib
+CFLAGS = -g -I.. -I.
+SHELL = /bin/sh
+# CC = cc
+AR = ar
+RM = rm -f
+CP = cp
+
+srcdir = .
+VPATH = .:$(srcdir)
+
+.SUFFIXES:
+.SUFFIXES: .def .c .o
+# How to make a .o file from a .def file.
+.def.o:
+       $(RM) $@
+       ./$(MKBUILTINS) $(DIRECTDEFINE) $<
+       $(CC) -c $(CFLAGS) $(CPPFLAGS) $*.c || ( $(RM) $*.c ; exit 1 )
+       $(RM) $*.c
+
+# How to make a .c file from a .def file.
+.def.c:
+       $(RM) $@
+       ./$(MKBUILTINS) $(DIRECTDEFINE) $<
+
+# Here is a rule for making .o files from .c files that does not
+# force the type of the machine (like -M_MACHINE) into the flags.
+.c.o:
+       $(RM) $@
+       $(CC) -c $(CFLAGS) $(CPPFLAGS) $<
+
+DEFS =  $(srcdir)/alias.def $(srcdir)/bind.def $(srcdir)/break.def \
+       $(srcdir)/builtin.def $(srcdir)/cd.def $(srcdir)/colon.def \
+       $(srcdir)/command.def $(srcdir)/declare.def $(srcdir)/echo.def \
+       $(srcdir)/enable.def $(srcdir)/eval.def $(srcdir)/getopts.def \
+       $(srcdir)/exec.def $(srcdir)/exit.def $(srcdir)/fc.def \
+       $(srcdir)/fg_bg.def $(srcdir)/hash.def $(srcdir)/help.def \
+       $(srcdir)/history.def $(srcdir)/jobs.def $(srcdir)/kill.def \
+       $(srcdir)/let.def $(srcdir)/read.def $(srcdir)/return.def \
+       $(srcdir)/set.def $(srcdir)/setattr.def $(srcdir)/shift.def \
+       $(srcdir)/source.def $(srcdir)/suspend.def $(srcdir)/test.def \
+       $(srcdir)/times.def $(srcdir)/trap.def $(srcdir)/type.def \
+       $(srcdir)/ulimit.def $(srcdir)/umask.def $(srcdir)/wait.def \
+       $(srcdir)/reserved.def
+
+STATIC_SOURCE = common.c getopt.c bashgetopt.c getopt.h 
+
+OFILES = builtins.o \
+       alias.o bind.o break.o builtin.o cd.o colon.o command.o \
+       common.o declare.o echo.o enable.o eval.o exec.o exit.o \
+       fc.o fg_bg.o hash.o help.o history.o jobs.o kill.o \
+       let.o read.o return.o set.o setattr.o shift.o source.o \
+       suspend.o test.o times.o trap.o type.o ulimit.o umask.o \
+       wait.o getopts.o getopt.o bashgetopt.o
+
+THINGS_TO_TAR = $(DEFS) $(STATIC_SOURCE) Makefile ChangeLog
+
+CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h
+
+all: $(MKBUILTINS) libbuiltins.a
+
+libbuiltins.a: $(MKBUILTINS) $(OFILES)
+       $(RM) $@
+       $(AR) cq $@ $(OFILES)
+       -$(RANLIB) $@
+
+builtext.h builtins.c: $(MKBUILTINS) $(DEFS)
+       $(RM) builtext.h builtins.c
+       ./$(MKBUILTINS) -externfile builtext.h -structfile builtins.c \
+       -noproduction $(DIRECTDEFINE) $(DEFS)
+
+mkbuiltins: $(srcdir)/mkbuiltins.c ../config.h
+       $(CC) $(CFLAGS) -o $(MKBUILTINS) $(srcdir)/mkbuiltins.c
+
+ulimit.o: ulimit.def pipesize.h
+
+pipesize.h:    psize.aux
+       $(SHELL) $(srcdir)/psize.sh > pipesize.h
+
+psize.aux:     psize.c
+       $(CC) $(CFLAGS) -o $@ $(srcdir)/psize.c
+
+documentation: builtins.texi
+
+$(OFILES):     $(MKBUILTINS) ../config.h
+
+builtins.texi: $(MKBUILTINS)
+       ./$(MKBUILTINS) -documentonly $(DEFS)
+
+clean:
+       $(RM) $(OFILES) $(CREATED_FILES) $(MKBUILTINS)
+
+mostlyclean:
+       $(RM) $(OFILES) libbuiltins.a
+
+distclean realclean maintainer-clean: clean
+       $(RM) libbuiltins.a
+
+alias.o: alias.def
+bind.o: bind.def
+break.o: break.def
+builtin.o: builtin.def
+cd.o: cd.def
+colon.o: colon.def
+command.o: command.def
+declare.o: declare.def
+echo.o: echo.def
+enable.o: enable.def
+eval.o: eval.def
+exec.o: exec.def
+exit.o: exit.def
+fc.o: fc.def
+fg_bg.o: fg_bg.def
+hash.o: hash.def
+help.o: help.def
+history.o: history.def
+jobs.o: jobs.def
+kill.o: kill.def
+let.o: let.def
+read.o: read.def
+return.o: return.def
+set.o: set.def
+setattr.o: setattr.def
+shift.o: shift.def
+source.o: source.def
+suspend.o: suspend.def
+test.o: test.def
+times.o: times.def
+trap.o: trap.def
+type.o: type.def
+umask.o: umask.def
+wait.o: wait.def
+getopts.o: getopts.def
+reserved.o: reserved.def
+
+common.o: ../shell.h ../command.h ../config.h ../memalloc.h ../general.h
+common.o: ../variables.h ../input.h hashcom.h ../bashhist.h
+common.o: ../quit.h  ../unwind_prot.h ../maxpath.h ../jobs.h ../builtins.h
+common.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+common.o: ../execute_cmd.h ../error.h
+alias.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+alias.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+alias.o: ../shell.h ../unwind_prot.h ../variables.h common.h ../maxpath.h
+bind.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+bind.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+bind.o: ../maxpath.h
+bind.o: ../shell.h ../unwind_prot.h ../variables.h bashgetopt.h
+break.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+break.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+break.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+builtin.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+builtin.o: ../quit.h common.h ../maxpath.h
+builtin.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+builtin.o: ../shell.h ../unwind_prot.h ../variables.h 
+cd.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+cd.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+cd.o: ../shell.h ../unwind_prot.h ../variables.h common.h ../maxpath.h
+command.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+command.o: ../quit.h bashgetopt.h ../maxpath.h
+command.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+command.o: ../shell.h ../unwind_prot.h ../variables.h 
+declare.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+declare.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+declare.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+echo.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+echo.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+echo.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+enable.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+enable.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+enable.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+eval.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+eval.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+eval.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+exec.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+exec.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+exec.o: ../shell.h ../unwind_prot.h ../variables.h common.h ../execute_cmd.h
+exec.o: ../maxpath.h ../flags.h
+exit.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+exit.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+exit.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+fc.o: ../builtins.h ../command.h bashgetopt.h ../bashhist.h
+fc.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+fc.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+fc.o: ../flags.h ../unwind_prot.h ../variables.h ../shell.h ../maxpath.h
+fg_bg.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+fg_bg.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+fg_bg.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+getopts.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+getopts.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+getopts.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+hash.o: ../builtins.h ../command.h ../quit.h ../execute_cmd.h
+hash.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+hash.o: ../shell.h ../unwind_prot.h ../variables.h common.h ../maxpath.h
+help.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+help.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+help.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+history.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+history.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+history.o: ../filecntl.h ../shell.h ../unwind_prot.h ../variables.h
+history.o: ../bashhist.h ../maxpath.h
+inlib.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+inlib.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+inlib.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+jobs.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+jobs.o: ../quit.h bashgetopt.h ../maxpath.h
+jobs.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+jobs.o: ../shell.h ../unwind_prot.h ../variables.h 
+kill.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+kill.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+kill.o: ../shell.h ../trap.h ../unwind_prot.h ../variables.h ../maxpath.h
+let.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+let.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+let.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+read.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+read.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+read.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+return.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+return.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+return.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+set.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+set.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+set.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+setattr.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+setattr.o: ../quit.h common.h bashgetopt.h ../maxpath.h
+setattr.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+setattr.o: ../shell.h ../unwind_prot.h ../variables.h 
+shift.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+shift.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+shift.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+source.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+source.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+source.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+suspend.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+suspend.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+suspend.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+test.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+test.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+test.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+times.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+times.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+times.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+trap.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+trap.o: ../quit.h common.h ../maxpath.h
+trap.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+trap.o: ../shell.h ../unwind_prot.h ../variables.h ../execute_cmd.h
+type.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+type.o: ../quit.h common.h ../maxpath.h
+type.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+type.o: ../shell.h ../unwind_prot.h ../variables.h 
+ulimit.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+ulimit.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+ulimit.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+umask.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+umask.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+umask.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+wait.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
+wait.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
+wait.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
+
+bashgetopt.o: ../bashansi.h ../ansi_stdlib.h
+mkbuiltins.o: ../bashansi.h ../ansi_stdlib.h
+fc.o: ../bashansi.h ../ansi_stdlib.h
+
+#bind.o: $(RL_LIBSRC)chardefs.h $(RL_LIBSRC)readline.h $(RL_LIBSRC)keymaps.h
diff --git a/builtins/alias.def b/builtins/alias.def
new file mode 100644 (file)
index 0000000..a878c70
--- /dev/null
@@ -0,0 +1,180 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$BUILTIN alias
+$FUNCTION alias_builtin
+$DEPENDS_ON ALIAS
+$PRODUCES alias.c
+$SHORT_DOC alias [ name[=value] ... ]
+`alias' with no arguments prints the list of aliases in the form
+NAME=VALUE on standard output.  An alias is defined for each NAME
+whose VALUE is given.  A trailing space in VALUE causes the next
+word to be checked for alias substitution.  Alias returns true
+unless a NAME is given for which no alias has been defined.
+$END
+
+#include "../config.h"
+
+#if defined (ALIAS)
+#  include <stdio.h>
+#  include "../shell.h"
+#  include "../alias.h"
+#  include "common.h"
+
+extern int interactive;
+static void print_alias ();
+
+/* Hack the alias command in a Korn shell way. */
+alias_builtin (list)
+     WORD_LIST *list;
+{
+  int any_failed = 0;
+
+  if (!list)
+    {
+      register int i;
+      ASSOC **alias_list;
+
+      if (!aliases)
+       return (EXECUTION_FAILURE);
+
+      alias_list = all_aliases ();
+
+      if (!alias_list)
+       return (EXECUTION_FAILURE);
+
+      for (i = 0; alias_list[i]; i++)
+       print_alias (alias_list[i]);
+
+      free (alias_list);       /* XXX - Do not free the strings. */
+    }
+  else
+    {
+      while (list)
+       {
+         register char *value, *name = list->word->word;
+         register int offset;
+
+         for (offset = 0; name[offset] && name[offset] != '='; offset++)
+           ;
+
+         if (offset && name[offset] == '=')
+           {
+             name[offset] = '\0';
+             value = name + offset + 1;
+
+             add_alias (name, value);
+           }
+         else
+           {
+             ASSOC *t = find_alias (name);
+             if (t)
+               print_alias (t);
+             else
+               {
+                 if (interactive)
+                   builtin_error ("`%s' not found", name);
+                 any_failed++;
+               }
+           }
+         list = list->next;
+       }
+    }
+  if (any_failed)
+    return (EXECUTION_FAILURE);
+  else
+    return (EXECUTION_SUCCESS);
+}
+#endif /* ALIAS */
+
+$BUILTIN unalias
+$FUNCTION unalias_builtin
+$DEPENDS_ON ALIAS
+$SHORT_DOC unalias [-a] [name ...]
+Remove NAMEs from the list of defined aliases.  If the -a option is given,
+then remove all alias definitions.
+$END
+
+#if defined (ALIAS)
+/* Remove aliases named in LIST from the aliases database. */
+unalias_builtin (list)
+     register WORD_LIST *list;
+{
+  register ASSOC *alias;
+  int any_failed = 0;
+
+  while (list && *list->word->word == '-')
+    {
+      register char *word = list->word->word;
+
+      if (ISOPTION (word, 'a'))
+       {
+         delete_all_aliases ();
+         list = list->next;
+       }
+      else if (ISOPTION (word, '-'))
+       {
+         list = list->next;
+         break;
+       }
+      else
+       {
+         bad_option (word);
+         return (EXECUTION_FAILURE);
+       }
+    }
+
+  while (list)
+    {
+      alias = find_alias (list->word->word);
+
+      if (alias)
+       remove_alias (alias->name);
+      else
+       {
+         if (interactive)
+           builtin_error ("`%s' not an alias", list->word->word);
+
+         any_failed++;
+       }
+
+      list = list->next;
+    }
+
+  if (any_failed)
+    return (EXECUTION_FAILURE);
+  else
+    return (EXECUTION_SUCCESS);
+}
+
+/* Output ALIAS in such a way as to allow it to be read back in. */
+static void
+print_alias (alias)
+     ASSOC *alias;
+{
+  char *value = single_quote (alias->value);
+
+  printf ("alias %s=%s\n", alias->name, value);
+  free (value);
+
+  fflush (stdout);
+}
+#endif /* ALIAS */
diff --git a/builtins/bashgetopt.c b/builtins/bashgetopt.c
new file mode 100644 (file)
index 0000000..95dcaac
--- /dev/null
@@ -0,0 +1,136 @@
+/* bashgetopt.c -- `getopt' for use by the builtins. */
+
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <errno.h>
+#include "shell.h"
+
+#include "bashansi.h"
+
+#define ERR(S, C)      builtin_error("%s%c", (S), (C))
+
+static int     sp;
+
+char    *list_optarg;
+int    list_optopt;
+
+static WORD_LIST *lhead = (WORD_LIST *)NULL;
+WORD_LIST      *lcurrent = (WORD_LIST *)NULL;
+WORD_LIST      *loptend;       /* Points to the first non-option argument in the list */
+
+int
+internal_getopt(list, opts)
+WORD_LIST      *list;
+char           *opts;
+{
+       register int c;
+       register char *cp;
+
+       if (!list) {
+               list_optarg = (char *)NULL;
+               loptend = (WORD_LIST *)NULL;    /* No non-option arguments */
+               return -1;
+       }
+
+       if (list != lhead || !lhead) {
+               /* Hmmm.... called with a different word list.  Reset. */
+               sp = 1;
+               lcurrent = lhead = list;
+               loptend = (WORD_LIST *)NULL;
+       }
+
+       if (sp == 1) {
+               if (!lcurrent ||
+                   (lcurrent->word->word[0] != '-' || lcurrent->word->word[1] == '\0')) {
+                       lhead = (WORD_LIST *)NULL;
+                       loptend = lcurrent;
+                       return(-1);
+               } else if (lcurrent->word->word[0] == '-' &&
+                          lcurrent->word->word[1] == '-' &&
+                          lcurrent->word->word[2] == 0) {
+                       lhead = (WORD_LIST *)NULL;
+                       loptend = lcurrent->next;
+                       return(-1);
+               }
+       }
+
+       list_optopt = c = lcurrent->word->word[sp];
+
+       if (c == ':' || (cp = strchr(opts, c)) == NULL) {
+               ERR("illegal option: -", c);
+               if (lcurrent->word->word[++sp] == '\0') {
+                       lcurrent = lcurrent->next;
+                       sp = 1;
+               }
+               list_optarg = NULL;
+               if (lcurrent)
+                       loptend = lcurrent->next;
+               return('?');
+       }
+
+       if (*++cp == ':') {
+               /* Option requires an argument. */
+               /* We allow -l2 as equivalent to -l 2 */
+               if (lcurrent->word->word[sp+1] != '\0') {
+                       list_optarg = &(lcurrent->word->word[sp+1]);
+                       lcurrent = lcurrent->next;
+               } else if (lcurrent->next == NULL) {
+                       ERR("option requires an argument: -", c);
+                       sp = 1;
+                       list_optarg = (char *)NULL;
+                       return('?');
+               } else {
+                       lcurrent = lcurrent->next;
+                       list_optarg = lcurrent->word->word;
+                       lcurrent = lcurrent->next;
+               }
+               sp = 1;
+       } else {
+               /* No argument, just return the option. */
+               if (lcurrent->word->word[++sp] == '\0') {
+                       sp = 1;
+                       lcurrent = lcurrent->next;
+               }
+               list_optarg = (char *)NULL;
+       }
+
+       return(c);
+}
+
+/*
+ * reset_internal_getopt -- force the in[ft]ernal getopt to reset
+ */
+
+void
+reset_internal_getopt ()
+{
+       lhead = lcurrent = loptend = (WORD_LIST *)NULL;
+       sp = 1;
+}
+
+void
+report_bad_option ()
+{
+       char s[3];
+
+       s[0] = '-';
+       s[1] = list_optopt;
+       s[2] = '\0';
+       bad_option (s);
+}
diff --git a/builtins/bashgetopt.h b/builtins/bashgetopt.h
new file mode 100644 (file)
index 0000000..0360dbb
--- /dev/null
@@ -0,0 +1,37 @@
+/* bashgetopt.h -- extern declarations for stuff defined in bashgetopt.c. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* See getopt.h for the explanation of these variables. */
+
+#if !defined (__BASH_GETOPT_H)
+#  define __BASH_GETOPT_H
+
+extern char *list_optarg;
+
+extern int list_optopt;
+
+extern WORD_LIST *lcurrent;
+extern WORD_LIST *loptend;
+
+extern int internal_getopt ();
+extern void reset_internal_getopt ();
+extern void report_bad_option ();
+
+#endif /* !__BASH_GETOPT_H */
diff --git a/builtins/bind.def b/builtins/bind.def
new file mode 100644 (file)
index 0000000..cdcd6a3
--- /dev/null
@@ -0,0 +1,219 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES bind.c
+
+$BUILTIN bind
+$DEPENDS_ON READLINE
+$FUNCTION bind_builtin
+$SHORT_DOC bind [-lvd] [-m keymap] [-f filename] [-q name] [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:
+  -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,
+                     vi-command, and vi-insert.
+  -l                 List names of functions.
+  -v                 List function names and bindings.
+  -d                 Dump functions and bindings such that they
+                     can be read back in.
+  -f  filename       Read key bindings from FILENAME.
+  -q  function-name  Query about which keys invoke the named function.
+$END
+
+#include <stdio.h>
+#include "../shell.h"
+#if defined (READLINE)
+#include <errno.h>
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+#include <readline/readline.h>
+#include <readline/history.h>
+#include "bashgetopt.h"
+
+static int query_bindings ();
+
+extern int bash_readline_initialized;
+extern int no_line_editing;
+
+#define BIND_RETURN(x)  do { return_code = x; goto bind_exit; } while (0)
+
+#define USAGE "usage: bind [-lvd] [-m keymap] [-f filename] [-q name] [keyseq:readline_func]"
+
+int
+bind_builtin (list)
+     WORD_LIST *list;
+{
+  int return_code = EXECUTION_SUCCESS;
+  FILE *old_rl_outstream;
+  Keymap kmap, saved_keymap;
+  int lflag, dflag, fflag, vflag, qflag, mflag, opt;
+  char *initfile, *map_name, *fun_name;
+
+  if (no_line_editing)
+    return (EXECUTION_FAILURE);
+
+  kmap = saved_keymap = (Keymap) NULL;
+  lflag = dflag = vflag = fflag = qflag = mflag = 0;
+  initfile = map_name = fun_name = (char *)NULL;
+
+  if (!bash_readline_initialized)
+    initialize_readline ();
+
+  /* Cannot use unwind_protect_pointer () on "FILE *", it is only
+     guaranteed to work for strings. */
+  /* XXX -- see if we can use unwind_protect here */
+  old_rl_outstream = rl_outstream;
+  rl_outstream = stdout;
+
+  reset_internal_getopt ();  
+  while ((opt = internal_getopt (list, "lvdf:q:m:")) != EOF)
+    {
+      switch (opt)
+       {
+       case 'l':
+         lflag++;
+         break;
+
+       case 'v':
+         vflag++;
+         break;
+
+       case 'd':
+         dflag++;
+         break;
+
+       case 'f':
+         fflag++;
+         initfile = list_optarg;
+         break;
+
+       case 'm':
+         mflag++;
+         map_name = list_optarg;
+         break;
+
+       case 'q':
+         qflag++;
+         fun_name = list_optarg;
+         break;
+
+       default:
+         builtin_error (USAGE);
+         BIND_RETURN (EX_USAGE);
+       }
+    }
+
+  list = loptend;
+
+  /* First, see if we need to install a special keymap for this
+     command.  Then start on the arguments. */
+
+  if (mflag && map_name)
+    {
+      kmap = rl_get_keymap_by_name (map_name);
+      if (!kmap)
+        {
+          builtin_error ("`%s': illegal keymap name", map_name);
+         BIND_RETURN (EXECUTION_FAILURE);
+        }
+    }
+
+  if (kmap)
+    {
+      saved_keymap = rl_get_keymap ();
+      rl_set_keymap (kmap);
+    }
+
+  /* XXX - we need to add exclusive use tests here.  It doesn't make sense
+     to use some of these options together. */
+  /* Now hack the option arguments */
+  if (lflag)
+    rl_list_funmap_names (0);
+
+  if (vflag)
+    rl_function_dumper (0);
+
+  if (dflag)
+    rl_function_dumper (1);
+
+  if (fflag && initfile)
+    {
+      if (rl_read_init_file (initfile) != 0)
+       {
+         builtin_error ("cannot read %s: %s", initfile, strerror (errno));
+         BIND_RETURN (EXECUTION_FAILURE);
+       }
+    }
+
+  if (qflag && fun_name)
+    return_code = query_bindings (fun_name);
+
+  /* Process the rest of the arguments as binding specifications. */
+  while (list)
+    {
+      rl_parse_and_bind (list->word->word);
+      list = list->next;
+    }
+
+ bind_exit:
+  if (saved_keymap)
+    rl_set_keymap (saved_keymap);
+
+  rl_outstream = old_rl_outstream;
+  return (return_code);
+}
+
+static int
+query_bindings (name)
+     char *name;
+{
+  Function *function;
+  char **keyseqs;
+  int j;
+
+  function = rl_named_function (name);
+  if (!function)
+    {
+      builtin_error ("unknown function name `%s'", name);
+      return EXECUTION_FAILURE;
+    }
+
+  keyseqs = rl_invoking_keyseqs (function);
+
+  if (!keyseqs)
+    {
+      printf ("%s is not bound to any keys.\n", name);
+      return EXECUTION_FAILURE;
+    }
+
+  printf ("%s can be invoked via ", name);
+  for (j = 0; j < 5 && keyseqs[j]; j++)
+    printf ("\"%s\"%s", keyseqs[j], keyseqs[j + 1] ? ", " : ".\n");
+  if (keyseqs[j])
+    printf ("...\n");
+  free_array (keyseqs);
+  return EXECUTION_SUCCESS;
+}
+#endif /* READLINE */
diff --git a/builtins/break.def b/builtins/break.def
new file mode 100644 (file)
index 0000000..d72f9e3
--- /dev/null
@@ -0,0 +1,110 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES break.c
+
+$BUILTIN break
+$FUNCTION break_builtin
+$SHORT_DOC break [n]
+Exit from within a FOR, WHILE or UNTIL loop.  If N is specified,
+break N levels.
+$END
+
+#include "../shell.h"
+
+extern char *this_command_name;
+
+static int check_loop_level ();
+
+/* The depth of while's and until's. */
+int loop_level = 0;
+
+/* Non-zero when a "break" instruction is encountered. */
+int breaking = 0;
+
+/* Non-zero when we have encountered a continue instruction. */
+int continuing = 0;
+
+/* Set up to break x levels, where x defaults to 1, but can be specified
+   as the first argument. */
+break_builtin (list)
+     WORD_LIST *list;
+{
+  int newbreak;
+
+  if (!check_loop_level ())
+    return (EXECUTION_FAILURE);
+
+  newbreak = get_numeric_arg (list);
+
+  if (newbreak <= 0)
+    return (EXECUTION_FAILURE);
+
+  if (newbreak > loop_level)
+    newbreak = loop_level;
+
+  breaking = newbreak;
+
+  return (EXECUTION_SUCCESS);
+}
+
+$BUILTIN continue
+$FUNCTION continue_builtin
+$SHORT_DOC continue [n]
+Resume the next iteration of the enclosing FOR, WHILE or UNTIL loop.
+If N is specified, resume at the N-th enclosing loop.
+$END
+
+/* Set up to continue x levels, where x defaults to 1, but can be specified
+   as the first argument. */
+continue_builtin (list)
+     WORD_LIST *list;
+{
+  int newcont;
+
+  if (!check_loop_level ())
+    return (EXECUTION_FAILURE);
+
+  newcont = get_numeric_arg (list);
+
+  if (newcont <= 0)
+    return (EXECUTION_FAILURE);
+
+  if (newcont > loop_level)
+    newcont = loop_level;
+
+  continuing = newcont;
+
+  return (EXECUTION_SUCCESS);
+}
+
+/* Return non-zero if a break or continue command would be okay.
+   Print an error message if break or continue is meaningless here. */
+static int
+check_loop_level ()
+{
+#if defined (BREAK_COMPLAINS)
+  if (!loop_level)
+    builtin_error ("Only meaningful in a `for', `while', or `until' loop");
+#endif /* BREAK_COMPLAINS */
+
+  return (loop_level);
+}
diff --git a/builtins/builtin.def b/builtins/builtin.def
new file mode 100644 (file)
index 0000000..824b30d
--- /dev/null
@@ -0,0 +1,67 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES builtin.c
+
+$BUILTIN builtin
+$FUNCTION builtin_builtin
+$SHORT_DOC builtin [shell-builtin [arg ...]]
+Run a shell builtin.  This is useful when you wish to rename a
+shell builtin to be a function, but need the functionality of the
+builtin within the function itself.
+$END
+
+#include "../shell.h"
+
+#include "common.h"
+
+extern char *this_command_name;
+
+/* Run the command mentioned in list directly, without going through the
+   normal alias/function/builtin/filename lookup process. */
+builtin_builtin (list)
+     WORD_LIST *list;
+{
+  Function *function;
+  register char *command;
+
+  if (!list)
+    return (EXECUTION_SUCCESS);
+
+  command = (list->word->word);
+#if defined (DISABLED_BUILTINS)
+  function = builtin_address (command);
+#else /* !DISABLED_BUILTINS */
+  function = find_shell_builtin (command);
+#endif /* !DISABLED_BUILTINS */
+
+  if (!function)
+    {
+      builtin_error ("%s: not a shell builtin", command);
+      return (EXECUTION_FAILURE);
+    }
+  else
+    {
+      this_command_name = command;
+      list = list->next;
+      return ((*function) (list));
+    }
+}
diff --git a/builtins/cd.def b/builtins/cd.def
new file mode 100644 (file)
index 0000000..338f694
--- /dev/null
@@ -0,0 +1,689 @@
+This file is cd.def, from which is created cd.c.  It implements the
+builtins "cd", "pwd", "pushd", "popd", and "dirs" in Bash.
+
+Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES cd.c
+
+#include <stdio.h>
+#include <sys/param.h>
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include <errno.h>
+#include <tilde/tilde.h>
+
+#include "../shell.h"
+#include "../flags.h"
+#include "../maxpath.h"
+#include "common.h"
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+static int change_to_directory (), cd_to_string ();
+
+$BUILTIN cd
+$FUNCTION cd_builtin
+$SHORT_DOC cd [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 are
+separated by a colon (:).  A null directory name is the same as
+the current directory, i.e. `.'.  If DIR begins with a slash (/),
+then $CDPATH is not used.  If the directory is not found, and the
+shell variable `cdable_vars' exists, then try the word as a variable
+name.  If that variable has a value, then cd to the value of that
+variable.
+$END
+
+/* This builtin is ultimately the way that all user-visible commands should
+   change the current working directory.  It is called by cd_to_string (),
+   so the programming interface is simple, and it handles errors and
+   restrictions properly. */
+int
+cd_builtin (list)
+     WORD_LIST *list;
+{
+  char *dirname;
+
+#if defined (RESTRICTED_SHELL)
+  if (restricted)
+    {
+      builtin_error ("restricted");
+      return (EXECUTION_FAILURE);
+    }
+#endif /* RESTRICTED_SHELL */
+
+  if (list)
+    {
+      char *extract_colon_unit ();
+      char *path_string = get_string_value ("CDPATH");
+      char *path;
+      int path_index = 0, dirlen, pathlen;
+
+      dirname = list->word->word;
+
+      if (path_string && !absolute_pathname (dirname))
+       {
+         while ((path = extract_colon_unit (path_string, &path_index)))
+           {
+             char *dir;
+
+             if (*path == '~')
+               {
+                 char *te_string = tilde_expand (path);
+
+                 free (path);
+                 path = te_string;
+               }
+
+             if (!*path)
+               {
+                 free (path);
+                 path = xmalloc (2);
+                 path[0] = '.';        /* by definition. */
+                 path[1] = '\0';
+               }
+
+             dirlen = strlen (dirname);
+             pathlen = strlen (path);
+             dir = xmalloc (2 + dirlen + pathlen);
+             strcpy (dir, path);
+             if (path[pathlen - 1] != '/')
+               {
+                 dir[pathlen++] = '/';
+                 dir[pathlen] = '\0';
+               }
+             strcpy (dir + pathlen, dirname);
+             free (path);
+
+             if (change_to_directory (dir))
+               {
+                 /* replaces (strncmp (dir, "./", 2) != 0) */
+                 if (dir[0] != '.' || dir[1] != '/')
+                   printf ("%s\n", dir);
+
+                 free (dir);
+                 goto bind_and_exit;
+               }
+             else
+               free (dir);
+           }
+       }
+
+      if (!change_to_directory (dirname))
+       {
+         /* Maybe this is `cd -', equivalent to `cd $OLDPWD' */
+         if (dirname[0] == '-' && dirname[1] == '\0')
+           {
+             char *t = get_string_value ("OLDPWD");
+
+             if (t && change_to_directory (t))
+               goto bind_and_exit;
+           }
+
+         /* If the user requests it, then perhaps this is the name of
+            a shell variable, whose value contains the directory to
+            change to.  If that is the case, then change to that
+            directory. */
+         if (find_variable ("cdable_vars"))
+           {
+             char *t = get_string_value (dirname);
+
+             if (t && change_to_directory (t))
+               {
+                 printf ("%s\n", t);
+                 goto bind_and_exit;
+               }
+           }
+
+         file_error (dirname);
+         return (EXECUTION_FAILURE);
+       }
+      goto bind_and_exit;
+    }
+  else
+    {
+      dirname = get_string_value ("HOME");
+
+      if (!dirname)
+       return (EXECUTION_FAILURE);
+
+      if (!change_to_directory (dirname))
+       {
+         file_error (dirname);
+         return (EXECUTION_FAILURE);
+       }
+
+    bind_and_exit:
+      {
+       char *directory;
+
+       directory = get_working_directory ("cd");
+
+       bind_variable ("OLDPWD", get_string_value ("PWD"));
+       bind_variable ("PWD", directory);
+
+       FREE (directory);
+      }
+      return (EXECUTION_SUCCESS);
+    }
+}
+
+$BUILTIN pwd
+$FUNCTION pwd_builtin
+$SHORT_DOC pwd
+Print the current working directory.
+$END
+
+/* Non-zero means that pwd always give verbatim directory, regardless of
+   symbolic link following. */
+static int verbatim_pwd;
+
+/* Print the name of the current working directory. */
+pwd_builtin (list)
+     WORD_LIST *list;
+{
+  char *directory, *s;
+
+#if 0
+  no_args (list);
+#else
+  verbatim_pwd = no_symbolic_links;
+  if (list && (s = list->word->word) && s[0] == '-' && s[1] == 'P' && !s[2])
+    verbatim_pwd = 1;
+#endif
+
+  if (verbatim_pwd)
+    {
+      char *buffer = xmalloc (MAXPATHLEN);
+      directory = getwd (buffer);
+
+      if (!directory)
+       {
+         builtin_error ("%s", buffer);
+         free (buffer);
+       }
+    }
+  else
+    directory = get_working_directory ("pwd");
+
+  if (directory)
+    {
+      printf ("%s\n", directory);
+      fflush (stdout);
+      free (directory);
+      return (EXECUTION_SUCCESS);
+    }
+  else
+    return (EXECUTION_FAILURE);
+}
+
+$BUILTIN pushd
+$FUNCTION pushd_builtin
+$DEPENDS_ON PUSHD_AND_POPD
+$SHORT_DOC pushd [dir | +n | -n]
+Adds a directory to the top of the directory stack, or rotates
+the stack, making the new top of the stack the current working
+directory.  With no arguments, exchanges the top two directories.
+
++n     Rotates the stack so that the Nth directory (counting
+       from the left of the list shown by `dirs') is at the top.
+
+-n     Rotates the stack so that the Nth directory (counting
+       from the right) is at the top.
+
+dir    adds DIR to the directory stack at the top, making it the
+       new current working directory.
+
+You can see the directory stack with the `dirs' command.
+$END
+
+#if defined (PUSHD_AND_POPD)
+/* Some useful commands whose behaviour has been observed in Csh. */
+
+/* The list of remembered directories. */
+static char **pushd_directory_list = (char **)NULL;
+
+/* Number of existing slots in this list. */
+static int directory_list_size = 0;
+
+/* Offset to the end of the list. */
+static int directory_list_offset = 0;
+
+pushd_builtin (list)
+     WORD_LIST *list;
+{
+  char *temp, *current_directory;
+  int j = directory_list_offset - 1;
+  char direction = '+';
+
+  /* If there is no argument list then switch current and
+     top of list. */
+  if (!list)
+    {
+      if (!directory_list_offset)
+       {
+         builtin_error ("No other directory");
+         return (EXECUTION_FAILURE);
+       }
+
+      current_directory = get_working_directory ("pushd");
+      if (!current_directory)
+       return (EXECUTION_FAILURE);
+
+      temp = pushd_directory_list[j];
+      pushd_directory_list[j] = current_directory;
+      goto change_to_temp;
+    }
+  else
+    {
+      direction = *(list->word->word);
+      if (direction == '+' || direction == '-')
+       {
+         int num;
+         if (1 == sscanf (&(list->word->word)[1], "%d", &num))
+           {
+             if (direction == '-')
+               num = directory_list_offset - num;
+
+             if (num > directory_list_offset || num < 0)
+               {
+                 if (!directory_list_offset)
+                   builtin_error ("Directory stack empty");
+                 else
+                   builtin_error ("Stack contains only %d directories",
+                                   directory_list_offset + 1);
+                 return (EXECUTION_FAILURE);
+               }
+             else
+               {
+                 /* Rotate the stack num times.  Remember, the
+                    current directory acts like it is part of the
+                    stack. */
+                 temp = get_working_directory ("pushd");
+
+                 if (!num)
+                   goto change_to_temp;
+
+                 do
+                   {
+                     char *top =
+                       pushd_directory_list[directory_list_offset - 1];
+
+                     for (j = directory_list_offset - 2; j > -1; j--)
+                       pushd_directory_list[j + 1] = pushd_directory_list[j];
+
+                     pushd_directory_list[j + 1] = temp;
+
+                     temp = top;
+                     num--;
+                   }
+                 while (num);
+
+                 temp = savestring (temp);
+               change_to_temp:
+                 {
+                   int tt = EXECUTION_FAILURE;
+
+                   if (temp)
+                     {
+                       tt = cd_to_string (temp);
+                       free (temp);
+                     }
+
+                   if ((tt == EXECUTION_SUCCESS))
+                     dirs_builtin ((WORD_LIST *)NULL);
+
+                   return (tt);
+                 }
+               }
+           }
+       }
+
+      /* Change to the directory in list->word->word.  Save the current
+        directory on the top of the stack. */
+      current_directory = get_working_directory ("pushd");
+      if (!current_directory)
+       return (EXECUTION_FAILURE);
+
+      if (cd_builtin (list) == EXECUTION_SUCCESS)
+       {
+         if (directory_list_offset == directory_list_size)
+           {
+             pushd_directory_list = (char **)
+               xrealloc (pushd_directory_list,
+                         (directory_list_size += 10) * sizeof (char *));
+           }
+         pushd_directory_list[directory_list_offset++] = current_directory;
+
+         dirs_builtin ((WORD_LIST *)NULL);
+
+         return (EXECUTION_SUCCESS);
+       }
+      else
+       {
+         free (current_directory);
+         return (EXECUTION_FAILURE);
+       }
+    }
+}
+#endif /* PUSHD_AND_POPD */
+
+$BUILTIN dirs
+$FUNCTION dirs_builtin
+$DEPENDS_ON PUSHD_AND_POPD
+$SHORT_DOC dirs [-l]
+Display the list of currently remembered directories.  Directories
+find their way onto the list with the `pushd' command; you can get
+back up through the list with the `popd' command.
+
+The -l flag specifies that `dirs' should not print shorthand versions
+of directories which are relative to your home directory.  This means
+that `~/bin' might be displayed as `/homes/bfox/bin'.
+$END
+
+#if defined (PUSHD_AND_POPD)
+/* Print the current list of directories on the directory stack. */
+dirs_builtin (list)
+     WORD_LIST *list;
+{
+  int i, format, desired_index, index_flag;
+  char *temp, *w;
+
+  format = index_flag = 0;
+  desired_index = -1;
+  /* Maybe do long form or print specific dir stack entry? */
+  while (list)
+    {
+      if (strcmp (list->word->word, "-l") == 0)
+       {
+         format++;
+         list = list->next;
+       }
+      else if (*list->word->word == '+' && all_digits (list->word->word + 1))
+       {
+         w = list->word->word + 1;
+         index_flag = 1;
+         i = atoi (w);
+         /* dirs +0 prints the current working directory. */
+         if (i == 0)
+           desired_index = i;
+         else if (i == directory_list_offset)
+           {
+             desired_index = 0;
+             index_flag = 2;
+           }
+         else
+           desired_index = directory_list_offset - i;
+         list = list->next;
+       }
+      else if (*list->word->word == '-' && all_digits (list->word->word + 1))
+       {
+         w = list->word->word + 1;
+         i = atoi (w);
+         index_flag = 2;
+         /* dirs -X where X is directory_list_offset prints the current
+            working directory. */
+         if (i == directory_list_offset)
+           {
+             index_flag = 1;
+             desired_index = 0;
+           }
+         else
+           desired_index = i;
+         list = list->next;
+       }
+      else
+       {
+         bad_option (list->word->word);
+         return (EXECUTION_FAILURE);
+       }
+    }
+
+  if (index_flag && (desired_index < 0 || desired_index > directory_list_offset))
+    {
+      if (directory_list_offset == 0)
+       builtin_error ("directory stack empty");
+      else
+       builtin_error ("%s: bad directory stack index", w);
+      return (EXECUTION_FAILURE);
+    }
+
+  /* The first directory printed is always the current working directory. */
+  if (!index_flag || (index_flag == 1 && desired_index == 0))
+    {
+      temp = get_working_directory ("dirs");
+      if (!temp)
+       temp = savestring ("<no directory>");
+      printf ("%s", format ? temp : polite_directory_format (temp));
+      free (temp);
+      if (index_flag)
+       {
+         putchar ('\n');
+         return EXECUTION_SUCCESS;
+       }
+    }
+
+#define DIRSTACK_ENTRY(i) \
+       format ? pushd_directory_list[i] \
+              : polite_directory_format (pushd_directory_list[i])
+
+  /* Now print the requested directory stack entries. */
+  if (index_flag)
+    printf ("%s", DIRSTACK_ENTRY (desired_index));
+  else
+    for (i = (directory_list_offset - 1); i > -1; i--)
+      printf (" %s", DIRSTACK_ENTRY (i));
+
+  putchar ('\n');
+  fflush (stdout);
+  return (EXECUTION_SUCCESS);
+}
+#endif /* PUSHD_AND_POPD */
+
+$BUILTIN popd
+$FUNCTION popd_builtin
+$DEPENDS_ON PUSHD_AND_POPD
+$SHORT_DOC popd [+n | -n]
+Removes entries from the directory stack.  With no arguments,
+removes the top directory from the stack, and cd's to the new
+top directory.
+
++n     removes the Nth entry counting from the left of the list
+       shown by `dirs', starting with zero.  For example: `popd +0'
+       removes the first directory, `popd +1' the second.
+
+-n     removes the Nth entry counting from the right of the list
+       shown by `dirs', starting with zero.  For example: `popd -0'
+       removes the last directory, `popd -1' the next to last.
+
+You can see the directory stack with the `dirs' command.
+$END
+
+#if defined (PUSHD_AND_POPD)
+/* Pop the directory stack, and then change to the new top of the stack.
+   If LIST is non-null it should consist of a word +N or -N, which says
+   what element to delete from the stack.  The default is the top one. */
+popd_builtin (list)
+     WORD_LIST *list;
+{
+  register int i;
+  int which = 0;
+  char direction = '+';
+
+  if (list)
+    {
+      direction = *(list->word->word);
+
+      if ((direction != '+' && direction != '-') ||
+         (1 != sscanf (&((list->word->word)[1]), "%d", &which)))
+       {
+         builtin_error ("bad arg `%s'", list->word->word);
+         return (EXECUTION_FAILURE);
+       }
+    }
+
+  if (which > directory_list_offset || (!directory_list_offset && !which))
+    {
+      if (!directory_list_offset)
+       builtin_error ("Directory stack empty");
+      else
+       builtin_error ("Stack contains only %d directories",
+                       directory_list_offset + 1);
+      return (EXECUTION_FAILURE);
+    }
+
+  /* Handle case of no specification, or top of stack specification. */
+  if ((direction == '+' && which == 0) ||
+      (direction == '-' && which == directory_list_offset))
+    {
+      i = cd_to_string (pushd_directory_list[directory_list_offset - 1]);
+      if (i != EXECUTION_SUCCESS)
+       return (i);
+      free (pushd_directory_list[--directory_list_offset]);
+    }
+  else
+    {
+      /* Since an offset other than the top directory was specified,
+        remove that directory from the list and shift the remainder
+        of the list into place. */
+
+      if (direction == '+')
+       i = directory_list_offset - which;
+      else
+       i = which;
+
+      free (pushd_directory_list[i]);
+      directory_list_offset--;
+
+      /* Shift the remainder of the list into place. */
+      for (; i < directory_list_offset; i++)
+       pushd_directory_list[i] = pushd_directory_list[i + 1];
+    }
+
+  dirs_builtin ((WORD_LIST *)NULL);
+
+  return (EXECUTION_SUCCESS);
+}
+#endif /* PUSHD_AND_POPD */
+
+/* Do the work of changing to the directory NEWDIR.  Handle symbolic
+   link following, etc. */
+
+static int
+change_to_directory (newdir)
+     char *newdir;
+{
+  char *t;
+
+  if (!no_symbolic_links)
+    {
+      int chdir_return = 0;
+      char *tdir = (char *)NULL;
+
+      if (!the_current_working_directory)
+       {
+         t = get_working_directory ("cd_links");
+         FREE (t);
+       }
+
+      if (the_current_working_directory)
+       t = make_absolute (newdir, the_current_working_directory);
+      else
+       t = savestring (newdir);
+
+      /* TDIR is the canonicalized absolute pathname of the NEWDIR. */
+      tdir = canonicalize_pathname (t);
+
+      /* Use the canonicalized version of NEWDIR, or, if canonicalization
+        failed, use the non-canonical form. */
+      if (tdir && *tdir)
+       free (t);
+      else
+       {
+         FREE (tdir);
+
+         tdir = t;
+       }
+
+      if (chdir (tdir) < 0)
+       {
+         int err;
+
+         chdir_return = 0;
+         free (tdir);
+
+         err = errno;
+
+         /* We failed changing to the canonicalized directory name.  Try
+            what the user passed verbatim.  If we succeed, reinitialize
+            the_current_working_directory. */
+         if (chdir (newdir) == 0)
+           {
+             chdir_return = 1;
+             if (the_current_working_directory)
+               {
+                 free (the_current_working_directory);
+                 the_current_working_directory = (char *)NULL;
+               }
+
+             tdir = get_working_directory ("cd");
+             FREE (tdir);
+           }
+         else
+           errno = err;
+       }
+      else
+       {
+         chdir_return = 1;
+
+         FREE (the_current_working_directory);
+         the_current_working_directory = tdir;
+       }
+
+      return (chdir_return);
+    }
+  else
+    {
+      if (chdir (newdir) < 0)
+       return (0);
+      else
+       return (1);
+    }
+}
+
+/* Switch to the directory in NAME.  This uses the cd_builtin to do the work,
+   so if the result is EXECUTION_FAILURE then an error message has already
+   been printed. */
+static int
+cd_to_string (name)
+     char *name;
+{
+  WORD_LIST *tlist = make_word_list (make_word (name), NULL);
+  int result = (cd_builtin (tlist));
+  dispose_words (tlist);
+  return (result);
+}
diff --git a/builtins/colon.def b/builtins/colon.def
new file mode 100644 (file)
index 0000000..4ae5b65
--- /dev/null
@@ -0,0 +1,37 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES colon.c
+
+$BUILTIN :
+$DOCNAME colon_builtin
+$FUNCTION colon_builtin
+$SHORT_DOC :
+No effect; the command does nothing.  A zero exit code is returned.
+$END
+
+/* Do nothing.  This command is a no-op. */
+int
+colon_builtin (ignore)
+     char *ignore;
+{
+  return (0);
+}
diff --git a/builtins/command.def b/builtins/command.def
new file mode 100644 (file)
index 0000000..b84613e
--- /dev/null
@@ -0,0 +1,177 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES command.c
+
+$BUILTIN command
+$FUNCTION command_builtin
+$SHORT_DOC command [-pVv] [command [arg ...]]
+Runs COMMAND with ARGS ignoring shell functions.  If you have a shell
+function called `ls', and you wish to call the command `ls', you can
+say "command ls".  If the -p option is given, a default value is used
+for PATH that is guaranteed to find all of the standard utilities.  If
+the -V or -v option is given, a string is printed describing COMMAND.
+The -V option produces a more verbose description.
+$END
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "../shell.h"
+#include "bashgetopt.h"
+
+extern int subshell_environment;
+
+static void restore_path ();
+static char *get_standard_path ();
+
+/* Run the commands mentioned in LIST without paying attention to shell
+   functions. */
+int
+command_builtin (list)
+     WORD_LIST *list;
+{
+  int result, verbose = 0, use_standard_path = 0, opt;
+  char *old_path;
+  
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, "pvV")) != -1)
+    {
+      switch (opt)
+       {
+       case 'p':
+         use_standard_path = 1;
+         break;
+       case 'V':
+         verbose = 2;
+         break;
+       case 'v':
+         verbose = 4;
+         break;
+
+       default:
+         report_bad_option ();
+         builtin_error ("usage: command [-pvV] [command [arg...]]");
+         return (EX_USAGE);
+       }
+    }
+  list = loptend;
+
+  if (!list)
+    return (EXECUTION_SUCCESS);
+
+  if (verbose)
+    {
+      int found, any_found = 0;
+
+      while (list)
+       {
+
+         found = describe_command (list->word->word, verbose, 0);
+
+         if (!found)
+           builtin_error ("%s: not found", list->word->word);
+
+         any_found += found;
+         list = list->next;
+       }
+      return (any_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
+    }
+
+  begin_unwind_frame ("command_builtin");
+
+  /* We don't want this to be reparsed (consider command echo 'foo &'), so
+     just make a simple_command structure and call execute_command with it. */
+  {
+    COMMAND *command;
+
+    if (use_standard_path)
+      {
+       char *standard_path;
+
+       old_path = get_string_value ("PATH");
+       if (old_path)
+         old_path = savestring (old_path);
+       else
+         old_path = savestring ("");
+       add_unwind_protect ((Function *)restore_path, old_path);
+
+       standard_path = get_standard_path ();
+       bind_variable ("PATH", standard_path);
+       free (standard_path);
+      }
+    command = make_bare_simple_command ();
+    command->value.Simple->words = (WORD_LIST *)copy_word_list (list);
+    command->value.Simple->redirects = (REDIRECT *)NULL;
+    command->flags |= (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION);
+    command->value.Simple->flags |= (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION);
+    /* If we're in a subshell, see if we can get away without forking
+       again, since we've already forked to run this builtin. */
+    if (subshell_environment)
+      {
+       command->flags |= CMD_NO_FORK;
+       command->value.Simple->flags |= CMD_NO_FORK;
+      }
+    add_unwind_protect ((char *)dispose_command, command);
+    result = execute_command (command);
+  }
+
+  run_unwind_frame ("command_builtin");
+
+  return (result);
+}
+
+/* Restore the value of the $PATH variable after replacing it when
+   executing `command -p'. */
+static void
+restore_path (var)
+     char *var;
+{
+  bind_variable ("PATH", var);
+  free (var);
+}
+
+/* Return a value for PATH that is guaranteed to find all of the standard
+   utilities.  This uses Posix.2 configuration variables, if present.  It
+   uses a value defined in config.h as a last resort. */
+static char *
+get_standard_path ()
+{
+#if defined (_CS_PATH) && !defined (hpux_7) && !defined (NetBSD)
+  char *p;
+  size_t len;
+
+  len = (size_t)confstr (_CS_PATH, (char *)NULL, (size_t)0);
+  p = xmalloc ((int)len + 2);
+  *p = '\0';
+  confstr (_CS_PATH, p, len);
+  return (p);
+#else /* !_CSPATH || hpux_7 || NetBSD */
+#  if defined (CS_PATH)
+  return (savestring (CS_PATH));
+#  else
+  return (savestring (STANDARD_UTILS_PATH));
+#  endif /* !CS_PATH */
+#endif /* !_CS_PATH || hpux_7 */
+}
diff --git a/builtins/common.c b/builtins/common.c
new file mode 100644 (file)
index 0000000..ff940b5
--- /dev/null
@@ -0,0 +1,829 @@
+/* Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 1, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+   
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "../posixstat.h"
+#if defined (HAVE_VFPRINTF)
+#include <varargs.h>
+#endif /* VFPRINTF */
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "../shell.h"
+#include "../unwind_prot.h"
+#include "../maxpath.h"
+#include "../jobs.h"
+#include "../builtins.h"
+#include "../input.h"
+#include "../execute_cmd.h"
+#include "hashcom.h"
+#include "common.h"
+#include <tilde/tilde.h>
+
+#if defined (HISTORY)
+#  include "../bashhist.h"
+#endif
+
+extern int no_symbolic_links, interactive, interactive_shell;
+extern int indirection_level, startup_state;
+extern int last_command_exit_value;
+extern int hashing_disabled;
+extern int variable_context;
+extern char *this_command_name, *shell_name;
+extern COMMAND *global_command;
+extern HASH_TABLE *hashed_filenames;
+
+/* Read a numeric arg for this_command_name, the name of the shell builtin
+   that wants it.  LIST is the word list that the arg is to come from. */
+int
+get_numeric_arg (list)
+     WORD_LIST *list;
+{
+  int count = 1;
+
+  if (list)
+    {
+      register char *arg;
+      int sign = 1;
+
+      arg = list->word->word;
+      if (!arg)
+       goto bad_number;
+
+      /* Skip optional leading white space. */
+      while (whitespace (*arg))
+       arg++;
+
+      if (!*arg)
+        goto bad_number;
+
+      /* We allow leading `-' or `+'. */
+      if (*arg == '-' || *arg == '+')
+       {
+         if (!digit (arg[1]))
+           goto bad_number;
+
+         if (*arg == '-')
+           sign = -1;
+
+         arg++;
+       }
+
+      for (count = 0; digit (*arg); arg++)
+       count = (count * 10) + digit_value (*arg);
+
+      /* Skip trailing whitespace, if any. */
+      while (whitespace (*arg))
+        arg++;
+
+      if (!*arg)
+        count = count * sign;
+      else
+       {
+  bad_number:
+         builtin_error ("bad non-numeric arg `%s'", list->word->word);
+         throw_to_top_level ();
+       }
+      no_args (list->next);
+    }
+  return (count);
+}
+
+/* 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 (HAVE_VFPRINTF)
+void
+builtin_error (va_alist)
+     va_dcl
+{
+  char *format;
+  va_list args;
+
+  if (this_command_name && *this_command_name)
+    fprintf (stderr, "%s: ", this_command_name);
+
+  va_start (args);
+  format = va_arg (args, char *);
+  vfprintf (stderr, format, args);
+  va_end (args);
+  fprintf (stderr, "\n");
+}
+#else /* !HAVE_VFPRINTF */
+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 /* !HAVE_VFPRINTF */
+
+/* Remember LIST in $0 ... $9, and REST_OF_ARGS.  If DESTRUCTIVE is
+   non-zero, then discard whatever the existing arguments are, else
+   only discard the ones that are to be replaced. */
+void
+remember_args (list, destructive)
+     WORD_LIST *list;
+     int destructive;
+{
+  register int i;
+
+  for (i = 1; i < 10; i++)
+    {
+      if (destructive && dollar_vars[i])
+       {
+         free (dollar_vars[i]);
+         dollar_vars[i] = (char *)NULL;
+       }
+
+      if (list)
+       {
+         if (!destructive && dollar_vars[i])
+           free (dollar_vars[i]);
+
+         dollar_vars[i] = savestring (list->word->word);
+         list = list->next;
+       }
+    }
+
+  /* If arguments remain, assign them to REST_OF_ARGS.
+     Note that copy_word_list (NULL) returns NULL, and
+     that dispose_words (NULL) does nothing. */
+  if (destructive || list)
+    {
+      dispose_words (rest_of_args);
+      rest_of_args = copy_word_list (list);
+    }
+
+  if (destructive)
+    set_dollar_vars_changed ();
+}
+
+/* Return if LIST is NULL else barf and jump to top_level. */
+void
+no_args (list)
+     WORD_LIST *list;
+{
+  if (list)
+    {
+      builtin_error ("extra arguments");
+      longjmp (top_level, DISCARD);
+    }
+}
+
+/* Return the octal number parsed from STRING, or -1 to indicate
+   that the string contained a bad number. */
+int
+read_octal (string)
+     char *string;
+{
+  int result = 0;
+  int digits = 0;
+
+  while (*string && *string >= '0' && *string < '8')
+    {
+      digits++;
+      result = (result * 8) + *string++ - '0';
+    }
+
+  if (!digits || result > 0777 || *string)
+    result = -1;
+
+  return (result);
+}
+
+/* Temporary static. */
+static char *dotted_filename = (char *)NULL;
+
+/* Return the full pathname that FILENAME hashes to.  If FILENAME
+   is hashed, but data->check_dot is non-zero, check ./FILENAME
+   and return that if it is executable. */
+char *
+find_hashed_filename (filename)
+     char *filename;
+{
+  register BUCKET_CONTENTS *item;
+
+  if (hashing_disabled)
+    return ((char *)NULL);
+
+  item = find_hash_item (filename, hashed_filenames);
+
+  if (item)
+    {
+      /* If this filename is hashed, but `.' comes before it in the path,
+        then see if `./filename' is an executable. */
+      if (pathdata(item)->check_dot)
+       {
+         if (dotted_filename)
+           free (dotted_filename);
+
+         dotted_filename = (char *)xmalloc (3 + strlen (filename));
+         strcpy (dotted_filename, "./");
+         strcat (dotted_filename, filename);
+
+         if (executable_file (dotted_filename))
+           return (dotted_filename);
+
+         /* Watch out.  If this file was hashed to "./filename", and
+            "./filename" is not executable, then return NULL. */
+
+         /* Since we already know "./filename" is not executable, what
+            we're really interested in is whether or not the `path'
+            portion of the hashed filename is equivalent to the current
+            directory, but only if it starts with a `.'.  (This catches
+            ./. and so on.)  same_file () is in execute_cmd.c; it tests
+            general Unix file equivalence -- same device and inode. */
+         {
+           char *path = pathdata (item)->path;
+
+           if (*path == '.')
+             {
+               int same = 0;
+               char *tail;
+
+               tail = (char *) strrchr (path, '/');
+
+               if (tail)
+                 {
+                   *tail = '\0';
+                   same = same_file
+                     (".", path, (struct stat *)NULL, (struct stat *)NULL);
+                   *tail = '/';
+                 }
+               if (same)
+                 return ((char *)NULL);
+             }
+         }
+       }
+      return (pathdata (item)->path);
+    }
+  else
+    return ((char *)NULL);
+}
+
+/* Remove FILENAME from the table of hashed commands. */
+void
+remove_hashed_filename (filename)
+     char *filename;
+{
+  register BUCKET_CONTENTS *item;
+
+  if (hashing_disabled)
+    return;
+
+  item = remove_hash_item (filename, hashed_filenames);
+  if (item)
+    {
+      if (item->data)
+        {
+         free (pathdata(item)->path);
+         free (item->data);
+        }
+      if (item->key)
+       free (item->key);
+      free (item);
+    }
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                 Pushing and Popping a Context                   */
+/*                                                                 */
+/* **************************************************************** */
+
+static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
+static int dollar_arg_stack_slots = 0;
+static int dollar_arg_stack_index = 0;
+
+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)
+    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)
+    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 = 0;
+
+/* Have the dollar variables been reset to new values since we last
+   checked? */
+dollar_vars_changed ()
+{
+  return (changed_dollar_vars);
+}
+
+void
+set_dollar_vars_unchanged ()
+{
+  changed_dollar_vars = 0;
+}
+
+void
+set_dollar_vars_changed ()
+{
+  changed_dollar_vars  = 1;
+}
+
+/* Function called when one of the builtin commands detects a bad
+   option. */
+void
+bad_option (s)
+     char *s;
+{
+  builtin_error ("unknown option: %s", s);
+}
+
+/* Return a consed string which is the current working directory.
+   FOR_WHOM is the name of the caller for error printing.  */
+char *the_current_working_directory = (char *)NULL;
+
+char *
+get_working_directory (for_whom)
+     char *for_whom;
+{
+  if (no_symbolic_links)
+    {
+      if (the_current_working_directory)
+       free (the_current_working_directory);
+
+      the_current_working_directory = (char *)NULL;
+    }
+
+  if (!the_current_working_directory)
+    {
+      char *directory;
+
+      the_current_working_directory = xmalloc (MAXPATHLEN);
+      directory = getwd (the_current_working_directory);
+      if (!directory)
+       {
+         if (for_whom && *for_whom)
+           fprintf (stderr, "%s: ", for_whom);
+         else
+           fprintf (stderr, "%s: ", get_name_for_error ());
+
+         fprintf (stderr, "could not get current directory: %s\n",
+                  the_current_working_directory);
+
+         free (the_current_working_directory);
+         the_current_working_directory = (char *)NULL;
+         return (char *)NULL;
+       }
+    }
+
+  return (savestring (the_current_working_directory));
+}
+
+/* Make NAME our internal idea of the current working directory. */
+void
+set_working_directory (name)
+     char *name;
+{
+  if (the_current_working_directory)
+    free (the_current_working_directory);
+
+  the_current_working_directory = savestring (name);
+}
+
+#if defined (JOB_CONTROL)
+/* Return the job spec found in LIST. */
+get_job_spec (list)
+     WORD_LIST *list;
+{
+  register char *word;
+  int job = NO_JOB;
+  int substring = 0;
+
+  if (!list)
+    return (current_job);
+
+  word = list->word->word;
+
+  if (!*word)
+    return (current_job);
+
+  if (*word == '%')
+    word++;
+
+  if (digit (*word) && (sscanf (word, "%d", &job) == 1))
+    return (job - 1);
+
+  switch (*word)
+    {
+    case 0:
+    case '%':
+    case '+':
+      return (current_job);
+
+    case '-':
+      return (previous_job);
+
+    case '?':                  /* Substring search requested. */
+      substring++;
+      word++;
+      goto find_string;
+
+    default:
+    find_string:
+      {
+       register int i, wl = strlen (word);
+       for (i = 0; i < job_slots; i++)
+         {
+           if (jobs[i])
+             {
+               register PROCESS *p = jobs[i]->pipe;
+               do
+                 {
+                   if ((substring && strindex (p->command, word)) ||
+                       (strncmp (p->command, word, wl) == 0))
+                     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);
+      }
+    }
+}
+#endif /* JOB_CONTROL */
+
+int parse_and_execute_level = 0;
+
+/* How to force parse_and_execute () to clean up after itself. */
+void
+parse_and_execute_cleanup ()
+{
+  run_unwind_frame ("parse_and_execute_top");
+}
+
+/* Parse and execute the commands in STRING.  Returns whatever
+   execute_command () returns.  This frees STRING.  INTERACT is
+   the new value for `interactive' while the commands are being
+   executed.  A value of -1 means don't change it. */
+int
+parse_and_execute (string, from_file, interact)
+     char *string;
+     char *from_file;
+     int interact;
+{
+  int last_result = EXECUTION_SUCCESS;
+  int code = 0, jump_to_top_level = 0;
+  char *orig_string = string;
+
+  /* Unwind protect this invocation of parse_and_execute (). */
+  begin_unwind_frame ("parse_and_execute_top");
+  unwind_protect_int (parse_and_execute_level);
+  unwind_protect_jmp_buf (top_level);
+  unwind_protect_int (indirection_level);
+  if (interact != -1 && interactive != interact)
+    unwind_protect_int (interactive);
+
+#if defined (HISTORY)
+  if (interactive_shell)
+    {
+      unwind_protect_int (remember_on_history);
+#  if defined (BANG_HISTORY)
+      unwind_protect_int (history_expansion_inhibited);
+#  endif /* BANG_HISTORY */
+    }
+#endif /* HISTORY */
+
+  add_unwind_protect (pop_stream, (char *)NULL);
+  if (orig_string)
+    add_unwind_protect (xfree, orig_string);
+  end_unwind_frame ();
+
+  parse_and_execute_level++;
+  push_stream ();
+  indirection_level++;
+  if (interact != -1)
+    interactive = interact;
+
+#if defined (HISTORY)
+  /* We don't remember text read by the shell this way on
+     the history list, and we don't use !$ in shell scripts. */
+  remember_on_history = 0;
+#  if defined (BANG_HISTORY)
+  history_expansion_inhibited = 1;
+#  endif /* BANG_HISTORY */
+#endif /* HISTORY */
+
+  with_input_from_string (string, from_file);
+  {
+    COMMAND *command;
+
+    while (*(bash_input.location.string))
+      {
+       if (interrupt_state)
+         {
+           last_result = EXECUTION_FAILURE;
+           break;
+         }
+
+       /* Provide a location for functions which `longjmp (top_level)' to
+          jump to.  This prevents errors in substitution from restarting
+          the reader loop directly, for example. */
+       code = setjmp (top_level);
+
+       if (code)
+         {
+           jump_to_top_level = 0;
+           switch (code)
+             {
+             case FORCE_EOF:
+             case EXITPROG:
+               run_unwind_frame ("pe_dispose");
+               /* Remember to call longjmp (top_level) after the old
+                  value for it is restored. */
+               jump_to_top_level = 1;
+               goto out;
+
+             case DISCARD:
+               dispose_command (command);
+               run_unwind_frame ("pe_dispose");
+               last_command_exit_value = 1;
+               continue;
+
+             default:
+               programming_error ("bad jump to top_level: %d", code);
+               break;
+             }
+         }
+         
+       if (parse_command () == 0)
+         {
+           if ((command = global_command) != (COMMAND *)NULL)
+             {
+               struct fd_bitmap *bitmap;
+
+               bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
+               begin_unwind_frame ("pe_dispose");
+               add_unwind_protect (dispose_fd_bitmap, bitmap);
+
+               global_command = (COMMAND *)NULL;
+
+#if defined (ONESHOT)
+               if (startup_state == 2 && *bash_input.location.string == '\0' &&
+                   command->type == cm_simple && !command->redirects &&
+                   !command->value.Simple->redirects)
+                 {
+                   command->flags |= CMD_NO_FORK;
+                   command->value.Simple->flags |= CMD_NO_FORK;
+                 }
+#endif /* ONESHOT */
+    
+               last_result = execute_command_internal
+                   (command, 0, NO_PIPE, NO_PIPE, bitmap);
+
+               dispose_command (command);
+               run_unwind_frame ("pe_dispose");
+             }
+         }
+       else
+         {
+           last_result = EXECUTION_FAILURE;
+
+           /* Since we are shell compatible, syntax errors in a script
+              abort the execution of the script.  Right? */
+           break;
+         }
+      }
+  }
+
+ out:
+
+  run_unwind_frame ("parse_and_execute_top");
+
+  if (interrupt_state && parse_and_execute_level == 0)
+    {
+      /* An interrupt during non-interactive execution in an
+         interactive shell (e.g. via $PROMPT_COMMAND) should
+         not cause the shell to exit. */
+      interactive = interactive_shell;
+      throw_to_top_level ();
+    }
+
+  if (jump_to_top_level)
+    longjmp (top_level, code);
+
+  return (last_result);
+}
+
+/* Return the address of the builtin named NAME.
+   DISABLED_OKAY means find it even if the builtin is disabled. */
+static Function *
+builtin_address_internal (name, disabled_okay)
+     char *name;
+     int disabled_okay;
+{
+  int hi, lo, mid, j;
+
+  hi = num_shell_builtins - 1;
+  lo = 0;
+
+  while (lo <= hi)
+    {
+      mid = (lo + hi) / 2;
+
+      j = shell_builtins[mid].name[0] - name[0];
+
+      if (j == 0)
+       j = strcmp (shell_builtins[mid].name, name);
+
+      if (j == 0)
+       {
+         /* It must have a function pointer.  It must be enabled, or we
+            must have explicitly allowed disabled functions to be found. */
+         if (shell_builtins[mid].function &&
+             ((shell_builtins[mid].flags & BUILTIN_ENABLED) || disabled_okay))
+           return (shell_builtins[mid].function);
+         else
+           return ((Function *)NULL);
+       }
+      if (j > 0)
+       hi = mid - 1;
+      else
+       lo = mid + 1;
+    }
+  return ((Function *)NULL);
+}
+
+/* Perform a binary search and return the address of the builtin function
+   whose name is NAME.  If the function couldn't be found, or the builtin
+   is disabled or has no function associated with it, return NULL. */
+Function *
+find_shell_builtin (name)
+       char *name;
+{
+  return (builtin_address_internal (name, 0));
+}
+
+/* Return the address of builtin with NAME, irregardless of its state of
+   enableness. */
+Function *
+builtin_address (name)
+     char *name;
+{
+  return (builtin_address_internal (name, 1));
+}
+
+static int
+shell_builtin_compare (sbp1, sbp2)
+     struct builtin *sbp1, *sbp2;
+{
+  int result;
+
+  if ((result = sbp1->name[0] - sbp2->name[0]) == 0)
+    result = strcmp (sbp1->name, sbp2->name);
+
+  return (result);
+}
+
+/* Sort the table of shell builtins so that the binary search will work
+   in find_shell_builtin. */
+void
+initialize_shell_builtins ()
+{
+  qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin),
+    shell_builtin_compare);
+}
+
+/* Return a new string which is the quoted version of STRING.  This is used
+   by alias and trap. */
+char *
+single_quote (string)
+     char *string;
+{
+  register int i, j, c;
+  char *result;
+
+  result = (char *)xmalloc (3 + (3 * strlen (string)));
+
+  result[0] = '\'';
+
+  for (i = 0, j = 1; string && (c = string[i]); i++)
+    {
+      result[j++] = c;
+
+      if (c == '\'')
+       {
+         result[j++] = '\\';   /* insert escaped single quote */
+         result[j++] = '\'';
+         result[j++] = '\'';   /* start new quoted string */
+       }
+    }
+
+  result[j++] = '\'';
+  result[j] = '\0';
+
+  return (result);
+}
+
+char *
+double_quote (string)
+     char *string;
+{
+  register int i, j, c;
+  char *result;
+
+  result = (char *)xmalloc (3 + (3 * strlen (string)));
+
+  result[0] = '"';
+
+  for (i = 0, j = 1; string && (c = string[i]); i++)
+    {
+      switch (c)
+        {
+       case '"':
+       case '$':
+       case '`':
+       case '\\':
+         result[j++] = '\\';
+       default:
+         result[j++] = c;
+         break;
+        }
+    }
+
+  result[j++] = '"';
+  result[j] = '\0';
+
+  return (result);
+}
diff --git a/builtins/common.h b/builtins/common.h
new file mode 100644 (file)
index 0000000..c7c99e7
--- /dev/null
@@ -0,0 +1,69 @@
+/* common.h -- extern declarations for functions defined in common.c. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if  !defined (__COMMON_H)
+#  define __COMMON_H
+
+#define ISOPTION(s, c) (s[0] == '-' && !s[2] && s[1] == c)
+
+extern void builtin_error ();
+extern void bad_option ();
+
+extern int get_numeric_arg ();
+
+extern void remember_args ();
+
+extern void no_args ();
+
+extern int read_octal ();
+
+extern char *find_hashed_filename ();
+extern void remove_hashed_filename ();
+extern void remember_filename ();
+
+extern void push_context (), pop_context ();
+extern void push_dollar_vars (), pop_dollar_vars ();
+extern void dispose_saved_dollar_vars ();
+extern int dollar_vars_changed ();
+extern void set_dollar_vars_unchanged (), set_dollar_vars_changed ();
+
+/* Keeps track of the current working directory. */
+extern char *the_current_working_directory;
+extern char *get_working_directory ();
+extern void set_working_directory ();
+
+#if defined (JOB_CONTROL)
+extern int get_job_spec ();
+#endif
+
+extern int parse_and_execute ();
+extern void parse_and_execute_cleanup ();
+
+extern void initialize_shell_builtins ();
+
+/* It's OK to declare a function as returning a Function * without
+   providing a definition of what a `Function' is. */
+extern Function *find_shell_builtin ();
+extern Function *builtin_address ();
+
+extern char *single_quote ();
+extern char *double_quote ();
+
+#endif /* !__COMMON_H */
diff --git a/builtins/declare.def b/builtins/declare.def
new file mode 100644 (file)
index 0000000..17b7ea2
--- /dev/null
@@ -0,0 +1,290 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES declare.c
+
+$BUILTIN declare
+$FUNCTION declare_builtin
+$SHORT_DOC declare [-[frxi]] name[=value] ...
+Declare variables and/or give them attributes.  If no NAMEs are
+given, then display the values of variables instead.
+
+The flags are:
+
+  -f   to select from among function names only,
+  -r   to make NAMEs readonly,
+  -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.
+
+Using `+' instead of `-' turns off the given attribute instead.  When
+used in a function, makes NAMEs local, as with the `local' command.
+$END
+
+$BUILTIN typeset
+$FUNCTION declare_builtin
+$SHORT_DOC typeset [-[frxi]] name[=value] ...
+Obsolete.  See `declare'.
+$END
+
+#include <stdio.h>
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "../shell.h"
+
+extern int variable_context, array_needs_making;
+
+static int declare_internal ();
+
+/* Declare or change variable attributes. */
+int
+declare_builtin (list)
+     register WORD_LIST *list;
+{
+  return (declare_internal (list, 0));
+}
+
+$BUILTIN local
+$FUNCTION local_builtin
+$SHORT_DOC local name[=value] ...
+Create a local variable called NAME, and give it VALUE.  LOCAL
+can only be used within a function; it makes the variable NAME
+have a visible scope restricted to that function and its children.
+$END
+int
+local_builtin (list)
+     register WORD_LIST *list;
+{
+  if (variable_context)
+    return (declare_internal (list, 1));
+  else
+    {
+      builtin_error ("Can only be used in a function");
+      return (EXECUTION_FAILURE);
+    }
+}
+
+/* The workhorse function. */
+static int
+declare_internal (list, local_var)
+     register WORD_LIST *list;
+     int local_var;
+{
+  int flags_on = 0, flags_off = 0;
+  int any_failed = 0;
+
+  while (list)
+    {
+      register char *t = list->word->word;
+      int *flags;
+
+      if (t[0] == '-' && t[1] == '-' && t[2] == '\0')
+       {
+         list = list->next;
+         break;
+       }
+
+      if (*t != '+' && *t != '-')
+       break;
+
+      if (*t == '+')
+       flags = &flags_off;
+      else
+       flags = &flags_on;
+
+      t++;
+
+      while (*t)
+       {
+         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++;
+         else
+           {
+             builtin_error ("unknown option: `-%c'", *t);
+             return (EX_USAGE);
+           }
+       }
+
+      list = list->next;
+    }
+
+  /* If there are no more arguments left, then we just want to show
+     some variables. */
+  if (!list)
+    {
+      /* Show local variables defined at this context level if this is
+        the `local' builtin. */
+      if (local_var)
+       {
+         register SHELL_VAR **vlist;
+         register int i;
+
+         vlist = map_over (variable_in_context, shell_variables);
+
+         if (vlist)
+           {
+             for (i = 0; vlist[i]; i++)
+               print_assignment (vlist[i]);
+
+             free (vlist);
+           }
+       }
+      else
+       {
+         if (!flags_on)
+           set_builtin ((WORD_LIST *)NULL);
+         else
+           set_or_show_attributes ((WORD_LIST *)NULL, flags_on);
+       }
+
+      fflush (stdout);
+      return (EXECUTION_SUCCESS);
+    }
+
+#define NEXT_VARIABLE() free (name); list = list->next; continue
+
+  /* There are arguments left, so we are making variables. */
+  while (list)
+    {
+      char *value, *name = savestring (list->word->word);
+      int offset = assignment (name);
+
+      if (offset)
+       {
+         name[offset] = '\0';
+         value = name + offset + 1;
+       }
+      else
+       value = "";
+
+      if (legal_identifier (name) == 0)
+       {
+         builtin_error ("%s: not a legal variable name", name);
+         any_failed++;
+         NEXT_VARIABLE ();
+       }
+
+      /* If VARIABLE_CONTEXT has a non-zero value, then we are executing
+        inside of a function.  This means we should make local variables,
+        not global ones. */
+
+      if (variable_context)
+       make_local_variable (name);
+
+      /* If we are declaring a function, then complain about it in some way.
+        We don't let people make functions by saying `typeset -f foo=bar'. */
+
+      /* There should be a way, however, to let people look at a particular
+        function definition by saying `typeset -f foo'. */
+
+      if (flags_on & att_function)
+       {
+         if (offset)
+           {
+             builtin_error ("Can't use `-f' to make functions");
+             return (EXECUTION_FAILURE);
+           }
+         else
+           {
+             SHELL_VAR *find_function (), *funvar;
+
+             funvar = find_function (name);
+
+             if (funvar)
+               {
+                 if (readonly_p (funvar) && (flags_off & att_readonly))
+                   {
+                     builtin_error ("%s: readonly function", name);
+                     any_failed++;
+                     NEXT_VARIABLE ();
+                   }
+
+                 if (flags_on == att_function && flags_off == 0)
+                   {
+                     char *result = named_function_string
+                               (name, (COMMAND *)function_cell (funvar), 1);
+                     printf ("%s\n", result);
+                   }
+                 else
+                   {
+                     funvar->attributes |= flags_on;
+                     funvar->attributes &= ~flags_off;
+                   }
+               }
+             else
+               any_failed++;
+             NEXT_VARIABLE ();
+           }
+       }
+      else
+       {
+         SHELL_VAR *var;
+
+         var = find_variable (name);
+
+         if (!var)
+           var = bind_variable (name, "");
+
+         if (readonly_p (var) && (flags_off & att_readonly))
+           {
+             builtin_error ("%s: readonly variable", name);
+             any_failed++;
+             NEXT_VARIABLE ();
+           }
+
+         var->attributes |= flags_on;
+         var->attributes &= ~flags_off;
+
+         if (offset)
+           {
+             free (var->value);
+             if (integer_p (var))
+               {
+                 long val, evalexp ();
+                 char *itos ();
+
+                 val = evalexp (value);
+                 var->value = itos ((int)val);
+               }
+             else
+               var->value = savestring (value);
+           }
+       }
+
+      stupidly_hack_special_variables (name);
+
+      NEXT_VARIABLE ();
+    }
+  return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+}
diff --git a/builtins/echo.def b/builtins/echo.def
new file mode 100644 (file)
index 0000000..7539103
--- /dev/null
@@ -0,0 +1,168 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES echo.c
+#include <stdio.h>
+#include "../shell.h"
+
+$BUILTIN echo
+$FUNCTION echo_builtin
+$DEPENDS_ON V9_ECHO
+$SHORT_DOC echo [-neE] [arg ...]
+Output the ARGs.  If -n is specified, the trailing newline is
+suppressed.  If the -e option is given, interpretation of the
+following backslash-escaped characters is turned on:
+       \a      alert (bell)
+       \b      backspace
+       \c      suppress trailing newline
+       \f      form feed
+       \n      new line
+       \r      carriage return
+       \t      horizontal tab
+       \v      vertical tab
+       \\      backslash
+       \num    the character whose ASCII code is NUM (octal).
+
+You can explicitly turn off the interpretation of the above characters
+with the -E option.
+$END
+
+$BUILTIN echo
+$FUNCTION echo_builtin
+$DEPENDS_ON !V9_ECHO
+$SHORT_DOC echo [-n] [arg ...]
+Output the ARGs.  If -n is specified, the trailing newline is suppressed.
+$END
+
+#if defined (V9_ECHO)
+#  define VALID_ECHO_OPTIONS "neE"
+#else /* !V9_ECHO */
+#  define VALID_ECHO_OPTIONS "n"
+#endif /* !V9_ECHO */
+
+/* Print the words in LIST to standard output.  If the first word is
+   `-n', then don't print a trailing newline.  We also support the
+   echo syntax from Version 9 unix systems. */
+echo_builtin (list)
+     WORD_LIST *list;
+{
+  int display_return = 1, do_v9 = 0;
+
+#if defined (DEFAULT_ECHO_TO_USG)
+/* System V machines already have a /bin/sh with a v9 behaviour.  We
+   give Bash the identical behaviour for these machines so that the
+   existing system shells won't barf. */
+  do_v9 = 1;
+#endif /* DEFAULT_ECHO_TO_USG */
+
+  while (list && list->word->word[0] == '-')
+    {
+      register char *temp;
+      register int i;
+
+      /* If it appears that we are handling options, then make sure that
+        all of the options specified are actually valid.  Otherwise, the
+        string should just be echoed. */
+      temp = &(list->word->word[1]);
+
+      for (i = 0; temp[i]; i++)
+       {
+         if (strchr (VALID_ECHO_OPTIONS, temp[i]) == 0)
+           goto just_echo;
+       }
+
+      if (!*temp)
+       goto just_echo;
+
+      /* All of the options in TEMP are valid options to ECHO.
+        Handle them. */
+      while (*temp)
+       {
+         if (*temp == 'n')
+           display_return = 0;
+#if defined (V9_ECHO)
+         else if (*temp == 'e')
+           do_v9 = 1;
+         else if (*temp == 'E')
+           do_v9 = 0;
+#endif /* V9_ECHO */
+         else
+           goto just_echo;
+
+         temp++;
+       }
+      list = list->next;
+    }
+
+just_echo:
+
+  if (list)
+    {
+#if defined (V9_ECHO)
+      if (do_v9)
+       {
+         while (list)
+           {
+             register char *s = list->word->word;
+             register int c;
+
+             while (c = *s++)
+               {
+                 if (c == '\\' && *s)
+                   {
+                     switch (c = *s++)
+                       {
+                       case 'a': c = '\007'; break;
+                       case 'b': c = '\b'; break;
+                       case 'c': display_return = 0; continue;
+                       case 'f': c = '\f'; break;
+                       case 'n': c = '\n'; break;
+                       case 'r': c = '\r'; break;
+                       case 't': c = '\t'; break;
+                       case 'v': c = (int) 0x0B; break;
+                       case '0': case '1': case '2': case '3':
+                       case '4': case '5': case '6': case '7':
+                         c -= '0';
+                         if (*s >= '0' && *s <= '7')
+                           c = c * 8 + (*s++ - '0');
+                         if (*s >= '0' && *s <= '7')
+                           c = c * 8 + (*s++ - '0');
+                         break;
+                       case '\\': break;
+                       default:  putchar ('\\'); break;
+                       }
+                   }
+                 putchar(c);
+               }
+             list = list->next;
+             if (list)
+               putchar(' ');
+           }
+       }
+      else
+#endif /* V9_ECHO */
+       print_word_list (list, " ");
+    }
+  if (display_return)
+    printf ("\n");
+  fflush (stdout);
+  return (EXECUTION_SUCCESS);
+}
diff --git a/builtins/enable.def b/builtins/enable.def
new file mode 100644 (file)
index 0000000..2aeae39
--- /dev/null
@@ -0,0 +1,156 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES enable.c
+
+$BUILTIN enable
+$FUNCTION enable_builtin
+$SHORT_DOC enable [-n] [name ...]
+Enable and disable builtin shell commands.  This allows
+you to use a disk command which has the same name as a shell
+builtin.  If -n is used, the NAMEs become disabled.  Otherwise
+NAMEs are enabled.  For example, to use the `test' found on your
+path instead of the shell builtin version, you type `enable -n test'.
+$END
+
+#include "../shell.h"
+#include "../builtins.h"
+#include "common.h"
+
+#define ENABLED  1
+#define DISABLED 2
+
+static int enable_shell_command ();
+static void list_some_builtins ();
+
+/* Enable/disable shell commands present in LIST.  If list is not specified,
+   then print out a list of shell commands showing which are enabled and
+   which are disabled. */
+enable_builtin (list)
+     WORD_LIST *list;
+{
+  int result = 0, any_failed = 0;
+  int disable_p, all_p;
+
+  disable_p = all_p = 0;
+
+  while (list && list->word->word && list->word->word[0] == '-')
+    {
+      char *arg = list->word->word;
+
+      list = list->next;
+
+      if (ISOPTION (arg, 'n'))
+       disable_p = 1;
+      else if (arg[1] == 'a' && (arg[2] == 0 || strcmp (arg + 2, "ll") == 0))
+       all_p = 1;
+      else if (ISOPTION (arg, '-'))
+        break;
+      else
+       {
+         bad_option (arg);
+         return (EXECUTION_FAILURE);
+       }
+    }
+
+  if (!list)
+    {
+      int filter;
+
+      if (all_p)
+       filter = ENABLED | DISABLED;
+      else if (disable_p)
+       filter = DISABLED;
+      else
+       filter = ENABLED;
+
+      list_some_builtins (filter);
+    }
+  else
+    {
+      while (list)
+       {
+         result = enable_shell_command (list->word->word, disable_p);
+
+         if (!result)
+           {
+             builtin_error ("%s: not a shell builtin", list->word->word);
+             any_failed++;
+           }
+         list = list->next;
+       }
+    }
+  return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+}
+
+/* List some builtins.
+   FILTER is a mask with two slots: ENABLED and DISABLED. */
+static void
+list_some_builtins (filter)
+     int filter;
+{
+  register int i;
+
+  for (i = 0; i < num_shell_builtins; i++)
+    {
+      if (!shell_builtins[i].function)
+       continue;
+
+      if ((filter & ENABLED) &&
+         (shell_builtins[i].flags & BUILTIN_ENABLED))
+       {
+         printf ("enable %s\n", shell_builtins[i].name);
+       }
+      else if ((filter & DISABLED) &&
+              ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
+       {
+         printf ("enable -n %s\n", shell_builtins[i].name);
+       }
+    }
+}
+
+/* Enable the shell command NAME.  If DISABLE_P is non-zero, then
+   disable NAME instead. */
+static int
+enable_shell_command (name, disable_p)
+     char *name;
+     int disable_p;
+{
+  register int i;
+  int found = 0;
+
+  for (i = 0; i < num_shell_builtins; i++)
+    {
+      if (!shell_builtins[i].function)
+       continue;
+
+      if (STREQ (name, shell_builtins[i].name))
+       {
+         found++;
+
+         if (disable_p)
+           shell_builtins[i].flags &= ~BUILTIN_ENABLED;
+         else
+           shell_builtins[i].flags |= BUILTIN_ENABLED;
+       }
+    }
+  return (found);
+}
diff --git a/builtins/eval.def b/builtins/eval.def
new file mode 100644 (file)
index 0000000..5c3eda8
--- /dev/null
@@ -0,0 +1,45 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES eval.c
+
+$BUILTIN eval
+$FUNCTION eval_builtin
+$SHORT_DOC eval [arg ...]
+Read ARGs as input to the shell and execute the resulting command(s).
+$END
+
+#include "../shell.h"
+
+/* Parse the string that these words make, and execute the command found. */
+int
+eval_builtin (list)
+     WORD_LIST *list;
+{
+  int result;
+
+  /* Note that parse_and_execute () frees the string it is passed. */
+  if (list)
+    result = parse_and_execute (string_list (list), "eval", -1);
+  else
+    result = EXECUTION_SUCCESS;
+  return (result);
+}
diff --git a/builtins/exec.def b/builtins/exec.def
new file mode 100644 (file)
index 0000000..f950afc
--- /dev/null
@@ -0,0 +1,163 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES exec.c
+
+$BUILTIN exec
+$FUNCTION exec_builtin
+$SHORT_DOC exec [ [-] file [redirection ...]]
+Exec FILE, replacing this shell with the specified program.
+If FILE is not specified, the redirections take effect in this
+shell.  If the first argument is `-', then place a dash in the
+zeroth arg passed to FILE.  If the file cannot be exec'ed and
+the shell is not interactive, then the shell exits, unless the
+shell variable "no_exit_on_failed_exec" exists.
+$END
+
+#include "../shell.h"
+#include <sys/types.h>
+#include "../posixstat.h"
+#include <signal.h>
+#include <errno.h>
+
+#include "../execute_cmd.h"
+#include "common.h"
+#include "../flags.h"
+
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+extern int interactive, subshell_environment;
+extern REDIRECT *redirection_undo_list;
+
+int
+exec_builtin (list)
+     WORD_LIST *list;
+{
+  int exit_value = EXECUTION_FAILURE;
+
+  maybe_make_export_env ();
+
+  /* First, let the redirections remain. */
+  dispose_redirects (redirection_undo_list);
+  redirection_undo_list = (REDIRECT *)NULL;
+
+  if (!list)
+    return (EXECUTION_SUCCESS);
+  else
+    {
+      /* Otherwise, execve the new command with args. */
+      char *command, **args;
+      int dash_name = 0;
+
+      if (list->word->word[0] == '-' && !list->word->word[1])
+       {
+         /* The user would like to exec this command as if it was a
+            login command.  Do so. */
+         list = list->next;
+         dash_name++;
+       }
+
+      if (!list)
+       return (EXECUTION_SUCCESS);
+
+#if defined (RESTRICTED_SHELL)
+      if (restricted)
+       {
+         builtin_error ("restricted");
+         return (EXECUTION_FAILURE);
+       }
+#endif /* RESTRICTED_SHELL */
+
+      args = make_word_array (list);
+
+      /* A command with a slash anywhere in its name is not looked up in
+        the search path. */
+      if (absolute_program (args[0]))
+       command = args[0];
+      else
+       command = find_user_command (args[0]);
+      if (!command)
+       {
+         builtin_error ("%s: not found", args[0]);
+         exit_value = EX_NOTFOUND;     /* As per Posix.2, 3.14.6 */
+         goto failed_exec;
+       }
+
+      command = full_pathname (command);
+      /* If the user wants this to look like a login shell, then
+        prepend a `-' onto the first argument (argv[0]). */
+      if (dash_name)
+       {
+         char *new_name = xmalloc (2 + strlen (args[0]));
+         new_name[0] = '-';
+         strcpy (new_name + 1, args[0]);
+         free (args[0]);
+         args[0] = new_name;
+       }
+
+      /* Decrement SHLVL by 1 so a new shell started here has the same value,
+        preserving the appearance.  After we do that, we need to change the
+        exported environment to include the new value. */
+      adjust_shell_level (-1);
+      maybe_make_export_env ();
+
+#if defined (HISTORY)
+      maybe_save_shell_history ();
+#endif /* HISTORY */
+      restore_original_signals ();
+
+#if defined (JOB_CONTROL)
+      if (subshell_environment == 0)
+       end_job_control ();
+#endif /* JOB_CONTROL */
+
+      shell_execve (command, args, export_env);
+
+      adjust_shell_level (1);
+
+      if (!executable_file (command))
+       {
+         builtin_error ("%s: cannot execute: %s", command, strerror (errno));
+         exit_value = EX_NOEXEC;       /* As per Posix.2, 3.14.6 */
+       }
+      else
+       file_error (command);
+
+  failed_exec:
+      if (command)
+       free (command);
+
+      if (subshell_environment ||
+         (!interactive && !find_variable ("no_exit_on_failed_exec")))
+       exit (exit_value);
+
+      initialize_traps ();
+      reinitialize_signals ();
+
+#if defined (JOB_CONTROL)
+      restart_job_control ();
+#endif /* JOB_CONTROL */
+
+      return (exit_value);
+    }
+}
diff --git a/builtins/exit.def b/builtins/exit.def
new file mode 100644 (file)
index 0000000..25a3b63
--- /dev/null
@@ -0,0 +1,129 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES exit.c
+
+$BUILTIN exit
+$FUNCTION exit_builtin
+$SHORT_DOC exit [n]
+Exit the shell with a status of N.  If N is omitted, the exit status
+is that of the last command executed.
+$END
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "../shell.h"
+#include "../jobs.h"
+
+#include "builtext.h"  /* for jobs_builtin */
+
+extern int interactive, login_shell;
+extern int last_command_exit_value;
+
+static int exit_or_logout ();
+static int sourced_logout = 0;
+
+int
+exit_builtin (list)
+     WORD_LIST *list;
+{
+  if (interactive)
+    {
+      fprintf (stderr, login_shell ? "logout\n" : "exit\n");
+      fflush (stderr);
+    }
+
+  return (exit_or_logout (list));
+}
+
+$BUILTIN logout
+$FUNCTION logout_builtin
+$SHORT_DOC logout
+Logout of a login shell.
+$END
+
+/* How to logout. */
+int
+logout_builtin (list)
+     WORD_LIST *list;
+{
+  if (!login_shell && interactive)
+    {
+      builtin_error ("Not login shell: use `exit'");
+      return (EXECUTION_FAILURE);
+    }
+  else
+    return (exit_or_logout (list));
+}
+
+/* Clean up work for exiting or logging out. */
+Function *last_shell_builtin = (Function *)NULL;
+Function *this_shell_builtin = (Function *)NULL;
+
+static int
+exit_or_logout (list)
+     WORD_LIST *list;
+{
+  int exit_value;
+
+#if defined (JOB_CONTROL)
+  int exit_immediate_okay;
+
+  exit_immediate_okay = (!interactive ||
+                        last_shell_builtin == exit_builtin ||
+                        last_shell_builtin == logout_builtin ||
+                        last_shell_builtin == jobs_builtin);
+
+  /* Check for stopped jobs if the user wants to. */
+  if (!exit_immediate_okay)
+    {
+      register int i;
+      for (i = 0; i < job_slots; i++)
+       if (jobs[i] && (jobs[i]->state == JSTOPPED))
+         {
+           fprintf (stderr, "There are stopped jobs.\n");
+
+           /* This is NOT superfluous because EOF can get here without
+              going through the command parser.  Set both last and this
+              so that either `exit', `logout', or ^D will work to exit
+              immediately if nothing intervenes. */
+           this_shell_builtin = last_shell_builtin = exit_builtin;
+           return (EXECUTION_FAILURE);
+         }
+    }
+#endif /* JOB_CONTROL */
+
+  /* Get return value if present.  This means that you can type
+     `logout 5' to a shell, and it returns 5. */
+  if (list)
+    exit_value = get_numeric_arg (list);
+  else
+    exit_value = last_command_exit_value;
+
+  /* Run our `~/.bash_logout' file if it exists, and this is a login shell. */
+  if (login_shell && sourced_logout++ == 0)
+    maybe_execute_file ("~/.bash_logout", 1);
+
+  last_command_exit_value = exit_value;
+
+  /* Exit the program. */
+  longjmp (top_level, EXITPROG);
+}
diff --git a/builtins/fc.def b/builtins/fc.def
new file mode 100644 (file)
index 0000000..1f6db68
--- /dev/null
@@ -0,0 +1,691 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES fc.c
+
+$BUILTIN fc
+$FUNCTION fc_builtin
+$DEPENDS_ON HISTORY
+$SHORT_DOC fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [cmd]
+
+FIRST and LAST can be numbers specifying the range, or FIRST can be a
+string, which means the most recent command beginning with that
+string.
+
+   -e ENAME selects which editor to use.  Default is FCEDIT, then EDITOR,
+      then the editor which corresponds to the current readline editing
+      mode, then vi.
+
+   -l means list lines instead of editing.
+   -n means no line numbers listed.
+   -r means reverse the order of the lines (making it newest listed first).
+
+With the `fc -s [pat=rep ...] [command]' format, the command is
+re-executed after the substitution OLD=NEW is performed.
+
+A useful alias to use with this is r='fc -s', so that typing `r cc'
+runs the last command beginning with `cc' and typing `r' re-executes
+the last command.
+$END
+
+#include <stdio.h>
+#include "../bashansi.h"
+#include "../shell.h"
+#if defined (HISTORY)
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <errno.h>
+#include "../builtins.h"
+#include "../flags.h"
+#include "../maxpath.h"
+#include "../bashhist.h"
+#include <readline/history.h>
+#include "bashgetopt.h"
+
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+extern int echo_input_at_read;
+
+extern int unlink ();
+
+/* **************************************************************** */
+/*                                                                 */
+/*     The K*rn shell style fc command (Fix Command)               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* fc builtin command (fix command) for Bash for those who
+   like K*rn-style history better than csh-style.
+
+     fc [-e ename] [-nlr] [first] [last]
+
+   FIRST and LAST can be numbers specifying the range, or FIRST can be
+   a string, which means the most recent command beginning with that
+   string.
+
+   -e ENAME selects which editor to use.  Default is FCEDIT, then EDITOR,
+      then the editor which corresponds to the current readline editing
+      mode, then vi.
+
+   -l means list lines instead of editing.
+   -n means no line numbers listed.
+   -r means reverse the order of the lines (making it newest listed first).
+
+     fc -e - [pat=rep ...] [command]
+     fc -s [pat=rep ...] [command]
+
+   Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's.
+*/
+
+static char *fc_dosubs (), *fc_replace (), *fc_gethist (), *fc_readline ();
+static int fc_gethnum ();
+static void fc_replhist (), fc_addhist ();
+
+/* Data structure describing a list of global replacements to perform. */
+typedef struct repl {
+  struct repl *next;
+  char *pat;
+  char *rep;
+} REPL;
+
+#define USAGE  "usage: fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [command]"
+
+/* Accessors for HIST_ENTRY lists that are called HLIST. */
+#define histline(i) (hlist[(i)]->line)
+#define histdata(i) (hlist[(i)]->data)
+
+#define FREE_RLIST() \
+       do { \
+               for (rl = rlist; rl; ) { \
+                       REPL *r;        \
+                       r = rl->next; \
+                       if (rl->pat) \
+                               free (rl->pat); \
+                       if (rl->rep) \
+                               free (rl->rep); \
+                       free (rl); \
+                       rl = r; \
+               } \
+       } while (0)
+
+/* String to execute on a file that we want to edit. */
+#define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
+
+int
+fc_builtin (list)
+     WORD_LIST *list;
+{
+  register int i;
+  register char *sep;
+  int numbering, reverse, listing, execute;
+  int histbeg, histend, last_hist, retval, first, opt;
+  FILE *stream;
+  REPL *rlist = (REPL *) NULL, *rl;
+  char *ename = NULL, *command, *newcom, *line;
+  HIST_ENTRY **hlist;
+  char fn[MAXPATHLEN];
+
+  numbering = 1;
+  reverse = listing = execute = 0;
+
+  /* Parse out the options and set which of the two forms we're in. */
+
+  while (list && *list->word->word == '-')
+    {
+      register char *s = &((list->word->word)[1]);
+
+      if (!isletter (*s))
+       break;
+
+      while (opt = *s++)
+       {
+         switch (opt)
+           {
+           case 'n':
+             numbering = 0;
+             break;
+
+           case 'l':
+             listing = 1;
+             break;
+
+           case 'r':
+             reverse = 1;
+             break;
+
+           case 's':
+             execute = 1;
+             break;
+
+           case 'e':
+             list = list->next;
+             if (list == NULL)
+               {
+                 builtin_error (USAGE);
+                 return (EX_USAGE);
+               }
+             ename = list->word->word;
+             break;
+
+           default:
+             builtin_error (USAGE);
+             return (EX_USAGE);
+           }
+       }
+      list = list->next;
+    }
+
+  if (ename && (*ename == '-') && (ename[1] == '\0'))
+    execute = 1;
+
+  /* The "execute" form of the command (re-run, with possible string
+     substitutions). */
+  if (execute)
+    {
+      while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
+       {
+         *sep++ = '\0';
+         rl = (REPL *)xmalloc (sizeof (REPL));
+         rl->next = (REPL *)NULL;
+         rl->pat = savestring (list->word->word);
+         rl->rep = savestring (sep);
+
+         if (rlist == NULL)
+           rlist = rl;
+         else
+           {
+             rl->next = rlist;
+             rlist = rl;
+           }
+         list = list->next;
+       }
+
+      /* 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);
+
+      hlist = history_list ();
+
+      /* If we still have something in list, it is a command spec.
+        Otherwise, we use the most recent command in time. */
+      if (list)
+       command = fc_gethist (list->word->word, hlist);
+      else
+       command = fc_gethist ((char *) NULL, hlist);
+
+      if (command == NULL)
+       {
+         builtin_error ("no command found");
+         if (rlist)
+           FREE_RLIST ();
+
+         return (EXECUTION_FAILURE);
+       }
+
+      if (rlist)
+       {
+         newcom = fc_dosubs (command, rlist);
+         free (command);
+         FREE_RLIST ();
+         command = newcom;
+       }
+
+      printf ("%s\n", command);
+      fc_replhist (command);   /* replace `fc -e -' with command */
+      return (parse_and_execute (command, "fc", -1));
+    }
+
+  /* This is the second form of the command (the list-or-edit-and-rerun
+     form). */
+  hlist = history_list ();
+  if (hlist == 0)
+    return (EXECUTION_SUCCESS);
+  for (i = 0; hlist[i]; i++);
+
+  /* With the Bash implementation of history, the current command line
+     ("fc blah..." and so on) is already part of the history list by
+     the time we get to this point.  This just skips over that command
+     and makes the last command that this deals with be the last command
+     the user entered before the fc. */
+
+  last_hist = i - 2;
+
+  if (list)
+    {
+      histbeg = fc_gethnum (list->word->word, hlist);
+      list = list->next;
+
+      if (list)
+       histend = fc_gethnum (list->word->word, hlist);
+      else
+       {
+         if (listing)
+           histend = last_hist;
+         else
+           histend = histbeg;
+       }
+    }
+  else
+    {
+      /* The default for listing is the last 16 history items. */
+      if (listing)
+       {
+         histend = last_hist;
+         histbeg = histend - 16;
+         if (histbeg < 0)
+           histbeg = 0;
+       }
+      else
+       {
+         /* For editing, it is the last history command. */
+         histbeg = histend = last_hist;
+      }
+    }
+
+  /* We print error messages for line specifications out of range. */
+  if ((histbeg < 0) || (histend < 0) ||
+      (histbeg > last_hist) || (histend > last_hist))
+    {
+      builtin_error ("history specification out of range");
+      return (EXECUTION_FAILURE);
+    }
+
+  if (histend < histbeg)
+    {
+      int t = histend;
+
+      histend = histbeg;
+      histbeg = t;
+      reverse = 1;
+    }
+
+  if (listing)
+    stream = stdout;
+  else
+    {
+      numbering = 0;
+      sprintf (fn, "/tmp/bash%d", (int)time ((long *) 0) + (int)getpid ());
+
+      stream = fopen (fn, "w");
+
+      if (!stream)
+       {
+         builtin_error ("cannot open temp file %s", fn);
+         return (EXECUTION_FAILURE);
+       }
+    }
+
+  if (!reverse)
+    {
+      for (i = histbeg; i <= histend; i++)
+       {
+         QUIT;
+         if (numbering)
+           fprintf (stream, "%d", i + history_base);
+         if (listing)
+           fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
+         fprintf (stream, "%s\n", histline (i));
+       }
+    }
+  else
+    {
+      for (i = histend; i >= histbeg; i--)
+       {
+         QUIT;
+         if (numbering)
+           fprintf (stream, "%d", i + history_base);
+         if (listing)
+           fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
+         fprintf (stream, "%s\n", histline (i));
+       }
+    }
+
+  if (listing)
+    return (EXECUTION_SUCCESS);
+
+  fclose (stream);
+
+  /* Now edit the file of commands. */
+  if (ename)
+    {
+      command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
+      sprintf (command, "%s %s", ename, fn);
+    }
+  else
+    {
+      command = (char *)xmalloc (3 + strlen (FC_EDIT_COMMAND) + strlen (fn));
+      sprintf (command, "%s %s", FC_EDIT_COMMAND, fn);
+    }
+  parse_and_execute (command, "fc", -1);
+
+  /* Now reopen the file and execute the edited commands. */
+
+  stream = fopen (fn, "r");
+
+  if (stream == NULL)
+    {
+      builtin_error ("cannot reopen temp file %s", fn);
+      unlink (fn);
+      return (EXECUTION_FAILURE);
+    }
+
+  retval = EXECUTION_SUCCESS;
+  first = 1;
+
+  /* First, write the commands to the history file.  This will not happen
+     when we call parse_and_execute, since parse_and_execute disables
+     the command line history while it executes. */
+     
+  while ((line = fc_readline (stream)) != NULL)
+    {
+      if (line[0] == '\n')
+       {
+         free (line);
+         continue;             /* Skip blank lines. */
+       }
+
+      if (first)
+       {
+         first = 0;
+         fc_replhist (line);
+       }
+      else
+       fc_addhist (line);
+
+      free (line);
+    }
+  fclose (stream);
+
+  /* Turn on the `v' flag while maybe_execute_file runs so the commands
+     will be echoed as they are read by the parser. */
+  begin_unwind_frame ("fc builtin");
+  add_unwind_protect (unlink, fn);
+  unwind_protect_int (echo_input_at_read);
+  echo_input_at_read = 1;
+    
+  retval = maybe_execute_file (fn, 0);
+
+  run_unwind_frame ("fc builtin");
+
+  return (retval);
+}
+
+/* Return an absolute index into HLIST which corresponds to COMMAND.  If
+   COMMAND is a number, then it was specified in relative terms.  If it
+   is a string, then it is the start of a command line present in HLIST. */
+static int
+fc_gethnum (command, hlist)
+     char *command;
+     HIST_ENTRY **hlist;
+{
+  int sign = 1, n, clen;
+  register int i, j;
+  register char *s;
+
+  /* Count history elements. */
+  for (i = 0; hlist[i]; i++);
+
+  /* With the Bash implementation of history, the current command line
+     ("fc blah..." and so on) is already part of the history list by
+     the time we get to this point.  This just skips over that command
+     and makes the last command that this deals with be the last command
+     the user entered before the fc. */
+  i -= 2;
+
+  /* No specification defaults to most recent command. */
+  if (command == NULL)
+    return (i);
+
+  /* Otherwise, there is a specification.  It can be a number relative to
+     the current position, or an absolute history number. */
+  s = command;
+
+  /* Handle possible leading minus sign. */
+  if (s && (*s == '-'))
+    {
+      sign = -1;
+      s++;
+    }
+
+  if (s && digit(*s))
+    {
+      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);
+      else if (n == 0)
+       return (i);
+      else
+       return (n - history_base);
+    }
+
+  clen = strlen (command);
+  for (j = i; j >= 0; j--)
+    {
+      if (STREQN (command, histline (j), clen))
+       return (j);
+    }
+  return (-1);
+}
+
+/* Locate the most recent history line which begins with
+   COMMAND in HLIST, and return a malloc()'ed copy of it. */
+static char *
+fc_gethist (command, hlist)
+     char *command;
+     HIST_ENTRY **hlist;
+{
+  int i;
+
+  if (!hlist)
+    return ((char *)NULL);
+
+  i = fc_gethnum (command, hlist);
+
+  if (i >= 0)
+    return (savestring (histline (i)));
+  else
+    return ((char *)NULL);
+}
+
+/* Read the edited history lines from STREAM and return them
+   one at a time.  This can read unlimited length lines.  The
+   caller should free the storage. */
+static char *
+fc_readline (stream)
+     FILE *stream;
+{
+  register int c;
+  int line_len = 0, lindex = 0;
+  char *line = (char *)NULL;
+
+  while ((c = getc (stream)) != EOF)
+    {
+      if ((lindex + 2) >= line_len)
+       line = (char *) xrealloc (line, (line_len += 128));
+
+      if (c == '\n')
+       {
+         line[lindex++] = '\n';
+         line[lindex++] = '\0';
+         return (line);
+       }
+      else
+       line[lindex++] = c;
+    }
+
+  if (!lindex)
+    {
+      if (line)
+       free (line);
+
+      return ((char *)NULL);
+    }
+
+  if (lindex + 2 >= line_len)
+    line = (char *)xrealloc (line, lindex + 3);
+
+  line[lindex++] = '\n';           /* Finish with newline if none in file */
+  line[lindex++] = '\0';
+  return (line);
+}
+
+/* Perform the SUBS on COMMAND.
+   SUBS is a list of substitutions, and COMMAND is a simple string.
+   Return a pointer to a malloc'ed string which contains the substituted
+   command. */
+static char *
+fc_dosubs (command, subs)
+     char *command;
+     REPL *subs;
+{
+  register char *new = savestring (command);
+  register REPL *r;
+
+  for (r = subs; r; r = r->next)
+    {
+      register char *t;
+
+      t = fc_replace (r->pat, r->rep, new);
+      free (new);
+      new = t;
+    }
+  return (new);
+}
+
+/* Replace the occurrences of PAT with REP in COMMAND.
+   This returns a new string; the caller should free it. */
+static char *
+fc_replace (pat, rep, command)
+     char *pat, *rep, *command;
+{
+  register int i;
+  int patlen, replen, templen;
+  char *new, *temp;
+
+  patlen = strlen (pat);
+  replen = strlen (rep);
+
+  temp = savestring (command);
+  templen = strlen (temp);
+  i = 0;
+
+  for (; (i + patlen) <= templen; i++)
+    {
+      if (STREQN (temp + i, pat, patlen))
+       {
+         new = (char *) xmalloc (1 + (replen - patlen) + templen);
+
+         strncpy (new, temp, i);
+         strncpy (new + i, rep, replen);
+         strncpy (new + i + replen,
+                  temp + i + patlen, templen - (i + patlen));
+         new[templen + (replen - patlen)] = '\0'; /* just in case */
+
+         free (temp);
+         temp = new;
+         i += replen;
+         templen = strlen (temp);
+       }
+    }
+  return (temp);
+}
+
+/* Use `command' to replace the last entry in the history list, which,
+   by this time, is `fc blah...'.  The intent is that the new command
+   become the history entry, and that `fc' should never appear in the
+   history list.  This way you can do `r' to your heart's content. */
+static void
+fc_replhist (command)
+     char *command;
+{
+  register int i;
+  HIST_ENTRY **hlist, *histent, *discard;
+  char *data;
+  int n;
+
+  if (!command || !*command)
+    return;
+
+  hlist = history_list ();
+
+  if (hlist == NULL)
+    return;
+
+  for (i = 0; hlist[i]; i++);
+  i--;
+
+  /* History_get () takes a parameter that should be
+     offset by history_base. */
+
+  histent = history_get (history_base + i);    /* Don't free this */
+  if (histent == NULL)
+    return;
+
+  n = strlen (command);
+
+  if (command[n - 1] == '\n')
+    command[n - 1] = '\0';
+
+  if (command && *command)
+    {
+      discard = remove_history (i);
+      if (discard)
+       {
+         if (discard->line)
+           free (discard->line);
+         free ((char *) discard);
+       }
+      maybe_add_history (command);     /* Obeys HISTCONTROL setting. */
+    }
+}
+
+/* Add LINE to the history, after removing a single trailing newline. */
+static void
+fc_addhist (line)
+     char *line;
+{
+  register int n;
+
+  n = strlen (line);
+
+  if (line[n - 1] == '\n')
+    line[n - 1] = '\0';
+
+  if (line && *line)
+    maybe_add_history (line);
+}
+#endif /* HISTORY */
diff --git a/builtins/fg_bg.def b/builtins/fg_bg.def
new file mode 100644 (file)
index 0000000..e48af38
--- /dev/null
@@ -0,0 +1,145 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES fg_bg.c
+
+$BUILTIN fg
+$FUNCTION fg_builtin
+$DEPENDS_ON JOB_CONTROL
+$SHORT_DOC fg [job_spec]
+Place JOB_SPEC in the foreground, and make it the current job.  If
+JOB_SPEC is not present, the shell's notion of the current job is
+used.
+$END
+
+#include <sys/types.h>
+#include <signal.h>
+#include "../shell.h"
+#include "../jobs.h"
+
+#if defined (JOB_CONTROL)
+extern char *this_command_name;
+
+static int fg_bg ();
+
+/* How to bring a job into the foreground. */
+int
+fg_builtin (list)
+     WORD_LIST *list;
+{
+  int fg_bit = 1;
+  register WORD_LIST *t = list;
+
+  if (!job_control)
+    {
+      builtin_error ("no job control");
+      return (EXECUTION_FAILURE);
+    }
+
+  /* If the last arg on the line is '&', then start this job in the
+     background.  Else, fg the job. */
+
+  while (t && t->next)
+    t = t->next;
+
+  if (t && t->word->word[0] == '&' && !t->word->word[1])
+    fg_bit = 0;
+
+  return (fg_bg (list, fg_bit));
+}
+#endif /* JOB_CONTROL */
+
+$BUILTIN bg
+$FUNCTION bg_builtin
+$DEPENDS_ON JOB_CONTROL
+$SHORT_DOC bg [job_spec]
+Place JOB_SPEC in the background, as if it had been started with
+`&'.  If JOB_SPEC is not present, the shell's notion of the current
+job is used.
+$END
+
+#if defined (JOB_CONTROL)
+/* How to put a job into the background. */
+int
+bg_builtin (list)
+     WORD_LIST *list;
+{
+  if (!job_control)
+    {
+      builtin_error ("no job control");
+      return (EXECUTION_FAILURE);
+    }
+
+  return (fg_bg (list, 0));
+}
+
+/* How to put a job into the foreground/background. */
+static int
+fg_bg (list, foreground)
+     WORD_LIST *list;
+     int foreground;
+{
+  sigset_t set, oset;
+  int job, status = EXECUTION_SUCCESS, old_async_pid;
+
+  BLOCK_CHILD (set, oset);
+  job = get_job_spec (list);
+
+  if (job < 0 || job >= job_slots || !jobs[job])
+    {
+      if (job != DUP_JOB)
+       builtin_error ("No such job %s", list ? list->word->word : "");
+
+      goto failure;
+    }
+
+  /* Or if jobs[job]->pgrp == shell_pgrp. */
+  if (!(jobs[job]->flags & J_JOBCONTROL))
+    {
+      builtin_error ("job %%%d started without job control", job + 1);
+      goto failure;
+    }
+
+  if (!foreground)
+    {
+      old_async_pid = last_asynchronous_pid;
+      last_asynchronous_pid = jobs[job]->pgrp; /* As per Posix.2 5.4.2 */
+    }
+
+  status = start_job (job, foreground);
+
+  if (status >= 0)
+    {
+    /* win: */
+      UNBLOCK_CHILD (oset);
+      return (status);
+    }
+  else
+    {
+      if (!foreground)
+       last_asynchronous_pid = old_async_pid;
+
+    failure:
+      UNBLOCK_CHILD (oset);
+      return (EXECUTION_FAILURE);
+    }
+}
+#endif /* JOB_CONTROL */
diff --git a/builtins/getopt.c b/builtins/getopt.c
new file mode 100644 (file)
index 0000000..7603430
--- /dev/null
@@ -0,0 +1,283 @@
+/* getopt for BASH.
+
+   Copyright (C) 1993, 1994
+       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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "../memalloc.h"
+#include "../shell.h"
+#include "getopt.h"
+
+/* For communication from `sh_getopt' to the caller.
+   When `sh_getopt' finds an option that takes an argument,
+   the argument value is returned here. */
+char *sh_optarg = 0;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `sh_getopt'.
+
+   On entry to `sh_getopt', zero means this is the first call; initialize.
+
+   When `sh_getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `sh_optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* XXX 1003.2 says this must be 1 before any call.  */
+int sh_optind = 0;
+
+/* Index of the current argument. */
+static int sh_curopt;
+
+/* The next char to be scanned in the option-element
+   in which the last option character we returned was found.
+   This allows us to pick up the scan where we left off.
+
+   If this is zero, or a null string, it means resume the scan
+   by advancing to the next ARGV-element.  */
+
+static char *nextchar;
+static int sh_charindex;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int sh_opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int sh_optopt = '?';
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `sh_getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `sh_getopt' finds another option character, it returns that character,
+   updating `sh_optind' and `nextchar' so that the next call to `sh_getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `sh_getopt' returns `EOF'.
+   Then `sh_optind' is the index in ARGV of the first ARGV-element
+   that is not an option.
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `sh_opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `sh_optarg'. */
+
+/* 1003.2 specifies the format of this message.  */
+#define BADOPT(x)  fprintf (stderr, "%s: illegal option -- %c\n", argv[0], x)
+#define NEEDARG(x) fprintf (stderr, "%s: option requires an argument -- %c\n", argv[0], x)
+
+int
+sh_getopt (argc, argv, optstring)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+{
+  int option_index;
+  char c, *temp;
+
+  sh_optarg = 0;
+
+  if (sh_optind > argc || sh_optind < 0)
+    {
+      sh_optind = argc;
+      return (EOF);
+    }
+
+  /* Initialize the internal data when the first call is made.
+     Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  if (sh_optind == 0)
+    {
+      sh_optind = 1;
+      nextchar = (char *)NULL;
+    }
+
+  if (nextchar == 0 || *nextchar == '\0')
+    {
+      /* If we have done all the ARGV-elements, stop the scan
+        and back over any non-options that we skipped and permuted.  */
+      if (sh_optind == argc)
+       return EOF;
+
+      temp = argv[sh_optind];
+
+      /* Special ARGV-element `--' means premature end of options.
+        Skip it like a null option, and return EOF. */
+      if (temp[0] == '-' && temp[1] == '-' && temp[2] == '\0')
+       {
+         sh_optind++;
+         return EOF;
+       }
+
+      /* If we have come to a non-option, either stop the scan or describe
+        it to the caller and pass it by.  This makes the pseudo-option
+        `-' mean the end of options, but does not skip over it. */
+      if (temp[0] != '-' || temp[1] == '\0')
+       return EOF;
+
+      /* We have found another option-ARGV-element.
+        Start decoding its characters.  */
+      nextchar = argv[sh_curopt = sh_optind] + 1;
+      sh_charindex = 1;
+    }
+
+  /* Look at and handle the next option-character.  */
+
+  c = *nextchar++; sh_charindex++;
+  temp = strchr (optstring, c);
+
+  /* Increment `sh_optind' when we start to process its last character.  */
+  if (nextchar == 0 || *nextchar == '\0')
+    {
+      sh_optind++;
+      nextchar = (char *)NULL;
+    }
+
+  sh_optopt = c;
+
+  if (temp == NULL || c == ':')
+    {
+      if (sh_opterr)
+       BADOPT (c);
+
+      return '?';
+    }
+
+  if (temp[1] == ':')
+    {
+      if (nextchar && *nextchar)
+       {
+         /* This is an option that requires an argument.  */
+         sh_optarg = nextchar;
+         /* If we end this ARGV-element by taking the rest as an arg,
+            we must advance to the next element now.  */
+         sh_optind++;
+       }
+      else if (sh_optind == argc)
+       {
+         if (sh_opterr)
+           NEEDARG (c);
+
+         sh_optopt = c;
+         c = (optstring[0] == ':') ? ':' : '?';
+       }
+      else
+       /* We already incremented `sh_optind' once;
+          increment it again when taking next ARGV-elt as argument.  */
+       sh_optarg = argv[sh_optind++];
+      nextchar = (char *)NULL;
+    }
+  return c;
+}
+
+void
+sh_getopt_restore_state (argv)
+     char **argv;
+{
+  if (nextchar)
+    nextchar = argv[sh_curopt] + sh_charindex;
+}
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `sh_getopt'.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_sh_optind = 0;
+
+  while (1)
+    {
+      int this_option_sh_optind = sh_optind ? sh_optind : 1;
+
+      c = sh_getopt (argc, argv, "abc:d:0123456789");
+      if (c == EOF)
+       break;
+
+      switch (c)
+       {
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+       case '8':
+       case '9':
+         if (digit_sh_optind != 0 && digit_sh_optind != this_option_sh_optind)
+           printf ("digits occur in two different argv-elements.\n");
+         digit_sh_optind = this_option_sh_optind;
+         printf ("option %c\n", c);
+         break;
+
+       case 'a':
+         printf ("option a\n");
+         break;
+
+       case 'b':
+         printf ("option b\n");
+         break;
+
+       case 'c':
+         printf ("option c with value `%s'\n", sh_optarg);
+         break;
+
+       case '?':
+         break;
+
+       default:
+         printf ("?? sh_getopt returned character code 0%o ??\n", c);
+       }
+    }
+
+  if (sh_optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (sh_optind < argc)
+       printf ("%s ", argv[sh_optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
diff --git a/builtins/getopt.h b/builtins/getopt.h
new file mode 100644 (file)
index 0000000..fa9878c
--- /dev/null
@@ -0,0 +1,57 @@
+/* Declarations for getopt.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* XXX THIS HAS BEEN MODIFIED FOR INCORPORATION INTO BASH XXX */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *sh_optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `sh_optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int sh_optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern int sh_opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern int sh_optopt;
+
+extern int sh_getopt ();
+extern void sh_getopt_restore_state ();
+
+#endif /* _GETOPT_H */
diff --git a/builtins/getopts.def b/builtins/getopts.def
new file mode 100644 (file)
index 0000000..0f2b82f
--- /dev/null
@@ -0,0 +1,300 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES getopts.c
+
+$BUILTIN getopts
+$DEPENDS_ON GETOPTS_BUILTIN
+$FUNCTION getopts_builtin
+$SHORT_DOC getopts optstring name [arg]
+Getopts is used by shell procedures to parse positional parameters.
+
+OPTSTRING contains the option letters to be recognized; if a letter
+is followed by a colon, the option is expected to have an argument,
+which should be separated from it by white space.
+
+Each time it is invoked, getopts will place the next option in the
+shell variable $name, initializing name if it does not exist, and
+the index of the next argument to be processed into the shell
+variable OPTIND.  OPTIND is initialized to 1 each time the shell or
+a shell script is invoked.  When an option requires an argument,
+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
+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
+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.
+
+If the shell variable OPTERR has the value 0, getopts disables the
+printing of error messages, even if the first character of
+OPTSTRING is not a colon.  OPTERR has the value 1 by default.
+
+Getopts normally parses the positional parameters ($0 - $9), but if
+more arguments are given, they are parsed instead.
+$END
+
+#include <stdio.h>
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "../shell.h"
+
+#if defined (GETOPTS_BUILTIN)
+#include "getopt.h"
+
+#define G_EOF          (-1)
+#define G_ILLEGAL_OPT  (-2)
+#define G_ARG_MISSING  (-3)
+
+extern char *this_command_name;
+extern WORD_LIST *rest_of_args;
+
+/* getopts_reset is magic code for when OPTIND is reset.  N is the
+   value that has just been assigned to OPTIND. */
+void
+getopts_reset (newind)
+     int newind;
+{
+  sh_optind = newind;
+}
+
+/* Error handling is now performed as specified by Posix.2, draft 11
+   (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.
+
+   ILLEGAL OPTIONS:
+        name -> "?"
+        if (special_error) then
+                OPTARG = option character found
+                no error output
+        else
+                OPTARG unset
+                diagnostic message
+        fi
+  MISSING OPTION ARGUMENT;
+        if (special_error) then
+                name -> ":"
+                OPTARG = option character found
+        else
+                name -> "?"
+                OPTARG unset
+                diagnostic message
+        fi
+ */
+
+static int
+dogetopts (argc, argv)
+     int argc;
+     char **argv;
+{
+  int ret, special_error, old_opterr = 0, i, n;
+  char strval[2], numval[16];
+  char *optstr;                        /* list of options */
+  char *name;                  /* variable to get flag val */
+  char *t;
+
+  if (argc < 3)
+    {
+      builtin_error("usage: getopts optstring name [arg]");
+      return (EX_USAGE);
+    }
+
+  /* argv[0] is "getopts". */
+
+  optstr = argv[1];
+  name = argv[2];
+  argc -= 2;
+  argv += 2;
+
+  special_error = optstr[0] == ':';
+
+  if (special_error)
+    {
+      old_opterr = sh_opterr;
+      optstr++;
+      sh_opterr = 0;           /* suppress diagnostic messages */
+    }
+
+  if (argc > 1)
+    {
+      sh_getopt_restore_state (argv);
+      t = argv[0];
+      argv[0] = dollar_vars[0];
+      ret = sh_getopt (argc, argv, optstr);
+      argv[0] = t;
+    }
+  else if (rest_of_args == (WORD_LIST *)NULL)
+    {
+      register int i;
+
+      for (i = 0; i < 10 && dollar_vars[i]; i++);
+      ret = sh_getopt (i, dollar_vars, optstr);
+    }
+  else
+    {
+      register int i;
+      register WORD_LIST *words;
+      char **v;
+
+      for (i = 0; i < 10 && dollar_vars[i]; i++);
+      for (words = rest_of_args; words; words = words->next, i++);
+      v = (char **)xmalloc ((i + 1) * sizeof (char *));
+      for (i = 0; i < 10 && dollar_vars[i]; i++)
+        v[i] = dollar_vars[i];
+      for (words = rest_of_args; words; words = words->next, i++)
+        v[i] = words->word->word;
+      v[i] = (char *)NULL;
+      ret = sh_getopt (i, v, optstr);
+      free (v);
+    }
+
+  if (special_error)
+    sh_opterr = old_opterr;
+
+  /* Set the OPTIND variable in any case, to handle "--" skipping. */
+  if (sh_optind < 10)
+    {
+      numval[14] = sh_optind + '0';
+      numval[15] = '\0';
+      i = 14;
+    }
+  else
+    {
+      numval[i = 15] = '\0';
+      n = sh_optind;
+      do
+       {
+         numval[--i] = (n % 10) + '0';
+       }
+      while (n /= 10);
+    }
+  bind_variable ("OPTIND", numval + i);
+
+  /* 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 SH_OPTOPT.  If an illegal option was encountered, OPTARG is
+     NULL.  If a required option argument was missing, OPTARG points
+     to a NULL string (that is, optarg[0] == 0). */
+  if (ret == '?')
+    {
+      if (sh_optarg == NULL)
+       ret = G_ILLEGAL_OPT;
+      else if (sh_optarg[0] == '\0')
+       ret = G_ARG_MISSING;
+    }
+           
+  if (ret == G_EOF)
+    {
+      bind_variable (name, "?");
+      return (EXECUTION_FAILURE);
+    }
+
+  if (ret == G_ILLEGAL_OPT)
+    {
+      /* Illegal option encountered. */
+      strval[0] = '?';
+      strval[1] = '\0';
+      bind_variable (name, strval);
+
+      if (special_error)
+       {
+         strval[0] = (char) sh_optopt;
+         strval[1] = '\0';
+         bind_variable ("OPTARG", strval);
+       }
+      else
+       makunbound ("OPTARG", shell_variables);
+      return (EXECUTION_SUCCESS);
+    }
+
+  if (ret == G_ARG_MISSING)
+    {
+      /* Required argument missing. */
+      if (special_error)
+       {
+         strval[0] = ':';
+         strval[1] = '\0';
+         bind_variable (name, strval);
+
+         strval[0] = (char) sh_optopt;
+         strval[1] = '\0';
+         bind_variable ("OPTARG", strval);
+       }
+      else
+       {
+         strval[0] = '?';
+         strval[1] = '\0';
+         bind_variable (name, strval);
+         makunbound ("OPTARG", shell_variables);
+       }
+      return (EXECUTION_SUCCESS);
+    }                  
+
+  bind_variable ("OPTARG", sh_optarg);
+
+  strval[0] = (char) ret;
+  strval[1] = '\0';
+  bind_variable (name, strval);
+
+  return (EXECUTION_SUCCESS);
+}
+
+/* The getopts builtin.  Build an argv, and call dogetopts with it. */
+int
+getopts_builtin (list)
+     WORD_LIST *list;
+{
+  register int i;
+  char **av;
+  int ac, ret;
+  WORD_LIST *t;
+
+  if (list == 0)
+    return EXECUTION_FAILURE;
+
+  for (t = list, ac = 0; t; t = t->next, ac++);
+
+  ac++;
+  av = (char **)xmalloc ((1 + ac) * sizeof (char *));
+  av[ac] = (char *) NULL;
+  av[0] = this_command_name;
+
+  for (t = list, i = 1; t; t = t->next, i++)
+    av[i] = t->word->word;
+
+  ret = dogetopts (ac, av);
+  free ((char *)av);
+  return (ret);
+}
+#endif /* GETOPTS_BUILTIN */
diff --git a/builtins/hash.def b/builtins/hash.def
new file mode 100644 (file)
index 0000000..f4d319b
--- /dev/null
@@ -0,0 +1,222 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES hash.c
+
+$BUILTIN hash
+$FUNCTION hash_builtin
+$SHORT_DOC hash [-r] [name ...]
+For each NAME, the full pathname of the command is determined and
+remembered.  The -r option causes the shell to forget all remembered
+locations.  If no arguments are given, information about remembered
+commands is presented.
+$END
+
+#include <sys/types.h>
+#include "../posixstat.h"
+
+#include <stdio.h>
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "../shell.h"
+#include "../builtins.h"
+#include "../flags.h"
+#include "hashcom.h"
+#include "common.h"
+#include "../execute_cmd.h"
+
+extern int dot_found_in_search;
+
+void
+initialize_filename_hashing ()
+{
+  hashed_filenames = make_hash_table (FILENAME_HASH_BUCKETS);
+}
+
+/* Print statistics on the current state of hashed commands.  If LIST is
+   not empty, then rehash (or hash in the first place) the specified
+   commands. */
+hash_builtin (list)
+     WORD_LIST *list;
+{
+  int expunge_hash_table = 0;
+  int any_failed = 0;
+
+  if (hashing_disabled)
+    {
+      builtin_error ("hashing disabled");
+      return (EXECUTION_FAILURE);
+    }
+
+  while (list)
+    {
+      char *arg = list->word->word;
+
+      if (ISOPTION (arg, 'r'))
+       {
+         expunge_hash_table = 1;
+         list = list->next;
+       }
+      else if (ISOPTION (arg, '-'))
+       {
+         list = list->next;
+         break;
+       }
+      else if (*arg == '-')
+       {
+         bad_option (list->word->word);
+         builtin_error ("usage: hash [-r] [command ...]");
+         return (EX_USAGE);
+       }
+      else
+       break;
+    }
+
+  /* We want hash -r to be silent, but hash -- to print hashing info.  That
+     is the reason for the !expunge_hash_table. */
+  if (!list && !expunge_hash_table)
+    {
+      /* Print information about current hashed info. */
+      int any_printed = 0;
+      int bucket = 0;
+      register BUCKET_CONTENTS *item_list;
+
+      while (bucket < hashed_filenames->nbuckets)
+       {
+         item_list = get_hash_bucket (bucket, hashed_filenames);
+         if (item_list)
+           {
+             if (!any_printed)
+               {
+                 printf ("hits\tcommand\n");
+                 any_printed++;
+               }
+             while (item_list)
+               {
+                 printf ("%4d\t%s\n",
+                         item_list->times_found, pathdata(item_list)->path);
+                 item_list = item_list->next;
+               }
+           }
+         bucket++;
+       }
+
+      if (!any_printed)
+       printf ("No commands in hash table.\n");
+
+      return (EXECUTION_SUCCESS);
+    }
+
+  if (expunge_hash_table)
+    {
+      int bucket = 0;
+      register BUCKET_CONTENTS *item_list, *prev;
+
+      while (bucket < hashed_filenames->nbuckets)
+       {
+         item_list = get_hash_bucket (bucket, hashed_filenames);
+         if (item_list)
+           {
+             while (item_list)
+               {
+                 prev = item_list;
+                 free (item_list->key);
+                 free (pathdata(item_list)->path);
+                 free (item_list->data);
+                 item_list = item_list->next;
+                 free (prev);
+               }
+             hashed_filenames->bucket_array[bucket] = (BUCKET_CONTENTS *)NULL;
+           }
+         bucket++;
+       }
+    }
+
+  while (list)
+    {
+      /* Add or rehash the specified commands. */
+      char *word;
+      char *full_path;
+      SHELL_VAR *var;
+
+      word = list->word->word;
+      if (absolute_program (word))
+       {
+         list = list->next;
+         continue;
+       }
+      full_path = find_user_command (word);
+      var = find_function (word);
+
+      if (!find_shell_builtin (word) && (!var))
+       {
+         if (full_path && executable_file (full_path))
+           remember_filename (word, full_path, dot_found_in_search, 0);
+         else
+           {
+             builtin_error ("%s: not found", word);
+             any_failed++;
+           }
+       }
+      if (full_path)
+       free (full_path);
+
+      list = list->next;
+    }
+
+  fflush (stdout);
+
+  if (any_failed)
+    return (EXECUTION_FAILURE);
+  else
+    return (EXECUTION_SUCCESS);
+}
+
+/* Place FILENAME (key) and FULL_PATHNAME (data->path) into the
+   hash table.  CHECK_DOT if non-null is for future calls to
+   find_hashed_filename ().  FOUND is the initial value for
+   times_found. */
+void
+remember_filename (filename, full_pathname, check_dot, found)
+     char *filename, *full_pathname;
+     int check_dot, found;
+{
+  register BUCKET_CONTENTS *item;
+
+  if (hashing_disabled)
+    return;
+  item = add_hash_item (filename, hashed_filenames);
+  if (item->data)
+    free (pathdata(item)->path);
+  else
+    {
+      item->key = savestring (filename);
+      item->data = (char *)xmalloc (sizeof (PATH_DATA));
+    }
+  pathdata(item)->path = savestring (full_pathname);
+  pathdata(item)->check_dot = check_dot;
+  item->times_found = found;
+}
diff --git a/builtins/hashcom.h b/builtins/hashcom.h
new file mode 100644 (file)
index 0000000..defe2fc
--- /dev/null
@@ -0,0 +1,32 @@
+/* hashcom.h - Common defines for hashing filenames. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "../hash.h"
+
+#define FILENAME_HASH_BUCKETS 631
+
+extern HASH_TABLE *hashed_filenames;
+
+typedef struct {
+  char *path;          /* The full pathname of the file. */
+  int check_dot;       /* Whether `.' appeared before this one in $PATH. */
+} PATH_DATA;
+
+#define pathdata(x) ((PATH_DATA *)(x)->data)
diff --git a/builtins/help.def b/builtins/help.def
new file mode 100644 (file)
index 0000000..c9f1db8
--- /dev/null
@@ -0,0 +1,134 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES help.c
+
+$BUILTIN help
+$FUNCTION help_builtin
+$SHORT_DOC help [pattern ...]
+Display helpful information about builtin commands.  If PATTERN is
+specified, gives detailed help on all commands matching PATTERN,
+otherwise a list of the builtins is printed.
+$END
+
+#include <stdio.h>
+#include "../shell.h"
+#include "../builtins.h"
+
+#if defined (USE_GLOB_LIBRARY)
+#  include <glob/glob.h>
+#else
+#  define FNM_NOMATCH 1
+#endif /* USE_GLOB_LIBRARY */
+
+/* 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
+   specified. */
+help_builtin (list)
+     WORD_LIST *list;
+{
+  if (!list)
+    {
+      register int i, j;
+      char blurb[256];
+
+      show_shell_version ();
+      printf (
+"Shell commands that 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\
+\n\
+A star (*) next to a name means that the command is disabled.\n\
+\n");
+
+      for (i = 0; i < num_shell_builtins; i++)
+       {
+         QUIT;
+         sprintf (blurb, "%c%s",
+                  (shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*',
+                  shell_builtins[i].short_doc);
+
+         blurb[35] = '\0';
+         printf ("%s", blurb);
+
+         if (i % 2)
+           printf ("\n");
+         else
+           for (j = strlen (blurb); j < 35; j++)
+             putc (' ', stdout);
+
+       }
+      if (i % 2)
+       printf ("\n");
+    }
+  else
+    {
+      int match_found = 0;
+      char *pattern = "";
+
+      if (glob_pattern_p (list->word->word))
+       {
+         printf ("Shell commands matching keyword%s `",
+                 list->next ? "s" : "");
+         print_word_list (list, ", ");
+         printf ("'\n\n");
+       }
+
+      while (list)
+       {
+         register int i = 0, plen;
+         char *name;
+
+         pattern = list->word->word;
+         plen = strlen (pattern);
+
+         while (name = shell_builtins[i].name)
+           {
+             int doc_index;
+
+             QUIT;
+             if ((strncmp (pattern, name, plen) == 0) ||
+                 (fnmatch (pattern, name, 0) != FNM_NOMATCH))
+               {
+                 printf ("%s: %s\n", name, shell_builtins[i].short_doc);
+
+                 for (doc_index = 0;
+                      shell_builtins[i].long_doc[doc_index]; doc_index++)
+                   printf ("    %s\n", shell_builtins[i].long_doc[doc_index]);
+
+                 match_found++;
+               }
+             i++;
+           }
+         list = list->next;
+       }
+
+      if (!match_found)
+       {
+         fprintf (stderr, "No help topics match `%s'.  Try `help help'.\n",
+                  pattern);
+         fflush (stderr);
+         return (EXECUTION_FAILURE);
+       }
+    }
+  fflush (stdout);
+  return (EXECUTION_SUCCESS);
+}
diff --git a/builtins/history.def b/builtins/history.def
new file mode 100644 (file)
index 0000000..814e705
--- /dev/null
@@ -0,0 +1,179 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES history.c
+
+$BUILTIN history
+$FUNCTION history_builtin
+$DEPENDS_ON HISTORY
+$SHORT_DOC history [n] [ [-awrn] [filename]]
+Display the history list with line numbers.  Lines listed with
+with a `*' have been modified.  Argument of N says to list only
+the last N lines.  Argument `-w' means to write out the current
+history file;  `-r' means to read it instead.  Argument `-a' means
+to append history lines from this session to the history file.
+Argument `-n' means to read all history lines not already read
+from the history file.  If FILENAME is given, then use that file,
+else if $HISTFILE has a value, use that, else use ~/.bash_history.
+$END
+
+#include "../shell.h"
+#if defined (HISTORY)
+#include <sys/types.h>
+#include <sys/file.h>
+#include "../filecntl.h"
+#include "../posixstat.h"
+#include "../bashhist.h"
+#include <readline/history.h>
+
+/* History.  Arg of -w FILENAME means write file, arg of -r FILENAME
+   means read file.  Arg of N means only display that many items. */
+
+history_builtin (list)
+     WORD_LIST *list;
+{
+  register int i;
+  int limited = 0, limit = 0;
+  HIST_ENTRY **hlist;
+
+  while (list)
+    {
+      char *arg = list->word->word;
+
+      if ((arg[0] == '-') &&
+         (strlen (arg) == 2) &&
+         (member (arg[1], "rwan")))
+       {
+         char *file;
+         int result = EXECUTION_SUCCESS;
+
+         if (list->next)
+           file = list->next->word->word;
+         else
+           file = get_string_value ("HISTFILE");
+
+         switch (arg[1])
+           {
+           case 'a':           /* Append `new' lines to file. */
+             {
+               if (history_lines_this_session)
+                 {
+                   void using_history ();
+
+                   if (history_lines_this_session < where_history ())
+                     {
+                       /* If the filename was supplied, then create it
+                          if it doesn't already exist. */
+                       if (file)
+                         {
+                           struct stat buf;
+
+                           if (stat (file, &buf) == -1)
+                             {
+                               int tem;
+
+                               tem = open (file, O_CREAT, 0666);
+                               close (tem);
+                             }
+                         }
+
+                       result =
+                         append_history (history_lines_this_session, file);
+                       history_lines_in_file += history_lines_this_session;
+                       history_lines_this_session = 0;
+                     }
+                 }
+               break;
+             }
+
+           case 'w':           /* Write entire history. */
+             {
+               result = write_history (file);
+               break;
+             }
+
+           case 'r':           /* Read entire file. */
+             {
+               result = read_history (file);
+               break;
+             }
+
+           case 'n':           /* Read `new' history from file. */
+             {
+               /* Read all of the lines in the file that we haven't
+                  already read. */
+               using_history ();
+               result = read_history_range (file, history_lines_in_file, -1);
+               using_history ();
+               history_lines_in_file = where_history ();
+
+               break;
+             }
+           }
+         return (result ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+       }
+      else if (strcmp (list->word->word, "--") == 0)
+       {
+         list = list->next;
+         break;
+       }
+      else if (*list->word->word == '-')
+       {
+         bad_option (list->word->word);
+         builtin_error ("usage: history [n] [-rwan [filename]]");
+         return (EX_USAGE);
+       }
+      else
+       break;
+    }
+
+  if (list)
+    {
+      limited = 1;
+      limit = get_numeric_arg (list);
+    }
+
+  hlist = history_list ();
+
+  if (hlist)
+    {
+      for (i = 0;  hlist[i]; i++);
+
+      if (limit < 0)
+       limit = -limit;
+
+      if (!limited)
+       i = 0;
+      else
+       if ((i -= limit) < 0)
+         i = 0;
+
+      while (hlist[i])
+       {
+         QUIT;
+         printf ("%5d%c %s\n", i + history_base,
+                 hlist[i]->data ? '*' : ' ', hlist[i]->line);
+         i++;
+       }
+    }
+  return (EXECUTION_SUCCESS);
+}
+#endif /* HISTORY */
diff --git a/builtins/inlib.def b/builtins/inlib.def
new file mode 100644 (file)
index 0000000..023945b
--- /dev/null
@@ -0,0 +1,74 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES inlib.c
+#include <stdio.h>
+#include "../shell.h"
+
+$BUILTIN inlib
+$FUNCTION inlib_builtin
+$DEPENDS_ON apollo
+$SHORT_DOC inlib pathname [pathname...]
+Install a user-supplied library specified by pathname in the current
+shell process. The library is used to resolve external references
+in programs and libraries loaded after its installation.  Note
+that the library is not loaded into the address space unless it is
+needed to resolve an external reference.  The list of inlibed
+libraries is passed to all children of the current shell.
+$END
+
+#if defined (apollo)
+
+#include <apollo/base.h>
+#include <apollo/loader.h>
+
+inlib_builtin (list)
+     WORD_LIST *list;
+{
+  status_$t status;
+  int return_value;
+  short len;
+
+  if (!list)
+    {
+      builtin_error ("usage: inlib pathname [pathname...]");
+      return (EX_USAGE);
+    }
+
+  return_value = EXECUTION_SUCCESS;
+
+  while (list)
+    {
+      len = (short)strlen (list->word->word);
+      loader_$inlib (list->word->word, len, &status);
+
+      if (status.all != status_$ok)
+       {
+         builtin_error ("inlib failed for %s", list->word->word);
+         return_value = EXECUTION_FAILURE;
+       }
+
+      list = list->next;
+    }
+
+  return (return_value);
+}
+#endif /* apollo */
diff --git a/builtins/jobs.def b/builtins/jobs.def
new file mode 100644 (file)
index 0000000..8a293da
--- /dev/null
@@ -0,0 +1,171 @@
+This file is jobs.def, from which is created jobs.c.
+It implements the builtin "jobs" in Bash.
+
+Copyright (C) 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES jobs.c
+
+$BUILTIN jobs
+$FUNCTION jobs_builtin
+$DEPENDS_ON JOB_CONTROL
+$SHORT_DOC jobs [-lnp] [jobspec ...] | jobs -x command [args]
+Lists the active jobs.  The -l option lists process id's in addition
+to the normal information; the -p option lists process id's only.
+If -n is given, only processes that have changed status since the last
+notification are printed.  JOBSPEC restricts output to that job.
+If -x is given, COMMAND is run after all job specifications that appear
+in ARGS have been replaced with the process ID of that job's process group
+leader.
+$END
+
+#include "../shell.h"
+
+#if defined (JOB_CONTROL)
+#include <sys/types.h>
+#include <signal.h>
+#include "../jobs.h"
+
+#include "bashgetopt.h"
+
+extern int job_control, interactive_shell;
+static int execute_list_with_replacements ();
+
+/* The `jobs' command.  Prints outs a list of active jobs.  If the
+   argument `-l' is given, then the process id's are printed also.
+   If the argument `-p' is given, print the process group leader's
+   pid only.  If `-n' is given, only processes that have changed
+   status since the last notification are printed.  If -x is given,
+   replace all job specs with the pid of the appropriate process
+   group leader and execute the command. */
+int
+jobs_builtin (list)
+     WORD_LIST *list;
+{
+  int form = JLIST_STANDARD, execute = 0;
+  int opt;
+  int any_failed = 0;
+
+  if (!job_control && !interactive_shell)
+    return (EXECUTION_SUCCESS);
+
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, "lpnx")) != -1)
+    {
+      switch (opt)
+       {
+       case 'l':
+         form = JLIST_LONG;
+         break;
+       case 'p':
+         form = JLIST_PID_ONLY;
+         break;
+       case 'n':
+         form = JLIST_CHANGED_ONLY;
+         break;
+       case 'x':
+         if (form != JLIST_STANDARD)
+           {
+             builtin_error ("Other options not allowed with `-x'");
+             return (EXECUTION_FAILURE);
+           }
+         execute++;
+         break;
+
+       default:
+         builtin_error ("usage: jobs [-lpn [jobspec]] [-x command [args]]");
+         return (EX_USAGE);
+       }
+    }
+
+  list = loptend;
+
+  if (execute)
+    return (execute_list_with_replacements (list));
+
+  if (!list)
+    {
+      list_jobs (form);
+      return (EXECUTION_SUCCESS);
+    }
+
+  while (list)
+    {
+      int job;
+      sigset_t set, oset;
+
+      BLOCK_CHILD (set, oset);
+      job = get_job_spec (list);
+
+      if ((job == NO_JOB) || !jobs || !jobs[job])
+       {
+         builtin_error ("No such job %s", list->word->word);
+         any_failed++;
+       }
+      else if (job != DUP_JOB)
+       list_one_job ((JOB *)NULL, form, 0, job);
+
+      UNBLOCK_CHILD (oset);
+      list = list->next;
+    }
+  return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+}
+
+static int
+execute_list_with_replacements (list)
+     WORD_LIST *list;
+{
+  register WORD_LIST *l;
+  int job, result;
+
+  /* First do the replacement of job specifications with pids. */
+  for (l = list; l; l = l->next)
+    {
+      if (l->word->word[0] == '%')     /* we have a winner */
+       {
+         job = get_job_spec (l);
+
+         /* A bad job spec is not really a job spec! Pass it through. */
+         if (job < 0 || job >= job_slots || !jobs[job])
+           continue;
+
+         free (l->word->word);
+         l->word->word = itos (jobs[job]->pgrp);
+       }
+    }
+
+  /* Next make a new simple command and execute it. */
+  begin_unwind_frame ("jobs_builtin");
+  {
+    COMMAND *command = (COMMAND *)NULL;
+
+    add_unwind_protect (dispose_command, command);
+
+    command = make_bare_simple_command ();
+    command->value.Simple->words = copy_word_list (list);
+    command->value.Simple->redirects = (REDIRECT *)NULL;
+    command->flags |= CMD_INHIBIT_EXPANSION;
+    command->value.Simple->flags |= CMD_INHIBIT_EXPANSION;
+
+    result = execute_command (command);
+  }
+
+  run_unwind_frame ("jobs_builtin");
+  return (result);
+}
+#endif /* JOB_CONTROL */
diff --git a/builtins/kill.def b/builtins/kill.def
new file mode 100644 (file)
index 0000000..53d5c8f
--- /dev/null
@@ -0,0 +1,281 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES kill.c
+
+$BUILTIN kill
+$FUNCTION kill_builtin
+$DEPENDS_ON JOB_CONTROL
+$SHORT_DOC kill [-s sigspec | -sigspec] [pid | job]... | -l [signum]
+Send the processes named by PID (or JOB) the signal SIGSPEC.  If
+SIGSPEC is not present, then SIGTERM is assumed.  An argument of `-l'
+lists the signal names; if arguments follow `-l' they are assumed to
+be signal numbers for which names should be listed.  Kill is a shell
+builtin for two reasons: it allows job IDs to be used instead of
+process IDs, and, if you have reached the limit on processes that
+you can create, you don't have to start a process to kill another one.
+$END
+
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "../bashtypes.h"
+#include "../shell.h"
+#include "../trap.h"
+#include "../jobs.h"
+#include "common.h"
+#include <errno.h>
+
+#if defined (JOB_CONTROL)
+extern int interactive;
+extern int posixly_correct;
+
+#if !defined (CONTINUE_AFTER_KILL_ERROR)
+#  define CONTINUE_OR_FAIL return (EXECUTION_FAILURE)
+#else
+#  define CONTINUE_OR_FAIL goto continue_killing
+#endif /* CONTINUE_AFTER_KILL_ERROR */
+
+/* Here is the kill builtin.  We only have it so that people can type
+   kill -KILL %1?  No, if you fill up the process table this way you
+   can still kill some. */
+int
+kill_builtin (list)
+     WORD_LIST *list;
+{
+  int signal = SIGTERM;
+  int any_succeeded = 0, listing = 0, saw_signal = 0;
+  char *sigspec = "TERM", *word;
+  pid_t pid;
+
+  if (!list)
+    return (EXECUTION_SUCCESS);
+
+  /* Process options. */
+  while (list)
+    {
+      word = list->word->word;
+
+      if (ISOPTION (word, 'l'))
+       {
+         listing++;
+         list = list->next;
+       }
+      else if (ISOPTION (word, 's'))
+       {
+         list = list->next;
+         if (list)
+           {
+             sigspec = list->word->word;
+             if (sigspec[0] == '0' && !sigspec[1])
+               signal = 0;
+             else
+               signal = decode_signal (sigspec);
+             list = list->next;
+           }
+         else
+           {
+             builtin_error ("-s requires an argument");
+             return (EXECUTION_FAILURE);
+           }
+       }
+      else if (ISOPTION (word, '-'))
+       {
+         list = list->next;
+         break;
+       }
+      /* If this is a signal specification then process it.  We only process
+        the first one seen; other arguments may signify process groups (e.g,
+        -num == process group num). */
+      else if ((*word == '-') && !saw_signal)
+       {
+         sigspec = word + 1;
+         signal = decode_signal (sigspec);
+         saw_signal++;
+         list = list->next;
+       }
+      else
+       break;
+    }
+
+  if (listing)
+    {
+      if (!list)
+       {
+         register int i;
+         register int column = 0;
+         char *name;
+
+         for (i = 1; i < NSIG; i++)
+           {
+             name = signal_name (i);
+             if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
+               continue;
+
+             if (posixly_correct)
+               printf ("%s%s", name, (i == NSIG - 1) ? "" : " ");
+             else
+               {
+                 printf ("%2d) %s", i, name);
+
+                 if (++column < 4)
+                   printf ("\t");
+                 else
+                   {
+                     printf ("\n");
+                     column = 0;
+                   }
+               }
+           }
+
+         if (posixly_correct || column != 0)
+           printf ("\n");
+       }
+      else
+       {
+         /* List individual signal names. */
+         while (list)
+           {
+             int signum;
+             char *name;
+
+             if ((sscanf (list->word->word, "%d", &signum) != 1) ||
+                 (signum <= 0))
+               {
+           list_error:
+                 builtin_error ("bad signal number: %s", list->word->word);
+                 list = list->next;
+                 continue;
+               }
+
+             /* This is specified by Posix.2 so that exit statuses can be
+                mapped into signal numbers. */
+             if (signum > 128)
+               signum -= 128;
+
+             if (signum >= NSIG)
+               goto list_error;
+
+             name = signal_name (signum);
+             if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
+               {
+                 list = list->next;
+                 continue;
+               }
+             printf ("%s\n", name);
+             list = list->next;
+           }
+       }
+      return (EXECUTION_SUCCESS);
+    }
+
+  /* OK, we are killing processes. */
+  if (signal == NO_SIG)
+    {
+      builtin_error ("bad signal spec `%s'", sigspec);
+      return (EXECUTION_FAILURE);
+    }
+
+  while (list)
+    {
+      word = list->word->word;
+
+      if (*word == '-')
+       word++;
+
+      if (all_digits (word))
+       {
+         /* Use the entire argument in case of minus sign presence. */
+         pid = (pid_t) atoi (list->word->word);
+
+         if (kill_pid (pid, signal, 0) < 0)
+           goto signal_error;
+         else
+           any_succeeded++;
+       }
+      else if (*list->word->word != '%')
+       {
+         builtin_error ("No such pid %s", list->word->word);
+         CONTINUE_OR_FAIL;
+       }
+#if 1
+      else if (interactive)
+       /* Posix.2 says you can kill without job control active (4.32.4) */
+#else
+      else if (job_control)    /* can't kill jobs if not using job control */
+#endif
+       {                       /* Must be a job spec.  Check it out. */
+         int job;
+         sigset_t set, oset;
+
+         BLOCK_CHILD (set, oset);
+         job = get_job_spec (list);
+
+         if (job < 0 || job >= job_slots || !jobs[job])
+           {
+             if (job != DUP_JOB)
+               builtin_error ("No such job %s", list->word->word);
+             UNBLOCK_CHILD (oset);
+             CONTINUE_OR_FAIL;
+           }
+
+         /* Job spec used.  Kill the process group. If the job was started
+            without job control, then its pgrp == shell_pgrp, so we have
+            to be careful.  We take the pid of the first job in the pipeline
+            in that case. */
+         if (jobs[job]->flags & J_JOBCONTROL)
+           pid = jobs[job]->pgrp;
+         else
+           pid = jobs[job]->pipe->pid;
+
+         UNBLOCK_CHILD (oset);
+
+         if (kill_pid (pid, signal, 1) < 0)
+           {
+           signal_error:
+             if (errno == EPERM)
+               builtin_error ("(%d) - Not owner", (int)pid);
+             else if (errno == ESRCH)
+               builtin_error ("(%d) - No such pid", (int)pid);
+             else
+               builtin_error ("Invalid signal %d", signal);
+             CONTINUE_OR_FAIL;
+           }
+         else
+           any_succeeded++;
+       }
+      else
+       {
+         builtin_error ("bad process specification `%s'", list->word->word);
+         CONTINUE_OR_FAIL;
+       }
+    continue_killing:
+      list = list->next;
+    }
+
+  if (any_succeeded)
+    return (EXECUTION_SUCCESS);
+  else
+    return (EXECUTION_FAILURE);
+}
+#endif /* JOB_CONTROL */
diff --git a/builtins/let.def b/builtins/let.def
new file mode 100644 (file)
index 0000000..fdb3a6f
--- /dev/null
@@ -0,0 +1,77 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$BUILTIN let
+$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.
+The levels are listed in order of decreasing precedence.
+
+       -               unary minus
+       !               logical NOT
+       * / %           multiplication, division, remainder
+       + -             addition, subtraction
+       <= >= < >       comparison
+       == !=           equality inequality
+       =               assignment
+
+Shell variables are allowed as operands.  The name of the variable
+is replaced by its value (coerced to a long integer) within
+an expression.  The variable need not have its integer attribute
+turned on to be used in an expression.
+
+Operators are evaluated in order of precedence.  Sub-expressions in
+parentheses are evaluated first and may override the precedence
+rules above.
+
+If the last ARG evaluates to 0, let returns 1; 0 is returned
+otherwise.
+$END
+
+#include "../shell.h"
+
+/* Arithmetic LET function. */
+let_builtin (list)
+     WORD_LIST *list;
+{
+  long ret = 0L;
+
+  if (!list)
+    {
+      builtin_error ("argument (expression) expected");
+      return (EXECUTION_FAILURE);
+    }
+
+  while (list)
+    {
+      ret = evalexp (list->word->word);
+      list = list->next;
+    }
+
+  if (ret == 0L)
+    return (EXECUTION_FAILURE);
+  else
+    return (EXECUTION_SUCCESS);
+}
diff --git a/builtins/mkbuiltins.c b/builtins/mkbuiltins.c
new file mode 100644 (file)
index 0000000..572d01e
--- /dev/null
@@ -0,0 +1,1311 @@
+/* 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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "../bashansi.h"
+#include "../config.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include "../filecntl.h"
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#define DOCFILE "builtins.texi"
+
+static char *xmalloc (), *xrealloc ();
+
+#if !defined (__STDC__) && !defined (strcpy)
+extern char *strcpy ();
+#endif /* !__STDC__ && !strcpy */
+
+#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+
+/* Flag values that builtins can have. */
+#define BUILTIN_FLAG_SPECIAL   0x01
+
+/* If this stream descriptor is non-zero, then write
+   texinfo documentation to it. */
+FILE *documentation_file = (FILE *)NULL;
+
+/* Non-zero means to only produce documentation. */
+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 */
+
+/* The name of a directory to precede the filename when reporting
+   errors. */
+char *error_directory = (char *)NULL;
+
+/* The name of the structure file. */
+char *struct_filename = (char *)NULL;
+
+/* The name of the external declaration file. */
+char *extern_filename = (char *)NULL;
+
+/* Here is a structure for manipulating arrays of data. */
+typedef struct {
+  int size;            /* Number of slots allocated to array. */
+  int sindex;          /* Current location in array. */
+  int width;           /* Size of each element. */
+  int growth_rate;     /* How fast to grow. */
+  char **array;                /* The array itself. */
+} ARRAY;
+
+/* Here is a structure defining a single BUILTIN. */
+typedef struct {
+  char *name;          /* The name of this builtin. */
+  char *function;      /* The name of the function to call. */
+  char *shortdoc;      /* The short documentation for this builtin. */
+  char *docname;       /* Possible name for documentation string. */
+  ARRAY *longdoc;      /* The long documentation for this builtin. */
+  ARRAY *dependencies; /* Null terminated array of #define names. */
+  int flags;           /* Flags for this builtin. */
+} BUILTIN_DESC;
+
+/* Here is a structure which defines a DEF file. */
+typedef struct {
+  char *filename;      /* The name of the input def file. */
+  ARRAY *lines;                /* The contents of the file. */
+  int line_number;     /* The current line number. */
+  char *production;    /* The name of the production file. */
+  FILE *output;                /* Open file stream for PRODUCTION. */
+  ARRAY *builtins;     /* Null terminated array of BUILTIN_DESC *. */
+} DEF_FILE;
+
+/* The array of all builtins encountered during execution of this code. */
+ARRAY *saved_builtins = (ARRAY *)NULL;
+
+/* The Posix.2 so-called `special' builtins. */
+char *special_builtins[] =
+{
+  ":", ".", "source", "break", "continue", "eval", "exec", "exit",
+  "export", "readonly", "return", "set", "shift", "trap", "unset",
+  (char *)NULL
+};
+static int is_special_builtin ();
+
+\f
+/* For each file mentioned on the command line, process it and
+   write the information to STRUCTFILE and EXTERNFILE, while
+   creating the production file if neccessary. */
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int arg_index = 1;
+  FILE *structfile, *externfile;
+  char *documentation_filename, *temp_struct_filename;
+
+  structfile = externfile = (FILE *)NULL;
+  documentation_filename = DOCFILE;
+  temp_struct_filename = (char *)NULL;
+
+  while (arg_index < argc && argv[arg_index][0] == '-')
+    {
+      char *arg = argv[arg_index++];
+
+      if (strcmp (arg, "-externfile") == 0)
+       extern_filename = argv[arg_index++];
+      else if (strcmp (arg, "-structfile") == 0)
+       struct_filename = argv[arg_index++];
+      else if (strcmp (arg, "-noproduction") == 0)
+       inhibit_production = 1;
+      else if (strcmp (arg, "-document") == 0)
+       documentation_file = fopen (documentation_filename, "w");
+      else if (strcmp (arg, "-D") == 0)
+       {
+         int len;
+
+         if (error_directory)
+           free (error_directory);
+
+         error_directory = xmalloc (2 + strlen (argv[arg_index]));
+         strcpy (error_directory, argv[arg_index]);
+         len = strlen (error_directory);
+
+         if (len && error_directory[len - 1] != '/')
+           strcat (error_directory, "/");
+
+         arg_index++;
+       }
+      else if (strcmp (arg, "-documentonly") == 0)
+       {
+         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
+       {
+         fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
+         exit (2);
+       }
+    }
+
+  /* If there are no files to process, just quit now. */
+  if (arg_index == argc)
+    exit (0);
+
+  if (!only_documentation)
+    {
+      /* Open the files. */
+      if (struct_filename)
+       {
+         temp_struct_filename = xmalloc (15);
+         sprintf (temp_struct_filename, "mk-%d", (int) getpid ());
+         structfile = fopen (temp_struct_filename, "w");
+
+         if (!structfile)
+           file_error (temp_struct_filename);
+       }
+
+      if (extern_filename)
+       {
+         externfile = fopen (extern_filename, "w");
+
+         if (!externfile)
+           file_error (extern_filename);
+       }
+
+      /* Write out the headers. */
+      write_file_headers (structfile, externfile);
+    }
+
+  if (documentation_file)
+    {
+      fprintf (documentation_file, "@c Table of builtins created with %s.\n",
+              argv[0]);
+      fprintf (documentation_file, "@ftable @asis\n");
+    }
+
+  /* Process the .def files. */
+  while (arg_index < argc)
+    {
+      register char *arg;
+
+      arg = argv[arg_index++];
+
+      extract_info (arg, structfile, externfile);
+    }
+
+  /* Close the files. */
+  if (!only_documentation)
+    {
+      /* Write the footers. */
+      write_file_footers (structfile, externfile);
+
+      if (structfile)
+       {
+         write_longdocs (structfile, saved_builtins);
+         fclose (structfile);
+         link (temp_struct_filename, struct_filename);
+         unlink (temp_struct_filename);
+       }
+
+      if (externfile)
+       fclose (externfile);
+    }
+
+  if (documentation_file)
+    {
+      fprintf (documentation_file, "@end ftable\n");
+      fclose (documentation_file);
+    }
+
+  exit (0);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*               Array Functions and Manipulators                  */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Make a new array, and return a pointer to it.  The array will
+   contain elements of size WIDTH, and is initialized to no elements. */
+ARRAY *
+array_create (width)
+     int width;
+{
+  ARRAY *array;
+
+  array = (ARRAY *)xmalloc (sizeof (ARRAY));
+  array->size = 0;
+  array->sindex = 0;
+  array->width = width;
+
+  /* Default to increasing size in units of 20. */
+  array->growth_rate = 20;
+
+  array->array = (char **)NULL;
+
+  return (array);
+}
+
+/* Copy the array of strings in ARRAY. */
+ARRAY *
+copy_string_array (array)
+     ARRAY *array;
+{
+  register int i;
+  ARRAY *copy;
+
+  if (!array)
+    return (ARRAY *)NULL;
+
+  copy = array_create (sizeof (char *));
+
+  copy->size = array->size;
+  copy->sindex = array->sindex;
+  copy->width = array->width;
+
+  copy->array = (char **)xmalloc ((1 + array->sindex) * sizeof (char *));
+  
+  for (i = 0; i < array->sindex; i++)
+    copy->array[i] = savestring (array->array[i]);
+
+  copy->array[i] = (char *)NULL;
+
+  return (copy);
+}
+
+/* Add ELEMENT to ARRAY, growing the array if neccessary. */
+array_add (element, array)
+     char *element;
+     ARRAY *array;
+{
+  if (array->sindex + 2 > array->size)
+    array->array = (char **)xrealloc
+      (array->array, (array->size += array->growth_rate) * array->width);
+
+#if defined (HAVE_BCOPY)
+  bcopy (&element, &(array->array[array->sindex]), array->width);
+  array->sindex++;
+  bzero (&(array->array[array->sindex]), array->width);
+#else
+  array->array[array->sindex++] = element;
+  array->array[array->sindex] = (char *)NULL;
+#endif /* !HAVE_BCOPY */
+}
+
+/* Free an allocated array and data pointer. */
+array_free (array)
+     ARRAY *array;
+{
+  if (array->array)
+    free (array->array);
+
+  free (array);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                    Processing a DEF File                        */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The definition of a function. */
+typedef int Function ();
+
+/* Structure handles processor directives. */
+typedef struct {
+  char *directive;
+  Function *function;
+} HANDLER_ENTRY;
+
+extern int
+  builtin_handler (), function_handler (), short_doc_handler (),
+  comment_handler (), depends_on_handler (), produces_handler (),
+  end_handler (), docname_handler ();
+
+HANDLER_ENTRY handlers[] = {
+  { "BUILTIN", builtin_handler },
+  { "DOCNAME", docname_handler },
+  { "FUNCTION", function_handler },
+  { "SHORT_DOC", short_doc_handler },
+  { "$", comment_handler },
+  { "COMMENT", comment_handler },
+  { "DEPENDS_ON", depends_on_handler },
+  { "PRODUCES", produces_handler },
+  { "END", end_handler },
+  { (char *)NULL, (Function *)NULL }
+};
+
+/* Return the entry in the table of handlers for NAME. */
+HANDLER_ENTRY *
+find_directive (directive)
+     char *directive;
+{
+  register int i;
+
+  for (i = 0; handlers[i].directive; i++)
+    if (strcmp (handlers[i].directive, directive) == 0)
+      return (&handlers[i]);
+
+  return ((HANDLER_ENTRY *)NULL);
+}
+
+/* Non-zero indicates that a $BUILTIN has been seen, but not
+   the corresponding $END. */
+static int building_builtin = 0;
+
+/* Non-zero means to output cpp line and file information before
+   printing the current line to the production file. */
+int output_cpp_line_info = 0;
+
+/* The main function of this program.  Read FILENAME and act on what is
+   found.  Lines not starting with a dollar sign are copied to the
+   $PRODUCES target, if one is present.  Lines starting with a dollar sign
+   are directives to this program, specifying the name of the builtin, the
+   function to call, the short documentation and the long documentation
+   strings.  FILENAME can contain multiple $BUILTINs, but only one $PRODUCES
+   target.  After the file has been processed, write out the names of
+   builtins found in each $BUILTIN.  Plain text found before the $PRODUCES
+   is ignored, as is "$$ comment text". */
+extract_info (filename, structfile, externfile)
+     char *filename;
+     FILE *structfile, *externfile;
+{
+  register int i;
+  DEF_FILE *defs;
+  struct stat finfo;
+  char *buffer, *line;
+  int fd;
+
+  if (stat (filename, &finfo) == -1)
+    file_error (filename);
+
+  fd = open (filename, O_RDONLY, 0666);
+
+  if (fd == -1)
+    file_error (filename);
+
+  buffer = xmalloc (1 + (int)finfo.st_size);
+
+  if (read (fd, buffer, finfo.st_size) != finfo.st_size)
+    file_error (filename);
+
+  close (fd);
+
+  /* Create and fill in the initial structure describing this file. */
+  defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE));
+  defs->filename = filename;
+  defs->lines = array_create (sizeof (char *));
+  defs->line_number = 0;
+  defs->production = (char *)NULL;
+  defs->output = (FILE *)NULL;
+  defs->builtins = (ARRAY *)NULL;
+
+  /* Build the array of lines. */
+  i = 0;
+  while (i < finfo.st_size)
+    {
+      array_add (&buffer[i], defs->lines);
+
+      while (buffer[i] != '\n' && i < finfo.st_size)
+       i++;
+      buffer[i++] = '\0';
+    }
+
+  /* Begin processing the input file.  We don't write any output
+     until we have a file to write output to. */
+  output_cpp_line_info = 1;
+
+  /* Process each line in the array. */
+  for (i = 0; line = defs->lines->array[i]; i++)
+    {
+      defs->line_number = i;
+
+      if (*line == '$')
+       {
+         register int j;
+         char *directive;
+         HANDLER_ENTRY *handler;
+
+         /* Isolate the directive. */
+         for (j = 0; line[j] && !whitespace (line[j]); j++);
+
+         directive = xmalloc (j);
+         strncpy (directive, line + 1, j - 1);
+         directive[j -1] = '\0';
+
+         /* Get the function handler and call it. */
+         handler = find_directive (directive);
+
+         if (!handler)
+           {
+             line_error (defs, "Unknown directive `%s'", directive);
+             free (directive);
+             continue;
+           }
+         else
+           {
+             /* Advance to the first non-whitespace character. */
+             while (whitespace (line[j]))
+               j++;
+
+             /* Call the directive handler with the FILE, and ARGS. */
+             (*(handler->function)) (directive, defs, line + j);
+           }
+         free (directive);
+       }
+      else
+       {
+         if (building_builtin)
+           add_documentation (defs, line);
+         else if (defs->output)
+           {
+             if (output_cpp_line_info)
+               {
+                 /* If we're handed an absolute pathname, don't prepend
+                    the directory name. */
+                 if (defs->filename[0] == '/')
+                   fprintf (defs->output, "#line %d \"%s\"\n",
+                            defs->line_number + 1, defs->filename);
+                 else
+                   fprintf (defs->output, "#line %d \"%s%s\"\n",
+                            defs->line_number + 1,
+                            error_directory ? error_directory : "./",
+                            defs->filename);
+                 output_cpp_line_info = 0;
+               }
+
+             fprintf (defs->output, "%s\n", line);
+           }
+       }
+    }
+
+  /* Close the production file. */
+  if (defs->output)
+    fclose (defs->output);
+
+  /* The file has been processed.  Write the accumulated builtins to
+     the builtins.c file, and write the extern definitions to the
+     builtext.h file. */
+  write_builtins (defs, structfile, externfile);
+
+  free (buffer);
+  free_defs (defs);
+}
+
+#define free_safely(x) if (x) free (x)
+
+static void
+free_builtin (builtin)
+     BUILTIN_DESC *builtin;
+{
+  register int i;
+
+  free_safely (builtin->name);
+  free_safely (builtin->function);
+  free_safely (builtin->shortdoc);
+  free_safely (builtin->docname);
+
+  if (builtin->longdoc)
+    array_free (builtin->longdoc);
+
+  if (builtin->dependencies)
+    {
+      for (i = 0; builtin->dependencies->array[i]; i++)
+       free (builtin->dependencies->array[i]);
+      array_free (builtin->dependencies);
+    }
+}
+
+/* Free all of the memory allocated to a DEF_FILE. */
+free_defs (defs)
+     DEF_FILE *defs;
+{
+  register int i;
+  register BUILTIN_DESC *builtin;
+
+  if (defs->production)
+    free (defs->production);
+
+  if (defs->lines)
+    array_free (defs->lines);
+
+  if (defs->builtins)
+    {
+      for (i = 0; builtin = (BUILTIN_DESC *)defs->builtins->array[i]; i++)
+        {
+         free_builtin (builtin);
+         free (builtin);
+        }
+      array_free (defs->builtins);
+    }
+  free (defs);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                  The Handler Functions Themselves               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Strip surrounding whitespace from STRING, and
+   return a pointer to the start of it. */
+char *
+strip_whitespace (string)
+     char *string;
+{
+  while (whitespace (*string))
+      string++;
+
+  remove_trailing_whitespace (string);
+  return (string);
+}
+
+/* Remove only the trailing whitespace from STRING. */
+remove_trailing_whitespace (string)
+     char *string;
+{
+  register int i;
+
+  i = strlen (string) - 1;
+
+  while (i > 0 && whitespace (string[i]))
+    i--;
+
+  string[++i] = '\0';
+}
+
+/* Ensure that there is a argument in STRING and return it.
+   FOR_WHOM is the name of the directive which needs the argument.
+   DEFS is the DEF_FILE in which the directive is found.
+   If there is no argument, produce an error. */
+char *
+get_arg (for_whom, defs, string)
+     char *for_whom, *string;
+     DEF_FILE *defs;
+{
+  char *new;
+
+  new = strip_whitespace (string);
+
+  if (!*new)
+    line_error (defs, "%s requires an argument", for_whom);
+
+  return (savestring (new));
+}
+
+/* Error if not building a builtin. */
+must_be_building (directive, defs)
+     char *directive;
+     DEF_FILE *defs;
+{
+  if (!building_builtin)
+    line_error (defs, "%s must be inside of a $BUILTIN block", directive);
+}
+
+/* Return the current builtin. */
+BUILTIN_DESC *
+current_builtin (directive, defs)
+     char *directive;
+     DEF_FILE *defs;
+{
+  must_be_building (directive, defs);
+  return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]);
+}
+
+/* Add LINE to the long documentation for the current builtin.
+   Ignore blank lines until the first non-blank line has been seen. */
+add_documentation (defs, line)
+     DEF_FILE *defs;
+     char *line;
+{
+  register BUILTIN_DESC *builtin;
+
+  builtin = current_builtin ("(implied LONGDOC)", defs);
+
+  remove_trailing_whitespace (line);
+
+  if (!*line && !builtin->longdoc)
+    return;
+
+  if (!builtin->longdoc)
+    builtin->longdoc = array_create (sizeof (char *));
+
+  array_add (line, builtin->longdoc);
+}
+
+/* How to handle the $BUILTIN directive. */
+int
+builtin_handler (self, defs, arg)
+     char *self, *arg;
+     DEF_FILE *defs;
+{
+  /* If we are already building a builtin, we cannot start a new one. */
+  if (building_builtin)
+    return (line_error (defs, "%s found before $END", self));
+
+  output_cpp_line_info++;
+
+  /* Get the name of this builtin, and stick it in the array. */
+  {
+    BUILTIN_DESC *new;
+    char *name;
+
+    name = get_arg (self, defs, arg);
+
+    /* If this is the first builtin, create the array to hold them. */
+    if (!defs->builtins)
+      defs->builtins = array_create (sizeof (BUILTIN_DESC *));
+
+    new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
+    new->name = name;
+    new->function = (char *)NULL;
+    new->shortdoc = (char *)NULL;
+    new->docname = (char *)NULL;
+    new->longdoc = (ARRAY *)NULL;
+    new->dependencies = (ARRAY *)NULL;
+    new->flags = 0;
+
+    if (is_special_builtin (name))
+      new->flags |= BUILTIN_FLAG_SPECIAL;
+
+    array_add ((char *)new, defs->builtins);
+    building_builtin = 1;
+  }
+  return (0);
+}
+
+/* How to handle the $FUNCTION directive. */
+int
+function_handler (self, defs, arg)
+     char *self, *arg;
+     DEF_FILE *defs;
+{
+  register BUILTIN_DESC *builtin;
+
+  builtin = current_builtin (self, defs);
+
+  if (builtin->function)
+    line_error (defs, "%s already has a function (%s)",
+               builtin->name, builtin->function);
+  else
+    builtin->function = get_arg (self, defs, arg);
+
+  return (0);
+}
+
+/* How to handle the $DOCNAME directive. */
+int
+docname_handler (self, defs, arg)
+     char *self, *arg;
+     DEF_FILE *defs;
+{
+  register BUILTIN_DESC *builtin;
+
+  builtin = current_builtin (self, defs);
+
+  if (builtin->docname)
+    line_error (defs, "%s already had a docname (%s)",
+               builtin->name, builtin->docname);
+  else
+    builtin->docname = get_arg (self, defs, arg);
+
+  return (0);
+}
+
+/* How to handle the $SHORT_DOC directive. */
+short_doc_handler (self, defs, arg)
+     char *self, *arg;
+     DEF_FILE *defs;
+{
+  register BUILTIN_DESC *builtin;
+
+  builtin = current_builtin (self, defs);
+
+  if (builtin->shortdoc)
+    line_error (defs, "%s already has short documentation (%s)",
+               builtin->name, builtin->shortdoc);
+  else
+    builtin->shortdoc = get_arg (self, defs, arg);
+
+  return (0);
+}
+
+/* How to handle the $COMMENT directive. */
+comment_handler (self, defs)
+     char *self;
+     DEF_FILE *defs;
+{
+}
+
+/* How to handle the $DEPENDS_ON directive. */
+depends_on_handler (self, defs, arg)
+     char *self, *arg;
+     DEF_FILE *defs;
+{
+  register BUILTIN_DESC *builtin;
+  char *dependent;
+
+  builtin = current_builtin (self, defs);
+  dependent = get_arg (self, defs, arg);
+
+  if (!builtin->dependencies)
+    builtin->dependencies = array_create (sizeof (char *));
+
+  array_add (dependent, builtin->dependencies);
+
+  return (0);
+}
+
+/* How to handle the $PRODUCES directive. */
+produces_handler (self, defs, arg)
+     char *self, *arg;
+     DEF_FILE *defs;
+{
+  /* If just hacking documentation, don't change any of the production
+     files. */
+  if (only_documentation)
+    return (0);
+
+  output_cpp_line_info++;
+
+  if (defs->production)
+    line_error (defs, "%s already has a %s definition", defs->filename, self);
+  else
+    {
+      defs->production = get_arg (self, defs, arg);
+
+      if (inhibit_production)
+       return (0);
+
+      defs->output = fopen (defs->production, "w");
+
+      if (!defs->output)
+       file_error (defs->production);
+
+      fprintf (defs->output, "/* %s, created from %s. */\n",
+              defs->production, defs->filename);
+    }
+  return (0);
+}
+
+/* How to handle the $END directive. */
+end_handler (self, defs, arg)
+     char *self, *arg;
+     DEF_FILE *defs;
+{
+  must_be_building (self, defs);
+  building_builtin = 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                 Error Handling Functions                        */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Produce an error for DEFS with FORMAT and ARGS. */
+line_error (defs, format, arg1, arg2)
+     DEF_FILE *defs;
+     char *format, *arg1, *arg2;
+{
+  if (defs->filename[0] != '/')
+    fprintf (stderr, "%s", error_directory ? error_directory : "./");
+  fprintf (stderr, "%s:%d:", defs->filename, defs->line_number + 1);
+  fprintf (stderr, format, arg1, arg2);
+  fprintf (stderr, "\n");
+  fflush (stderr);
+}
+
+/* Print error message for FILENAME. */
+file_error (filename)
+     char *filename;
+{
+  perror (filename);
+  exit (2);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "mkbuiltins: Out of virtual memory!\n");
+  abort ();
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*               Creating the Struct and Extern Files              */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Return a pointer to a newly allocated builtin which is
+   an exact copy of BUILTIN. */
+BUILTIN_DESC *
+copy_builtin (builtin)
+     BUILTIN_DESC *builtin;
+{
+  BUILTIN_DESC *new;
+
+  new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
+
+  new->name         = savestring (builtin->name);
+  new->shortdoc     = savestring (builtin->shortdoc);
+  new->longdoc      = copy_string_array (builtin->longdoc);
+  new->dependencies = copy_string_array (builtin->dependencies);
+
+  new->function =
+    builtin->function ? savestring (builtin->function) : (char *)NULL;
+  new->docname =
+    builtin->docname  ? savestring (builtin->docname)  : (char *)NULL;
+
+  return (new);
+}
+
+/* How to save away a builtin. */
+save_builtin (builtin)
+     BUILTIN_DESC *builtin;
+{
+  BUILTIN_DESC *newbuiltin;
+
+  newbuiltin = copy_builtin (builtin);
+
+  /* If this is the first builtin to be saved, create the array
+     to hold it. */
+  if (!saved_builtins)
+      saved_builtins = array_create (sizeof (BUILTIN_DESC *));
+
+  array_add ((char *)newbuiltin, saved_builtins);
+}
+
+/* Flags that mean something to write_documentation (). */
+#define STRING_ARRAY 1
+#define TEXINFO 2
+
+char *structfile_header[] = {
+  "/* builtins.c -- the built in shell commands. */",
+  "",
+  "/* 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.",
+  "",
+  "   This file is part of GNU Bash, the Bourne Again SHell.",
+  "",
+  "   Bash is free software; you can redistribute it and/or modify it",
+  "   under the terms of the GNU General Public License as published by",
+  "   the Free Software Foundation; either version 1, or (at your option)",
+  "   any later version.",
+  "",
+  "   Bash is distributed in the hope that it will be useful, but WITHOUT",
+  "   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY",
+  "   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public",
+  "   License for more details.",
+  "",
+  "   You should have received a copy of the GNU General Public License",
+  "   along with Bash; see the file COPYING.  If not, write to the Free",
+  "   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */",
+  "",
+  "/* The list of shell builtins.  Each element is name, function, enabled-p,",
+  "   long-doc, short-doc.  The long-doc field contains a pointer to an array",
+  "   of help lines.  The function takes a WORD_LIST *; the first word in the",
+  "   list is the first arg to the command.  The list has already had word",
+  "   expansion performed.",
+  "",
+  "   Functions which need to look at only the simple commands (e.g.",
+  "   the enable_builtin ()), should ignore entries where",
+  "   (array[i].function == (Function *)NULL).  Such entries are for",
+  "   the list of shell reserved control structures, like `if' and `while'.",
+  "   The end of the list is denoted with a NULL name field. */",
+  "",
+  "#include \"../builtins.h\"",
+  (char *)NULL
+  };
+
+char *structfile_footer[] = {
+  "  { (char *)0x0, (Function *)0x0, 0, (char **)0x0, (char *)0x0 }",
+  "};",
+  "",
+  "int num_shell_builtins =",
+  "\tsizeof (shell_builtins) / sizeof (struct builtin) - 1;",
+  (char *)NULL
+};
+
+/* Write out any neccessary opening information for
+   STRUCTFILE and EXTERNFILE. */
+write_file_headers (structfile, externfile)
+     FILE *structfile, *externfile;
+{
+  register int i;
+
+  if (structfile)
+    {
+      for (i = 0; structfile_header[i]; i++)
+       fprintf (structfile, "%s\n", structfile_header[i]);
+
+      fprintf (structfile, "#include \"%s\"\n",
+              extern_filename ? extern_filename : "builtext.h");
+      fprintf (structfile, "\nstruct builtin shell_builtins[] = {\n");
+    }
+
+  if (externfile)
+    fprintf (externfile,
+            "/* %s - The list of builtins found in libbuiltins.a. */\n",
+            extern_filename ? extern_filename : "builtext.h");
+}
+
+/* Write out any necessary closing information for
+   STRUCTFILE and EXTERNFILE. */
+write_file_footers (structfile, externfile)
+     FILE *structfile, *externfile;
+{
+  register int i;
+
+  /* Write out the footers. */
+  if (structfile)
+    {
+      for (i = 0; structfile_footer[i]; i++)
+       fprintf (structfile, "%s\n", structfile_footer[i]);
+    }
+}
+
+/* Write out the information accumulated in DEFS to
+   STRUCTFILE and EXTERNFILE. */
+write_builtins (defs, structfile, externfile)
+     DEF_FILE *defs;
+     FILE *structfile, *externfile;
+{
+  register int i;
+
+  /* Write out the information. */
+  if (defs->builtins)
+    {
+      register BUILTIN_DESC *builtin;
+
+      for (i = 0; i < defs->builtins->sindex; i++)
+       {
+         builtin = (BUILTIN_DESC *)defs->builtins->array[i];
+
+         /* Write out any #ifdefs that may be there. */
+         if (!only_documentation)
+           {
+             if (builtin->dependencies)
+               {
+                 if (builtin->function)
+                   write_ifdefs (externfile, builtin->dependencies->array);
+                 write_ifdefs (structfile, builtin->dependencies->array);
+               }
+
+             /* Write the extern definition. */
+             if (externfile)
+               {
+                 if (builtin->function)
+                   fprintf (externfile, "extern int %s ();\n",
+                            builtin->function);
+
+                 fprintf (externfile, "extern char *%s_doc[];\n",
+                          builtin->docname ?builtin->docname : builtin->name);
+               }
+
+             /* Write the structure definition. */
+             if (structfile)
+               {
+                 fprintf (structfile, "  { \"%s\", ", builtin->name);
+
+                 if (builtin->function)
+                   fprintf (structfile, "%s, ", builtin->function);
+                 else
+                   fprintf (structfile, "(Function *)0x0, ");
+
+#define SPECIAL_FLAG_STRING "BUILTIN_ENABLED | STATIC_BUILTIN | SPECIAL_BUILTIN"
+#define NORMAL_FLAG_STRING "BUILTIN_ENABLED | STATIC_BUILTIN"
+
+                 fprintf (structfile, "%s, %s_doc,\n",
+                   (builtin->flags & BUILTIN_FLAG_SPECIAL) ?
+                       SPECIAL_FLAG_STRING :
+                       NORMAL_FLAG_STRING,
+                   builtin->docname ? builtin->docname : builtin->name);
+
+#undef SPECIAL_FLAG_STRING
+#undef NORMAL_FLAG_STRING
+
+                 fprintf
+                   (structfile, "     \"%s\" },\n",
+                    builtin->shortdoc ? builtin->shortdoc : builtin->name);
+
+                 /* 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)
+               {
+                 if (externfile)
+                   write_endifs (externfile, builtin->dependencies->array);
+
+                 if (structfile)
+                   write_endifs (structfile, builtin->dependencies->array);
+               }
+           }
+
+         if (documentation_file)
+           {
+             fprintf (documentation_file, "@item %s\n", builtin->name);
+             write_documentation
+               (documentation_file, builtin->longdoc->array, 0, TEXINFO);
+           }
+       }
+    }
+}
+
+/* Write out the long documentation strings in BUILTINS to STREAM. */
+write_longdocs (stream, builtins)
+     FILE *stream;
+     ARRAY *builtins;
+{
+  register int i;
+  register BUILTIN_DESC *builtin;
+
+  for (i = 0; i < builtins->sindex; i++)
+    {
+      builtin = (BUILTIN_DESC *)builtins->array[i];
+
+      if (builtin->dependencies)
+       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);
+
+      if (builtin->dependencies)
+       write_endifs (stream, builtin->dependencies->array);
+
+    }
+}
+
+/* Write an #ifdef string saying what needs to be defined (or not defined)
+   in order to allow compilation of the code that will follow.
+   STREAM is the stream to write the information to,
+   DEFINES is a null terminated array of define names.
+   If a define is preceded by an `!', then the sense of the test is
+   reversed. */
+write_ifdefs (stream, defines)
+     FILE *stream;
+     char **defines;
+{
+  register int i;
+
+  if (!stream)
+    return;
+
+  fprintf (stream, "#if ");
+
+  for (i = 0; defines[i]; i++)
+    {
+      char *def = defines[i];
+
+      if (*def == '!')
+       fprintf (stream, "!defined (%s)", def + 1);
+      else
+       fprintf (stream, "defined (%s)", def);
+
+      if (defines[i + 1])
+       fprintf (stream, " && ");
+    }
+  fprintf (stream, "\n");
+}
+
+/* Write an #endif string saying what defines controlled the compilation
+   of the immediately preceding code.
+   STREAM is the stream to write the information to.
+   DEFINES is a null terminated array of define names. */
+write_endifs (stream, defines)
+     FILE *stream;
+     char **defines;
+{
+  register int i;
+
+  if (!stream)
+    return;
+
+  fprintf (stream, "#endif /* ");
+
+  for (i = 0; defines[i]; i++)
+    {
+      fprintf (stream, "%s", defines[i]);
+
+      if (defines[i + 1])
+       fprintf (stream, " && ");
+    }
+
+  fprintf (stream, " */\n");
+}
+
+/* Write DOCUMENTAION to STREAM, perhaps surrounding it with double-quotes
+   and quoting special characters in the string. */
+write_documentation (stream, documentation, indentation, flags)
+     FILE *stream;
+     char **documentation;
+     int indentation, flags;
+{
+  register int i, j;
+  register char *line;
+  int string_array = (flags & STRING_ARRAY); /* Mutually exclusive. */
+  int texinfo = (flags & TEXINFO);
+
+  if (!stream)
+    return;
+
+  if (string_array)
+    fprintf (stream, " {\n");
+
+#if !defined (OLDCODE)
+  /* XXX -- clean me up; for experiment only */
+  if (no_long_document)
+    goto end_of_document;
+#endif /* !OLDCODE */
+
+  for (i = 0; line = documentation[i]; i++)
+    {
+      /* Allow #ifdef's to be written out verbatim. */
+      if (*line == '#')
+       {
+         if (string_array)
+           fprintf (stream, "%s\n", line);
+         continue;
+       }
+
+      if (string_array)
+       fprintf (stream, "  \"");
+
+      if (indentation)
+       for (j = 0; j < indentation; j++)
+         fprintf (stream, " ");
+
+      if (string_array)
+       {
+         for (j = 0; line[j]; j++)
+           {
+             switch (line[j])
+               {
+               case '\\':
+               case '"':
+                 fprintf (stream, "\\%c", line[j]);
+                 break;
+
+               default:
+                 fprintf (stream, "%c", line[j]);
+               }
+           }
+
+         fprintf (stream, "\",\n");
+       }
+      else if (texinfo)
+       {
+         for (j = 0; line[j]; j++)
+           {
+             switch (line[j])
+               {
+               case '@':
+               case '{':
+               case '}':
+                 fprintf (stream, "@%c", line[j]);
+                 break;
+
+               default:
+                 fprintf (stream, "%c", line[j]);
+               }
+           }
+         fprintf (stream, "\n");
+       }
+      else
+       fprintf (stream, "%s\n", line);
+    }
+
+#if !defined (OLDCODE)
+end_of_document:
+#endif /* !OLDCODE */
+
+  if (string_array)
+    fprintf (stream, "  (char *)NULL\n};\n");
+}
+
+static int
+is_special_builtin (name)
+     char *name;
+{
+  register int i;
+
+  for (i = 0; special_builtins[i]; i++)
+    if (strcmp (name, special_builtins[i]) == 0)
+      return 1;
+  return 0;
+}
diff --git a/builtins/psize.c b/builtins/psize.c
new file mode 100644 (file)
index 0000000..03a4f6e
--- /dev/null
@@ -0,0 +1,63 @@
+/* psize.c - Find pipe size. */
+
+/* Copyright (C) 1987, 1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*  Write output in 128-byte chunks until we get a sigpipe or write gets an
+    EPIPE.  Then report how many bytes we wrote.  We assume that this is the
+    pipe size. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+
+#include "../command.h"
+#include "../general.h"
+extern int errno;
+
+int nw;
+
+sighandler
+sigpipe (sig)
+     int sig;
+{
+  fprintf (stderr, "%d\n", nw);
+  exit (0);
+}
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char buf[128];
+  register int i;
+
+  for (i = 0; i < 128; i++)
+    buf[i] = ' ';
+
+  signal (SIGPIPE, sigpipe);
+
+  nw = 0;
+  for (;;)
+    {
+      int n;
+      n = write (1, buf, 128);
+      nw += n;
+    }
+}
diff --git a/builtins/psize.sh b/builtins/psize.sh
new file mode 100755 (executable)
index 0000000..961becd
--- /dev/null
@@ -0,0 +1,24 @@
+#! /bin/sh
+#
+# psize.sh -- determine this system's pipe size, and write a define to
+#             pipesize.h so ulimit.c can use it.
+
+echo "/*"
+echo " * pipesize.h"
+echo " *"
+echo " * This file is automatically generated by psize.sh"
+echo " * Do not edit!"
+echo " */"
+echo ""
+
+./psize.aux 2>/tmp/pipesize | sleep 3
+
+if [ -s /tmp/pipesize ]; then
+       echo "#define PIPESIZE `cat /tmp/pipesize`"
+else
+       echo "#define PIPESIZE 512"
+fi
+
+rm -f /tmp/pipesize
+
+exit 0
diff --git a/builtins/read.def b/builtins/read.def
new file mode 100644 (file)
index 0000000..7b6dfc9
--- /dev/null
@@ -0,0 +1,276 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES read.c
+
+$BUILTIN read
+$FUNCTION read_builtin
+$SHORT_DOC read [-r] [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, etc.
+with leftover words assigned to the last NAME.  Only the characters
+found in $IFS are recognized as word delimiters.  The return code is
+zero, unless end-of-file is encountered.  If the -r option is given,
+this signifies `raw' input, and backslash processing is disabled.
+$END
+
+#include <stdio.h>
+#include "../shell.h"
+#include "common.h"
+
+#define issep(c)       (strchr (ifs_chars, (c)) != (char *)0)
+
+static int stream_close ();
+
+extern int interrupt_immediately;
+
+/* Read the value of the shell variables whose names follow.
+   The reading is done from the current input stream, whatever
+   that may be.  Successive words of the input line are assigned
+   to the variables mentioned in LIST.  The last variable in LIST
+   gets the remainder of the words on the line.  If no variables
+   are mentioned in LIST, then the default variable is $REPLY.
+
+   S. R. Bourne's shell complains if you don't name a variable
+   to receive the stuff that is read.  GNU's shell doesn't.  This
+   allows you to let the user type random things. */
+read_builtin (list)
+     WORD_LIST *list;
+{
+  register char *varname;
+  int size, c, i, fildes, raw_mode, pass_next, saw_escape, retval;
+  char *input_string, *orig_input_string, *ifs_chars, *t;
+  FILE *input_stream;
+  SHELL_VAR *var;
+
+  i = 0;               /* Index into the string that we are reading. */
+  raw_mode = 0;                /* Not reading raw input be default. */
+
+  while (list)
+    {
+      if (ISOPTION (list->word->word, 'r'))
+       {
+         raw_mode = 1;
+         list = list->next;
+       }
+      else if (ISOPTION (list->word->word, '-'))
+       {
+         list = list->next;
+         break;
+       }
+      else if (*list->word->word == '-')
+       {
+         bad_option (list->word->word);
+         builtin_error ("usage: read [-r] [name ...]");
+         return (EX_USAGE);
+       }
+      else
+       break;
+    }
+
+  /* We need unbuffered input from stdin.  So we make a new stream with
+     the same file descriptor as stdin, then unbuffer it. */
+  fildes = dup (fileno (stdin));
+
+  if (fildes == -1)
+    return (EXECUTION_FAILURE);
+
+  input_stream = fdopen (fildes, "r");
+
+  if (!input_stream)
+    {
+      close (fildes);
+      return (EXECUTION_FAILURE);
+    }
+
+  var = find_variable ("IFS");
+  ifs_chars = var ? value_cell (var) : " \t\n";
+  
+  input_string = xmalloc (size = 128);
+
+  setbuf (input_stream, (char *)NULL);
+
+  begin_unwind_frame ("read_builtin");
+  add_unwind_protect (xfree, input_string);
+  add_unwind_protect (stream_close, input_stream);
+  interrupt_immediately++;
+
+  pass_next = 0;       /* Non-zero signifies last char was backslash. */
+  saw_escape = 0;      /* Non-zero signifies that we saw an escape char */
+
+  while ((c = getc (input_stream)) != EOF)
+    {
+      if (i + 2 >= size)
+       input_string = xrealloc (input_string, size += 128);
+
+      /* If the next character is to be accepted verbatim, a backslash
+        newline pair still disappears from the input. */
+      if (pass_next)
+       {
+         if (c == '\n')
+           i--;                /* back up over the CTLESC */
+         else
+           input_string[i++] = c;
+         pass_next = 0;
+         continue;
+       }
+
+      if (c == '\\' && !raw_mode)
+       {
+         pass_next++;
+         saw_escape++;
+         input_string[i++] = CTLESC;
+         continue;
+       }
+
+      if (c == '\n')
+       break;
+
+      if (c == CTLESC || c == CTLNUL)
+       {
+         saw_escape++;
+         input_string[i++] = CTLESC;
+       }
+
+      input_string[i++] = c;
+    }
+  input_string[i] = '\0';
+
+  interrupt_immediately--;
+  discard_unwind_frame ("read_builtin");
+
+  fclose (input_stream);
+
+  if (c == EOF)
+    {
+      retval = EXECUTION_FAILURE;
+      /* input_string[0] = '\0'; */
+    }
+  else
+    retval = EXECUTION_SUCCESS;
+
+  if (!list)
+    {
+      if (saw_escape)
+       {
+         t = dequote_string (input_string);
+         var = bind_variable ("REPLY", t);
+         free (t);
+       }
+      else
+       var = bind_variable ("REPLY", input_string);
+      var->attributes &= ~att_invisible;
+      free (input_string);
+    }
+  else
+    {
+      /* This code implements the Posix.2 spec for splitting the words
+        read and assigning them to variables.  If $IFS is unset, we
+        use the default value of " \t\n". */
+      orig_input_string = input_string;
+
+      /* Remove IFS white space at the beginning of the input string.  If
+        $IFS is null, no field splitting is performed. */
+      for (t = input_string; *ifs_chars && spctabnl (*t) && issep (*t); t++)
+       ;
+      input_string = t;
+
+      for (; list->next; list = list->next)
+       {
+         char *e, *t1;
+
+         varname = list->word->word;
+         if (legal_identifier (varname) == 0)
+           {
+             builtin_error ("%s: not a legal variable name", varname);
+             free (orig_input_string);
+             return (EXECUTION_FAILURE);
+           }
+
+         /* If there are more variables than words read from the input,
+            the remaining variables are set to the empty string. */
+         if (*input_string)
+           {
+             /* This call updates INPUT_STRING. */
+             t = get_word_from_string (&input_string, ifs_chars, &e);
+             if (t)
+               *e = '\0';
+             /* Don't bother to remove the CTLESC unless we added one
+                somewhere while reading the string. */
+             if (t && saw_escape)
+               {
+                 t1 = dequote_string (t);
+                 var = bind_variable (varname, t1);
+                 free (t1);
+               }
+             else
+               var = bind_variable (varname, t);
+           }
+         else
+           {
+             t = (char *)0;
+             var = bind_variable (varname, "");
+           }
+
+         stupidly_hack_special_variables (varname);
+         var->attributes &= ~att_invisible;
+
+         if (t)
+           free (t);
+       }
+
+      if (legal_identifier (list->word->word) == 0)
+       {
+         builtin_error ("%s: not a legal variable name", list->word->word);
+         free (orig_input_string);
+         return (EXECUTION_FAILURE);
+       }
+
+      /* This has to be done this way rather than using string_list
+        and list_string because Posix.2 says that the last variable gets the
+        remaining words and their intervening separators. */
+      input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars,
+                                                     saw_escape);
+
+      if (saw_escape)
+       {
+         t = dequote_string (input_string);
+         var = bind_variable (list->word->word, t);
+         free (t);
+       }
+      else
+       var = bind_variable (list->word->word, input_string);
+      stupidly_hack_special_variables (list->word->word);
+      var->attributes &= ~att_invisible;
+      free (orig_input_string);
+    }
+
+  return (retval);
+}
+
+/* This way I don't have to know whether fclose () is a
+   function or a macro. */
+static int
+stream_close (file)
+     FILE *file;
+{
+  return (fclose (file));
+}
diff --git a/builtins/reserved.def b/builtins/reserved.def
new file mode 100644 (file)
index 0000000..4074ae0
--- /dev/null
@@ -0,0 +1,154 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$BUILTIN for
+$SHORT_DOC for NAME [in WORDS ... ;] do COMMANDS; done
+The `for' loop executes a sequence of commands for each member in a
+list of items.  If `in WORDS ...;' is not present, then `in "$@"' is
+assumed.  For each element in WORDS, NAME is set to that element, and
+the COMMANDS are executed.
+$END
+
+$BUILTIN select
+$SHORT_DOC select NAME [in WORDS ... ;] do COMMANDS; done
+The WORDS are expanded, generating a list of words.  The
+set of expanded words is printed on the standard error, each
+preceded by a number.  If `in WORDS' is not present, `in "$@"'
+is assumed.  The PS3 prompt is then displayed and a line read
+from the standard input.  If the line consists of the number
+corresponding to one of the displayed words, then NAME is set
+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.
+$END
+
+$BUILTIN case
+$SHORT_DOC case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
+Selectively execute COMMANDS based upon WORD matching PATTERN.  The
+`|' is used to separate multiple patterns.
+$END
+
+$BUILTIN if
+$SHORT_DOC if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
+The if COMMANDS are executed.  If the exit status is zero, then the then
+COMMANDS are executed.  Otherwise, each of the elif COMMANDS are executed
+in turn, and if the exit status is zero, the corresponding then COMMANDS
+are executed and the if command completes.  Otherwise, the else COMMANDS
+are executed, if present.  The exit status is the exit status of the last
+command executed, or zero if no condition tested true.
+$END
+
+$BUILTIN while
+$SHORT_DOC while COMMANDS; do COMMANDS; done
+Expand and execute COMMANDS as long as the final command in the
+`while' COMMANDS has an exit status of zero.
+$END
+
+$BUILTIN until
+$SHORT_DOC until COMMANDS; do COMMANDS; done
+Expand and execute COMMANDS as long as the final command in the
+`until' COMMANDS has an exit status which is not zero.
+$END
+
+$BUILTIN function
+$SHORT_DOC function NAME { COMMANDS ; } or NAME () { COMMANDS ; }
+Create a simple command invoked by NAME which runs COMMANDS.
+Arguments on the command line along with NAME are passed to the
+function as $0 .. $n.
+$END
+
+$BUILTIN { ... }
+$DOCNAME grouping_braces
+$SHORT_DOC { COMMANDS }
+Run a set of commands in a group.  This is one way to redirect an
+entire set of commands.
+$END
+
+$BUILTIN %
+$DOCNAME fg_percent
+$SHORT_DOC %[DIGITS | WORD] [&]
+This is similar to the `fg' command.  Resume a stopped or background
+job.  If you specifiy DIGITS, then that job is used.  If you specify
+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 variables
+$DOCNAME variable_help
+$SHORT_DOC variables - Some variable names and meanings
+BASH_VERSION    The version numbers of this Bash.
+CDPATH          A colon separated list of directories to search
+               when the argument to `cd' is not found in the current
+               directory.
+#if defined (HISTORY)
+HISTFILE        The name of the file where your command history is stored.
+HISTFILESIZE    The maximum number of lines this file can contain.
+HISTSIZE        The maximum number of history lines that a running
+               shell can access.
+#endif /* HISTORY */
+HOME            The complete pathname to your login directory.
+HOSTTYPE        The type of CPU this version of Bash is running under.
+IGNOREEOF       Controls the action of the shell on receipt of an EOF
+               character as the sole input.  If set, then the value
+               of it is the number of EOF characters that can be seen
+               in a row on an empty line before the shell will exit
+               (default 10).  When unset, EOF signifies the end of input.
+MAILCHECK      How often, in seconds, Bash checks for new mail.
+MAILPATH       A colon-separated list of filenames which Bash checks
+               for new mail.
+PATH            A colon-separated list of directories to search when
+               looking for commands.
+PROMPT_COMMAND  A command to be executed before the printing of each
+               primary prompt.
+PS1             The primary prompt string.
+PS2             The secondary prompt string.
+TERM            The name of the current terminal type.
+auto_resume     Non-null means a command word appearing on a line by
+               itself is first looked for in the list of currently
+               stopped jobs.  If found there, that job is foregrounded.
+               A value of `exact' means that the command word must
+               exactly match a command in the list of stopped jobs.  A
+               value of `substring' means that the command word must
+               match a substring of the job.  Any other value means that
+               the command must be a prefix of a stopped job.
+#if defined (HISTORY)
+command_oriented_history
+                Non-null means to save multiple-line commands together on
+                a single history line.
+#  if defined (BANG_HISTORY)
+histchars       Characters controlling history expansion and quick
+               substitution.  The first character is the history
+               substitution character, usually `!'.  The second is
+               the `quick substitution' character, usually `^'.  The
+               third is the `history comment' character, usually `#'.
+#  endif /* BANG_HISTORY */
+HISTCONTROL    Set to a value of `ignorespace', it means don't enter
+               lines which begin with a space or tab on the history
+               list.  Set to a value of `ignoredups', it means don't
+               enter lines which match the last entered line.  Set to
+               `ignoreboth' means to combine the two options.  Unset,
+               or set to any other value than those above means to save
+               all lines on the history list.
+#endif /* HISTORY */
+$END
diff --git a/builtins/return.def b/builtins/return.def
new file mode 100644 (file)
index 0000000..8340a44
--- /dev/null
@@ -0,0 +1,57 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES return.c
+
+$BUILTIN return
+
+$FUNCTION return_builtin
+$SHORT_DOC return [n]
+Causes a function to exit with the return value specified by N.  If N
+is omitted, the return status is that of the last command.
+$END
+
+#include "../shell.h"
+
+extern int last_command_exit_value;
+extern int return_catch_flag, return_catch_value;
+extern jmp_buf return_catch;
+
+/* If we are executing a user-defined function then exit with the value
+   specified as an argument.  if no argument is given, then the last
+   exit status is used. */
+int
+return_builtin (list)
+     WORD_LIST *list;
+{
+  return_catch_value = get_numeric_arg (list);
+
+  if (!list)
+    return_catch_value = last_command_exit_value;
+
+  if (return_catch_flag)
+    longjmp (return_catch, 1);
+  else
+    {
+      builtin_error ("Can only `return' from a function");
+      return (EXECUTION_FAILURE);
+    }
+}
diff --git a/builtins/set.def b/builtins/set.def
new file mode 100644 (file)
index 0000000..a97168c
--- /dev/null
@@ -0,0 +1,528 @@
+This file is set.def, from which is created set.c.
+It implements the "set" and "unset" builtins in Bash.
+
+Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES set.c
+
+#include <stdio.h>
+#include "../shell.h"
+#include "../flags.h"
+
+#include "bashgetopt.h"
+
+extern int interactive;
+extern int noclobber, no_brace_expansion, posixly_correct;
+#if defined (READLINE)
+extern int rl_editing_mode, no_line_editing;
+#endif /* READLINE */
+
+#define USAGE_STRING "set [--abefhknotuvxldHCP] [-o option] [arg ...]"
+
+$BUILTIN set
+$FUNCTION set_builtin
+$SHORT_DOC set [--abefhknotuvxldHCP] [-o option] [arg ...]
+    -a  Mark variables which are modified or created for export.
+    -b  Notify of job termination immediately.
+    -e  Exit immediately if a command exits with a non-zero status.
+    -f  Disable file name generation (globbing).
+    -h  Locate and remember function commands as functions are
+        defined.  Function commands are normally looked up when
+        the function is executed.
+    -i  Force the shell to be an "interactive" one.  Interactive shells
+        always read `~/.bashrc' on startup.
+    -k  All keyword arguments are placed in the environment for a
+        command, not just those that precede the command name.
+    -m  Job control is enabled.
+    -n  Read commands but do not execute them.
+    -o option-name
+        Set the variable corresponding to option-name:
+            allexport    same as -a
+            braceexpand  the shell will perform brace expansion
+#if defined (READLINE)
+            emacs        use an emacs-style line editing interface
+#endif /* READLINE */
+            errexit      same as -e
+#if defined (BANG_HISTORY)
+            histexpand   same as -H
+#endif /* BANG_HISTORY */
+            ignoreeof    the shell will not exit upon reading EOF
+            interactive-comments
+                         allow comments to appear in interactive commands
+            monitor      same as -m
+            noclobber    disallow redirection to existing files
+            noexec       same as -n
+            noglob       same as -f
+            nohash       same as -d
+            notify       save as -b
+            nounset      same as -u
+           physical     same as -P
+           posix        change the behavior of bash where the default
+                        operation differs from the 1003.2 standard to
+                        match the standard
+           privileged   same as -p
+            verbose      same as -v
+#if defined (READLINE)
+            vi           use a vi-style line editing interface
+#endif /* READLINE */
+            xtrace       same as -x
+    -p  Turned on whenever the real and effective user ids do not match.
+        Disables processing of the $ENV file and importing of shell
+        functions.  Turning this option off causes the effective uid and
+       gid to be set to the real uid and gid.
+    -t  Exit after reading and executing one command.
+    -u  Treat unset variables as an error when substituting.
+    -v  Print shell input lines as they are read.
+    -x  Print commands and their arguments as they are executed.
+    -l  Save and restore the binding of the NAME in a FOR command.
+    -d  Disable the hashing of commands that are looked up for execution.
+        Normally, commands are remembered in a hash table, and once
+        found, do not have to be looked up again.
+#if defined (BANG_HISTORY)
+    -H  Enable ! style history substitution.  This flag is on
+        by default.
+#endif /* BANG_HISTORY */
+    -C  If set, disallow existing regular files to be overwritten
+        by redirection of output.
+    -P  If set, do not follow symbolic links when executing commands
+        such as cd which change the current directory.
+
+Using + rather than - causes these flags to be turned off.  The
+flags can also be used upon invocation of the shell.  The current
+set of flags may be found in $-.  The remaining n ARGs are positional
+parameters and are assigned, in order, to $1, $2, .. $n.  If no
+ARGs are given, all shell variables are printed.
+$END
+
+/* An a-list used to match long options for set -o to the corresponding
+   option letter. */
+struct {
+  char *name;
+  int letter;
+} o_options[] = {
+  { "allexport",  'a' },
+  { "errexit",   'e' },
+#if defined (BANG_HISTORY)
+  { "histexpand", 'H' },
+#endif /* BANG_HISTORY */
+  { "monitor",   'm' },
+  { "noexec",    'n' },
+  { "noglob",    'f' },
+  { "nohash",    'd' },
+#if defined (JOB_CONTROL)
+  { "notify",    'b' },
+#endif /* JOB_CONTROL */
+  {"nounset",    'u' },
+  {"physical",    'P' },
+  {"privileged",  'p' },
+  {"verbose",    'v' },
+  {"xtrace",     'x' },
+  {(char *)NULL, 0},
+};
+
+#define MINUS_O_FORMAT "%-15s\t%s\n"
+
+void
+list_minus_o_opts ()
+{
+  register int i;
+  char *on = "on", *off = "off";
+
+  printf (MINUS_O_FORMAT, "braceexpand", (no_brace_expansion == 0) ? on : off);
+  printf (MINUS_O_FORMAT, "noclobber", (noclobber == 1) ? on : off);
+
+  if (find_variable ("ignoreeof") || find_variable ("IGNOREEOF"))
+    printf (MINUS_O_FORMAT, "ignoreeof", on);
+  else
+    printf (MINUS_O_FORMAT, "ignoreeof", off);
+
+  printf (MINUS_O_FORMAT, "interactive-comments",
+         interactive_comments ? on : off);
+
+  printf (MINUS_O_FORMAT, "posix", posixly_correct ? on : off);
+
+#if defined (READLINE)
+  if (no_line_editing)
+    {
+      printf (MINUS_O_FORMAT, "emacs", off);
+      printf (MINUS_O_FORMAT, "vi", off);
+    }
+  else
+    {
+      /* Magic.  This code `knows' how readline handles rl_editing_mode. */
+      printf (MINUS_O_FORMAT, "emacs", (rl_editing_mode == 1) ? on : off);
+      printf (MINUS_O_FORMAT, "vi", (rl_editing_mode == 0) ? on : off);
+    }
+#endif /* READLINE */
+
+  for (i = 0; o_options[i].name; i++)
+    {
+      int *on_or_off, zero = 0;
+
+      on_or_off = find_flag (o_options[i].letter);
+      if (on_or_off == FLAG_UNKNOWN)
+       on_or_off = &zero;
+      printf (MINUS_O_FORMAT, o_options[i].name, (*on_or_off == 1) ? on : off);
+    }
+}
+
+set_minus_o_option (on_or_off, option_name)
+     int on_or_off;
+     char *option_name;
+{
+  int option_char = -1;
+
+  if (STREQ (option_name, "braceexpand"))
+    {
+      if (on_or_off == FLAG_ON)
+       no_brace_expansion = 0;
+      else
+       no_brace_expansion = 1;
+    }
+  else if (STREQ (option_name, "noclobber"))
+    {
+      if (on_or_off == FLAG_ON)
+       bind_variable ("noclobber", "");
+      else
+       unbind_variable ("noclobber");
+      stupidly_hack_special_variables ("noclobber");
+    }
+  else if (STREQ (option_name, "ignoreeof"))
+    {
+      unbind_variable ("ignoreeof");
+      unbind_variable ("IGNOREEOF");
+      if (on_or_off == FLAG_ON)
+       bind_variable ("IGNOREEOF", "10");
+      stupidly_hack_special_variables ("IGNOREEOF");
+    }
+  
+#if defined (READLINE)
+  else if ((STREQ (option_name, "emacs")) || (STREQ (option_name, "vi")))
+    {
+      if (on_or_off == FLAG_ON)
+       {
+         rl_variable_bind ("editing-mode", option_name);
+
+         if (interactive)
+           with_input_from_stdin ();
+         no_line_editing = 0;
+       }
+      else
+       {
+         int isemacs = (rl_editing_mode == 1);
+         if ((isemacs && STREQ (option_name, "emacs")) ||
+             (!isemacs && STREQ (option_name, "vi")))
+           {
+             if (interactive)
+               with_input_from_stream (stdin, "stdin");
+             no_line_editing = 1;
+           }
+         else
+           builtin_error ("not in %s editing mode", option_name);
+       }
+    }
+#endif /* READLINE */
+  else if (STREQ (option_name, "interactive-comments"))
+    interactive_comments = (on_or_off == FLAG_ON);
+  else if (STREQ (option_name, "posix"))
+    {
+      posixly_correct = (on_or_off == FLAG_ON);
+      unbind_variable ("POSIXLY_CORRECT");
+      unbind_variable ("POSIX_PEDANTIC");
+      if (on_or_off == FLAG_ON)
+       {
+         bind_variable ("POSIXLY_CORRECT", "");
+         stupidly_hack_special_variables ("POSIXLY_CORRECT");
+       }
+    }
+  else
+    {
+      register int i;
+      for (i = 0; o_options[i].name; i++)
+       {
+         if (STREQ (option_name, o_options[i].name))
+           {
+             option_char = o_options[i].letter;
+             break;
+           }
+       }
+      if (option_char == -1)
+       {
+         builtin_error ("%s: unknown option name", option_name);
+         return (EXECUTION_FAILURE);
+       }
+      if (change_flag (option_char, on_or_off) == FLAG_ERROR)
+       {
+         bad_option (option_name);
+         return (EXECUTION_FAILURE);
+       }
+    }
+  return (EXECUTION_SUCCESS);
+}
+
+/* Set some flags from the word values in the input list.  If LIST is empty,
+   then print out the values of the variables instead.  If LIST contains
+   non-flags, then set $1 - $9 to the successive words of LIST. */
+set_builtin (list)
+     WORD_LIST *list;
+{
+  int on_or_off, flag_name, force_assignment = 0;
+
+  if (!list)
+    {
+      SHELL_VAR **vars;
+
+      vars = all_shell_variables ();
+      if (vars)
+       {
+         print_var_list (vars);
+         free (vars);
+       }
+
+      vars = all_shell_functions ();
+      if (vars)
+       {
+         print_var_list (vars);
+         free (vars);
+       }
+
+      return (EXECUTION_SUCCESS);
+    }
+
+  /* Check validity of flag arguments. */
+  if (*list->word->word == '-' || *list->word->word == '+')
+    {
+      register char *arg;
+      WORD_LIST *save_list = list;
+
+      while (list && (arg = list->word->word))
+       {
+         char c;
+
+         if (arg[0] != '-' && arg[0] != '+')
+           break;
+
+         /* `-' or `--' signifies end of flag arguments. */
+         if (arg[0] == '-' &&
+             (!arg[1] || (arg[1] == '-' && !arg[2])))
+           break;
+
+         while (c = *++arg)
+           {
+             if (find_flag (c) == FLAG_UNKNOWN && c != 'o')
+               {
+                 char s[2];
+                 s[0] = c; s[1] = '\0';
+                 bad_option (s);
+                 if (c == '?')
+                   printf ("usage: %s\n", USAGE_STRING);
+                 return (c == '?' ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
+               }
+           }
+         list = list->next;
+       }
+      list = save_list;
+    }
+
+  /* Do the set command.  While the list consists of words starting with
+     '-' or '+' treat them as flags, otherwise, start assigning them to
+     $1 ... $n. */
+  while (list)
+    {
+      char *string = list->word->word;
+
+      /* If the argument is `--' or `-' then signal the end of the list
+        and remember the remaining arguments. */
+      if (string[0] == '-' && (!string[1] || (string[1] == '-' && !string[2])))
+       {
+         list = list->next;
+
+         /* `set --' unsets the positional parameters. */
+         if (string[1] == '-')
+           force_assignment = 1;
+
+         /* Until told differently, the old shell behaviour of
+            `set - [arg ...]' being equivalent to `set +xv [arg ...]'
+            stands.  Posix.2 says the behaviour is marked as obsolescent. */
+         else
+           {
+             change_flag ('x', '+');
+             change_flag ('v', '+');
+           }
+
+         break;
+       }
+
+      if ((on_or_off = *string) &&
+         (on_or_off == '-' || on_or_off == '+'))
+       {
+         int i = 1;
+         while (flag_name = string[i++])
+           {
+             if (flag_name == '?')
+               {
+                 printf ("usage: %s\n", USAGE_STRING);
+                 return (EXECUTION_SUCCESS);
+               }
+             else if (flag_name == 'o') /* -+o option-name */
+               {
+                 char *option_name;
+                 WORD_LIST *opt;
+
+                 opt = list->next;
+
+                 if (!opt)
+                   {
+                     list_minus_o_opts ();
+                     continue;
+                   }
+
+                 option_name = opt->word->word;
+
+                 if (!option_name || !*option_name || (*option_name == '-'))
+                   {
+                     list_minus_o_opts ();
+                     continue;
+                   }
+                 list = list->next; /* Skip over option name. */
+
+                 if (set_minus_o_option (on_or_off, option_name) != EXECUTION_SUCCESS)
+                   return (EXECUTION_FAILURE);
+               }
+             else
+               {
+                 if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
+                   {
+                     char opt[3];
+                     opt[0] = on_or_off;
+                     opt[1] = flag_name;
+                     opt[2] = '\0';
+                     bad_option (opt);
+                     return (EXECUTION_FAILURE);
+                   }
+               }
+           }
+       }
+      else
+       {
+         break;
+       }
+      list = list->next;
+    }
+
+  /* Assigning $1 ... $n */
+  if (list || force_assignment)
+    remember_args (list, 1);
+  return (EXECUTION_SUCCESS);
+}
+
+$BUILTIN unset
+$FUNCTION unset_builtin
+$SHORT_DOC unset [-f] [-v] [name ...]
+For each NAME, remove the corresponding variable or function.  Given
+the `-v', unset will only act on variables.  Given the `-f' flag,
+unset will only act on functions.  With neither flag, unset first
+tries to unset a variable, and if that fails, then tries to unset a
+function.  Some variables (such as PATH and IFS) cannot be unset; also
+see readonly.
+$END
+
+unset_builtin (list)
+  WORD_LIST *list;
+{
+  int unset_function = 0, unset_variable = 0, opt;
+  int any_failed = 0;
+  char *name;
+
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, "fv")) != -1)
+    {
+      switch (opt)
+       {
+       case 'f':
+         unset_function = 1;
+         break;
+       case 'v':
+         unset_variable = 1;
+         break;
+       default:
+         return (EXECUTION_FAILURE);
+       }
+    }
+
+  list = loptend;
+
+  if (unset_function && unset_variable)
+    {
+      builtin_error ("cannot simultaneously unset a function and a variable");
+      return (EXECUTION_FAILURE);
+    }
+
+  while (list)
+    {
+      name = list->word->word;
+
+      if (!unset_function &&
+         find_name_in_list (name, non_unsettable_vars) > -1)
+       {
+         builtin_error ("%s: cannot unset", name);
+         any_failed++;
+       }
+      else
+       {
+         SHELL_VAR *var;
+         int tem;
+
+         var = unset_function ? find_function (name) : find_variable (name);
+
+         /* Posix.2 says that unsetting readonly variables is an error. */
+         if (var && readonly_p (var))
+           {
+             builtin_error ("%s: cannot unset: readonly %s",
+                            name, unset_function ? "function" : "variable");
+             any_failed++;
+             list = list->next;
+             continue;
+           }
+
+         /* Unless the -f option is supplied, the name refers to a
+            variable. */
+         tem = makunbound
+           (name, unset_function ? shell_functions : shell_variables);
+
+         /* This is what Posix.2 draft 11+ says.  ``If neither -f nor -v
+            is specified, the name refers to a variable; if a variable by
+            that name does not exist, a function by that name, if any,
+            shall be unset.'' */
+         if ((tem == -1) && !unset_function && !unset_variable)
+           tem = makunbound (name, shell_functions);
+
+         if (tem == -1)
+           any_failed++;
+         else if (!unset_function)
+           stupidly_hack_special_variables (name);
+       }
+      list = list->next;
+    }
+
+  if (any_failed)
+    return (EXECUTION_FAILURE);
+  else
+    return (EXECUTION_SUCCESS);
+}
diff --git a/builtins/setattr.def b/builtins/setattr.def
new file mode 100644 (file)
index 0000000..2340e1a
--- /dev/null
@@ -0,0 +1,253 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES setattr.c
+
+#include "../shell.h"
+#include "common.h"
+#include "bashgetopt.h"
+
+extern int array_needs_making;
+extern char *this_command_name;
+
+$BUILTIN export
+$FUNCTION export_builtin
+$SHORT_DOC export [-n] [-f] [name ...] 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'
+is given, a list of all names that are exported in this shell is
+printed.  An argument of `-n' says to remove the export property
+from subsequent NAMEs.  An argument of `--' disables further option
+processing.
+$END
+
+/* For each variable name in LIST, make that variable appear in the
+   environment passed to simple commands.  If there is no LIST, then
+   print all such variables.  An argument of `-n' says to remove the
+   exported attribute from variables named in LIST.  An argument of
+  -f indicates that the names present in LIST refer to functions. */
+export_builtin (list)
+     register WORD_LIST *list;
+{
+  return (set_or_show_attributes (list, att_exported));
+}
+
+$BUILTIN readonly
+$FUNCTION readonly_builtin
+$SHORT_DOC readonly [-n] [-f] [name ...] 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
+arguments are given, or if `-p' is given, a list of all readonly names
+is printed.  An argument of `-n' says to remove the readonly property
+from subsequent NAMEs.  An argument of `--' disables further option
+processing.
+$END
+
+/* For each variable name in LIST, make that variable readonly.  Given an
+   empty LIST, print out all existing readonly variables. */
+readonly_builtin (list)
+     register WORD_LIST *list;
+{
+  return (set_or_show_attributes (list, att_readonly));
+}
+
+/* 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. */
+int
+set_or_show_attributes (list, attribute)
+     register WORD_LIST *list;
+     int attribute;
+{
+  register SHELL_VAR *var;
+  int assign, undo = 0, functions_only = 0, any_failed = 0, opt;
+
+  /* Read arguments from the front of the list. */
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, "nfp")) != -1)
+    {
+      switch (opt)
+       {
+         case 'n':
+           undo = 1;
+           break;
+         case 'f':
+           functions_only = 1;
+           break;
+         case 'p':
+           break;
+         default:
+           builtin_error ("usage: %s [-nfp] [varname]", this_command_name);
+           return (EX_USAGE);
+       }
+    }
+  list = loptend;
+
+  if (list)
+    {
+      if (attribute & att_exported)
+       array_needs_making = 1;
+
+      /* Cannot undo readonly status. */
+      if (undo && (attribute & att_readonly))
+       attribute &= ~att_readonly;
+
+      while (list)
+       {
+         register char *name = list->word->word;
+
+         if (functions_only)
+           {
+             var = find_function (name);
+             if (!var)
+               {
+                 builtin_error ("%s: not a function", name);
+                 any_failed++;
+               }
+             else
+               {
+                 if (undo)
+                   var->attributes &= ~attribute;
+                 else
+                   var->attributes |= attribute;
+               }
+             list = list->next;
+             if (attribute == att_exported)
+               array_needs_making++;
+             continue;
+           }
+
+         assign = assignment (name);
+
+          if (assign)
+           name[assign] = '\0';
+         if (legal_identifier (name) == 0)
+           {
+             builtin_error ("%s: not a legal variable name", name);
+             any_failed++;
+             list = list->next;
+             continue;
+           }
+
+         if (assign)
+           {
+             name[assign] = '=';
+             /* This word has already been expanded once with command
+                and parameter expansion.  Call do_assignment_no_expand (),
+                which does not do command or parameter substitution. */
+             do_assignment_no_expand (name);
+             name[assign] = '\0';
+           }
+
+         if (undo)
+           {
+             var = find_variable (name);
+             if (var)
+               var->attributes &= ~attribute;
+           }
+         else
+           {
+             SHELL_VAR *find_tempenv_variable (), *tv;
+
+             if (tv = find_tempenv_variable (name))
+               {
+                 var = bind_variable (tv->name, tv->value);
+                 dispose_variable (tv);
+               }
+             else
+               var = find_variable (name);
+
+             if (!var)
+               {
+                 var = bind_variable (name, (char *)NULL);
+                 var->attributes |= att_invisible;
+               }
+
+             var->attributes |= attribute;
+           }
+
+         array_needs_making++; /* XXX */
+         list = list->next;
+       }
+    }
+  else
+    {
+      SHELL_VAR **variable_list;
+      register int i;
+
+      if ((attribute & att_function) || functions_only)
+       {
+         variable_list = all_shell_functions ();
+         if (attribute != att_function)
+           attribute &= ~att_function; /* so declare -xf works, for example */
+       }
+      else
+       variable_list = all_shell_variables ();
+
+      if (variable_list)
+       {
+         for (i = 0; var = variable_list[i]; i++)
+           {
+             if ((var->attributes & attribute) && !invisible_p (var))
+               {
+                 char flags[6];
+
+                 flags[0] = '\0';
+
+                 if (exported_p (var))
+                   strcat (flags, "x");
+
+                 if (readonly_p (var))
+                   strcat (flags, "r");
+
+                 if (function_p (var))
+                   strcat (flags, "f");
+
+                 if (integer_p (var))
+                   strcat (flags, "i");
+
+                 if (flags[0])
+                   {
+                     printf ("declare -%s ", flags);
+
+                     if (!function_p (var))
+                       {
+                         char *x = double_quote (value_cell (var));
+                         printf ("%s=%s\n", var->name, x);
+                         free (x);
+                       }
+                     else
+                       {
+                         char *named_function_string ();
+
+                         printf ("%s\n", named_function_string
+                                 (var->name, function_cell (var), 1));
+                       }
+                   }
+               }
+           }
+         free (variable_list);
+       }
+    }
+  return (any_failed == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
+}
diff --git a/builtins/shift.def b/builtins/shift.def
new file mode 100644 (file)
index 0000000..4d8fed0
--- /dev/null
@@ -0,0 +1,95 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES shift.c
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "../shell.h"
+
+$BUILTIN shift
+$FUNCTION shift_builtin
+$SHORT_DOC shift [n]
+The positional parameters from $N+1 ... are renamed to $1 ...  If N is
+not given, it is assumed to be 1.
+$END
+
+/* Shift the arguments ``left''.  Shift DOLLAR_VARS down then take one
+   off of REST_OF_ARGS and place it into DOLLAR_VARS[9].  If LIST has
+   anything in it, it is a number which says where to start the
+   shifting.  Return > 0 if `times' > $#, otherwise 0. */
+int
+shift_builtin (list)
+     WORD_LIST *list;
+{
+  int times, number;
+  WORD_LIST *args;
+
+  times = get_numeric_arg (list);
+
+  if (!times)
+    return (EXECUTION_SUCCESS);
+
+  if (times < 0)
+    {
+      builtin_error ("shift count must be >= 0");
+      return (EXECUTION_FAILURE);
+    }
+
+  args = list_rest_of_args ();
+  number = list_length (args);
+  dispose_words (args);
+
+  if (times > number)
+    {
+      builtin_error ("shift count must be <= $#");
+      return (EXECUTION_FAILURE);
+    }
+
+  while (times-- > 0)
+    {
+      register int count;
+
+      if (dollar_vars[1])
+       free (dollar_vars[1]);
+
+      for (count = 1; count < 9; count++)
+       dollar_vars[count] = dollar_vars[count + 1];
+
+      if (rest_of_args)
+       {
+         WORD_LIST *temp = rest_of_args;
+
+         dollar_vars[9] = savestring (temp->word->word);
+         rest_of_args = rest_of_args->next;
+         temp->next = (WORD_LIST *)NULL;
+         dispose_words (temp);
+       }
+      else
+       dollar_vars[9] = (char *)NULL;
+    }
+
+  return (EXECUTION_SUCCESS);
+}
diff --git a/builtins/source.def b/builtins/source.def
new file mode 100644 (file)
index 0000000..895e98b
--- /dev/null
@@ -0,0 +1,186 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES source.c
+
+$BUILTIN source
+$FUNCTION source_builtin
+$SHORT_DOC source filename
+Read and execute commands from FILENAME and return.  The pathnames
+in $PATH are used to find the directory containing FILENAME.
+$END
+$BUILTIN .
+$DOCNAME dot
+$FUNCTION source_builtin
+$SHORT_DOC . filename
+Read and execute commands from FILENAME and return.  The pathnames
+in $PATH are used to find the directory containing FILENAME.
+$END
+/* source.c - Implements the `.' and `source' builtins. */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <errno.h>
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "../shell.h"
+#include "../posixstat.h"
+#include "../filecntl.h"
+#include "../execute_cmd.h"
+
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+/* Variables used here but defined in other files. */
+extern int return_catch_flag, return_catch_value;
+extern jmp_buf return_catch;
+extern int posixly_correct;
+extern int interactive, interactive_shell, last_command_exit_value;
+
+/* How many `levels' of sourced files we have. */
+int sourcelevel = 0;
+
+/* If this . script is supplied arguments, we save the dollar vars and
+   replace them with the script arguments for the duration of the script's
+   execution.  If the script does not change the dollar vars, we restore
+   what we saved.  If the dollar vars are changed in the script, we leave
+   the new values alone and free the saved values. */
+static void
+maybe_pop_dollar_vars ()
+{
+  if (dollar_vars_changed ())
+    {
+      dispose_saved_dollar_vars ();
+      set_dollar_vars_unchanged ();
+    }
+  else
+    pop_dollar_vars ();
+}
+
+/* Read and execute commands from the file passed as argument.  Guess what.
+   This cannot be done in a subshell, since things like variable assignments
+   take place in there.  So, I open the file, place it into a large string,
+   close the file, and then execute the string. */
+source_builtin (list)
+     WORD_LIST *list;
+{
+  int result, return_val;
+
+  /* Assume the best. */
+  result = EXECUTION_SUCCESS;
+
+  if (list)
+    {
+      char *string, *filename;
+      struct stat finfo;
+      int fd, tt;
+
+      filename = find_path_file (list->word->word);
+      if (!filename)
+       filename = savestring (list->word->word);
+
+      if (((fd = open (filename, O_RDONLY)) < 0) || (fstat (fd, &finfo) < 0))
+       goto file_error_exit;
+
+      string = (char *)xmalloc (1 + (int)finfo.st_size);
+      tt = read (fd, string, finfo.st_size);
+      string[finfo.st_size] = '\0';
+
+      /* Close the open file, preserving the state of errno. */
+      { int temp = errno; close (fd); errno = temp; }
+
+      if (tt != finfo.st_size)
+       {
+         free (string);
+
+       file_error_exit:
+         file_error (filename);
+         free (filename);
+
+         /* POSIX shells exit if non-interactive and file error. */
+         if (posixly_correct && !interactive_shell)
+           {
+             last_command_exit_value = 1;
+             longjmp (top_level, EXITPROG);
+           }
+
+         return (EXECUTION_FAILURE);
+       }
+
+      if (tt > 80)
+       tt = 80;
+
+      if (check_binary_file ((unsigned char *)string, tt))
+       {
+         free (string);
+         builtin_error ("%s: cannot execute binary file", filename);
+         free (filename);
+         return (EX_BINARY_FILE);
+       }
+
+      begin_unwind_frame ("File Sourcing");
+
+      if (list->next)
+       {
+         push_dollar_vars ();
+         add_unwind_protect ((Function *)maybe_pop_dollar_vars, (char *)NULL);
+         remember_args (list->next, 1);
+       }
+
+      unwind_protect_int (return_catch_flag);
+      unwind_protect_jmp_buf (return_catch);
+      unwind_protect_int (interactive);
+      unwind_protect_int (sourcelevel);
+      add_unwind_protect ((Function *)xfree, filename);
+      interactive = 0;
+      sourcelevel++;
+
+      set_dollar_vars_unchanged ();
+
+      return_catch_flag++;
+      return_val = setjmp (return_catch);
+
+      if (return_val)
+       parse_and_execute_cleanup ();
+      else
+       result = parse_and_execute (string, filename, -1);
+
+      run_unwind_frame ("File Sourcing");
+
+      /* If RETURN_VAL is non-zero, then we return the value given
+        to return_builtin (), since that is how we got here. */
+      if (return_val)
+       result = return_catch_value;
+    }
+  else
+    {
+      builtin_error ("filename argument required");
+      result = EXECUTION_FAILURE;
+    }
+  return (result);
+}
diff --git a/builtins/suspend.def b/builtins/suspend.def
new file mode 100644 (file)
index 0000000..48edc20
--- /dev/null
@@ -0,0 +1,86 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES suspend.c
+
+$BUILTIN suspend
+$DEPENDS_ON JOB_CONTROL
+$FUNCTION suspend_builtin
+$SHORT_DOC suspend [-f]
+Suspend the execution of this shell until it receives a SIGCONT
+signal.  The `-f' if specified says not to complain about this
+being a login shell if it is; just suspend anyway.
+$END
+
+#include <sys/types.h>
+#include <signal.h>
+#include "../shell.h"
+#include "../jobs.h"
+
+#if defined (JOB_CONTROL)
+extern int job_control;
+
+static SigHandler *old_cont, *old_tstp;
+
+/* Continue handler. */
+sighandler
+suspend_continue (sig)
+     int sig;
+{
+  set_signal_handler (SIGCONT, old_cont);
+  set_signal_handler (SIGTSTP, old_tstp);
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* !VOID_SIGHANDLER */
+}
+
+/* Suspending the shell.  If -f is the arg, then do the suspend
+   no matter what.  Otherwise, complain if a login shell. */
+int
+suspend_builtin (list)
+     WORD_LIST *list;
+{
+  if (!job_control)
+    {
+      builtin_error ("Cannot suspend a shell without job control");
+      return (EXECUTION_FAILURE);
+    }
+
+  if (list)
+    if (strcmp (list->word->word, "-f") == 0)
+      goto do_suspend;
+
+  no_args (list);
+
+  if (login_shell)
+    {
+      builtin_error ("Can't suspend a login shell");
+      return (EXECUTION_FAILURE);
+    }
+
+do_suspend:
+  old_cont = (SigHandler *)set_signal_handler (SIGCONT, suspend_continue);
+  old_tstp = (SigHandler *)set_signal_handler (SIGTSTP, SIG_DFL);
+  killpg (shell_pgrp, SIGTSTP);
+  return (EXECUTION_SUCCESS);
+}
+
+#endif /* JOB_CONTROL */
diff --git a/builtins/test.def b/builtins/test.def
new file mode 100644 (file)
index 0000000..2b1457b
--- /dev/null
@@ -0,0 +1,144 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES test.c
+
+$BUILTIN test
+$FUNCTION test_builtin
+$SHORT_DOC test [expr]
+Exits with a status of 0 (trueness) or 1 (falseness) 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.
+
+File operators:
+
+    -b FILE        True if file is block special.
+    -c FILE        True if file is character special.
+    -d FILE        True if file is a directory.
+    -e FILE        True if file exists.
+    -f FILE        True if file exists and is a regular file.
+    -g FILE        True if file is set-group-id.
+    -h FILE        True if file is a symbolic link.  Use "-L".
+    -L FILE        True if file is a symbolic link.
+    -k FILE        True if file has its "sticky" bit set.
+    -p FILE        True if file is a named pipe.
+    -r FILE        True if file is readable by you.
+    -s FILE        True if file is not empty.
+    -S FILE        True if file is a socket.
+    -t FD          True if FD is opened on a terminal.
+    -u FILE        True if the file is set-user-id.
+    -w FILE        True if the file is writable by you.
+    -x FILE        True if the file is executable by you.
+    -O FILE        True if the file is effectively owned by you.
+    -G FILE        True if the file is effectively owned by your group.
+
+  FILE1 -nt FILE2  True if file1 is newer than (according to
+                   modification date) file2.
+
+  FILE1 -ot FILE2  True if file1 is older than file2.
+
+  FILE1 -ef FILE2  True if file1 is a hard link to file2.
+
+String operators:
+
+    -z STRING      True if string is empty.
+
+    -n STRING
+ or STRING         True if string is not empty.
+
+    STRING1 = STRING2
+                   True if the strings are equal.
+    STRING1 != STRING2
+                   True if the strings are not equal.
+
+Other operators:
+
+    ! EXPR         True if expr is false.
+    EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
+    EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.
+
+    arg1 OP arg2   Arithmetic tests.  OP is one of -eq, -ne,
+                   -lt, -le, -gt, or -ge.
+
+Arithmetic binary operators return true if ARG1 is equal, not-equal,
+less-than, less-than-or-equal, greater-than, or greater-than-or-equal
+than ARG2.
+$END
+
+$BUILTIN [
+$DOCNAME test_bracket
+$FUNCTION test_builtin
+$SHORT_DOC [ arg... ]
+This is a synonym for the "test" shell builtin, excepting that the
+last argument must be literally `]', to match the `[' which invoked
+the test.
+$END
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "../shell.h"
+extern char *this_command_name;
+
+/* TEST/[ builtin. */
+int
+test_builtin (list)
+     WORD_LIST *list;
+{
+  char **argv;
+  int argc, result;
+  WORD_LIST *t = list;
+
+  /* We let Matthew Bradburn and Kevin Braunsdorf's code do the
+     actual test command.  So turn the list of args into an array
+     of strings, since that is what his code wants. */
+  if (!list)
+    {
+      if (this_command_name[0] == '[' && !this_command_name[1])
+       builtin_error ("missing `]'");
+
+      return (EXECUTION_FAILURE);
+    }
+
+  /* Get the length of the argument list. */
+  for (argc = 0; t; t = t->next, argc++);
+
+  /* Account for argv[0] being a command name.  This makes our life easier. */
+  argc++;
+  argv = (char **)xmalloc ((1 + argc) * sizeof (char *));
+  argv[argc] = (char *)NULL;
+
+  /* this_command_name is the name of the command that invoked this
+     function.  So you can't call test_builtin () directly from
+     within this code, there are too many things to worry about. */
+  argv[0] = savestring (this_command_name);
+
+  for (t = list, argc = 1; t; t = t->next, argc++)
+    argv[argc] = savestring (t->word->word);
+
+  result = test_command (argc, argv);
+  free_array (argv);
+  return (result);
+}
diff --git a/builtins/times.def b/builtins/times.def
new file mode 100644 (file)
index 0000000..9c42768
--- /dev/null
@@ -0,0 +1,89 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES times.c
+
+$BUILTIN times
+$FUNCTION times_builtin
+$SHORT_DOC times
+Print the accumulated user and system times for processes run from
+the shell.
+$END
+
+#include "../shell.h"
+#include <sys/types.h>
+
+#if defined (hpux) || defined (USGr4) || defined (XD88) || defined (USGr3)
+#  undef HAVE_RESOURCE
+#endif /* hpux || USGr4 || XD88 || USGr3 */
+
+#if defined (_POSIX_VERSION) || !defined (HAVE_RESOURCE)
+#  include <sys/times.h>
+#else /* !_POSIX_VERSION && HAVE_RESOURCE */
+#  include <sys/time.h>
+#  include <sys/resource.h>
+#endif /* !_POSIX_VERSION && HAVE_RESOURCE */
+
+/* Print the totals for system and user time used.  The
+   information comes from variables in jobs.c used to keep
+   track of this stuff. */
+times_builtin (list)
+     WORD_LIST *list;
+{
+#if !defined (_POSIX_VERSION) && defined (HAVE_RESOURCE) && defined (RUSAGE_SELF)
+  struct rusage self, kids;
+
+  getrusage (RUSAGE_SELF, &self);
+  getrusage (RUSAGE_CHILDREN, &kids);  /* terminated child processes */
+
+  print_timeval (&self.ru_utime);
+  putchar (' ');
+  print_timeval (&self.ru_stime);
+  putchar ('\n');
+  print_timeval (&kids.ru_utime);
+  putchar (' ');
+  print_timeval (&kids.ru_stime);
+  putchar ('\n');
+
+#else /* _POSIX_VERSION || !HAVE_RESOURCE || !RUSAGE_SELF */
+#  if !defined (BrainDeath)
+  struct tms t;
+
+  times (&t);
+
+  /* As of System V.3, HP-UX 6.5, and other ATT-like systems, this stuff is
+     returned in terms of clock ticks (HZ from sys/param.h).  C'mon, guys.
+     This kind of stupid clock-dependent stuff is exactly the reason 4.2BSD
+     introduced the `timeval' struct. */
+
+  print_time_in_hz (t.tms_utime);
+  putchar (' ');
+  print_time_in_hz (t.tms_stime);
+  putchar ('\n');
+  print_time_in_hz (t.tms_cutime);
+  putchar (' ');
+  print_time_in_hz (t.tms_cstime);
+  putchar ('\n');
+#  endif /* BrainDeath */
+#endif /* _POSIX_VERSION || !HAVE_RESOURCE || !RUSAGE_SELF */
+
+  return (EXECUTION_SUCCESS);
+}
diff --git a/builtins/trap.def b/builtins/trap.def
new file mode 100644 (file)
index 0000000..b81651d
--- /dev/null
@@ -0,0 +1,204 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES trap.c
+
+$BUILTIN trap
+$FUNCTION trap_builtin
+$SHORT_DOC trap [arg] [signal_spec]
+The command ARG is to be read and executed when the shell receives
+signal(s) SIGNAL_SPEC.  If ARG is absent all specified signals are
+reset to their original values.  If ARG is the null string this
+signal is ignored by the shell and by the commands it invokes.  If
+SIGNAL_SPEC is EXIT (0) the command ARG is executed on exit from
+the shell.  The trap command with no arguments prints the list of
+commands associated with each signal number.  SIGNAL_SPEC is either
+a signal name in <signal.h>, or a signal number.  The syntax `trap -l'
+prints a list of signal names and their corresponding numbers.
+Note that a signal can be sent to the shell with "kill -signal $$".
+$END
+
+#include <sys/types.h>
+#include <signal.h>
+#include "../shell.h"
+#include "../trap.h"
+#include "common.h"
+
+/* The trap command:
+
+   trap <arg> <signal ...>
+   trap <signal ...>
+   trap -l
+   trap [--]
+
+   Set things up so that ARG is executed when SIGNAL(s) N is recieved.
+   If ARG is the empty string, then ignore the SIGNAL(s).  If there is
+   no ARG, then set the trap for SIGNAL(s) to its original value.  Just
+   plain "trap" means to print out the list of commands associated with
+   each signal number.  Single arg of "-l" means list the signal names. */
+
+/* Possible operations to perform on the list of signals.*/
+#define SET 0                  /* Set this signal to first_arg. */
+#define REVERT 1               /* Revert to this signals original value. */
+#define IGNORE 2               /* Ignore this signal. */
+
+extern int interactive;
+
+trap_builtin (list)
+     WORD_LIST *list;
+{
+  register int i;
+  int list_signal_names = 0;
+
+  while (list)
+    {
+      if (ISOPTION (list->word->word, 'l'))
+       {
+         list_signal_names++;
+         list = list->next;
+       }
+      else if (ISOPTION (list->word->word, '-'))
+       {
+         list = list->next;
+         break;
+       }
+      else if ((*list->word->word == '-') && list->word->word[1])
+       {
+         bad_option (list->word->word);
+         builtin_error ("usage: trap [-l] [arg] [sigspec]");
+         return (EX_USAGE);
+       }
+      else
+       break;
+    }
+
+  if (list_signal_names)
+    {
+      int column = 0;
+
+      for (i = 0; i < NSIG; i++)
+       {
+         printf ("%2d) %s", i, signal_name (i));
+         if (++column < 4)
+           printf ("\t");
+         else
+           {
+             printf ("\n");
+             column = 0;
+           }
+       }
+      if (column != 0)
+       printf ("\n");
+      return (EXECUTION_SUCCESS);
+    }
+
+  if (list)
+    {
+      char *first_arg = list->word->word;
+      int operation = SET, any_failed = 0;
+
+      if (signal_object_p (first_arg))
+       operation = REVERT;
+      else
+       {
+         list = list->next;
+         if (*first_arg == '\0')
+           operation = IGNORE;
+         else if (first_arg[0] == '-' && !first_arg[1])
+           operation = REVERT;
+       }
+
+      while (list)
+       {
+         int sig;
+
+         sig = decode_signal (list->word->word);
+
+         if (sig == NO_SIG)
+           {
+             builtin_error ("%s: not a signal specification",
+                            list->word->word);
+             any_failed++;
+           }
+         else
+           {
+             switch (operation)
+               {
+                 case SET:
+                   set_signal (sig, first_arg);
+                   break;
+
+                 case REVERT:
+                   restore_default_signal (sig);
+
+                   /* Signals that the shell treats specially need special
+                      handling. */
+                   switch (sig)
+                     {
+                     case SIGINT:
+                       if (interactive)
+                         set_signal_handler (SIGINT, sigint_sighandler);
+                       else
+                         set_signal_handler (SIGINT, termination_unwind_protect);
+                       break;
+
+                     case SIGQUIT:
+                       /* Always ignore SIGQUIT. */
+                       set_signal_handler (SIGQUIT, SIG_IGN);
+                       break;
+                     case SIGTERM:
+#if defined (JOB_CONTROL)
+                     case SIGTTIN:
+                     case SIGTTOU:
+                     case SIGTSTP:
+#endif /* JOB_CONTROL */
+                       if (interactive)
+                         set_signal_handler (sig, SIG_IGN);
+                       break;
+                     }
+                   break;
+
+                 case IGNORE:
+                   ignore_signal (sig);
+                   break;
+               }
+           }
+         list = list->next;
+       }
+      return ((!any_failed) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
+    }
+
+  for (i = 0; i < NSIG; i++)
+    {
+      char *t, *p;
+
+      p = trap_list[i];
+
+      if (p == (char *)DEFAULT_SIG)
+       continue;
+
+      t = (p == (char *)IGNORE_SIG) ? (char *)NULL : single_quote (p);
+      printf ("trap -- %s %s\n", t ? t : "''", signal_name (i));
+      if (t)
+       free (t);
+    }
+  return (EXECUTION_SUCCESS);
+}
diff --git a/builtins/type.def b/builtins/type.def
new file mode 100644 (file)
index 0000000..aecc303
--- /dev/null
@@ -0,0 +1,325 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES type.c
+
+$BUILTIN type
+$FUNCTION type_builtin
+$SHORT_DOC type [-all] [-type | -path] [name ...]
+For each NAME, indicate how it would be interpreted if used as a
+command name.
+
+If the -type flag is used, returns a single word which is one of
+`alias', `keyword', `function', `builtin', `file' or `', if NAME is an
+alias, shell reserved word, shell function, shell builtin, disk file,
+or unfound, respectively.
+
+If the -path flag is used, either returns the name of the disk file
+that would be exec'ed, or nothing if -type wouldn't return `file'.
+
+If the -all flag is used, displays all of the places that contain an
+executable named `file'.  This includes aliases and functions, if and
+only if the -path flag is not also used.
+$END
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "../posixstat.h"
+#include "../shell.h"
+#include "../execute_cmd.h"
+
+#if defined (ALIAS)
+#include "../alias.h"
+#endif /* ALIAS */
+
+#include "common.h"
+
+extern STRING_INT_ALIST word_token_alist[];
+
+/* For each word in LIST, find out what the shell is going to do with
+   it as a simple command. i.e., which file would this shell use to
+   execve, or if it is a builtin command, or an alias.  Possible flag
+   arguments:
+       -type           Returns the "type" of the object, one of
+                       `alias', `keyword', `function', `builtin',
+                       or `file'.
+
+       -path           Returns the pathname of the file if -type is
+                       a file.
+
+       -all            Returns all occurrences of words, whether they
+                       be a filename in the path, alias, function,
+                       or builtin.
+   Order of evaluation:
+       alias
+       keyword
+       function
+       builtin
+       file
+ */
+type_builtin (list)
+     WORD_LIST *list;
+{
+  int path_only, type_only, all, verbose;
+  int successful_finds;
+
+  path_only = type_only = all = 0;
+  successful_finds = 0;
+
+  if (!list)
+    return (EXECUTION_SUCCESS);
+
+  while (list && *(list->word->word) == '-')
+    {
+      char *flag = &(list->word->word[1]);
+
+      if (flag[0] == 't' && (!flag[1] || strcmp (flag + 1, "ype") == 0))
+       {
+         type_only = 1;
+         path_only = 0;
+       }
+      else if (flag[0] == 'p' && (!flag[1] || strcmp (flag + 1, "ath") == 0))
+       {
+         path_only = 1;
+         type_only = 0;
+       }
+      else if (flag[0] == 'a' && (!flag[1] || strcmp (flag + 1, "ll") == 0))
+       {
+         all = 1;
+       }
+      else
+       {
+         bad_option (flag);
+         builtin_error ("usage: type [-all | -path | -type ] name [name ...]");
+         return (EX_USAGE);
+       }
+      list = list->next;
+    }
+
+  if (type_only)
+    verbose = 1;
+  else if (!path_only)
+    verbose = 2;
+  else if (path_only)
+    verbose = 3;
+  else
+    verbose = 0;
+
+  while (list)
+    {
+      int found;
+
+      found = describe_command (list->word->word, verbose, all);
+
+      if (!found && !path_only && !type_only)
+       builtin_error ("%s: not found", list->word->word);
+
+      successful_finds += found;
+      list = list->next;
+    }
+
+  fflush (stdout);
+
+  if (successful_finds != 0)
+    return (EXECUTION_SUCCESS);
+  else
+    return (EXECUTION_FAILURE);
+}
+
+/*
+ * Describe COMMAND as required by the type builtin.
+ *
+ * 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'
+ *
+ * ALL says whether or not to look for all occurrences of COMMAND, or
+ * return after finding it once.
+ */
+describe_command (command, verbose, all)
+     char *command;
+     int verbose, all;
+{
+  int found = 0, i, found_file = 0;
+  char *full_path = (char *)NULL;
+  SHELL_VAR *func;
+
+#if defined (ALIAS)
+  /* Command is an alias? */
+  ASSOC *alias = find_alias (command);
+
+  if (alias)
+    {
+      if (verbose == 1)
+       printf ("alias\n");
+      else if (verbose == 2)
+       printf ("%s is aliased to `%s'\n", command, alias->value);
+      else if (verbose == 4)
+       {
+         char *x = single_quote (alias->value);
+         printf ("alias %s=%s\n", command, x);
+         free (x);
+       }
+
+      found = 1;
+
+      if (!all)
+       return (1);
+    }
+#endif /* ALIAS */
+
+  /* Command is a shell reserved word? */
+  i = find_reserved_word (command);
+  if (i >= 0)
+    {
+      if (verbose == 1)
+       printf ("keyword\n");
+      else if (verbose == 2)
+       printf ("%s is a shell keyword\n", command);
+      else if (verbose == 4)
+       printf ("%s\n", command);
+
+      found = 1;
+
+      if (!all)
+       return (1);
+    }
+
+  /* Command is a function? */
+  func = find_function (command);
+
+  if (func)
+    {
+      if (verbose == 1)
+       printf ("function\n");
+      else if (verbose == 2)
+       {
+#define PRETTY_PRINT_FUNC 1
+         char *result;
+
+         printf ("%s is a function\n", command);
+
+         /* We're blowing away THE_PRINTED_COMMAND here... */
+
+         result = named_function_string (command,
+                                         (COMMAND *) function_cell (func),
+                                         PRETTY_PRINT_FUNC);
+         printf ("%s\n", result);
+#undef PRETTY_PRINT_FUNC
+       }
+      else if (verbose == 4)
+       printf ("%s\n", command);
+
+      found = 1;
+
+      if (!all)
+       return (1);
+    }
+
+  /* Command is a builtin? */
+  if (find_shell_builtin (command))
+    {
+      if (verbose == 1)
+       printf ("builtin\n");
+      else if (verbose == 2)
+       printf ("%s is a shell builtin\n", command);
+      else if (verbose == 4)
+       printf ("%s\n", command);
+
+      found = 1;
+
+      if (!all)
+       return (1);
+    }
+
+  /* Command is a disk file? */
+  /* If the command name given is already an absolute command, just
+     check to see if it is executable. */
+  if (absolute_program (command))
+    {
+      int f = file_status (command);
+      if (f & FS_EXECABLE)
+        {
+         if (verbose == 1)
+           printf ("file\n");
+         else if (verbose == 2)
+           printf ("%s is %s\n", command, command);
+         else if (verbose == 3 || verbose == 4)
+           printf ("%s\n", command);
+
+         /* There's no use looking in the hash table or in $PATH,
+            because they're not consulted when an absolute program
+            name is supplied. */
+         return (1);
+        }
+    }
+
+  /* If the user isn't doing "-all", then we might care about
+     whether the file is present in our hash table. */
+  if (!all)
+    {
+      if ((full_path = find_hashed_filename (command)) != (char *)NULL)
+       {
+         if (verbose == 1)
+           printf ("file\n");
+         else if (verbose == 2)
+           printf ("%s is hashed (%s)\n", command, full_path);
+         else if (verbose == 3 || verbose == 4)
+           printf ("%s\n", full_path);
+
+         return (1);
+       }
+    }
+
+  /* Now search through $PATH. */
+  while (1)
+    {
+      if (!all)
+       full_path = find_user_command (command);
+      else
+       full_path =
+         user_command_matches (command, FS_EXEC_ONLY, found_file);
+         /* XXX - should that be FS_EXEC_PREFERRED? */
+
+      if (!full_path)
+       break;
+
+      found_file++;
+      found = 1;
+
+      if (verbose == 1)
+       printf ("file\n");
+      else if (verbose == 2)
+       printf ("%s is %s\n", command, full_path);
+      else if (verbose == 3 || verbose == 4)
+       printf ("%s\n", full_path);
+
+      free (full_path);
+      full_path = (char *)NULL;
+
+      if (!all)
+       break;
+    }
+
+  return (found);
+}
diff --git a/builtins/ulimit.def b/builtins/ulimit.def
new file mode 100644 (file)
index 0000000..1947c36
--- /dev/null
@@ -0,0 +1,731 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES ulimit.c
+
+$BUILTIN ulimit
+$FUNCTION ulimit_builtin
+$DEPENDS_ON !MINIX
+$SHORT_DOC ulimit [-SHacdfmstpnuv [limit]]
+Ulimit provides control over the resources available to processes
+started by the shell, on systems that allow such control.  If an
+option is given, it is interpreted as follows:
+
+    -S use the `soft' resource limit
+    -H use the `hard' resource limit
+    -a all current limits are reported
+    -c the maximum size of core files created
+    -d the maximum size of a process's data segment
+    -m the maximum resident set size
+    -s the maximum stack size
+    -t the maximum amount of cpu time in seconds
+    -f the maximum size of files created by the shell
+    -p the pipe buffer size
+    -n the maximum number of open file descriptors
+    -u the maximum number of user processes
+    -v the size of virtual memory 
+
+If LIMIT is given, it is the new value of the specified resource.
+Otherwise, the current value of the specified resource is printed.
+If no option is given, then -f is assumed.  Values are in 1k
+increments, except for -t, which is in seconds, -p, which is in
+increments of 512 bytes, and -u, which is an unscaled number of
+processes.
+$END
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <errno.h>
+#include "../shell.h"
+#include "pipesize.h"
+
+#if !defined (errno)
+extern int errno;
+#endif
+
+#if defined (HAVE_RESOURCE)
+#  include <sys/time.h>
+#  include <sys/resource.h>
+#else
+#  include <sys/times.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#if defined (HAVE_LIMITS_H)
+#  include <limits.h>
+#endif
+
+/* Check for the most basic symbols.  If they aren't present, this
+   system's <sys/resource.h> isn't very useful to us. */
+#if !defined (RLIMIT_FSIZE) || defined (GETRLIMIT_MISSING)
+#  undef HAVE_RESOURCE
+#endif
+
+#if !defined (RLIMTYPE)
+#  define RLIMTYPE long
+#  define string_to_rlimtype string_to_long
+#  define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "")
+#endif
+
+static void print_long ();
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Ulimit builtin and Hacks.                   */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Block size for ulimit operations. */
+#define ULIMIT_BLOCK_SIZE ((long)1024)
+
+#define u_FILE_SIZE            0x001
+#define u_MAX_BREAK_VAL                0x002
+#define u_PIPE_SIZE            0x004
+#define u_CORE_FILE_SIZE       0x008
+#define u_DATA_SEG_SIZE                0x010
+#define u_PHYS_MEM_SIZE                0x020
+#define u_CPU_TIME_LIMIT       0x040
+#define u_STACK_SIZE           0x080
+#define u_NUM_OPEN_FILES       0x100
+#define u_MAX_VIRTUAL_MEM      0x200
+#define u_MAX_USER_PROCS       0x400
+
+#define u_ALL_LIMITS           0x7ff
+
+#if !defined (RLIM_INFINITY)
+#  define RLIM_INFINITY  0x7fffffff
+#endif
+
+/* Some systems use RLIMIT_NOFILE, others use RLIMIT_OFILE */
+#if defined (HAVE_RESOURCE) && defined (RLIMIT_OFILE) && !defined (RLIMIT_NOFILE)
+#  define RLIMIT_NOFILE RLIMIT_OFILE
+#endif /* HAVE_RESOURCE && RLIMIT_OFILE && !RLIMIT_NOFILE */
+
+#define LIMIT_HARD 0x01
+#define LIMIT_SOFT 0x02
+
+static RLIMTYPE shell_ulimit ();
+static RLIMTYPE pipesize ();
+static RLIMTYPE open_files ();
+
+#if defined (HAVE_RESOURCE)
+static RLIMTYPE getmaxvm ();
+#endif /* HAVE_RESOURCE */
+
+static void print_specific_limits ();
+static void print_all_limits ();
+
+static char t[2];
+
+/* Return 1 if the limit associated with CMD can be raised from CURRENT
+   to NEW.  This is for USG systems without HAVE_RESOURCE, most of which
+   do not allow any user other than root to raise limits.  There are,
+   however, exceptions. */
+#if !defined (HAVE_RESOURCE)
+static int
+canraise (cmd, current, new)
+     int cmd;
+     RLIMTYPE current, new;
+{
+#  if defined (HAVE_SETDTABLESIZE)
+  if (cmd == u_NUM_OPEN_FILES)
+    return (1);
+#  endif /* HAVE_SETDTABLSIZE */
+
+  return ((current > new) || (current_user.uid == 0));
+}
+#endif /* !HAVE_RESOURCE */
+
+/* Report or set limits associated with certain per-process resources.
+   See the help documentation in builtins.c for a full description.
+
+   Rewritten by Chet Ramey 6/30/91. */
+int
+ulimit_builtin (list)
+     register WORD_LIST *list;
+{
+  register char *s;
+  int c, setting, cmd, mode, verbose_print, opt_eof;
+  int all_limits, specific_limits;
+  long block_factor;
+  RLIMTYPE current_limit, real_limit, limit;
+
+  c = mode = verbose_print = opt_eof = 0;
+  limit = (RLIMTYPE)-1;
+
+  do
+    {
+      cmd = setting = all_limits = specific_limits = 0;
+      block_factor = ULIMIT_BLOCK_SIZE;
+
+      /* read_options: */
+      if (list && !opt_eof && *list->word->word == '-')
+       {
+         s = &(list->word->word[1]);
+         list = list->next;
+
+         while (*s && (c = *s++))
+           {
+             switch (c)
+               {
+#define ADD_CMD(x) { if (cmd) specific_limits++; cmd |= (x); }
+
+               case '-':       /* ulimit -- */
+                 opt_eof++;
+                 break;
+                 
+               case 'a':
+                 all_limits++;
+                 break;
+
+               case 'f':
+                 ADD_CMD (u_FILE_SIZE);
+                 break;
+
+#if defined (HAVE_RESOURCE)
+               /* -S and -H are modifiers, not real options.  */
+               case 'S':
+                 mode |= LIMIT_SOFT;
+                 break;
+
+               case 'H':
+                 mode |= LIMIT_HARD;
+                 break;
+
+               case 'c':
+                 ADD_CMD (u_CORE_FILE_SIZE);
+                 break;
+
+               case 'd':
+                 ADD_CMD (u_DATA_SEG_SIZE);
+                 break;
+
+#if !defined (USGr4)
+               case 'm':
+                 ADD_CMD (u_PHYS_MEM_SIZE);
+                 break;
+#endif /* USGr4 */
+
+               case 't':
+                 ADD_CMD (u_CPU_TIME_LIMIT);
+                 block_factor = 1;     /* seconds */
+                 break;
+
+               case 's':
+                 ADD_CMD (u_STACK_SIZE);
+                 break;
+
+               case 'v':
+                 ADD_CMD (u_MAX_VIRTUAL_MEM);
+                 block_factor = 1;
+                 break;
+
+               case 'u':
+                 ADD_CMD (u_MAX_USER_PROCS);
+                 block_factor = 1;
+                 break;
+
+#endif /* HAVE_RESOURCE */
+
+               case 'p':
+                 ADD_CMD (u_PIPE_SIZE);
+                 block_factor = 512;
+                 break;
+
+               case 'n':
+                 ADD_CMD (u_NUM_OPEN_FILES);
+                 block_factor = 1;
+                 break;
+
+               default:                /* error_case: */
+                 t[0] = c;
+                 t[1] = '\0';
+                 bad_option (t);
+#if !defined (HAVE_RESOURCE)
+                 builtin_error("usage: ulimit [-afnp] [new limit]");
+#else
+                 builtin_error("usage: ulimit [-SHacmdstfnpuv] [new limit]");
+#endif
+                 return (EX_USAGE);
+               }
+           }
+       }
+
+       if (all_limits)
+         {
+           print_all_limits (mode);
+           return (EXECUTION_SUCCESS);
+         }
+
+       if (specific_limits)
+         {
+           print_specific_limits (cmd, mode);
+           if (list)
+             verbose_print++;
+           continue;
+         }
+
+       if (cmd == 0)
+         cmd = u_FILE_SIZE;
+
+       /* If an argument was supplied for the command, then we want to
+          set the limit.  Note that `ulimit something' means a command
+          of -f with argument `something'. */
+       if (list)
+         {
+           if (opt_eof || (*list->word->word != '-'))
+             {
+               s = list->word->word;
+               list = list->next;
+
+               if (STREQ (s, "unlimited"))
+                 limit = RLIM_INFINITY;
+               else if (all_digits (s))
+                 limit = string_to_rlimtype (s);
+               else
+                 {
+                   builtin_error ("bad non-numeric arg `%s'", s);
+                   return (EXECUTION_FAILURE);
+                 }
+               setting++;
+             }
+           else if (!opt_eof)
+             verbose_print++;
+         }
+
+      if (limit == RLIM_INFINITY)
+       block_factor = 1;
+
+      real_limit = limit * block_factor;
+
+      /* If more than one option is given, list each in a verbose format,
+        the same that is used for -a. */
+      if (!setting && verbose_print)
+       {
+         print_specific_limits (cmd, mode);
+         continue;
+       }
+
+      current_limit = shell_ulimit (cmd, real_limit, 0, mode);
+
+      if (setting)
+       {
+#if !defined (HAVE_RESOURCE)
+         /* Most USG systems do not most allow limits to be raised by any
+            user other than root.  There are, however, exceptions. */
+         if (canraise (cmd, current_limit, real_limit) == 0)
+           {
+             builtin_error ("cannot raise limit: %s", strerror (EPERM));
+             return (EXECUTION_FAILURE);
+           }
+#endif /* !HAVE_RESOURCE */
+
+         if (shell_ulimit (cmd, real_limit, 1, mode) == (RLIMTYPE)-1)
+           {
+             builtin_error ("cannot raise limit: %s", strerror (errno));
+             return (EXECUTION_FAILURE);
+           }
+
+         continue;
+       }
+      else
+       {
+         if (current_limit < 0)
+           builtin_error ("cannot get limit: %s", strerror (errno));
+         else if (current_limit != RLIM_INFINITY)
+           print_rlimtype ((current_limit / block_factor), 1);
+         else
+           printf ("unlimited\n");
+       }
+    }
+  while (list);
+
+  return (EXECUTION_SUCCESS);
+}
+
+/* The ulimit that we call from within Bash.
+
+   WHICH says which limit to twiddle; SETTING is non-zero if NEWLIM
+   contains the desired new limit.  Otherwise, the existing limit is
+   returned.  If mode & LIMIT_HARD, the hard limit is used; if
+   mode & LIMIT_SOFT, the soft limit.  Both may be set by specifying
+   -H and -S; if both are specified, or if neither is specified, the
+   soft limit will be returned.
+
+   Systems without BSD resource limits can specify only u_FILE_SIZE.
+   This includes most USG systems.
+
+   Chet Ramey supplied the BSD resource limit code. */
+static RLIMTYPE
+shell_ulimit (which, newlim, setting, mode)
+     int which, setting, mode;
+     RLIMTYPE newlim;
+{
+#if defined (HAVE_RESOURCE)
+  struct rlimit limit;
+  int cmd;
+
+  if (mode == 0)
+    mode |= LIMIT_SOFT;
+#endif
+
+  switch (which)
+    {
+#if !defined (HAVE_RESOURCE)
+
+    case u_FILE_SIZE:
+      if (!setting)
+       {
+         /* ulimit () returns a number that is in 512 byte blocks, thus we
+            must multiply it by 512 to get back to bytes.  This is false
+            only under HP/UX 6.x. */
+         RLIMTYPE result;
+
+         result = ulimit (1, 0L);
+
+#  if defined (hpux) && !defined (_POSIX_VERSION)
+         return (result);
+#  else
+         return (result * 512);
+#  endif /* hpux 6.x */
+       }
+      else
+       return (ulimit (2, newlim / 512L));
+
+      break;
+
+#else /* defined (HAVE_RESOURCE) */
+
+    case u_FILE_SIZE:
+      cmd = RLIMIT_FSIZE;
+      goto do_ulimit;
+
+    case u_CORE_FILE_SIZE:
+      cmd = RLIMIT_CORE;
+      goto do_ulimit;
+
+    case u_DATA_SEG_SIZE:
+      cmd = RLIMIT_DATA;
+      goto do_ulimit;
+
+#if !defined (USGr4)
+    case u_PHYS_MEM_SIZE:
+#  if defined (RLIMIT_RSS)
+      cmd = RLIMIT_RSS;
+#  else /* !RLIMIT_RSS */
+      errno = EINVAL;
+      return ((RLIMTYPE)-1);
+#  endif /* !RLIMIT_RSS */
+
+      goto do_ulimit;
+#endif /* USGr4 */
+
+    case u_CPU_TIME_LIMIT:
+#if defined (RLIMIT_CPU)
+      cmd = RLIMIT_CPU;
+      goto do_ulimit;
+#else
+      errno = EINVAL;
+      return ((RLIMTYPE)-1);
+#  endif /* !RLIMIT_CPU */
+
+
+    case u_STACK_SIZE:
+      cmd = RLIMIT_STACK;
+
+    do_ulimit:
+
+      if (getrlimit (cmd, &limit) != 0)
+       return ((RLIMTYPE)-1);
+
+      if (!setting)
+       {
+         if (mode & LIMIT_SOFT)
+           return (limit.rlim_cur);
+         else
+           return (limit.rlim_max);
+       }
+      else
+       {
+         if (mode & LIMIT_SOFT)
+           {
+             /* Non-root users are only allowed to raise a limit up to the
+                hard limit, not to infinity. */
+             if (current_user.euid != 0 && newlim == RLIM_INFINITY)
+               limit.rlim_cur = limit.rlim_max;
+             else
+               limit.rlim_cur = newlim;
+           }
+         if (mode & LIMIT_HARD)
+           limit.rlim_max = newlim;
+
+         return (setrlimit (cmd, &limit));
+       }
+
+      break;
+
+#endif /* HAVE_RESOURCE */
+
+      /* You can't get or set the pipe size with getrlimit, so we have to
+        cheat.  */
+    case u_PIPE_SIZE:
+      if (setting)
+       {
+         errno = EINVAL;
+         return ((RLIMTYPE)-1);
+       }
+      return (pipesize ());
+
+    case u_NUM_OPEN_FILES:
+      if (setting)
+       {
+#if defined (HAVE_RESOURCE) && defined (RLIMIT_NOFILE)
+         cmd = RLIMIT_NOFILE;
+         goto do_ulimit;
+#else
+#  if defined (HAVE_SETDTABLESIZE)
+         return (setdtablesize (newlim));
+#  else
+         errno = EINVAL;
+         return ((RLIMTYPE)-1);
+#  endif /* HAVE_SETDTABLESIZE */
+#endif /* !HAVE_RESOURCE || !RLIMIT_NOFILE */
+       }
+      else
+       return (open_files (mode));
+
+    case u_MAX_VIRTUAL_MEM:
+      if (setting)
+       {
+         errno = EINVAL;
+         return ((RLIMTYPE)-1);
+       }
+      else
+       {
+#if defined (HAVE_RESOURCE)
+         return (getmaxvm (mode));
+#else /* !HAVE_RESOURCE */
+         errno = EINVAL;
+         return ((RLIMTYPE)-1);
+#endif /* !HAVE_RESOURCE */
+       }
+
+    case u_MAX_USER_PROCS:
+#if defined (HAVE_RESOURCE) && defined (RLIMIT_NPROC)
+      cmd = RLIMIT_NPROC;
+      goto do_ulimit;
+#else /* !HAVE_RESOURCE || !RLIMIT_NPROC */
+      errno = EINVAL;
+      return ((RLIMTYPE)-1);
+#endif /* !HAVE_RESOURCE || !RLIMIT_NPROC */
+      
+    default:
+      errno = EINVAL;
+      return ((RLIMTYPE)-1);
+    }
+}
+
+#if defined (HAVE_RESOURCE)
+static RLIMTYPE
+getmaxvm (mode)
+     int mode;
+{
+  struct rlimit rl;
+
+#if defined (RLIMIT_VMEM)
+  if (getrlimit (RLIMIT_VMEM, &rl) < 0)
+    return ((RLIMTYPE)-1);
+  else
+    return (((mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max) / 1024L);
+#else /* !RLIMIT_VMEM */
+  RLIMTYPE maxdata, maxstack;
+
+  if (getrlimit (RLIMIT_DATA, &rl) < 0)
+    return ((RLIMTYPE)-1);
+  else
+    maxdata = (mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max;
+
+  if (getrlimit (RLIMIT_STACK, &rl) < 0)
+    return ((RLIMTYPE)-1);
+  else
+    maxstack = (mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max;
+
+  /* Protect against overflow. */
+  return ((maxdata / 1024L) + (maxstack / 1024L));
+#endif /* !RLIMIT_VMEM */
+}
+#endif /* HAVE_RESOURCE */
+
+static RLIMTYPE
+open_files (mode)
+     int mode;
+{
+#if !defined (RLIMIT_NOFILE)
+  return ((RLIMTYPE)getdtablesize ());
+#else
+  struct rlimit rl;
+
+  getrlimit (RLIMIT_NOFILE, &rl);
+  if (mode & LIMIT_SOFT)
+    return (rl.rlim_cur);
+  else
+    return (rl.rlim_max);
+#endif
+}
+
+static RLIMTYPE
+pipesize ()
+{
+#if defined (PIPE_BUF)
+  /* This is defined on Posix systems. */
+  return ((RLIMTYPE) PIPE_BUF);
+#else
+#  if defined (PIPESIZE)
+  /* This is defined by running a program from the Makefile. */
+  return ((RLIMTYPE) PIPESIZE);
+#  else
+  errno = EINVAL;
+  return ((RLIMTYPE)-1);
+#  endif /* PIPESIZE */
+#endif /* PIPE_BUF */
+}
+
+/* ulimit(2) returns information about file size limits in terms of 512-byte
+   blocks.  This is the factor by which to divide to turn it into information
+   in terms of 1024-byte blocks.  Except for hpux 6.x, which returns it in
+   terms of bytes. */
+#if !defined (hpux) || defined (_POSIX_VERSION)
+#  define ULIMIT_DIVISOR 2
+#else
+#  define ULIMIT_DIVISOR 1024
+#endif
+
+#if defined (HAVE_RESOURCE)
+
+typedef struct {
+  int  option_cmd;             /* The ulimit command for this limit. */
+  int  parameter;              /* Parameter to pass to getrlimit (). */
+  int  block_factor;           /* Blocking factor for specific limit. */
+  char *description;           /* Descriptive string to output. */
+} BSD_RESOURCE_LIMITS;
+
+static BSD_RESOURCE_LIMITS limits[] = {
+  { u_CORE_FILE_SIZE, RLIMIT_CORE,  1024, "core file size (blocks)" },
+  { u_DATA_SEG_SIZE,  RLIMIT_DATA,  1024, "data seg size (kbytes)" },
+  { u_FILE_SIZE,      RLIMIT_FSIZE, 1024, "file size (blocks)" },
+#if !defined (USGr4) && defined (RLIMIT_RSS)
+  { u_PHYS_MEM_SIZE,  RLIMIT_RSS,   1024, "max memory size (kbytes)" },
+#endif /* USGr4 && RLIMIT_RSS */
+  { u_STACK_SIZE,     RLIMIT_STACK, 1024, "stack size (kbytes)" },
+#if defined (RLIMIT_CPU)
+  { u_CPU_TIME_LIMIT, RLIMIT_CPU,      1, "cpu time (seconds)" },
+#endif /* RLIMIT_CPU */
+#if defined (RLIMIT_NPROC)
+  { u_MAX_USER_PROCS, RLIMIT_NPROC,    1, "max user processes" },
+#endif /* RLIMIT_NPROC */
+  { 0, 0, 0, (char *)NULL }
+};
+
+static void
+print_bsd_limit (i, mode)
+     int i, mode;
+{
+  struct rlimit rl;
+  RLIMTYPE limit;
+
+  getrlimit (limits[i].parameter, &rl);
+  if (mode & LIMIT_HARD)
+    limit = rl.rlim_max;
+  else
+    limit = rl.rlim_cur;
+  printf ("%-25s", limits[i].description);
+  if (limit == RLIM_INFINITY)
+    printf ("unlimited\n");
+  else
+    print_rlimtype ((limit / limits[i].block_factor), 1);
+}
+
+static void
+print_specific_bsd_limits (cmd, mode)
+     int cmd, mode;
+{
+  register int i;
+
+  for (i = 0; limits[i].option_cmd; i++)
+    if (cmd & limits[i].option_cmd)
+      print_bsd_limit (i, mode);
+}
+#endif /* HAVE_RESOURCE */
+
+/* Print the limits corresponding to a specific set of resources.  This is
+   called when an option string contains more than one character (e.g. -at),
+   because limits may not be specified with that kind of argument. */
+static void
+print_specific_limits (cmd, mode)
+     int cmd, mode;
+{
+  if (mode == 0)
+    mode = LIMIT_SOFT;
+
+#if defined (HAVE_RESOURCE)
+  print_specific_bsd_limits (cmd, mode);
+#else /* !HAVE_RESOURCE */
+  if (cmd & u_FILE_SIZE)
+    {
+      printf ("%-25s", "file size (blocks)");
+      print_rlimtype ((ulimit (1, 0L) / ULIMIT_DIVISOR), 1);
+    }
+#endif /* !HAVE_RESOURCE */
+
+  if (cmd & u_PIPE_SIZE)
+    {
+      printf ("%-25s", "pipe size (512 bytes)");
+      print_rlimtype ((pipesize () / 512), 1);
+    }
+
+  if (cmd & u_NUM_OPEN_FILES)
+    {
+      printf ("%-25s", "open files");
+      print_rlimtype (open_files (mode), 1);
+    }
+
+#if defined (HAVE_RESOURCE)
+  if (cmd & u_MAX_VIRTUAL_MEM)
+    {
+      printf ("%-25s", "virtual memory (kbytes)");
+      print_rlimtype (getmaxvm (mode), 1);
+    }
+#endif /* HAVE_RESOURCE */
+}
+
+static void
+print_all_limits (mode)
+     int mode;
+{
+  if (mode == 0)
+    mode |= LIMIT_SOFT;
+
+  print_specific_limits (u_ALL_LIMITS, mode);
+}
diff --git a/builtins/umask.def b/builtins/umask.def
new file mode 100644 (file)
index 0000000..1d84aa9
--- /dev/null
@@ -0,0 +1,288 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$PRODUCES umask.c
+
+$BUILTIN umask
+$FUNCTION umask_builtin
+$SHORT_DOC umask [-S] [mode]
+The user file-creation mask is set to MODE.  If MODE is omitted, or if
+`-S' is supplied, the current value of the mask is printed.  The `-S'
+option makes the output symbolic; otherwise an octal number is output.
+If MODE begins with a digit, it is interpreted as an octal number,
+otherwise it is a symbolic mode string like that accepted by chmod(1).
+$END
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include "../shell.h"
+#include "../posixstat.h"
+#include "common.h"
+
+/* **************************************************************** */
+/*                                                                  */
+/*                     UMASK Builtin and Helpers                    */
+/*                                                                  */
+/* **************************************************************** */
+
+static void print_symbolic_umask ();
+static int symbolic_umask ();
+
+/* Set or display the mask used by the system when creating files.  Flag
+   of -S means display the umask in a symbolic mode. */
+umask_builtin (list)
+     WORD_LIST *list;
+{
+  int print_symbolically = 0;
+
+  while (list)
+    {
+      if (ISOPTION (list->word->word, 'S'))
+       {
+         list = list->next;
+         print_symbolically++;
+         continue;
+       }
+      else if (ISOPTION (list->word->word, '-'))
+       {
+         list = list->next;
+         break;
+       }
+      else if (*(list->word->word) == '-')
+       {
+         bad_option (list->word->word);
+         builtin_error ("usage: umask [-S] [mode]");
+         return (EX_USAGE);
+       }
+      else
+       break;
+    }
+
+  if (list)
+    {
+      int new_umask;
+
+      if (digit (*list->word->word))
+       {
+         new_umask = read_octal (list->word->word);
+
+         /* Note that other shells just let you set the umask to zero
+            by specifying a number out of range.  This is a problem
+            with those shells.  We don't change the umask if the input
+            is lousy. */
+         if (new_umask == -1)
+           {
+             builtin_error ("`%s' is not an octal number from 000 to 777",
+                               list->word->word);
+             return (EXECUTION_FAILURE);
+           }
+       }
+      else
+       {
+         new_umask = symbolic_umask (list);
+         if (new_umask == -1)
+           return (EXECUTION_FAILURE);
+       }
+      umask (new_umask);
+      if (print_symbolically)
+       print_symbolic_umask (new_umask);
+    }
+  else                         /* Display the UMASK for this user. */
+    {
+      int old_umask;
+
+      old_umask = umask (022);
+      umask (old_umask);
+
+      if (print_symbolically)
+       print_symbolic_umask (old_umask);
+      else
+       printf ("%03o\n", old_umask);
+    }
+  fflush (stdout);
+  return (EXECUTION_SUCCESS);
+}
+
+/* Print the umask in a symbolic form.  In the output, a letter is
+   printed if the corresponding bit is clear in the umask. */
+static void
+print_symbolic_umask (um)
+     int um;
+{
+  char ubits[4], gbits[4], obits[4];           /* u=rwx,g=rwx,o=rwx */
+  int i;
+
+  i = 0;
+  if ((um & S_IRUSR) == 0)
+    ubits[i++] = 'r';
+  if ((um & S_IWUSR) == 0)
+    ubits[i++] = 'w';
+  if ((um & S_IXUSR) == 0)
+    ubits[i++] = 'x';
+  ubits[i] = '\0';
+
+  i = 0;
+  if ((um & S_IRGRP) == 0)
+    gbits[i++] = 'r';
+  if ((um & S_IWGRP) == 0)
+    gbits[i++] = 'w';
+  if ((um & S_IXGRP) == 0)
+    gbits[i++] = 'x';
+  gbits[i] = '\0';
+
+  i = 0;
+  if ((um & S_IROTH) == 0)
+    obits[i++] = 'r';
+  if ((um & S_IWOTH) == 0)
+    obits[i++] = 'w';
+  if ((um & S_IXOTH) == 0)
+    obits[i++] = 'x';
+  obits[i] = '\0';
+
+  printf ("u=%s,g=%s,o=%s\n", ubits, gbits, obits);
+}
+
+/* Set the umask from a symbolic mode string similar to that accepted
+   by chmod.  If the -S argument is given, then print the umask in a
+   symbolic form. */
+static int
+symbolic_umask (list)
+     WORD_LIST *list;
+{
+  int um, umc, c;
+  int who, op, perm, mask;
+  char *s;
+
+  /* Get the initial umask.  Don't change it yet. */
+  um = umask (022);
+  umask (um);
+
+  /* All work below is done with the complement of the umask -- its
+     more intuitive and easier to deal with.  It is complemented
+     again before being returned. */
+  umc = ~um;
+
+  s = list->word->word;
+
+  for (;;)
+    {
+      who = op = perm = mask = 0;
+
+      /* Parse the `who' portion of the symbolic mode clause. */
+      while (member (*s, "agou"))
+        {
+         switch (c = *s++)
+           {
+             case 'u':
+               who |= S_IRWXU;
+               continue;
+             case 'g':
+               who |= S_IRWXG;
+               continue;
+             case 'o':
+               who |= S_IRWXO;
+               continue;
+             case 'a':
+               who |= S_IRWXU | S_IRWXG | S_IRWXO;
+               continue;
+             default:
+               break;
+           }
+       }
+
+      /* The operation is now sitting in *s. */
+      op = *s++;
+      switch (op)
+       {
+         case '+':
+         case '-':
+         case '=':
+           break;
+         default:
+           builtin_error ("bad symbolic mode operator: %c", op);
+           return (-1);
+       }
+
+      /* Parse out the `perm' section of the symbolic mode clause. */
+      while (member (*s, "rwx"))
+       {
+         c = *s++;
+
+         switch (c)
+           {
+             case 'r':
+               perm |= S_IRUGO;
+               break;
+
+             case 'w':
+               perm |= S_IWUGO;
+               break;
+
+             case 'x':
+               perm |= S_IXUGO;
+               break;
+           }
+       }
+
+      /* Now perform the operation or return an error for a
+        bad permission string. */
+      if (!*s || *s == ',')
+       {
+         if (who)
+           perm &= who;
+
+         switch (op)
+           {
+             case '+':
+               umc |= perm;
+               break;
+
+             case '-':
+               umc &= ~perm;
+               break;
+
+             case '=':
+               umc &= ~who;
+               umc |= perm;
+               break;
+
+             default:
+               builtin_error ("bad operation character: %c", op);
+               return (-1);
+           }
+
+         if (!*s)
+           {
+             um = ~umc & 0777;
+             break;
+           }
+         else
+           s++;        /* skip past ',' */
+       }
+      else
+       {
+         builtin_error ("bad character in symbolic mode: %c", *s);
+         return (-1);
+       }
+    }
+  return (um);
+}
diff --git a/builtins/wait.def b/builtins/wait.def
new file mode 100644 (file)
index 0000000..f613179
--- /dev/null
@@ -0,0 +1,132 @@
+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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+$BUILTIN wait
+$FUNCTION wait_builtin
+$DEPENDS_ON JOB_CONTROL
+$PRODUCES wait.c
+$SHORT_DOC wait [n]
+Wait for the specified process and report its termination status.  If
+N is not given, all currently active child processes are waited for,
+and the return code is zero.  N may be a process ID or a job
+specification; if a job spec is given, all processes in the job's
+pipeline are waited for.
+$END
+
+$BUILTIN wait
+$FUNCTION wait_builtin
+$DEPENDS_ON !JOB_CONTROL
+$SHORT_DOC wait [n]
+Wait for the specified process and report its termination status.  If
+N is not given, all currently active child processes are waited for,
+and the return code is zero.  N is a process ID; if it is not given,
+all child processes of the shell are waited for.
+$END
+
+#include <sys/types.h>
+#include <signal.h>
+#include "../shell.h"
+#include "../jobs.h"
+
+extern int interrupt_immediately;
+
+/* Wait for the pid in LIST to stop or die.  If no arguments are given, then
+   wait for all of the active background processes of the shell and return
+   0.  If a list of pids or job specs are given, return the exit status of
+   the last one waited for. */
+wait_builtin (list)
+     WORD_LIST *list;
+{
+  int status = EXECUTION_SUCCESS;
+
+  begin_unwind_frame ("wait_builtin");
+  unwind_protect_int (interrupt_immediately);
+  interrupt_immediately++;
+
+  /* We support jobs or pids.
+     wait <pid-or-job> [pid-or-job ...] */
+
+  /* But wait without any arguments means to wait for all of the shell's
+     currently active background processes. */
+  if (!list)
+    {
+      wait_for_background_pids ();
+      status = EXECUTION_SUCCESS;
+      goto return_status;
+    }
+
+  while (list)
+    {
+      pid_t pid;
+      char *w;
+
+      w = list->word->word;
+      if (digit (*w))
+       {
+         if (all_digits (w + 1))
+           {
+             pid = (pid_t)atoi (w);
+             status = wait_for_single_pid (pid);
+           }
+         else
+           {
+             builtin_error ("`%s' is not a pid or legal job spec", w);
+             status = EXECUTION_FAILURE;
+             goto return_status;
+           }
+       }
+#if defined (JOB_CONTROL)
+      else if (job_control && *w)
+       /* Must be a job spec.  Check it out. */
+       {
+         int job;
+         sigset_t set, oset;
+
+         BLOCK_CHILD (set, oset);
+         job = get_job_spec (list);
+
+         if (job < 0 || job >= job_slots || !jobs[job])
+           {
+             if (job != DUP_JOB)
+               builtin_error ("No such job %s", list->word->word);
+             UNBLOCK_CHILD (oset);
+             status = 127;     /* As per Posix.2, section 4.70.2 */
+             list = list->next;
+             continue;
+           }
+
+         /* Job spec used.  Wait for the last pid in the pipeline. */
+         UNBLOCK_CHILD (oset);
+         status = wait_for_job (job);
+       }
+#endif /* JOB_CONTROL */
+      else
+       {
+         builtin_error ("`%s' is not a pid or legal job spec", w);
+         status = EXECUTION_FAILURE;
+       }
+      list = list->next;
+    }
+ return_status:
+  run_unwind_frame ("wait_builtin");
+  return (status);
+}
diff --git a/command.h b/command.h
new file mode 100644 (file)
index 0000000..cffc15f
--- /dev/null
+++ b/command.h
@@ -0,0 +1,215 @@
+/* command.h -- The structures used internally to represent commands, and
+   the extern declarations of the functions used to create them. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_COMMAND_H)
+#define _COMMAND_H
+
+#include "stdc.h"
+
+/* Instructions describing what kind of thing to do for a redirection. */
+enum r_instruction {
+  r_output_direction, r_input_direction, r_inputa_direction,
+  r_appending_to, r_reading_until, r_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
+};
+
+/* 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 };
+
+/* A structure which represents a word. */
+typedef struct word_desc {
+  char *word;          /* Zero terminated string. */
+  int dollar_present;  /* Non-zero means dollar sign present. */
+  int quoted;          /* Non-zero means single, double, or back quote
+                          or backslash is present. */
+  int assignment;      /* Non-zero means that this word contains an
+                          assignment. */
+} WORD_DESC;
+
+/* A linked list of words. */
+typedef struct word_list {
+  struct word_list *next;
+  WORD_DESC *word;
+} WORD_LIST;
+
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Shell Command Structs                       */
+/*                                                                 */
+/* **************************************************************** */
+
+/* What a redirection descriptor looks like.  If FLAGS is IS_DESCRIPTOR,
+   then we use REDIRECTEE.DEST, else we use the file specified. */
+
+typedef union {
+  long dest;                   /* Place to redirect REDIRECTOR to, or ... */
+  WORD_DESC *filename;         /* filename to redirect to. */
+} REDIRECTEE;
+
+typedef struct redirect {
+  struct redirect *next;       /* Next element, or NULL. */
+  int redirector;              /* Descriptor to be redirected. */
+  int flags;                   /* Flag value for `open'. */
+  enum r_instruction  instruction; /* What to do with the information. */
+  REDIRECTEE redirectee;       /* File descriptor or filename */
+  char *here_doc_eof;          /* The word that appeared in <<foo. */
+} REDIRECT;
+
+/* An element used in parsing.  A single word or a single redirection.
+   This is an ephemeral construct. */
+typedef struct element {
+  WORD_DESC *word;
+  REDIRECT *redirect;
+} ELEMENT;
+
+/* Possible values for command->flags. */
+#define CMD_WANT_SUBSHELL  0x01        /* User wants a subshell: ( command ) */
+#define CMD_FORCE_SUBSHELL 0x02        /* Shell needs to force a subshell. */
+#define CMD_INVERT_RETURN  0x04        /* Invert the exit value. */
+#define CMD_IGNORE_RETURN  0x08        /* Ignore the exit value.  For set -e. */
+#define CMD_NO_FUNCTIONS   0x10 /* Ignore functions during command lookup. */
+#define CMD_INHIBIT_EXPANSION 0x20 /* Do not expand the command words. */
+#define CMD_NO_FORK       0x40 /* Don't fork; just call execve */
+
+/* What a command looks like. */
+typedef struct command {
+  enum command_type type;      /* FOR CASE WHILE IF CONNECTION or SIMPLE. */
+  int flags;                   /* Flags controlling execution environment. */
+  int line;                    /* line number the command starts on */
+  REDIRECT *redirects;         /* Special redirects for FOR CASE, etc. */
+  union {
+    struct for_com *For;
+    struct case_com *Case;
+    struct while_com *While;
+    struct if_com *If;
+    struct connection *Connection;
+    struct simple_com *Simple;
+    struct function_def *Function_def;
+    struct group_com *Group;
+#if defined (SELECT_COMMAND)
+    struct select_com *Select;
+#endif
+  } value;
+} COMMAND;
+
+/* Structure used to represent the CONNECTION type. */
+typedef struct connection {
+  int ignore;                  /* Unused; simplifies make_command (). */
+  COMMAND *first;              /* Pointer to the first command. */
+  COMMAND *second;             /* Pointer to the second command. */
+  int connector;               /* What separates this command from others. */
+} CONNECTION;
+
+/* Structures used to represent the CASE command. */
+
+/* Pattern/action structure for CASE_COM. */
+typedef struct pattern_list {
+  struct pattern_list *next;   /* Clause to try in case this one failed. */
+  WORD_LIST *patterns;         /* Linked list of patterns to test. */
+  COMMAND *action;             /* Thing to execute if a pattern matches. */
+} PATTERN_LIST;
+
+/* The CASE command. */
+typedef struct case_com {
+  int flags;                   /* See description of CMD flags. */
+  WORD_DESC *word;             /* The thing to test. */
+  PATTERN_LIST *clauses;       /* The clauses to test against, or NULL. */
+} CASE_COM;
+
+/* FOR command. */
+typedef struct for_com {
+  int flags;           /* See description of CMD flags. */
+  WORD_DESC *name;     /* The variable name to get mapped over. */
+  WORD_LIST *map_list; /* The things to map over.  This is never NULL. */
+  COMMAND *action;     /* The action to execute.
+                          During execution, NAME is bound to successive
+                          members of MAP_LIST. */
+} FOR_COM;
+
+#if defined (SELECT_COMMAND)
+/* KSH SELECT command. */
+typedef struct select_com {
+  int flags;           /* See description of CMD flags. */
+  WORD_DESC *name;     /* The variable name to get mapped over. */
+  WORD_LIST *map_list; /* The things to map over.  This is never NULL. */
+  COMMAND *action;     /* The action to execute.
+                          During execution, NAME is bound to the member of
+                          MAP_LIST chosen by the user. */
+} SELECT_COM;
+#endif /* SELECT_COMMAND */
+
+/* IF command. */
+typedef struct if_com {
+  int flags;                   /* See description of CMD flags. */
+  COMMAND *test;               /* Thing to test. */
+  COMMAND *true_case;          /* What to do if the test returned non-zero. */
+  COMMAND *false_case;         /* What to do if the test returned zero. */
+} IF_COM;
+
+/* WHILE command. */
+typedef struct while_com {
+  int flags;                   /* See description of CMD flags. */
+  COMMAND *test;               /* Thing to test. */
+  COMMAND *action;             /* Thing to do while test is non-zero. */
+} WHILE_COM;
+
+/* The "simple" command.  Just a collection of words and redirects. */
+typedef struct simple_com {
+  int flags;                   /* See description of CMD flags. */
+  WORD_LIST *words;            /* The program name, the arguments,
+                                  variable assignments, etc. */
+  REDIRECT *redirects;         /* Redirections to perform. */
+  int line;                    /* line number the command starts on */
+} SIMPLE_COM;
+
+/* The "function_def" command.  This isn't really a command, but it is
+   represented as such for now.  If the function def appears within 
+   `(' `)' the parser tries to set the SUBSHELL bit of the command.  That
+   means that FUNCTION_DEF has to be run through the executor.  Maybe this
+   command should be defined in a subshell.  Who knows or cares. */
+typedef struct function_def {
+  int ignore;                  /* See description of CMD flags. */
+  WORD_DESC *name;             /* The name of the function. */
+  COMMAND *command;            /* The parsed execution tree. */
+} FUNCTION_DEF;
+
+/* A command that is `grouped' allows pipes to take effect over
+   the entire command structure. */
+typedef struct group_com {
+  int ignore;                  /* See description of CMD flags. */
+  COMMAND *command;
+} GROUP_COM;
+
+extern COMMAND *global_command;
+
+/* Forward declarations of functions declared in copy_cmd.c. */
+
+extern WORD_DESC *copy_word __P((WORD_DESC *));
+extern WORD_LIST *copy_word_list __P((WORD_LIST *));
+extern REDIRECT *copy_redirect __P((REDIRECT *));
+extern REDIRECT *copy_redirects __P((REDIRECT *));
+extern COMMAND *copy_command __P((COMMAND *));
+
+#endif /* _COMMAND_H */
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..8fd2ba3
--- /dev/null
+++ b/config.h
@@ -0,0 +1,186 @@
+/* config.h -- Configuration file for bash. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_CONFIG_H_)
+#define _CONFIG_H_
+
+#if !defined (BUILDING_MAKEFILE)
+#include "memalloc.h"
+#endif
+
+#if defined (HAVE_UNISTD_H) && !defined (BUILDING_MAKEFILE)
+#  ifdef CRAY
+#    define word __word
+#  endif
+#include <unistd.h>
+#  ifdef CRAY
+#    undef word
+#  endif
+#endif
+
+/* Define JOB_CONTROL if your operating system supports
+   BSD-like job control. */
+#define JOB_CONTROL
+
+/* Note that vanilla System V machines don't support BSD job control,
+   although some do support Posix job control. */
+#if defined (USG) || defined (MINIX) || defined (Minix)
+#  if !defined (_POSIX_JOB_CONTROL)
+#    undef JOB_CONTROL
+#  endif /* !_POSIX_JOB_CONTROL */
+#endif /* USG || Minix || MINIX */
+
+/* Define ALIAS if you want the alias features. */
+#define ALIAS
+
+/* Define PUSHD_AND_POPD if you want those commands to be compiled in.
+   (Also the `dirs' commands.) */
+#define PUSHD_AND_POPD
+
+/* Define BRACE_EXPANSION if you want curly brace expansion a la Csh:
+   foo{a,b} -> fooa foob.  Even if this is compiled in (the default) you
+   can turn it off at shell startup with `-nobraceexpansion', or during
+   shell execution with `set +o braceexpand'. */
+#define BRACE_EXPANSION
+
+/* Define READLINE to get the nifty/glitzy editing features.
+   This is on by default.  You can turn it off interactively
+   with the -nolineediting flag. */
+#define READLINE
+
+/* Define BANG_HISTORY if you want to have Csh style "!" history expansion.
+   This is unrelated to READLINE. */
+#define BANG_HISTORY
+
+/* Define HISTORY if you want to have access to previously typed commands.
+
+   If both HISTORY and READLINE are defined, you can get at the commands
+   with line editing commands, and you can directly manipulate the history
+   from the command line.
+
+   If only HISTORY is defined, the `fc' and `history' builtins are
+   available. */
+#define HISTORY
+
+#if defined (BANG_HISTORY) && !defined (HISTORY)
+   /* BANG_HISTORY requires HISTORY. */
+#  define HISTORY
+#endif /* BANG_HISTORY && !HISTORY */
+
+#if defined (READLINE) && !defined (HISTORY)
+#  define HISTORY
+#endif
+
+/* The default value of the PATH variable. */
+#define DEFAULT_PATH_VALUE \
+  "/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:."
+
+/* The value for PATH when invoking `command -p'.  This is only used when
+   the Posix.2 confstr () function, or CS_PATH define are not present. */
+#define STANDARD_UTILS_PATH \
+  "/bin:/usr/bin:/usr/ucb:/usr/sbin:/sbin:/etc:/usr/etc:/usr/lib"
+
+/* Put system-specific default mail directories here. */
+#if defined (__bsdi__) || defined (__FreeBSD__) || defined (__NetBSD__)
+#  define DEFAULT_MAIL_PATH "/var/mail/"
+#endif
+
+#if !defined (DEFAULT_MAIL_PATH)
+#if defined (USG)
+#  define DEFAULT_MAIL_PATH "/usr/mail/"
+#else
+#  define DEFAULT_MAIL_PATH "/usr/spool/mail/"
+#endif
+#endif
+
+/* Define V9_ECHO if you want to give the echo builtin backslash-escape
+   interpretation using the -e option, in the style of the Bell Labs 9th
+   Edition version of echo. */
+#define V9_ECHO
+
+/* Define DEFAULT_ECHO_TO_USG if you want the echo builtin to interpret
+   the backslash-escape characters by default, like the System V echo.
+   This requires that V9_ECHO be defined. */
+/* #define DEFAULT_ECHO_TO_USG */
+#if !defined (V9_ECHO)
+#  undef DEFAULT_ECHO_TO_USG
+#endif
+
+/* Define CONTINUE_AFTER_KILL_ERROR if you want the kill command to
+   continue processing arguments after one of them fails. */
+#define CONTINUE_AFTER_KILL_ERROR
+
+/* Define BREAK_COMPLAINS if you want the non-standard, but useful
+   error messages about `break' and `continue' out of context. */
+#define BREAK_COMPLAINS
+
+/* Define GETOPTS_BUILTIN if you want the Posix.2 `getopts' shell builtin
+   compiled into the shell. */
+#define GETOPTS_BUILTIN
+
+/* When ALLOW_RIGID_POSIX_COMPLIANCE is defined, you can turn on strictly
+   Posix compliant behaviour by setting the environment variable
+   POSIXLY_CORRECT. */
+#define ALLOW_RIGID_POSIX_COMPLIANCE
+
+/* Define RESTRICTED_SHELL if you want the generated shell to have the
+   ability to be a restricted one.  The shell thus generated can become
+   restricted by being run with the name "rbash", or by setting the -r
+   flag. */
+/* #define RESTRICTED_SHELL */
+
+/* Define DISABLED_BUILTINS if you want "builtin foo" to always run the
+   shell builtin "foo", even if it has been disabled with "enable -n foo". */
+/* #define DISABLED_BUILTINS */
+
+/* Define PROCESS_SUBSTITUTION if you want the K*rn shell-like process
+   substitution features "<(file)". */
+/* Right now, you cannot do this on machines without fully operational
+   FIFO support.  This currently include NeXT and Alliant. */
+#if !defined (MKFIFO_MISSING) || defined (HAVE_DEV_FD)
+#  define PROCESS_SUBSTITUTION
+#endif /* !MKFIFO_MISSING */
+
+/* Define PROMPT_STRING_DECODE if you want the backslash-escaped special
+   characters in PS1 and PS2 expanded.  Variable expansion will still be
+   performed. */
+#define PROMPT_STRING_DECODE
+
+/* Define BUFFERED_INPUT if you want the shell to do its own input
+   buffering. */
+#define BUFFERED_INPUT
+
+/* Define INTERACTIVE_COMMENTS if you want # comments to work by default
+   when the shell is interactive, as Posix.2a specifies. */
+#define INTERACTIVE_COMMENTS
+
+/* Define ONESHOT if you want sh -c 'command' to avoid forking to execute
+   `command' whenever possible. */
+#define ONESHOT
+
+/* Default primary and secondary prompt strings. */
+#define PPROMPT "bash\\$ "
+#define SPROMPT "> "
+
+/* Define SELECT_COMMAND if you want the Korn-shell style `select' command:
+       select word in word_list; do command_list; done */
+#define SELECT_COMMAND
+
+#endif /* !_CONFIG_H_ */
diff --git a/config.h.mini b/config.h.mini
new file mode 100644 (file)
index 0000000..3acc84e
--- /dev/null
@@ -0,0 +1,194 @@
+/* config.h -- Configuration file for bash. */
+
+/* This is a `minimal' configuration file.  It will create a shell without:
+       job control
+       aliases
+       pushd and popd
+       readline
+       history
+       restricted shell mode
+       `disabled' builtins (builtin xxx finds xxx even after enable -n xxx)
+       process substitution
+       prompt string decoding (though variable expansion is still done)
+       the `select' command */
+       
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_CONFIG_H_)
+#define _CONFIG_H_
+
+#include "memalloc.h"
+
+#if defined (HPUX) || defined (UNIXPC) || defined (Xenix)
+#  if !defined (USG)
+#    define USG
+#  endif
+#endif
+
+#if defined (HAVE_UNISTD_H) && !defined (BUILDING_MAKEFILE)
+#include <unistd.h>
+#endif
+
+/* Define JOB_CONTROL if your operating system supports
+   BSD-like job control. */
+/* #define JOB_CONTROL */
+
+/* Note that vanilla System V machines don't support BSD job control,
+   although some do support Posix job control. */
+#if defined (USG) && !defined (_POSIX_JOB_CONTROL)
+#  undef JOB_CONTROL
+#endif /* USG && !_POSIX_JOB_CONTROL */
+
+/* Define ALIAS if you want the alias features. */
+/* #define ALIAS */
+
+/* Define PUSHD_AND_POPD if you want those commands to be compiled in.
+   (Also the `dirs' commands.) */
+/* #define PUSHD_AND_POPD */
+
+/* Define BRACE_EXPANSION if you want curly brace expansion a la Csh:
+   foo{a,b} -> fooa foob.  Even if this is compiled in (the default) you
+   can turn it off at shell startup with `-nobraceexpansion', or during
+   shell execution with `set +o braceexpand'. */
+/* #define BRACE_EXPANSION */
+
+/* Define READLINE to get the nifty/glitzy editing features.
+   This is on by default.  You can turn it off interactively
+   with the -nolineediting flag. */
+/* #define READLINE */
+
+/* Define BANG_HISTORY if you want to have Csh style "!" history expansion.
+   This is unrelated to READLINE. */
+/* #define BANG_HISTORY */
+
+/* Define HISTORY if you want to have access to previously typed commands.
+
+   If both HISTORY and READLINE are defined, you can get at the commands
+   with line editing commands, and you can directly manipulate the history
+   from the command line.
+
+   If only HISTORY is defined, the `fc' and `history' builtins are
+   available. */
+/* #define HISTORY */
+
+#if defined (BANG_HISTORY) && !defined (HISTORY)
+   /* BANG_HISTORY requires HISTORY. */
+#  define HISTORY
+#endif /* BANG_HISTORY && !HISTORY */
+
+#if defined (READLINE) && !defined (HISTORY)
+#  define HISTORY
+#endif
+
+/* The default value of the PATH variable. */
+#define DEFAULT_PATH_VALUE \
+  "/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:."
+
+/* The value for PATH when invoking `command -p'.  This is only used when
+   the Posix.2 confstr () function, or CS_PATH define are not present. */
+#define STANDARD_UTILS_PATH \
+  "/bin:/usr/bin:/usr/ucb:/usr/sbin:/sbin:/etc:/usr/etc:/usr/lib"
+
+/* Put system-specific default mail directories here. */
+#if defined (__bsdi__) || defined (__FreeBSD__) || defined (__NetBSD__)
+#  define DEFAULT_MAIL_PATH "/var/mail/"
+#endif
+
+#if !defined (DEFAULT_MAIL_PATH)
+#if defined (USG)
+#  define DEFAULT_MAIL_PATH "/usr/mail/"
+#else
+#  define DEFAULT_MAIL_PATH "/usr/spool/mail/"
+#endif
+#endif
+
+/* Define V9_ECHO if you want to give the echo builtin backslash-escape
+   interpretation using the -e option, in the style of the Bell Labs 9th
+   Edition version of echo. */
+#define V9_ECHO
+
+/* Define DEFAULT_ECHO_TO_USG if you want the echo builtin to interpret
+   the backslash-escape characters by default, like the System V echo.
+   This requires that V9_ECHO be defined. */
+/* #define DEFAULT_ECHO_TO_USG */
+#if !defined (V9_ECHO)
+#  undef DEFAULT_ECHO_TO_USG
+#endif
+
+/* Define CONTINUE_AFTER_KILL_ERROR if you want the kill command to
+   continue processing arguments after one of them fails. */
+#define CONTINUE_AFTER_KILL_ERROR
+
+/* Define BREAK_COMPLAINS if you want the non-standard, but useful
+   error messages about `break' and `continue' out of context. */
+#define BREAK_COMPLAINS
+
+/* Define GETOPTS_BUILTIN if you want the Posix.2 `getopts' shell builtin
+   compiled into the shell. */
+#define GETOPTS_BUILTIN
+
+/* When ALLOW_RIGID_POSIX_COMPLIANCE is defined, you can turn on strictly
+   Posix compliant behaviour by setting the environment variable
+   POSIXLY_CORRECT. */
+#define ALLOW_RIGID_POSIX_COMPLIANCE
+
+/* Define RESTRICTED_SHELL if you want the generated shell to have the
+   ability to be a restricted one.  The shell thus generated can become
+   restricted by being run with the name "rbash", or by setting the -r
+   flag. */
+/* #define RESTRICTED_SHELL */
+
+/* Define DISABLED_BUILTINS if you want "builtin foo" to always run the
+   shell builtin "foo", even if it has been disabled with "enable -n foo". */
+/* #define DISABLED_BUILTINS */
+
+/* Define PROCESS_SUBSTITUTION if you want the K*rn shell-like process
+   substitution features "<(file)". */
+/* Right now, you cannot do this on machines without fully operational
+   FIFO support.  This currently include NeXT and Alliant. */
+#if !defined (MKFIFO_MISSING)
+#  define PROCESS_SUBSTITUTION
+#endif /* !MKFIFO_MISSING */
+
+/* Define PROMPT_STRING_DECODE if you want the backslash-escaped special
+   characters in PS1 and PS2 expanded.  Variable expansion will still be
+   performed. */
+/* #define PROMPT_STRING_DECODE */
+
+/* Define BUFFERED_INPUT if you want the shell to do its own input
+   buffering. */
+#define BUFFERED_INPUT
+
+/* Define INTERACTIVE_COMMENTS if you want # comments to work by default
+   when the shell is interactive, as Posix.2a specifies. */
+#define INTERACTIVE_COMMENTS
+
+/* Define ONESHOT if you want sh -c 'command' to avoid forking to execute
+   `command' whenever possible. */
+#define ONESHOT
+
+/* Default primary and secondary prompt strings. */
+#define PPROMPT "bash\\$ "
+#define SPROMPT "> "
+
+/* Define SELECT_COMMAND if you want the Korn-shell style `select' command:
+       select word in word_list; do command_list; done */
+/* #define SELECT_COMMAND */
+
+#endif /* !_CONFIG_H_ */
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..53e10b6
--- /dev/null
+++ b/configure
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# This shell script does nothing since Bash doesn't require
+# configuration to be forced on it; it auto-configures.  You can
+# change the location of the source directory with +srcdir.
+#
+echo "Bash is configured to auto configure."
+exit 0
diff --git a/copy_cmd.c b/copy_cmd.c
new file mode 100644 (file)
index 0000000..991bbc9
--- /dev/null
@@ -0,0 +1,305 @@
+/* copy_command.c -- copy a COMMAND structure.  This is needed
+   primarily for making function definitions, but I'm not sure
+   that anyone else will need it.  */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "shell.h"
+
+WORD_DESC *
+copy_word (word)
+     WORD_DESC *word;
+{
+  WORD_DESC *new_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
+  FASTCOPY ((char *)word, (char *)new_word, sizeof (WORD_DESC));
+  new_word->word = savestring (word->word);
+  return (new_word);
+}
+
+/* Copy the chain of words in LIST.  Return a pointer to 
+   the new chain. */
+WORD_LIST *
+copy_word_list (list)
+     WORD_LIST *list;
+{
+  WORD_LIST *new_list = NULL;
+
+  while (list)
+    {
+      WORD_LIST *temp = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
+      temp->next = new_list;
+      new_list = temp;
+      new_list->word = copy_word (list->word);
+      list = list->next;
+    }
+  return (REVERSE_LIST (new_list, WORD_LIST *));
+}
+
+static PATTERN_LIST *
+copy_case_clause (clause)
+     PATTERN_LIST *clause;
+{
+  PATTERN_LIST *new_clause = (PATTERN_LIST *)xmalloc (sizeof (PATTERN_LIST));
+  new_clause->patterns = copy_word_list (clause->patterns);
+  new_clause->action = copy_command (clause->action);
+  return (new_clause);
+}
+
+static PATTERN_LIST *
+copy_case_clauses (clauses)
+     PATTERN_LIST *clauses;
+{
+  PATTERN_LIST *new_list = (PATTERN_LIST *)NULL;
+
+  while (clauses)
+    {
+      PATTERN_LIST *new_clause = copy_case_clause (clauses);
+      new_clause->next = new_list;
+      new_list = new_clause;
+      clauses = clauses->next;
+    }
+  return (REVERSE_LIST (new_list, PATTERN_LIST *));
+}
+
+/* Copy a single redirect. */
+REDIRECT *
+copy_redirect (redirect)
+     REDIRECT *redirect;
+{
+  REDIRECT *new_redirect = (REDIRECT *)xmalloc (sizeof (REDIRECT));
+  FASTCOPY ((char *)redirect, (char *)new_redirect, (sizeof (REDIRECT)));
+  switch (redirect->instruction)
+    {
+    case r_reading_until:
+    case r_deblank_reading_until:
+      new_redirect->here_doc_eof = savestring (redirect->here_doc_eof);
+      /* There is NO BREAK HERE ON PURPOSE!!!! */
+    case r_appending_to:
+    case r_output_direction:
+    case r_input_direction:
+    case r_inputa_direction:
+    case r_err_and_out:
+    case r_input_output:
+    case r_output_force:
+    case r_duplicating_input_word:
+    case r_duplicating_output_word:
+      new_redirect->redirectee.filename =
+       copy_word (redirect->redirectee.filename);
+      break;
+    }
+  return (new_redirect);
+}
+  
+REDIRECT *
+copy_redirects (list)
+     REDIRECT *list;
+{
+  REDIRECT *new_list = NULL;
+
+  while (list)
+    {
+      REDIRECT *temp = copy_redirect (list);
+      temp->next = new_list;
+      new_list = temp;
+      list = list->next;
+    }
+  return (REVERSE_LIST (new_list, REDIRECT *));
+}
+  
+static FOR_COM *
+copy_for_command (com)
+     FOR_COM *com;
+{
+  FOR_COM *new_for = (FOR_COM *)xmalloc (sizeof (FOR_COM));
+  new_for->flags = com->flags;
+  new_for->name = copy_word (com->name);
+  new_for->map_list = copy_word_list (com->map_list);
+  new_for->action = copy_command (com->action);
+  return (new_for);
+}
+
+#if defined (SELECT_COMMAND)
+static SELECT_COM *
+copy_select_command (com)
+     SELECT_COM *com;
+{
+  SELECT_COM *new_select = (SELECT_COM *)xmalloc (sizeof (SELECT_COM));
+  new_select->flags = com->flags;
+  new_select->name = copy_word (com->name);
+  new_select->map_list = copy_word_list (com->map_list);
+  new_select->action = copy_command (com->action);
+  return (new_select);
+}
+#endif /* SELECT_COMMAND */
+
+static GROUP_COM *
+copy_group_command (com)
+     GROUP_COM *com;
+{
+  GROUP_COM *new_group = (GROUP_COM *)xmalloc (sizeof (GROUP_COM));
+
+  new_group->command = copy_command (com->command);
+  return (new_group);
+}
+
+static CASE_COM *
+copy_case_command (com)
+     CASE_COM *com;
+{
+  CASE_COM *new_case = (CASE_COM *)xmalloc (sizeof (CASE_COM));
+
+  new_case->flags = com->flags;
+  new_case->word = copy_word (com->word);
+  new_case->clauses = copy_case_clauses (com->clauses);
+  return (new_case);
+}
+
+static WHILE_COM *
+copy_while_command (com)
+     WHILE_COM *com;
+{
+  WHILE_COM *new_while = (WHILE_COM *)xmalloc (sizeof (WHILE_COM));
+
+  new_while->flags = com->flags;
+  new_while->test = copy_command (com->test);
+  new_while->action = copy_command (com->action);
+  return (new_while);
+}
+
+static IF_COM *
+copy_if_command (com)
+     IF_COM *com;
+{
+  IF_COM *new_if = (IF_COM *)xmalloc (sizeof (IF_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);
+  return (new_if);
+}
+
+static SIMPLE_COM *
+copy_simple_command (com)
+     SIMPLE_COM *com;
+{
+  SIMPLE_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->line = com->line;
+  return (new_simple);
+}
+
+static FUNCTION_DEF *
+copy_function_def (com)
+     FUNCTION_DEF *com;
+{
+  FUNCTION_DEF *new_def = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF));
+
+  new_def->name = copy_word (com->name);
+  new_def->command = copy_command (com->command);
+  return (new_def);
+}
+
+/* Copy the command structure in COMMAND.  Return a pointer to the
+   copy.  Don't you forget to dispose_command () on this pointer
+   later! */
+COMMAND *
+copy_command (command)
+     COMMAND *command;
+{
+  COMMAND *new_command = (COMMAND *)NULL;
+
+  if (command)
+    {
+      new_command = (COMMAND *)xmalloc (sizeof (COMMAND));
+      FASTCOPY ((char *)command, (char *)new_command, sizeof (COMMAND));
+      new_command->flags = command->flags;
+      new_command->line = command->line;
+
+      if (command->redirects)
+       new_command->redirects = copy_redirects (command->redirects);
+
+      switch (command->type)
+       {
+       case cm_for:
+         new_command->value.For = copy_for_command (command->value.For);
+         break;
+
+#if defined (SELECT_COMMAND)
+       case cm_select:
+         new_command->value.Select = copy_select_command (command->value.Select);
+         break;
+#endif
+
+       case cm_group:
+         new_command->value.Group = copy_group_command (command->value.Group);
+         break;
+
+       case cm_case:
+         new_command->value.Case = copy_case_command (command->value.Case);
+         break;
+      
+       case cm_until:
+       case cm_while:
+         new_command->value.While = copy_while_command (command->value.While);
+         break;
+      
+       case cm_if:
+         new_command->value.If = copy_if_command (command->value.If);
+         break;
+      
+       case cm_simple:
+         new_command->value.Simple = copy_simple_command (command->value.Simple);
+         break;
+      
+       case cm_connection:
+         {
+           CONNECTION *new_connection;
+
+           new_connection = (CONNECTION *)xmalloc (sizeof (CONNECTION));
+           new_connection->connector = command->value.Connection->connector;
+           new_connection->first =
+             copy_command (command->value.Connection->first);
+           new_connection->second =
+             copy_command (command->value.Connection->second);
+           new_command->value.Connection = new_connection;
+           break;
+         }
+      
+         /* Pathological case.  I'm not even sure that you can have a
+            function definition as part of a function definition. */
+       case cm_function_def:
+         new_command->value.Function_def =
+           copy_function_def (command->value.Function_def);
+         break;
+       }
+    }
+  return (new_command);
+}
diff --git a/cpp-Makefile b/cpp-Makefile
new file mode 100644 (file)
index 0000000..9e1e2e8
--- /dev/null
@@ -0,0 +1,1553 @@
+/* This -*- C -*- file (cpp-Makefile) is run through the C preprocessor
+   to produce bash-Makefile which is machine specific.
+
+   If you have Gcc and/or Bison, you might wish to mention that right
+   below here.
+
+   Since this is to become a Makefile, blank lines which appear outside
+   of comments may not contain a TAB character.
+
+   Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 1, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/**/# This Makefile is automagically made from cpp-Makefile.  You should
+/**/# not be editing this file; edit cpp-Makefile, machines.h, or
+/**/# support/mksysdefs instead.  Then, assuming the edits were required
+/**/# to compile Bash on your system, mail the changes you had to make to
+/**/# bash-maintainers@prep.ai.mit.edu.  We will do our best to incorporate
+/**/# them into the next release.
+
+/**/# Make sure the first target in the makefile is the right one
+all: .made
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Which compiler are you using?               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Define HAVE_GCC if you have the GNU C compiler. */
+/* #define HAVE_GCC */
+
+#if defined (__GNUC__) && !defined (HAVE_GCC) && !defined (GCC_STANDARD)
+#  define HAVE_GCC
+#endif
+
+/* Undefine HAVE_FIXED_INCLUDES if you are not using GCC with the fixed
+   header files. */
+#if defined (HAVE_GCC) && !defined (HAVE_FIXED_INCLUDES)
+#  define HAVE_FIXED_INCLUDES
+#endif /* HAVE_GCC && !HAVE_FIXED_INCLUDES */
+
+/* Define HAVE_BISON if you have the GNU replacement for Yacc. */
+/**/# We would like you to use Bison instead of Yacc since some
+/**/# versions of Yacc cannot handle reentrant parsing.  Unfortunately,
+/**/# this includes the Yacc currently being shipped with SunOS4.x.
+/**/# If you do use Yacc, please make sure that any bugs in parsing
+/**/# are not really manifestations of Yacc bugs before you report
+/**/# them.
+/* #define HAVE_BISON */
+
+/* Include some boilerplate Gnu makefile definitions. */
+prefix = /usr/local
+
+exec_prefix = $(prefix)
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+
+manroot = $(prefix)/man
+
+man1ext = 1
+man1dir = $(manroot)/man$(man1ext)
+man3ext = 3
+man3dir = $(manroot)/man$(man3ext)
+mandir = $(man1dir)
+manext = $(man1ext)
+
+infodir = $(prefix)/info
+
+srcdir = .
+
+VPATH = .:$(srcdir)
+
+/* If you have purify, and want to use it, uncomment this definition or
+   run the make as `make -f bash-Makefile bash PURIFY=purify'. */
+PURIFY = # purify
+
+/* This includes the appropriate description for the machine that you are
+   using (we hope).  If the compilation doesn't work correctly, then you
+   will have to edit the file `machines.h' to include a description for the
+   machine that your Cpp uniquely identifies this as.  For example, Sun 4's
+   are recognized by the Cpp identifier `sparc', Vax is recognized with `vax',
+   etc.  The order of these files is very important.  Config.h must come last,
+   since it is capable of undef'ing various things. */
+#define BUILDING_MAKEFILE   /* Tell config.h to avoid #including anything. */
+#include "sysdefs.h"
+#include "machines.h"
+#include "config.h"
+
+/* Can't use the Gnu malloc library without saying we want the Gnu malloc. */
+#if !defined (USE_GNU_MALLOC)
+#  undef USE_GNU_MALLOC_LIBRARY
+#endif /* !USE_GNU_MALLOC */
+
+.SUFFIXES: .aux
+/**/# Here is a rule for making .o files from .c files that does not
+/**/# force the type of the machine (like -M_MACHINE) into the flags.
+.c.o:
+       $(RM) $@
+       $(CC) $(CCFLAGS) $(CPPFLAGS) -c $<
+
+.c.aux:
+       $(RM) $@
+       $(CC) $(CCFLAGS) $(CPPFLAGS) -o $@ $<
+
+#if defined (HAVE_BISON)
+BISON = bison -y
+#else
+BISON = yacc
+#endif
+
+#if defined (HAVE_GCC)
+#  if defined (GCC_FLAGS)
+GCC_EXTRAS = GCC_FLAGS
+#  endif /* GCC_FLAGS */
+#  if !defined (HAVE_FIXED_INCLUDES)
+/* This is guaranteed to work, even if you have the fixed includes!
+   (Unless, of course, you have the fixed include files installed in
+   /usr/include.  Then it will break.) */
+CC = gcc -traditional -I/usr/include $(GCC_EXTRAS)
+#  else /* HAVE_FIXED_INCLUDES */
+CC = gcc $(GCC_EXTRAS)
+#  endif /* HAVE_FIXED_INCLUDES */
+#else /* !HAVE_GCC */
+CC = CPP_CC
+#endif /* !HAVE_GCC */
+
+/**/# If the user has specified a Make shell, then use that.
+#if defined (MAKE_SHELL)
+SHELL = MAKE_SHELL
+#else
+SHELL=/bin/sh
+#endif /* MAKE_SHELL */
+
+CP = cp
+RM = rm -f
+AR = ar
+
+INSTALL = $(SUPPORT_SRC)install.sh
+INSTALL_PROGRAM = $(INSTALL) -c
+INSTALL_DATA = $(INSTALL) -c -m 644
+
+COMPRESS = gzip
+COMPRESS_EXT = .gz
+
+Machine = M_MACHINE
+OS = M_OS
+
+/**/# PROFILE_FLAGS is either -pg, to generate profiling info for use
+/**/# with gprof, or nothing (the default).
+PROFILE_FLAGS=
+
+#if defined (SYSDEP_CFLAGS)
+/**/# This system has some peculiar flags that must be passed to the
+/**/# the C compiler (or to cpp).
+SYSDEP = SYSDEP_CFLAGS
+#endif /* SYSDEP_CFLAGS */
+
+#if defined (SYSDEP_LDFLAGS)
+/**/# This system has some peculiar flags that must be passed to the
+/**/# link editor (ld).
+SYSDEP_LD = SYSDEP_LDFLAGS
+#endif /* SYSDEP_LDFLAGS */
+
+#if defined (HAVE_SETLINEBUF)
+/**/# This system has the setlinebuf () call.
+LINEBUF = -DHAVE_SETLINEBUF
+#endif
+
+#if defined (HAVE_VFPRINTF)
+/**/# This system has the vprintf () and vfprintf () calls.
+VPRINTF = -DHAVE_VFPRINTF
+#endif /* HAVE_VFPRINTF */
+
+#if defined (USE_VFPRINTF_EMULATION)
+VPRINTF = -DHAVE_VFPRINTF
+VPRINT_OBJ = vprint.o
+#endif /* USE_VFPRINTF_EMULATION */
+
+#if defined (HAVE_SYS_STREAM_H)
+/**/# This system has <sys/stream.h>
+STREAM = -DHAVE_SYS_STREAM_H
+#endif /* HAVE_SYS_STREAM_H */
+
+#if defined (HAVE_SYS_PTEM_H)
+/**/# This system has <sys/ptem.h>
+PTEM = -DHAVE_SYS_PTEM_H
+#endif /* HAVE_SYS_PTEM_H */
+
+#if defined (HAVE_SYS_PTE_H)
+/**/# This system has <sys/pte.h>
+PTE = -DHAVE_SYS_PTE_H
+#endif /* HAVE_SYS_PTE_H */
+
+/**/# This system has <unistd.h>.
+#if defined (HAVE_UNISTD_H)
+UNISTD = -DHAVE_UNISTD_H
+#endif
+
+/**/# This system has <stdlib.h>
+#if defined (HAVE_STDLIB_H)
+STDLIB = -DHAVE_STDLIB_H
+#endif
+
+/**/# This system has <limits.h>
+#if defined (HAVE_LIMITS_H)
+LIMITSH = -DHAVE_LIMITS_H
+#endif
+
+#if defined (HAVE_GETGROUPS)
+/**/# This system has multiple groups.
+GROUPS = -DHAVE_GETGROUPS
+#endif
+
+#if defined (HAVE_RESOURCE)
+/**/# This system has <sys/resource.h>
+RESOURCE = -DHAVE_RESOURCE
+#endif
+
+#if defined (HAVE_SYS_PARAM)
+/**/# This system has <sys/param.h>
+PARAM = -DHAVE_SYS_PARAM
+#endif
+
+#if defined (VOID_SIGHANDLER)
+/**/# The signal () call provided by the system returns a pointer to
+/**/# a function returning void.  The signal handlers themselves are
+/**/# thus void functions.
+SIGHANDLER = -DVOID_SIGHANDLER
+#endif
+
+#if defined (HAVE_STRERROR)
+/**/# This system has the strerror () function.
+STRERROR = -DHAVE_STRERROR
+#endif
+
+#if defined (HAVE_WAIT_H)
+/**/# This system has <sys/wait.h>
+WAITH = -DHAVE_WAIT_H
+#endif
+
+#if defined (HAVE_GETWD)
+/**/# This system has the getwd () call.
+GETWD = -DHAVE_GETWD
+#endif
+
+#if defined (HAVE_DUP2)
+/**/# This system has a working version of dup2 ().
+DUP2 = -DHAVE_DUP2
+#endif /* HAVE_DUP2 */
+
+#if defined (HAVE_DIRENT)
+/**/# This system uses struct dirent for reading directories with readdir.
+DIRENT = -DHAVE_DIRENT
+#endif /* HAVE_DIRENT */
+
+#if defined (HAVE_DIRENT_H)
+/**/# This system has /usr/include/dirent.h
+DIRENTH = -DHAVE_DIRENT_H
+#endif /* HAVE_DIRENT_H */
+
+#if defined (HAVE_STRING_H)
+/**/# This system has /usr/include/string.h
+STRINGH = -DHAVE_STRING_H
+#endif /* HAVE_STRING_H */
+
+#if defined (HAVE_VARARGS_H)
+/**/# This system has /usr/include/varargs.h
+VARARGSH = -DHAVE_VARARGS_H
+#endif /* HAVE_VARARGS_H */
+
+#if defined (HAVE_STRCHR)
+/**/# This system has strchr () and strrchr () string functions.
+STRCHR = -DHAVE_STRCHR
+#endif /* HAVE_STRCHR */
+
+#if defined (HAVE_STRCASECMP)
+STRCASE = -DHAVE_STRCASECMP
+#endif /* HAVE_STRCASECMP */
+
+#if defined (HAVE_DEV_FD)
+/**/# This system has the /dev/fd directory for naming open files.
+DEVFD = -DHAVE_DEV_FD
+#endif /* HAVE_DEV_FD */
+
+/**/# 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 = -O -g
+
+SYSTEM_FLAGS = $(LINEBUF) $(VPRINTF) $(UNISTD) $(STDLIB) $(LIMITSH) \
+       $(GROUPS) $(RESOURCE) $(PARAM) $(SIGHANDLER) $(SYSDEP) $(WAITH) \
+       $(GETWD) $(DUP2) $(STRERROR) $(DIRENT) $(DIRENTH) $(STRINGH) \
+       $(VARARGSH) $(STRCHR) $(STRCASE) $(DEVFD) \
+       -D$(Machine) -D$(OS)
+LDFLAGS        = $(NOSHARE) $(SYSDEP_LD) $(EXTRA_LD_PATH) $(PROFILE_FLAGS) $(CFLAGS)
+CCFLAGS        = $(PROFILE_FLAGS) $(SYSTEM_FLAGS) -DSHELL $(ALLOCA_CFLAGS) \
+         $(MALLOC_CFLAGS) $(CFLAGS)
+CPPFLAGS= -I. -I$(srcdir) -I$(LIBSRC)
+GCC_LINT_FLAGS = -ansi -Wall -Wshadow -Wpointer-arith -Wcast-qual \
+                -Wwrite-strings -Werror -Wstrict-prototypes \
+                -Wmissing-prototypes
+GCC_LINT_CFLAGS = $(PROFILE_FLAGS) $(CFLAGS) $(SYSTEM_FLAGS) -DSHELL $(ALLOCA_CFLAGS) \
+                 $(MALLOC_CFLAGS) $(GCC_LINT_FLAGS)
+
+/* It is conceivable that you wish to edit some things beyond this point,
+   but I guess that it is highly unlikely, and may give you a headache. */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                 How to Build the support libraries.             */
+/*                                                                 */
+/* **************************************************************** */
+
+/**/# The location of sources for the support libraries.
+LIBPATH = ./lib/
+LIBSRC = $(srcdir)/$(LIBPATH)
+
+/**/# Preface building with the full path of the current library source.
+LIBINC_DECL  = topdir=`sh $(srcdir)/support/srcdir $(srcdir)`; export topdir
+LIBINC_USAGE = "-I$${topdir} -I$${topdir}/$(LIBPATH) -I$(LIBSRC)"
+
+/* Defines used when building libraries. */
+#define LIB_CFLAGS_DECL CFLAGS='$(LIBRARY_CFLAGS) '$(LIBINC_USAGE)
+#define LIB_CPPFLAGS_DECL CPPFLAGS='$(CPPFLAGS)'
+#define LIB_LDFLAGS_DECL LDFLAGS='$(LDFLAGS)'
+#define LIBMAKE_FLAGS LIB_CFLAGS_DECL LIB_CPPFLAGS_DECL LIB_LDFLAGS_DECL \
+       RANLIB='$(RANLIB)' AR='$(AR)' CC='$(CC)' RM='$(RM)' \
+
+/* Macro used to build a library. */
+#define build_lib_in_dir(directory, target, srcdef, makefile) \
+       @echo "Building in " directory "..."; \
+       sh $(SUPPORT_SRC)mkdirs directory ; \
+       ($(LIBINC_DECL); cd directory; \
+        if [ ! -f Makefile ]; then cp makefile Makefile; fi; \
+        $(MAKE) target $(MFLAGS) LIBMAKE_FLAGS srcdef)
+
+/* The builtins are somewhat special in that more information is needed
+   to compile them correctly. */
+#define build_builtins(target) \
+       @sh $(SUPPORT_SRC)mkdirs $(DEFDIR) ; \
+       ($(LIBINC_DECL); cd $(DEFDIR); \
+        if [ ! -f Makefile ]; then \
+               cp $(BUILTIN_ABSSRC)/Makefile Makefile; \
+        fi; \
+        $(MAKE) $(MFLAGS) target \
+        srcdir=$(BUILTIN_ABSSRC) CPPFLAGS='$(CPPFLAGS)' \
+        CFLAGS='$(CCFLAGS) '$(LIBINC_USAGE)' -I. -I$(BUILTIN_ABSSRC)' \
+        LDFLAGS='$(LDFLAGS)' RANLIB='$(RANLIB)' AR='$(AR)' CC='$(CC)' \
+        RM='$(RM)' RL_LIBSRC='$(RL_ABSSRC)' \
+        DIRECTDEFINE='-D '$(srcdir)/$(DEFDIR))
+
+/**/# Flags used when building libraries.
+LIBRARY_CFLAGS  = $(PROFILE_FLAGS) $(CFLAGS) $(SIGHANDLER) $(ALLOCA_CFLAGS) \
+                 $(SYSDEP) $(DIRENT) $(DIRENTH) $(STRINGH) $(VARARGSH) \
+                 $(PTEM) $(PTE) $(STREAM) $(STRERROR) $(RESOURCE) \
+                 $(STRCHR) -D$(Machine) -D$(OS) $(UNISTD) $(LIMITSH) \
+                 $(STRCASE) $(STDLIB) -DSHELL
+
+/**/# These are required for sending bug reports.
+SYSTEM_NAME = $(Machine)
+OS_NAME = $(OS)
+
+/**/# The name of this program.
+Program = bash
+
+/**/# The type of machine and OS Bash is being compiled on.
+HOSTTYPE_DECL = -DHOSTTYPE='$(SYSTEM_NAME)' -DOSTYPE='$(OS_NAME)'
+
+/**/# The group of configuration flags.  These are for shell.c
+CFG_FLAGS = -DOS_NAME='$(OS_NAME)' -DSYSTEM_NAME='$(SYSTEM_NAME)' \
+           $(SIGLIST_FLAG)
+
+/* **************************************************************** */
+/*                                                                  */
+/*                 Support for desired libraries.                   */
+/*    This includes Termcap, Glob, Tilde, History, and Readline.    */
+/*                                                                  */
+/* **************************************************************** */
+
+/* Does this machine's linker need a space after -L? */
+#if defined (HAVE_GCC)
+#  undef SEARCH_LIB_NEEDS_SPACE
+#endif /* HAVE_GCC */
+
+#if defined (SEARCH_LIB_NEEDS_SPACE)
+/**/# The native compiler for this machines requires a space after '-L'.
+SEARCH_LIB = -L $(UNSET_VARIABLE_CREATES_SPACE)
+#else
+/**/# The compiler being used to build Bash can handle -L/library/path.
+SEARCH_LIB = -L
+#endif /* !SEARCH_LIB_NEEDS_SPACE */
+
+#if defined (EXTRA_LIB_SEARCH_PATH)
+/**/# Additional instructions to the linker telling it how to find libraries.
+LOCAL_LD_PATH = EXTRA_LIB_SEARCH_PATH
+EXTRA_LD_PATH = $(SEARCH_LIB)$(LOCAL_LD_PATH)
+#endif /* EXTRA_LIB_SEARCH_PATH */
+
+/* Right now we assume that you have the full source code to Bash.  If
+   you simply have the library and header files installed, then
+   undefine HAVE_READLINE_SOURCE. */
+#define HAVE_READLINE_SOURCE
+
+#if defined (HAVE_READLINE_SOURCE)
+
+RL_LIBSRC = $(LIBSRC)readline/
+RL_LIBDOC = $(RL_LIBSRC)doc/
+RL_LIBDIR = $(LIBPATH)readline/
+RL_ABSSRC = $${topdir}/$(RL_LIBDIR)
+
+READLINE_LIBRARY = $(RL_LIBDIR)libreadline.a
+
+/**/# The source, object and documentation of the GNU Readline library.
+READLINE_SOURCE        = $(RL_LIBSRC)rldefs.h $(RL_LIBSRC)rlconf.h \
+                 $(RL_LIBSRC)readline.h \
+                 $(RL_LIBSRC)chardefs.h $(RL_LIBSRC)keymaps.h \
+                 $(RL_LIBSRC)funmap.c $(RL_LIBSRC)emacs_keymap.c \
+                 $(RL_LIBSRC)search.c $(RL_LIBSRC)vi_keymap.c \
+                 $(RL_LIBSRC)keymaps.c $(RL_LIBSRC)parens.c \
+                 $(RL_LIBSRC)vi_mode.c $(RL_LIBSRC)history.c \
+                 $(RL_LIBSRC)readline.c $(RL_LIBSRC)tilde.c \
+                 $(RL_LIBSRC)rltty.c $(RL_LIBSRC)complete.c \
+                 $(RL_LIBSRC)bind.c $(RL_LIBSRC)isearch.c \
+                 $(RL_LIBSRC)display.c $(RL_LIBSRC)signals.c \
+                 $(RL_LIBSRC)posixstat.h $(RL_LIBSRC)tilde.h \
+                 $(RL_LIBSRC)xmalloc.c
+
+READLINE_OBJ   = $(RL_LIBDIR)readline.o $(RL_LIBDIR)funmap.o \
+                 $(RL_LIBDIR)parens.o $(RL_LIBDIR)search.o \
+                 $(RL_LIBDIR)keymaps.o $(RL_LIBDIR)history.o \
+                 $(RL_LIBDIR)rltty.o $(RL_LIBDIR)complete.o \
+                 $(RL_LIBDIR)bind.o $(RL_LIBDIR)isearch.o \
+                 $(RL_LIBDIR)display.o $(RL_LIBDIR)signals.o \
+                 $(RL_LIBDIR)tilde.o $(RL_LIBDIR)xmalloc.o
+
+READLINE_DOC   = $(RL_LIBDOC)rlman.texinfo $(RL_LIBDOC)rluser.texinfo \
+                 $(RL_LIBDOC)rltech.texinfo
+
+READLINE_DOC_SUPPORT  = $(RL_LIBDOC)Makefile $(RL_LIBDOC)readline.dvi \
+                 $(RL_LIBDOC)readline.info
+
+/**/# This has to be written funny to avoid looking like a C comment starter.
+READLINE_EXAMPLES = $(RL_LIBSRC)examples/[a-zA-Z]*.[ch] \
+                   $(RL_LIBSRC)examples/Makefile $(RL_LIBSRC)examples/Inputrc
+
+/**/# Support files for GNU Readline.
+READLINE_SUPPORT = $(RL_LIBSRC)Makefile $(RL_LIBSRC)ChangeLog \
+                  $(RL_LIBSRC)COPYING $(READLINE_EXAMPLES) \
+                  $(READLINE_DOC_SUPPORT)
+
+#else /* !HAVE_READLINE_SOURCE */
+
+#  if defined (READLINE)
+READLINE_LIBRARY = -lreadline
+#  endif /* READLINE */
+RL_LIBDIR = $(srcdir)/$(LIBSRC)readline/
+
+#endif /* !HAVE_READLINE_SOURCE */
+
+/* Right now we assume that you have the full source code to Bash,
+   including the source code to the history library.  If you only have
+   the library and header files installed, then you can undefine
+   HAVE_HISTORY_SOURCE. */
+#define HAVE_HISTORY_SOURCE
+
+#if defined (READLINE) && !defined (HISTORY)
+#  define HISTORY
+#endif /* READLINE && !HISTORY */
+
+#  if defined (HISTORY) && !defined (READLINE)
+/**/# You are compiling with history features but without line editing.
+HISTORY_LIB = -lhistory
+#  endif /* HISTORY && !READLINE */
+
+#if defined (HISTORY)
+HIST_SUPPORT_SRC = bashhist.c
+HIST_SUPPORT_OBJ = bashhist.o
+#endif /* HISTORY */
+
+#if defined (HAVE_HISTORY_SOURCE)
+
+HIST_LIBSRC = $(LIBSRC)readline/
+HIST_LIBDOC = $(HIST_LIBSRC)doc/
+HIST_LIBDIR = $(LIBPATH)readline/
+HIST_ABSSRC = $${topdir}/$(HIST_LIBDIR)/
+
+/* If you are building with readline, then you do not explicitly need the
+   history library. */
+#  if defined (READLINE)
+HISTORY_LIBRARY = 
+#  else
+HISTORY_LIBRARY = $(HIST_LIBDIR)libhistory.a
+#  endif /* !READLINE */
+
+/**/# The source, object and documentation of the history library.
+HISTORY_SOURCE = $(HIST_LIBSRC)history.c $(HIST_LIBSRC)history.h
+HISTORY_OBJ    = $(HIST_LIBDIR)history.o
+HISTORY_DOC    = $(HIST_LIBDOC)hist.texinfo $(HIST_LIBDOC)hsuser.texinfo \
+                 $(HIST_LIBDOC)hstech.texinfo
+
+/**/# Directory list for -L so that the link editor (ld) can find -lhistory.
+#  if defined (HISTORY) && !defined (READLINE)
+#    if !defined (LD_HAS_NO_DASH_L)
+HISTORY_LDFLAGS = $(SEARCH_LIB)$(HIST_LIBDIR)
+#    endif /* LD_HAS_NO_DASH_L */
+#  endif /* HISTORY && !READLINE */
+#else /* !HAVE_HISTORY_SOURCE */
+#  if defined (HISTORY) && !defined (READLINE)
+HISTORY_LIBRARY = -lhistory
+HISTORY_LDFLAGS = $(SEARCH_LIB)$(libdir) $(SEARCH_LIB)/usr/local/lib
+#  endif /* HISTORY && !READLINE */
+#endif /* !HAVE_HISTORY_SOURCE */
+
+#if defined (USE_GNU_TERMCAP)
+#  define HAVE_TERMCAP_SOURCE
+TERM_LIBSRC = $(LIBSRC)termcap/
+TERM_LIBDIR = $(LIBPATH)termcap/
+TERM_ABSSRC = $${topdir}/$(TERM_LIBDIR)
+
+/**/# The source, object and documentation for the GNU Termcap library.
+TERMCAP_LIBRARY = $(TERM_LIBDIR)libtermcap.a
+
+TERMCAP_SOURCE = $(TERM_LIBSRC)termcap.c $(TERM_LIBSRC)tparam.c
+TERMCAP_OBJ    = $(TERM_LIBDIR)termcap.o $(TERM_LIBDIR)tparam.o
+TERMCAP_DOC    = $(TERM_LIBSRC)termcap.texinfo
+TERMCAP_SUPPORT = $(TERM_LIBSRC)Makefile $(TERM_LIBSRC)ChangeLog
+
+#  if !defined (LD_HAS_NO_DASH_L)
+TERMCAP_LDFLAGS = $(SEARCH_LIB)$(TERM_LIBDIR)
+#  endif /* !LD_HAS_NO_DASH_L */
+#else /* !USE_GNU_TERMCAP */
+
+/* Guessed at symbol for LIBRARIES, below. */
+#  if defined (USE_TERMCAP_EMULATION)
+TERMCAP_LIBRARY = -lcurses
+#  else /* !USE_TERMCAP_EMULATION */
+TERMCAP_LIBRARY = -ltermcap
+#  endif /* !USE_TERMCAP_EMULATION */
+#endif /* !USE_GNU_TERMCAP */
+
+/* The glob library is always used. */
+#define USE_GLOB_LIBRARY
+
+#if defined (USE_GLOB_LIBRARY)
+GLOB_LIBSRC = $(LIBSRC)glob/
+GLOB_LIBDIR = $(LIBPATH)glob/
+GLOB_ABSSRC = $${topdir}/$(GLOB_LIBDIR)
+
+GLOB_LIBRARY = $(GLOB_LIBDIR)libglob.a
+
+GLOB_SOURCE = $(GLOB_LIBSRC)glob.c $(GLOB_LIBSRC)fnmatch.c \
+             $(GLOB_LIBSRC)fnmatch.h
+GLOB_OBJ    = $(GLOB_LIBDIR)glob.o $(GLOB_LIBDIR)fnmatch.o
+GLOB_DOC    = $(GLOB_LIBSRC)doc/glob.texi $(GLOB_LIBSRC)doc/Makefile
+GLOB_SUPPORT= $(GLOB_LIBSRC)Makefile $(GLOB_LIBSRC)ChangeLog
+
+#  if !defined (LD_HAS_NO_DASH_L)
+GLOB_LDFLAGS = $(SEARCH_LIB)$(GLOB_LIBDIR)
+#  endif /* !LD_HAS_NO_DASH_L */
+GLOB_LIB     = -lglob
+#endif /* USE_GLOB_LIBRARY */
+
+/* The source code for the tilde expansion library. */
+#if defined (HAVE_READLINE_SOURCE)
+#  define HAVE_TILDE_SOURCE
+#endif /* HAVE_READLINE_SOURCE */
+
+#if defined (HAVE_TILDE_SOURCE)
+/**/# The source, object and documentation for the GNU Tilde library.
+TILDE_LIBSRC = $(LIBSRC)tilde/
+TILDE_LIBDIR = $(LIBPATH)tilde/
+TILDE_ABSSRC = $${topdir}/$(TILDE_LIBDIR)
+
+TILDE_LIBRARY = $(TILDE_LIBDIR)libtilde.a
+
+TILDE_SOURCE   = $(TILDE_LIBSRC)tilde.c $(TILDE_LIBSRC)tilde.h
+TILDE_OBJ      = $(TILDE_LIBDIR)tilde.o
+TILDE_DOC      = $(TILDE_LIBSRC)doc/tilde.texi $(TILDE_LIBSRC)doc/Makefile
+TILDE_SUPPORT  = $(TILDE_LIBSRC)Makefile $(TILDE_LIBSRC)ChangeLog
+
+TILDE_LIB = -ltilde
+
+#  if !defined (LD_HAS_NO_DASH_L)
+TILDE_LDFLAGS = $(SEARCH_LIB)$(TILDE_LIBDIR)
+#  endif /* !LD_HAS_NO_DASH_L */
+
+#else /* !HAVE_TILDE_SOURCE */
+/**/# Guessed at location of the tilde 
+TILDE_LIBRARY = $(libdir)/libtilde.a
+#endif /* !HAVE_TILDE_SOURCE */
+
+#if defined (USE_GNU_MALLOC_LIBRARY)
+/**/# Our malloc library.
+MALLOC_LIBSRC = $(LIBSRC)malloclib/
+MALLOC_LIBDIR = $(LIBPATH)malloclib/
+MALLOC_ABSSRC = $${topdir}/$(MALLOC_LIBDIR)
+
+MALLOC_LIBRARY = $(MALLOC_LIBDIR)libmalloc.a
+
+MALLOC_SOURCE = $(MALLOC_LIBSRC)calloc.c $(MALLOC_LIBSRC)cfree.c \
+               $(MALLOC_LIBSRC)free.c $(MALLOC_LIBSRC)malloc.c \
+               $(MALLOC_LIBSRC)mcheck.c $(MALLOC_LIBSRC)memalign.c \
+               $(MALLOC_LIBSRC)morecore.c $(MALLOC_LIBSRC)mstats.c \
+               $(MALLOC_LIBSRC)mtrace.c $(MALLOC_LIBSRC)realloc.c \
+               $(MALLOC_LIBSRC)valloc.c
+MALLOC_OBJ    = $(MALLOC_LIBDIR)calloc.c $(MALLOC_LIBDIR)cfree.c \
+               $(MALLOC_LIBDIR)free.c $(MALLOC_LIBDIR)malloc.c \
+               $(MALLOC_LIBDIR)mcheck.c $(MALLOC_LIBDIR)memalign.c \
+               $(MALLOC_LIBDIR)morecore.c $(MALLOC_LIBDIR)mstats.c \
+               $(MALLOC_LIBDIR)mtrace.c $(MALLOC_LIBDIR)realloc.c \
+               $(MALLOC_LIBDIR)valloc.c
+
+MALLOC_SUPPORT= $(MALLOC_LIBSRC)Makefile
+MALLOC_CFLAGS = -DUSE_GNU_MALLOC_LIBRARY
+
+#  if !defined (LD_HAS_NO_DASH_L)
+MALLOC_LDFLAGS = $(SEARCH_LIB)$(MALLOC_LIBDIR)
+#  endif /* !LD_HAS_NO_DASH_L */
+MALLOC_LIB     = -lmalloc
+
+MALLOC_DEP = $(MALLOC_LIBRARY)
+#else
+MALLOC_LIBRARY =
+#endif /* USE_GNU_MALLOC_LIBRARY */
+
+BASHPOSIX_LIB     = $(LIBSRC)posixheaders/
+BASHPOSIX_SUPPORT = $(BASHPOSIX_LIB)posixstat.h $(BASHPOSIX_LIB)ansi_stdlib.h \
+                   $(BASHPOSIX_LIB)memalloc.h $(BASHPOSIX_LIB)stdc.h
+
+/**/# Declare all of the sources for the libraries that we have.
+LIBRARY_SOURCE  = $(READLINE_SOURCE) $(HISTORY_SOURCE) $(TERMCAP_SOURCE) \
+                 $(GLOB_SOURCE) $(TILDE_SOURCE) $(MALLOC_SOURCE)
+LIBRARY_DOC    = $(READLINE_DOC) $(HISTORY_DOC) $(TERMCAP_DOC) $(GLOB_DOC) \
+                 $(TILDE_DOC) $(MALLOC_DOC)
+LIBRARY_SUPPORT = $(READLINE_SUPPORT) $(HISTORY_SUPPORT) $(TERMCAP_SUPPORT) \
+                 $(GLOB_SUPPORT) $(TILDE_SUPPORT) $(MALLOC_SUPPORT)
+LIBRARY_TAR     = $(LIBRARY_SOURCE) $(LIBRARY_DOC) $(LIBRARY_SUPPORT)
+
+#if defined (READLINE)
+/**/# You wish to compile with the line editing features installed.
+READLINE_LIB = -lreadline
+
+/**/# You only need termcap (or curses) if you are linking with GNU Readline.
+#  if defined (USE_TERMCAP_EMULATION)
+TERMCAP_LIB = -lcurses
+#  else  /* !USE_TERMCAP_EMULATION */
+TERMCAP_LIB = -ltermcap
+#  endif /* !USE_TERMCAP_EMULATION */
+
+/**/# Directory list for -L so that the link editor (ld) can find -lreadline.
+#  if !defined (LD_HAS_NO_DASH_L)
+#    if defined (HAVE_READLINE_SOURCE)
+READLINE_LDFLAGS = $(SEARCH_LIB)$(RL_LIBDIR) $(TERMCAP_LDFLAGS)
+#    else
+READLINE_LDFLAGS = $(TERMCAP_LDFLAGS) $(SEARCH_LIB)$(libdir) \
+                  $(SEARCH_LIB)/usr/local/lib
+#    endif /* HAVE_READLINE_SOURCE */
+#  endif /* LD_HAS_NO_DASH_L */
+
+/**/# The source and object of the bash<->readline interface code.
+RL_SUPPORT_SRC = bashline.c bracecomp.c
+RL_SUPPORT_OBJ = bashline.o $(BRACECOMP_OBJECT)
+#endif /* READLINE */
+
+/**/# The order is important.  Most dependent first.
+#if defined (LD_HAS_NO_DASH_L)
+/**/# This linker does not know how to grok the -l flag, or perhaps how
+/**/# to grok the -L flag, or both.
+LIBRARIES = $(READLINE_LIBRARY) $(HISTORY_LIBRARY) $(TERMCAP_LIBRARY) \
+           $(GLOB_LIBRARY) $(TILDE_LIBRARY) $(MALLOC_LIBRARY) $(LOCAL_LIBS)
+#else /* !LD_HAS_NO_DASH_L */
+LIBRARIES = $(READLINE_LIB) $(HISTORY_LIB) $(TERMCAP_LIB) $(GLOB_LIB) \
+           $(TILDE_LIB) $(MALLOC_LIB) $(LOCAL_LIBS)
+#endif /* !LD_HAS_NO_DASH_L */
+
+#if defined (READLINE)
+#  if defined (HAVE_TERMCAP_SOURCE)
+TERMCAP_DEP = $(TERMCAP_LIBRARY)
+#  endif /* HAVE_TERMCAP_SOURCE */
+#  if defined (HAVE_READLINE_SOURCE)
+READLINE_DEP = $(READLINE_LIBRARY)
+#  endif /* HAVE_READLINE_SOURCE */
+#endif /* READLINE */
+
+#if defined (HISTORY) && defined (HAVE_HISTORY_SOURCE) && !defined (READLINE)
+HISTORY_DEP = $(HISTORY_LIBRARY)
+#endif
+
+#if defined (USE_GLOB_LIBRARY)
+GLOB_DEP = $(GLOB_LIBRARY)
+#else
+GLOBC = glob.c fnmatch.c
+GLOBO = glob.o fnmatch.o
+#endif /* USE_GLOB_LIBRARY */
+
+#if defined (HAVE_TILDE_SOURCE)
+TILDE_DEP = $(TILDE_LIBRARY)
+#endif
+
+/**/# Source files for libraries that Bash depends on.
+LIBDEP = $(READLINE_DEP) $(TERMCAP_DEP) $(GLOB_DEP) $(HISTORY_DEP) $(TILDE_DEP) $(MALLOC_DEP)
+
+/**/# Rules for cleaning the readline and termcap sources.
+#if defined (HAVE_READLINE_SOURCE)
+CLEAN_READLINE = (cd $(RL_LIBDIR); $(MAKE) $(MFLAGS) $@)
+#else
+CLEAN_READLINE = :
+#endif /* !HAVE_READLINE_SOURCE */
+
+#if defined (HAVE_HISTORY_SOURCE)
+#  if !defined (READLINE)
+CLEAN_HISTORY = (cd $(HIST_LIBDIR); $(MAKE) $(MFLAGS) $@)
+#  else
+CLEAN_HISTORY = :
+#  endif /* READLINE */
+#endif /* !HAVE_HISTORY_SOURCE */
+
+#if defined (HAVE_TERMCAP_SOURCE)
+CLEAN_TERMCAP = (cd $(TERM_LIBDIR); $(MAKE) $(MFLAGS) $@)
+#else
+CLEAN_TERMCAP = :
+#endif /* !HAVE_TERMCAP_SOURCE */
+
+#if defined (USE_GLOB_LIBRARY)
+CLEAN_GLOB = (cd $(GLOB_LIBDIR); $(MAKE) $(MFLAGS) $@)
+#else
+CLEAN_GLOB = :
+#endif /* !USE_GLOB_LIBRARY */
+
+#if defined (HAVE_TILDE_SOURCE)
+CLEAN_TILDE = (cd $(TILDE_LIBDIR); $(MAKE) $(MFLAGS) $@)
+#else
+CLEAN_TILDE = :
+#endif /* !HAVE_TILDE_SOURCE */
+
+#if defined (USE_GNU_MALLOC_LIBRARY)
+CLEAN_MALLOC = (cd $(MALLOC_LIBDIR); $(MAKE) $(MFLAGS) $@)
+#else
+CLEAN_MALLOC = :
+#endif /* !USE_GNU_MALLOC_LIBRARY */
+
+LIBRARY_LDFLAGS = $(READLINE_LDFLAGS) $(HISTORY_LDFLAGS) $(TILDE_LDFLAGS) \
+                 $(GLOB_LDFLAGS) $(MALLOC_LDFLAGS)
+
+/**/# The directory which contains the source for malloc.  The name must
+/**/# end in a slash, as in "./lib/malloc/".
+ALLOC_LIBSRC = $(LIBSRC)malloc/
+ALLOC_LIBDIR = $(LIBPATH)malloc/
+ALLOC_ABSSRC = $${topdir}/$(ALLOC_LIBDIR)
+
+/**/# Our malloc.
+#if defined (USE_GNU_MALLOC) && !defined (USE_GNU_MALLOC_LIBRARY)
+
+MALLOC_OBJ = $(ALLOC_LIBDIR)malloc.o
+MALLOC_SRC = $(ALLOC_LIBSRC)malloc.c
+MALLOC_DEP = $(MALLOC_SRC) $(ALLOC_LIBSRC)getpagesize.h
+MALLOC_FLAGS = -Drcheck -Dbotch=programming_error
+
+MALLOC_LIBRARY =
+
+#endif /* USE_GNU_MALLOC && !USE_GNU_MALLOC_LIBRARY */
+
+/* If this user doesn't have alloca (), then we must try to supply them
+   with a working one. */
+#if !defined (HAVE_ALLOCA)
+ALLOCA = $(ALLOC_LIBDIR)alloca.o
+#  if defined (ALLOCA_ASM)
+ALLOCA_SOURCE = ALLOCA_ASM
+ALLOCA_OBJECT = ALLOCA_OBJ
+#  else
+ALLOCA_SOURCE = alloca.c
+ALLOCA_OBJECT = alloca.o
+#  endif /* ALLOCA_ASM */
+ALLOCA_DEP = $(ALLOC_LIBSRC)$(ALLOCA_SOURCE)
+#endif /* !HAVE_ALLOCA */
+
+/* Compilation flags to use in the shell directory and to pass to builds
+   in subdirectories (readline, termcap) to ensure that alloca is treated
+   in a consistent fashion. */
+#if defined (HAVE_ALLOCA_H)
+ALLOCA_H_DEFINE = -DHAVE_ALLOCA_H
+#else
+ALLOCA_H_DEFINE =
+#endif /* HAVE_ALLOCA_H */
+
+#if defined (HAVE_ALLOCA)
+ALLOCA_DEFINE = -DHAVE_ALLOCA
+#else
+ALLOCA_DEFINE =
+#endif /* HAVE_ALLOCA */
+
+ALLOCA_CFLAGS = $(ALLOCA_DEFINE) $(ALLOCA_H_DEFINE)
+
+/* Protect the `i386' used in the definition of ALLOC_FILES. */
+#if defined (i386)
+#  undef i386
+#  define i386_defined
+#endif /* i386 */
+
+ALLOC_HEADERS = $(ALLOC_LIBSRC)getpagesize.h
+ALLOC_FILES = $(ALLOC_LIBSRC)malloc.c $(ALLOC_LIBSRC)alloca.c \
+             $(ALLOC_LIBSRC)i386-alloca.s $(ALLOC_LIBSRC)x386-alloca.s \
+             $(ALLOC_LIBSRC)xmalloc.c
+
+/* Perhaps restore the `i386' define. */
+#if defined (i386_defined)
+#  define i386
+#  undef i386_defined
+#endif /* i386_defined */
+
+#if defined (USE_GNU_MALLOC) && !defined (USE_GNU_MALLOC_LIBRARY)
+$(MALLOC_OBJ): $(MALLOC_DEP)
+               @sh $(SUPPORT_SRC)mkdirs $(ALLOC_LIBDIR)
+               @$(RM) $@
+               @($(LIBINC_DECL); cd $(ALLOC_LIBDIR) ; \
+                if [ ! -f Makefile ]; then cp $(ALLOC_ABSSRC)Makefile Makefile ; fi; \
+                $(MAKE) $(MFLAGS) \
+                CFLAGS='$(LIBRARY_CFLAGS) $(MALLOC_FLAGS)' \
+                CPPFLAGS='$(CPPFLAGS)' MALLOC_SOURCE=$(MALLOC_SRC) \
+                srcdir=$(ALLOC_ABSSRC) malloc.o )
+#endif /* USE_GNU_MALLOC && !USE_GNU_MALLOC_LIBRARY */
+
+#if !defined (HAVE_ALLOCA)
+$(ALLOCA):     $(ALLOCA_DEP)
+               @sh $(SUPPORT_SRC)mkdirs $(ALLOC_LIBDIR)
+               @$(RM) $@
+               @($(LIBINC_DECL); cd $(ALLOC_LIBDIR) ; \
+                if [ ! -f Makefile ]; then cp $(ALLOC_ABSSRC)Makefile Makefile ; fi; \
+                 $(MAKE) $(MFLAGS) CC='$(CC)' \
+                CFLAGS='$(LIBRARY_CFLAGS) $(MALLOC_FLAGS)' \
+                 CPPFLAGS='$(CPPFLAGS)' ALLOCA_SOURCE=$(ALLOCA_SOURCE) \
+                ALLOCA_OBJECT=$(ALLOCA_OBJECT) \
+                srcdir=$(ALLOC_ABSSRC) alloca.o )
+#endif /* !HAVE_ALLOCA */
+
+/**/# The location of ranlib on your system.
+#if defined (RANLIB_LOCATION)
+RANLIB = RANLIB_LOCATION
+#else
+RANLIB = ranlib
+#endif /* RANLIB_LOCATION */
+
+/* **************************************************************** */
+/*                                                                  */
+/*               Support for optional object files                 */
+/*                                                                  */
+/* **************************************************************** */
+#if !defined (HAVE_SYS_SIGLIST)
+/**/# Since this system does not have sys_siglist, we define SIGLIST
+/**/# as siglist.o.
+SIGLIST = siglist.o
+SIGLIST_FLAG=-DINITIALIZE_SIGLIST
+#endif /* HAVE_SYS_SIGLIST */
+
+#if !defined (HAVE_GETCWD)
+/**/# Since this system does not have a correctly working getcwd (),
+/**/# we define GETCWD as getcwd.o.
+GETCWD = getcwd.o
+#endif /* !HAVE_GETCWD */
+
+/**/# The source and object of the curly brace expansion and completion code.
+BRACES_SOURCE   = braces.c
+BRACECOMP_SOURCE = bracecomp.c
+#if defined (BRACE_EXPANSION)
+BRACES_OBJECT = braces.o
+#  if defined (READLINE)
+BRACECOMP_OBJECT = bracecomp.o
+#  endif /* READLINE */
+#endif /* BRACE_EXPANSION */
+
+#if defined (REQUIRED_LIBRARIES)
+/**/# Locally required libraries.
+LOCAL_LIBS = REQUIRED_LIBRARIES
+#endif /* REQUIRED_LIBRARIES */
+
+BUILTINS_LIB = builtins/libbuiltins.a
+
+/**/# The main source code for the Bourne Again SHell.
+CSOURCES = shell.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \
+          dispose_cmd.c execute_cmd.c variables.c $(GLOBC) version.c \
+          expr.c copy_cmd.c flags.c subst.c hash.c mailcheck.c \
+          test.c trap.c jobs.c nojobs.c $(ALLOC_FILES) $(BRACES_SOURCE) \
+          vprint.c input.c bashhist.c \
+          unwind_prot.c siglist.c getcwd.c $(RL_SUPPORT_SRC) error.c
+
+HSOURCES = shell.h flags.h trap.h hash.h jobs.h builtins.h alias.c y.tab.h \
+          general.h variables.h config.h $(ALLOC_HEADERS) alias.h maxpath.h \
+          quit.h machines.h posixstat.h filecntl.h unwind_prot.h parser.h \
+          command.h input.h error.h bashansi.h dispose_cmd.h make_cmd.h \
+          subst.h externs.h siglist.h bashhist.h bashtypes.h
+
+SOURCES         = $(CSOURCES) $(HSOURCES) $(BUILTIN_DEFS)
+
+/**/# Matching object files.
+OBJECTS         = shell.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \
+          dispose_cmd.o execute_cmd.o variables.o copy_cmd.o error.o \
+          expr.o flags.o jobs.o subst.o hash.o mailcheck.o test.o \
+          trap.o alias.o $(MALLOC_OBJ) $(ALLOCA) $(BRACES_OBJECT) \
+          unwind_prot.o $(VPRINT_OBJ) input.o $(HIST_SUPPORT_OBJ) \
+          $(SIGLIST) $(GETCWD) version.o $(RL_SUPPORT_OBJ) $(BUILTINS_LIB)
+
+/**/# Where the source code of the shell builtins resides.
+BUILTIN_SRCDIR=$(srcdir)/builtins/
+/**/# The trailing slash was left off this definition on purpose
+BUILTIN_ABSSRC=$${topdir}/builtins
+DEFDIR = builtins/
+BUILTIN_DEFS = $(DEFDIR)alias.def $(DEFDIR)bind.def $(DEFDIR)break.def \
+              $(DEFDIR)builtin.def $(DEFDIR)cd.def $(DEFDIR)colon.def \
+              $(DEFDIR)command.def $(DEFDIR)declare.def $(LOAD_DEF) \
+              $(DEFDIR)echo.def $(DEFDIR)enable.def $(DEFDIR)eval.def \
+              $(DEFDIR)exec.def $(DEFDIR)exit.def $(DEFDIR)fc.def \
+              $(DEFDIR)fg_bg.def $(DEFDIR)hash.def $(DEFDIR)help.def \
+              $(DEFDIR)history.def $(DEFDIR)jobs.def $(DEFDIR)kill.def \
+              $(DEFDIR)let.def $(DEFDIR)read.def $(DEFDIR)return.def \
+              $(DEFDIR)set.def $(DEFDIR)setattr.def $(DEFDIR)shift.def \
+              $(DEFDIR)source.def $(DEFDIR)suspend.def $(DEFDIR)test.def \
+              $(DEFDIR)times.def $(DEFDIR)trap.def $(DEFDIR)type.def \
+              $(DEFDIR)ulimit.def $(DEFDIR)umask.def $(DEFDIR)wait.def \
+              $(DEFDIR)getopts.def $(DEFDIR)reserved.def
+BUILTIN_C_SRC  = $(DEFDIR)mkbuiltins.c $(DEFDIR)common.c \
+                 $(DEFDIR)hashcom.h $(DEFDIR)/bashgetopt.c $(GETOPT_SOURCE)
+BUILTIN_C_OBJ  = $(GETOPTS_OBJ) $(DEFDIR)common.o $(DEFDIR)bashgetopt.o
+BUILTIN_OBJS = $(DEFDIR)alias.o $(DEFDIR)bind.o $(DEFDIR)break.o \
+              $(DEFDIR)builtin.o $(DEFDIR)cd.o $(DEFDIR)colon.o \
+              $(DEFDIR)command.o $(DEFDIR)declare.o $(LOAD_OBJ) \
+              $(DEFDIR)echo.o $(DEFDIR)enable.o $(DEFDIR)eval.o \
+              $(DEFDIR)exec.o $(DEFDIR)exit.o $(DEFDIR)fc.o \
+              $(DEFDIR)fg_bg.o $(DEFDIR)hash.o $(DEFDIR)help.o \
+              $(DEFDIR)history.o $(DEFDIR)jobs.o $(DEFDIR)kill.o \
+              $(DEFDIR)let.o $(DEFDIR)read.o $(DEFDIR)return.o \
+              $(DEFDIR)set.o $(DEFDIR)setattr.o $(DEFDIR)shift.o \
+              $(DEFDIR)source.o $(DEFDIR)suspend.o $(DEFDIR)test.o \
+              $(DEFDIR)times.o $(DEFDIR)trap.o $(DEFDIR)type.o \
+              $(DEFDIR)ulimit.o $(DEFDIR)umask.o $(DEFDIR)wait.o \
+              $(BUILTIN_C_OBJ)
+#if defined (GETOPTS_BUILTIN)
+GETOPTS_OBJ    = $(DEFDIR)getopts.o
+#endif
+GETOPT_SOURCE   = $(DEFDIR)getopt.c $(DEFDIR)getopt.h
+PSIZE_SOURCE   = $(DEFDIR)psize.sh $(DEFDIR)psize.c
+BUILTIN_SUPPORT = $(DEFDIR)Makefile $(DEFDIR)ChangeLog $(PSIZE_SOURCE) \
+                 $(BUILTIN_C_SRC)
+
+/**/# Documentation for the shell.
+DOCDIR = $(srcdir)/documentation/
+BASH_TEXINFO = $(DOCDIR)*.texi $(DOCDIR)*.tex \
+               $(DOCDIR)*.dvi $(DOCDIR)Makefile
+BASH_MAN = $(DOCDIR)bash.1
+BASHDOCS = $(BASH_TEXINFO) $(BASH_MAN) INSTALL README RELEASE
+DOCUMENTATION = $(BASHDOCS) $(LIBRARY_DOC)
+
+/**/# Some example files demonstrating use of the shell.
+/* This has to be written funny to avoid looking like a comment starter. */
+EXAMPLES = examples/[a-zA-Z]*
+
+ENDIAN_SUPPORT = endian.c
+#if !defined (HAVE_WAIT_H)
+ENDIAN_HEADER = bash_endian.h
+#else
+ENDIAN_HEADER =
+#endif
+ENDIAN_OUTPUT = endian.aux $(ENDIAN_HEADER)
+
+SIGNAMES_SUPPORT = signames.c
+SIGNAMES_OUTPUT  = signames.aux signames.h
+
+SUPPORT_SRC = $(srcdir)/support/
+SDIR = ./support/
+MKTARFILE = $(SDIR)mktarfile
+SCRIPTS_SUPPORT = $(SUPPORT_SRC)mksysdefs $(SUPPORT_SRC)cppmagic \
+                 $(SUPPORT_SRC)cat-s $(MKTARFILE) $(SUPPORT_SRC)mail-shell \
+                 $(SUPPORT_SRC)inform $(SUPPORT_SRC)/fixdist \
+                 $(SUPPORT_SRC)mklinks $(SUPPORT_SRC)PORTING \
+                 $(SUPPORT_SRC)/clone.bash
+FAQ = $(SUPPORT_SRC)FAQ
+
+TEST_SUITE = ./test-suite/
+TEST_SUITE_SUPPORT = $(TEST_SUITE)[a-zA-Z0-9]* $(SUPPORT_SRC)recho.c
+
+CREATED_SUPPORT = $(ENDIAN_OUTPUT) $(SIGNAMES_OUTPUT) sysdefs.h \
+                 $(SDIR)getcppsyms recho tests/recho tests/printenv
+
+SUPPORT = configure $(ENDIAN_SUPPORT) $(SIGNAMES_SUPPORT) $(SCRIPTS_SUPPORT) \
+         $(BUILTIN_SUPPORT) COPYING Makefile cpp-Makefile ChangeLog \
+         .distribution newversion.c $(EXAMPLES) $(SUPPORT_SRC)bash.xbm \
+         $(FAQ) $(SUPPORT_SRC)getcppsyms.c $(TEST_SUITE_SUPPORT)
+
+/**/# BAGGAGE consists of things that you want to keep with the shell for some
+/**/# reason, but do not actually use; old source code, etc.
+BAGGAGE =
+
+/**/# Things that the world at large needs.
+THINGS_TO_TAR = $(SOURCES) $(LIBRARY_TAR) $(BASHDOCS) $(SUPPORT) $(BAGGAGE)
+
+/**/# Keep GNU Make from exporting the entire environment for small machines.
+.NOEXPORT:
+
+.made: $(Program) bashbug
+       cp .machine .made
+
+$(Program):  .build $(OBJECTS) $(LIBDEP) $(srcdir)/.distribution
+       $(RM) $@
+       $(PURIFY) $(CC) $(LDFLAGS) $(LIBRARY_LDFLAGS) -o $(Program) $(OBJECTS) $(LIBRARIES)
+       ls -l $(Program)
+       size $(Program)
+
+.build:        $(SOURCES) cpp-Makefile newversion.aux
+       if ./newversion.aux -dir $(srcdir) -build; then mv -f newversion.h version.h; fi
+       @echo
+       @echo "   ***************************************************"
+       @echo "   *                                                 *"
+       @echo "   * Making Bash-`cat $(srcdir)/.distribution`.`cat $(srcdir)/.patchlevel` for a $(Machine) running $(OS)"
+       @echo "   *                                                 *"
+       @echo "   ***************************************************"
+       @echo
+       @echo "$(Program) last made for a $(Machine) running $(OS)" >.machine
+
+bashbug: $(SUPPORT_SRC)bashbug.sh cpp-Makefile newversion.aux
+       @sed -e "s:@MACHINE@:$(Machine):" -e "s:@OS@:$(OS):" \
+            -e "s:@CFLAGS@:$(CCFLAGS):" -e "s:@CC@:$(CC):" \
+            -e "s:@RELEASE@:`cat $(srcdir)/.distribution`:" \
+            -e "s:@PATCHLEVEL@:`cat $(srcdir)/.patchlevel`:" \
+            $(SUPPORT_SRC)bashbug.sh > $@
+       @chmod a+rx bashbug
+
+version.h:     newversion.aux
+       if ./newversion.aux -dir $(srcdir) -build; then mv -f newversion.h version.h; fi
+
+y.tab.c: parser-built
+y.tab.h: parser-built
+parser-built:  parse.y parser.h command.h stdc.h input.h
+       $(RM) $@
+       -if test -f y.tab.h; then mv -f y.tab.h old-y.tab.h; fi
+       @echo expect 66 shift/reduce conflicts
+       $(BISON) -d $(srcdir)/parse.y
+       -if cmp -s old-y.tab.h y.tab.h; then mv old-y.tab.h y.tab.h; fi
+       touch $@
+
+#if defined (READLINE) && defined (HAVE_READLINE_SOURCE)
+$(READLINE_LIBRARY): $(READLINE_SOURCE)
+       build_lib_in_dir ($(RL_LIBDIR), libreadline.a, srcdir=$(RL_ABSSRC), $(RL_ABSSRC)Makefile)
+#endif /* READLINE && HAVE_READLINE_SOURCE */
+
+#if defined (HISTORY) && defined (HAVE_HISTORY_SOURCE) && !defined (READLINE)
+$(HISTORY_LIBRARY): $(HISTORY_SOURCE)
+       build_lib_in_dir ($(HIST_LIBDIR), libhistory.a, srcdir=$(HIST_ABSSRC), $(HIST_ABSSRC)Makefile)
+#endif /* HISTORY && HAVE_HISTORY_SOURCE && !READLINE */
+
+#if defined (HAVE_TERMCAP_SOURCE)
+$(TERMCAP_LIBRARY): $(TERMCAP_SOURCE)
+       build_lib_in_dir ($(TERM_LIBDIR), libtermcap.a, srcdir=$(TERM_ABSSRC), $(TERM_ABSSRC)Makefile)
+#endif /* HAVE_TERMCAP_SOURCE */
+
+#if defined (USE_GLOB_LIBRARY)
+$(GLOB_LIBRARY): $(GLOB_SOURCE)
+       build_lib_in_dir ($(GLOB_LIBDIR), libglob.a, srcdir=$(GLOB_ABSSRC), $(GLOB_ABSSRC)Makefile)
+#endif /* USE_GLOB_LIBRARY */
+
+#if defined (HAVE_TILDE_SOURCE)
+$(TILDE_LIBRARY): $(TILDE_SOURCE)
+       build_lib_in_dir ($(TILDE_LIBDIR), libtilde.a, srcdir=$(TILDE_ABSSRC), $(TILDE_ABSSRC)Makefile)
+#endif /* HAVE_TILDE_SOURCE */
+
+#if defined (USE_GNU_MALLOC) && defined (USE_GNU_MALLOC_LIBRARY)
+$(MALLOC_LIBRARY): $(MALLOC_SOURCE)
+       build_lib_in_dir ($(MALLOC_LIBDIR), libmalloc.a, srcdir=$(MALLOC_ABSSRC), $(MALLOC_ABSSRC)Makefile)
+#endif /* USE_GNU_MALLOC && USE_GNU_MALLOC_LIBRARY */
+
+version.o: version.c version.h
+
+shell.o: shell.c shell.h flags.h shell.c posixstat.h filecntl.h stdc.h $(ENDIAN_HEADER) parser.h
+       $(RM) $@
+       $(CC) $(CFG_FLAGS) $(CCFLAGS) $(CPPFLAGS) -c $(srcdir)/shell.c
+
+#if !defined (HAVE_WAIT_H)
+$(ENDIAN_HEADER):     endian.aux
+       $(RM) $@
+       ./endian.aux $@
+#endif
+
+signames.h:   signames.aux
+       $(RM) $@
+       ./signames.aux $@
+
+variables.o:  variables.c shell.h hash.h flags.h variables.h
+               $(RM) $@
+               $(CC) -c $(CCFLAGS) $(HOSTTYPE_DECL) $(CPPFLAGS) $(srcdir)/variables.c
+
+builtins/libbuiltins.a: $(BUILTIN_OBJS) config.h memalloc.h
+       build_builtins (libbuiltins.a)
+
+#if 0
+/* This is a nice idea, but it does not work right, and the syntax is
+   not universally available. */
+$(BUILTIN_OBJS):       $(BUILTIN_DEFS)
+       build_builtins ($(@F))
+#endif
+
+builtins/common.o:     $(BUILTIN_SRCDIR)common.c
+       build_builtins (common.o)
+builtins/bashgetopt.o: $(BUILTIN_SRCDIR)bashgetopt.c
+       build_builtins (bashgetopt.o)
+
+builtins/builtext.h: builtins/libbuiltins.a
+
+/* Dependencies for the main bash source. */
+copy_cmd.o: shell.h command.h stdc.h hash.h
+copy_cmd.o: general.h variables.h config.h memalloc.h quit.h
+copy_cmd.o: dispose_cmd.h make_cmd.h subst.h externs.h
+dispose_cmd.o: shell.h command.h stdc.h
+dispose_cmd.o: general.h variables.h config.h memalloc.h quit.h
+dispose_cmd.o: dispose_cmd.h make_cmd.h subst.h externs.h
+error.o: error.h
+execute_cmd.o: shell.h command.h stdc.h y.tab.h posixstat.h flags.h jobs.h
+execute_cmd.o: general.h variables.h config.h memalloc.h quit.h hash.h
+execute_cmd.o: unwind_prot.h siglist.h builtins/builtext.h 
+execute_cmd.o: dispose_cmd.h make_cmd.h subst.h externs.h bashtypes.h
+expr.o: shell.h command.h stdc.h hash.h
+expr.o: general.h variables.h config.h memalloc.h quit.h
+expr.o: dispose_cmd.h make_cmd.h subst.h externs.h
+flags.o: flags.h stdc.h config.h memalloc.h general.h quit.h
+general.o: shell.h command.h stdc.h maxpath.h
+general.o: general.h variables.h config.h memalloc.h quit.h machines.h
+general.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+hash.o: shell.h command.h stdc.h hash.h
+hash.o: general.h variables.h config.h memalloc.h quit.h
+hash.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+jobs.o: shell.h command.h stdc.h hash.h trap.h jobs.h siglist.h
+jobs.o: general.h variables.h config.h memalloc.h quit.h
+jobs.o: dispose_cmd.h make_cmd.h subst.h externs.h builtins/builtext.h
+mailcheck.o: posixstat.h maxpath.h variables.h
+mailcheck.o: hash.h quit.h
+make_cmd.o: shell.h command.h stdc.h flags.h input.h bashtypes.h
+make_cmd.o: general.h variables.h config.h memalloc.h quit.h
+make_cmd.o: dispose_cmd.h make_cmd.h subst.h externs.h
+y.tab.o: shell.h command.h stdc.h flags.h maxpath.h alias.h
+y.tab.o: general.h variables.h config.h memalloc.h quit.h
+y.tab.o: dispose_cmd.h make_cmd.h subst.h externs.h bashtypes.h
+print_cmd.o: shell.h command.h stdc.h y.tab.h
+print_cmd.o: general.h variables.h config.h memalloc.h quit.h
+print_cmd.o: dispose_cmd.h make_cmd.h subst.h externs.h
+shell.o: shell.h command.h stdc.h flags.h machines.h
+shell.o: general.h variables.h config.h memalloc.h quit.h
+shell.o: dispose_cmd.h make_cmd.h subst.h externs.h
+shell.o: posixstat.h filecntl.h jobs.h input.h
+subst.o: shell.h command.h stdc.h flags.h jobs.h siglist.h bashtypes.h
+subst.o: general.h variables.h config.h memalloc.h quit.h
+subst.o: dispose_cmd.h make_cmd.h subst.h externs.h execute_cmd.h
+test.o: posixstat.h
+trap.o: trap.h shell.h command.h stdc.h hash.h unwind_prot.h signames.h
+trap.o: general.h variables.h config.h memalloc.h quit.h
+trap.o: dispose_cmd.h make_cmd.h subst.h externs.h
+unwind_prot.o: config.h memalloc.h general.h unwind_prot.h
+variables.o: shell.h command.h stdc.h hash.h flags.h
+variables.o: config.h memalloc.h general.h variables.h quit.h
+variables.o: execute_cmd.h dispose_cmd.h make_cmd.h subst.h externs.h
+version.o: version.h .build
+
+alias.o: ansi_stdlib.h
+bashline.o: ansi_stdlib.h
+variables.o: ansi_stdlib.h
+shell.o: ansi_stdlib.h
+error.o: ansi_stdlib.h
+hash.o: ansi_stdlib.h
+signames.o: ansi_stdlib.h
+expr.o: ansi_stdlib.h
+general.o: ansi_stdlib.h
+input.o: ansi_stdlib.h
+
+#if !defined (JOB_CONTROL)
+jobs.o: nojobs.c
+#endif /* !JOB_CONTROL */
+
+#if defined (BRACE_EXPANSION)
+braces.o: general.h shell.h variables.h quit.h config.h memalloc.h
+braces.o: dispose_cmd.h make_cmd.h subst.h externs.h
+braces.o: maxpath.h unwind_prot.h command.h stdc.h
+#  if defined (READLINE)
+bracecomp.o: bracecomp.c
+bracecomp.o: shell.h command.h hash.h builtins.h general.h variables.h
+bracecomp.o: quit.h alias.h
+bracecomp.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+#    if defined (HAVE_READLINE_SOURCE)
+bracecomp.o: $(RL_LIBSRC)readline.h
+#    endif /* HAVE_READLINE_SOURCE */
+#  endif /* READLINE */
+#endif /* BRACE_EXPANSION */
+
+#if defined (READLINE)
+bashline.o: shell.h command.h stdc.h hash.h builtins.h execute_cmd.h
+bashline.o: general.h variables.h config.h memalloc.h quit.h alias.h
+bashline.o: dispose_cmd.h make_cmd.h subst.h externs.h
+#endif /* READLINE */
+
+/* Dependencies which rely on the user using the source to READLINE. */
+#if defined (READLINE) && defined (HAVE_READLINE_SOURCE)
+bashline.o: $(RL_LIBSRC)chardefs.h $(RL_LIBSRC)readline.h $(RL_LIBSRC)keymaps.h
+y.tab.o: $(RL_LIBSRC)keymaps.h $(RL_LIBSRC)chardefs.h $(RL_LIBSRC)readline.h
+#endif /* READLINE && HAVE_READLINE_SOURCE */
+
+#if defined (HISTORY) && defined (HAVE_HISTORY_SOURCE)
+subst.o: $(HIST_LIBSRC)history.h
+bashline.o: $(HIST_LIBSRC)history.h
+y.tab.o: $(HIST_LIBSRC)history.h
+#endif /* HISTORY && HAVE_HISTORY_SOURCE */
+
+#if defined (USE_GLOB_LIBRARY)
+subst.o: $(GLOB_LIBSRC)fnmatch.h
+execute_cmd.o: $(GLOB_LIBSRC)fnmatch.h
+#endif /* USE_GLOB_LIBRARY */
+
+#if defined (HAVE_TILDE_SOURCE)
+execute_cmd.o: $(TILDE_LIBSRC)tilde.h
+general.o: $(TILDE_LIBSRC)tilde.h
+mailcheck.o: $(TILDE_LIBSRC)tilde.h
+shell.o: $(TILDE_LIBSRC)tilde.h
+subst.o: $(TILDE_LIBSRC)tilde.h
+variables.o: $(TILDE_LIBSRC)tilde.h
+#endif /* HAVE_TILDE_SOURCE */
+
+/* Dependencies for the shell builtins. */
+builtins/common.o: shell.h command.h config.h memalloc.h general.h error.h
+builtins/common.o: variables.h input.h $(DEFDIR)hashcom.h siglist.h
+builtins/common.o: quit.h unwind_prot.h maxpath.h jobs.h builtins.h
+builtins/common.o: dispose_cmd.h make_cmd.h subst.h externs.h bashhist.h
+builtins/common.o: execute_cmd.h stdc.h
+builtins/alias.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/alias.o: quit.h builtins/common.h
+builtins/alias.o: shell.h command.h stdc.h unwind_prot.h variables.h 
+builtins/alias.o: dispose_cmd.h make_cmd.h subst.h externs.h
+builtins/bind.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/bind.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/bind.o: shell.h unwind_prot.h variables.h quit.h
+builtins/bind.o: $(DEFDIR)bashgetopt.h
+builtins/break.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/break.o: shell.h unwind_prot.h variables.h quit.h
+builtins/break.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/builtin.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/builtin.o: quit.h $(DEFDIR)common.h
+builtins/builtin.o: shell.h unwind_prot.h variables.h 
+builtins/builtin.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/cd.o: command.h config.h memalloc.h error.h general.h maxpath.h quit.h 
+builtins/cd.o: shell.h unwind_prot.h variables.h $(DEFDIR)common.h
+builtins/cd.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/command.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/command.o: quit.h $(DEFDIR)bashgetopt.h
+builtins/command.o: shell.h unwind_prot.h variables.h 
+builtins/command.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/declare.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/declare.o: shell.h unwind_prot.h variables.h quit.h
+builtins/declare.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/echo.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/echo.o: shell.h unwind_prot.h variables.h quit.h
+builtins/echo.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/enable.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/enable.o: shell.h unwind_prot.h variables.h quit.h
+builtins/enable.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/eval.o: command.h config.h memalloc.h error.h general.h maxpath.h quit.h 
+builtins/eval.o: shell.h unwind_prot.h variables.h 
+builtins/eval.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/exec.o: command.h config.h memalloc.h error.h general.h maxpath.h quit.h 
+builtins/exec.o: shell.h unwind_prot.h variables.h $(DEFDIR)common.h stdc.h
+builtins/exec.o: dispose_cmd.h make_cmd.h subst.h externs.h execute_cmd.h
+builtins/exec.o: flags.h
+builtins/exit.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/exit.o: shell.h unwind_prot.h variables.h quit.h
+builtins/exit.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/fc.o: builtins.h command.h stdc.h 
+builtins/fc.o: command.h config.h memalloc.h error.h general.h maxpath.h quit.h 
+builtins/fc.o: flags.h unwind_prot.h variables.h shell.h 
+builtins/fc.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/fc.o: $(DEFDIR)bashgetopt.h bashhist.h
+builtins/fg_bg.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/fg_bg.o: shell.h unwind_prot.h variables.h quit.h
+builtins/fg_bg.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/getopts.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/getopts.o: shell.h unwind_prot.h variables.h quit.h 
+builtins/getopts.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/hash.o: builtins.h command.h execute_cmd.h stdc.h
+builtins/hash.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/hash.o: shell.h unwind_prot.h variables.h $(DEFDIR)common.h quit.h 
+builtins/help.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/help.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/help.o: shell.h unwind_prot.h variables.h quit.h
+builtins/history.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/history.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/history.o: filecntl.h shell.h unwind_prot.h variables.h 
+builtins/history.o: bashhist.h
+builtins/inlib.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/inlib.o: shell.h unwind_prot.h variables.h quit.h 
+builtins/inlib.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/jobs.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/jobs.o: quit.h $(DEFDIR)bashgetopt.h
+builtins/jobs.o: shell.h unwind_prot.h variables.h 
+builtins/jobs.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/kill.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/kill.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/kill.o: shell.h trap.h unwind_prot.h variables.h 
+builtins/let.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/let.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/let.o: shell.h unwind_prot.h variables.h 
+builtins/read.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/read.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/read.o: shell.h unwind_prot.h variables.h 
+builtins/return.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/return.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/return.o: shell.h unwind_prot.h variables.h 
+builtins/set.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/set.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h
+builtins/set.o: shell.h unwind_prot.h variables.h flags.h stdc.h
+builtins/setattr.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/setattr.o: quit.h $(DEFDIR)common.h $(DEFDIR)bashgetopt.h
+builtins/setattr.o: shell.h unwind_prot.h variables.h 
+builtins/setattr.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/shift.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/shift.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/shift.o: shell.h unwind_prot.h variables.h 
+builtins/shift.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/source.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/source.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/source.o: shell.h unwind_prot.h variables.h 
+builtins/suspend.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/suspend.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/suspend.o: shell.h unwind_prot.h variables.h 
+builtins/test.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/test.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/test.o: shell.h unwind_prot.h variables.h 
+builtins/times.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/times.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/times.o: shell.h unwind_prot.h variables.h 
+builtins/trap.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/trap.o: quit.h $(DEFDIR)common.h
+builtins/trap.o: shell.h unwind_prot.h variables.h 
+builtins/trap.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/type.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/type.o: quit.h $(DEFDIR)common.h
+builtins/type.o: shell.h unwind_prot.h variables.h execute_cmd.h
+builtins/type.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/ulimit.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/ulimit.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/ulimit.o: shell.h unwind_prot.h variables.h 
+builtins/umask.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/umask.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/umask.o: shell.h unwind_prot.h variables.h 
+builtins/wait.o: command.h config.h memalloc.h error.h general.h maxpath.h
+builtins/wait.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h
+builtins/wait.o: shell.h unwind_prot.h variables.h
+
+builtins/bashgetopt.o: bashansi.h ansi_stdlib.h
+builtins/mkbuiltins.o: bashansi.h ansi_stdlib.h
+builtins/fc.o: bashansi.h ansi_stdlib.h
+
+#if defined (READLINE) && defined (HAVE_READLINE_SOURCE)
+builtins/bind.o: $(RL_LIBSRC)chardefs.h $(RL_LIBSRC)readline.h $(RL_LIBSRC)keymaps.h
+#endif /* READLINE && HAVE_READLINE_SOURCE */
+
+#if defined (HISTORY) && defined (HAVE_HISTORY_SOURCE)
+builtins/bind.o: $(HIST_LIBSRC)history.h
+builtins/fc.o: $(HIST_LIBSRC)history.h
+builtins/history.o: $(HIST_LIBSRC)history.h
+#endif /* HISTORY && HAVE_HISTORY_SOURCE */
+
+#if defined (HAVE_TILDE_SOURCE)
+builtins/common.o: $(TILDE_LIBSRC)tilde.h
+builtins/cd.o: $(TILDE_LIBSRC)tilde.h 
+#endif /* HAVE_TILDE_SOURCE */
+
+builtins/alias.o: builtins/alias.def
+builtins/bind.o: builtins/bind.def
+builtins/break.o: builtins/break.def
+builtins/builtin.o: builtins/builtin.def
+builtins/cd.o: builtins/cd.def
+builtins/colon.o: builtins/colon.def
+builtins/command.o: builtins/command.def
+builtins/declare.o: builtins/declare.def
+builtins/echo.o: builtins/echo.def
+builtins/enable.o: builtins/enable.def
+builtins/eval.o: builtins/eval.def
+builtins/exec.o: builtins/exec.def
+builtins/exit.o: builtins/exit.def
+builtins/fc.o: builtins/fc.def
+builtins/fg_bg.o: builtins/fg_bg.def
+builtins/getopts.o: builtins/getopts.def
+builtins/hash.o: builtins/hash.def
+builtins/help.o: builtins/help.def
+builtins/histctl.o: builtins/histctl.def
+builtins/history.o: builtins/history.def
+builtins/inlib.o: builtins/inlib.def
+builtins/jobs.o: builtins/jobs.def
+builtins/kill.o: builtins/kill.def
+builtins/let.o: builtins/let.def
+builtins/read.o: builtins/read.def
+builtins/reserved.o: builtins/reserved.def
+builtins/return.o: builtins/return.def
+builtins/set.o: builtins/set.def
+builtins/setattr.o: builtins/setattr.def
+builtins/shift.o: builtins/shift.def
+builtins/source.o: builtins/source.def
+builtins/suspend.o: builtins/suspend.def
+builtins/test.o: builtins/test.def
+builtins/times.o: builtins/times.def
+builtins/trap.o: builtins/trap.def
+builtins/type.o: builtins/type.def
+builtins/ulimit.o: builtins/ulimit.def
+builtins/umask.o: builtins/umask.def
+builtins/wait.o: builtins/wait.def
+
+$(Program).tar: $(THINGS_TO_TAR) .distribution
+       @$(MKTARFILE) $(Program) `cat .distribution` $(THINGS_TO_TAR)
+
+$(Program).tar$(COMPRESS_EXT): $(Program).tar
+               $(COMPRESS) < $(Program).tar > $@
+
+clone:         $(THINGS_TO_TAR)
+               @$(MKTARFILE) +notar $(Machine) $(OS) $(THINGS_TO_TAR)
+
+installdirs:
+               @${SHELL} $(SUPPORT_SRC)mkdirs $(bindir)
+               @${SHELL} $(SUPPORT_SRC)mkdirs $(mandir) $(man3dir)
+               @${SHELL} $(SUPPORT_SRC)mkdirs $(infodir)
+
+install:       .made installdirs documentation
+               -if [ -f $(bindir)/$(Program) ]; then \
+                 rm -f $(bindir)/$(Program).old ;\
+                 ln $(bindir)/$(Program) $(bindir)/$(Program).old; \
+               fi
+               $(INSTALL_PROGRAM) $(Program) $(bindir)/$(Program)
+               -if [ -f $(bindir)/bashbug ]; \
+                 then mv $(bindir)/bashbug $(bindir)/bashbug.old; \
+               fi
+               $(INSTALL_PROGRAM) bashbug $(bindir)/bashbug
+               ( cd $(DOCDIR) ; $(MAKE) $(MFLAGS) mandir=$(mandir) \
+                       man3dir=$(man3dir) infodir=$(infodir) $@ )
+
+uninstall:     .made
+               $(RM) $(bindir)/$(Program) installed-$(Program) $(bindir)/bashbug
+               ( cd $(DOCDIR) ; $(MAKE) $(MFLAGS) mandir=$(mandir) man3dir=$(man3dir) infodir=$(infodir) $@ )
+               
+.distribution:
+               ./newversion.aux -dir $(srcdir) -dist `$(Program) -c 'echo $$BASH_VERSION'`
+
+distribution:  $(Program) $(Program).tar$(COMPRESS_EXT) .distribution
+               @echo cp $(Program).tar$(COMPRESS_EXT) \
+                       $(Program)-`cat .distribution`.tar$(COMPRESS_EXT)
+               @cp $(Program).tar$(COMPRESS_EXT) \
+                       $(Program)-`cat .distribution`.tar$(COMPRESS_EXT)
+
+mailable:      distribution
+               /bin/rm -rf uuencoded
+               mkdir uuencoded
+               $(SHELL) -c 'f=$(Program)-`cat .distribution`.tar.Z;uuencode $$f $$f | split -800 - uuencoded/$$f.uu.'
+
+newversion.aux:        newversion.c
+               $(CC) $(CCFLAGS) -o $@ $(srcdir)/newversion.c
+
+newversion:    newversion.aux
+               $(RM) .build
+               ./newversion.aux -dir $(srcdir) -dist
+               mv -f newversion.h version.h
+               $(MAKE) -f $(srcdir)/Makefile $(MFLAGS) srcdir=$(srcdir)
+
+documentation:  force
+               (cd $(DOCDIR); $(MAKE) $(MFLAGS))
+
+force:
+
+tags:          $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+               etags $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+
+TAGS:          $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+               ctags -x $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE) > $@
+
+basic-clean:
+               $(RM) $(OBJECTS) $(Program) bashbug ansi-Makefile *.aux
+               $(RM) .build .made .machine version.h
+               $(RM) $(CREATED_SUPPORT)
+               $(RM) tags TAGS
+
+mostlyclean:
+               $(RM) $(OBJECTS) $(Program) bashbug
+               $(RM) .build .made .machine version.h
+               $(RM) tags TAGS
+               (cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+               (cd builtins && $(MAKE) $(MFLAGS) $@ )
+               $(CLEAN_READLINE) ;
+               $(CLEAN_HISTORY) ;
+               $(CLEAN_TERMCAP) ;
+               $(CLEAN_GLOB) ;
+               $(CLEAN_TILDE) ;
+               $(CLEAN_MALLOC) ;
+
+distclean clean:       basic-clean
+               (cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+               (cd builtins && $(MAKE) $(MFLAGS) $@ )
+               $(CLEAN_READLINE) ;
+               $(CLEAN_HISTORY) ;
+               $(CLEAN_TERMCAP) ;
+               $(CLEAN_GLOB) ;
+               $(CLEAN_TILDE) ;
+               $(CLEAN_MALLOC) ;
+               $(RM) bash-Makefile
+
+realclean maintainer-clean:    basic-clean
+               $(RM) y.tab.c y.tab.h parser-built
+               (cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+               (cd builtins && $(MAKE) $(MFLAGS) $@ )
+               $(CLEAN_READLINE) ;
+               $(CLEAN_HISTORY) ;
+               $(CLEAN_TERMCAP) ;
+               $(CLEAN_GLOB) ;
+               $(CLEAN_TILDE) ;
+               $(CLEAN_MALLOC) ;
+               $(RM) bash-Makefile
+
+recho:         $(SUPPORT_SRC)recho.c
+       @$(CC) -o $@ $(SUPPORT_SRC)recho.c
+
+tests check:           force $(Program) recho
+       @cp recho $(SUPPORT_SRC)printenv tests
+       ( cd tests ; sh run-all )
+
+/**/# Here is a convenient rule when you arrive at a new site and wish to
+/**/# install bash on several different architectures.  It creates a new
+/**/# directory to hold the results of compilation.  The directory is
+/**/# named Machine-OS.
+architecture: $(Machine)-$(OS)/$(Program)
+
+$(Machine)-$(OS):
+       -mkdir $(Machine)-$(OS)
+
+$(Machine)-$(OS)/$(Program): $(Machine)-$(OS) $(Program)
+       mv $(Program) $(Machine)-$(OS)
+       mv sysdefs.h $(Machine)-$(OS)
+       mv $(SDIR)getcppsyms $(Machine)-$(OS)
+       $(MAKE) $(MFLAGS) clean
+
+DEFINES: config.h memalloc.h cpp-Makefile sysdefs.h
+       echo $(CCFLAGS) $(CPPFLAGS) >DEFINES
diff --git a/dispose_cmd.c b/dispose_cmd.c
new file mode 100644 (file)
index 0000000..f420fe1
--- /dev/null
@@ -0,0 +1,207 @@
+/* dispose_command.c -- dispose of a COMMAND structure. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "shell.h"
+
+/* Dispose of the command structure passed. */
+void
+dispose_command (command)
+     COMMAND *command;
+{
+  if (!command) return;
+
+  if (command->redirects)
+    dispose_redirects (command->redirects);
+
+  switch (command->type)
+    {
+    case cm_for:
+      {
+       register FOR_COM *c = command->value.For;
+       dispose_word (c->name);
+       dispose_words (c->map_list);
+       dispose_command (c->action);
+       free (c);
+       break;
+      }
+
+#if defined (SELECT_COMMAND)
+    case cm_select:
+      {
+       register SELECT_COM *c = command->value.Select;
+       dispose_word (c->name);
+       dispose_words (c->map_list);
+       dispose_command (c->action);
+       free (c);
+       break;
+      }
+#endif
+    
+    case cm_group:
+      {
+       dispose_command (command->value.Group->command);
+       free (command->value.Group);
+       break;
+      }
+
+    case cm_case:
+      {
+       register CASE_COM *c = command->value.Case;
+       PATTERN_LIST *t, *p = c->clauses;
+
+       dispose_word (c->word);
+
+       while (p)
+         {
+           dispose_words (p->patterns);
+           dispose_command (p->action);
+           t = p;
+           p = p->next;
+           free (t);
+         }
+       free (c);
+       break;
+      }
+
+    case cm_until:
+    case cm_while:
+      {
+       register WHILE_COM *c = command->value.While;
+
+       dispose_command (c->test);
+       dispose_command (c->action);
+       free (c);
+       break;
+      }
+
+    case cm_if:
+      {
+       register IF_COM *c = command->value.If;
+       dispose_command (c->test);
+       dispose_command (c->true_case);
+       dispose_command (c->false_case);
+       free (c);
+       break;
+      }
+
+    case cm_simple:
+      {
+       register SIMPLE_COM *c = command->value.Simple;
+       dispose_words (c->words);
+       dispose_redirects (c->redirects);
+       free (c);
+       break;
+      }
+
+    case cm_connection:
+      {
+       register CONNECTION *c = command->value.Connection;
+       dispose_command (c->first);
+       dispose_command (c->second);
+       free (c);
+       break;
+      }
+
+    case cm_function_def:
+      {
+       register FUNCTION_DEF *c = command->value.Function_def;
+       dispose_word (c->name);
+       dispose_command (c->command);
+       free (c);
+       break;
+      }
+
+    default:
+      report_error ("Attempt to free unknown command type `%d'.\n", command->type);
+      break;
+    }
+  free (command);
+}
+
+/* How to free a WORD_DESC. */
+void
+dispose_word (word)
+     WORD_DESC *word;
+{
+  if (word->word)
+    free (word->word);
+  free (word);
+}
+
+/* How to get rid of a linked list of words.  A WORD_LIST. */
+void
+dispose_words (list)
+     WORD_LIST *list;
+{
+  WORD_LIST *t;
+  while (list)
+    {
+      t = list;
+      list = list->next;
+      dispose_word (t->word);
+      free (t);
+    }
+}
+
+/* How to dispose of an array of pointers to char. */
+void
+dispose_word_array (array)
+     char **array;
+{
+  register int count;
+
+  for (count = 0; array[count]; count++)
+    free (array[count]);
+
+  free (array);
+}
+
+/* How to dispose of an list of redirections.  A REDIRECT. */
+void
+dispose_redirects (list)
+     REDIRECT *list;
+{
+  register REDIRECT *t;
+
+  while (list)
+    {
+      t = list;
+      list = list->next;
+      switch (t->instruction)
+       {
+       case r_reading_until:
+       case r_deblank_reading_until:
+         free (t->here_doc_eof);
+         /* ... */
+       case r_output_direction:
+       case r_input_direction:
+       case r_inputa_direction:
+       case r_appending_to:
+       case r_err_and_out:
+       case r_input_output:
+       case r_output_force:
+       case r_duplicating_input_word:
+       case r_duplicating_output_word:
+         dispose_word (t->redirectee.filename);
+         break;
+       }
+      free (t);
+    }
+}
diff --git a/dispose_cmd.h b/dispose_cmd.h
new file mode 100644 (file)
index 0000000..11166dd
--- /dev/null
@@ -0,0 +1,32 @@
+/* dispose_cmd.h -- Functions appearing in dispose_cmd.c. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_DISPOSE_CMD_H_)
+#define _DISPOSE_CMD_H_
+
+#include "stdc.h"
+
+extern void dispose_command __P((COMMAND *));
+extern void dispose_word __P((WORD_DESC *));
+extern void dispose_words __P((WORD_LIST *));
+extern void dispose_word_array __P((char **));
+extern void dispose_redirects __P((REDIRECT *));
+
+#endif /* !_DISPOSE_CMD_H_ */
diff --git a/documentation/FAQ b/documentation/FAQ
new file mode 100644 (file)
index 0000000..c44bc47
--- /dev/null
@@ -0,0 +1,795 @@
+This is the Bash FAQ, version 1.2, for Bash version 1.14.6.
+
+This document contains a set of frequently-asked questions concerning
+Bash, the GNU Bourne-Again Shell.  Bash is a freely-available command
+interpreter with advanced features for both interactive use and shell
+programming.
+
+Another good source of basic information about shells is the collection
+of FAQ articles periodically posted to comp.unix.shell.
+
+Questions and comments concerning this document should be set to
+chet@po.cwru.edu.
+
+Contents:
+1)  What is it?
+2)  What's the latest version?
+3)  Where can I get it?
+4)  What's the `Posix 1003.2 standard'?
+5)  On what machines will bash run?
+6)  How does bash differ from sh, the Bourne shell?
+7)  How does bash differ from the Korn shell?
+8)  What is the bash `posix mode'?
+9)  How can I build bash with gcc?
+10) Why does bash run a different version of `command' than
+    `which command' says it will?
+11) How can I make my csh aliases work when I convert to bash?
+12) Now that I've converted from ksh to bash, are there equivalents to
+    ksh features like autoloaded functions and the `whence' command?
+13) Why is the bash builtin `test' slightly different from /bin/test?
+14) Why does bash sometimes say `Broken pipe'?
+15) How can I get bash to read and display eight-bit characters?
+16) Why can't I use command line editing in my `cmdtool'?
+17) How do I write a function `x' to replace builtin command `x', but
+    still invoke the command from within the function?
+18) When I have terminal escape sequences in my prompt, why does bash
+    wrap lines at the wrong column?
+19) I built bash on Solaris 2.  Why do globbing expansions and filename
+    completion chop off the first few characters of each filename?
+20) Why doesn't bash treat brace expansions exactly like csh?
+21) Why does bash dump core after I interrupt username completion?
+22) I'm running SVR4.2.  Why is the line erased every time I type `@'?
+23) How can I find the value of a shell variable whose name is the value
+    of another shell variable?
+24) If I pipe the output of a command into `read variable', why doesn't
+    the output show up in $variable when the read command finishes?
+25) I just changed my shell to bash, and now I can't FTP into my machine.
+    Why not?
+26) I have a bunch of shell scripts that use backslash-escaped characters
+    in arguments to `echo'.  Bash doesn't interpret these characters.  Why
+    not, and how can I make it understand them?
+27) Why doesn't bash have csh variable modifiers?
+28) Why does bash report syntax errors when my C News scripts use a
+    redirection before a subshell command?
+29) How do I report bugs in bash, and where should I look for fixes and
+    advice?
+30) What kind of bash documentation is there?
+31) What's coming in future versions?
+32) What's on the bash `wish list'?
+33) When will the next release appear?
+
+1)  What is it?
+
+Bash is a Unix command interpreter (shell).  It is an implementation of
+the Posix 1003.2 shell standard, and resembles the Korn and System V
+shells.
+
+Bash contains a number of enhancements over those shells, both
+for interactive use and shell programming.  Features geared
+toward interactive use include command line editing, command
+history, job control, aliases, and prompt expansion.  Programming
+features include additional variable expansions, shell
+arithmetic, and a number of variables and options to control
+shell behavior.
+
+Bash was originally written by Brian Fox of the Free Software
+Foundation.  The current developer and maintainer is Chet Ramey
+of Case Western Reserve University.
+
+2)  What's the latest version?
+
+The latest version is 1.14.6, first made available on December 19, 1995.
+
+3)  Where can I get it?
+
+Bash is the GNU project's shell, and so is available from the
+master GNU archive site, prep.ai.mit.edu, and its mirrors.  The
+latest version is also available for FTP from slc2.ins.cwru.edu,
+the maintainer's machine.  The following URLs tell how to get
+version 1.14.6:
+
+ftp://prep.ai.mit.edu/pub/gnu/bash-1.14.6.tar.gz
+ftp://slc2.ins.cwru.edu/pub/dist/bash-1.14.6.tar.gz
+
+4)  What's the `Posix 1003.2 standard'?
+
+POSIX is a name originally coined by Richard Stallman for a
+family of open system standards based on UNIX.  There are a
+number of aspects of UNIX under consideration for
+standardization, from the basic system services at the system
+call and C library level to applications and tools to system
+administration and management.  Each area of standardization is
+assigned to a working group in the 1003 series. 
+
+The POSIX Shell and Utilities standard has been developed by IEEE
+Working Group 1003.2 (POSIX.2).  It concentrates on the command
+interpreter interface and utility programs commonly executed from
+the command line or by other programs.  An initial version of the
+standard has been approved and published by the IEEE, and work is
+currently underway to update it. 
+
+Bash is concerned with the aspects of the shell's behavior
+defined by POSIX.2.  The shell command language has of course
+been standardized, including the basic flow control and program
+execution constructs, I/O redirection and pipelining, argument
+handling, variable expansion, and quoting. 
+
+The `special' builtins, which must be implemented as part of the
+shell to provide the desired functionality, are specified as
+being part of the shell; examples of these are `eval' and
+`export'.  Other utilities appear in the sections of POSIX.2 not
+devoted to the shell which are commonly (and in some cases must
+be) implemented as builtin commands, such as `read' and `test'. 
+POSIX.2 also specifies aspects of the shell's interactive
+behavior as part of the UPE, including job control and command
+line editing.  Only vi-style line editing commands have been
+standardized; emacs editing commands were left out due to
+objections.
+
+5)  On what machines will bash run?
+
+Bash has been ported to nearly every version of UNIX.  All you
+should have to do to build it on a machine for which a port
+exists is to type `make'.  The build process will attempt to
+discover the version of UNIX you have and tailor itself
+accordingly, using a combination of saved definitions in the file
+`machines.h' and a file `sysdefs.h' created by inspecting the
+environment for various things. 
+
+More information appears in the file `INSTALL' in the distribution.
+
+6)  How does bash differ from sh, the Bourne shell?
+
+This is a non-comprehensive list of features that differentiate bash
+from the SVR4 shell.  The bash manual page explains these completely.
+
+Things bash has that sh does not:
+       long invocation options
+       `!' reserved word to invert pipeline return value
+       the select compound command
+       the $(...) form of command substitution
+       the ${#param} parameter value length operator
+       expansions to perform substring removal (${p%[%]w}, ${p#[#]w})
+       variables: BASH, BASH_VERSION, UID, EUID, REPLY, PPID, PWD,
+                  OLDPWD, SHLVL, RANDOM, SECONDS, LINENO, HISTCMD,
+                  HOSTTYPE, OSTYPE, ENV, MAIL_WARNING, PS3, PS4,
+                  HISTSIZE, HISTFILE, HISTFILESIZE, PROMPT_COMMAND,
+                  FCEDIT, FIGNORE, IGNOREEOF, INPUTRC, HISTCONTROL,
+                  command_oriented_history, allow_null_glob_expansion,
+                  glob_dot_filenames, histchars, nolinks, auto_resume,
+                  HOSTFILE, noclobber, TMOUT, no_exit_on_failed_exec,
+                  cdable_vars
+       redirections: <>, &>, >|
+       prompt string special char translation and variable expansion
+       auto-export of modified values of variables in initial environment
+       command search finds functions before builtins
+       bash return builtin will exit a file sourced with `.'
+       builtins: cd -, exec -, echo -e/-E, export -n/-f/-p/name=value,
+                 pwd -P, read -r, readonly -f, trap -l, ulimit -n/-p/-u,
+                 set -b/-m/-o option/-p/-l/-d/-C/-H/-P, unset -f/-v,
+                 umask -S, type -all/-path/-type, suspend -f, kill -s
+       bash reads ~/.bashrc for interactive shells, $ENV for non-interactive
+       bash restricted shell mode is more extensive
+       bash allows functions and variables with the same name
+       brace expansion
+       tilde expansion
+       arithmetic expansion and `let' builtin
+       process substitution
+       aliases and alias/unalias builtins
+       local variables in functions and `local' builtin
+       readline and command-line editing
+       history and history/fc builtins
+       csh-like history expansion
+       other new bash builtins: bind, command, builtin, declare/typeset,
+                                dirs, enable, fc, help, history, logout,
+                                popd, pushd
+       exported functions
+       filename generation when using output redirection (command >a*)
+
+Things sh has that bash does not:
+       uses variable SHACCT to do shell accounting
+       includes `stop' builtin (bash can use alias stop='kill -s STOP')
+       `newgrp' builtin
+       turns on job control if called as `jsh'
+       ulimit attempts to set both soft & hard limits if -S/-H not given
+
+New things in the SVR4.2 sh:
+       internationalization: $LANG, $LC_CTYPE, $LC_MESSAGES, setlocale, etc.
+       $TIMEOUT (like bash $TMOUT)
+       new builtins: mldmode, priv
+       `read' builtin has -r
+       cannot trap SIGALRM or SIGCHLD
+       kill -s is present
+
+Implementation differences:
+       redirection to/from compound commands causes sh to create a subshell
+       bash does not allow unbalanced quotes; sh silently inserts them at EOF
+       bash does not mess with signal 11
+       sh sets (euid, egid) to (uid, gid) if -p not supplied and uid < 100
+       bash splits only the results of expansions on IFS
+       sh does not allow MAILCHECK to be unset (?)
+
+7)  How does bash differ from the Korn shell?
+
+Things bash has or uses that ksh does not:
+       long invocation options
+       `!' reserved word
+       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
+       variables: BASH, BASH_VERSION, UID, EUID, SHLVL, HISTCMD, HOSTTYPE,
+                  OSTYPE, MAIL_WARNING, HISTFILESIZE, OPTERR,
+                  PROMPT_COMMAND, IGNOREEOF, FIGNORE, INPUTRC, HISTCONTROL,
+                  notify, command_oriented_history, glob_dot_filenames,
+                  allow_null_glob_expansion, histchars, nolinks, HOSTFILE,
+                  noclobber, auto_resume, no_exit_on_failed_exec, cdable_vars
+       prompt expansion with backslash escapes and command substitution
+       redirection: &> (stdout and stderr)
+       more extensive and extensible editing and completion
+       builtins: bind, builtin, command, declare, dirs, echo -e/-E, enable,
+                 exec -, fc -s, export -n/-f/-p, hash, help, history,
+                 jobs -x, kill -s, local, logout, popd, pushd,
+                 readonly -n/-f/-p, set -o braceexpand/-o histexpand/
+                 -o interactive-comments/-o notify/-o physical/-o posix/
+                 -l/-d/-C/-b/-H/-P, suspend, trap -l, type, ulimit -u,
+                 umask -S
+       $[...] synonym for $((...))
+       `!' csh-style history expansion
+
+Things ksh has or uses that bash does not:
+       new version of test: [[...]]
+       ((...)) equivalent to let "..."
+       time keyword to let pipelines be timed
+       tracked aliases
+       $(<file)        
+       one-dimensional arrays and appropriate expansions
+       variables: ERRNO, FPATH, COLUMNS, LINES, EDITOR, VISUAL
+       extended pattern matching with egrep-style pattern lists
+       co-processes (|&, >&p, <&p)
+       weirdly-scoped functions
+       typeset +f to list all function names without definitions
+       text of command history kept in a file, not memory
+       builtins: alias -x, cd old new, fc -e -, newgrp, print,
+                 read -p/-s/u/var?prompt, set -A/-o gmacs/-o keyword/
+                 -o bgnice/-o markdirs/-o nolog/-o trackall/-o viraw/-s,
+                 typeset -H/-L/-R/-A/-ft/-fu/-fx/-l/-u/-t, whence
+
+Implementation differences:
+       ksh runs last command of a pipeline in parent shell context
+       ksh ulimit sets hard and soft limits by default
+       bash has brace expansion by default
+       bash has fixed startup file for all interactive shells; ksh reads $ENV
+       bash has exported functions
+       bash command search finds functions before builtins
+
+8)  What is the bash `posix mode'?
+
+Although bash is an implementation of the Posix.2 shell
+specification, there are areas where the bash default behavior
+differs from that spec.  The bash `posix mode' changes the bash
+behavior in these areas so that it obeys the spec more closely. 
+
+Posix mode is entered by starting bash with the -posix 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. 
+
+9) How can I build bash with gcc? 
+
+Type
+       make CC=gcc CPPNAME='$(CC) -E'
+
+10) Why does bash run a different version of `command' than
+    `which command' says it will?
+
+`which' is actually a csh script that assumes you're running csh. 
+It reads the csh startup files from your home directory and uses
+those to determine which `command' will be invoked.  Since bash
+doesn't use any of those startup files, there's a good chance
+that your bash environment differs from your csh environment. 
+
+11) How can I make my csh aliases work when I convert to bash?
+
+Bash uses a different syntax to support aliases than csh does. 
+The details can be found in the documentation.  We have provided
+a shell script which does most of the work of conversion for you;
+this script can be found in ./examples/alias-conv.sh.  Here is
+how you use it:
+  
+Start csh in the normal way for you.  (e.g., `csh')
+  
+Pipe the output of `alias' through `alias-conv.sh', saving the
+results into `bash_aliases':
+  
+       alias | alias-conv.sh >bash_aliases
+  
+Edit `bash_aliases', carefully reading through any created
+functions.  You will need to change the names of csh specific
+variables (like $cwd) to the bash equivalents (like $PWD).  You
+will also need to remove recursive references to commands which
+are defined as functions.  For example, the csh alias:
+  
+       alias cd 'cd \!*;echo $cwd'
+  
+is converted to the bash function:
+
+       cd () 
+       { 
+               cd $*;
+               echo $cwd
+       }
+  
+This function contains a self-pointing reference to `cd', which
+should be changed to use the `builtin' version.  It also uses
+the csh variable `$cwd' which has an equivalent in bash.
+Precede the recursive reference with the word `builtin', and
+change the name of the variable:
+  
+        cd () { builtin cd $*; echo $PWD; }
+  
+Merge the edited file into your ~/.bashrc.
+
+12) Now that I've converted from ksh to bash, are there equivalents to
+    ksh features like autoloaded functions and the `whence' command?
+
+There are features in ksh-88 that do not have direct bash equivalents.
+Most, however, can be emulated with very little trouble.
+
+ksh-88 feature         Bash equivalent
+--------------         ---------------
+[[...]]                        can usually use [...]; minor differences
+compiled-in aliases    set up aliases in .bashrc; some ksh aliases are
+                       bash builtins (hash, history, type)
+$(<file)               $(cat file)
+arrays                 no good subsitute yet
+((...))                        let "..."
+time                   use external command; GNU time is particularly useful
+                       use time bash -c '...' for complicated constructs
+extended patterns      no good substitute
+coprocesses            named pipe pairs (one for read, one for write)
+typeset +f             declare -f |
+                            sed -n 's:^declare -[a-z]* \([^ ]*\).*$:\1:p'
+cd, print, whence      function subsitutes in examples/functions/kshenv
+autoloaded functions   examples/functions/autoload is the same as typeset -fu
+read var?prompt                [ -t 0 ] && echo -n prompt >&2; read var
+
+13) Why is the bash builtin `test' slightly different from /bin/test?
+
+The specific example used here is [ ! x -o x ], which is false.
+
+Bash's builtin `test' implements the Posix.2 spec, which can be
+summarized as follows (the wording is due to David Korn):
+   
+Here is the set of rules for processing test arguments.
+  
+    0 Args: False
+    1 Arg:  True iff argument is not null.
+    2 Args: If first arg is !, True iff second argument is null.
+           If first argument is unary, then true if unary test is true
+           Otherwise error.
+    3 Args: If second argument is a binary operator, do binary test of $1 $3
+           If first argument is !, negate two argument test of $2 $3
+           Otherwise error.
+    4 Args: If first argument is !, negate three argument test of $2 $3 $4.
+           Otherwise unspecified
+    5 or more Args: unspecified.  (Historical shells would use their
+    current algorithm).
+   
+The operators -a and -o are considered binary operators for the purpose
+of the 3 Arg case.
+   
+As you can see, the test becomes (not (x or x)), which is false.
+
+14) Why does bash sometimes say `Broken pipe'?
+
+If a sequence of commands appear in a pipeline, and one of the
+reading commands finishes before the writer has finished, the
+writer receives a SIGPIPE signal.  Many other shells special-case
+SIGPIPE as an exit status in the pipeline and do not report it. 
+For example, in:
+  
+      ps -aux | head
+  
+`head' can finish before `ps' writes all of its output, and ps
+will try to write on a pipe without a reader.  In that case, bash
+will print `Broken pipe' to stderr when ps is killed by a
+SIGPIPE. 
+
+15) How can I get bash to read and display eight-bit characters?
+
+This is a process requiring several steps.
+
+First, you must ensure that the `physical' data path is a full eight
+bits.  For xterms, for example, the `vt100' resources `eightBitInput'
+and `eightBitOutput' should be set to `true'.
+
+Once you have set up an eight-bit path, you must tell the kernel and
+tty driver to leave the eigth bit of characters alone when processing
+keyboard input.  Use `stty' to do this:
+
+       stty cs8 -istrip -parenb
+
+For old BSD-style systems, you can use
+
+       stty pass8
+
+You may also need
+
+       stty even odd
+
+Finally, you need to tell readline that you will be inputting and
+displaying eight-bit characters.  You use readline variables to do
+this.  These variables can be set in your .inputrc or using the bash
+`bind' builtin.  Here's an example using `bind':
+
+       bash$ bind 'set convert-meta off'
+       bash$ bind 'set meta-flag on'
+       bash$ bind 'set output-meta on'
+
+The `set' commands between the single quotes may also be placed
+in ~/.inputrc.
+
+16) Why can't I use command line editing in my `cmdtool'?
+
+The problem is `cmdtool' and bash fighting over the input.  When
+scrolling is enabled in a cmdtool window, cmdtool puts the tty in
+`raw mode' to permit command-line editing using the mouse for
+applications that cannot do it themselves.  As a result, bash and
+cmdtool each try to read keyboard input immediately, with neither
+getting enough of it to be useful.
+
+This mode also causes cmdtool to not implement many of the
+terminal functions and control sequences appearing in the
+`sun-cmd' termcap entry.  For a more complete explanation, see
+that file examples/suncmd.termcap in the bash distribution. 
+
+`xterm' is a better choice, and gets along with bash much more
+smoothly.
+
+17) How do I write a function `x' to replace builtin command `x', but
+    still invoke the command from within the function?
+
+This is what the `command' and `builtin' builtins are for.  The
+`command' builtin executes the command supplied as its first
+argument, skipping over any function defined with that name.  The
+`builtin' builtin executes the builtin command given as its first
+argument directly. 
+
+For example, to write a function to replace `cd' that writes the
+hostname and current directory to an xterm title bar, use
+something like the following:
+
+       cd()
+       {
+               builtin cd "$@" && xtitle $HOST: $PWD
+       }
+
+This could also be written using `command' instead of `builtin';
+the version above is marginally more efficient. 
+
+18) When I have terminal escape sequences in my prompt, why does bash
+    wrap lines at the wrong column?
+
+Bash does not know that the terminal escape sequences do not take
+up space on the screen.  The redisplay code assumes, unless told
+otherwise, that each character in the prompt is a `printable'
+character that takes up one character position on the screen. 
+
+You can use the bash prompt expansion facility (see the PROMPTING
+section in the manual page) to tell readline that sequences of
+characters in the prompt strings take up no screen space. 
+
+Use the \[ escape to begin a sequence of non-printing characters,
+and the \] escape to signal the end of such a sequence. 
+
+19) I built bash on Solaris 2.  Why do globbing expansions and filename
+    completion chop off the first few characters of each filename?
+
+This is the consequence of building bash on SunOS 5 and linking
+with the libraries in /usr/ucblib, but using the definitions
+and strutures from files in /usr/include. 
+
+The actual conflict is between the dirent structure in
+/usr/include/dirent.h and the struct returned by the version of
+`readdir' in libucb.a (a 4.3-BSD style `struct direct'). 
+
+Make sure you've got /usr/ccs/bin ahead of /usr/ucb in your $PATH
+when building bash.  This will ensure that you use /usr/ccs/bin/cc
+or acc instead of /usr/ucb/cc and that you link with libc before
+libucb.
+
+If you have installed the Sun C compiler, you may also need to
+put /usr/ccs/bin and /opt/SUNWspro/bin into your $PATH before
+/usr/ucb.
+
+20) Why doesn't bash treat brace expansions exactly like csh?
+
+The only difference between bash and csh brace expansion is that
+bash requires a brace expression to contain at least on unquoted
+comma if it is to be expanded.  Any brace-surrounded word not
+containing an unquoted comma is left unchanged by the brace
+expansion code.  This affords the greatest degree of sh
+compatibility. 
+
+Bash, ksh, zsh, and pd-ksh all implement brace expansion this way. 
+
+21) Why does bash dump core after I interrupt username completion on a
+    machine running NIS?
+
+This is a famous and long-standing bug in the SunOS YP (sorry, NIS)
+client library, which is part of libc.
+
+The YP library code keeps static state -- a pointer into the data
+returned from the server.  When YP initializes itself (setpwent),
+it looks at this pointer and calls free on it if it's non-null. 
+So far, so good. 
+
+If one of the YP functions is interrupted during getpwent (the
+exact function is interpretwithsave()), and returns NULL, the
+pointer is freed without being reset to NULL, and the function
+returns.  The next time getpwent is called, it sees that this
+pointer is non-null, calls free, and the bash free() blows up
+because it's being asked to free freed memory. 
+
+The traditional Unix mallocs allow memory to be freed multiple
+times; that's probably why this has never been fixed.  You can
+probably stop it by adding an #undef USE_GNU_MALLOC to the
+appropriate machine description in machines.h. 
+
+22) I'm running SVR4.2.  Why is the line erased every time I type `@'?
+
+The `@' character is the default `line kill' character in most
+versions of System V, including SVR4.2.  You can change this
+character to whatever you want using `stty'.  For example, to
+change the line kill character to control-u, type
+
+       stty kill ^U
+
+where the `^' and `U' can be two separate characters.
+
+23) How can I find the value of a shell variable whose name is the value
+    of another shell variable?
+
+Use the `eval' builtin.  The important thing to remember is that
+`eval' expands the arguments you give it again, so you need to
+quote the parts of the arguments that you want `eval' to act on. 
+
+For example, this expression prints the value of the last positional
+parameter:
+
+       eval echo \$\{$#\}
+
+The expansion of the quoted portions of this expression will be
+deferred until `eval' runs, while the `$#' will be expanded
+before `eval' is executed. 
+
+24) If I pipe the output of a command into `read variable', why doesn't
+    the output show up in $variable when the read command finishes?
+
+This has to do with the parent-child relationship between Unix
+processes. 
+
+Each element of a pipeline runs in a separate process, a child of
+the shell running the pipeline.  A subprocess cannot affect its
+parent's environment.  When the `read' command sets the variable
+to the input, that variable is set only in the subshell, not the
+parent shell.  When the subshell exits, the value of the variable
+is lost. 
+
+Many pipelines that end with `read variable' can be converted
+into command substitutions, which will capture the output into a
+variable:
+
+       grep ^gnu /usr/lib/news/active | wc -l | read ngroup
+
+can be converted into
+
+       ngroup=$(grep ^gnu /usr/lib/news/active | wc -l)
+
+This does not, unfortunately, work to split the text among
+multiple variables, as read does when given multiple variable
+arguments.
+
+25) I just changed my shell to bash, and now I can't FTP into my machine.
+    Why not?
+
+You must add the full pathname to bash to the file /etc/shells. 
+Many versions of ftpd use this file to prohibit `special' users
+such as `uucp' and `news' from using FTP. 
+
+26) I have a bunch of shell scripts that use backslash-escaped characters
+    in arguments to `echo'.  Bash doesn't interpret these characters.  Why
+    not, and how can I make it understand them?
+
+This is the behavior of echo on most Unix System V machines.
+
+The bash builtin `echo' is modelled after the 9th Edition
+Research Unix version of `echo'.  It does not interpret
+backslash-escaped characters in its argument strings by default,
+but requires the use of the -e option to enable the
+interpretation.  The System V echo provides no way to disable the
+special characters; the bash echo has a -E option to disable
+them. 
+
+There is a compile-time option that will make bash behave like
+the System V echo and interpret things like \t by default. 
+Change config.h so that DEFAULT_ECHO_TO_USG is defined, remove
+builtins/libbuiltins.a and builtins/echo.o, and rebuild.
+
+27) Why doesn't bash have csh variable modifiers?
+
+Posix has specified a more powerful, albeit somewhat more confusing,
+mechanism cribbed from ksh, and bash implements it.
+
+${parameter%word}
+        Remove smallest suffix pattern.  The WORD is expanded to produce
+        a pattern.  It then expands to the value of PARAMETER, with the
+        smallest portion of the suffix matched by the pattern deleted.
+
+        x=file.c
+        echo ${x%.c}.o
+        -->file.o
+
+${parameter%%word}
+
+        Remove largest suffix pattern.  The WORD is expanded to produce
+        a pattern.  It then expands to the value of PARAMETER, with the
+        largest portion of the suffix matched by the pattern deleted.
+
+        x=posix/src/std
+        echo ${x%%/*}
+        -->posix
+
+${parameter#word}
+        Remove smallest prefix pattern.  The WORD is expanded to produce
+        a pattern.  It then expands to the value of PARAMETER, with the
+        smallest portion of the prefix matched by the pattern deleted.
+
+        x=$HOME/src/cmd
+        echo ${x#$HOME}
+        -->/src/cmd
+
+${parameter##word}
+        Remove largest prefix pattern.  The WORD is expanded to produce
+        a pattern.  It then expands to the value of PARAMETER, with the
+        largest portion of the prefix matched by the pattern deleted.
+
+        x=/one/two/three
+        echo ${x##*/}
+        -->three
+
+
+Given
+       a=/a/b/c/d
+       b=b.xxx
+
+       csh                     bash            result
+       ---                     ----            ------
+       $a:h                    ${a%/*}            /a/b/c
+       $a:t                    ${a##*/}           d
+       $b:r                    ${b%.*}            b
+       $b:e                    ${b##*.}           xxx
+
+
+28) Why does bash report syntax errors when my C News scripts use a
+    redirection before a subshell command?
+
+The actual command in question is something like
+
+       < file ( command )
+
+According to the grammar given in the Posix.2 standard, this construct
+is, in fact, a syntax error.  Redirections may only precede `simple
+commands'.  A subshell construct such as the above is one of the shell's
+`compound commands'.  A redirection may only follow a compound command.
+
+The file CWRU/sh-redir-hack in the 1.14.6 distribution is an (unofficial)
+patch to parse.y that will modify the grammar to support this construct.
+Note that if you apply this, you must recompile with -DREDIRECTION_HACK.
+This introduces a large number of reduce/reduce conflicts into the shell
+grammar.
+
+29) How do I report bugs in bash, and where should I look for fixes and
+    advice?
+
+Use the `bashbug' script to report bugs.  It is built and
+installed at the same time as bash.  It provides a standard
+template for reporting a problem and automatically includes
+information about your configuration and build environment. 
+
+`bashbug' sends its reports to bug-bash@prep.ai.mit.edu, which
+is a large mailing list gatewayed to the usenet newsgroup gnu.bash.bug. 
+
+Bug fixes, answers to questions, and announcements of new releases
+are all posted to gnu.bash.bug.  Discussions concerning bash features
+and problems also take place there.
+
+To reach the bash maintainers directly, send mail to
+bash-maintainers@prep.ai.mit.edu.
+
+30) What kind of bash documentation is there?
+
+First, look in the documentation directory in the bash distribution.
+It should contain the following files:
+
+bash.1         an extensive, thorough Unix-style manual page
+builtins.1     a manual page covering just bash builtin commands
+features.texi  a Gnu-style info file overview
+FAQ            this file
+article.ms     text of an article written for The Linux Journal
+readline.3     a man page describing readline
+
+Postscript files created from the above source are also present in
+the distribution.
+
+There is additional documentation available for anonymous FTP from host
+slc2.ins.cwru.edu in the `pub/bash' directory.
+
+Cameron Newham is in the midst of writing a book on bash, to be
+published by O'Reilly and Associates.  Look for it sometime this
+year.
+
+31) What's coming in future versions?
+
+There will be no new features in future releases of version 1.14.
+
+The next major release, bash-2.0, will contain extensive changes and new
+features.  Here's a short list:
+
+one-dimensional arrays with a new compound assignment statement,
+        appropriate expansion constructs and modifications to some
+       of the builtins (read, declare, etc.) to use them
+new expansions to do ANSI-C string expansion, substring extraction,
+       pattern replacement, and indirect variable expansion
+new builtins: `disown' and `shopt'
+new variables: HISTIGNORE, SHELLOPTS, PIPESTATUS, DIRSTACK
+special handling of many unused or redundant variables removed
+dynamic loading of new builtin commands; many loadable examples provided
+new prompt expansions: \e, \n, \H, \T
+new readline variables: enable-keypad, mark-directories, input-meta
+new readline commands to manipulate the mark and operate on the region
+new readline emacs mode commands and bindings for ksh-88 compatibility
+updated and extended builtins
+new DEBUG trap
+expanded (and now documented) restricted shell mode
+
+implementation stuff:  
+autoconf-based configuration
+nearly all of the bugs reported since version 1.14 have been fixed
+most builtins converted to use builtin `getopt' for consistency
+most builtins use -p option to display output in a reusable form
+       (for consistency)
+grammar tighter and smaller (66 reduce-reduce conflicts gone)
+lots of code now smaller and faster
+test suite greatly expanded
+
+32) What's on the bash `wish list'?
+
+internationalization with a variable expansion to translate a string
+       according to a particular message catalog
+Programmable completion a la zsh
+menu completion a la tcsh
+the ksh egrep-style extended pattern matching operators
+associative arrays (not really all that hard)
+breaking some of the shell functionality into embeddable libraries
+a bash debugger
+
+Much of this will not be in bash-2.0.
+
+33) When will the next release appear?
+
+Version 1.14.6 will probably be the last release for version 1.14.
+
+The next version will appear sometime in 1996.  Never make predictions.
+
+
+This document is copyright Chester Ramey, 1995.
+
+Permission is hereby granted, without written agreement and
+without license or royalty fees, to use, copy, and distribute
+this document for any purpose, provided that the above copyright
+notice appears in all copies of this document and that the
+contents of this document remain unaltered.
diff --git a/documentation/Makefile b/documentation/Makefile
new file mode 100644 (file)
index 0000000..fb437eb
--- /dev/null
@@ -0,0 +1,103 @@
+# This Makefile is for the Bash/documentation directory -*- text -*-.
+#
+RM         = rm -f
+
+INSTALL_DATA = ../support/install.sh -c -m 644
+
+# unused
+TEXINDEX    = texindex
+TEX        = tex
+
+MAKEINFO    = makeinfo
+TEXI2DVI    = ../support/texi2dvi
+QUIETPS            = #set this to -q to shut up dvips
+DVIPS      = dvips -D 300 $(QUIETPS) -o $@     # tricky
+TEXINPUTS   = ./../lib/readline/doc
+
+# Change to groff -Tascii if you don't have nroff
+NROFF      = nroff
+
+# This should be a program that converts troff to postscript
+GROFF      = groff
+
+HSUSER      = ./../lib/readline/doc/hsuser.texinfo
+RLUSER      = ./../lib/readline/doc/rluser.texinfo
+
+.SUFFIXES:     .1 .3 .ms .ps .txt .dvi
+
+.1.ps:
+       $(RM) $@
+       ${GROFF} -man $< > $@
+
+.1.txt:
+       $(RM) $@
+       ${NROFF} -man $< > $@
+
+.ms.ps:
+       $(RM) $@
+       ${GROFF} -ms $< > $@
+
+.ms.txt:
+       $(RM) $@
+       ${NROFF} -ms $< > $@
+
+.3.ps:
+       $(RM) $@
+       ${GROFF} -man $< > $@
+
+.3.txt:
+       $(RM) $@
+       ${NROFF} -man $< > $@
+
+all: ps info dvi text
+
+ps: bash.ps readline.ps article.ps
+dvi: features.dvi features.ps 
+info: features.info
+text: bash.txt builtins.txt readline.txt article.txt
+
+features.dvi: features.texi $(HSUSER) $(RLUSER)
+       TEXINPUTS=.:$(TEXINPUTS):$$TEXINPUTS $(TEXI2DVI) features.texi
+
+features.ps: features.dvi
+       $(RM) $@
+       $(DVIPS) features.dvi
+
+features.info: features.texi $(HSUSER) $(RLUSER)
+       $(MAKEINFO) --no-split -I$(TEXINPUTS) features.texi
+
+bash.txt: bash.1
+bash.ps: bash.1
+builtins.txt: builtins.1 bash.1
+readline.txt: readline.3
+readline.ps: readline.3
+article.ps: article.ms
+
+hsuser.texinfo: ../lib/readline/doc/hsuser.texinfo
+       ln -s ../lib/readline/doc/hsuser.texinfo .
+
+rluser.texinfo: ../lib/readline/doc/rluser.texinfo
+       ln -s ../lib/readline/doc/rluser.texinfo .
+
+clean:
+       $(RM) *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps *.pgs \
+       *.fns *.kys *.tps *.vrs *.o core rluser.texinfo hsuser.texinfo
+
+distclean mostlyclean: clean
+
+realclean maintainer-clean:    clean
+       rm -f *.dvi *.info *.ps *.txt
+
+installdirs:
+       -[ -d $(mandir) ] || mkdir $(mandir)
+       -[ -d $(man3dir) ] || mkdir $(man3dir)
+       -[ -d $(infodir) ] || mkdir $(infodir)
+
+install: all installdirs
+       $(INSTALL_DATA) bash.1 $(mandir)
+       $(INSTALL_DATA) readline.3 $(man3dir)
+       $(INSTALL_DATA) features.info $(infodir)/bash.info
+
+uninstall:
+       $(RM) $(mandir)/bash.1
+       $(RM) $(man3dir)/readline.3 $(infodir)/bash.info
diff --git a/documentation/README b/documentation/README
new file mode 100644 (file)
index 0000000..c20007d
--- /dev/null
@@ -0,0 +1,32 @@
+This directory contains the bash documentation.
+
+FAQ            - a set of frequently-asked questions about Bash with answers
+article.ms     - an article I wrote about bash for The Linux Journal
+bash.1         - the bash man page
+builtins.1     - a man page that documents the builtins, extracted from bash.1
+features.texi  - the `bash features' document, suitable for an info tree
+readline.3     - the readline man page
+
+The `.ps' files are postscript versions of the above.  The `.txt' versions
+are ascii -- the output of `nroff'.
+
+The rest of this file explains how to use the `builtins.1' man page.
+
+For each command in the list of builtins create a file in man/man1 called:
+
+${command}.1
+
+eg.
+for.1
+type.1
+alias.1
+etc.
+
+All these files are identical as follows:
+
+jaws@jaws(264)$ cat alias.1
+.so man1/builtins.1
+jaws@jaws(265)$ 
+
+Make sure you adjust the .so line in builtins.1 to reflect where you
+put it.
diff --git a/documentation/article.ms b/documentation/article.ms
new file mode 100644 (file)
index 0000000..027f876
--- /dev/null
@@ -0,0 +1,1114 @@
+.de SE \" start example
+.sp .5
+.RS
+.ft CR
+.nf
+..
+.de EE \" end example
+.fi
+.sp .5
+.RE
+.ft R
+..
+.TL
+Bash \- The GNU shell*
+.AU
+Chet Ramey
+Case Western Reserve University
+chet@po.cwru.edu
+.FS
+*An earlier version of this article appeared in The Linux Journal.
+.FE
+.NH 1
+Introduction
+.PP
+.B Bash
+is the shell, or command language interpreter,
+that will appear in the GNU operating system.
+The name is an acronym for
+the \*QBourne-Again SHell\*U, a pun on Steve Bourne, the author
+of the direct ancestor of the current
+.UX
+shell \fI/bin/sh\fP,
+which appeared in the Seventh Edition Bell Labs Research version
+of \s-1UNIX\s+1.
+.PP
+Bash is an \fBsh\fP\-compatible shell that incorporates useful
+features from the Korn shell (\fBksh\fP) and the C shell (\fBcsh\fP),
+described later in this article.  It is ultimately intended to be a
+conformant implementation of the IEEE POSIX Shell and Utilities
+specification (IEEE Working Group 1003.2).  It offers functional
+improvements over sh for both interactive and programming use.
+.PP
+While the GNU operating system will most likely include a version
+of the Berkeley shell csh, Bash will be the default shell.
+Like other GNU software, Bash is quite portable.  It currently runs
+on nearly every version of
+.UX
+and a few other operating systems \- an independently-supported
+port exists for OS/2, and there are rumors of ports to DOS and
+Windows NT.  Ports to \s-1UNIX\s+1-like systems such as QNX and Minix
+are part of the distribution.
+.PP
+The original author of Bash
+was Brian Fox, an employee of the Free Software Foundation.  The
+current developer and maintainer is Chet Ramey, a volunteer who
+works at Case Western Reserve University.
+.NH 1
+What's POSIX, anyway?
+.PP
+.I POSIX
+is a name originally coined by Richard Stallman for a family of open
+system standards based on \s-1UNIX\s+1.  There are a number of aspects of \s-1UNIX\s+1
+under consideration for standardization, from the basic system services
+at the system call and C library level to applications and tools to system
+administration and management.  Each area of standardization is
+assigned to a working group in the 1003 series.
+.PP
+The POSIX Shell and Utilities standard has been developed by IEEE Working
+Group 1003.2 (POSIX.2).\(dd
+.FS
+\(ddIEEE, \fIIEEE Standard for Information Technology -- Portable
+Operating System Interface (POSIX) Part 2: Shell and Utilities\fP,
+1992.
+.FE
+It concentrates on the command interpreter
+interface and utility programs
+commonly executed from the command line or by other programs.
+An initial version of the standard has been
+approved and published by the IEEE, and work is currently underway to
+update it.
+There are four primary areas of work in the 1003.2 standard:
+.IP \(bu
+Aspects of the shell's syntax and command language.
+A number of special builtins such as
+.B cd
+and
+.B exec
+are being specified as part of the shell, since their
+functionality usually cannot be implemented by a separate executable;
+.IP \(bu
+A set of utilities to be called by shell scripts and applications.
+Examples are programs like
+.I sed,
+.I tr,
+and
+.I awk.
+Utilities commonly implemented as shell builtins
+are described in this section, such as
+.B test
+and
+.B kill .
+An expansion of this section's scope, termed the User Portability
+Extension, or UPE, has standardized interactive programs such as
+.I vi
+and
+.I mailx;
+.IP \(bu
+A group of functional interfaces to services provided by the
+shell, such as the traditional \f(CRsystem()\fP
+C library function.  There are functions to perform shell word
+expansions, perform filename expansion (\fIglobbing\fP), obtain values
+of POSIX.2 system configuration variables, retrieve values of
+environment variables (\f(CRgetenv()\fP\^), and other services;
+.IP \(bu
+A suite of \*Qdevelopment\*U utilities such as
+.I c89
+(the POSIX.2 version of \fIcc\fP),
+and
+.I yacc.
+.PP
+Bash is concerned with the aspects of the shell's behavior
+defined by POSIX.2.  The shell command language has of
+course been standardized, including the basic flow control
+and program execution constructs, I/O redirection and
+pipelining, argument handling, variable expansion, and quoting.
+The
+.I special
+builtins, which must be implemented as part of the shell to
+provide the desired functionality, are specified as being
+part of the shell; examples of these are
+.B eval
+and
+.B export .
+Other utilities appear in the sections of POSIX.2 not
+devoted to the shell which are commonly (and in some
+cases must be) implemented as builtin commands, such as
+.B read
+and
+.B test .
+POSIX.2 also specifies aspects of the shell's
+interactive behavior as part of
+the UPE, including job control and command line editing.
+Interestingly enough, only \fIvi\fP-style line editing commands
+have been standardized; \fIemacs\fP editing commands were left
+out due to objections.
+.PP
+While POSIX.2 includes much of what the shell has traditionally
+provided, some important things have been omitted as being
+\*Qbeyond its scope.\*U  There is, for instance, no mention of
+a difference between a
+.I login
+shell and any other interactive shell (since POSIX.2 does not
+specify a login program).  No fixed startup files are defined,
+either \- the standard does not mention
+.I .profile .
+.NH 1
+Basic Bash features
+.PP
+Since the Bourne shell
+provides Bash with most of its philosophical underpinnings,
+Bash inherits most of its features and functionality from sh.
+Bash implements all of the traditional sh flow
+control constructs (\fIfor\fP, \fIif\fP, \fIwhile\fP, etc.).
+All of the Bourne shell builtins, including those not specified in
+the POSIX.2 standard, appear in Bash.  Shell \fIfunctions\fP,
+introduced in the SVR2 version of the Bourne shell,
+are similar to shell scripts, but are defined using a special
+syntax and are executed in the same process as the calling shell.
+Bash has shell functions
+which behave in a fashion upward-compatible with sh functions.
+There are certain shell
+variables that Bash interprets in the same way as sh, such as
+.B PS1 ,
+.B IFS ,
+and
+.B PATH .
+Bash implements essentially the same grammar, parameter and
+variable expansion semantics, redirection, and quoting as the
+Bourne shell.  Where differences appear between the POSIX.2
+standard and traditional sh behavior, Bash follows POSIX.
+.PP
+The Korn Shell (\fBksh\fP) is a descendent of the Bourne shell written
+at AT&T Bell Laboratories by David Korn\(dg.  It provides a number of
+useful features that POSIX and Bash have adopted.  Many of the
+interactive facilities in POSIX.2 have their roots in the ksh:
+for example, the POSIX and ksh job control facilities are nearly
+identical. Bash includes features from the Korn Shell for both
+interactive use and shell programming.  For programming, Bash provides
+variables such as
+.B RANDOM
+and
+.B REPLY ,
+the
+.B typeset
+builtin,
+the ability to remove substrings from variables based on patterns,
+and shell arithmetic.
+.FS
+\(dgMorris Bolsky and David Korn, \fIThe KornShell Command and
+Programming Language\fP, Prentice Hall, 1989.
+.FE
+.B RANDOM
+expands to a random number each time it is referenced; assigning a
+value to
+.B RANDOM
+seeds the random number generator.
+.B REPLY
+is the default variable used by the
+.B read
+builtin when no variable names are supplied as arguments.
+The
+.B typeset
+builtin is used to define variables and give them attributes
+such as \fBreadonly\fP.
+Bash arithmetic allows the evaluation of an expression and the
+substitution of the result.  Shell variables may be used as operands,
+and the result of an expression may be assigned to a variable.
+Nearly all of the operators from the C language are available,
+with the same precedence rules:
+.SE
+$ echo $((3 + 5 * 32))
+163
+.EE
+.LP
+For interactive use, Bash implements ksh-style aliases and builtins
+such as
+.B fc
+(discussed below) and
+.B jobs .
+Bash aliases allow a string to be substituted for a command name.
+They can be used to create a mnemonic for a \s-1UNIX\s+1 command
+name (\f(CRalias del=rm\fP), to expand a single word to a complex command
+(\f(CRalias news='xterm -g 80x45 -title trn -e trn -e -S1 -N &'\fP), or to
+ensure that a command is invoked with a basic set of options
+(\f(CRalias ls="/bin/ls -F"\fP).
+.PP
+The C shell (\fBcsh\fP)\(dg, originally written by Bill Joy while at
+Berkeley, is widely used and quite popular for its interactive
+facilities.  Bash includes a csh-compatible history expansion
+mechanism (\*Q! history\*U), brace expansion, access to a stack
+of directories via the
+.B pushd ,
+.B popd ,
+and
+.B dirs
+builtins, and tilde expansion, to generate users' home directories.
+Tilde expansion has also been adopted by both the Korn Shell and
+POSIX.2.
+.FS
+\(dgBill Joy, An Introduction to the C Shell, \fIUNIX User's Supplementary
+Documents\fP, University of California at Berkeley, 1986.
+.FE
+.PP
+There were certain areas in which POSIX.2 felt standardization
+was necessary, but no existing implementation provided the proper
+behavior.  The working group invented and standardized functionality
+in these areas, which Bash implements.  The
+.B command
+builtin was invented so that shell functions could be written to
+replace builtins; it makes the capabilities of the builtin
+available to the function.  The reserved word \*Q!\*U was added
+to negate the return value of a command or pipeline; it was nearly
+impossible to express \*Qif not x\*U cleanly using the sh language.
+There exist multiple incompatible implementations of the 
+.B test
+builtin, which tests files for type and other attributes and performs
+arithmetic and string comparisons.
+POSIX considered none of these correct, so the standard
+behavior was specified in terms of the number of arguments to the
+command.  POSIX.2 dictates exactly what will happen when four or
+fewer arguments are given to
+.B test ,
+and leaves the behavior undefined when more arguments are supplied.
+Bash uses the POSIX.2 algorithm, which was conceived by David Korn.
+.NH 2
+Features not in the Bourne Shell
+.PP
+There are a number of minor differences between Bash and the
+version of sh present on most other versions of \s-1UNIX\s+1.  The majority
+of these are due to the POSIX standard, but some are the result of
+Bash adopting features from other shells.  For instance, Bash
+includes the new \*Q!\*U reserved word, the
+.B command
+builtin, the ability of the
+.B read
+builtin to correctly return a line ending with a backslash, symbolic
+arguments to the
+.B umask
+builtin, variable substring removal, a way to get the length of a variable,
+and the new algorithm for the
+.B test
+builtin from the POSIX.2 standard, none of which appear in sh.
+.PP
+Bash also implements the \*Q$(...)\*U command substitution syntax,
+which supersedes the sh `...` construct.
+The \*Q$(...)\*U construct expands to the output of the command
+contained within the
+parentheses, with trailing newlines removed.  The sh syntax is
+accepted for backwards compatibility, but the \*Q$(...)\*U form
+is preferred because its quoting rules are much simpler and it
+is easier to nest.
+.PP
+The Bourne shell does not provide such features as brace expansion,
+the ability
+to define a variable and a function with the same name, local variables
+in shell functions, the ability to enable and disable individual
+builtins or write a function to replace a builtin, or a means to
+export a shell function to a child process.
+.PP
+Bash has closed
+a long-standing shell security hole by not using the
+.B $IFS
+variable to split each word read by the shell, but splitting only
+the results of expansion (ksh and the 4.4 BSD sh have fixed this
+as well).  Useful behavior such as a means to abort
+execution of a script read with the \*Q.\*U command using the
+\fBreturn\fP builtin or automatically
+exporting variables in the shell's environment to children is also
+not present in the Bourne shell.  Bash provides a much more powerful
+environment for both interactive use and programming.
+.NH 1
+Bash-specific Features
+.PP
+This section details a few of the features which make Bash unique.
+Most of them provide improved interactive use, but a few programming
+improvements are present as well.  Full descriptions of these
+features can be found in the Bash documentation.
+.NH 2
+Startup Files
+.PP
+Bash executes startup files differently than other shells.  The Bash
+behavior is a compromise between the csh principle of startup files
+with fixed names executed for each shell and the sh
+\*Qminimalist\*U behavior.  An interactive instance of Bash started
+as a login shell reads and executes
+.I ~/.bash_profile
+(the file .bash_profile in the user's home directory), if it exists.
+An interactive non-login shell reads and executes
+.I ~/.bashrc .
+A non-interactive shell (one begun to execute a shell script, for
+example) reads no fixed startup file, but uses the value of the variable
+.B $ENV ,
+if set, as the name of a startup file.  The ksh practice of reading
+.B $ENV
+for every shell, with the accompanying difficulty of defining the
+proper variables and functions for interactive and non-interactive
+shells or having the file read only for interactive shells, was
+considered too complex.  Ease of use won out here.  Interestingly,
+the next release of ksh will change to reading
+.B $ENV
+only for interactive shells.
+.NH 2
+New Builtin Commands
+.PP
+There are a few builtins which are new or have been extended in Bash.
+The
+.B enable
+builtin allows builtin commands to be turned on and off arbitrarily.
+To use the version of
+.I echo
+found in a user's search path rather than the Bash builtin,
+\f(CRenable -n echo\fP suffices.  The
+.B help
+builtin provides
+quick synopses of the shell facilities without requiring
+access to a manual page.
+.B Builtin
+is similar to
+.B command
+in that it bypasses shell functions and directly executes builtin
+commands.  Access to a csh-style stack of directories is provided
+via the
+.B pushd ,
+.B popd ,
+and
+.B dirs
+builtins.
+.B Pushd
+and
+.B popd
+insert and remove directories from the stack, respectively, and
+.B dirs
+lists the stack contents.  On systems that allow fine-grained control
+of resources, the
+.B ulimit
+builtin can be used to tune these settings.
+.B Ulimit
+allows a user to control,
+among other things, whether core dumps are to be generated,
+how much memory the shell or a child process is allowed to allocate,
+and how large a file created by a child process can grow.  The
+.B suspend
+command will stop the shell process when job control is active; most
+other shells do not allow themselves to be stopped like that.
+.B Type,
+the Bash answer to
+.B which
+and 
+.B whence,
+shows what will happen when a word is typed as a command:
+.SE
+$ type export
+export is a shell builtin
+$ type -t export
+builtin
+$ type bash
+bash is /bin/bash
+$ type cd
+cd is a function
+cd ()
+{
+    builtin cd ${1+"$@"} && xtitle $HOST: $PWD
+}
+.EE
+.LP
+Various
+modes tell what a command word is (reserved word, alias, function, builtin,
+or file) or which version of a command will be executed based on
+a user's search path.  Some of this functionality has been adopted
+by POSIX.2 and folded into the
+.B command
+utility.
+.NH 2
+Editing and Completion
+.PP
+One area in which Bash shines is command line editing.  Bash uses the
+.I readline
+library to read and edit lines when interactive.  Readline is a
+powerful and flexible input facility that a user can configure to
+individual tastes.  It allows lines to be edited using either emacs
+or vi commands, where those commands are appropriate.  The full
+capability of emacs is not present \- there is no way to execute
+a named command with M-x, for instance \- but the existing commands
+are more than adequate.  The vi mode is compliant with
+the command line editing standardized by POSIX.2.
+.PP
+Readline is fully customizable.  In addition to the basic commands
+and key bindings, the library allows users to define additional
+key bindings using a startup file.  The 
+.I inputrc
+file, which defaults to the file
+.I ~/.inputrc ,
+is read each time readline initializes, permitting users to
+maintain a consistent interface across a set of programs.  Readline
+includes an extensible interface, so each program using the
+library can add its own bindable commands and program-specific
+key bindings.  Bash uses this facility to add bindings
+that perform history expansion or shell word expansions on the current
+input line.
+.PP
+Readline interprets a number of
+variables which further tune its behavior.  Variables
+exist to control whether or not eight-bit characters are directly
+read as input or converted to meta-prefixed key sequences (a
+meta-prefixed key sequence consists of the character with the
+eighth bit zeroed, preceded by the
+.I meta-prefix
+character, usually escape, which selects an alternate keymap), to
+decide whether to output characters with the eighth bit set
+directly or as a meta-prefixed key sequence, whether or not to
+wrap to a new screen line when a line being edited is longer than
+the screen width, the keymap to which subsequent key bindings should
+apply, or even what happens when readline wants to
+ring the terminal's bell.  All of these variables can be set in
+the inputrc file.
+.PP
+The startup file understands a set of C
+preprocessor-like conditional constructs which allow variables or
+key bindings to be assigned based on the application using readline,
+the terminal currently being used, or the editing mode.  Users can
+add program-specific bindings to make their lives easier:  I have
+bindings that let me edit the value of
+.B $PATH
+and double-quote the current or previous word:
+.SE
+# Macros that are convenient for shell interaction
+$if Bash
+# edit the path
+"\eC-xp": "PATH=${PATH}\ee\eC-e\eC-a\eef\eC-f"
+# prepare to type a quoted word -- insert open and close double
+# quotes and move to just after the open quote
+"\eC-x\e"": "\e"\e"\eC-b"
+# Quote the current or previous word
+"\eC-xq": "\eeb\e"\eef\e""
+$endif
+.EE
+.LP
+There is a readline
+command to re-read the file, so users can edit the file, change
+some bindings, and begin to use them almost immediately.
+.PP
+Bash implements the
+.B bind
+builtin for more dyamic control of readline than the startup file
+permits.
+.B Bind
+is used in several ways.  In
+.I list
+mode, it can display the current key bindings, list all the
+readline editing directives available for binding, list which keys
+invoke a given directive, or output the current set of key
+bindings in a format that can be incorporated directly into an inputrc
+file.  In
+.I batch
+mode, it reads a series of key bindings directly from a file and
+passes them to readline.  In its most common usage,
+.B bind
+takes a single string and passes it directly to readline, which
+interprets the line as if it had just been read from the inputrc file.
+Both key bindings and variable assignments may appear in the
+string given to
+.B bind .
+.PP
+The readline library also provides an interface for \fIword completion\fP.
+When the
+.I completion
+character (usually TAB) is typed, readline looks at the word currently
+being entered and computes the set of filenames of which the current
+word is a valid prefix.
+If there is only one possible completion, the
+rest of the characters are inserted directly, otherwise the 
+common prefix of the set of filenames is added to the current word.
+A second TAB character entered immediately after a non-unique
+completion causes readline to list the possible completions; there is
+an option to have the list displayed immediately.
+Readline provides hooks so that applications can provide specific types
+of completion before the default filename completion is attempted.
+This is quite flexible, though it is not completely user-programmable.
+Bash, for example, can complete filenames, command names (including aliases,
+builtins, shell reserved words, shell functions, and executables found
+in the file system), shell variables, usernames, and hostnames.  It
+uses a set of heuristics that, while not perfect, is generally quite
+good at determining what type of completion to attempt.
+.NH 2
+History
+.PP
+Access to the list of commands previously entered (the \fIcommand history\fP)
+is provided jointly by Bash and the readline library.  Bash provides
+variables (\fB$HISTFILE\fP, \fB$HISTSIZE\fP, and \fB$HISTCONTROL\fP)
+and the
+.B history
+and
+.B fc
+builtins to manipulate the history list.
+The value of
+.B $HISTFILE
+specifes the file where Bash writes the command history on exit and
+reads it on startup.
+.B $HISTSIZE
+is used to limit the number of commands saved in the history.
+.B $HISTCONTROL
+provides a crude form of control over which commands are saved on
+the history list: a value of
+.I ignorespace
+means to not save commands which begin with a space; a value of
+.I ignoredups
+means to not save commands identical to the last command saved.
+\fB$HISTCONTROL\fP was named \fB$history_control\fP in earlier
+versions of Bash; the old name is still accepted for backwards
+compatibility.  The
+.B history
+command can read or write files containing the history list
+and display the current list contents.  The
+.B fc
+builtin, adopted from POSIX.2 and the Korn Shell, allows display
+and re-execution, with optional editing,
+of commands from the history list.  The readline
+library offers a set of commands to search the history list for
+a portion of the current input line or a string typed by the user.
+Finally, the
+.I history
+library, generally incorporated directly into the readline library,
+implements a facility for history recall, expansion, and re-execution
+of previous commands very similar to csh
+(\*Qbang history\*U, so called because the exclamation point
+introduces a history substitution):
+.SE
+$ echo a b c d e
+a b c d e
+$ !! f g h i
+echo a b c d e f g h i
+a b c d e f g h i
+$ !-2
+echo a b c d e
+a b c d e
+$ echo !-2:1-4
+echo a b c d
+a b c d
+.EE
+.LP
+The command history is only
+saved when the shell is interactive, so it is not available for use
+by shell scripts.
+.NH 2
+New Shell Variables
+.PP
+There are a number of convenience variables that Bash interprets
+to make life easier.  These include
+.B FIGNORE ,
+which is a set of filename suffixes identifying files to exclude when
+completing filenames;
+.B HOSTTYPE ,
+which is automatically set to a string describing the type of
+hardware on which Bash is currently executing;
+.B command_oriented_history ,
+which directs Bash to save all lines of a multiple-line
+command such as a \fIwhile\fP or \fIfor\fP loop in a single
+history entry, allowing easy re-editing; and
+.B IGNOREEOF ,
+whose value indicates the number of consecutive EOF characters that
+an interactive shell will read before exiting \- an easy way to keep
+yourself from being logged out accidentally.  The
+.B auto_resume
+variable alters the way the shell treats simple command names:
+if job control is active, and this variable is set, single-word
+simple commands without redirections cause the shell to first
+look for and restart a suspended job with that name before
+starting a new process.
+.NH 2
+Brace Expansion
+.PP
+Since sh offers no convenient way to generate arbitrary strings that
+share a common prefix or suffix (filename expansion requires that
+the filenames exist), Bash implements \fIbrace expansion\fP, a
+capability picked up from csh.
+Brace expansion is similar to filename expansion, but the strings
+generated need not correspond to existing files.  A brace expression
+consists of an optional
+.I preamble ,
+followed by a pair of braces enclosing a series of comma-separated
+strings, and an optional
+.I postamble .
+The preamble is prepended to each string within the braces, and the
+postamble is then appended to each resulting string:
+.SE
+$ echo a{d,c,b}e
+ade ace abe
+.EE
+.LP
+As this example demonstrates, the results of brace expansion are not
+sorted, as they are by filename expansion.
+.NH 2
+Process Substitution
+.PP
+On systems that can support it, Bash provides a facility known as
+\fIprocess substitution\fP.  Process substitution is similar to command
+substitution in that its specification includes a command to execute,
+but the shell does not collect the command's output and insert it into
+the command line.  Rather, Bash opens a pipe to the command, which
+is run in the background.  The shell uses named pipes (FIFOs) or the
+.I /dev/fd
+method of naming open files to expand the process
+substitution to a filename which connects to the pipe when opened.
+This filename becomes the result of the expansion.  Process substitution
+can be used to compare the outputs of two different versions of an
+application as part of a regression test:
+.SE
+$ cmp <(old_prog) <(new_prog)
+.EE
+.NH 2
+Prompt Customization
+.PP
+One of the more popular interactive features that Bash provides is
+the ability to customize the prompt.  Both
+.B $PS1
+and
+.B $PS2,
+the primary and secondary prompts, are expanded before being
+displayed.  Parameter and variable expansion is performed when
+the prompt string is expanded, so any shell variable can be
+put into the prompt (e.g., 
+.B $SHLVL ,
+which indicates how deeply the current shell is nested).
+Bash specially interprets characters in the prompt string
+preceded by a backslash.  Some of these backslash escapes are
+replaced with 
+the current time, the date, the current working directory,
+the username, and the command number or history number of the command
+being entered.  There is even a backslash escape to cause the shell
+to change its prompt when running as root after an \fIsu\fP.
+Before printing each primary prompt, Bash expands the variable 
+.B $PROMPT_COMMAND 
+and, if it has a value, executes the expanded value as a command,
+allowing additional prompt customization.  For example, this assignment
+causes the current user, the current host, the time, the last
+component of the current working directory, the level of shell
+nesting, and the history number of the current command to be embedded
+into the primary prompt:
+.SE
+$ PS1='\eu@\eh [\et] \eW($SHLVL:\e!)\e$ '
+chet@odin [21:03:44] documentation(2:636)$ cd ..
+chet@odin [21:03:54] src(2:637)$
+.EE
+.LP
+The string being assigned is surrounded by single quotes so that if
+it is exported, the value of
+.B $SHLVL
+will be updated by a child shell:
+.SE
+chet@odin [21:17:35] src(2:638)$ export PS1
+chet@odin [21:17:40] src(2:639)$ bash
+chet@odin [21:17:46] src(3:696)$
+.EE
+.LP
+The \fP\e$\fP escape is displayed
+as \*Q\fB$\fP\*U when running as a normal user, but as \*Q\fB#\fP\*U when
+running as root.
+.NH 2
+File System Views
+.PP
+Since Berkeley introduced symbolic links in 4.2 BSD, one of their most
+annoying properties has been the \*Qwarping\*U to a completely
+different area of the file system when using
+.B cd ,
+and the resultant non-intuitive behavior of \*Q\fBcd ..\fP\*U.
+The \s-1UNIX\s+1 kernel treats symbolic links
+.I physically .
+When the kernel is translating a pathname
+in which one component is a symbolic link, it replaces all or part
+of the pathname while processing the link.  If the contents of the symbolic
+link begin with a slash, the kernel replaces the
+pathname entirely; if not, the link contents replace
+the current component.  In either case, the symbolic link
+is visible.  If the link value is an absolute pathname,
+the user finds himself in a completely different part of the file
+system.
+.PP
+Bash provides a
+.I logical
+view of the file system.  In this default mode, command and filename
+completion and builtin commands such as
+.B cd
+and
+.B pushd
+which change the current working directory transparently follow
+symbolic links as if they were directories.
+The
+.B $PWD
+variable, which holds the shell's idea of the current working directory,
+depends on the path used to reach the directory rather than its
+physical location in the local file system hierarchy.  For example:
+.SE
+$ cd /usr/local/bin
+$ echo $PWD
+/usr/local/bin
+$ pwd
+/usr/local/bin
+$ /bin/pwd
+/net/share/sun4/local/bin
+$ cd ..
+$ pwd
+/usr/local
+$ /bin/pwd
+/net/share/sun4/local
+$ cd ..
+$ pwd
+/usr
+$ /bin/pwd
+/usr
+.EE
+.LP
+One problem with this, of
+course, arises when programs that do not understand the shell's logical
+notion of the file system interpret \*Q..\*U differently.  This generally
+happens when Bash completes filenames containing \*Q..\*U according to a
+logical hierarchy which does not correspond to their physical location. 
+For users who find this troublesome, a corresponding
+.I physical
+view of the file system is available:
+.SE
+$ cd /usr/local/bin
+$ pwd
+/usr/local/bin
+$ set -o physical
+$ pwd
+/net/share/sun4/local/bin
+.EE
+.NH 2
+Internationalization
+.PP
+One of the most significant improvements in version 1.13 of Bash was the
+change to \*Qeight-bit cleanliness\*U.  Previous versions used the
+eighth bit of characters to mark whether or not they were
+quoted when performing word expansions.  While this did not affect
+the majority of users, most of whom used only seven-bit ASCII characters,
+some found it confining.  Beginning with version 1.13, Bash
+implemented a different quoting mechanism that did not alter the
+eighth bit of characters.  This allowed Bash
+to manipulate files with \*Qodd\*U characters in their names, but
+did nothing to help users enter those names, so
+version 1.13 introduced changes to readline that
+made it eight-bit clean as well.  Options exist that force readline to
+attach no special significance to characters with the eighth bit set
+(the default behavior is to convert these characters to meta-prefixed
+key sequences) and to output these characters without conversion to
+meta-prefixed sequences.  These changes, along with the expansion of
+keymaps to a full eight bits, enable readline to work with most of the
+ISO-8859 family of character sets, used by many European countries.
+.NH 2
+POSIX Mode
+.PP
+Although Bash is intended to be POSIX.2 conformant, there are areas in
+which the default behavior is not compatible with the standard.  For
+users who wish to operate in a strict POSIX.2 environment, Bash
+implements a \fIPOSIX mode\fP.  When this mode is active, Bash modifies
+its default operation where it differs from POSIX.2 to match the
+standard.  POSIX mode is entered when Bash is started with the
+.B -posix
+option.  This feature is also available as an option to the
+\fBset\fP builtin, \fBset -o posix\fP.
+For compatibility with other GNU software that attempts to be POSIX.2
+compliant, Bash also enters POSIX mode if the variable
+.B $POSIXLY_CORRECT
+is set when Bash is started or assigned a value during execution.
+.B $POSIX_PEDANTIC
+is accepted as well, to be compatible with some older GNU utilities.
+When Bash is started in POSIX mode, for example, it sources the
+file named by the value of 
+.B $ENV
+rather than the \*Qnormal\*U startup files, and does not allow
+reserved words to be aliased.
+.NH 1
+New Features and Future Plans
+.PP
+There are several features introduced in the current
+version of Bash, version 1.14, and a number under consideration
+for future releases.  This section will briefly detail the new
+features in version 1.14 and describe several features
+that may appear in later versions.
+.NH 2
+New Features in Bash-1.14
+.PP
+The new features available in Bash-1.14 answer several of
+the most common requests for enhancements.  Most notably, there
+is a mechanism
+for including non-visible character sequences in prompts, such as
+those which cause a terminal to print characters in different
+colors or in standout mode.  There was nothing preventing the use
+of these sequences in earlier
+versions, but the readline redisplay algorithm assumed each
+character occupied physical screen space and would wrap lines
+prematurely.
+.PP
+Readline has a few new
+variables, several new bindable commands, and some additional
+emacs mode default key bindings.  A new history search
+mode has been implemented: in this mode, readline searches the
+history for lines beginning with the characters between the
+beginning of the current line and the cursor.  The existing readline
+incremental search commands no longer match identical lines more
+than once.
+Filename completion now expands variables in directory names.
+The history expansion facilities are now nearly
+completely csh-compatible: missing modifiers have been added and
+history substitution has been extended.
+.PP
+Several of the features described earlier, such as
+.B "set -o posix"
+and
+.B $POSIX_PEDANTIC ,
+are new in version 1.14.
+There is a new shell variable,
+.B OSTYPE ,
+to which Bash assigns a value that identifies the
+version of \s-1UNIX\s+1 it's
+running on (great for putting architecture-specific binary directories
+into the \fB$PATH\fP).
+Two variables have been renamed:
+.B $HISTCONTROL
+replaces
+.B $history_control ,
+and
+.B $HOSTFILE
+replaces
+.B $hostname_completion_file .
+In both cases, the old names are accepted for backwards
+compatibility.  The ksh
+.I select
+construct, which allows the generation of simple menus,
+has been implemented.  New capabilities have been added
+to existing variables:
+.B $auto_resume
+can now take values of
+.I exact
+or
+.I substring ,
+and
+.B $HISTCONTROL
+understands the value
+.I ignoreboth ,
+which combines the two previously acceptable values.  The
+.B dirs
+builtin has acquired options to print out specific members of the
+directory stack.  The
+.B $nolinks
+variable, which forces a physical view of the file system,
+has been superseded by the
+.B \-P
+option to the
+.B set
+builtin (equivalent to \fBset -o physical\fP); the variable is retained
+for backwards compatibility.  The version string contained in
+.B $BASH_VERSION
+now includes an indication of the patch level as well as the
+\*Qbuild version\*U.
+Some little-used features have
+been removed:  the
+.B bye
+synonym for
+.B exit
+and the
+.B $NO_PROMPT_VARS
+variable are gone.  There is now an organized test suite that can be
+run as a regression test when building a new version of Bash.
+.PP
+The documentation has been thoroughly overhauled:
+there is a new manual page on the readline library and the \fIinfo\fP
+file has been updated to reflect the current version.
+As always, as many bugs as possible have been fixed, although some
+surely remain.
+.NH 2
+Other Features
+.PP
+There are a few features that I hope to include in later Bash releases.
+Some are based on work already done in other shells.
+.PP
+In addition to simple variables, a future release of Bash will include
+one-dimensional arrays, using the ksh
+implementation of arrays as a model.  Additions to the ksh syntax,
+such as \fIvarname\fP=( ... ) to assign a list of words directly to
+an array and a mechanism to allow
+the
+.B read
+builtin to read a list of values directly into an array, would be
+desirable.  Given those extensions, the ksh
+.B "set \-A"
+syntax may not be worth supporting (the
+.B \-A
+option assigns a list of values to an array, but is a rather
+peculiar special case).
+.PP
+Some shells include a means of \fIprogrammable\fP word
+completion, where the user specifies on a per-command basis how the
+arguments of the command are to be treated when completion is attempted:
+as filenames, hostnames, executable files, and so on.  The other
+aspects of the current Bash implementation could remain as-is; the
+existing heuristics would still be valid.  Only when completing the
+arguments to a simple command would the programmable completion be
+in effect.
+.PP
+It would also be nice to give the user finer-grained
+control over which commands are saved onto the history list.  One
+proposal is for a variable, tentatively named
+.B HISTIGNORE ,
+which would contain a colon-separated list of commands.  Lines beginning
+with these commands, after the restrictions of
+.B $HISTCONTROL
+have been applied, would not be placed onto the history list.  The
+shell pattern-matching capabilities could also be available when
+specifying the contents of
+.B $HISTIGNORE .
+.PP
+One thing that newer shells such as
+.B wksh
+(also known as
+.B dtksh )
+provide is a command to dynamically load code
+implementing additional builtin commands into a running shell.
+This new builtin would take an object file or shared library
+implementing the \*Qbody\*U of the
+builtin (\fIxxx_builtin()\fP for those familiar with Bash internals)
+and a structure containing the name of the new command, the function
+to call when the new builtin is invoked (presumably defined in the
+shared object specified as an argument), and the documentation to be
+printed by the
+.B help
+command (possibly present in the shared object as well).  It would
+manage the details of extending the internal table of builtins. 
+.PP
+A few other builtins would also be desirable: two are the POSIX.2
+.B getconf
+command, which prints the values of system configuration variables
+defined by POSIX.2, and a
+.B disown
+builtin, which causes a shell running
+with job control active to \*Qforget about\*U one or more
+background jobs in its internal jobs table.  Using
+.B getconf ,
+for example, a user could retrieve a value for
+.B $PATH
+guaranteed to find all of the POSIX standard utilities, or
+find out how long filenames may be in the file system containing
+a specified directory.
+.PP
+There are no implementation timetables for any of these features, nor
+are there concrete plans to include them.  If anyone has comments on
+these proposals, feel free to send me electronic mail.
+.NH 1
+Reflections and Lessons Learned
+.PP
+The lesson that has been repeated most often during Bash
+development is that there are dark corners in the Bourne Shell,
+and people use all of them.  In the original description of the
+Bourne shell, quoting and the shell grammar are both poorly
+specified and incomplete; subsequent descriptions have not helped
+much.  The grammar presented in Bourne's paper describing
+the shell distributed with the Seventh Edition of \s-1UNIX\s+1\(dg
+is so far off that it does not allow the command \f(CWwho|wc\fP.
+In fact, as Tom Duff states:
+.QP
+Nobody really knows what the
+Bourne shell's grammar is.  Even examination of the source code is
+little help.\(dd
+.FS
+\(dgS. R. Bourne, \*QUNIX Time-Sharing System:  The UNIX Shell\*U,
+\fIBell System Technical Journal\fP, 57(6), July-August, 1978, pp. 1971-1990.
+.FE
+.FS
+\(ddTom Duff, \*QRc \- A Shell for Plan 9 and \s-1UNIX\s+1 systems\*U,
+\fIProc. of the Summer 1990 EUUG Conference\fP, London, July, 1990,
+pp. 21-33.
+.FE
+.LP
+The POSIX.2 standard includes a \fIyacc\fP grammar that comes close
+to capturing the Bourne shell's behavior, but it disallows some
+constructs which sh accepts without complaint \- and there are
+scripts out there that use them.  It took a few versions and
+several bug reports before Bash implemented sh-compatible quoting,
+and there are still some \*Qlegal\*U sh constructs which Bash flags as
+syntax errors.  Complete sh compatibility is a tough nut.
+.PP
+The shell is bigger and slower than I would like, though the current
+version is substantially faster than previously.  The readline library
+could stand a substantial rewrite.  A hand-written parser to replace
+the current \fIyacc\fP-generated one would probably result in a speedup,
+and would solve one glaring problem:  the shell could parse
+commands in \*Q$(...)\*U constructs
+as they are entered, rather than reporting errors when the construct
+is expanded.
+.PP
+As always, there is some chaff to go with the wheat.
+Areas of duplicated functionality need to be cleaned
+up.  There are several cases where Bash treats a variable specially to
+enable functionality available another way (\fB$notify\fP vs.
+\fBset -o notify\fP and \fB$nolinks\fP vs. \fBset -o physical\fP, for
+instance); the special treatment of the variable name should probably
+be removed.  A few more things could stand removal; the
+.B $allow_null_glob_expansion
+and
+.B $glob_dot_filenames
+variables are of particularly questionable value.
+The \fB$[...]\fP arithmetic evaluation syntax is redundant now that
+the POSIX-mandated \fB$((...))\fP construct has been implemented,
+and could be deleted.
+It would be nice if the text output by the
+.B help
+builtin were external to the shell rather than compiled into it.
+The behavior enabled by
+.B $command_oriented_history ,
+which causes the shell to attempt to save all lines of a multi-line
+command in a single history entry, should be made the default and
+the variable removed.
+.NH 1
+Availability
+.PP
+As with all other
+GNU software, Bash is available for anonymous FTP from
+.I prep.ai.mit.edu:/pub/gnu
+and from other GNU software mirror sites.  The current version is in
+.I bash-1.14.1.tar.gz
+in that directory.  Use
+.I archie
+to find the nearest archive site.  The
+latest version is always available for FTP from
+.I bash.CWRU.Edu:/pub/dist.
+Bash documentation is available for FTP from
+.I bash.CWRU.Edu:/pub/bash.
+.PP
+The Free Software Foundation sells tapes and CD-ROMs
+containing Bash; send electronic mail to
+\f(CRgnu@prep.ai.mit.edu\fP or call \f(CR+1-617-876-3296\fP
+for more information.
+.PP
+Bash is also distributed with several versions of \s-1UNIX\s+1-compatible
+systems.  It is included as /bin/sh and /bin/bash on several Linux
+distributions (more about the difference in a moment), and as contributed
+software in BSDI's BSD/386* and FreeBSD.
+.FS
+*BSD/386 is a trademark of Berkeley Software Design, Inc.
+.FE
+.PP
+The Linux distribution deserves special mention.  There are two
+configurations included in the standard Bash distribution: a
+\*Qnormal\*U configuration, in which all of the standard features
+are included, and a \*Qminimal\*U configuration, which omits job
+control, aliases, history and command line editing, the directory
+stack and
+.B pushd/popd/dirs,
+process substitution, prompt string special character decoding, and the
+.I select
+construct.  This minimal version is designed to be a drop-in replacement
+for the traditional \s-1UNIX\s+1 /bin/sh, and is included as the Linux
+/bin/sh in several packagings.
+.NH 1
+Conclusion
+.PP
+Bash is a worthy successor to sh.
+It is sufficiently portable
+to run on nearly every version of \s-1UNIX\s+1 from
+4.3 BSD to SVR4.2, and several \s-1UNIX\s+1 workalikes.
+It is robust enough to replace sh on most of those systems,
+and provides more functionality.  It has several thousand regular users,
+and their feedback has helped to make it as good as it is today \- a
+testament to the benefits of free software.
diff --git a/documentation/article.ps b/documentation/article.ps
new file mode 100644 (file)
index 0000000..3cf5f39
--- /dev/null
@@ -0,0 +1,1368 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Bold
+%%+ font Times-Italic
+%%+ font Times-Roman
+%%+ font Courier
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 11
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Courier
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Courier@0 ENC0/Courier RE/Times-Roman@0
+ENC0/Times-Roman RE/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0
+/Times-Bold RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 12/Times-Bold@0 SF(Bash \255 The GNU shell*)227.904 120 Q/F1 10
+/Times-Italic@0 SF(Chet Rame)263.85 144 Q(y)-.3 E(Case W)221.72 156 Q
+(estern Reserve Univer)-.92 E(sity)-.1 E -.15(ch)250.425 168 S(et@po.cwru.edu)
+.15 E/F2 10/Times-Bold@0 SF 2.5(1. Intr)72 234 R(oduction)-.18 E(Bash)97 249.6
+Q/F3 10/Times-Roman@0 SF .904(is the shell, or command language interpreter)
+3.404 F 3.404(,t)-.4 G .904(hat will appear in the GNU operating system.)
+316.032 249.6 R .91(The name is an acron)72 261.6 R .91(ym for the `)-.15 F
+(`Bourne-Ag)-.74 E .91(ain SHell')-.05 F .911(', a pun on Ste)-.74 F 1.211 -.15
+(ve B)-.25 H .911(ourne, the author of the direct).15 F .212
+(ancestor of the current)72 273.6 R/F4 9/Times-Roman@0 SF(UNIX)2.712 E F3 2.712
+<8773>C(hell)199.131 273.6 Q F1(/bin/sh)2.712 E F3 2.712(,w)C .212
+(hich appeared in the Se)256.505 273.6 R -.15(ve)-.25 G .211
+(nth Edition Bell Labs Research v).15 F(er)-.15 E(-)-.2 E(sion of)72 285.6 Q F4
+(UNIX)2.5 E F3(.)A .387(Bash is an)97 301.2 R F2(sh)2.887 E F3 .387
+(\255compatible shell that incorporates useful features from the K)B .388
+(orn shell \()-.35 F F2(ksh)A F3 2.888(\)a)C .388(nd the C)469.334 301.2 R .023
+(shell \()72 313.2 R F2(csh)A F3 .023(\), described later in this article.)B
+.022(It is ultimately intended to be a conformant implementation of the)5.022 F
+3.568(IEEE POSIX Shell and Utilities speci\214cation \(IEEE W)72 325.2 R 3.568
+(orking Group 1003.2\).)-.8 F 3.569(It of)8.569 F 3.569(fers functional)-.25 F
+(impro)72 337.2 Q -.15(ve)-.15 G(ments o).15 E -.15(ve)-.15 G 2.5(rs).15 G 2.5
+(hf)155.28 337.2 S(or both interacti)166.11 337.2 Q .3 -.15(ve a)-.25 H
+(nd programming use.).15 E .697(While the GNU operating system will most lik)97
+352.8 R .697(ely include a v)-.1 F .697(ersion of the Berk)-.15 F(ele)-.1 E
+3.197(ys)-.15 G .696(hell csh, Bash)446.778 352.8 R .015(will be the def)72
+364.8 R .015(ault shell.)-.1 F(Lik)5.015 E 2.515(eo)-.1 G .015(ther GNU softw)
+199.1 364.8 R .016(are, Bash is quite portable.)-.1 F .016
+(It currently runs on nearly e)5.016 F -.15(ve)-.25 G(ry).15 E -.15(ve)72 376.8
+S .367(rsion of).15 F F4(UNIX)2.867 E F3 .367(and a fe)2.867 F 2.867(wo)-.25 G
+.367(ther operating systems \255 an independently-supported port e)187.933
+376.8 R .366(xists for OS/2, and)-.15 F .706
+(there are rumors of ports to DOS and W)72 388.8 R(indo)-.4 E .706(ws NT)-.25 F
+5.706(.P)-.74 G .706(orts to)295.97 388.8 R F4(UNIX)3.206 E F3(-lik)A 3.206(es)
+-.1 G .706(ystems such as QNX and Minix)372.979 388.8 R
+(are part of the distrib)72 400.8 Q(ution.)-.2 E .405
+(The original author of Bash w)97 416.4 R .405(as Brian F)-.1 F .405
+(ox, an emplo)-.15 F .405(yee of the Free Softw)-.1 F .405(are F)-.1 F 2.905
+(oundation. The)-.15 F(cur)2.905 E(-)-.2 E(rent de)72 428.4 Q -.15(ve)-.25 G
+(loper and maintainer is Chet Rame).15 E 1.3 -.65(y, a v)-.15 H(olunteer who w)
+.45 E(orks at Case W)-.1 E(estern Reserv)-.8 E 2.5(eU)-.15 G(ni)458.91 428.4 Q
+-.15(ve)-.25 G(rsity).15 E(.)-.65 E F2 2.5(2. What')72 452.4 R 2.5(sP)-.37 G
+(OSIX, anyway?)123.85 452.4 Q F1(POSIX)97 468 Q F3 .239
+(is a name originally coined by Richard Stallman for a f)4.405 F .239
+(amily of open system standards based)-.1 F(on)72 480 Q F4(UNIX)3.24 E F3 5.74
+(.T)C .74(here are a number of aspects of)122.081 480 R F4(UNIX)3.24 E F3 .74
+(under consideration for standardization, from the basic)3.24 F .192
+(system services at the system call and C library le)72 492 R -.15(ve)-.25 G
+2.692(lt).15 G 2.692(oa)290.156 492 S .192
+(pplications and tools to system administration and)302.288 492 R 2.5
+(management. Each)72 504 R(area of standardization is assigned to a w)2.5 E
+(orking group in the 1003 series.)-.1 E 2.814
+(The POSIX Shell and Utilities standard has been de)97 519.6 R -.15(ve)-.25 G
+2.814(loped by IEEE W).15 F 2.813(orking Group 1003.2)-.8 F .254
+(\(POSIX.2\).\210 It concentrates on the command interpreter interf)72 531.6 R
+.253(ace and utility programs commonly e)-.1 F -.15(xe)-.15 G(cuted).15 E 1.112
+(from the command line or by other programs.)72 543.6 R 1.112(An initial v)
+6.112 F 1.113(ersion of the standard has been appro)-.15 F -.15(ve)-.15 G 3.613
+(da).15 G(nd)494 543.6 Q .365(published by the IEEE, and w)72 555.6 R .365
+(ork is currently underw)-.1 F .365(ay to update it.)-.1 F .365
+(There are four primary areas of w)5.365 F(ork)-.1 E(in the 1003.2 standard:)72
+567.6 Q 21.5<8341>72 583.2 S .835(spects of the shell')104.22 583.2 R 3.335(ss)
+-.55 G .835(yntax and command language.)192 583.2 R 3.335(An)5.835 G .835
+(umber of special b)338.095 583.2 R .835(uiltins such as)-.2 F F2(cd)3.335 E F3
+(and)3.335 E F2(exec)97 595.2 Q F3 .545(are being speci\214ed as part of the s\
+hell, since their functionality usually cannot be implemented)3.046 F
+(by a separate e)97 607.2 Q -.15(xe)-.15 G(cutable;).15 E 21.5<8341>72 622.8 S
+.73(set of utilities to be called by shell scripts and applications.)107.45
+622.8 R .731(Examples are programs lik)5.731 F(e)-.1 E F1 2.397(sed, tr)3.231 F
+(,)-1.11 E F3(and)97 634.8 Q F1(awk.)2.853 E F3 .352
+(Utilities commonly implemented as shell b)4.519 F .352
+(uiltins are described in this section, such as)-.2 F F2(test)2.852 E F3(and)97
+646.8 Q F2(kill)3.422 E F3 5.922(.A)C 3.422(ne)144.404 646.8 S .922
+(xpansion of this section')157.116 646.8 R 3.423(ss)-.55 G .923
+(cope, termed the User Portability Extension, or UPE, has)268.586 646.8 R
+(standardized interacti)97 658.8 Q .3 -.15(ve p)-.25 H(rograms such as).15 E F1
+(vi)2.5 E F3(and)4.166 E F1(mailx;)2.5 E .32 LW 76 668.8 72 668.8 DL 80 668.8
+76 668.8 DL 84 668.8 80 668.8 DL 88 668.8 84 668.8 DL 92 668.8 88 668.8 DL 96
+668.8 92 668.8 DL 100 668.8 96 668.8 DL 104 668.8 100 668.8 DL 108 668.8 104
+668.8 DL 112 668.8 108 668.8 DL 116 668.8 112 668.8 DL 120 668.8 116 668.8 DL
+124 668.8 120 668.8 DL 128 668.8 124 668.8 DL 132 668.8 128 668.8 DL 136 668.8
+132 668.8 DL 140 668.8 136 668.8 DL 144 668.8 140 668.8 DL/F5 8/Times-Roman@0
+SF(*An earlier v)72 678.8 Q
+(ersion of this article appeared in The Linux Journal.)-.12 E<87>72 688.8 Q/F6
+7/Times-Roman@0 SF(UNIX)2 E F5(is a trademark of Bell Laboratories.)2 E
+(\210IEEE,)72 698.8 Q/F7 8/Times-Italic@0 SF .042(IEEE Standar)2.042 F 2.042
+(df)-.296 G .042(or Information T)150.046 698.8 R(ec)-.736 E(hnolo)-.12 E .042
+(gy -- P)-.08 F .042(ortable Oper)-.64 F .042
+(ating System Interface \(POSIX\) P)-.12 F .042(art 2: Shell and Utili-)-.64 F
+(ties)72 708.8 Q F5 2(,1)C(992.)91.112 708.8 Q EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-2-)279.67 48 S 21.5<8341>72 84 S .288
+(group of functional interf)107.008 84 R .287(aces to services pro)-.1 F .287
+(vided by the shell, such as the traditional)-.15 F/F1 10/Courier@0 SF
+(system\(\))2.787 E F0 3.289(Cl)97 96 S .789(ibrary function.)109.739 96 R .789
+(There are functions to perform shell w)5.789 F .789(ord e)-.1 F .79
+(xpansions, perform \214lename e)-.15 F(xpan-)-.15 E .324(sion \()97 108 R/F2
+10/Times-Italic@0 SF(globbing)A F0 .324(\), obtain v)B .323
+(alues of POSIX.2 system con\214guration v)-.25 F .323(ariables, retrie)-.25 F
+.623 -.15(ve v)-.25 H .323(alues of en)-.1 F(viron-)-.4 E(ment v)97 120 Q
+(ariables \()-.25 E F1(getenv\(\))A F0(\), and other services;).833 E 21.5
+<8341>72 135.6 S(suite of `)106.72 135.6 Q(`de)-.74 E -.15(ve)-.25 G(lopment')
+.15 E 2.5('u)-.74 G(tilities such as)209.54 135.6 Q F2(c89)2.5 E F0
+(\(the POSIX.2 v)4.166 E(ersion of)-.15 E F2(cc)2.5 E F0(\), and)A F2(yacc.)2.5
+E F0 .483(Bash is concerned with the aspects of the shell')97 151.2 R 2.983(sb)
+-.55 G(eha)301.597 151.2 Q .484(vior de\214ned by POSIX.2.)-.2 F .484
+(The shell command)5.484 F 1.439
+(language has of course been standardized, including the basic \215o)72 163.2 R
+3.938(wc)-.25 G 1.438(ontrol and program e)359.688 163.2 R -.15(xe)-.15 G 1.438
+(cution con-).15 F 1.145(structs, I/O redirection and pipelining, ar)72 175.2 R
+1.145(gument handling, v)-.18 F 1.145(ariable e)-.25 F 1.146
+(xpansion, and quoting.)-.15 F(The)6.146 E F2(special)3.646 E F0 -.2(bu)72
+187.2 S .676(iltins, which must be implemented as part of the shell to pro).2 F
+.676(vide the desired functionality)-.15 F 3.176(,a)-.65 G .676(re speci\214ed)
+457.504 187.2 R .7(as being part of the shell; e)72 199.2 R .7
+(xamples of these are)-.15 F/F3 10/Times-Bold@0 SF -2.3 -.15(ev a)3.201 H(l).15
+E F0(and)3.201 E F3(export)3.201 E F0 5.701(.O)C .701
+(ther utilities appear in the sections of)352.034 199.2 R .256(POSIX.2 not de)
+72 211.2 R -.2(vo)-.25 G .256(ted to the shell which are commonly \(and in som\
+e cases must be\) implemented as b).2 F(uiltin)-.2 E .213(commands, such as)72
+223.2 R F3 -.18(re)2.713 G(ad).18 E F0(and)2.713 E F3(test)2.713 E F0 5.213(.P)
+C .213(OSIX.2 also speci\214es aspects of the shell')220.018 223.2 R 2.713(si)
+-.55 G(nteracti)398.159 223.2 Q .513 -.15(ve b)-.25 H(eha).15 E .214
+(vior as part)-.2 F .598
+(of the UPE, including job control and command line editing.)72 235.2 R .598
+(Interestingly enough, only)5.598 F F2(vi)3.098 E F0 .598(-style line edit-)B
+(ing commands ha)72 247.2 Q .3 -.15(ve b)-.2 H(een standardized;).15 E F2
+(emacs)2.5 E F0(editing commands were left out due to objections.)2.5 E 1.128
+(While POSIX.2 includes much of what the shell has traditionally pro)97 262.8 R
+1.129(vided, some important things)-.15 F(ha)72 274.8 Q .58 -.15(ve b)-.2 H .28
+(een omitted as being `).15 F(`be)-.74 E .28(yond its scope.)-.15 F 4.26 -.74
+('' T)-.7 H .28(here is, for instance, no mention of a dif).74 F .28
+(ference between)-.25 F(a)72 286.8 Q F2(lo)3.354 E(gin)-.1 E F0 .854
+(shell and an)5.02 F 3.354(yo)-.15 G .854(ther interacti)167.956 286.8 R 1.154
+-.15(ve s)-.25 H .854(hell \(since POSIX.2 does not specify a login program\).)
+.15 F .855(No \214x)5.855 F(ed)-.15 E
+(startup \214les are de\214ned, either \255 the standard does not mention)72
+298.8 Q F2(.pr)2.5 E(o\214le)-.45 E F0(.)1.666 E F3 2.5(3. Basic)72 322.8 R
+(Bash featur)2.5 E(es)-.18 E F0 1.448(Since the Bourne shell pro)97 338.4 R
+1.448(vides Bash with most of its philosophical underpinnings, Bash inherits)
+-.15 F .64(most of its features and functionality from sh.)72 350.4 R .641
+(Bash implements all of the traditional sh \215o)5.641 F 3.141(wc)-.25 G .641
+(ontrol con-)459.199 350.4 R .8(structs \()72 362.4 R F2(for)A F0(,)A F2(if)3.3
+E F0(,)A F2(while)3.3 E F0 3.3(,e)C 3.3(tc.\). All)165.48 362.4 R .799
+(of the Bourne shell b)3.3 F .799
+(uiltins, including those not speci\214ed in the POSIX.2)-.2 F .536
+(standard, appear in Bash.)72 374.4 R(Shell)5.536 E F2(functions)3.036 E F0
+3.036(,i)C .536(ntroduced in the SVR2 v)248.536 374.4 R .537
+(ersion of the Bourne shell, are similar)-.15 F .779(to shell scripts, b)72
+386.4 R .779(ut are de\214ned using a special syntax and are e)-.2 F -.15(xe)
+-.15 G .779(cuted in the same process as the calling).15 F 2.841(shell. Bash)72
+398.4 R .341(has shell functions which beha)2.841 F .641 -.15(ve i)-.2 H 2.841
+(naf).15 G .341(ashion upw)278.759 398.4 R .342
+(ard-compatible with sh functions.)-.1 F .342(There are)5.342 F 1.447
+(certain shell v)72 410.4 R 1.446(ariables that Bash interprets in the same w)
+-.25 F 1.446(ay as sh, such as)-.1 F F3(PS1)3.946 E F0(,)A F3(IFS)3.946 E F0
+3.946(,a)C(nd)435.018 410.4 Q F3 -.74(PA)3.946 G(TH)-.21 E F0 6.446(.B)C(ash)
+490.67 410.4 Q 1.423(implements essentially the same grammar)72 422.4 R 3.924
+(,p)-.4 G 1.424(arameter and v)256.476 422.4 R 1.424(ariable e)-.25 F 1.424
+(xpansion semantics, redirection, and)-.15 F 1.06(quoting as the Bourne shell.)
+72 434.4 R 1.06(Where dif)6.06 F 1.06
+(ferences appear between the POSIX.2 standard and traditional sh)-.25 F(beha)72
+446.4 Q(vior)-.2 E 2.5(,B)-.4 G(ash follo)118.06 446.4 Q(ws POSIX.)-.25 E 1.608
+(The K)97 462 R 1.608(orn Shell \()-.35 F F3(ksh)A F0 4.108(\)i)C 4.108(sad)
+194.192 462 S 1.608(escendent of the Bourne shell written at A)215.738 462 R
+1.609(T&T Bell Laboratories by)-1.11 F(Da)72 474 Q 1.059(vid K)-.2 F 3.559
+(orn\207. It)-.35 F(pro)3.559 E 1.059
+(vides a number of useful features that POSIX and Bash ha)-.15 F 1.359 -.15
+(ve a)-.2 H 3.558(dopted. Man).15 F 3.558(yo)-.15 G 3.558(ft)484.892 474 S(he)
+494.56 474 Q(interacti)72 486 Q 1.312 -.15(ve f)-.25 H 1.012
+(acilities in POSIX.2 ha).05 F 1.312 -.15(ve t)-.2 H 1.012
+(heir roots in the ksh: for e).15 F 1.013
+(xample, the POSIX and ksh job control)-.15 F -.1(fa)72 498 S .513
+(cilities are nearly identical. Bash includes features from the K).1 F .513
+(orn Shell for both interacti)-.35 F .813 -.15(ve u)-.25 H .513(se and shell)
+.15 F 3.905(programming. F)72 510 R 1.405(or programming, Bash pro)-.15 F 1.405
+(vides v)-.15 F 1.405(ariables such as)-.25 F F3(RANDOM)3.905 E F0(and)3.905 E
+F3(REPL)3.905 E(Y)-.92 E F0 3.905(,t)C(he)460.665 510 Q F3(typeset)3.905 E F0
+-.2(bu)72 522 S .398(iltin, the ability to remo).2 F .698 -.15(ve s)-.15 H .398
+(ubstrings from v).15 F .398(ariables based on patterns, and shell arithmetic.)
+-.25 F F3(RANDOM)5.397 E F0 -.15(ex)72 534 S .489
+(pands to a random number each time it is referenced; assigning a v).15 F .49
+(alue to)-.25 F F3(RANDOM)2.99 E F0 .49(seeds the random)2.99 F .055
+(number generator)72 546 R(.)-.55 E F3(REPL)5.055 E(Y)-.92 E F0 .054
+(is the def)2.554 F .054(ault v)-.1 F .054(ariable used by the)-.25 F F3 -.18
+(re)2.554 G(ad).18 E F0 -.2(bu)2.554 G .054(iltin when no v).2 F .054
+(ariable names are sup-)-.25 F .742(plied as ar)72 558 R 3.243(guments. The)
+-.18 F F3(typeset)3.243 E F0 -.2(bu)3.243 G .743(iltin is used to de\214ne v).2
+F .743(ariables and gi)-.25 F 1.043 -.15(ve t)-.25 H .743(hem attrib).15 F .743
+(utes such as)-.2 F F3 -.18(re)3.243 G(ad-).18 E(only)72 570 Q F0 5.512(.B)C
+.512(ash arithmetic allo)105.022 570 R .512(ws the e)-.25 F -.25(va)-.25 G .511
+(luation of an e).25 F .511(xpression and the substitution of the result.)-.15
+F .511(Shell v)5.511 F(ari-)-.25 E .222
+(ables may be used as operands, and the result of an e)72 582 R .222
+(xpression may be assigned to a v)-.15 F 2.722(ariable. Nearly)-.25 F .222
+(all of)2.722 F(the operators from the C language are a)72 594 Q -.25(va)-.2 G
+(ilable, with the same precedence rules:).25 E F1 6($e)97 612 S
+(cho $\(\(3 + 5 * 32\)\))115 612 Q(163)97 624 Q F0 -.15(Fo)72 645.6 S 3.24(ri)
+.15 G(nteracti)91.76 645.6 Q 1.04 -.15(ve u)-.25 H .74
+(se, Bash implements ksh-style aliases and b).15 F .74(uiltins such as)-.2 F F3
+(fc)3.24 E F0 .74(\(discussed belo)3.24 F .74(w\) and)-.25 F F3(jobs)3.24 E F0
+(.)A .291(Bash aliases allo)72 657.6 R 2.791(was)-.25 G .291
+(tring to be substituted for a command name.)160.124 657.6 R(The)5.291 E 2.791
+(yc)-.15 G .291(an be used to create a mnemonic)371.733 657.6 R .568(for a)72
+669.6 R/F4 9/Times-Roman@0 SF(UNIX)3.068 E F0 .568(command name \()3.068 F F1
+.568(alias del=rm)B F0 .568(\), to e)B .567(xpand a single w)-.15 F .567
+(ord to a comple)-.1 F 3.067(xc)-.15 G .567(ommand \()432.603 669.6 R F1(alias)
+A .255(news='xterm -g 80x45 -title trn -e trn -e -S1 -N &')72 681.6 R F0 .255
+(\), or to ensure that a command)B(is in)72 693.6 Q -.2(vo)-.4 G -.1(ke).2 G
+2.5(dw).1 G(ith a basic set of options \()122.41 693.6 Q F1
+(alias ls="/bin/ls -F")A F0(\).)A .32 LW 76 703.6 72 703.6 DL 80 703.6 76 703.6
+DL 84 703.6 80 703.6 DL 88 703.6 84 703.6 DL 92 703.6 88 703.6 DL 96 703.6 92
+703.6 DL 100 703.6 96 703.6 DL 104 703.6 100 703.6 DL 108 703.6 104 703.6 DL
+112 703.6 108 703.6 DL 116 703.6 112 703.6 DL 120 703.6 116 703.6 DL 124 703.6
+120 703.6 DL 128 703.6 124 703.6 DL 132 703.6 128 703.6 DL 136 703.6 132 703.6
+DL 140 703.6 136 703.6 DL 144 703.6 140 703.6 DL/F5 8/Times-Roman@0 SF
+(\207Morris Bolsk)72 713.6 Q 2(ya)-.12 G(nd Da)127.88 713.6 Q(vid K)-.16 E
+(orn,)-.28 E/F6 8/Times-Italic@0 SF(The K)2 E(ornShell Command and Pr)-.32 E
+-.08(og)-.36 G -.12(ra).08 G(mming Langua).12 E -.08(ge)-.08 G F5 2(,P).08 G
+(rentice Hall, 1989.)363.064 713.6 Q EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-3-)279.67 48 S .293(The C shell \()97 84 R/F1 10
+/Times-Bold@0 SF(csh)A F0 .293(\)\207, originally written by Bill Jo)B 2.792
+(yw)-.1 G .292(hile at Berk)304.534 84 R(ele)-.1 E 1.592 -.65(y, i)-.15 H 2.792
+(sw).65 G .292(idely used and quite popular)389.512 84 R 1.252
+(for its interacti)72 96 R 1.552 -.15(ve f)-.25 H 3.752(acilities. Bash).05 F
+1.253(includes a csh-compatible history e)3.752 F 1.253(xpansion mechanism \(`)
+-.15 F 1.253(`! history')-.74 F('\),)-.74 E .019(brace e)72 108 R .018
+(xpansion, access to a stack of directories via the)-.15 F F1(pushd)2.518 E F0
+(,)A F1(popd)2.518 E F0 2.518(,a)C(nd)357.31 108 Q F1(dirs)2.518 E F0 -.2(bu)
+2.518 G .018(iltins, and tilde e).2 F(xpansion,)-.15 E 1.293
+(to generate users' home directories.)72 120 R -.35(Ti)6.294 G 1.294(lde e).35
+F 1.294(xpansion has also been adopted by both the K)-.15 F 1.294
+(orn Shell and)-.35 F(POSIX.2.)72 132 Q .148
+(There were certain areas in which POSIX.2 felt standardization w)97 147.6 R
+.149(as necessary)-.1 F 2.649(,b)-.65 G .149(ut no e)420.643 147.6 R .149
+(xisting imple-)-.15 F 1.598(mentation pro)72 159.6 R 1.598
+(vided the proper beha)-.15 F(vior)-.2 E 6.598(.T)-.55 G 1.598(he w)251.56
+159.6 R 1.597(orking group in)-.1 F -.15(ve)-.4 G 1.597
+(nted and standardized functionality in).15 F .674
+(these areas, which Bash implements.)72 171.6 R(The)5.674 E F1(command)3.174 E
+F0 -.2(bu)3.174 G .674(iltin w).2 F .674(as in)-.1 F -.15(ve)-.4 G .674
+(nted so that shell functions could be).15 F .996(written to replace b)72 183.6
+R .996(uiltins; it mak)-.2 F .996(es the capabilities of the b)-.1 F .995
+(uiltin a)-.2 F -.25(va)-.2 G .995(ilable to the function.).25 F .995
+(The reserv)5.995 F(ed)-.15 E -.1(wo)72 195.6 S 1.566(rd `).1 F(`!')-.74 E
+4.066('w)-.74 G 1.566(as added to ne)122.872 195.6 R -.05(ga)-.15 G 1.567
+(te the return v).05 F 1.567(alue of a command or pipeline; it w)-.25 F 1.567
+(as nearly impossible to)-.1 F -.15(ex)72 207.6 S .089(press `).15 F .089
+(`if not x')-.74 F 2.589('c)-.74 G .089(leanly using the sh language.)152.366
+207.6 R .089(There e)5.089 F .088
+(xist multiple incompatible implementations of the)-.15 F F1(test)72 219.6 Q F0
+-.2(bu)3.163 G .663(iltin, which tests \214les for type and other attrib).2 F
+.664(utes and performs arithmetic and string comparisons.)-.2 F .5
+(POSIX considered none of these correct, so the standard beha)72 231.6 R .5
+(vior w)-.2 F .5(as speci\214ed in terms of the number of)-.1 F(ar)72 243.6 Q
+.412(guments to the command.)-.18 F .412(POSIX.2 dictates e)5.412 F .412
+(xactly what will happen when four or fe)-.15 F .412(wer ar)-.25 F .412
+(guments are)-.18 F(gi)72 255.6 Q -.15(ve)-.25 G 5.01(nt).15 G(o)101.61 255.6 Q
+F1(test)5.01 E F0 5.01(,a)C 2.51(nd lea)138.56 255.6 R -.15(ve)-.2 G 5.01(st)
+.15 G 2.51(he beha)186 255.6 R 2.51(vior unde\214ned when more ar)-.2 F 2.51
+(guments are supplied.)-.18 F 2.51(Bash uses the)7.51 F
+(POSIX.2 algorithm, which w)72 267.6 Q(as concei)-.1 E -.15(ve)-.25 G 2.5(db)
+.15 G 2.5(yD)247.31 267.6 S -.2(av)262.03 267.6 S(id K).2 E(orn.)-.35 E F1 2.5
+(3.1. F)72 291.6 R(eatur)-.25 E(es not in the Bour)-.18 E(ne Shell)-.15 E F0
+.718(There are a number of minor dif)97 307.2 R .719
+(ferences between Bash and the v)-.25 F .719
+(ersion of sh present on most other)-.15 F -.15(ve)72 319.2 S .874(rsions of)
+.15 F/F2 9/Times-Roman@0 SF(UNIX)3.374 E F0 5.873(.T)C .873
+(he majority of these are due to the POSIX standard, b)157.232 319.2 R .873
+(ut some are the result of Bash)-.2 F .188
+(adopting features from other shells.)72 331.2 R -.15(Fo)5.188 G 2.689(ri).15 G
+.189(nstance, Bash includes the ne)239.069 331.2 R 2.689(w`)-.25 G(`!')369.554
+331.2 Q 2.689('r)-.74 G(eserv)388.153 331.2 Q .189(ed w)-.15 F .189(ord, the)
+-.1 F F1(command)2.689 E F0 -.2(bu)72 343.2 S .116(iltin, the ability of the).2
+F F1 -.18(re)2.616 G(ad).18 E F0 -.2(bu)2.615 G .115
+(iltin to correctly return a line ending with a backslash, symbolic ar).2 F
+(guments)-.18 E .798(to the)72 355.2 R F1(umask)3.298 E F0 -.2(bu)3.298 G .798
+(iltin, v).2 F .798(ariable substring remo)-.25 F -.25(va)-.15 G .798(l, a w)
+.25 F .799(ay to get the length of a v)-.1 F .799(ariable, and the ne)-.25 F
+3.299(wa)-.25 G(lgo-)487.89 355.2 Q(rithm for the)72 367.2 Q F1(test)2.5 E F0
+-.2(bu)2.5 G(iltin from the POSIX.2 standard, none of which appear in sh.).2 E
+.998(Bash also implements the `)97 382.8 R(`$\(...\)')-.74 E 3.498('c)-.74 G
+.998(ommand substitution syntax, which supersedes the sh `...` con-)244.93
+382.8 R 2.654(struct. The)72 394.8 R -.74(``)2.654 G($\(...\)').74 E 2.654('c)
+-.74 G .154(onstruct e)158.172 394.8 R .154
+(xpands to the output of the command contained within the parentheses, with)
+-.15 F .467(trailing ne)72 406.8 R .467(wlines remo)-.25 F -.15(ve)-.15 G 2.967
+(d. The).15 F .467(sh syntax is accepted for backw)2.967 F .467
+(ards compatibility)-.1 F 2.966(,b)-.65 G .466(ut the `)415.026 406.8 R
+(`$\(...\)')-.74 E 2.966('f)-.74 G .466(orm is)478.254 406.8 R(preferred becau\
+se its quoting rules are much simpler and it is easier to nest.)72 418.8 Q .772
+(The Bourne shell does not pro)97 434.4 R .772(vide such features as brace e)
+-.15 F .772(xpansion, the ability to de\214ne a v)-.15 F(ariable)-.25 E .283
+(and a function with the same name, local v)72 446.4 R .282
+(ariables in shell functions, the ability to enable and disable indi-)-.25 F
+.547(vidual b)72 458.4 R .547(uiltins or write a function to replace a b)-.2 F
+.547(uiltin, or a means to e)-.2 F .547(xport a shell function to a child pro-)
+-.15 F(cess.)72 470.4 Q .32
+(Bash has closed a long-standing shell security hole by not using the)97 486 R
+F1($IFS)2.82 E F0 -.25(va)2.82 G .32(riable to split each w).25 F(ord)-.1 E
+1.254(read by the shell, b)72 498 R 1.254(ut splitting only the results of e)
+-.2 F 1.255(xpansion \(ksh and the 4.4 BSD sh ha)-.15 F 1.555 -.15(ve \214)-.2
+H -.15(xe).15 G 3.755(dt).15 G 1.255(his as)480.245 498 R 2.752(well\). Useful)
+72 510 R(beha)2.751 E .251(vior such as a means to abort e)-.2 F -.15(xe)-.15 G
+.251(cution of a script read with the `).15 F(`.)-.74 E 1.731 -.74('' c)-.7 H
+.251(ommand using the).74 F F1 -.18(re)72 522 S(tur).18 E(n)-.15 E F0 -.2(bu)
+2.742 G .242(iltin or automatically e).2 F .242(xporting v)-.15 F .243
+(ariables in the shell')-.25 F 2.743(se)-.55 G -.4(nv)336.842 522 S .243
+(ironment to children is also not present).4 F .969(in the Bourne shell.)72 534
+R .968(Bash pro)5.968 F .968(vides a much more po)-.15 F .968(werful en)-.25 F
+.968(vironment for both interacti)-.4 F 1.268 -.15(ve u)-.25 H .968
+(se and pro-).15 F(gramming.)72 546 Q F1 2.5(4. Bash-speci\214c)72 570 R -.25
+(Fe)2.5 G(atur).25 E(es)-.18 E F0 .491(This section details a fe)97 585.6 R
+2.991(wo)-.25 G 2.991(ft)208.355 585.6 S .491(he features which mak)217.456
+585.6 R 2.991(eB)-.1 G .491(ash unique.)323.18 585.6 R .492(Most of them pro)
+5.491 F .492(vide impro)-.15 F -.15(ve)-.15 G(d).15 E(interacti)72 597.6 Q
+1.182 -.15(ve u)-.25 H .882(se, b).15 F .882(ut a fe)-.2 F 3.382(wp)-.25 G .882
+(rogramming impro)183.31 597.6 R -.15(ve)-.15 G .882
+(ments are present as well.).15 F .882(Full descriptions of these fea-)5.882 F
+(tures can be found in the Bash documentation.)72 609.6 Q F1 2.5(4.1. Startup)
+72 633.6 R(Files)2.5 E F0 .161(Bash e)97 649.2 R -.15(xe)-.15 G .161
+(cutes startup \214les dif).15 F .161(ferently than other shells.)-.25 F .162
+(The Bash beha)5.161 F .162(vior is a compromise between)-.2 F .116
+(the csh principle of startup \214les with \214x)72 661.2 R .116(ed names e)
+-.15 F -.15(xe)-.15 G .116(cuted for each shell and the sh `).15 F
+(`minimalist')-.74 E 2.615('b)-.74 G(eha)472.26 661.2 Q(vior)-.2 E(.)-.55 E
+2.844(An interacti)72 673.2 R 3.144 -.15(ve i)-.25 H 2.844
+(nstance of Bash started as a login shell reads and e).15 F -.15(xe)-.15 G
+(cutes).15 E/F3 10/Times-Italic@0 SF(~/.bash_pr)5.345 E(o\214le)-.45 E F0 2.845
+(\(the \214le)7.011 F .954(.bash_pro\214le in the user')72 685.2 R 3.454(sh)
+-.55 G .953(ome directory\), if it e)186.086 685.2 R 3.453(xists. An)-.15 F
+(interacti)3.453 E 1.253 -.15(ve n)-.25 H .953(on-login shell reads and e).15 F
+-.15(xe)-.15 G(cutes).15 E .32 LW 76 695.2 72 695.2 DL 80 695.2 76 695.2 DL 84
+695.2 80 695.2 DL 88 695.2 84 695.2 DL 92 695.2 88 695.2 DL 96 695.2 92 695.2
+DL 100 695.2 96 695.2 DL 104 695.2 100 695.2 DL 108 695.2 104 695.2 DL 112
+695.2 108 695.2 DL 116 695.2 112 695.2 DL 120 695.2 116 695.2 DL 124 695.2 120
+695.2 DL 128 695.2 124 695.2 DL 132 695.2 128 695.2 DL 136 695.2 132 695.2 DL
+140 695.2 136 695.2 DL 144 695.2 140 695.2 DL/F4 8/Times-Roman@0 SF .764
+(\207Bill Jo)72 705.2 R 1.804 -.52(y, A)-.08 H 2.764(nI).52 G .764
+(ntroduction to the C Shell,)121.252 705.2 R/F5 8/Times-Italic@0 SF .763
+(UNIX User')2.764 F 2.763(sS)-.32 G .763(upplementary Documents)260.942 705.2 R
+F4 2.763(,U)C(ni)354.228 705.2 Q -.12(ve)-.2 G .763
+(rsity of California at Berk).12 F(ele)-.08 E -.52(y,)-.12 G(1986.)72 715.2 Q
+EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-4-)279.67 48 S/F1 10/Times-Italic@0 SF(~/.bashr)72
+84 Q(c)-.37 E F0 5.537(.A)1.666 G(non-interacti)127.42 84 Q .837 -.15(ve s)-.25
+H .537(hell \(one be).15 F .538(gun to e)-.15 F -.15(xe)-.15 G .538
+(cute a shell script, for e).15 F .538(xample\) reads no \214x)-.15 F .538
+(ed startup)-.15 F .342(\214le, b)72 96 R .342(ut uses the v)-.2 F .342
+(alue of the v)-.25 F(ariable)-.25 E/F2 10/Times-Bold@0 SF($ENV)2.842 E F0
+2.841(,i)C 2.841(fs)260.187 96 S .341(et, as the name of a startup \214le.)
+270.248 96 R .341(The ksh practice of read-)5.341 F(ing)72 108 Q F2($ENV)3.114
+E F0 .614(for e)3.114 F -.15(ve)-.25 G .614(ry shell, with the accompan).15 F
+.615(ying dif)-.15 F .615(\214culty of de\214ning the proper v)-.25 F .615
+(ariables and functions)-.25 F .721(for interacti)72 120 R 1.021 -.15(ve a)-.25
+H .721(nd non-interacti).15 F 1.021 -.15(ve s)-.25 H .721(hells or ha).15 F
+.721(ving the \214le read only for interacti)-.2 F 1.02 -.15(ve s)-.25 H .72
+(hells, w).15 F .72(as considered)-.1 F .158(too comple)72 132 R 2.658(x. Ease)
+-.15 F .158(of use w)2.658 F .158(on out here.)-.1 F(Interestingly)5.158 E
+2.658(,t)-.65 G .158(he ne)295.822 132 R .159
+(xt release of ksh will change to reading)-.15 F F2($ENV)2.659 E F0
+(only for interacti)72 144 Q .3 -.15(ve s)-.25 H(hells.).15 E F2 2.5(4.2. New)
+72 168 R(Builtin Commands)2.5 E F0 1.02(There are a fe)97 183.6 R 3.52(wb)-.25
+G 1.02(uiltins which are ne)170.59 183.6 R 3.52(wo)-.25 G 3.52(rh)267.74 183.6
+S -2.25 -.2(av e)279.59 183.6 T 1.02(been e)3.72 F 1.02(xtended in Bash.)-.15 F
+(The)6.02 E F2(enable)3.52 E F0 -.2(bu)3.52 G 1.02(iltin allo).2 F(ws)-.25 E
+-.2(bu)72 195.6 S .736(iltin commands to be turned on and of).2 F 3.236(fa)-.25
+G(rbitrarily)250.198 195.6 Q 5.736(.T)-.65 G 3.237(ou)298.644 195.6 S .737
+(se the v)311.881 195.6 R .737(ersion of)-.15 F F1(ec)3.237 E(ho)-.15 E F0 .737
+(found in a user')4.903 F 3.237(ss)-.55 G(earch)482.35 195.6 Q .625
+(path rather than the Bash b)72 207.6 R(uiltin,)-.2 E/F3 10/Courier@0 SF .625
+(enable -n echo)3.125 F F0(suf)3.125 E 3.125(\214ces. The)-.25 F F2(help)3.124
+E F0 -.2(bu)3.124 G .624(iltin pro).2 F .624(vides quick synopses)-.15 F .703
+(of the shell f)72 219.6 R .704
+(acilities without requiring access to a manual page.)-.1 F F2(Builtin)5.704 E
+F0 .704(is similar to)3.204 F F2(command)3.204 E F0 .704(in that it)3.204 F
+.342(bypasses shell functions and directly e)72 231.6 R -.15(xe)-.15 G .342
+(cutes b).15 F .342(uiltin commands.)-.2 F .342
+(Access to a csh-style stack of directories)5.342 F .072(is pro)72 243.6 R .073
+(vided via the)-.15 F F2(pushd)2.573 E F0(,)A F2(popd)2.573 E F0 2.573(,a)C(nd)
+211.197 243.6 Q F2(dirs)2.573 E F0 -.2(bu)2.573 G(iltins.).2 E F2(Pushd)5.073 E
+F0(and)2.573 E F2(popd)2.573 E F0 .073(insert and remo)2.573 F .373 -.15(ve d)
+-.15 H .073(irectories from the).15 F 2.858(stack, respecti)72 255.6 R -.15(ve)
+-.25 G(ly).15 E 5.358(,a)-.65 G(nd)159.976 255.6 Q F2(dirs)5.358 E F0 2.858
+(lists the stack contents.)5.358 F 2.858(On systems that allo)7.858 F 5.358
+<778c>-.25 G 2.857(ne-grained control of)413.866 255.6 R 1.339(resources, the)
+72 267.6 R F2(ulimit)3.839 E F0 -.2(bu)3.839 G 1.339
+(iltin can be used to tune these settings.).2 F F2(Ulimit)6.34 E F0(allo)3.84 E
+1.34(ws a user to control, among)-.25 F 1.086
+(other things, whether core dumps are to be generated, ho)72 279.6 R 3.586(wm)
+-.25 G 1.086(uch memory the shell or a child process is)327.002 279.6 R(allo)72
+291.6 Q .496(wed to allocate, and ho)-.25 F 2.996(wl)-.25 G(ar)193.96 291.6 Q
+.496(ge a \214le created by a child process can gro)-.18 F 4.296 -.65(w. T)-.25
+H(he).65 E F2(suspend)2.996 E F0 .497(command will)2.997 F .744
+(stop the shell process when job control is acti)72 303.6 R -.15(ve)-.25 G
+3.243(;m).15 G .743(ost other shells do not allo)282.443 303.6 R 3.243(wt)-.25
+G(hemselv)404.431 303.6 Q .743(es to be stopped)-.15 F(lik)72 315.6 Q 2.717(et)
+-.1 G(hat.)92.397 315.6 Q F2 -.74(Ty)5.217 G(pe,).74 E F0 .217
+(the Bash answer to)2.717 F F2(which)2.717 E F0(and)2.717 E F2(whence,)2.717 E
+F0(sho)2.717 E .218(ws what will happen when a w)-.25 F .218(ord is typed as a)
+-.1 F(command:)72 327.6 Q F3 6($t)97 345.6 S(ype export)115 345.6 Q
+(export is a shell builtin)97 357.6 Q 6($t)97 369.6 S(ype -t export)115 369.6 Q
+(builtin)97 381.6 Q 6($t)97 393.6 S(ype bash)115 393.6 Q(bash is /bin/bash)97
+405.6 Q 6($t)97 417.6 S(ype cd)115 417.6 Q(cd is a function)97 429.6 Q(cd \(\))
+97 441.6 Q({)97 453.6 Q(builtin cd ${1+"$@"} && xtitle $HOST: $PWD)121 465.6 Q
+(})97 477.6 Q F0 -1.11(Va)72 499.2 S .682(rious modes tell what a command w)
+1.11 F .681(ord is \(reserv)-.1 F .681(ed w)-.15 F .681
+(ord, alias, function, b)-.1 F .681(uiltin, or \214le\) or which v)-.2 F(er)
+-.15 E(-)-.2 E 1.15(sion of a command will be e)72 511.2 R -.15(xe)-.15 G 1.15
+(cuted based on a user').15 F 3.65(ss)-.55 G 1.15(earch path.)305.7 511.2 R
+1.15(Some of this functionality has been)6.15 F
+(adopted by POSIX.2 and folded into the)72 523.2 Q F2(command)2.5 E F0(utility)
+2.5 E(.)-.65 E F2 2.5(4.3. Editing)72 547.2 R(and Completion)2.5 E F0 .584
+(One area in which Bash shines is command line editing.)97 562.8 R .584
+(Bash uses the)5.584 F F1 -.37(re)3.084 G(adline).37 E F0 .583
+(library to read and)4.749 F .942(edit lines when interacti)72 574.8 R -.15(ve)
+-.25 G 5.942(.R).15 G .942(eadline is a po)194.798 574.8 R .942
+(werful and \215e)-.25 F .942(xible input f)-.15 F .943
+(acility that a user can con\214gure to)-.1 F(indi)72 586.8 Q .732
+(vidual tastes.)-.25 F .732(It allo)5.732 F .732
+(ws lines to be edited using either emacs or vi commands, where those commands)
+-.25 F .2(are appropriate.)72 598.8 R .2
+(The full capability of emacs is not present \255 there is no w)5.2 F .2
+(ay to e)-.1 F -.15(xe)-.15 G .2(cute a named command).15 F 1.15
+(with M-x, for instance \255 b)72 610.8 R 1.15(ut the e)-.2 F 1.149
+(xisting commands are more than adequate.)-.15 F 1.149
+(The vi mode is compliant)6.149 F
+(with the command line editing standardized by POSIX.2.)72 622.8 Q 1.69
+(Readline is fully customizable.)97 638.4 R 1.691
+(In addition to the basic commands and k)6.69 F 1.991 -.15(ey b)-.1 H 1.691
+(indings, the library).15 F(allo)72 650.4 Q .83
+(ws users to de\214ne additional k)-.25 F 1.13 -.15(ey b)-.1 H .83
+(indings using a startup \214le.).15 F(The)5.83 E F1(inputr)3.329 E(c)-.37 E F0
+.829(\214le, which def)4.995 F .829(aults to the)-.1 F(\214le)72 662.4 Q F1
+(~/.inputr)4.287 E(c)-.37 E F0 4.287(,i)1.666 G 4.287(sr)137.43 662.4 S 1.788(\
+ead each time readline initializes, permitting users to maintain a consistent \
+interf)148.937 662.4 R(ace)-.1 E .547(across a set of programs.)72 674.4 R .546
+(Readline includes an e)5.546 F .546(xtensible interf)-.15 F .546
+(ace, so each program using the library can)-.1 F .23(add its o)72 686.4 R .23
+(wn bindable commands and program-speci\214c k)-.25 F .531 -.15(ey b)-.1 H
+2.731(indings. Bash).15 F .231(uses this f)2.731 F .231
+(acility to add bindings)-.1 F(that perform history e)72 698.4 Q
+(xpansion or shell w)-.15 E(ord e)-.1 E(xpansions on the current input line.)
+-.15 E .707(Readline interprets a number of v)97 714 R .706
+(ariables which further tune its beha)-.25 F(vior)-.2 E 5.706(.V)-.55 G .706
+(ariables e)408.432 714 R .706(xist to control)-.15 F .157
+(whether or not eight-bit characters are directly read as input or con)72 726 R
+-.15(ve)-.4 G .158(rted to meta-pre\214x).15 F .158(ed k)-.15 F .458 -.15(ey s)
+-.1 H .158(equences \(a).15 F EP
+%%Page: 5 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-5-)279.67 48 S(meta-pre\214x)72 84 Q 1.575(ed k)
+-.15 F 1.875 -.15(ey s)-.1 H 1.575
+(equence consists of the character with the eighth bit zeroed, preceded by the)
+.15 F/F1 10/Times-Italic@0 SF(meta-)4.074 E(pr)72 96 Q(e\214x)-.37 E F0
+(character)4.45 E 2.784(,u)-.4 G .284
+(sually escape, which selects an alternate k)145.374 96 R -.15(ey)-.1 G .285
+(map\), to decide whether to output characters).15 F .485
+(with the eighth bit set directly or as a meta-pre\214x)72 108 R .485(ed k)-.15
+F .784 -.15(ey s)-.1 H .484(equence, whether or not to wrap to a ne).15 F 2.984
+(ws)-.25 G(creen)482.35 108 Q .157
+(line when a line being edited is longer than the screen width, the k)72 120 R
+-.15(ey)-.1 G .158(map to which subsequent k).15 F .458 -.15(ey b)-.1 H
+(indings).15 E .531(should apply)72 132 R 3.031(,o)-.65 G 3.031(re)133.802 132
+S -.15(ve)144.353 132 S 3.031(nw).15 G .531(hat happens when readline w)168.894
+132 R .531(ants to ring the terminal')-.1 F 3.03(sb)-.55 G 3.03(ell. All)399.37
+132 R .53(of these v)3.03 F(ariables)-.25 E(can be set in the inputrc \214le.)
+72 144 Q .284(The startup \214le understands a set of C preprocessor)97 159.6 R
+(-lik)-.2 E 2.785(ec)-.1 G .285(onditional constructs which allo)329.49 159.6 R
+2.785(wv)-.25 G(ariables)472.9 159.6 Q .12(or k)72 171.6 R .42 -.15(ey b)-.1 H
+.119(indings to be assigned based on the application using readline, the termi\
+nal currently being used, or).15 F .338(the editing mode.)72 183.6 R .338
+(Users can add program-speci\214c bindings to mak)5.338 F 2.838(et)-.1 G .338
+(heir li)353.02 183.6 R -.15(ve)-.25 G 2.838(se).15 G 2.838(asier: I)397.176
+183.6 R(ha)2.838 E .639 -.15(ve b)-.2 H .339(indings that).15 F
+(let me edit the v)72 195.6 Q(alue of)-.25 E/F2 10/Times-Bold@0 SF($P)2.5 E
+-.95(AT)-.74 G(H).95 E F0(and double-quote the current or pre)2.5 E(vious w)
+-.25 E(ord:)-.1 E/F3 10/Courier@0 SF 6(#M)97 213.6 S
+(acros that are convenient for shell interaction)115 213.6 Q($if Bash)97 225.6
+Q 6(#e)97 237.6 S(dit the path)115 237.6 Q
+("\\C-xp": "PATH=${PATH}\\e\\C-e\\C-a\\ef\\C-f")97 249.6 Q 6(#p)97 261.6 S
+(repare to type a quoted word -- insert open and close double)115 261.6 Q 6(#q)
+97 273.6 S(uotes and move to just after the open quote)115 273.6 Q
+("\\C-x\\"": "\\"\\"\\C-b")97 285.6 Q 6(#Q)97 297.6 S
+(uote the current or previous word)115 297.6 Q("\\C-xq": "\\eb\\"\\ef\\"")97
+309.6 Q($endif)97 321.6 Q F0 .322(There is a readline command to re-read the \
+\214le, so users can edit the \214le, change some bindings, and be)72 343.2 R
+(gin)-.15 E(to use them almost immediately)72 355.2 Q(.)-.65 E .851
+(Bash implements the)97 370.8 R F2(bind)3.351 E F0 -.2(bu)3.351 G .851
+(iltin for more dyamic control of readline than the startup \214le permits.).2
+F F2(Bind)72 382.8 Q F0 .167(is used in se)2.667 F -.15(ve)-.25 G .167(ral w)
+.15 F 2.667(ays. In)-.1 F F1(list)2.667 E F0 .167
+(mode, it can display the current k)4.333 F .466 -.15(ey b)-.1 H .166
+(indings, list all the readline edit-).15 F .149(ing directi)72 394.8 R -.15
+(ve)-.25 G 2.649(sa).15 G -.25(va)132.798 394.8 S .149
+(ilable for binding, list which k).25 F -.15(ey)-.1 G 2.649(si).15 G -1.9 -.4
+(nv o)282.352 394.8 T .349 -.1(ke a g).4 H -2.15 -.25(iv e).1 H 2.65(nd).25 G
+(irecti)345.3 394.8 Q -.15(ve)-.25 G 2.65(,o).15 G 2.65(ro)385.04 394.8 S .15
+(utput the current set of k)396.02 394.8 R -.15(ey)-.1 G .526(bindings in a fo\
+rmat that can be incorporated directly into an inputrc \214le.)72 406.8 R(In)
+5.526 E F1(batc)3.026 E(h)-.15 E F0 .526(mode, it reads a series)4.692 F .71
+(of k)72 418.8 R 1.01 -.15(ey b)-.1 H .71
+(indings directly from a \214le and passes them to readline.).15 F .71
+(In its most common usage,)5.71 F F2(bind)3.21 E F0(tak)3.21 E .71(es a)-.1 F
+.534(single string and passes it directly to readline, which interprets the li\
+ne as if it had just been read from the)72 430.8 R(inputrc \214le.)72 442.8 Q
+(Both k)5 E .3 -.15(ey b)-.1 H(indings and v).15 E
+(ariable assignments may appear in the string gi)-.25 E -.15(ve)-.25 G 2.5(nt)
+.15 G(o)427.74 442.8 Q F2(bind)2.5 E F0(.)A .401(The readline library also pro)
+97 458.4 R .402(vides an interf)-.15 F .402(ace for)-.1 F F1(wor)2.902 E 2.902
+(dc)-.37 G(ompletion)328.546 458.4 Q F0 5.402(.W)C .402(hen the)385.888 458.4 R
+F1(completion)2.902 E F0(character)4.568 E 1.261(\(usually T)72 470.4 R 1.261
+(AB\) is typed, readline looks at the w)-.93 F 1.26
+(ord currently being entered and computes the set of \214le-)-.1 F .523
+(names of which the current w)72 482.4 R .523(ord is a v)-.1 F .523
+(alid pre\214x.)-.25 F .524
+(If there is only one possible completion, the rest of the)5.523 F .358
+(characters are inserted directly)72 494.4 R 2.858(,o)-.65 G .358(therwise the\
+ common pre\214x of the set of \214lenames is added to the current)205.232
+494.4 R -.1(wo)72 506.4 S 3.199(rd. A).1 F .699(second T)3.199 F .699(AB chara\
+cter entered immediately after a non-unique completion causes readline to list)
+-.93 F 1.814(the possible completions; there is an option to ha)72 518.4 R
+2.113 -.15(ve t)-.2 H 1.813(he list displayed immediately).15 F 6.813(.R)-.65 G
+1.813(eadline pro)436.517 518.4 R(vides)-.15 E .482
+(hooks so that applications can pro)72 530.4 R .482
+(vide speci\214c types of completion before the def)-.15 F .483
+(ault \214lename completion)-.1 F .132(is attempted.)72 542.4 R .132
+(This is quite \215e)5.132 F .132(xible, though it is not completely user)-.15
+F 2.632(-programmable. Bash,)-.2 F .132(for e)2.632 F .132(xample, can)-.15 F
+.37(complete \214lenames, command names \(including aliases, b)72 554.4 R .37
+(uiltins, shell reserv)-.2 F .37(ed w)-.15 F .37(ords, shell functions, and)-.1
+F -.15(exe)72 566.4 S .424(cutables found in the \214le system\), shell v).15 F
+.424(ariables, usernames, and hostnames.)-.25 F .423
+(It uses a set of heuristics)5.424 F(that, while not perfect, is generally qui\
+te good at determining what type of completion to attempt.)72 578.4 Q F2 2.5
+(4.4. History)72 602.4 R F0 .144(Access to the list of commands pre)97 618 R
+.144(viously entered \(the)-.25 F F1 .144(command history)2.644 F F0 2.644(\)i)
+C 2.644(sp)398.014 618 S(ro)409.548 618 Q .144(vided jointly by Bash)-.15 F
+.078(and the readline library)72 630 R 5.077(.B)-.65 G .077(ash pro)178.861 630
+R .077(vides v)-.15 F .077(ariables \()-.25 F F2($HISTFILE)A F0(,)A F2
+($HISTSIZE)2.577 E F0 2.577(,a)C(nd)391.916 630 Q F2($HISTCONTR)2.577 E(OL)-.3
+E F0 2.577(\)a)C(nd)494 630 Q(the)72 642 Q F2(history)2.89 E F0(and)2.89 E F2
+(fc)2.89 E F0 -.2(bu)2.89 G .39(iltins to manipulate the history list.).2 F
+.391(The v)5.391 F .391(alue of)-.25 F F2($HISTFILE)2.891 E F0 .391
+(specifes the \214le where)2.891 F .49(Bash writes the command history on e)72
+654 R .489(xit and reads it on startup.)-.15 F F2($HISTSIZE)5.489 E F0 .489
+(is used to limit the number)2.989 F .642(of commands sa)72 666 R -.15(ve)-.2 G
+3.142(di).15 G 3.142(nt)158.286 666 S .642(he history)169.208 666 R(.)-.65 E F2
+($HISTCONTR)5.642 E(OL)-.3 E F0(pro)3.142 E .642
+(vides a crude form of control o)-.15 F -.15(ve)-.15 G 3.142(rw).15 G .642
+(hich com-)463.088 666 R .32(mands are sa)72 678 R -.15(ve)-.2 G 2.819(do).15 G
+2.819(nt)146.199 678 S .319(he history list: a v)156.798 678 R .319(alue of)
+-.25 F F1(ignor)2.819 E(espace)-.37 E F0 .319(means to not sa)4.485 F .619 -.15
+(ve c)-.2 H .319(ommands which be).15 F .319(gin with)-.15 F 2.866(as)72 690 S
+.366(pace; a v)83.196 690 R .366(alue of)-.25 F F1(ignor)2.866 E(edups)-.37 E
+F0 .367(means to not sa)4.533 F .667 -.15(ve c)-.2 H .367
+(ommands identical to the last command sa).15 F -.15(ve)-.2 G(d.).15 E F2
+($HIST)5.367 E(-)-.92 E(CONTR)72 702 Q(OL)-.3 E F0 -.1(wa)3.778 G 3.778(sn).1 G
+(amed)150.266 702 Q F2($history_contr)3.778 E(ol)-.18 E F0 1.278(in earlier v)
+3.778 F 1.278(ersions of Bash; the old name is still accepted for)-.15 F(backw)
+72 714 Q .575(ards compatibility)-.1 F 5.575(.T)-.65 G(he)184.61 714 Q F2
+(history)3.075 E F0 .575
+(command can read or write \214les containing the history list and dis-)3.075 F
+.167(play the current list contents.)72 726 R(The)5.167 E F2(fc)2.667 E F0 -.2
+(bu)2.667 G .167(iltin, adopted from POSIX.2 and the K).2 F .167
+(orn Shell, allo)-.35 F .167(ws display and)-.25 F EP
+%%Page: 6 6
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-6-)279.67 48 S(re-e)72 84 Q -.15(xe)-.15 G .58
+(cution, with optional editing, of commands from the history list.).15 F .58
+(The readline library of)5.58 F .58(fers a set of)-.25 F 1.255(commands to sea\
+rch the history list for a portion of the current input line or a string typed\
+ by the user)72 96 R(.)-.55 E(Finally)72 108 Q 3.499(,t)-.65 G(he)108.469 108 Q
+/F1 10/Times-Italic@0 SF(history)3.499 E F0(library)5.165 E 3.499(,g)-.65 G 1
+(enerally incorporated directly into the readline library)191.362 108 R 3.5(,i)
+-.65 G 1(mplements a f)420.44 108 R(acility)-.1 E .613(for history recall, e)72
+120 R .613(xpansion, and re-e)-.15 F -.15(xe)-.15 G .613(cution of pre).15 F
+.613(vious commands v)-.25 F .613(ery similar to csh \(`)-.15 F .612
+(`bang history')-.74 F(',)-.74 E(so called because the e)72 132 Q
+(xclamation point introduces a history substitution\):)-.15 E/F2 10/Courier@0
+SF 6($e)97 150 S(cho a b c d e)115 150 Q 6(abcde)97 162 S 6($!)97 174 S 6
+(!fghi)115 174 S(echo a b c d e f g h i)97 186 Q 6(abcdefghi)97 198 S 6($!)97
+210 S(-2)115 210 Q(echo a b c d e)97 222 Q 6(abcde)97 234 S 6($e)97 246 S
+(cho !-2:1-4)115 246 Q(echo a b c d)97 258 Q 6(abcd)97 270 S F0 1.456
+(The command history is only sa)72 291.6 R -.15(ve)-.2 G 3.957(dw).15 G 1.457
+(hen the shell is interacti)232.599 291.6 R -.15(ve)-.25 G 3.957(,s).15 G 3.957
+(oi)352.804 291.6 S 3.957(ti)364.541 291.6 S 3.957(sn)374.058 291.6 S 1.457
+(ot a)386.905 291.6 R -.25(va)-.2 G 1.457(ilable for use by shell).25 F
+(scripts.)72 303.6 Q/F3 10/Times-Bold@0 SF 2.5(4.5. New)72 327.6 R(Shell V)2.5
+E(ariables)-.92 E F0 .59(There are a number of con)97 343.2 R -.15(ve)-.4 G
+.589(nience v).15 F .589(ariables that Bash interprets to mak)-.25 F 3.089(el)
+-.1 G .589(ife easier)403.093 343.2 R 5.589(.T)-.55 G .589(hese include)453.701
+343.2 R F3(FIGNORE)72 355.2 Q F0 3.973(,w)C 1.473
+(hich is a set of \214lename suf)132.363 355.2 R<8c78>-.25 E 1.474
+(es identifying \214les to e)-.15 F 1.474(xclude when completing \214lenames;)
+-.15 F F3(HOSTTYPE)72 367.2 Q F0 2.932(,w)C .432
+(hich is automatically set to a string describing the type of hardw)139.112
+367.2 R .431(are on which Bash is cur)-.1 F(-)-.2 E .335(rently e)72 379.2 R
+-.15(xe)-.15 G(cuting;).15 E F3(command_oriented_history)2.835 E F0 2.835(,w)C
+.335(hich directs Bash to sa)272.685 379.2 R .635 -.15(ve a)-.2 H .336
+(ll lines of a multiple-line com-).15 F 1.071(mand such as a)72 391.2 R F1
+(while)3.571 E F0(or)3.571 E F1(for)3.571 E F0 1.071
+(loop in a single history entry)3.571 F 3.57(,a)-.65 G(llo)321.92 391.2 Q 1.07
+(wing easy re-editing; and)-.25 F F3(IGNOREEOF)3.57 E F0(,)A .747(whose v)72
+403.2 R .747(alue indicates the number of consecuti)-.25 F 1.047 -.15(ve E)-.25
+H .747(OF characters that an interacti).15 F 1.048 -.15(ve s)-.25 H .748
+(hell will read before).15 F -.15(ex)72 415.2 S 1.432(iting \255 an easy w).15
+F 1.432(ay to k)-.1 F 1.432(eep yourself from being logged out accidentally)-.1
+F 6.432(.T)-.65 G(he)399.926 415.2 Q F3(auto_r)3.932 E(esume)-.18 E F0 -.25(va)
+3.932 G(riable).25 E .571(alters the w)72 427.2 R .571
+(ay the shell treats simple command names: if job control is acti)-.1 F -.15
+(ve)-.25 G 3.071(,a).15 G .571(nd this v)396.954 427.2 R .571
+(ariable is set, sin-)-.25 F(gle-w)72 439.2 Q .239(ord simple commands without\
+ redirections cause the shell to \214rst look for and restart a suspended job)
+-.1 F(with that name before starting a ne)72 451.2 Q 2.5(wp)-.25 G(rocess.)
+225.33 451.2 Q F3 2.5(4.6. Brace)72 475.2 R(Expansion)2.5 E F0 .653
+(Since sh of)97 490.8 R .653(fers no con)-.25 F -.15(ve)-.4 G .653(nient w).15
+F .653(ay to generate arbitrary strings that share a common pre\214x or suf)-.1
+F<8c78>-.25 E 2.124(\(\214lename e)72 502.8 R 2.124
+(xpansion requires that the \214lenames e)-.15 F 2.123(xist\), Bash implements)
+-.15 F F1(br)4.623 E 2.123(ace e)-.15 F(xpansion)-.2 E F0 4.623(,ac)C
+(apability)469 502.8 Q(pick)72 514.8 Q .773(ed up from csh.)-.1 F .774(Brace e)
+5.773 F .774(xpansion is similar to \214lename e)-.15 F .774(xpansion, b)-.15 F
+.774(ut the strings generated need not)-.2 F 1.107(correspond to e)72 526.8 R
+1.107(xisting \214les.)-.15 F 3.607(Ab)6.107 G 1.107(race e)207.655 526.8 R
+1.107(xpression consists of an optional)-.15 F F1(pr)3.606 E(eamble)-.37 E F0
+3.606(,f)1.666 G(ollo)419.286 526.8 Q 1.106(wed by a pair of)-.25 F 2.809
+(braces enclosing a series of comma-separated strings, and an optional)72 538.8
+R F1(postamble)5.31 E F0 7.81(.T)1.666 G 2.81(he preamble is)440.06 538.8 R(pr\
+epended to each string within the braces, and the postamble is then appended t\
+o each resulting string:)72 550.8 Q F2 6($e)97 568.8 S(cho a{d,c,b}e)115 568.8
+Q(ade ace abe)97 580.8 Q F0 .306(As this e)72 602.4 R .306
+(xample demonstrates, the results of brace e)-.15 F .305
+(xpansion are not sorted, as the)-.15 F 2.805(ya)-.15 G .305
+(re by \214lename e)416.315 602.4 R(xpan-)-.15 E(sion.)72 614.4 Q F3 2.5
+(4.7. Pr)72 638.4 R(ocess Substitution)-.18 E F0 .457
+(On systems that can support it, Bash pro)97 654 R .457(vides a f)-.15 F .457
+(acility kno)-.1 F .458(wn as)-.25 F F1(pr)2.958 E .458(ocess substitution)-.45
+F F0 5.458(.P)C .458(rocess sub-)458.832 654 R .347(stitution is similar to co\
+mmand substitution in that its speci\214cation includes a command to e)72 666 R
+-.15(xe)-.15 G .346(cute, b).15 F .346(ut the)-.2 F .181
+(shell does not collect the command')72 678 R 2.681(so)-.55 G .181
+(utput and insert it into the command line.)228.076 678 R(Rather)5.181 E 2.681
+(,B)-.4 G .182(ash opens a pipe)437.635 678 R 1.763
+(to the command, which is run in the background.)72 690 R 1.763
+(The shell uses named pipes \(FIFOs\) or the)6.763 F F1(/de)4.263 E(v/fd)-.15 E
+F0 .961(method of naming open \214les to e)72 702 R .962
+(xpand the process substitution to a \214lename which connects to the pipe)-.15
+F .104(when opened.)72 714 R .103(This \214lename becomes the result of the e)
+5.104 F 2.603(xpansion. Process)-.15 F .103(substitution can be used to com-)
+2.603 F(pare the outputs of tw)72 726 Q 2.5(od)-.1 G(if)171.61 726 Q(ferent v)
+-.25 E(ersions of an application as part of a re)-.15 E(gression test:)-.15 E
+EP
+%%Page: 7 7
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-7-)279.67 48 S/F1 10/Courier@0 SF 6($c)97 84 S
+(mp <\(old_prog\) <\(new_prog\))115 84 Q/F2 10/Times-Bold@0 SF 2.5(4.8. Pr)72
+114 R(ompt Customization)-.18 E F0 2.229(One of the more popular interacti)97
+129.6 R 2.529 -.15(ve f)-.25 H 2.229(eatures that Bash pro).15 F 2.23
+(vides is the ability to customize the)-.15 F 3.234(prompt. Both)72 141.6 R F2
+($PS1)3.234 E F0(and)3.234 E F2($PS2,)3.234 E F0 .734
+(the primary and secondary prompts, are e)3.234 F .733
+(xpanded before being displayed.)-.15 F -.15(Pa)72 153.6 S .804(rameter and v)
+.15 F .804(ariable e)-.25 F .805
+(xpansion is performed when the prompt string is e)-.15 F .805(xpanded, so an)
+-.15 F 3.305(ys)-.15 G .805(hell v)453.735 153.6 R(ariable)-.25 E .729
+(can be put into the prompt \(e.g.,)72 165.6 R F2($SHL)3.228 E(VL)-.92 E F0
+3.228(,w)C .728(hich indicates ho)258.568 165.6 R 3.228(wd)-.25 G .728
+(eeply the current shell is nested\).)342.992 165.6 R(Bash)5.728 E 1.895
+(specially interprets characters in the prompt string preceded by a backslash.)
+72 177.6 R 1.895(Some of these backslash)6.895 F .874
+(escapes are replaced with the current time, the date, the current w)72 189.6 R
+.874(orking directory)-.1 F 3.373(,t)-.65 G .873(he username, and the)416.961
+189.6 R .78(command number or history number of the command being entered.)72
+201.6 R .781(There is e)5.781 F -.15(ve)-.25 G 3.281(nab).15 G .781
+(ackslash escape to)429.128 201.6 R .007
+(cause the shell to change its prompt when running as root after an)72 213.6 R
+/F3 10/Times-Italic@0 SF(su)2.507 E F0 5.007(.B)C .007
+(efore printing each primary prompt,)360.392 213.6 R .305(Bash e)72 225.6 R
+.305(xpands the v)-.15 F(ariable)-.25 E F2($PR)2.805 E(OMPT_COMMAND)-.3 E F0
+.305(and, if it has a v)2.805 F .306(alue, e)-.25 F -.15(xe)-.15 G .306
+(cutes the e).15 F .306(xpanded v)-.15 F .306(alue as)-.25 F 3.735(ac)72 237.6
+S 1.235(ommand, allo)84.615 237.6 R 1.234
+(wing additional prompt customization.)-.25 F -.15(Fo)6.234 G 3.734(re).15 G
+1.234(xample, this assignment causes the current)327.3 237.6 R(user)72 249.6 Q
+2.917(,t)-.4 G .417
+(he current host, the time, the last component of the current w)96.457 249.6 R
+.417(orking directory)-.1 F 2.917(,t)-.65 G .418(he le)417.188 249.6 R -.15(ve)
+-.25 G 2.918(lo).15 G 2.918(fs)456.504 249.6 S .418(hell nest-)466.642 249.6 R
+(ing, and the history number of the current command to be embedded into the pr\
+imary prompt:)72 261.6 Q F1 6($P)97 279.6 S
+(S1='\\u@\\h [\\t] \\W\($SHLVL:\\!\)\\$ ')115 279.6 Q
+(chet@odin [21:03:44] documentation\(2:636\)$ cd ..)97 291.6 Q
+(chet@odin [21:03:54] src\(2:637\)$)97 303.6 Q F0 .146
+(The string being assigned is surrounded by single quotes so that if it is e)72
+325.2 R .146(xported, the v)-.15 F .146(alue of)-.25 F F2($SHL)2.646 E(VL)-.92
+E F0(will)2.646 E(be updated by a child shell:)72 337.2 Q F1
+(chet@odin [21:17:35] src\(2:638\)$ export PS1)97 355.2 Q
+(chet@odin [21:17:40] src\(2:639\)$ bash)97 367.2 Q
+(chet@odin [21:17:46] src\(3:696\)$)97 379.2 Q F0
+(The \\$ escape is displayed as `)72 400.8 Q(`)-.74 E F2($)A F0 1.48 -.74('' w)
+D(hen running as a normal user).74 E 2.5(,b)-.4 G(ut as `)342.08 400.8 Q(`)-.74
+E F2(#)A F0 1.48 -.74('' w)D(hen running as root.).74 E F2 2.5(4.9. File)72
+424.8 R(System V)2.5 E(iews)-.37 E F0 .029(Since Berk)97 440.4 R(ele)-.1 E
+2.529(yi)-.15 G .029
+(ntroduced symbolic links in 4.2 BSD, one of their most anno)162.908 440.4 R
+.03(ying properties has been)-.1 F 1.701(the `)72 452.4 R(`w)-.74 E(arping')-.1
+E 4.201('t)-.74 G 4.201(oac)139.912 452.4 S 1.701(ompletely dif)162.194 452.4 R
+1.701(ferent area of the \214le system when using)-.25 F F2(cd)4.2 E F0 4.2(,a)
+C 1.7(nd the resultant non-)416.41 452.4 R(intuiti)72 464.4 Q .658 -.15(ve b)
+-.25 H(eha).15 E .359(vior of `)-.2 F(`)-.74 E F2 .359(cd ..)B F0 -.74('')C
+5.359(.T).74 G(he)200.304 464.4 Q/F4 9/Times-Roman@0 SF(UNIX)2.859 E F0 -.1(ke)
+2.859 G .359(rnel treats symbolic links).1 F F3(physically)2.859 E F0 5.359(.W)
+1.666 G .359(hen the k)411.574 464.4 R .359(ernel is trans-)-.1 F .401(lating \
+a pathname in which one component is a symbolic link, it replaces all or part \
+of the pathname while)72 476.4 R .946(processing the link.)72 488.4 R .946
+(If the contents of the symbolic link be)5.946 F .946(gin with a slash, the k)
+-.15 F .947(ernel replaces the path-)-.1 F .661
+(name entirely; if not, the link contents replace the current component.)72
+500.4 R .66(In either case, the symbolic link is)5.66 F 2.546(visible. If)72
+512.4 R .046(the link v)2.546 F .047
+(alue is an absolute pathname, the user \214nds himself in a completely dif)
+-.25 F .047(ferent part of the)-.25 F(\214le system.)72 524.4 Q .599(Bash pro)
+97 540 R .599(vides a)-.15 F F3(lo)3.099 E(gical)-.1 E F0(vie)4.765 E 3.099(wo)
+-.25 G 3.099(ft)224.761 540 S .599(he \214le system.)233.97 540 R .599
+(In this def)5.599 F .599(ault mode, command and \214lename com-)-.1 F .522
+(pletion and b)72 552 R .522(uiltin commands such as)-.2 F F2(cd)3.022 E F0
+(and)3.022 E F2(pushd)3.022 E F0 .522(which change the current w)3.022 F .522
+(orking directory transpar)-.1 F(-)-.2 E .127(ently follo)72 564 R 2.627(ws)
+-.25 G .127(ymbolic links as if the)127.004 564 R 2.627(yw)-.15 G .127
+(ere directories.)231.099 564 R(The)5.126 E F2($PWD)2.626 E F0 -.25(va)2.626 G
+.126(riable, which holds the shell').25 F 2.626(si)-.55 G .126(dea of)479.164
+564 R .366(the current w)72 576 R .366(orking directory)-.1 F 2.866(,d)-.65 G
+.367(epends on the path used to reach the directory rather than its ph)200.184
+576 R .367(ysical loca-)-.05 F(tion in the local \214le system hierarch)72 588
+Q 3.8 -.65(y. F)-.05 H(or e).5 E(xample:)-.15 E F1 6($c)97 606 S 6(d/)115 606 S
+(usr/local/bin)133 606 Q 6($e)97 618 S(cho $PWD)115 618 Q(/usr/local/bin)97 630
+Q 6($p)97 642 S(wd)115 642 Q(/usr/local/bin)97 654 Q 6($/)97 666 S(bin/pwd)115
+666 Q(/net/share/sun4/local/bin)97 678 Q 6($c)97 690 S 6(d.)115 690 S(.)133 690
+Q 6($p)97 702 S(wd)115 702 Q(/usr/local)97 714 Q 6($/)97 726 S(bin/pwd)115 726
+Q EP
+%%Page: 8 8
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-8-)279.67 48 S/F1 10/Courier@0 SF
+(/net/share/sun4/local)97 84 Q 6($c)97 96 S 6(d.)115 96 S(.)133 96 Q 6($p)97
+108 S(wd)115 108 Q(/usr)97 120 Q 6($/)97 132 S(bin/pwd)115 132 Q(/usr)97 144 Q
+F0 .3(One problem with this, of course, arises when programs that do not under\
+stand the shell')72 165.6 R 2.8(sl)-.55 G .3(ogical notion of)440.07 165.6 R
+.717(the \214le system interpret `)72 177.6 R(`..)-.74 E 2.197 -.74('' d)-.7 H
+(if).74 E(ferently)-.25 E 5.717(.T)-.65 G .717
+(his generally happens when Bash completes \214lenames contain-)246.521 177.6 R
+.977(ing `)72 189.6 R(`..)-.74 E 2.457 -.74('' a)-.7 H .977
+(ccording to a logical hierarch).74 F 3.476(yw)-.05 G .976
+(hich does not correspond to their ph)249.056 189.6 R .976(ysical location.)
+-.05 F -.15(Fo)5.976 G 3.476(ru).15 G(sers)488.45 189.6 Q
+(who \214nd this troublesome, a corresponding)72 201.6 Q/F2 10/Times-Italic@0
+SF(physical)2.5 E F0(vie)4.166 E 2.5(wo)-.25 G 2.5(ft)312.006 201.6 S
+(he \214le system is a)320.616 201.6 Q -.25(va)-.2 G(ilable:).25 E F1 6($c)97
+219.6 S 6(d/)115 219.6 S(usr/local/bin)133 219.6 Q 6($p)97 231.6 S(wd)115 231.6
+Q(/usr/local/bin)97 243.6 Q 6($s)97 255.6 S(et -o physical)115 255.6 Q 6($p)97
+267.6 S(wd)115 267.6 Q(/net/share/sun4/local/bin)97 279.6 Q/F3 10/Times-Bold@0
+SF 2.5(4.10. Inter)72 309.6 R(nationalization)-.15 E F0 .052
+(One of the most signi\214cant impro)97 325.2 R -.15(ve)-.15 G .052(ments in v)
+.15 F .053(ersion 1.13 of Bash w)-.15 F .053(as the change to `)-.1 F .053
+(`eight-bit clean-)-.74 F(liness')72 337.2 Q 2.846('. Pre)-.74 F .346(vious v)
+-.25 F .345
+(ersions used the eighth bit of characters to mark whether or not the)-.15 F
+2.845(yw)-.15 G .345(ere quoted when)437.22 337.2 R 1.495(performing w)72 349.2
+R 1.495(ord e)-.1 F 3.995(xpansions. While)-.15 F 1.495(this did not af)3.995 F
+1.496(fect the majority of users, most of whom used only)-.25 F(se)72 361.2 Q
+-.15(ve)-.25 G 1.236(n-bit ASCII characters, some found it con\214ning.).15 F
+(Be)6.236 E 1.236(ginning with v)-.15 F 1.236(ersion 1.13, Bash implemented a)
+-.15 F(dif)72 373.2 Q .02
+(ferent quoting mechanism that did not alter the eighth bit of characters.)-.25
+F .021(This allo)5.021 F .021(wed Bash to manipulate)-.25 F .263
+(\214les with `)72 385.2 R(`odd')-.74 E 2.763('c)-.74 G .262
+(haracters in their names, b)146.019 385.2 R .262
+(ut did nothing to help users enter those names, so v)-.2 F .262(ersion 1.13)
+-.15 F 1.458
+(introduced changes to readline that made it eight-bit clean as well.)72 397.2
+R 1.458(Options e)6.458 F 1.458(xist that force readline to)-.15 F .744(attach\
+ no special signi\214cance to characters with the eighth bit set \(the def)72
+409.2 R .744(ault beha)-.1 F .744(vior is to con)-.2 F -.15(ve)-.4 G .744
+(rt these).15 F 1.88(characters to meta-pre\214x)72 421.2 R 1.88(ed k)-.15 F
+2.18 -.15(ey s)-.1 H 1.88
+(equences\) and to output these characters without con).15 F -.15(ve)-.4 G 1.88
+(rsion to meta-).15 F(pre\214x)72 433.2 Q .582(ed sequences.)-.15 F .581
+(These changes, along with the e)5.582 F .581(xpansion of k)-.15 F -.15(ey)-.1
+G .581(maps to a full eight bits, enable read-).15 F(line to w)72 445.2 Q
+(ork with most of the ISO-8859 f)-.1 E(amily of character sets, used by man)-.1
+E 2.5(yE)-.15 G(uropean countries.)394.94 445.2 Q F3 2.5(4.11. POSIX)72 469.2 R
+(Mode)2.5 E F0 .584(Although Bash is intended to be POSIX.2 conformant, there \
+are areas in which the def)97 484.8 R .584(ault beha)-.1 F(vior)-.2 E .463
+(is not compatible with the standard.)72 496.8 R -.15(Fo)5.463 G 2.962(ru).15 G
+.462(sers who wish to operate in a strict POSIX.2 en)244.25 496.8 R .462
+(vironment, Bash)-.4 F .505(implements a)72 508.8 R F2 .505(POSIX mode)3.005 F
+F0 5.505(.W)C .505(hen this mode is acti)199 508.8 R -.15(ve)-.25 G 3.005(,B)
+.15 G .505(ash modi\214es its def)304.455 508.8 R .505
+(ault operation where it dif)-.1 F(fers)-.25 E .267
+(from POSIX.2 to match the standard.)72 520.8 R .266
+(POSIX mode is entered when Bash is started with the)5.267 F F3(-posix)2.766 E
+F0(option.)2.766 E .149(This feature is also a)72 532.8 R -.25(va)-.2 G .149
+(ilable as an option to the).25 F F3(set)2.649 E F0 -.2(bu)2.649 G(iltin,).2 E
+F3 .149(set -o posix)2.649 F F0 5.149(.F)C .149
+(or compatibility with other GNU)371.744 532.8 R(softw)72 544.8 Q 4.02(are tha\
+t attempts to be POSIX.2 compliant, Bash also enters POSIX mode if the v)-.1 F
+(ariable)-.25 E F3($POSIXL)72 556.8 Q(Y_CORRECT)-.92 E F0 5.824
+(is set when Bash is started or assigned a v)8.324 F 5.825(alue during e)-.25 F
+-.15(xe)-.15 G(cution.).15 E F3($POSIX_PED)72 568.8 Q(ANTIC)-.35 E F0 .27
+(is accepted as well, to be compatible with some older GNU utilities.)2.77 F
+.27(When Bash is)5.27 F .428(started in POSIX mode, for e)72 580.8 R .428
+(xample, it sources the \214le named by the v)-.15 F .429(alue of)-.25 F F3
+($ENV)2.929 E F0 .429(rather than the `)2.929 F(`nor)-.74 E(-)-.2 E(mal')72
+592.8 Q 2.5('s)-.74 G(tartup \214les, and does not allo)99.31 592.8 Q 2.5(wr)
+-.25 G(eserv)227.66 592.8 Q(ed w)-.15 E(ords to be aliased.)-.1 E F3 2.5
+(5. New)72 616.8 R -.25(Fe)2.5 G(atur).25 E(es and Futur)-.18 E 2.5(eP)-.18 G
+(lans)201.65 616.8 Q F0 1.632(There are se)97 632.4 R -.15(ve)-.25 G 1.632
+(ral features introduced in the current v).15 F 1.631(ersion of Bash, v)-.15 F
+1.631(ersion 1.14, and a number)-.15 F .241
+(under consideration for future releases.)72 644.4 R .242
+(This section will brie\215y detail the ne)5.242 F 2.742(wf)-.25 G .242
+(eatures in v)395.702 644.4 R .242(ersion 1.14 and)-.15 F(describe se)72 656.4
+Q -.15(ve)-.25 G(ral features that may appear in later v).15 E(ersions.)-.15 E
+F3 2.5(5.1. New)72 680.4 R -.25(Fe)2.5 G(atur).25 E(es in Bash-1.14)-.18 E F0
+.884(The ne)97 696 R 3.384(wf)-.25 G .884(eatures a)139.058 696 R -.25(va)-.2 G
+.884(ilable in Bash-1.14 answer se).25 F -.15(ve)-.25 G .883
+(ral of the most common requests for enhance-).15 F 2.931(ments. Most)72 708 R
+(notably)2.931 E 2.931(,t)-.65 G .432(here is a mechanism for including non-vi\
+sible character sequences in prompts, such)164.873 708 R 1.533
+(as those which cause a terminal to print characters in dif)72 720 R 1.532
+(ferent colors or in standout mode.)-.25 F 1.532(There w)6.532 F(as)-.1 E EP
+%%Page: 9 9
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-9-)279.67 48 S 1.967(nothing pre)72 84 R -.15(ve)
+-.25 G 1.967(nting the use of these sequences in earlier v).15 F 1.967
+(ersions, b)-.15 F 1.967(ut the readline redisplay algorithm)-.2 F
+(assumed each character occupied ph)72 96 Q(ysical screen space and w)-.05 E
+(ould wrap lines prematurely)-.1 E(.)-.65 E .13(Readline has a fe)97 111.6 R
+2.63(wn)-.25 G .63 -.25(ew va)180.58 111.6 T .13(riables, se).25 F -.15(ve)-.25
+G .13(ral ne).15 F 2.63(wb)-.25 G .13
+(indable commands, and some additional emacs mode)290.19 111.6 R(def)72 123.6 Q
+.918(ault k)-.1 F 1.218 -.15(ey b)-.1 H 3.418(indings. A).15 F(ne)3.418 E 3.418
+(wh)-.25 G .919
+(istory search mode has been implemented: in this mode, readline searches)
+199.03 123.6 R .336(the history for lines be)72 135.6 R .336
+(ginning with the characters between the be)-.15 F .336
+(ginning of the current line and the cursor)-.15 F(.)-.55 E .555(The e)72 147.6
+R .556(xisting readline incremental search commands no longer match identical \
+lines more than once.)-.15 F(File-)5.556 E 1.979(name completion no)72 159.6 R
+4.479(we)-.25 G 1.979(xpands v)173.357 159.6 R 1.979
+(ariables in directory names.)-.25 F 1.978(The history e)6.978 F 1.978
+(xpansion f)-.15 F 1.978(acilities are no)-.1 F(w)-.25 E 1.449
+(nearly completely csh-compatible: missing modi\214ers ha)72 171.6 R 1.749 -.15
+(ve b)-.2 H 1.449(een added and history substitution has been).15 F -.15(ex)72
+183.6 S(tended.).15 E(Se)97 199.2 Q -.15(ve)-.25 G .474
+(ral of the features described earlier).15 F 2.973(,s)-.4 G .473(uch as)266.483
+199.2 R/F1 10/Times-Bold@0 SF .473(set -o posix)2.973 F F0(and)2.973 E F1
+($POSIX_PED)2.973 E(ANTIC)-.35 E F0 2.973(,a)C .473(re ne)466.094 199.2 R 2.973
+(wi)-.25 G(n)499 199.2 Q -.15(ve)72 211.2 S .106(rsion 1.14.).15 F .106
+(There is a ne)5.106 F 2.606(ws)-.25 G .106(hell v)194.156 211.2 R(ariable,)
+-.25 E F1(OSTYPE)2.606 E F0 2.606(,t)C 2.606(ow)296.724 211.2 S .106
+(hich Bash assigns a v)311.55 211.2 R .106(alue that identi\214es the v)-.25 F
+(er)-.15 E(-)-.2 E 1.38(sion of)72 223.2 R/F2 9/Times-Roman@0 SF(UNIX)3.88 E F0
+(it')3.88 E 3.879(sr)-.55 G 1.379(unning on \(great for putting architecture-s\
+peci\214c binary directories into the)150.57 223.2 R F1($P)3.879 E -.95(AT)-.74
+G(H).95 E F0(\).)A -1 -.8(Tw o)72 235.2 T -.25(va)6.215 G 2.915(riables ha).25
+F 3.215 -.15(ve b)-.2 H 2.915(een renamed:).15 F F1($HISTCONTR)5.416 E(OL)-.3 E
+F0(replaces)5.416 E F1($history_contr)5.416 E(ol)-.18 E F0 5.416(,a)C(nd)
+432.454 235.2 Q F1($HOSTFILE)5.416 E F0(replaces)72 247.2 Q F1
+($hostname_completion_\214le)2.521 E F0 5.021(.I)C 2.521(nb)234.242 247.2 S
+.021(oth cases, the old names are accepted for backw)246.763 247.2 R .02
+(ards compatibil-)-.1 F(ity)72 259.2 Q 5.676(.T)-.65 G .677(he ksh)96.196 259.2
+R/F3 10/Times-Italic@0 SF(select)3.177 E F0 .677(construct, which allo)4.843 F
+.677(ws the generation of simple menus, has been implemented.)-.25 F(Ne)5.677 E
+(w)-.25 E 2.892(capabilities ha)72 271.2 R 3.192 -.15(ve b)-.2 H 2.892
+(een added to e).15 F 2.892(xisting v)-.15 F(ariables:)-.25 E F1($auto_r)5.392
+E(esume)-.18 E F0 2.892(can no)5.392 F 5.392(wt)-.25 G(ak)404.13 271.2 Q 5.391
+(ev)-.1 G 2.891(alues of)428.051 271.2 R F3 -.2(ex)5.391 G(act).2 E F0(or)7.057
+E F3(substring)72 283.2 Q F0 3.278(,a)1.666 G(nd)121.114 283.2 Q F1($HISTCONTR)
+3.278 E(OL)-.3 E F0 .778(understands the v)3.278 F(alue)-.25 E F3(ignor)3.278 E
+(eboth)-.37 E F0 3.278(,w)1.666 G .778(hich combines the tw)366.248 283.2 R
+3.278(op)-.1 G(re)467.03 283.2 Q(viously)-.25 E 1.556(acceptable v)72 295.2 R
+4.056(alues. The)-.25 F F1(dirs)4.056 E F0 -.2(bu)4.056 G 1.556
+(iltin has acquired options to print out speci\214c members of the directory).2
+F 3.062(stack. The)72 307.2 R F1($nolinks)3.062 E F0 -.25(va)3.062 G .562
+(riable, which forces a ph).25 F .562(ysical vie)-.05 F 3.062(wo)-.25 G 3.062
+(ft)322.028 307.2 S .563(he \214le system, has been superseded by the)331.2
+307.2 R F1<ad50>72 319.2 Q F0 .494(option to the)2.994 F F1(set)2.994 E F0 -.2
+(bu)2.994 G .494(iltin \(equi).2 F -.25(va)-.25 G .494(lent to).25 F F1 .494
+(set -o ph)2.994 F(ysical)-.15 E F0 .493(\); the v)B .493
+(ariable is retained for backw)-.25 F .493(ards compati-)-.1 F(bility)72 331.2
+Q 5.196(.T)-.65 G .196(he v)106.276 331.2 R .196(ersion string contained in)
+-.15 F F1($B)2.696 E(ASH_VERSION)-.3 E F0(no)2.696 E 2.696(wi)-.25 G .196
+(ncludes an indication of the patch le)335.558 331.2 R -.15(ve)-.25 G 2.696(la)
+.15 G(s)500.11 331.2 Q .665(well as the `)72 343.2 R(`b)-.74 E .665(uild v)-.2
+F(ersion')-.15 E 3.165('. Some)-.74 F .665(little-used features ha)3.165 F .965
+-.15(ve b)-.2 H .665(een remo).15 F -.15(ve)-.15 G 3.165(d: the).15 F F1(by)
+3.165 E(e)-.1 E F0(synon)3.165 E .665(ym for)-.15 F F1(exit)3.165 E F0(and)
+3.165 E(the)72 355.2 Q F1($NO_PR)3.498 E(OMPT_V)-.3 E(ARS)-1.35 E F0 -.25(va)
+3.498 G .998(riable are gone.).25 F .998(There is no)5.998 F 3.498(wa)-.25 G
+3.498(no)331.114 355.2 S -2.19 -.18(rg a)344.612 355.2 T .998
+(nized test suite that can be run as a).18 F(re)72 367.2 Q
+(gression test when b)-.15 E(uilding a ne)-.2 E 2.5(wv)-.25 G(ersion of Bash.)
+222.34 367.2 Q 1.696(The documentation has been thoroughly o)97 382.8 R -.15
+(ve)-.15 G 1.696(rhauled: there is a ne).15 F 4.196(wm)-.25 G 1.695
+(anual page on the readline)392.25 382.8 R .467(library and the)72 394.8 R F3
+(info)2.967 E F0 .467(\214le has been updated to re\215ect the current v)2.967
+F 2.968(ersion. As)-.15 F(al)2.968 E -.1(wa)-.1 G .468(ys, as man).1 F 2.968
+(yb)-.15 G .468(ugs as possi-)451.954 394.8 R(ble ha)72 406.8 Q .3 -.15(ve b)
+-.2 H(een \214x).15 E(ed, although some surely remain.)-.15 E F1 2.5
+(5.2. Other)72 430.8 R -.25(Fe)2.5 G(atur).25 E(es)-.18 E F0 1.68
+(There are a fe)97 446.4 R 4.18(wf)-.25 G 1.68
+(eatures that I hope to include in later Bash releases.)171.76 446.4 R 1.68
+(Some are based on w)6.68 F(ork)-.1 E(already done in other shells.)72 458.4 Q
+.958(In addition to simple v)97 474 R .959
+(ariables, a future release of Bash will include one-dimensional arrays, using)
+-.25 F .206(the ksh implementation of arrays as a model.)72 486 R .205
+(Additions to the ksh syntax, such as)5.205 F F3(varname)2.705 E F0 .205
+(=\( ... \) to assign)B 2.587(al)72 498 S .087(ist of w)81.807 498 R .088
+(ords directly to an array and a mechanism to allo)-.1 F 2.588(wt)-.25 G(he)
+320.248 498 Q F1 -.18(re)2.588 G(ad).18 E F0 -.2(bu)2.588 G .088
+(iltin to read a list of v).2 F .088(alues directly)-.25 F .092(into an array)
+72 510 R 2.592(,w)-.65 G .092(ould be desirable.)134.286 510 R(Gi)5.092 E -.15
+(ve)-.25 G 2.592(nt).15 G .092(hose e)239.794 510 R .092(xtensions, the ksh)
+-.15 F F1 .092(set \255A)2.592 F F0 .091(syntax may not be w)2.591 F .091
+(orth support-)-.1 F(ing \(the)72 522 Q F1<ad41>2.5 E F0
+(option assigns a list of v)2.5 E(alues to an array)-.25 E 2.5(,b)-.65 G
+(ut is a rather peculiar special case\).)292.41 522 Q .76
+(Some shells include a means of)97 537.6 R F3(pr)3.26 E -.1(og)-.45 G -.15(ra)
+.1 G(mmable).15 E F0 -.1(wo)3.26 G .76
+(rd completion, where the user speci\214es on a per).1 F(-)-.2 E .163
+(command basis ho)72 549.6 R 2.663(wt)-.25 G .163(he ar)159.179 549.6 R .163(g\
+uments of the command are to be treated when completion is attempted: as \214l\
+e-)-.18 F .194(names, hostnames, e)72 561.6 R -.15(xe)-.15 G .194
+(cutable \214les, and so on.).15 F .195
+(The other aspects of the current Bash implementation could)5.195 F .482
+(remain as-is; the e)72 573.6 R .482(xisting heuristics w)-.15 F .481
+(ould still be v)-.1 F 2.981(alid. Only)-.25 F .481(when completing the ar)
+2.981 F .481(guments to a simple)-.18 F(command w)72 585.6 Q
+(ould the programmable completion be in ef)-.1 E(fect.)-.25 E .479(It w)97
+601.2 R .479(ould also be nice to gi)-.1 F .779 -.15(ve t)-.25 H .479
+(he user \214ner).15 F .479(-grained control o)-.2 F -.15(ve)-.15 G 2.98(rw).15
+G .48(hich commands are sa)363.92 601.2 R -.15(ve)-.2 G 2.98(do).15 G .48
+(nto the)476.02 601.2 R 1.786(history list.)72 613.2 R 1.786
+(One proposal is for a v)6.786 F 1.786(ariable, tentati)-.25 F -.15(ve)-.25 G
+1.786(ly named).15 F F1(HISTIGNORE)4.286 E F0 4.285(,w)C 1.785(hich w)415.145
+613.2 R 1.785(ould contain a)-.1 F .496(colon-separated list of commands.)72
+625.2 R .496(Lines be)5.496 F .496
+(ginning with these commands, after the restrictions of)-.15 F F1($HIST)2.997 E
+(-)-.92 E(CONTR)72 637.2 Q(OL)-.3 E F0(ha)2.65 E .45 -.15(ve b)-.2 H .15
+(een applied, w).15 F .15(ould not be placed onto the history list.)-.1 F .15
+(The shell pattern-matching capa-)5.15 F(bilities could also be a)72 649.2 Q
+-.25(va)-.2 G(ilable when specifying the contents of).25 E F1($HISTIGNORE)2.5 E
+F0(.)A .729(One thing that ne)97 664.8 R .729(wer shells such as)-.25 F F1
+(wksh)3.229 E F0 .729(\(also kno)3.229 F .729(wn as)-.25 F F1(dtksh)3.23 E F0
+3.23(\)p)C(ro)370.79 664.8 Q .73(vide is a command to dynami-)-.15 F 1.189
+(cally load code implementing additional b)72 676.8 R 1.189
+(uiltin commands into a running shell.)-.2 F 1.188(This ne)6.188 F 3.688(wb)
+-.25 G 1.188(uiltin w)454.292 676.8 R(ould)-.1 E(tak)72 688.8 Q 2.69(ea)-.1 G
+2.69(no)95.69 688.8 S .19(bject \214le or shared library implementing the `)
+108.38 688.8 R(`body')-.74 E 2.69('o)-.74 G 2.69(ft)327.83 688.8 S .19(he b)
+336.63 688.8 R .19(uiltin \()-.2 F F3(xxx_b)A(uiltin\(\))-.2 E F0 .19
+(for those f)2.69 F(amiliar)-.1 E .052
+(with Bash internals\) and a structure containing the name of the ne)72 700.8 R
+2.552(wc)-.25 G .051(ommand, the function to call when the)349.544 700.8 R(ne)
+72 712.8 Q 3.458(wb)-.25 G .958(uiltin is in)96.668 712.8 R -.2(vo)-.4 G -.1
+(ke).2 G 3.458(d\().1 G .959
+(presumably de\214ned in the shared object speci\214ed as an ar)169.682 712.8 R
+.959(gument\), and the docu-)-.18 F 1.352(mentation to be printed by the)72
+724.8 R F1(help)3.851 E F0 1.351
+(command \(possibly present in the shared object as well\).)3.851 F 1.351(It w)
+6.351 F(ould)-.1 E EP
+%%Page: 10 10
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)277.17 48 S 2.5(0-)288 48 S
+(manage the details of e)72 84 Q(xtending the internal table of b)-.15 E
+(uiltins.)-.2 E 3.291(Af)97 99.6 S 1.291 -.25(ew o)110.841 99.6 T .791(ther b)
+.25 F .791(uiltins w)-.2 F .791(ould also be desirable: tw)-.1 F 3.291(oa)-.1 G
+.791(re the POSIX.2)307.609 99.6 R/F1 10/Times-Bold@0 SF(getconf)3.292 E F0
+.792(command, which prints)3.292 F 1.412(the v)72 111.6 R 1.412
+(alues of system con\214guration v)-.25 F 1.411
+(ariables de\214ned by POSIX.2, and a)-.25 F F1(diso)3.911 E(wn)-.1 E F0 -.2
+(bu)3.911 G 1.411(iltin, which causes a).2 F 1.173
+(shell running with job control acti)72 123.6 R 1.473 -.15(ve t)-.25 H 3.673
+(o`).15 G(`for)240.45 123.6 Q 1.173(get about')-.18 F 3.673('o)-.74 G 1.173
+(ne or more background jobs in its internal jobs)307.966 123.6 R 3.465
+(table. Using)72 135.6 R F1(getconf)3.465 E F0 3.465(,f)C .965(or e)167.655
+135.6 R .965(xample, a user could retrie)-.15 F 1.264 -.15(ve a v)-.25 H .964
+(alue for)-.1 F F1($P)3.464 E -.95(AT)-.74 G(H).95 E F0 .964
+(guaranteed to \214nd all of the)3.464 F .884
+(POSIX standard utilities, or \214nd out ho)72 147.6 R 3.385(wl)-.25 G .885
+(ong \214lenames may be in the \214le system containing a speci\214ed)247.39
+147.6 R(directory)72 159.6 Q(.)-.65 E 1.521
+(There are no implementation timetables for an)97 175.2 R 4.021(yo)-.15 G 4.021
+(ft)305.517 175.2 S 1.52(hese features, nor are there concrete plans to)315.648
+175.2 R(include them.)72 187.2 Q(If an)5 E
+(yone has comments on these proposals, feel free to send me electronic mail.)
+-.15 E F1 2.5(6. Re\215ections)72 211.2 R(and Lessons Lear)2.5 E(ned)-.15 E F0
+.433(The lesson that has been repeated most often during Bash de)97 226.8 R
+-.15(ve)-.25 G .433(lopment is that there are dark corners).15 F .093
+(in the Bourne Shell, and people use all of them.)72 238.8 R .092
+(In the original description of the Bourne shell, quoting and)5.093 F .073(the\
+ shell grammar are both poorly speci\214ed and incomplete; subsequent descript\
+ions ha)72 250.8 R .373 -.15(ve n)-.2 H .073(ot helped much.).15 F 1.856
+(The grammar presented in Bourne')72 262.8 R 4.356(sp)-.55 G 1.856
+(aper describing the shell distrib)232.64 262.8 R 1.855(uted with the Se)-.2 F
+-.15(ve)-.25 G 1.855(nth Edition of).15 F/F2 9/Times-Roman@0 SF(UNIX)72 274.8 Q
+F0 2.5<8769>C 2.5(ss)104.771 274.8 S 2.5(of)115.051 274.8 S(ar of)125.781 274.8
+Q 2.5(ft)-.25 G(hat it does not allo)152.741 274.8 Q 2.5(wt)-.25 G(he command)
+238.881 274.8 Q/F3 10/Courier@0 SF(who|wc)2.5 E F0 5(.I)C 2.5(nf)339.591 274.8
+S(act, as T)350.321 274.8 Q(om Duf)-.8 E 2.5(fs)-.25 G(tates:)423.421 274.8 Q
+1.375(Nobody really kno)97 290.4 R 1.375(ws what the Bourne shell')-.25 F 3.875
+(sg)-.55 G 1.375(rammar is.)296.635 290.4 R(Ev)6.376 E 1.376(en e)-.15 F 1.376
+(xamination of the source)-.15 F(code is little help.\210)97 302.4 Q .382
+(The POSIX.2 standard includes a)72 318 R/F4 10/Times-Italic@0 SF(yacc)2.882 E
+F0 .382(grammar that comes close to capturing the Bourne shell')2.882 F 2.882
+(sb)-.55 G(eha)472.11 318 Q(vior)-.2 E(,)-.4 E -.2(bu)72 330 S 3.246(ti).2 G
+3.246(td)90.606 330 S(isallo)101.632 330 Q .747(ws some constructs which sh ac\
+cepts without complaint \255 and there are scripts out there that)-.25 F .501
+(use them.)72 342 R .501(It took a fe)5.501 F 3.001(wv)-.25 G .501
+(ersions and se)176.256 342 R -.15(ve)-.25 G .501(ral b).15 F .5
+(ug reports before Bash implemented sh-compatible quoting,)-.2 F .094
+(and there are still some `)72 354 R(`le)-.74 E -.05(ga)-.15 G(l').05 E 2.594
+('s)-.74 G 2.594(hc)205.294 354 S .094
+(onstructs which Bash \215ags as syntax errors.)217.328 354 R .095
+(Complete sh compatibility)5.095 F(is a tough nut.)72 366 Q 1.231
+(The shell is bigger and slo)97 381.6 R 1.231(wer than I w)-.25 F 1.231
+(ould lik)-.1 F 1.23(e, though the current v)-.1 F 1.23
+(ersion is substantially f)-.15 F(aster)-.1 E .086(than pre)72 393.6 R(viously)
+-.25 E 5.086(.T)-.65 G .087(he readline library could stand a substantial re)
+146.822 393.6 R 2.587(write. A)-.25 F .087(hand-written parser to replace the)
+2.587 F(current)72 405.6 Q F4(yacc)2.978 E F0 .478(-generated one w)B .477
+(ould probably result in a speedup, and w)-.1 F .477(ould solv)-.1 F 2.977(eo)
+-.15 G .477(ne glaring problem:)406.469 405.6 R(the)5.477 E .199
+(shell could parse commands in `)72 417.6 R(`$\(...\)')-.74 E 2.699('c)-.74 G
+.199(onstructs as the)236.954 417.6 R 2.699(ya)-.15 G .2
+(re entered, rather than reporting errors when the)311.001 417.6 R
+(construct is e)72 429.6 Q(xpanded.)-.15 E 1.064(As al)97 445.2 R -.1(wa)-.1 G
+1.064(ys, there is some chaf).1 F 3.564(ft)-.25 G 3.564(og)230.404 445.2 S
+3.564(ow)243.968 445.2 S 1.064(ith the wheat.)259.752 445.2 R 1.063
+(Areas of duplicated functionality need to be)6.063 F .382(cleaned up.)72 457.2
+R .382(There are se)5.382 F -.15(ve)-.25 G .382
+(ral cases where Bash treats a v).15 F .382
+(ariable specially to enable functionality a)-.25 F -.25(va)-.2 G(ilable).25 E
+.185(another w)72 469.2 R .185(ay \()-.1 F F1($notify)A F0(vs.)2.684 E F1 .184
+(set -o notify)5.184 F F0(and)2.684 E F1($nolinks)2.684 E F0(vs.)2.684 E F1
+.184(set -o ph)2.684 F(ysical)-.15 E F0 2.684(,f)C .184
+(or instance\); the special treatment)368.294 469.2 R 3.421(of the v)72 481.2 R
+3.421(ariable name should probably be remo)-.25 F -.15(ve)-.15 G 5.921(d. A).15
+F(fe)5.921 E 5.921(wm)-.25 G 3.422(ore things could stand remo)346.47 481.2 R
+-.25(va)-.15 G 3.422(l; the).25 F F1($allo)72 493.2 Q(w_null_glob_expansion)-.1
+E F0(and)4.112 E F1($glob_dot_\214lenames)4.112 E F0 -.25(va)4.111 G 1.611
+(riables are of particularly questionable v).25 F(alue.)-.25 E(The)72 505.2 Q
+F1($[...])3.977 E F0 1.477(arithmetic e)3.977 F -.25(va)-.25 G 1.478
+(luation syntax is redundant no).25 F 3.978(wt)-.25 G 1.478
+(hat the POSIX-mandated)312.76 505.2 R F1($\(\(...\)\))3.978 E F0 1.478
+(construct has)3.978 F .326(been implemented, and could be deleted.)72 517.2 R
+.326(It w)5.326 F .326(ould be nice if the te)-.1 F .326(xt output by the)-.15
+F F1(help)2.825 E F0 -.2(bu)2.825 G .325(iltin were e).2 F(xter)-.15 E(-)-.2 E
+.061(nal to the shell rather than compiled into it.)72 529.2 R .062(The beha)
+5.062 F .062(vior enabled by)-.2 F F1($command_oriented_history)2.562 E F0
+2.562(,w)C(hich)486.78 529.2 Q 1.125(causes the shell to attempt to sa)72 541.2
+R 1.424 -.15(ve a)-.2 H 1.124
+(ll lines of a multi-line command in a single history entry).15 F 3.624(,s)-.65
+G 1.124(hould be)468.156 541.2 R(made the def)72 553.2 Q(ault and the v)-.1 E
+(ariable remo)-.25 E -.15(ve)-.15 G(d.).15 E F1 2.5(7. A)72 577.2 R -.1(va)-1 G
+(ilability).1 E F0 8.538(As with all other GNU softw)97 592.8 R 8.538
+(are, Bash is a)-.1 F -.25(va)-.2 G 8.539(ilable for anon).25 F 8.539
+(ymous FTP from)-.15 F F4(pr)72 604.8 Q(ep.ai.mit.edu:/pub/gnu)-.37 E F0 4.552
+(and from other GNU softw)8.718 F 4.552(are mirror sites.)-.1 F 4.552
+(The current v)9.552 F 4.552(ersion is in)-.15 F F4(bash-1.14.1.tar)72 616.8 Q
+(.gz)-1.11 E F0 .074(in that directory)4.24 F 5.075(.U)-.65 G(se)226.084 616.8
+Q F4(ar)2.575 E -.15(ch)-.37 G(ie).15 E F0 .075(to \214nd the nearest archi)
+4.241 F .375 -.15(ve s)-.25 H 2.575(ite. The).15 F .075(latest v)2.575 F .075
+(ersion is al)-.15 F -.1(wa)-.1 G(ys).1 E -.2(av)72 628.8 S 3.659
+(ailable for FTP from)-.05 F F4(bash.CWR)6.159 E -.25(U.)-.4 G(Edu:/pub/dist.)
+.25 E F0 3.658(Bash documentation is a)7.825 F -.25(va)-.2 G 3.658
+(ilable for FTP from).25 F F4(bash.CWR)72 640.8 Q -.25(U.)-.4 G(Edu:/pub/bash.)
+.25 E F0 1.168(The Free Softw)97 656.4 R 1.168(are F)-.1 F 1.168
+(oundation sells tapes and CD-R)-.15 F 1.169
+(OMs containing Bash; send electronic mail to)-.4 F F3(gnu@prep.ai.mit.edu)72
+668.4 Q F0(or call)2.5 E F3(+1-617-876-3296)2.5 E F0(for more information.)2.5
+E .32 LW 76 678.4 72 678.4 DL 80 678.4 76 678.4 DL 84 678.4 80 678.4 DL 88
+678.4 84 678.4 DL 92 678.4 88 678.4 DL 96 678.4 92 678.4 DL 100 678.4 96 678.4
+DL 104 678.4 100 678.4 DL 108 678.4 104 678.4 DL 112 678.4 108 678.4 DL 116
+678.4 112 678.4 DL 120 678.4 116 678.4 DL 124 678.4 120 678.4 DL 128 678.4 124
+678.4 DL 132 678.4 128 678.4 DL 136 678.4 132 678.4 DL 140 678.4 136 678.4 DL
+144 678.4 140 678.4 DL/F5 8/Times-Roman@0 SF 1.39(\207S. R. Bourne, `)72 688.4
+R 1.389(`UNIX T)-.592 F 1.389(ime-Sharing System:)-.28 F 1.389(The UNIX Shell')
+5.389 F(',)-.592 E/F6 8/Times-Italic@0 SF 1.389(Bell System T)3.389 F(ec)-.736
+E 1.389(hnical J)-.12 F(ournal)-.2 E F5 3.389(,5)C 1.389(7\(6\), July-August,)
+408.171 688.4 R(1978, pp. 1971-1990.)72 698.4 Q<8854>72 708.4 Q .684(om Duf)
+-.64 F .684(f, `)-.2 F .684(`Rc \255 A Shell for Plan 9 and)-.592 F/F7 7
+/Times-Roman@0 SF(UNIX)2.684 E F5(systems')2.684 E(',)-.592 E F6(Pr)2.684 E
+.684(oc. of the Summer 1990 EUUG Confer)-.36 F(ence)-.296 E F5 2.685(,L)C .685
+(ondon, July)428.499 708.4 R(,)-.52 E(1990, pp. 21-33.)72 718.4 Q EP
+%%Page: 11 11
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 2.5(-1)277.17 48 S 2.5(1-)288 48 S .695
+(Bash is also distrib)97 84 R .694(uted with se)-.2 F -.15(ve)-.25 G .694
+(ral v).15 F .694(ersions of)-.15 F/F1 9/Times-Roman@0 SF(UNIX)3.194 E F0 .694
+(-compatible systems.)B .694(It is included as /bin/sh)5.694 F .948
+(and /bin/bash on se)72 96 R -.15(ve)-.25 G .948(ral Linux distrib).15 F .948
+(utions \(more about the dif)-.2 F .948(ference in a moment\), and as contrib)
+-.25 F(uted)-.2 E(softw)72 108 Q(are in BSDI')-.1 E 2.5(sB)-.55 G
+(SD/386* and FreeBSD.)157.73 108 Q .599(The Linux distrib)97 123.6 R .599
+(ution deserv)-.2 F .599(es special mention.)-.15 F .598(There are tw)5.599 F
+3.098(oc)-.1 G .598(on\214gurations included in the stan-)364.948 123.6 R .547
+(dard Bash distrib)72 135.6 R .547(ution: a `)-.2 F(`normal')-.74 E 3.047('c)
+-.74 G .548
+(on\214guration, in which all of the standard features are included, and a)
+222.755 135.6 R -.74(``)72 147.6 S(minimal').74 E 2.792('c)-.74 G .292(on\214g\
+uration, which omits job control, aliases, history and command line editing, t\
+he directory)124.412 147.6 R .747(stack and)72 159.6 R/F2 10/Times-Bold@0 SF
+(pushd/popd/dirs,)3.247 E F0 .747
+(process substitution, prompt string special character decoding, and the)3.247
+F/F3 10/Times-Italic@0 SF(select)3.247 E F0 3.369(construct. This)72 171.6 R
+.869(minimal v)3.369 F .869
+(ersion is designed to be a drop-in replacement for the traditional)-.15 F F1
+(UNIX)3.368 E F0(/bin/sh,)3.368 E(and is included as the Linux /bin/sh in se)72
+183.6 Q -.15(ve)-.25 G(ral packagings.).15 E F2 2.5(8. Conclusion)72 207.6 R F0
+.8(Bash is a w)97 223.2 R(orth)-.1 E 3.3(ys)-.05 G .8(uccessor to sh.)173.379
+223.2 R .8(It is suf)5.8 F .8(\214ciently portable to run on nearly e)-.25 F
+-.15(ve)-.25 G .8(ry v).15 F .8(ersion of)-.15 F F1(UNIX)3.3 E F0 .311
+(from 4.3 BSD to SVR4.2, and se)72 235.2 R -.15(ve)-.25 G(ral).15 E F1(UNIX)
+2.811 E F0 -.1(wo)2.811 G(rkalik).1 E 2.811(es. It)-.1 F .31(is rob)2.81 F .31
+(ust enough to replace sh on most of those)-.2 F 1.515(systems, and pro)72
+247.2 R 1.515(vides more functionality)-.15 F 6.515(.I)-.65 G 4.015(th)254.315
+247.2 S 1.515(as se)266.11 247.2 R -.15(ve)-.25 G 1.515(ral thousand re).15 F
+1.515(gular users, and their feedback has)-.15 F(helped to mak)72 259.2 Q 2.5
+(ei)-.1 G 2.5(ta)138.28 259.2 S 2.5(sg)148 259.2 S
+(ood as it is today \255 a testament to the bene\214ts of free softw)159.39
+259.2 Q(are.)-.1 E .32 LW 76 698 72 698 DL 80 698 76 698 DL 84 698 80 698 DL 88
+698 84 698 DL 92 698 88 698 DL 96 698 92 698 DL 100 698 96 698 DL 104 698 100
+698 DL 108 698 104 698 DL 112 698 108 698 DL 116 698 112 698 DL 120 698 116 698
+DL 124 698 120 698 DL 128 698 124 698 DL 132 698 128 698 DL 136 698 132 698 DL
+140 698 136 698 DL 144 698 140 698 DL/F4 8/Times-Roman@0 SF
+(*BSD/386 is a trademark of Berk)72 708 Q(ele)-.08 E 2(yS)-.12 G(oftw)198.896
+708 Q(are Design, Inc.)-.08 E EP
+%%Trailer
+end
+%%EOF
diff --git a/documentation/article.txt b/documentation/article.txt
new file mode 100644 (file)
index 0000000..38cd71f
--- /dev/null
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+                   Bash - The GNU shell*
+
+
+                         Chet Ramey
+              Case Western Reserve University
+                      chet@po.cwru.edu
+
+
+
+
+
+
+_\b1.  _\bI_\bn_\bt_\br_\bo_\bd_\bu_\bc_\bt_\bi_\bo_\bn
+
+     _\bB_\ba_\bs_\bh is the shell,  or  command  language  interpreter,
+that  will  appear in the GNU operating system.  The name is
+an acronym for the "Bourne-Again  SHell",  a  pun  on  Steve
+Bourne,  the  author  of  the direct ancestor of the current
+UNIX|\b- shell /_\bb_\bi_\bn/_\bs_\bh, which appeared in the  Seventh  Edition
+Bell Labs Research version of UNIX.
+
+     Bash is an sh-compatible shell that incorporates useful
+features  from  the  Korn shell (ksh) and the C shell (csh),
+described later in this article.  It is ultimately  intended
+to  be  a  conformant implementation of the IEEE POSIX Shell
+and Utilities specification (IEEE Working Group 1003.2).  It
+offers  functional improvements over sh for both interactive
+and programming use.
+
+     While the GNU operating system will most likely include
+a  version  of  the  Berkeley  shell  csh,  Bash will be the
+default shell.  Like other GNU software, Bash is quite port-
+able.  It currently runs on nearly every version of UNIX and
+a few other operating systems -  an  independently-supported
+port  exists  for OS/2, and there are rumors of ports to DOS
+and Windows NT.  Ports to UNIX-like systems such as QNX  and
+Minix are part of the distribution.
+
+     The original author of Bash was Brian Fox, an  employee
+of  the Free Software Foundation.  The current developer and
+maintainer is Chet Ramey, a  volunteer  who  works  at  Case
+Western Reserve University.
+
+_\b2.  _\bW_\bh_\ba_\bt'_\bs _\bP_\bO_\bS_\bI_\bX, _\ba_\bn_\by_\bw_\ba_\by?
+
+     _\bP_\bO_\bS_\bI_\bX is a name originally coined by  Richard  Stallman
+_________________________
+*An earlier version of this  article  appeared  in  The
+Linux Journal.
+|\b- UNIX is a trademark of Bell Laboratories.
+
+
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 2 -
+
+
+for a family of open system standards based on UNIX.   There
+are  a  number  of  aspects  of UNIX under consideration for
+standardization, from the basic system services at the  sys-
+tem  call  and  C library level to applications and tools to
+system administration and management.  Each  area  of  stan-
+dardization  is  assigned  to  a  working  group in the 1003
+series.
+
+     The  POSIX  Shell  and  Utilities  standard  has   been
+developed by IEEE Working Group 1003.2 (POSIX.2).|\b=  It  con-
+centrates  on  the command interpreter interface and utility
+programs commonly executed from the command line or by other
+programs.   An  initial  version  of  the  standard has been
+approved and published by the IEEE, and  work  is  currently
+underway to update it.  There are four primary areas of work
+in the 1003.2 standard:
+
+o\b+    Aspects of the shell's syntax and command language.   A
+     number  of  special  builtins  such  as _\bc_\bd and _\be_\bx_\be_\bc are
+     being specified as part of the shell, since their func-
+     tionality  usually  cannot be implemented by a separate
+     executable;
+
+o\b+    A set of utilities to be called by  shell  scripts  and
+     applications.   Examples are programs like _\bs_\be_\bd, _\bt_\br, and
+     _\ba_\bw_\bk.  Utilities commonly implemented as shell  builtins
+     are  described  in this section, such as _\bt_\be_\bs_\bt and _\bk_\bi_\bl_\bl.
+     An expansion of this section's scope, termed  the  User
+     Portability   Extension,   or   UPE,  has  standardized
+     interactive programs such as _\bv_\bi and _\bm_\ba_\bi_\bl_\bx;
+
+o\b+    A group of functional interfaces to  services  provided
+     by  the  shell,  such  as  the  traditional  system() C
+     library function.  There are functions to perform shell
+     word expansions, perform filename expansion (_\bg_\bl_\bo_\bb_\bb_\bi_\bn_\bg),
+     obtain values of  POSIX.2  system  configuration  vari-
+     ables,   retrieve   values   of  environment  variables
+     (getenv()), _\ba_\bn_\bd _\bo_\bt_\bh_\be_\br _\bs_\be_\br_\bv_\bi_\bc_\be_\bs;
+
+o\b+    A suite of "development" utilities  such  as  _\bc_\b8_\b9  (the
+     POSIX.2 version of _\bc_\bc), and _\by_\ba_\bc_\bc.
+
+     Bash is concerned  with  the  aspects  of  the  shell's
+behavior defined by POSIX.2.  The shell command language has
+of course been standardized, including the basic  flow  con-
+trol  and  program execution constructs, I/O redirection and
+pipelining, argument handling, variable expansion, and quot-
+ing.   The  _\bs_\bp_\be_\bc_\bi_\ba_\bl  builtins,  which must be implemented as
+part of the shell to provide the desired functionality,  are
+_________________________
+|\b=IEEE, _\bI_\bE_\bE_\bE  _\bS_\bt_\ba_\bn_\bd_\ba_\br_\bd  _\bf_\bo_\br  _\bI_\bn_\bf_\bo_\br_\bm_\ba_\bt_\bi_\bo_\bn  _\bT_\be_\bc_\bh_\bn_\bo_\bl_\bo_\bg_\by  --
+_\bP_\bo_\br_\bt_\ba_\bb_\bl_\be  _\bO_\bp_\be_\br_\ba_\bt_\bi_\bn_\bg  _\bS_\by_\bs_\bt_\be_\bm  _\bI_\bn_\bt_\be_\br_\bf_\ba_\bc_\be  (_\bP_\bO_\bS_\bI_\bX) _\bP_\ba_\br_\bt _\b2:
+_\bS_\bh_\be_\bl_\bl _\ba_\bn_\bd _\bU_\bt_\bi_\bl_\bi_\bt_\bi_\be_\bs, 1992.
+
+
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 3 -
+
+
+specified as being part of the shell; examples of these  are
+_\be_\bv_\ba_\bl  and _\be_\bx_\bp_\bo_\br_\bt.  Other utilities appear in the sections of
+POSIX.2 not devoted to the shell which are commonly (and  in
+some cases must be) implemented as builtin commands, such as
+_\br_\be_\ba_\bd and  _\bt_\be_\bs_\bt.   POSIX.2  also  specifies  aspects  of  the
+shell's  interactive  behavior as part of the UPE, including
+job control and command line editing.  Interestingly enough,
+only  _\bv_\bi-style line editing commands have been standardized;
+_\be_\bm_\ba_\bc_\bs editing commands were left out due to objections.
+
+     While POSIX.2 includes much of what the shell has trad-
+itionally  provided, some important things have been omitted
+as being "beyond its scope."  There  is,  for  instance,  no
+mention  of a difference between a _\bl_\bo_\bg_\bi_\bn shell and any other
+interactive shell (since POSIX.2 does not  specify  a  login
+program).   No fixed startup files are defined, either - the
+standard does not mention ._\bp_\br_\bo_\bf_\bi_\bl_\be.
+
+_\b3.  _\bB_\ba_\bs_\bi_\bc _\bB_\ba_\bs_\bh _\bf_\be_\ba_\bt_\bu_\br_\be_\bs
+
+     Since the Bourne shell provides Bash with most  of  its
+philosophical  underpinnings,  Bash  inherits  most  of  its
+features and functionality from sh.  Bash implements all  of
+the  traditional sh flow control constructs (_\bf_\bo_\br, _\bi_\bf, _\bw_\bh_\bi_\bl_\be,
+etc.).  All of the Bourne shell  builtins,  including  those
+not  specified  in  the  POSIX.2  standard,  appear in Bash.
+Shell _\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn_\bs, introduced  in  the  SVR2  version  of  the
+Bourne  shell, are similar to shell scripts, but are defined
+using a special syntax and are executed in the same  process
+as the calling shell.  Bash has shell functions which behave
+in a fashion upward-compatible with sh functions.  There are
+certain shell variables that Bash interprets in the same way
+as sh, such as _\bP_\bS_\b1, _\bI_\bF_\bS, and _\bP_\bA_\bT_\bH.  Bash  implements  essen-
+tially  the  same  grammar, parameter and variable expansion
+semantics, redirection, and quoting  as  the  Bourne  shell.
+Where  differences  appear  between the POSIX.2 standard and
+traditional sh behavior, Bash follows POSIX.
+
+     The Korn Shell (ksh) is  a  descendent  of  the  Bourne
+shell  written at AT&T Bell Laboratories by David Korn|\b-.  It
+provides a number of useful features  that  POSIX  and  Bash
+have adopted.  Many of the interactive facilities in POSIX.2
+have their roots in the ksh: for example, the POSIX and  ksh
+job  control  facilities are nearly identical. Bash includes
+features from the Korn Shell for both  interactive  use  and
+shell programming.  For programming, Bash provides variables
+such as _\bR_\bA_\bN_\bD_\bO_\bM and _\bR_\bE_\bP_\bL_\bY, the _\bt_\by_\bp_\be_\bs_\be_\bt builtin,  the  ability
+to  remove  substrings from variables based on patterns, and
+shell arithmetic.  _\bR_\bA_\bN_\bD_\bO_\bM expands to a  random  number  each
+time it is referenced; assigning a value to _\bR_\bA_\bN_\bD_\bO_\bM seeds the
+_________________________
+|\b-Morris Bolsky and David Korn,  _\bT_\bh_\be  _\bK_\bo_\br_\bn_\bS_\bh_\be_\bl_\bl  _\bC_\bo_\bm_\bm_\ba_\bn_\bd
+_\ba_\bn_\bd _\bP_\br_\bo_\bg_\br_\ba_\bm_\bm_\bi_\bn_\bg _\bL_\ba_\bn_\bg_\bu_\ba_\bg_\be, Prentice Hall, 1989.
+
+
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 4 -
+
+
+random number generator.  _\bR_\bE_\bP_\bL_\bY is the default variable used
+by  the  _\br_\be_\ba_\bd builtin when no variable names are supplied as
+arguments.  The _\bt_\by_\bp_\be_\bs_\be_\bt builtin is used to define  variables
+and  give them attributes such as readonly.  Bash arithmetic
+allows the evaluation of an expression and the  substitution
+of the result.  Shell variables may be used as operands, and
+the result of an expression may be assigned to  a  variable.
+Nearly  all  of the operators from the C language are avail-
+able, with the same precedence rules:
+\e9     $ echo $((3 + 5 * 32))
+     163
+\e9
+For interactive use, Bash implements ksh-style  aliases  and
+builtins  such  as  _\bf_\bc  (discussed  below)  and  _\bj_\bo_\bb_\bs.  Bash
+aliases allow a string to be substituted for a command name.
+They  can  be  used  to create a mnemonic for a UNIX command
+name (alias del=rm), to expand a single word  to  a  complex
+command (alias news='xterm -g 80x45 -title trn -e trn -e -S1
+-N &'), or to ensure that a command is invoked with a  basic
+set of options (alias ls="/bin/ls -F").
+
+     The C shell (csh)|\b-,  originally  written  by  Bill  Joy
+while  at Berkeley, is widely used and quite popular for its
+interactive facilities.  Bash includes a csh-compatible his-
+tory  expansion  mechanism  ("!  history"), brace expansion,
+access to a stack of directories via the  _\bp_\bu_\bs_\bh_\bd,  _\bp_\bo_\bp_\bd,  and
+_\bd_\bi_\br_\bs  builtins, and tilde expansion, to generate users' home
+directories.  Tilde expansion has also been adopted by  both
+the Korn Shell and POSIX.2.
+
+     There were certain areas in which  POSIX.2  felt  stan-
+dardization  was  necessary,  but no existing implementation
+provided the proper behavior.  The  working  group  invented
+and  standardized  functionality  in these areas, which Bash
+implements.  The _\bc_\bo_\bm_\bm_\ba_\bn_\bd builtin was invented so that  shell
+functions could be written to replace builtins; it makes the
+capabilities of the builtin available to the function.   The
+reserved  word "!" was added to negate the return value of a
+command or pipeline; it was nearly impossible to express "if
+not  x" cleanly using the sh language.  There exist multiple
+incompatible implementations  of  the  _\bt_\be_\bs_\bt  builtin,  which
+tests  files  for  type  and  other  attributes and performs
+arithmetic and string comparisons.  POSIX considered none of
+these  correct,  so  the  standard behavior was specified in
+terms of the number of arguments to  the  command.   POSIX.2
+dictates  exactly  what will happen when four or fewer argu-
+ments are given to _\bt_\be_\bs_\bt, and leaves the  behavior  undefined
+when  more  arguments  are  supplied.  Bash uses the POSIX.2
+_________________________
+|\b-Bill Joy, An Introduction to the C Shell, _\bU_\bN_\bI_\bX  _\bU_\bs_\be_\br'_\bs
+_\bS_\bu_\bp_\bp_\bl_\be_\bm_\be_\bn_\bt_\ba_\br_\by  _\bD_\bo_\bc_\bu_\bm_\be_\bn_\bt_\bs,  University  of California at
+Berkeley, 1986.
+
+
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 5 -
+
+
+algorithm, which was conceived by David Korn.
+
+_\b3._\b1.  _\bF_\be_\ba_\bt_\bu_\br_\be_\bs _\bn_\bo_\bt _\bi_\bn _\bt_\bh_\be _\bB_\bo_\bu_\br_\bn_\be _\bS_\bh_\be_\bl_\bl
+
+     There are a number of minor  differences  between  Bash
+and  the  version  of  sh  present on most other versions of
+UNIX.  The majority of these are due to the POSIX  standard,
+but some are the result of Bash adopting features from other
+shells.  For instance, Bash includes the  new  "!"  reserved
+word,  the  _\bc_\bo_\bm_\bm_\ba_\bn_\bd builtin, the ability of the _\br_\be_\ba_\bd builtin
+to correctly return a line ending with a backslash, symbolic
+arguments  to the _\bu_\bm_\ba_\bs_\bk builtin, variable substring removal,
+a way to get the length of a variable, and the new algorithm
+for  the  _\bt_\be_\bs_\bt  builtin  from  the POSIX.2 standard, none of
+which appear in sh.
+
+     Bash also implements the "$(...)" command  substitution
+syntax,  which  supersedes  the  sh  `...`  construct.   The
+"$(...)" construct expands to the output of the command con-
+tained   within  the  parentheses,  with  trailing  newlines
+removed.  The sh syntax is accepted for  backwards  compati-
+bility, but the "$(...)" form is preferred because its quot-
+ing rules are much simpler and it is easier to nest.
+
+     The Bourne shell does  not  provide  such  features  as
+brace  expansion,  the  ability  to  define a variable and a
+function with the same name, local variables in shell  func-
+tions, the ability to enable and disable individual builtins
+or write a function to replace a  builtin,  or  a  means  to
+export a shell function to a child process.
+
+     Bash has closed a long-standing shell security hole  by
+not  using  the $_\bI_\bF_\bS variable to split each word read by the
+shell, but splitting only the results of expansion (ksh  and
+the  4.4  BSD  sh have fixed this as well).  Useful behavior
+such as a means to abort execution of a script read with the
+"."  command  using  the  return  builtin  or  automatically
+exporting variables in the shell's environment  to  children
+is  also  not  present in the Bourne shell.  Bash provides a
+much more powerful environment for both interactive use  and
+programming.
+
+_\b4.  _\bB_\ba_\bs_\bh-_\bs_\bp_\be_\bc_\bi_\bf_\bi_\bc _\bF_\be_\ba_\bt_\bu_\br_\be_\bs
+
+     This section details a few of the features  which  make
+Bash unique.  Most of them provide improved interactive use,
+but a few programming  improvements  are  present  as  well.
+Full descriptions of these features can be found in the Bash
+documentation.
+
+_\b4._\b1.  _\bS_\bt_\ba_\br_\bt_\bu_\bp _\bF_\bi_\bl_\be_\bs
+
+     Bash executes  startup  files  differently  than  other
+shells.   The  Bash behavior is a compromise between the csh
+
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 6 -
+
+
+principle of startup files with  fixed  names  executed  for
+each shell and the sh "minimalist" behavior.  An interactive
+instance of Bash started as a login shell reads and executes
+~/._\bb_\ba_\bs_\bh__\bp_\br_\bo_\bf_\bi_\bl_\be  (the  file .bash_profile in the user's home
+directory), if it exists.  An  interactive  non-login  shell
+reads  and executes ~/._\bb_\ba_\bs_\bh_\br_\bc.  A non-interactive shell (one
+begun to execute a shell script, for example) reads no fixed
+startup  file,  but  uses the value of the variable $_\bE_\bN_\bV, if
+set, as the name of a startup file.   The  ksh  practice  of
+reading  $_\bE_\bN_\bV  for every shell, with the accompanying diffi-
+culty of defining the proper  variables  and  functions  for
+interactive  and  non-interactive  shells or having the file
+read only for interactive shells, was  considered  too  com-
+plex.   Ease  of  use won out here.  Interestingly, the next
+release of ksh will change to reading $_\bE_\bN_\bV only for interac-
+tive shells.
+
+_\b4._\b2.  _\bN_\be_\bw _\bB_\bu_\bi_\bl_\bt_\bi_\bn _\bC_\bo_\bm_\bm_\ba_\bn_\bd_\bs
+
+     There are a few builtins which are  new  or  have  been
+extended  in  Bash.   The _\be_\bn_\ba_\bb_\bl_\be builtin allows builtin com-
+mands to be turned on and off arbitrarily.  To use the  ver-
+sion  of  _\be_\bc_\bh_\bo found in a user's search path rather than the
+Bash builtin, enable -n echo  suffices.   The  _\bh_\be_\bl_\bp  builtin
+provides  quick  synopses  of  the  shell facilities without
+requiring access to a manual page.  _\bB_\bu_\bi_\bl_\bt_\bi_\bn  is  similar  to
+_\bc_\bo_\bm_\bm_\ba_\bn_\bd  in  that  it  bypasses shell functions and directly
+executes builtin commands.  Access to a csh-style  stack  of
+directories  is provided via the _\bp_\bu_\bs_\bh_\bd, _\bp_\bo_\bp_\bd, and _\bd_\bi_\br_\bs buil-
+tins.  _\bP_\bu_\bs_\bh_\bd and _\bp_\bo_\bp_\bd insert and remove directories from the
+stack,  respectively, and _\bd_\bi_\br_\bs lists the stack contents.  On
+systems that allow fine-grained control  of  resources,  the
+_\bu_\bl_\bi_\bm_\bi_\bt  builtin  can be used to tune these settings.  _\bU_\bl_\bi_\bm_\bi_\bt
+allows a user to control, among other things,  whether  core
+dumps  are  to  be generated, how much memory the shell or a
+child process is allowed to allocate, and how large  a  file
+created  by  a  child process can grow.  The _\bs_\bu_\bs_\bp_\be_\bn_\bd command
+will stop the shell process when job control is active; most
+other  shells  do  not  allow  themselves to be stopped like
+that.  _\bT_\by_\bp_\be, the Bash answer to _\bw_\bh_\bi_\bc_\bh and _\bw_\bh_\be_\bn_\bc_\be, shows what
+will happen when a word is typed as a command:
+\e9     $ type export
+     export is a shell builtin
+     $ type -t export
+     builtin
+     $ type bash
+     bash is /bin/bash
+     $ type cd
+     cd is a function
+     cd ()
+     {
+         builtin cd ${1+"$@"} && xtitle $HOST: $PWD
+     }
+\e9
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 7 -
+
+
+Various modes tell what a command word  is  (reserved  word,
+alias,  function,  builtin,  or  file) or which version of a
+command will be executed based  on  a  user's  search  path.
+Some  of  this functionality has been adopted by POSIX.2 and
+folded into the _\bc_\bo_\bm_\bm_\ba_\bn_\bd utility.
+
+_\b4._\b3.  _\bE_\bd_\bi_\bt_\bi_\bn_\bg _\ba_\bn_\bd _\bC_\bo_\bm_\bp_\bl_\be_\bt_\bi_\bo_\bn
+
+     One area in which Bash shines is command line  editing.
+Bash  uses  the _\br_\be_\ba_\bd_\bl_\bi_\bn_\be library to read and edit lines when
+interactive.  Readline is  a  powerful  and  flexible  input
+facility that a user can configure to individual tastes.  It
+allows lines to be edited using either emacs or vi commands,
+where  those  commands are appropriate.  The full capability
+of emacs is not present - there is no way to execute a named
+command  with  M-x, for instance - but the existing commands
+are more than adequate.  The vi mode is compliant  with  the
+command line editing standardized by POSIX.2.
+
+     Readline is fully customizable.   In  addition  to  the
+basic commands and key bindings, the library allows users to
+define additional key bindings using a  startup  file.   The
+_\bi_\bn_\bp_\bu_\bt_\br_\bc file, which defaults to the file ~/._\bi_\bn_\bp_\bu_\bt_\br_\bc, is read
+each time readline initializes, permitting users to maintain
+a  consistent  interface across a set of programs.  Readline
+includes an extensible interface, so each program using  the
+library  can  add  its  own  bindable  commands and program-
+specific key bindings.  Bash uses this facility to add bind-
+ings that perform history expansion or shell word expansions
+on the current input line.
+
+     Readline interprets a number of variables which further
+tune  its  behavior.   Variables exist to control whether or
+not eight-bit characters are directly read as input or  con-
+verted  to  meta-prefixed key sequences (a meta-prefixed key
+sequence consists of  the  character  with  the  eighth  bit
+zeroed,  preceded  by  the  _\bm_\be_\bt_\ba-_\bp_\br_\be_\bf_\bi_\bx  character,  usually
+escape,  which  selects  an  alternate  keymap),  to  decide
+whether  to  output  characters  with  the  eighth  bit  set
+directly or as a meta-prefixed key sequence, whether or  not
+to  wrap  to  a  new screen line when a line being edited is
+longer than the screen width, the keymap to which subsequent
+key  bindings  should apply, or even what happens when read-
+line wants to ring the terminal's bell.  All of these  vari-
+ables can be set in the inputrc file.
+
+     The startup file understands a set of  C  preprocessor-
+like  conditional  constructs  which  allow variables or key
+bindings to be assigned based on the application using read-
+line,  the  terminal  currently  being  used, or the editing
+mode.  Users can add program-specific bindings to make their
+lives easier:  I have bindings that let me edit the value of
+$_\bP_\bA_\bT_\bH and double-quote the current or previous word:
+\e9     # Macros that are convenient for shell interaction
+
+
+\e9                       July 18, 1994
+
+
+
+
+
+                           - 8 -
+
+
+     $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 and move to just after the open quote
+     "\C-x\"": "\"\"\C-b"
+     # Quote the current or previous word
+     "\C-xq": "\eb\"\ef\""
+     $endif
+\e9
+There is a readline command to re-read the  file,  so  users
+can  edit  the  file, change some bindings, and begin to use
+them almost immediately.
+
+     Bash implements the _\bb_\bi_\bn_\bd builtin for more  dyamic  con-
+trol  of  readline  than  the startup file permits.  _\bB_\bi_\bn_\bd is
+used in several ways.  In _\bl_\bi_\bs_\bt  mode,  it  can  display  the
+current  key  bindings, list all the readline editing direc-
+tives available for binding, list which keys invoke a  given
+directive,  or  output  the current set of key bindings in a
+format that can be incorporated  directly  into  an  inputrc
+file.   In  _\bb_\ba_\bt_\bc_\bh  mode,  it  reads a series of key bindings
+directly from a file and passes them to  readline.   In  its
+most  common usage, _\bb_\bi_\bn_\bd takes a single string and passes it
+directly to readline, which interprets the line as if it had
+just been read from the inputrc file.  Both key bindings and
+variable assignments may appear in the string given to _\bb_\bi_\bn_\bd.
+
+     The readline library also  provides  an  interface  for
+_\bw_\bo_\br_\bd  _\bc_\bo_\bm_\bp_\bl_\be_\bt_\bi_\bo_\bn.   When  the  _\bc_\bo_\bm_\bp_\bl_\be_\bt_\bi_\bo_\bn character (usually
+TAB) is typed, readline looks at the  word  currently  being
+entered  and  computes  the  set  of  filenames of which the
+current word is a valid prefix.  If there is only one possi-
+ble  completion,  the  rest  of  the characters are inserted
+directly,  otherwise  the  common  prefix  of  the  set   of
+filenames  is added to the current word.  A second TAB char-
+acter entered  immediately  after  a  non-unique  completion
+causes  readline  to list the possible completions; there is
+an option to have the list displayed immediately.   Readline
+provides  hooks  so  that  applications can provide specific
+types of completion before the default  filename  completion
+is attempted.  This is quite flexible, though it is not com-
+pletely user-programmable.  Bash, for example, can  complete
+filenames, command names (including aliases, builtins, shell
+reserved words, shell functions, and  executables  found  in
+the file system), shell variables, usernames, and hostnames.
+It uses a set of heuristics that, while not perfect, is gen-
+erally  quite good at determining what type of completion to
+attempt.
+
+_\b4._\b4.  _\bH_\bi_\bs_\bt_\bo_\br_\by
+
+     Access to the list of commands previously entered  (the
+_\bc_\bo_\bm_\bm_\ba_\bn_\bd  _\bh_\bi_\bs_\bt_\bo_\br_\by)  is  provided  jointly  by  Bash  and  the
+
+
+\e9                       July 18, 1994
+
+
+
+
+
+                           - 9 -
+
+
+readline  library.   Bash  provides  variables   ($HISTFILE,
+$HISTSIZE, and $HISTCONTROL) and the _\bh_\bi_\bs_\bt_\bo_\br_\by and _\bf_\bc builtins
+to manipulate the history  list.   The  value  of  $_\bH_\bI_\bS_\bT_\bF_\bI_\bL_\bE
+specifes  the  file where Bash writes the command history on
+exit and reads it on startup.  $_\bH_\bI_\bS_\bT_\bS_\bI_\bZ_\bE is  used  to  limit
+the  number  of commands saved in the history.  $_\bH_\bI_\bS_\bT_\bC_\bO_\bN_\bT_\bR_\bO_\bL
+provides a crude form of control  over  which  commands  are
+saved  on  the history list: a value of _\bi_\bg_\bn_\bo_\br_\be_\bs_\bp_\ba_\bc_\be means to
+not save commands which begin  with  a  space;  a  value  of
+_\bi_\bg_\bn_\bo_\br_\be_\bd_\bu_\bp_\bs  means to not save commands identical to the last
+command saved.  $HISTCONTROL was named  $history_control  in
+earlier versions of Bash; the old name is still accepted for
+backwards compatibility.  The _\bh_\bi_\bs_\bt_\bo_\br_\by command  can  read  or
+write  files  containing  the  history  list and display the
+current list contents.  The _\bf_\bc builtin, adopted from POSIX.2
+and  the  Korn  Shell, allows display and re-execution, with
+optional editing, of commands from the  history  list.   The
+readline library offers a set of commands to search the his-
+tory list for a portion of  the  current  input  line  or  a
+string  typed  by  the  user.  Finally, the _\bh_\bi_\bs_\bt_\bo_\br_\by library,
+generally incorporated directly into the  readline  library,
+implements  a  facility  for  history recall, expansion, and
+re-execution of previous commands very similar to csh ("bang
+history", so called because the exclamation point introduces
+a history substitution):
+\e9     $ echo a b c d e
+     a b c d e
+     $ !! f g h i
+     echo a b c d e f g h i
+     a b c d e f g h i
+     $ !-2
+     echo a b c d e
+     a b c d e
+     $ echo !-2:1-4
+     echo a b c d
+     a b c d
+\e9
+The command history is only saved when the shell is interac-
+tive, so it is not available for use by shell scripts.
+
+_\b4._\b5.  _\bN_\be_\bw _\bS_\bh_\be_\bl_\bl _\bV_\ba_\br_\bi_\ba_\bb_\bl_\be_\bs
+
+     There are a number of convenience variables  that  Bash
+interprets  to  make  life  easier.   These include _\bF_\bI_\bG_\bN_\bO_\bR_\bE,
+which is a set of filename  suffixes  identifying  files  to
+exclude   when  completing  filenames;  _\bH_\bO_\bS_\bT_\bT_\bY_\bP_\bE,  which  is
+automatically  set  to  a  string  describing  the  type  of
+hardware    on    which   Bash   is   currently   executing;
+_\bc_\bo_\bm_\bm_\ba_\bn_\bd__\bo_\br_\bi_\be_\bn_\bt_\be_\bd__\bh_\bi_\bs_\bt_\bo_\br_\by, which directs  Bash  to  save  all
+lines of a multiple-line command such as a _\bw_\bh_\bi_\bl_\be or _\bf_\bo_\br loop
+in a single history entry,  allowing  easy  re-editing;  and
+_\bI_\bG_\bN_\bO_\bR_\bE_\bE_\bO_\bF,  whose  value indicates the number of consecutive
+EOF characters that an interactive shell  will  read  before
+
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 10 -
+
+
+exiting - an easy way to keep yourself from being logged out
+accidentally.  The _\ba_\bu_\bt_\bo__\br_\be_\bs_\bu_\bm_\be variable alters the  way  the
+shell treats simple command names: if job control is active,
+and  this  variable  is  set,  single-word  simple  commands
+without  redirections  cause the shell to first look for and
+restart a suspended job with that name before starting a new
+process.
+
+_\b4._\b6.  _\bB_\br_\ba_\bc_\be _\bE_\bx_\bp_\ba_\bn_\bs_\bi_\bo_\bn
+
+     Since sh offers no convenient way to generate arbitrary
+strings  that  share  a  common  prefix  or suffix (filename
+expansion requires that the filenames  exist),  Bash  imple-
+ments  _\bb_\br_\ba_\bc_\be  _\be_\bx_\bp_\ba_\bn_\bs_\bi_\bo_\bn,  a  capability  picked up from csh.
+Brace expansion is similar to filename  expansion,  but  the
+strings  generated need not correspond to existing files.  A
+brace expression consists of an optional _\bp_\br_\be_\ba_\bm_\bb_\bl_\be,  followed
+by  a  pair  of braces enclosing a series of comma-separated
+strings,  and  an  optional  _\bp_\bo_\bs_\bt_\ba_\bm_\bb_\bl_\be.   The  preamble   is
+prepended  to each string within the braces, and the postam-
+ble is then appended to each resulting string:
+\e9     $ echo a{d,c,b}e
+     ade ace abe
+\e9
+As this example demonstrates, the results of brace expansion
+are not sorted, as they are by filename expansion.
+
+_\b4._\b7.  _\bP_\br_\bo_\bc_\be_\bs_\bs _\bS_\bu_\bb_\bs_\bt_\bi_\bt_\bu_\bt_\bi_\bo_\bn
+
+     On systems that can support it, Bash provides a  facil-
+ity  known as _\bp_\br_\bo_\bc_\be_\bs_\bs _\bs_\bu_\bb_\bs_\bt_\bi_\bt_\bu_\bt_\bi_\bo_\bn.  Process substitution is
+similar to command substitution in  that  its  specification
+includes  a  command to execute, but the shell does not col-
+lect the command's output and insert  it  into  the  command
+line.   Rather,  Bash  opens a pipe to the command, which is
+run in the background.  The shell uses named  pipes  (FIFOs)
+or  the  /_\bd_\be_\bv/_\bf_\bd  method  of naming open files to expand the
+process substitution to a filename  which  connects  to  the
+pipe  when  opened.  This filename becomes the result of the
+expansion.  Process substitution can be used to compare  the
+outputs  of two different versions of an application as part
+of a regression test:
+\e9     $ cmp <(old_prog) <(new_prog)
+\e9
+_\b4._\b8.  _\bP_\br_\bo_\bm_\bp_\bt _\bC_\bu_\bs_\bt_\bo_\bm_\bi_\bz_\ba_\bt_\bi_\bo_\bn
+
+     One of the more popular interactive features that  Bash
+provides  is the ability to customize the prompt.  Both $_\bP_\bS_\b1
+and $_\bP_\bS_\b2, the primary and secondary  prompts,  are  expanded
+before being displayed.  Parameter and variable expansion is
+performed when the prompt string is expanded, so  any  shell
+variable  can  be  put  into the prompt (e.g., $_\bS_\bH_\bL_\bV_\bL, which
+
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 11 -
+
+
+indicates how deeply the current  shell  is  nested).   Bash
+specially  interprets  characters  in the prompt string pre-
+ceded by a backslash.  Some of these backslash  escapes  are
+replaced  with the current time, the date, the current work-
+ing directory, the username, and the command number or  his-
+tory  number  of the command being entered.  There is even a
+backslash escape to cause the shell  to  change  its  prompt
+when running as root after an _\bs_\bu.  Before printing each pri-
+mary prompt, Bash expands the variable $_\bP_\bR_\bO_\bM_\bP_\bT__\bC_\bO_\bM_\bM_\bA_\bN_\bD  and,
+if it has a value, executes the expanded value as a command,
+allowing additional prompt customization.  For example, this
+assignment  causes  the  current user, the current host, the
+time, the last component of the current  working  directory,
+the  level  of  shell nesting, and the history number of the
+current command to be embedded into the primary prompt:
+\e9     $ PS1='\u@\h [\t] \W($SHLVL:\!)\$ '
+     chet@odin [21:03:44] documentation(2:636)$ cd ..
+     chet@odin [21:03:54] src(2:637)$
+\e9
+The string being assigned is surrounded by single quotes  so
+that  if it is exported, the value of $_\bS_\bH_\bL_\bV_\bL will be updated
+by a child shell:
+\e9     chet@odin [21:17:35] src(2:638)$ export PS1
+     chet@odin [21:17:40] src(2:639)$ bash
+     chet@odin [21:17:46] src(3:696)$
+\e9
+The \$ escape is displayed as "$" when running as  a  normal
+user, but as "#" when running as root.
+
+_\b4._\b9.  _\bF_\bi_\bl_\be _\bS_\by_\bs_\bt_\be_\bm _\bV_\bi_\be_\bw_\bs
+
+     Since Berkeley introduced symbolic links  in  4.2  BSD,
+one of their most annoying properties has been the "warping"
+to a completely different area of the file system when using
+_\bc_\bd,  and  the  resultant  non-intuitive behavior of "cd ..".
+The UNIX kernel treats symbolic links _\bp_\bh_\by_\bs_\bi_\bc_\ba_\bl_\bl_\by.  When  the
+kernel is translating a pathname in which one component is a
+symbolic link, it replaces all or part of the pathname while
+processing  the  link.  If the contents of the symbolic link
+begin  with  a  slash,  the  kernel  replaces  the  pathname
+entirely; if not, the link contents replace the current com-
+ponent.  In either case, the symbolic link is  visible.   If
+the  link value is an absolute pathname, the user finds him-
+self in a completely different part of the file system.
+
+     Bash provides a _\bl_\bo_\bg_\bi_\bc_\ba_\bl view of the  file  system.   In
+this default mode, command and filename completion and buil-
+tin commands such as _\bc_\bd and _\bp_\bu_\bs_\bh_\bd which change  the  current
+working  directory transparently follow symbolic links as if
+they were directories.  The $_\bP_\bW_\bD variable, which  holds  the
+shell's  idea  of  the current working directory, depends on
+the path  used  to  reach  the  directory  rather  than  its
+
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 12 -
+
+
+physical  location  in the local file system hierarchy.  For
+example:
+\e9     $ cd /usr/local/bin
+     $ echo $PWD
+     /usr/local/bin
+     $ pwd
+     /usr/local/bin
+     $ /bin/pwd
+     /net/share/sun4/local/bin
+     $ cd ..
+     $ pwd
+     /usr/local
+     $ /bin/pwd
+     /net/share/sun4/local
+     $ cd ..
+     $ pwd
+     /usr
+     $ /bin/pwd
+     /usr
+\e9
+One problem with this, of course, arises when programs  that
+do  not  understand  the  shell's logical notion of the file
+system interpret ".." differently.  This  generally  happens
+when Bash completes filenames containing ".." according to a
+logical hierarchy which does not correspond to their  physi-
+cal  location.  For  users  who  find  this  troublesome,  a
+corresponding _\bp_\bh_\by_\bs_\bi_\bc_\ba_\bl view of the file system is available:
+\e9     $ cd /usr/local/bin
+     $ pwd
+     /usr/local/bin
+     $ set -o physical
+     $ pwd
+     /net/share/sun4/local/bin
+\e9
+_\b4._\b1_\b0.  _\bI_\bn_\bt_\be_\br_\bn_\ba_\bt_\bi_\bo_\bn_\ba_\bl_\bi_\bz_\ba_\bt_\bi_\bo_\bn
+
+     One of the most  significant  improvements  in  version
+1.13  of  Bash  was  the  change to "eight-bit cleanliness".
+Previous versions used the eighth bit of characters to  mark
+whether  or not they were quoted when performing word expan-
+sions.  While this did not affect  the  majority  of  users,
+most  of  whom  used  only  seven-bit ASCII characters, some
+found it  confining.   Beginning  with  version  1.13,  Bash
+implemented a different quoting mechanism that did not alter
+the eighth bit of characters.  This allowed Bash to  manipu-
+late  files  with  "odd"  characters in their names, but did
+nothing to help users enter those  names,  so  version  1.13
+introduced  changes to readline that made it eight-bit clean
+as well.  Options exist that force  readline  to  attach  no
+special  significance  to characters with the eighth bit set
+(the default behavior is  to  convert  these  characters  to
+meta-prefixed  key sequences) and to output these characters
+
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 13 -
+
+
+without  conversion  to  meta-prefixed   sequences.    These
+changes, along with the expansion of keymaps to a full eight
+bits, enable readline to work with most of the ISO-8859 fam-
+ily of character sets, used by many European countries.
+
+_\b4._\b1_\b1.  _\bP_\bO_\bS_\bI_\bX _\bM_\bo_\bd_\be
+
+     Although Bash is intended  to  be  POSIX.2  conformant,
+there  are areas in which the default behavior is not compa-
+tible with the standard.  For users who wish to operate in a
+strict  POSIX.2  environment,  Bash implements a _\bP_\bO_\bS_\bI_\bX _\bm_\bo_\bd_\be.
+When this mode is active, Bash modifies its  default  opera-
+tion  where  it  differs from POSIX.2 to match the standard.
+POSIX mode is entered when Bash is started with  the  -_\bp_\bo_\bs_\bi_\bx
+option.   This feature is also available as an option to the
+set builtin, set -o posix.  For compatibility with other GNU
+software  that  attempts  to be POSIX.2 compliant, Bash also
+enters POSIX mode if the variable  $_\bP_\bO_\bS_\bI_\bX_\bL_\bY__\bC_\bO_\bR_\bR_\bE_\bC_\bT  is  set
+when  Bash  is started or assigned a value during execution.
+$_\bP_\bO_\bS_\bI_\bX__\bP_\bE_\bD_\bA_\bN_\bT_\bI_\bC is accepted as well, to be  compatible  with
+some  older  GNU  utilities.   When Bash is started in POSIX
+mode, for example, it sources the file named by the value of
+$_\bE_\bN_\bV  rather  than  the "normal" startup files, and does not
+allow reserved words to be aliased.
+
+_\b5.  _\bN_\be_\bw _\bF_\be_\ba_\bt_\bu_\br_\be_\bs _\ba_\bn_\bd _\bF_\bu_\bt_\bu_\br_\be _\bP_\bl_\ba_\bn_\bs
+
+     There are several features introduced  in  the  current
+version of Bash, version 1.14, and a number under considera-
+tion for future releases.  This section will briefly  detail
+the  new  features  in  version  1.14  and  describe several
+features that may appear in later versions.
+
+_\b5._\b1.  _\bN_\be_\bw _\bF_\be_\ba_\bt_\bu_\br_\be_\bs _\bi_\bn _\bB_\ba_\bs_\bh-_\b1._\b1_\b4
+
+     The new features available in Bash-1.14 answer  several
+of the most common requests for enhancements.  Most notably,
+there is a mechanism  for  including  non-visible  character
+sequences  in  prompts, such as those which cause a terminal
+to print characters in different colors or in standout mode.
+There  was  nothing preventing the use of these sequences in
+earlier  versions,  but  the  readline  redisplay  algorithm
+assumed  each  character  occupied physical screen space and
+would wrap lines prematurely.
+
+     Readline has a few new variables, several new  bindable
+commands,  and  some additional emacs mode default key bind-
+ings.  A new history search mode has  been  implemented:  in
+this mode, readline searches the history for lines beginning
+with the characters between the  beginning  of  the  current
+line  and  the  cursor.   The  existing readline incremental
+search commands no longer match identical  lines  more  than
+once.   Filename  completion now expands variables in direc-
+tory names.  The history expansion facilities are now nearly
+
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 14 -
+
+
+completely csh-compatible: missing modifiers have been added
+and history substitution has been extended.
+
+     Several of the features described earlier, such as  _\bs_\be_\bt
+-_\bo  _\bp_\bo_\bs_\bi_\bx  and  $_\bP_\bO_\bS_\bI_\bX__\bP_\bE_\bD_\bA_\bN_\bT_\bI_\bC,  are  new  in version 1.14.
+There is a new shell variable, _\bO_\bS_\bT_\bY_\bP_\bE, to which Bash assigns
+a  value that identifies the version of UNIX it's running on
+(great for putting architecture-specific binary  directories
+into the $PATH).  Two variables have been renamed: $_\bH_\bI_\bS_\bT_\bC_\bO_\bN_\b-
+_\bT_\bR_\bO_\bL  replaces  $_\bh_\bi_\bs_\bt_\bo_\br_\by__\bc_\bo_\bn_\bt_\br_\bo_\bl,  and  $_\bH_\bO_\bS_\bT_\bF_\bI_\bL_\bE   replaces
+$_\bh_\bo_\bs_\bt_\bn_\ba_\bm_\be__\bc_\bo_\bm_\bp_\bl_\be_\bt_\bi_\bo_\bn__\bf_\bi_\bl_\be.  In both cases, the old names are
+accepted for backwards compatibility.  The ksh  _\bs_\be_\bl_\be_\bc_\bt  con-
+struct,  which  allows  the  generation of simple menus, has
+been implemented.   New  capabilities  have  been  added  to
+existing  variables:  $_\ba_\bu_\bt_\bo__\br_\be_\bs_\bu_\bm_\be  can  now  take values of
+_\be_\bx_\ba_\bc_\bt or _\bs_\bu_\bb_\bs_\bt_\br_\bi_\bn_\bg, and $_\bH_\bI_\bS_\bT_\bC_\bO_\bN_\bT_\bR_\bO_\bL understands  the  value
+_\bi_\bg_\bn_\bo_\br_\be_\bb_\bo_\bt_\bh,  which  combines  the  two previously acceptable
+values.  The _\bd_\bi_\br_\bs builtin has acquired options to print  out
+specific members of the directory stack.  The $_\bn_\bo_\bl_\bi_\bn_\bk_\bs vari-
+able, which forces a physical view of the file  system,  has
+been  superseded  by  the  -_\bP  option  to  the  _\bs_\be_\bt  builtin
+(equivalent to set -o physical); the  variable  is  retained
+for  backwards  compatibility.  The version string contained
+in $_\bB_\bA_\bS_\bH__\bV_\bE_\bR_\bS_\bI_\bO_\bN now includes an  indication  of  the  patch
+level  as  well  as  the  "build version".  Some little-used
+features have been removed:  the _\bb_\by_\be synonym  for  _\be_\bx_\bi_\bt  and
+the  $_\bN_\bO__\bP_\bR_\bO_\bM_\bP_\bT__\bV_\bA_\bR_\bS  variable  are  gone.   There is now an
+organized test suite that can be run as  a  regression  test
+when building a new version of Bash.
+
+     The documentation has been thoroughly overhauled: there
+is  a  new  manual page on the readline library and the _\bi_\bn_\bf_\bo
+file has been updated to reflect the  current  version.   As
+always,  as  many bugs as possible have been fixed, although
+some surely remain.
+
+_\b5._\b2.  _\bO_\bt_\bh_\be_\br _\bF_\be_\ba_\bt_\bu_\br_\be_\bs
+
+     There are a few features that  I  hope  to  include  in
+later Bash releases.  Some are based on work already done in
+other shells.
+
+     In addition to simple variables, a  future  release  of
+Bash  will  include  one-dimensional  arrays,  using the ksh
+implementation of arrays as a model.  Additions to  the  ksh
+syntax,  such  as  _\bv_\ba_\br_\bn_\ba_\bm_\be=( ... ) to assign a list of words
+directly to an array and a mechanism to allow the _\br_\be_\ba_\bd buil-
+tin  to  read a list of values directly into an array, would
+be desirable.  Given those extensions, the ksh _\bs_\be_\bt -_\bA syntax
+may not be worth supporting (the -_\bA option assigns a list of
+values to an array, but is a rather peculiar special case).
+
+     Some shells include a means of _\bp_\br_\bo_\bg_\br_\ba_\bm_\bm_\ba_\bb_\bl_\be  word  com-
+pletion, where the user specifies on a per-command basis how
+
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 15 -
+
+
+the arguments of the command are to be treated when  comple-
+tion  is  attempted:  as  filenames,  hostnames,  executable
+files, and so on.  The other aspects  of  the  current  Bash
+implementation  could  remain as-is; the existing heuristics
+would still be valid.  Only when completing the arguments to
+a  simple  command  would  the programmable completion be in
+effect.
+
+     It would also be nice to give  the  user  finer-grained
+control over which commands are saved onto the history list.
+One proposal is for a variable,  tentatively  named  _\bH_\bI_\bS_\bT_\bI_\bG_\b-
+_\bN_\bO_\bR_\bE,  which  would  contain  a colon-separated list of com-
+mands.  Lines beginning with these commands, after the  res-
+trictions  of  $_\bH_\bI_\bS_\bT_\bC_\bO_\bN_\bT_\bR_\bO_\bL  have been applied, would not be
+placed onto the history list.   The  shell  pattern-matching
+capabilities  could  also  be  available when specifying the
+contents of $_\bH_\bI_\bS_\bT_\bI_\bG_\bN_\bO_\bR_\bE.
+
+     One thing that newer shells such as _\bw_\bk_\bs_\bh (also known as
+_\bd_\bt_\bk_\bs_\bh)  provide is a command to dynamically load code imple-
+menting additional builtin commands into  a  running  shell.
+This new builtin would take an object file or shared library
+implementing the "body" of the  builtin  (_\bx_\bx_\bx__\bb_\bu_\bi_\bl_\bt_\bi_\bn()  for
+those familiar with Bash internals) and a structure contain-
+ing the name of the new command, the function to  call  when
+the new builtin is invoked (presumably defined in the shared
+object specified as an argument), and the  documentation  to
+be  printed  by  the  _\bh_\be_\bl_\bp  command (possibly present in the
+shared object as well).  It  would  manage  the  details  of
+extending the internal table of builtins.
+
+     A few other builtins would also be desirable:  two  are
+the POSIX.2 _\bg_\be_\bt_\bc_\bo_\bn_\bf command, which prints the values of sys-
+tem configuration variables defined by POSIX.2, and a _\bd_\bi_\bs_\bo_\bw_\bn
+builtin,  which  causes  a  shell  running  with job control
+active to "forget about" one or more background jobs in  its
+internal  jobs  table.   Using  _\bg_\be_\bt_\bc_\bo_\bn_\bf, for example, a user
+could retrieve a value for $_\bP_\bA_\bT_\bH guaranteed to find  all  of
+the POSIX standard utilities, or find out how long filenames
+may be in the file system containing a specified directory.
+
+     There are no implementation timetables for any of these
+features,  nor are there concrete plans to include them.  If
+anyone has comments on these proposals, feel free to send me
+electronic mail.
+
+_\b6.  _\bR_\be_\bf_\bl_\be_\bc_\bt_\bi_\bo_\bn_\bs _\ba_\bn_\bd _\bL_\be_\bs_\bs_\bo_\bn_\bs _\bL_\be_\ba_\br_\bn_\be_\bd
+
+     The lesson that has been  repeated  most  often  during
+Bash  development  is  that  there  are  dark corners in the
+Bourne Shell, and people use all of them.  In  the  original
+description of the Bourne shell, quoting and the shell gram-
+mar are both poorly  specified  and  incomplete;  subsequent
+descriptions have not helped much.  The grammar presented in
+
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 16 -
+
+
+Bourne's paper describing the  shell  distributed  with  the
+Seventh  Edition  of  UNIX|\b-  is  so far off that it does not
+allow the command who|wc.  In fact, as Tom Duff states:
+
+     Nobody really knows what the Bourne shell's  gram-
+     mar  is.   Even  examination of the source code is
+     little help.|\b=
+
+The POSIX.2 standard includes  a  _\by_\ba_\bc_\bc  grammar  that  comes
+close  to  capturing  the  Bourne  shell's  behavior, but it
+disallows some constructs which sh accepts without complaint
+-  and there are scripts out there that use them.  It took a
+few versions and several bug reports before Bash implemented
+sh-compatible  quoting,  and there are still some "legal" sh
+constructs which Bash flags as syntax errors.   Complete  sh
+compatibility is a tough nut.
+
+     The shell is bigger  and  slower  than  I  would  like,
+though the current version is substantially faster than pre-
+viously.  The readline library  could  stand  a  substantial
+rewrite.   A  hand-written  parser  to  replace  the current
+_\by_\ba_\bc_\bc-generated one would probably result in a  speedup,  and
+would solve one glaring problem:  the shell could parse com-
+mands in "$(...)" constructs as  they  are  entered,  rather
+than reporting errors when the construct is expanded.
+
+     As always, there is some chaff to go  with  the  wheat.
+Areas  of  duplicated  functionality  need to be cleaned up.
+There are several cases where Bash treats  a  variable  spe-
+cially   to   enable  functionality  available  another  way
+($notify vs.  set -o notify and $nolinks vs. set  -o  physi-
+cal,  for  instance);  the special treatment of the variable
+name should probably be removed.  A few  more  things  could
+stand    removal;    the    $_\ba_\bl_\bl_\bo_\bw__\bn_\bu_\bl_\bl__\bg_\bl_\bo_\bb__\be_\bx_\bp_\ba_\bn_\bs_\bi_\bo_\bn   and
+$_\bg_\bl_\bo_\bb__\bd_\bo_\bt__\bf_\bi_\bl_\be_\bn_\ba_\bm_\be_\bs variables are of particularly  question-
+able  value.   The  $[...]  arithmetic  evaluation syntax is
+redundant now that the POSIX-mandated $((...)) construct has
+been implemented, and could be deleted.  It would be nice if
+the text output by the _\bh_\be_\bl_\bp builtin  were  external  to  the
+shell rather than compiled into it.  The behavior enabled by
+$_\bc_\bo_\bm_\bm_\ba_\bn_\bd__\bo_\br_\bi_\be_\bn_\bt_\be_\bd__\bh_\bi_\bs_\bt_\bo_\br_\by, which causes the shell to attempt
+to  save  all lines of a multi-line command in a single his-
+tory entry, should be made  the  default  and  the  variable
+removed.
+
+
+_________________________
+|\b-S. R. Bourne, "UNIX  Time-Sharing  System:   The  UNIX
+Shell",  _\bB_\be_\bl_\bl  _\bS_\by_\bs_\bt_\be_\bm  _\bT_\be_\bc_\bh_\bn_\bi_\bc_\ba_\bl  _\bJ_\bo_\bu_\br_\bn_\ba_\bl, 57(6), July-
+August, 1978, pp. 1971-1990.
+|\b=Tom Duff, "Rc - A Shell for Plan 9 and UNIX  systems",
+_\bP_\br_\bo_\bc. _\bo_\bf _\bt_\bh_\be _\bS_\bu_\bm_\bm_\be_\br _\b1_\b9_\b9_\b0 _\bE_\bU_\bU_\bG _\bC_\bo_\bn_\bf_\be_\br_\be_\bn_\bc_\be, London, July,
+1990, pp. 21-33.
+
+
+
+
+                       July 18, 1994
+
+
+
+
+
+                           - 17 -
+
+
+_\b7.  _\bA_\bv_\ba_\bi_\bl_\ba_\bb_\bi_\bl_\bi_\bt_\by
+
+     As with all other GNU software, Bash is  available  for
+anonymous  FTP  from _\bp_\br_\be_\bp._\ba_\bi._\bm_\bi_\bt._\be_\bd_\bu:/_\bp_\bu_\bb/_\bg_\bn_\bu and from other
+GNU software mirror sites.  The current version is in  _\bb_\ba_\bs_\bh-
+_\b1._\b1_\b4._\b1._\bt_\ba_\br._\bg_\bz  in  that  directory.   Use _\ba_\br_\bc_\bh_\bi_\be to find the
+nearest archive site.  The latest version is  always  avail-
+able  for FTP from _\bb_\ba_\bs_\bh._\bC_\bW_\bR_\bU._\bE_\bd_\bu:/_\bp_\bu_\bb/_\bd_\bi_\bs_\bt.  Bash documenta-
+tion is available for FTP from _\bb_\ba_\bs_\bh._\bC_\bW_\bR_\bU._\bE_\bd_\bu:/_\bp_\bu_\bb/_\bb_\ba_\bs_\bh.
+
+     The Free Software Foundation sells  tapes  and  CD-ROMs
+containing Bash; send electronic mail to gnu@prep.ai.mit.edu
+or call +1-617-876-3296 for more information.
+
+     Bash is  also  distributed  with  several  versions  of
+UNIX-compatible  systems.   It  is  included  as /bin/sh and
+/bin/bash on several Linux  distributions  (more  about  the
+difference  in  a  moment),  and  as contributed software in
+BSDI's BSD/386* and FreeBSD.
+
+     The Linux distribution deserves special mention.  There
+are two configurations included in the standard Bash distri-
+bution: a "normal" configuration, in which all of the  stan-
+dard  features  are included, and a "minimal" configuration,
+which omits job control, aliases, history and  command  line
+editing,  the  directory  stack and _\bp_\bu_\bs_\bh_\bd/_\bp_\bo_\bp_\bd/_\bd_\bi_\br_\bs, process
+substitution, prompt string special character decoding,  and
+the  _\bs_\be_\bl_\be_\bc_\bt  construct.  This minimal version is designed to
+be a drop-in replacement for the traditional  UNIX  /bin/sh,
+and is included as the Linux /bin/sh in several packagings.
+
+_\b8.  _\bC_\bo_\bn_\bc_\bl_\bu_\bs_\bi_\bo_\bn
+
+     Bash is a worthy successor to sh.  It  is  sufficiently
+portable to run on nearly every version of UNIX from 4.3 BSD
+to SVR4.2, and several UNIX workalikes.  It is robust enough
+to  replace  sh  on most of those systems, and provides more
+functionality.  It has several thousand regular  users,  and
+their  feedback has helped to make it as good as it is today
+- a testament to the benefits of free software.
+
+
+
+
+
+
+
+
+
+
+_________________________
+*BSD/386 is a trademark of  Berkeley  Software  Design,
+Inc.
+
+
+
+
+                       July 18, 1994
+
+
diff --git a/documentation/bash.1 b/documentation/bash.1
new file mode 100644 (file)
index 0000000..9a04b1a
--- /dev/null
@@ -0,0 +1,5371 @@
+.\"
+.\" MAN PAGE COMMENTS to
+.\"
+.\"    Chet Ramey
+.\"    Information Network Services
+.\"    Case Western Reserve University
+.\"    chet@ins.CWRU.Edu
+.\"
+.\"    Last Change: Fri May  5 10:44:39 EDT 1995
+.\"
+.\" bash_builtins, strip all but Built-Ins section
+.if \n(zZ=1 .ig zZ
+.TH BASH 1 "1995 May 5" GNU
+.\"
+.\" There's some problem with having a `@'
+.\" in a tagged paragraph with the BSD man macros.
+.\" It has to do with `@' appearing in the }1 macro.
+.\" This is a problem on 4.3 BSD and Ultrix, but Sun
+.\" appears to have fixed it.
+.\" If you're seeing the characters
+.\" `@u-3p' appearing before the lines reading
+.\" `possible-hostname-completions
+.\" and `complete-hostname' down in READLINE,
+.\" then uncomment this redefinition.
+.\"
+.de }1
+.ds ]X \&\\*(]B\\
+.nr )E 0
+.if !"\\$1"" .nr )I \\$1n
+.}f
+.ll \\n(LLu
+.in \\n()Ru+\\n(INu+\\n()Iu
+.ti \\n(INu
+.ie !\\n()Iu+\\n()Ru-\w\a\\*(]X\au-3p \{\\*(]X
+.br\}
+.el \\*(]X\h\a|\\n()Iu+\\n()Ru\a\c
+.}f
+..
+.\"
+.\" File Name macro.  This used to be `.PN', for Path Name,
+.\" but Sun doesn't seem to like that very much.
+.\"
+.de FN
+\fI\|\\$1\|\fP
+..
+.SH NAME
+bash \- GNU Bourne\-Again SHell
+.SH SYNOPSIS
+.B bash
+[options]
+[file]
+.SH COPYRIGHT
+.if n Bash is Copyright (C) 1989, 1991 by the Free Software Foundation, Inc.
+.if t Bash is Copyright \(co 1989, 1991 by the Free Software Foundation, Inc.
+.SH DESCRIPTION
+.B Bash
+is an \fBsh\fR\-compatible command language interpreter that
+executes commands read from the standard input or from a file.
+.B Bash
+also incorporates useful features from the \fIKorn\fP and \fIC\fP
+shells (\fBksh\fP and \fBcsh\fP).
+.PP
+.B Bash
+is ultimately intended to be a conformant implementation of the IEEE
+Posix Shell and Tools specification (IEEE Working Group 1003\.2).
+.SH OPTIONS
+In addition to the single\-character shell options documented in the
+description of the \fBset\fR builtin command, \fBbash\fR
+interprets the following flags when it is invoked:
+.PP
+.PD 0
+.TP 10
+.BI \-c "\| string\^"
+If the 
+.B \-c
+flag is present, then commands are read from
+.IR string .
+If there are arguments after the
+.IR string ,
+they are assigned to the positional parameters, starting with
+.BR $0 .
+.TP
+.B \-i
+If the
+.B \-i
+flag is present, the shell is
+.IR interactive .
+.TP
+.B \-s
+If the
+.B \-s
+flag is present, or if no arguments remain after option
+processing, then commands are read from the standard input.
+This option allows the positional parameters to be set
+when invoking an interactive shell.
+.TP
+.B \-
+A single
+.B \-
+signals the end of options and disables further option processing.
+Any arguments after the
+.B \-
+are treated as filenames and arguments.  An argument of
+.B \-\-
+is equivalent to an argument of \fB\-\fP.
+.PD
+.PP
+.B Bash
+also interprets a number of multi\-character options.  These options must
+appear on the command line before the single\-character options to be
+recognized.
+.PP
+.PD 0
+.TP 10
+.B \-norc
+Do not read and execute the personal initialization file
+.I ~/.bashrc
+if the shell is interactive.
+This option is on by default if the shell is invoked as
+.BR sh .
+.TP
+.B \-noprofile
+Do not read either the system\-wide startup file
+.FN /etc/profile
+or any of the personal initialization files
+.IR ~/.bash_profile ,
+.IR ~/.bash_login ,
+or
+.IR ~/.profile .
+By default,
+.B bash
+normally reads these files when it is invoked as a login shell (see
+.SM
+.B INVOCATION
+below).
+.TP
+\fB\-rcfile\fP \fIfile\fP
+Execute commands from
+.I file
+instead of the standard personal initialization file
+.IR ~/.bashrc ,
+if the shell is interactive (see
+.SM
+.B INVOCATION
+below).
+.TP
+.B \-version
+Show the version number of this instance of
+.B bash
+when starting.
+.TP
+.B \-quiet
+Do not be verbose when starting up (do not show the shell version or any
+other information).  This is the default.
+.TP
+.B \-login
+Make
+.B bash
+act as if it had been invoked as a login shell.
+.TP
+.B \-nobraceexpansion
+Do not perform curly brace expansion (see
+.B Brace Expansion
+below).
+.TP
+.B \-nolineediting
+Do not use the GNU
+.I readline
+library to read command lines if interactive.
+.TP
+.B \-posix
+Change the behavior of bash where the default operation differs
+from the Posix 1003.2 standard to match the standard
+.PD
+.SH ARGUMENTS
+If arguments remain after option processing, and neither the
+.B \-c
+nor the
+.B \-s
+option has been supplied, the first argument is assumed to
+be the name of a file containing shell commands.  If
+.B bash
+is invoked in this fashion, 
+.B $0
+is set to the name of the file, and the positional parameters
+are set to the remaining arguments.
+.B Bash
+reads and executes commands from this file, then exits.
+.B Bash's
+exit status is the exit status of the last command executed
+in the script.
+.SH DEFINITIONS
+.PD 0
+.TP
+.B blank 
+A space or tab.
+.TP
+.B word
+A sequence of characters considered as a single unit by the shell.
+Also known as a
+.BR token .
+.TP
+.B name
+A 
+.I word
+consisting only of alphanumeric characters and underscores, and
+beginning with an alphabetic character or an underscore.  Also
+referred to as an
+.BR identifier .
+.TP
+.B metacharacter
+A character that, when unquoted, separates words.  One of the following:
+.br
+.RS
+.PP
+.if t \fB|  &  ;  (  )  <  >  space  tab\fP
+.if n \fB|  & ; ( ) < > space tab\fP
+.RE
+.PP
+.TP
+.B control operator
+A \fItoken\fP that performs a control function.  It is one of the following
+symbols:
+.RS
+.PP
+.if t \fB\(bv\|\(bv  &  &&  ;  ;;  (  )  |  <newline>\fP
+.if n \fB|| & && ; ;; ( ) | <newline>\fP
+.RE
+.PD
+.SH "RESERVED WORDS"
+\fIReserved words\fP are words that have a special meaning to the shell.
+The following words are recognized as reserved when unquoted and either
+the first word of a simple command (see
+.SM
+.B SHELL GRAMMAR
+below) or the third word of a 
+.B case 
+or
+.B for
+command:
+.if t .RS
+.PP
+.B
+.if n ! case  do done elif else esac fi for function if in select then until while { }
+.if t !    case    do    done    elif    else    esac    fi    for    function    if    in    select    then    until    while    {    }
+.if t .RE
+.RE
+.SH "SHELL GRAMMAR"
+.SS Simple Commands
+.PP
+A \fIsimple command\fP is a sequence of optional variable assignments
+followed by \fIblank\fP\-separated words and redirections, and
+terminated by a \fIcontrol operator\fP.  The first word
+specifies the command to be executed.  The remaining words are
+passed as arguments to the invoked command.
+.PP
+The return value of a \fIsimple command\fP is its exit status, or
+128+\fIn\^\fP if the command is terminated by signal
+.IR n .
+.SS Pipelines
+.PP
+A \fIpipeline\fP is a sequence of one or more commands separated by
+the character
+.BR | .
+The format for a pipeline is:
+.RS
+.PP
+[ ! ] \fIcommand\fP [ \fB|\fP \fIcommand2\fP ... ]
+.RE
+.PP
+The standard output of
+.I command
+is connected to the standard input of
+.IR command2 .
+This connection is performed before any redirections specified by the
+command (see
+.SM
+.B REDIRECTION
+below).
+.PP
+If the reserved word
+.B !
+precedes a pipeline, the exit status of that
+pipeline is the logical NOT of the exit status of the last command.
+Otherwise, the status of the pipeline is the exit status of the last
+command.  The shell waits for all commands in the pipeline to
+terminate before returning a value.
+.PP
+Each command in a pipeline is executed as a separate process (i.e., in a
+subshell).
+.SS Lists
+.PP
+A \fIlist\fP is a sequence of one or more pipelines separated by one
+of the operators
+.BR ; ,
+.BR & ,
+.BR && ,
+or
+.BR \(bv\|\(bv ,
+and terminated by one of
+.BR ; ,
+.BR & ,
+or
+.BR <newline> .
+.PP
+Of these list operators,
+.B &&
+and
+.B \(bv\|\(bv
+have equal precedence, followed by
+.B ;
+and
+.BR &,
+which have equal precedence.
+.PP
+If a command is terminated by the control operator
+.BR & ,
+the shell executes the command in the \fIbackground\fP
+in a subshell.  The shell does not wait for the command to
+finish, and the return status is 0.  Commands separated by a
+.B ;
+are executed sequentially; the shell waits for each
+command to terminate in turn.  The return status is the
+exit status of the last command executed.
+.PP
+The control operators
+.B &&
+and
+.B \(bv\|\(bv
+denote AND lists and OR lists, respectively.
+An AND list has the form
+.RS
+.PP
+\fIcommand\fP \fB&&\fP \fIcommand2\fP
+.RE
+.PP
+.I command2
+is executed if, and only if,
+.I command
+returns an exit status of zero.
+.PP
+An OR list has the form
+.RS
+.PP
+\fIcommand\fP \fB\(bv\|\(bv\fP \fIcommand2\fP
+.PP
+.RE
+.PP
+.I command2
+is executed if and only if
+.I command
+returns a non\-zero exit status.  The return status of
+AND and OR lists is the exit status of the last command
+executed in the list.
+.SS Compound Commands
+.PP
+A \fIcompound command\fP is one of the following:
+.TP
+(\fIlist\fP)
+\fIlist\fP is executed in a subshell.  Variable assignments and builtin
+commands that affect the shell's environment do not remain in effect
+after the command completes.  The return status is the exit status of
+\fIlist\fP.
+.TP
+{ \fIlist\fP; }
+\fIlist\fP is simply executed in the current shell environment.  This is
+known as a \fIgroup command\fP.  The return status is the exit status of
+\fIlist\fP.
+.TP
+\fBfor\fP \fIname\fP [ \fBin\fP \fIword\fP; ] \fBdo\fP \fIlist\fP ; \fBdone\fP
+The list of words following \fBin\fP is expanded, generating a list
+of items.  The variable \fIname\fP is set to each element of this list
+in turn, and \fIlist\fP is executed each time.  If the \fBin\fP
+\fIword\fP is omitted, the \fBfor\fP command executes \fIlist\fP 
+once for each positional parameter that is set (see
+.SM
+.B PARAMETERS
+below).
+.TP
+\fBselect\fP \fIname\fP [ \fBin\fP \fIword\fP; ] \fBdo\fP \fIlist\fP ; \fBdone\fP
+The list of words following \fBin\fP is expanded, generating a list
+of items.  The set of expanded words is printed on the standard
+error, each preceded by a number.  If the \fBin\fP
+\fIword\fP is omitted, the positional parameters are printed (see
+.SM
+.B PARAMETERS
+below).  The
+.B PS3
+prompt is then displayed and a line read from the standard input.
+If the line consists of the number corresponding to one of
+the displayed words, then the value of
+.I name
+is set to that word.  If the line is empty, the words and prompt
+are displayed again.  If EOF is read, the command completes.  Any
+other value read causes
+.I name
+to be set to null.  The line read is saved in the variable
+.BR REPLY .
+The
+.I list
+is executed after each selection until a
+.B break
+or
+.B return
+command is executed.
+The exit status of
+.B select
+is the exit status of the last command executed in
+.IR list ,
+or zero if no commands were executed.
+.TP
+\fBcase\fP \fIword\fP \fBin\fP [ \fIpattern\fP [ \fB|\fP \fIpattern\fP ] \
+... ) \fIlist\fP ;; ] ... \fBesac\fP
+A \fBcase\fP command first expands \fIword\fP, and tries to match
+it against each \fIpattern\fP in turn, using the same matching rules
+as for pathname expansion (see
+.B Pathname Expansion
+below).  When a match is found, the
+corresponding \fIlist\fP is executed.  After the first match, no
+subsequent matches are attempted.  The exit status is zero if no
+patterns are matches.  Otherwise, it is the exit status of the
+last command executed in \fIlist\fP.
+.TP
+\fBif\fP \fIlist\fP \fBthen\fP \fIlist\fP \
+[ \fBelif\fP \fIlist\fP \fBthen\fP \fIlist\fP ] ... \
+[ \fBelse\fP \fIlist\fP ] \fBfi\fP
+The
+.B if 
+.I list
+is executed.  If its exit status is zero, the
+\fBthen\fP \fIlist\fP is executed.  Otherwise, each \fBelif\fP
+\fIlist\fP is executed in turn, and if its exit status is zero,
+the corresponding \fBthen\fP \fIlist\fP is executed and the
+command completes.  Otherwise, the \fBelse\fP \fIlist\fP is
+executed, if present.  The exit status is the exit status of the
+last command executed, or zero if no condition tested true.
+.TP
+.PD 0
+\fBwhile\fP \fIlist\fP \fBdo\fP \fIlist\fP \fBdone\fP
+.TP
+\fBuntil\fP \fIlist\fP \fBdo\fP \fIlist\fP \fBdone\fP
+.PD
+The \fBwhile\fP command continuously executes the \fBdo\fP
+\fIlist\fP as long as the last command in \fIlist\fP returns
+an exit status of zero.  The \fBuntil\fP command is identical
+to the \fBwhile\fP command, except that the test is negated;
+the
+.B do
+.I list
+is executed as long as the last command in
+.I list
+returns a non\-zero exit status.
+The exit status of the \fBwhile\fP and \fBuntil\fP commands
+is the exit status
+of the last \fBdo\fP \fIlist\fP command executed, or zero if
+none was executed.
+.TP
+[ \fBfunction\fP ] \fIname\fP () { \fIlist\fP; }
+This defines a function named \fIname\fP.  The \fIbody\fP of the
+function is the
+.I list
+of commands between { and }.  This list
+is executed whenever \fIname\fP is specified as the
+name of a simple command.  The exit status of a function is
+the exit status of the last command executed in the body.  (See
+.SM
+.B FUNCTIONS
+below.)
+.SH COMMENTS
+In a non\-interactive shell, or an interactive shell in which the
+.B -o interactive\-comments
+option to the \fBset\fP builtin is enabled, a word beginning with
+.B #
+causes that word and all remaining characters on that line to
+be ignored.  An interactive shell without the
+.B -o interactive\-comments
+option enabled does not allow comments.
+.SH QUOTING
+\fIQuoting\fP is used to remove the special meaning of certain
+characters or words to the shell.  Quoting can be used to 
+disable special treatment for special characters, to prevent
+reserved words from being recognized as such, and to prevent
+parameter expansion.
+.PP
+Each of the \fImetacharacters\fP listed above under
+.SM
+.B DEFINITIONS
+has special meaning to the shell and must be quoted if they are to
+represent themselves.  There are three quoting mechanisms: the
+.IR "escape character" ,
+single quotes, and double quotes.
+.PP
+A non-quoted backslash (\fB\e\fP) is the
+.IR "escape character" .
+It preserves the literal value of the next character that follows,
+with the exception of <newline>.  If a \fB\e\fP<newline> pair
+appears, and the backslash is not quoted, the \fB\e\fP<newline>
+is treated as a line continuation (that is, it is effectively ignored).
+.PP
+Enclosing characters in single quotes preserves the literal value
+of each character within the quotes.  A single quote may not occur
+between single quotes, even when preceded by a backslash.
+.PP
+Enclosing characters in double quotes preserves the literal value
+of all characters within the quotes, with the exception of
+.BR $ ,
+.BR ` ,
+and
+.BR \e .
+The characters
+.B $
+and
+.B `
+retain their special meaning within double quotes.  The backslash
+retains its special meaning only when followed by one of the following
+characters:
+.BR $ ,
+.BR ` ,
+\^\fB"\fP\^,
+.BR \e ,
+or
+.BR <newline> .
+A double quote may be quoted within double quotes by preceding it with
+a backslash.
+.PP
+The special parameters
+.B *
+and
+.B @
+have special meaning when in double
+quotes (see
+.SM
+.B PARAMETERS
+below).
+.SH PARAMETERS
+A
+.I parameter
+is an entity that stores values, somewhat like a
+variable in a conventional programming language.  It can be a
+.IR name ,
+a number, or one of the special characters listed below under
+.BR "Special Parameters" .
+For the shell's purposes, a
+.I variable
+is a parameter denoted by a
+.IR name .
+.PP
+A parameter is set if it has been assigned a value.  The null string is
+a valid value.  Once a variable is set, it may be unset only by using
+the
+.B unset
+builtin command (see
+.SM
+.B SHELL BUILTIN COMMANDS
+below).
+.PP
+A
+.I variable
+may be assigned to by a statement of the form
+.RS
+.PP
+\fIname\fP=[\fIvalue\fP]
+.RE
+.PP
+If
+.I value
+is not given, the variable is assigned the null string.  All
+.I values
+undergo tilde expansion, parameter and variable expansion, command
+substitution, arithmetic expansion, and quote removal.  If
+the variable has its
+.B \-i
+attribute set (see
+.B declare
+below in
+.SM
+.BR "SHELL BUILTIN COMMANDS" )
+then
+.I value
+is subject to arithmetic expansion even if the $[...] syntax does
+not appear.  Word splitting is not performed, with the exception
+of \fB"$@"\fP as explained below under
+.BR "Special Parameters" .
+Pathname expansion is not performed.
+.SS Positional Parameters
+.PP
+A
+.I positional parameter
+is a parameter denoted by one or more
+digits, other than the single digit 0.  Positional parameters are
+assigned from the shell's arguments when it is invoked,
+and may be reassigned using the
+.B set
+builtin command.  Positional parameters may not be assigned to
+with assignment statements.  The positional parameters are
+temporarily replaced when a shell function is executed (see
+.SM
+.B FUNCTIONS
+below).
+.PP
+When a positional parameter consisting of more than a single
+digit is expanded, it must be enclosed in braces (see
+.SM
+.B EXPANSION
+below).
+.SS Special Parameters
+.PP
+The shell treats several parameters specially.  These parameters may
+only be referenced; assignment to them is not allowed.
+.PD 0
+.TP
+.B *
+Expands to the positional parameters, starting from one.  When the
+expansion occurs within double quotes, it expands to a single word
+with the value of each parameter separated by the first character
+of the 
+.SM
+.B IFS
+special variable.  That is, ``\fB$*\fP'' is equivalent
+to ``\fB$1\fP\fIc\fP\fB$2\fP\fIc\fP\fB...\fP'', where
+.I c
+is the first character of the value of the
+.SM
+.B IFS
+variable.  If
+.SM
+.B IFS
+is null or unset, the parameters are separated by spaces.
+.TP
+.B @
+Expands to the positional parameters, starting from one.  When the
+expansion occurs within double quotes, each parameter expands as a
+separate word.  That is, ``
+.BR $@ ''
+is equivalent to
+``\fB$1\fP'' ``\fB$2\fP'' ...
+When there are no positional parameters, ``\fB$@\fP'' and 
+.B $@
+expand to nothing (i.e., they are removed).
+.TP
+.B #
+Expands to the number of positional parameters in decimal.
+.TP
+.B ?
+Expands to the status of the most recently executed foreground
+pipeline.
+.TP
+.B \-
+Expands to the current option flags as specified upon invocation, 
+by the
+.B set
+builtin command, or those set by the shell itself
+(such as the
+.B \-i
+flag).
+.TP
+.B $
+Expands to the process ID of the shell.  In a () subshell, it
+expands to the process ID of the current shell, not the
+subshell.
+.TP
+.B !
+Expands to the process ID of the most recently executed background
+(asynchronous) command.
+.TP
+.B 0
+Expands to the name of the shell or shell script.  This is set at
+shell initialization.  If
+.B bash
+is invoked with a file of commands,
+.B $0
+is set to the name of that file.  If
+.B bash
+is started with the
+.B \-c
+option, then
+.B $0
+is set to the first argument after the string to be
+executed, if one is present.  Otherwise, it is set
+to the pathname used to invoke
+.BR bash ,
+as given by argument zero.
+.TP
+.B _
+Expands to the last argument to the previous command, after expansion.
+Also set to the full pathname of each command executed and placed in
+the environment exported to that command.
+.PD
+.SS Shell Variables
+.PP
+The following variables are set by the shell:
+.PP
+.PD 0
+.TP
+.B PPID
+The process ID of the shell's parent.
+.TP
+.B PWD
+The current working directory as set by the
+.B cd
+command.
+.TP
+.B OLDPWD
+The previous working directory as set by the
+.B cd
+command.
+.TP
+.B REPLY
+Set to the line of input read by the
+.B read
+builtin command when no arguments are supplied.
+.TP
+.B UID
+Expands to the user ID of the current user, initialized at shell startup.
+.TP
+.B EUID
+Expands to the effective user ID of the current user, initialized at
+shell startup.
+.TP
+.B BASH
+Expands to the full pathname used to invoke this instance of
+.BR bash .
+.TP
+.B BASH_VERSION
+Expands to the version number of this instance of
+.BR bash .
+.TP
+.B SHLVL
+Incremented by one each time an instance of
+.B bash
+is started.
+.TP
+.B RANDOM
+Each time this parameter is referenced, a random integer is
+generated.  The sequence of random numbers may be initialized by assigning
+a value to
+.SM
+.BR RANDOM .
+If
+.SM
+.B RANDOM
+is unset, it loses its special properties, even if it is
+subsequently reset.
+.TP
+.B SECONDS
+Each time this parameter is
+referenced, the number of seconds since shell invocation is returned.  If a
+value is assigned to 
+.SM
+.BR SECONDS ,
+the value returned upon subsequent
+references is
+the number of seconds since the assignment plus the value assigned.
+If
+.SM
+.B SECONDS
+is unset, it loses its special properties, even if it is
+subsequently reset.
+.TP
+.B LINENO
+Each time this parameter is referenced, the shell substitutes
+a decimal number representing the current sequential line number
+(starting with 1) within a script or function.  When not in a
+script or function, the value substituted is not guaranteed to
+be meaningful.  When in a function, the value is not
+the number of the source line that the command appears
+on (that information has been lost by the time the function is
+executed), but is an approximation of the number of
+.I simple commands
+executed in the current function.
+If
+.SM
+.B LINENO
+is unset, it loses its special properties, even if it is
+subsequently reset.
+.TP
+.B HISTCMD
+The history number, or index in the history list, of the current
+command.  If
+.SM
+.B HISTCMD
+is unset, it loses its special properties, even if it is
+subsequently reset.
+.TP
+.B OPTARG
+The value of the last option argument processed by the
+.B getopts
+builtin command (see
+.SM
+.B SHELL BUILTIN COMMANDS
+below).
+.TP
+.B OPTIND
+The index of the next argument to be processed by the
+.B getopts
+builtin command (see
+.SM
+.B SHELL BUILTIN COMMANDS
+below).
+.TP
+.B HOSTTYPE
+Automatically set to a string that uniquely
+describes the type of machine on which
+.B bash
+is executing.  The default is system-dependent.
+.TP
+.B OSTYPE
+Automatically set to a string that
+describes the operating system on which
+.B bash
+is executing.  The default is system-dependent.
+.PD
+.PP
+The following variables are used by the shell.  In some cases,
+.B bash
+assigns a default value to a variable; these cases are noted
+below.
+.PP
+.PD 0
+.TP
+.B IFS
+The
+.I Internal Field Separator
+that is used
+for word splitting after expansion and to
+split lines into words with the
+.B read
+builtin command.  The default value is
+``<space><tab><newline>''.
+.TP
+.B PATH
+The search path for commands.  It
+is a colon-separated list of directories in which
+the shell looks for commands (see
+.SM
+.B COMMAND EXECUTION
+below).  The default path is system\-dependent,
+and is set by the administrator who installs
+.BR bash .
+A common value is ``/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:.''.
+.TP
+.B HOME
+The home directory of the current user; the default argument for the
+\fBcd\fP builtin command.
+.TP
+.B CDPATH
+The search path for the
+.B cd
+command.  This is a colon-separated
+list of directories in which the shell looks for destination directories
+specified by the
+.B cd
+command.  A sample value is
+``.:~:/usr''.
+.TP
+.B ENV
+If this parameter is set when \fBbash\fP is executing a shell script,
+its value is interpreted as a filename containing commands to
+initialize the shell, as in
+.IR .bashrc .
+The value of
+.SM
+.B ENV
+is subjected to parameter expansion, command substitution, and arithmetic
+expansion before being interpreted as a pathname.
+.SM
+.B PATH
+is not used to search for the resultant pathname.
+.TP
+.B MAIL
+If this parameter is set to a filename and the
+.SM
+.B MAILPATH
+variable is not set,
+.B bash
+informs the user of the arrival of mail in the specified file.
+.TP
+.B MAILCHECK
+Specifies how
+often (in seconds)
+.B bash
+checks for mail.  The default is 60 seconds.  When it is time to check
+for mail, the shell does so before prompting.
+If this variable is unset, the shell disables mail checking.
+.TP
+.B MAILPATH
+A colon-separated list of pathnames to be checked for mail. 
+The message to be printed may be specified by separating the pathname from
+the message with a `?'.  $_ stands for the name of the current mailfile. 
+Example:
+.RS
+.PP
+\fBMAILPATH\fP='/usr/spool/mail/bfox?"You have mail":~/shell-mail?"$_ has mail!"'
+.PP
+.B Bash
+supplies a default value for this variable, but the location of the user
+mail files that it uses is system dependent (e.g., /usr/spool/mail/\fB$USER\fP).
+.RE
+.TP
+.B MAIL_WARNING
+If set, and a file that \fBbash\fP is checking for mail has been
+accessed since the last time it was checked, the message ``The mail in
+\fImailfile\fP has been read'' is printed.
+.TP
+.B PS1
+The value of this parameter is expanded (see
+.SM
+.B PROMPTING
+below) and used as the primary prompt string.  The default value is
+``\fBbash\e$ \fP''.
+.TP
+.B PS2
+The value of this parameter is expanded
+and used as the secondary prompt string.  The default is
+``\fB> \fP''.
+.TP
+.B PS3
+The value of this parameter is used as the prompt for the
+.I select
+command (see
+.SM
+.B SHELL GRAMMAR
+above).
+.TP
+.B PS4
+The value of this parameter is expanded
+and the value is printed before each command
+.B bash
+displays during an execution trace.  The first character of
+.SM
+.B PS4
+is replicated multiple times, as necessary, to indicate multiple
+levels of indirection.  The default is ``\fB+ \fP''.
+.TP
+.B HISTSIZE
+The number of commands to remember in the command history (see
+.SM
+.B HISTORY
+below).  The default value is 500.
+.TP
+.B HISTFILE
+The name of the file in which command history is saved.  (See
+.SM
+.B HISTORY
+below.)  The default value is \fI~/.bash_history\fP.  If unset, the
+command history is not saved when an interactive shell exits.
+.TP
+.B HISTFILESIZE
+The maximum number of lines contained in the history file.  When this
+variable is assigned a value, the history file is truncated, if
+necessary, to contain no more than that number of lines.  The default
+value is 500.
+.TP
+.B OPTERR
+If set to the value 1,
+.B bash
+displays error messages generated by the
+.B getopts
+builtin command (see
+.SM
+.B SHELL BUILTIN COMMANDS
+below).
+.SM
+.B OPTERR
+is initialized to 1 each time the shell is invoked or a shell
+script is executed.
+.TP
+.B PROMPT_COMMAND
+If set, the value is executed as a command prior to issuing each primary
+prompt.
+.TP
+.B IGNOREEOF
+Controls the
+action of the shell on receipt of an
+.SM
+.B EOF
+character as the sole input.  If set, the value is the number of
+consecutive
+.SM
+.B EOF
+characters typed as the first characters on an input line before
+.B bash
+exits.  If the variable exists but does not have a numeric value, or
+has no value, the default value is 10.  If it does not exist,
+.SM
+.B EOF
+signifies the end of input to the shell.  This is only in effect for
+interactive shells.
+.TP
+.B 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.
+.B Bash
+terminates after waiting for that number of seconds if input does
+not arrive.
+.TP
+.B FCEDIT
+The default editor for the
+.B fc
+builtin command.
+.TP
+.B FIGNORE
+A colon-separated list of suffixes to ignore when performing
+filename completion (see
+.SM
+.B READLINE
+below).  A filename whose suffix matches one of the entries in 
+.SM
+.B FIGNORE
+is excluded from the list of matched filenames.  A sample
+value is ``.o:~''.
+.TP
+.B INPUTRC
+The filename for the readline startup file, overriding the default
+of
+.FN ~/.inputrc
+(see
+.SM
+.B READLINE
+below).
+.TP
+.B notify
+If set,
+.B bash
+reports terminated background jobs immediately, rather than waiting
+until before printing the next primary prompt (see also the
+.B \-b
+option to the
+.B set
+builtin command).
+.PD 0
+.TP
+.B history_control
+.TP
+.B HISTCONTROL
+.PD
+If set to a value of
+.IR ignorespace ,
+lines which begin with a
+.B space
+character are not entered on the history list.  If set to
+a value of
+.IR ignoredups ,
+lines matching the last history line are not entered.
+A value of
+.I ignoreboth
+combines the two options.
+If unset, or if set to any other value than those above,
+all lines read
+by the parser are saved on the history list.
+.TP
+.B command_oriented_history
+If set,
+.B bash
+attempts to save all lines of a multiple\-line
+command in the same history entry.  This allows
+easy re\-editing of multi\-line commands.
+.TP
+.B glob_dot_filenames
+If set,
+.B bash
+includes filenames beginning with a `.' in the results of pathname
+expansion.
+.TP
+.B allow_null_glob_expansion
+If set,
+.B bash
+allows pathname patterns which match no
+files (see
+.B Pathname Expansion
+below)
+to expand to a null string, rather than themselves.
+.TP
+.B histchars
+The two or three characters which control history expansion
+and tokenization (see
+.SM
+.B HISTORY EXPANSION
+below).  The first character is the
+.IR "history expansion character" ,
+that is, the character which signals the start of a history
+expansion, normally `\fB!\fP'.
+The second character is the
+.IR "quick substitution"
+character, which is used as shorthand for re-running the previous
+command entered, substituting one string for another in the command.
+The default is `\fB^\fP'.
+The optional third character is the character
+which signifies that the remainder of the line is a comment, when found
+as the first character of a word, normally `\fB#\fP'.  The history
+comment character causes history substitution to be skipped for the
+remaining words on the line.  It does not necessarily cause the shell
+parser to treat the rest of the line as a comment.
+.TP
+.B nolinks
+If set, the shell does not follow symbolic links when executing
+commands that change the current working directory.  It uses the
+physical directory structure instead.  By default,
+.B bash
+follows the logical chain of directories when performing commands
+which change the current directory, such as 
+.BR cd .
+See also the description of the \fB\-P\fP option to the \fBset\fP
+builtin (
+.SM
+.B SHELL BUILTIN COMMANDS
+below).
+.PD 0
+.TP
+.B hostname_completion_file
+.TP
+.B HOSTFILE
+.PD
+Contains the name of a file in the same format as
+.FN /etc/hosts
+that should be read when the shell needs to complete a
+hostname.  The file may be changed interactively; the next
+time hostname completion is attempted
+.B bash
+adds the contents of the new file to the already existing database.
+.TP
+.B noclobber
+If set,
+.B bash
+does not overwrite an existing file with the
+.BR > ,
+.BR >& ,
+and
+.B <>
+redirection operators.  This variable may be overridden when 
+creating output files by using the redirection operator
+.B >|
+instead of
+.B >
+(see also the \fB\-C\fP option to the
+.B set
+builtin command).
+.TP
+.B auto_resume
+This variable controls how the shell interacts with the user and
+job control.  If this variable is set, single word simple
+commands without redirections are treated as candidates for resumption
+of an existing stopped job.  There is no ambiguity allowed; if there is
+more than one job beginning with the string typed, the job most recently
+accessed is selected.  The
+.I name
+of a stopped job, in this context, is the command line used to
+start it.
+If set to the value
+.IR exact ,
+the string supplied must match the name of a stopped job exactly;
+if set to
+.IR substring ,
+the string supplied needs to match a substring of the name of a
+stopped job.  The
+.I substring
+value provides functionality analogous to the
+.B %?
+job id (see
+.SM
+.B JOB CONTROL
+below).  If set to any other value, the supplied string must
+be a prefix of a stopped job's name; this provides functionality
+analogous to the
+.B %
+job id.
+.TP
+.B no_exit_on_failed_exec
+If this variable exists, a non-interactive shell will not exit if
+it cannot execute the file specified in the
+.B exec
+builtin command.  An interactive shell does not exit if
+.B exec
+fails.
+.TP
+.B cdable_vars
+If this is set, an argument to the
+.B cd
+builtin command that
+is not a directory is assumed to be the name of a variable whose
+value is the directory to change to.
+.PD
+.SH EXPANSION
+Expansion is performed on the command line after it has been split into
+words.  There are seven kinds of expansion performed:
+.IR "brace expansion" ,
+.IR "tilde expansion" ,
+.IR "parameter and variable expansion" ,
+.IR "command substitution" ,
+.IR "arithmetic expansion" ,
+.IR "word splitting" ,
+and
+.IR "pathname expansion" .
+.PP
+The order of expansions is: brace expansion, tilde expansion,
+parameter, variable, command, and arithmetic substitution (done
+in a left\-to\-right fashion), word splitting, and pathname
+expansion.
+.PP
+On systems that can support it, there is an additional expansion
+available: \fIprocess substitution\fP.
+.PP
+Only brace expansion, word splitting, and pathname expansion
+can change the number of words of the expansion; other expansions
+expand a single word to a single word.
+The single exception to this is the expansion of
+``\fB$@\fP'' as explained above (see
+.SM
+.BR PARAMETERS ).
+.SS Brace Expansion
+.PP
+.I "Brace expansion"
+is a mechanism by which arbitrary strings
+may be generated.  This mechanism is similar to
+\fIpathname expansion\fP, but the filenames generated
+need not exist.  Patterns to be brace expanded take
+the form of an optional
+.IR preamble ,
+followed by a series of comma-separated strings
+between a pair of braces, followed by an optional
+.IR postamble .
+The preamble is prepended to each string contained
+within the braces, and the postamble is then appended
+to each resulting string, expanding left to right.
+.PP
+Brace expansions may be nested.  The results of each expanded
+string are not sorted; left to right order is preserved.
+For example, a\fB{\fPd,c,b\fB}\fPe expands into `ade ace abe'.
+.PP
+Brace expansion is performed before any other expansions,
+and any characters special to other expansions are preserved
+in the result.  It is strictly textual.
+.B Bash
+does not apply any syntactic interpretation to the context of the
+expansion or the text between the braces.
+.PP
+A correctly-formed brace expansion must contain unquoted opening
+and closing braces, and at least one unquoted comma.
+Any incorrectly formed brace expansion is left unchanged.
+.PP
+This construct is typically used as shorthand when the common
+prefix of the strings to be generated is longer than in the
+above example:
+.RS
+.PP
+mkdir /usr/local/src/bash/{old,new,dist,bugs}
+.RE
+or
+.RS
+chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
+.RE
+.PP
+Brace expansion introduces a slight incompatibility with
+traditional versions of
+.BR sh ,
+the Bourne shell.
+.B sh
+does not treat opening or closing braces specially when they
+appear as part of a word, and preserves them in the output.
+.B Bash
+removes braces from words as a consequence of brace
+expansion.  For example, a word entered to
+.B sh
+as \fIfile{1,2}\fP
+appears identically in the output.  The same word is
+output as
+.I file1 file2
+after expansion by
+.BR bash .
+If strict compatibility with
+.B sh
+is desired, start
+.B bash
+with the
+.B \-nobraceexpansion
+flag (see
+.SM
+.B OPTIONS
+above)
+or disable brace expansion with the
+.B +o braceexpand
+option to the
+.B set
+command (see
+.SM
+.B SHELL BUILTIN COMMANDS
+below).
+.SS Tilde Expansion
+.PP
+If a word begins with a tilde character (`\fB~\fP'), all of the characters
+preceding the first slash (or all characters, if there is no slash)
+are treated as a possible \fIlogin name\fP. If this \fIlogin name\fP
+is the null string, the tilde is replaced with the value of the
+parameter
+.SM
+.BR HOME .
+If
+.SM
+.B HOME
+is unset, the home directory of
+the user executing the shell is substituted instead.
+.PP
+If a `+' follows the tilde, the value of
+.SM
+.B PWD
+replaces the tilde and `+'.  If
+a `\-' follows, the value of
+.SM
+.B OLDPWD
+is substituted.
+If the value following the tilde is a valid \fIlogin name\fP,
+the tilde and \fIlogin name\fP are replaced with the home directory
+associated with that name.  If the name is invalid, or the tilde
+expansion fails, the word is unchanged.
+.PP
+Each variable assignment is checked for unquoted
+instances of tildes following a
+.B :
+or
+.BR = .
+In these cases, tilde substitution is also performed.  Consequently, one
+may use pathnames with tildes in assignments to
+.SM
+.BR PATH ,
+.SM
+.BR MAILPATH ,
+and
+.SM
+.BR CDPATH ,
+and the shell assigns the expanded value.
+.SS Parameter Expansion
+.PP
+The `\fB$\fP' character introduces parameter expansion,
+command substitution, or arithmetic expansion.  The parameter name
+or symbol to be expanded may be enclosed in braces, which
+are optional but serve to protect the variable to be expanded from
+characters immediately following it which could be
+interpreted as part of the name.
+.PP
+.PD 0
+.TP
+${\fIparameter\fP}
+The value of \fIparameter\fP is substituted.  The braces are required
+when
+.I parameter
+is a positional parameter with more than one digit,
+or when
+.I parameter
+is followed by a character which is not to be
+interpreted as part of its name.
+.PD
+.PP
+In each of the cases below, \fIword\fP is subject to tilde expansion,
+parameter expansion, command substitution, and arithmetic expansion.
+\fBBash\fP tests for a parameter that is unset or null; omitting the
+colon results in a test only for a parameter that is unset.
+.PP
+.PD 0
+.TP
+${\fIparameter\fP\fB:\-\fP\fIword\fP}
+\fBUse Default Values\fP.  If
+.I parameter
+is unset or null, the expansion of
+.I word
+is substituted.  Otherwise, the value of
+.I parameter
+is substituted.
+.TP
+${\fIparameter\fP\fB:=\fP\fIword\fP}
+\fBAssign Default Values\fP.
+If
+.I parameter
+is unset or null, the expansion of
+.I word
+is assigned to
+.IR parameter .
+The value of
+.I parameter
+is then substituted.  Positional parameters and special parameters may
+not be assigned to in this way.
+.TP
+${\fIparameter\fP\fB:?\fP\fIword\fP}
+\fBDisplay Error if Null or Unset\fP.
+If
+.I parameter
+is null or unset, the expansion of \fIword\fP (or a message to that effect
+if
+.I word
+is not present) is written to the standard error and the shell, if it
+is not interactive, exits.  Otherwise, the value of \fIparameter\fP is
+substituted.
+.TP
+${\fIparameter\fP\fB:+\fP\fIword\fP}
+\fBUse Alternate Value\fP.
+If
+.I parameter
+is null or unset, nothing is substituted, otherwise the expansion of
+.I word
+is substituted.
+.TP
+${\fB#\fP\fIparameter\fP}
+The length in characters of the value of \fIparameter\fP is substituted.
+If \fIparameter\fP is
+.B *
+or 
+.BR @ ,
+the length substituted is the length of
+.B *
+expanded within double quotes.
+.TP
+.PD 0
+${\fIparameter\fP\fB#\fP\fIword\fP}
+.TP
+${\fIparameter\fP\fB##\fP\fIword\fP}
+.PD
+The 
+.I word
+is expanded to produce a pattern just as in pathname
+expansion.  If the pattern matches the beginning of
+the value of
+.IR parameter ,
+then the expansion is the value of
+.I parameter
+with the shortest matching pattern deleted (the ``\fB#\fP''
+case) or the longest
+matching pattern deleted (the ``\fB##\fP'' case).
+.TP
+.PD 0
+${\fIparameter\fP\fB%\fP\fIword\fP}
+.TP
+${\fIparameter\fP\fB%%\fP\fIword\fP}
+.PD
+The \fIword\fP is expanded to produce a pattern just as in
+pathname expansion.  If the pattern matches a
+trailing portion of the value of
+.IR parameter ,
+then the expansion is the value of
+.I parameter
+with the shortest matching pattern deleted
+(the ``\fB%\fP'' case) or the longest
+matching pattern deleted (the ``\fB%%\fP'' case).
+.SS Command Substitution
+.PP
+\fICommand substitution\fP allows the output of a command to replace 
+the command name.  There are two forms:
+.PP
+.RS
+.PP
+\fB$(\fP\fIcommand\fP\|\fB)\fP
+.RE
+or
+.RS
+\fB`\fP\fIcommand\fP\fB`\fP
+.RE
+.PP
+. B Bash
+performs the expansion by executing \fIcommand\fP and
+replacing the command substitution with the standard output of the
+command, with any trailing newlines deleted.
+.PP
+When the old\-style backquote form of substitution is used,
+backslash retains its literal meaning except when followed by
+.BR $ ,
+.BR ` ,
+or
+.BR \e .
+When using the $(\^\fIcommand\fP\|) form, all characters between the
+parentheses make up the command; none are treated specially.
+.PP
+Command substitutions may be nested.  To nest when using the old form,
+escape the inner backquotes with backslashes.
+.PP
+If the substitution appears within double quotes, word splitting and
+pathname expansion are not performed on the results.
+.SS Arithmetic Expansion
+.PP
+Arithmetic expansion allows the evaluation of an arithmetic expression
+and the substitution of the result.  There are two formats for
+arithmetic expansion:
+.RS
+.PP
+\fB$[\fP\fIexpression\fP\fB]\fP
+.PP
+\fB$((\fP\fIexpression\fP\fB))\fP
+.RE
+.PP
+The
+.I expression
+is treated as if it were within double quotes, but a double quote
+inside the braces or parentheses
+is not treated specially.  All tokens in the
+expression undergo parameter expansion, command substitution,
+and quote removal.  Arithmetic substitutions may be nested.
+.PP
+The evaluation is performed according to the rules listed below under
+.SM
+.BR "ARITHMETIC EVALUATION" .
+If
+.I expression
+is invalid,
+.B bash
+prints a message indicating failure and no substitution occurs.
+.SS Process Substitution
+.PP
+\fIProcess substitution\fP is supported on systems that support named
+pipes (\fIFIFOs\fP) or the \fB/dev/fd\fP method of naming open files.
+It takes the form of
+\fB<(\fP\fIlist\^\fP\fB)\fP
+or
+\fB>(\fP\fIlist\^\fP\fB)\fP.
+The process \fIlist\fP is run with its input or output connected to a
+\fIFIFO\fP or some file in \fB/dev/fd\fP.  The name of this file is
+passed as an argument to the current command as the result of the
+expansion.  If the \fB>(\fP\fIlist\^\fP\fB)\fP form is used, writing to
+the file will provide input for \fIlist\fP.  If the
+\fB<(\fP\fIlist\^\fP\fB)\fP form is used, the file passed as an
+argument should be read to obtain the output of \fIlist\fP.
+.PP
+On systems that support it, \fIprocess substitution\fP is performed
+simultaneously with
+.IR "parameter and variable expansion" ,
+.IR "command substitution" ,
+and
+.IR "arithmetic expansion" .
+.SS Word Splitting
+.PP
+The shell scans the results of
+parameter expansion,
+command substitution,
+and
+arithmetic expansion
+that did not occur within double quotes for
+.IR "word splitting" .
+.PP
+The shell treats each character of
+.SM
+.B IFS
+as a delimiter, and splits the results of the other
+expansions into words on these characters.  If the
+value of
+.SM
+.B IFS
+is exactly
+.BR <space><tab><newline> ,
+the default, then
+any sequence of
+.SM
+.B IFS
+characters serves to delimit words.  If
+.SM
+.B IFS
+has a value other than the default, then sequences of
+the whitespace characters
+.B space
+and
+.B tab
+are ignored at the beginning and end of the
+word, as long as the whitespace character is in the
+value of
+.SM
+.BR IFS
+(an
+.SM
+.B IFS
+whitespace character).
+Any character in
+.SM
+.B IFS
+that is not
+.SM
+.B IFS
+whitespace, along with any adjacent
+.SM
+.B IFS
+whitespace characters, delimits a field.
+A sequence of
+.SM
+.B IFS
+whitespace characters is also treated as a delimiter.
+If the value of
+.SM
+.B IFS
+is null, no word splitting occurs.
+.SM
+.B IFS
+cannot be unset.
+.PP
+Explicit null arguments (\^\f3"\^"\fP or \^\f3'\^'\fP\^)
+are retained.  Implicit null arguments, resulting from the expansion
+of
+.I parameters
+that have no values, are removed.
+.PP
+Note that if no expansion occurs, no splitting
+is performed.
+.SS Pathname Expansion
+.PP
+After word splitting,
+unless the
+.B \-f
+option has been set,
+.B bash
+scans each
+.I word
+for the characters
+.BR * ,
+.BR ? ,
+and
+.BR [ .
+If one of these characters appears, then the word is
+regarded as a
+.IR pattern ,
+and replaced with an alphabetically sorted list of
+pathnames matching the pattern.
+If no matching pathnames are found,
+and the shell variable
+.B allow_null_glob_expansion
+is unset, the word is left unchanged.
+If the variable is set, and no matches are found,
+the word is removed.
+When a pattern is used for pathname generation,
+the character
+.B ``.''
+at the start of a name or immediately following a slash
+must be matched explicitly, unless the shell variable
+.B glob_dot_filenames
+is set.  The slash character must always be matched
+explicitly.  In other cases, the
+.B ``.''
+character is not treated specially.
+.PP
+The special pattern characters have the following meanings:
+.PP
+.PD 0
+.TP
+.B *
+Matches any string, including the null string.
+.TP
+.B ?
+Matches any single character.
+.TP
+.B [...]
+Matches any one of the enclosed characters.  A pair of characters
+separated by a minus sign denotes a
+.IR range ;
+any character lexically between those two characters, inclusive,
+is matched.  If the first character following the
+.B [
+is a
+.B !
+or a
+.B ^
+then any character not enclosed is matched.  A 
+.B \-
+or
+.B ]
+may be matched by including it as the first or last character
+in the set.
+.PD
+.SS Quote Removal
+.PP
+After the preceding expansions, all unquoted occurrences of the
+characters
+.BR \e ,
+.BR ` ,
+and \^\f3"\fP\^ are removed. 
+.SH REDIRECTION
+Before a command is executed, its input and output
+may be
+.I redirected
+using a special notation interpreted by the shell.
+Redirection may also be used to open and close files for the
+current shell execution environment.  The following redirection
+operators may precede or appear anywhere within a
+.I simple command
+or may follow a
+.IR command .
+Redirections are processed in the order they appear, from
+left to right.
+.PP
+In the following descriptions, if the file descriptor number is
+omitted, and the first character of the redirection operator is
+.BR < ,
+the redirection refers to the standard input (file descriptor
+0).  If the first character of the redirection operator is
+.BR > ,
+the redirection refers to the standard output (file descriptor
+1).
+.PP
+The word that follows the redirection operator in the following
+descriptions is subjected to brace expansion, tilde expansion,
+parameter expansion, command substitution, arithmetic expansion,
+quote removal, and pathname expansion.  If it expands to more
+than one word,
+.B bash
+reports an error.
+.PP
+Note that the order of redirections is significant.  For example, 
+the command
+.RS
+.PP
+ls \fB>\fP dirlist 2\fB>&\fP1
+.RE
+.PP
+directs both standard output and standard error to the file 
+.IR dirlist ,
+while the command
+.RS
+.PP
+ls 2\fB>&\fP1 \fB>\fP dirlist
+.RE
+.PP
+directs only the standard output to file
+.IR dirlist ,
+because the standard error was duplicated as standard output
+before the standard output was redirected to
+.IR dirlist .
+.SS Redirecting Input
+.PP
+Redirection of input causes the file whose name results from
+the expansion of
+.I word
+to be opened for reading on file descriptor
+.IR n ,
+or the standard input (file descriptor 0) if
+.I n
+is not specified.
+.PP
+The general format for redirecting input is:
+.RS
+.PP
+[\fIn\fP]\fB<\fP\fIword\fP
+.RE
+.SS Redirecting Output
+.PP
+Redirection of output causes the file whose name results from
+the expansion of
+.I word
+to be opened for writing on file descriptor
+.IR n ,
+or the standard output (file descriptor 1) if
+.I n
+is not specified.  If the file does not exist it is created;
+if it does exist it is truncated to zero size.
+.PP
+The general format for redirecting output is:
+.RS
+.PP
+[\fIn\fP]\fB>\fP\fIword\fP
+.RE
+.PP
+If the redirection operator is
+.BR >| ,
+then the value of the
+.B -C
+option to the
+.B set
+builtin command is not tested, and file creation is attempted.
+(See also the description of
+.B noclobber
+under
+.B "Shell Variables"
+above.)
+.SS Appending Redirected Output
+.PP
+Redirection of output in this fashion
+causes the file whose name results from
+the expansion of
+.I word
+to be opened for appending on file descriptor
+.IR n ,
+or the standard output (file descriptor 1) if
+.I n
+is not specified.  If the file does not exist it is created.
+.PP
+The general format for appending output is:
+.RS
+.PP
+[\fIn\fP]\fB>>\fP\fIword\fP
+.RE
+.PP
+.SS Redirecting Standard Output and Standard Error
+.PP
+.B Bash
+allows both the
+standard output (file descriptor 1) and
+the standard error output (file descriptor 2)
+to be redirected to the file whose name is the
+expansion of
+.I word
+with this construct.
+.PP
+There are two formats for redirecting standard output and
+standard error:
+.RS
+.PP
+\fB&>\fP\fIword\fP
+.RE
+and
+.RS
+\fB>&\fP\fIword\fP
+.RE
+.PP
+Of the two forms, the first is preferred.
+This is semantically equivalent to
+.RS
+.PP
+\fB>\fP\fIword\fP 2\fB>&\fP1
+.RE
+.SS Here Documents
+.PP
+This type of redirection instructs the shell to read input from the
+current source until a line containing only
+.I 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.
+.PP
+The format of here-documents is as follows:
+.RS
+.PP
+.nf
+\fB<<\fP[\fB\-\fP]\fIword\fP
+        \fIhere-document\fP
+\fIdelimiter\fP
+.fi
+.RE
+.PP
+No parameter expansion, command substitution, pathname
+expansion, or arithmetic expansion is performed on
+.IR word .
+If any characters in
+.I word
+are quoted, the
+.I delimiter
+is the result of quote removal on
+.IR word ,
+and the lines in the here-document are not expanded.  Otherwise,
+all lines of the here-document are subjected to parameter expansion,
+command substitution, and arithmetic expansion.  In the latter
+case, the pair
+.B \e<newline>
+is ignored, and
+.B \e
+must be used to quote the characters
+.BR \e ,
+.BR $ ,
+and
+.BR ` .
+.PP
+If the redirection operator is
+.BR <<\- ,
+then all leading tab characters are stripped from input lines and the
+line containing
+.IR delimiter .
+This allows
+here-documents within shell scripts to be indented in a
+natural fashion.
+.SS "Duplicating File Descriptors"
+.PP
+The redirection operator
+.RS
+.PP
+[\fIn\fP]\fB<&\fP\fIword\fP
+.RE
+.PP
+is used to duplicate input file descriptors.
+If
+.I word
+expands to one or more digits, the file descriptor denoted by
+.I n
+is made to be a copy of that file descriptor.  If
+.I word
+evaluates to
+.BR \- ,
+file descriptor
+.I n
+is closed.  If
+.I n
+is not specified, the standard input (file descriptor 0) is used.
+.PP
+The operator
+.RS
+.PP
+[\fIn\fP]\fB>&\fP\fIword\fP
+.RE
+.PP
+is used similarly to duplicate output file descriptors.  If
+.I n
+is not specified, the standard output (file descriptor 1) is used.
+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 "Opening File Descriptors for Reading and Writing"
+.PP
+The redirection operator
+.RS
+.PP
+[\fIn\fP]\fB<>\fP\fIword\fP
+.RE
+.PP
+causes the file whose name is the expansion of
+.I word
+to be opened for both reading and writing on file descriptor
+.IR n ,
+or as the standard input and standard output if 
+.I n
+is not specified.  If the file does not exist, it is created.
+.SH FUNCTIONS
+A shell function, defined as described above under
+.SM
+.BR "SHELL GRAMMAR" ,
+stores a series of commands for later execution.
+Functions are executed in the context of the
+current shell; no new process is created to interpret
+them (contrast this with the execution of a shell script).
+When a function is executed, the arguments to the
+function become the positional parameters
+during its execution.  The special parameter
+.B #
+is updated to reflect the change.  Positional parameter 0
+is unchanged.
+.PP
+Variables local to the function may be declared with the
+.B local
+builtin command.  Ordinarily, variables and their values
+are shared between the function and its caller.
+.PP
+If the builtin command
+.B return
+is executed in a function, the function completes and
+execution resumes with the next command after the function
+call.  When a function completes, the values of the
+positional parameters and the special parameter
+.B #
+are restored to the values they had prior to function
+execution.
+.PP
+Function names and definitions may be listed with the
+.B \-f
+option to the
+.B declare
+or
+.B typeset
+builtin commands.  Functions may be exported so that subshells
+automatically have them defined with the
+.B \-f
+option to the 
+.B export
+builtin.
+.PP
+Functions may be recursive.  No limit is imposed on the number
+of recursive calls.
+.SH ALIASES
+The shell maintains a list of
+.I aliases
+that may be set and unset with the
+.B alias
+and
+.B unalias
+builtin commands (see
+.SM
+.B SHELL BUILTIN COMMANDS
+below).
+The first word of each command, if unquoted,
+is checked to see if it has an
+alias.  If so, that word is replaced by the text of the alias.
+The alias name and the replacement text may contain any valid
+shell input, including the
+.I metacharacters
+listed above, with the exception that the alias name may not
+contain \fI=\fP.  The first word of the replacement text is tested
+for aliases, but a word that is identical to an alias being expanded
+is not expanded a second time.  This means that one may alias
+.B ls
+to
+.BR "ls \-F" ,
+for instance, and
+.B bash
+does not try to recursively expand the replacement text.
+If the last character of the alias value is a
+.IR blank ,
+then the next command
+word following the alias is also checked for alias expansion.
+.PP
+Aliases are created and listed with the
+.B alias
+command, and removed with the
+.B unalias
+command.
+.PP
+There is no mechanism for using arguments in the replacement text,
+as in
+.BR csh .
+If arguments are needed, a shell function should be used.
+.PP
+Aliases are not expanded when the shell is not interactive.
+.PP
+The rules concerning the definition and use of aliases are
+somewhat confusing.
+.B Bash
+always reads at least one complete line
+of input before executing any
+of the commands on that line.  Aliases are expanded when a
+command is read, not when it is executed.  Therefore, an
+alias definition appearing on the same line as another
+command does not take effect until the next line of input is read.
+This means that the commands following the alias definition
+on that line are not affected by the new alias.
+This behavior is also an issue when functions are executed.
+Aliases are expanded when the function definition is read,
+not when the function is executed, because a function definition
+is itself a compound command.  As a consequence, aliases
+defined in a function are not available until after that
+function is executed.  To be safe, always put
+alias definitions on a separate line, and do not use
+.B alias
+in compound commands.
+.PP
+Note that for almost every purpose, aliases are superseded by
+shell functions.
+.SH "JOB CONTROL"
+.I Job control
+refers to the ability to selectively stop (\fIsuspend\fP)
+the execution of processes and continue (\fIresume\fP)
+their execution at a later point.  A user typically employs
+this facility via an interactive interface supplied jointly
+by the system's terminal driver and
+.BR bash .
+.PP
+The shell associates a
+.I job
+with each pipeline.  It keeps a table of currently executing
+jobs, which may be listed with the
+.B jobs
+command.  When
+.B bash
+starts a job asynchronously (in the
+.IR background ),
+it prints a line that looks like:
+.RS
+.PP
+[1] 25647
+.RE
+.PP
+indicating that this job is job number 1 and that the process ID
+of the last process in the pipeline associated with this job is 25647.
+All of the processes in a single pipeline are members of the same job.
+.B Bash
+uses the
+.I job
+abstraction as the basis for job control.
+.PP
+To facilitate the implementation of the user interface to job
+control, the system maintains the notion of a \fIcurrent terminal
+process group ID\fP.  Members of this process group (processes whose
+process group ID is equal to the current terminal process group ID)
+receive keyboard-generated signals such as
+.SM
+.BR SIGINT .
+These processes are said to be in the
+.IR foreground .
+.I Background
+processes are those whose process group ID differs from the terminal's;
+such processes are immune to keyboard-generated signals.
+Only foreground processes are allowed to read from or write to the
+terminal.  Background processes which attempt to read from (write to) the
+terminal are sent a 
+.SM
+.B SIGTTIN (SIGTTOU)
+signal by the terminal driver, 
+which, unless caught, suspends the process.
+.PP
+If the operating system on which
+.B bash
+is running supports
+job control,
+.B bash
+allows you to use it.
+Typing the
+.I suspend
+character (typically
+.BR ^Z ,
+Control-Z) while a process is running
+causes that process to be stopped and returns you to 
+.BR bash .
+Typing the
+.I "delayed suspend"
+character (typically
+.BR ^Y ,
+Control-Y) causes the process to be stopped when it
+attempts to read input from the terminal, and control to
+be returned to
+.BR bash .
+You may then manipulate the state of this job, using the
+.B bg
+command to continue it in the background, the
+.B fg
+command to continue it in the foreground, or
+the
+.B kill
+command to kill it.  A \fB^Z\fP takes effect immediately,
+and has the additional side effect of causing pending output
+and typeahead to be discarded.
+.PP
+There are a number of ways to refer to a job in the shell.
+The character
+.B %
+introduces a job name.  Job number
+.I n
+may be referred to as
+.BR %n .
+A job may also be referred to using a prefix of the name used to
+start it, or using a substring that appears in its command line.
+For example,
+.B %ce
+refers to a stopped
+.B ce
+job.  If a prefix matches more than one job,
+.B bash
+reports an error.  Using
+.BR %?ce ,
+on the other hand, refers to any job containing the string
+.B ce
+in its command line.  If the substring matches more than one job,
+.B bash
+reports an error.  The symbols
+.B %%
+and
+.B %+
+refer to the shell's notion of the
+.IR "current job" ,
+which is the last job stopped while it was in
+the foreground.
+The 
+.I "previous job"
+may be referenced using
+.BR %\- .
+In output pertaining to jobs (e.g., the output of the
+.B jobs
+command), the current job is always flagged with a
+.BR + ,
+and the previous job with a
+.BR \- .
+.PP
+Simply naming a job can be used to bring it into the
+foreground:
+.B %1
+is a synonym for
+\fB``fg %1''\fP,
+bringing job 1 from the background into the foreground.
+Similarly,
+.B ``%1 &''
+resumes job 1 in the background, equivalent to
+\fB``bg %1''\fP.
+.PP
+The shell learns immediately whenever a job changes state.
+Normally,
+.B bash
+waits until it is about to print a prompt before reporting
+changes in a job's status so as to not interrupt
+any other output.  If the 
+.B -b
+option to the
+.B set
+builtin command
+is set,
+.B bash
+reports such changes immediately.  (See also the description of
+.B notify
+variable under
+.B "Shell Variables"
+above.)
+.PP
+If you attempt to exit
+.B bash
+while jobs are stopped, the shell prints a message warning you.  You
+may then use the
+.B jobs
+command to inspect their status.  If you do this, or try to exit
+again immediately, you are not warned again, and the stopped
+jobs are terminated.
+.SH SIGNALS
+When \fBbash\fP is interactive, it ignores
+.SM
+.B SIGTERM
+(so that \fBkill 0\fP does not kill an interactive shell),
+and
+.SM
+.B SIGINT
+is caught and handled (so that the \fBwait\fP builtin is interruptible).
+In all cases, \fBbash\fP ignores
+.SM
+.BR SIGQUIT .
+If job control is in effect,
+.B bash
+ignores
+.SM
+.BR SIGTTIN ,
+.SM
+.BR SIGTTOU ,
+and
+.SM
+.BR SIGTSTP .
+.PP
+Synchronous jobs started by \fBbash\fP have signals set to the
+values inherited by the shell from its parent.  When job control
+is not in effect, background jobs (jobs started with
+.BR & )
+ignore
+.SM
+.B SIGINT
+and
+.SM
+.BR SIGQUIT .
+Commands run as a result of command substitution ignore the
+keyboard-generated job control signals
+.SM
+.BR SIGTTIN ,
+.SM
+.BR SIGTTOU ,
+and
+.SM
+.BR SIGTSTP .
+.SH "COMMAND EXECUTION"
+After a command has been split into words, if it results in a
+simple command and an optional list of arguments, the following
+actions are taken.
+.PP
+If the command name contains no slashes, the shell attempts to
+locate it.  If there exists a shell function by that name, that
+function is invoked as described above in
+.SM
+.BR FUNCTIONS .
+If the name does not match a function, the shell searches for
+it in the list of shell builtins.  If a match is found, that
+builtin is invoked.
+.PP
+If the name is neither a shell function nor a builtin,
+and contains no slashes,
+.B bash
+searches each element of the
+.SM
+.B PATH
+for a directory containing an executable file by that name.
+If the search is unsuccessful, the shell prints an error
+message and returns a nonzero exit status.
+.PP
+If the search is successful, or if the command name contains
+one or more slashes, the shell executes the named program.
+Argument 0 is set to the name given, and the remaining arguments
+to the command are set to the arguments given, if any.
+.PP
+If this execution fails because the file is not in executable
+format, and the file is not a directory, it is assumed to be
+a \fIshell script\fP, a file
+containing shell commands.  A subshell is spawned to execute
+it.  This subshell reinitializes itself, so
+that the effect is as if a new shell had been invoked
+to handle the script, with the exception that the locations of
+commands remembered by the parent (see
+.B hash
+below under
+.SM
+\fBSHELL BUILTIN COMMANDS\fP)
+are retained by the child.
+.PP
+If the program is a file beginning with
+.BR #! ,
+the remainder of the first line specifies an interpreter
+for the program.  The shell executes the
+specified interpreter on operating systems that do not
+handle this executable format themselves.  The arguments to the 
+interpreter consist of a single optional argument following the
+interpreter name on the first line of the program, followed
+by the name of the program, followed by the command
+arguments, if any.
+.SH ENVIRONMENT
+When a program is invoked it is given an array of strings
+called the
+.IR environment .
+This is a list of 
+\fIname\fP\-\fIvalue\fP pairs, of the form
+.IR "name\fR=\fPvalue" .
+.PP
+The shell allows you to manipulate the environment in several
+ways.  On invocation, the shell scans its own environment and
+creates a parameter for each name found, automatically marking
+it for
+.I export
+to child processes.  Executed commands inherit the environment.
+The
+.B export
+and
+.B declare \-x
+commands allow parameters and functions to be added to and
+deleted from the environment.  If the value of a parameter
+in the environment is modified, the new value becomes part
+of the environment, replacing the old.  The environment
+inherited by any executed command consists of the shell's
+initial environment, whose values may be modified in the shell,
+less any pairs removed by the
+.B unset
+command, plus any additions via the
+.B export
+and
+.B declare \-x
+commands.
+.PP
+The environment for any
+.I simple command
+or function may be augmented temporarily by prefixing it with
+parameter assignments, as described above in
+.SM
+.BR PARAMETERS .
+These assignment statements affect only the environment seen
+by that command.
+.PP
+If the 
+.B \-k
+flag is set (see the
+.B set
+builtin command below), then
+.I all
+parameter assignments are placed in the environment for a command,
+not just those that precede the command name.
+.PP
+When
+.B bash
+invokes an external command, the variable
+.B _
+is set to the full path name of the command and passed to that
+command in its environment.
+.SH "EXIT STATUS"
+For the purposes of the shell, a command which exits with a 
+zero exit status has succeeded.  An exit status of zero
+indicates success.  A non\-zero exit status indicates failure.
+When a command terminates on a fatal signal, \fBbash\fP uses
+the value of 128+\fBsignal\fP as the exit status.
+.PP
+If a command is not found, the child process created to
+execute it returns a status of 127.  If a command is found
+but is not executable, the return status is 126.
+.PP
+\fBBash\fP itself returns the exit status of the last command
+executed, unless a syntax error occurs, in which case it exits
+with a non\-zero value.  See also the \fBexit\fP builtin
+command below.
+.SH PROMPTING
+When executing interactively, 
+.B bash
+displays the primary prompt
+.SM
+.B PS1
+when it is ready to read a command, and the secondary prompt
+.SM
+.B PS2
+when it needs more input to complete a command.
+.B Bash
+allows these prompt strings to be customized by inserting a number of
+backslash-escaped special characters that are decoded as follows:
+.RS
+.PD 0
+.TP
+.B \et
+the current time in HH:MM:SS format
+.TP
+.B \ed
+the date in "Weekday Month Date" format (e.g., "Tue May 26")
+.TP
+.B \en
+newline
+.TP
+.B \es
+the name of the shell, the basename of
+.B $0
+(the portion following the final slash)
+.TP
+.B \ew
+the current working directory
+.TP
+.B \eW
+the basename of the current working directory
+.TP
+.B \eu
+the username of the current user
+.TP
+.B \eh
+the hostname
+.TP
+.B \e#
+the command number of this command
+.TP
+.B \e!
+the history number of this command
+.TP
+.B \e$
+if the effective UID is 0, a
+.BR # ,
+otherwise a
+.B $
+.TP
+.B \ennn
+the character corresponding to the octal number \fBnnn\fP
+.TP
+.B \e\e
+a backslash
+.TP
+.B \e[
+begin a sequence of non-printing characters, which could be used to
+embed a terminal control sequence into the prompt
+.TP
+.B \e]
+end a sequence of non-printing characters
+.PD
+.RE
+.PP
+The command number and the history number are usually different:
+the history number of a command is its position in the history
+list, which may include commands restored from the history file
+(see
+.SM
+.B HISTORY
+below), while the command number is the position in the sequence
+of commands executed during the current shell session.
+After the string is decoded, it is expanded via
+parameter expansion,
+command substitution, arithmetic expansion, and word splitting.
+.SH READLINE
+This is the library that handles reading input when using an interactive
+shell, unless the
+.B \-nolineediting
+option is given.  By default, the line editing commands
+are similar to those of emacs.
+A vi-style line editing interface is also available.
+.PP
+In this section, the emacs-style notation is used to denote
+keystrokes.  Control keys are denoted by C\-\fIkey\fR, e.g., C\-n
+means Control\-N.  Similarly, 
+.I meta
+keys are denoted by M\-\fIkey\fR, so M\-x means Meta\-X.  (On keyboards
+without a 
+.I meta
+key, M\-\fIx\fP means ESC \fIx\fP, i.e., press the Escape key
+then the
+.I x
+key.  This makes ESC the \fImeta prefix\fP.
+The combination M\-C\-\fIx\fP means ESC\-Control\-\fIx\fP,
+or press the Escape key
+then hold the Control key while pressing the
+.I x
+key.)
+.PP
+The default key-bindings may be changed with an
+.FN ~/.inputrc 
+file.  The value of the shell variable
+.SM
+.BR INPUTRC ,
+if set, is used instead of
+.IR ~/.inputrc .
+Other programs that use this library may add their own commands
+and bindings.
+.PP
+For example, placing
+.RS
+.PP
+M\-Control\-u: universal\-argument
+.RE
+or
+.RS
+C\-Meta\-u: universal\-argument
+.RE
+into the 
+.FN ~/.inputrc
+would make M\-C\-u execute the readline command
+.IR universal\-argument .
+.PP
+The following symbolic character names are recognized:
+.IR RUBOUT ,
+.IR DEL ,
+.IR ESC ,
+.IR LFD ,
+.IR NEWLINE ,
+.IR RET ,
+.IR RETURN ,
+.IR SPC ,
+.IR SPACE ,
+and
+.IR TAB .
+In addition to command names, readline allows keys to be bound
+to a string that is inserted when the key is pressed (a \fImacro\fP).
+.PP
+Readline is customized by putting commands in an initialization
+file.  The name of this file is taken from the value of the
+.SM
+.B INPUTRC
+variable.  If that variable is unset, the default is
+.IR ~/.inputrc .
+When a program which uses the readline library starts up, the
+init file is read, and the key bindings and variables are set.
+There are only a few basic constructs allowed in the
+readline init file.  Blank lines are ignored.
+Lines beginning with a \fB#\fP are comments.
+Lines beginning with a \fB$\fP indicate conditional
+constructs.  Other lines
+denote key bindings and variable settings.
+.PP
+The syntax for controlling key bindings in the
+.I ~/.inputrc
+file is simple.  All that is required is the name of the
+command or the text of a macro and a key sequence to which
+it should be bound. The name may be specified in one of two ways:
+as a symbolic key name, possibly with \fIMeta-\fP or \fIControl-\fP
+prefixes, or as a key sequence.
+When using the form \fBkeyname\fP:\fIfunction-name\fP or \fImacro\fP,
+.I keyname
+is the name of a key spelled out in English.  For example:
+.sp
+.RS
+Control-u: universal\-argument
+.br
+Meta-Rubout: backward-kill-word
+.br
+Control-o: ">&output"
+.RE
+.LP
+In the above example,
+.I C-u
+is bound to the function
+.BR universal\-argument ,
+.I M-DEL
+is bound to the function
+.BR backward\-kill\-word ,
+and
+.I C-o
+is bound to run the macro
+expressed on the right hand side (that is, to insert the text
+.I >&output
+into the line).
+.PP
+In the second form, \fB"keyseq"\fP:\fIfunction-name\fP or \fImacro\fP,
+.B keyseq
+differs from
+.B keyname
+above in that strings denoting
+an entire key sequence may be specified by placing the sequence
+within double quotes.  Some GNU Emacs style key escapes can be
+used, as in the following example.
+.sp
+.RS
+"\eC-u": universal\-argument
+.br
+"\eC-x\eC-r": re\-read\-init\-file
+.br
+"\ee[11~": "Function Key 1"
+.RE
+.PP
+In this example,
+.I C-u
+is again bound to the function
+.BR universal\-argument .
+.I "C-x C-r"
+is bound to the function
+.BR re\-read\-init\-file ,
+and 
+.I "ESC [ 1 1 ~"
+is bound to insert the text
+.BR "Function Key 1" .
+The full set of escape sequences is
+.RS
+.TP
+.B \eC\-
+control prefix
+.TP
+.B \eM-
+meta prefix
+.TP
+.B \ee
+an escape character
+.TP
+.B \e\e
+backslash
+.TP
+.B \e"
+literal "
+.TP
+.B \e'
+literal '
+.RE
+.PP
+When entering the text of a macro, single or double quotes should
+be used to indicate a macro definition.  Unquoted text
+is assumed to be a function name.  Backslash
+will quote any character in the macro text, including " and '.
+.PP
+.B Bash
+allows the current readline key bindings to be displayed or modified
+with the
+.B bind
+builtin command.  The editing mode may be switched during interactive
+use by using the
+.B \-o
+option to the
+.B set
+builtin command (see
+.SM
+.B SHELL BUILTIN COMMANDS
+below).
+.PP
+Readline has variables that can be used to further customize its
+behavior.  A variable may be set in the
+.I inputrc
+file with a statement of the form
+.RS
+.PP
+\fBset\fP \fIvariable\-name\fP \fIvalue\fP
+.RE
+.PP
+Except where noted, readline variables can take the values
+.B On
+or
+.BR Off .
+The variables and their default values are:
+.PP
+.PD 0
+.TP
+.B horizontal\-scroll\-mode (Off)
+When set to \fBOn\fP, makes readline use a single line for display,
+scrolling the input horizontally on a single screen line when it
+becomes longer than the screen width rather than wrapping to a new line.
+.TP
+.B editing\-mode (emacs)
+Controls whether readline begins with a set of key bindings similar
+to \fIemacs\fP or \fIvi\fP.
+.B editing\-mode
+can be set to either
+.B emacs
+or
+.BR vi .
+.TP
+.B mark\-modified\-lines (Off)
+If set to \fBOn\fP, history lines that have been modified are displayed
+with a preceding asterisk (\fB*\fP).
+.TP
+.B bell\-style (audible)
+Controls what happens when readline wants to ring the terminal bell.
+If set to \fBnone\fP, readline never rings the bell.  If set to
+\fBvisible\fP, readline uses a visible bell if one is available.
+If set to \fBaudible\fP, readline attempts to ring the terminal's bell.
+.TP
+.B comment\-begin (``#'')
+The string that is inserted in \fBvi\fP mode when the
+.B vi\-comment
+command is executed.
+.TP
+.B meta\-flag (Off)
+If set to \fBOn\fP, readline will enable eight-bit input (that is,
+it will not strip the high bit from the characters it reads),
+regardless of what the terminal claims it can support.
+.TP
+.B convert\-meta (On)
+If set to \fBOn\fP, readline will convert characters with the
+eighth bit set to an ASCII key sequence
+by stripping the eighth bit and prepending an
+escape character (in effect, using escape as the \fImeta prefix\fP).
+.TP
+.B output\-meta (Off)
+If set to \fBOn\fP, readline will display characters with the
+eighth bit set directly rather than as a meta-prefixed escape
+sequence.
+.TP
+.B completion\-query\-items (100)
+This determines when the user is queried about viewing
+the number of possible completions
+generated by the \fBpossible\-completions\fP command.
+It may be set to any integer value greater than or equal to
+zero.  If the number of possible completions is greater than
+or equal to the value of this variable, the user is asked whether
+or not he wishes to view them; otherwise they are simply listed
+on the terminal.
+.TP
+.B keymap (emacs)
+Set the current readline keymap.  The set of legal keymap names is
+\fIemacs, emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,
+vi-command\fP, and
+.IR vi-insert .
+\fIvi\fP is equivalent to \fIvi-command\fP; \fIemacs\fP is
+equivalent to \fIemacs-standard\fP.  The default value is
+.IR emacs ;
+the value of
+.B editing\-mode
+also affects the default keymap.
+.TP
+.B show\-all\-if\-ambiguous (Off)
+This alters the default behavior of the completion functions.  If
+set to
+.BR on ,
+words which have more than one possible completion cause the
+matches to be listed immediately instead of ringing the bell.
+.TP
+.B expand\-tilde (Off)
+If set to \fBon\fP, tilde expansion is performed when readline
+attempts word completion.
+.PD
+.PP
+Readline implements a facility similar in spirit to the conditional
+compilation features of the C preprocessor which allows key
+bindings and variable settings to be performed as the result
+of tests.  There are three parser directives used.
+.IP \fB$if\fP
+The 
+.B $if
+construct allows bindings to be made based on the
+editing mode, the terminal being used, or the application using
+readline.  The text of the test extends to the end of the line;
+no characters are required to isolate it.
+.RS
+.IP \fBmode\fP
+The \fBmode=\fP form of the \fB$if\fP directive is used to test
+whether readline is in emacs or vi mode.
+This may be used in conjunction
+with the \fBset keymap\fP command, for instance, to set bindings in
+the \fIemacs-standard\fP and \fIemacs-ctlx\fP keymaps only if
+readline is starting out in emacs mode.
+.IP \fBterm\fP
+The \fBterm=\fP form may be used to include terminal-specific
+key bindings, perhaps to bind the key sequences output by the
+terminal's function keys.  The word on the right side of the
+.B =
+is tested against the full name of the terminal and the portion
+of the terminal name before the first \fB\-\fP.  This allows
+.I sun
+to match both
+.I sun
+and
+.IR sun\-cmd ,
+for instance.
+.IP \fBapplication\fP
+The \fBapplication\fP construct is used to include
+application\-specific settings.  Each program using the readline
+library sets the \fIapplication name\fP, and an initialization
+file can test for a particular value.
+This could be used to bind key sequences to functions useful for
+a specific program.  For instance, the following command adds a
+key sequence that quotes the current or previous word in Bash:
+.RS
+.nf
+\fB$if\fP Bash
+# Quote the current or previous word
+"\eC-xq": "\eeb\e"\eef\e""
+\fB$endif\fP
+.fi
+.RE
+.RE
+.IP \fB$endif\fP
+This command, as you saw in the previous example, terminates an
+\fB$if\fP command.
+.IP \fB$else\fP
+Commands in this branch of the \fB$if\fP directive are executed if
+the test fails.
+.PP
+Readline commands may be given numeric
+.IR arguments ,
+which normally act as a repeat count.  Sometimes, however, it is the
+sign of the argument that is significant.  Passing a negative argument
+to a command that acts in the forward direction (e.g., \fBkill\-line\fP)
+causes that command to act in a backward direction.  Commands whose
+behavior with arguments deviates from this are noted.
+.PP
+When a command is described as \fIkilling\fP text, the text
+deleted is saved for possible future retrieval
+(\fIyanking\fP).  The killed text is saved in a
+\fIkill\-ring\fP.  Consecutive kills cause the text to be
+accumulated into one unit, which can be yanked all at once. 
+Commands which do not kill text separate the chunks of text
+on the kill\-ring.
+.PP
+The following is a list of the names of the commands and the default
+key sequences to which they are bound.
+.SS Commands for Moving
+.PP
+.PD 0
+.TP
+.B beginning\-of\-line (C\-a)
+Move to the start of the current line.
+.TP
+.B end\-of\-line (C\-e)
+Move to the end of the line.
+.TP
+.B forward\-char (C\-f)
+Move forward a character.
+.TP
+.B backward\-char (C\-b)
+Move back a character.
+.TP
+.B forward\-word (M\-f)
+Move forward to the end of the next word.  Words are composed of
+alphanumeric characters (letters and digits).
+.TP
+.B backward\-word (M\-b)
+Move back to the start of this, or the previous, word.  Words are
+composed of alphanumeric characters (letters and digits).
+.TP
+.B clear\-screen (C\-l)
+Clear the screen leaving the current line at the top of the screen.
+With an argument, refresh the current line without clearing the
+screen.
+.TP
+.B redraw\-current\-line
+Refresh the current line.  By default, this is unbound.
+.PD
+.SS Commands for Manipulating the History
+.PP
+.PD 0
+.TP
+.B accept\-line (Newline, Return)
+Accept the line regardless of where the cursor is.  If this line is
+non\-empty, add it to the history list according to the state of the
+.SM
+.B HISTCONTROL
+variable.  If the line is a modified history
+line, then restore the history line to its original state.
+.TP
+.B previous\-history (C\-p)
+Fetch the previous command from the history list, moving back in
+the list.
+.TP
+.B next\-history (C\-n)
+Fetch the next command from the history list, moving forward in the
+list.
+.TP
+.B beginning\-of\-history (M\-<)
+Move to the first line in the history.
+.TP
+.B end\-of\-history (M\->)
+Move to the end of the input history, i.e., the line currently being
+entered.
+.TP
+.B reverse\-search\-history (C\-r)
+Search backward starting at the current line and moving `up' through
+the history as necessary.  This is an incremental search.
+.TP
+.B forward\-search\-history (C\-s)
+Search forward starting at the current line and moving `down' through
+the history as necessary.  This is an incremental search.
+.TP
+.B non\-incremental\-reverse\-search\-history (M\-p)
+Search backward through the history starting at the current line
+using a non\-incremental search for a string supplied by the user.
+.TP
+.B non\-incremental\-forward\-search\-history (M\-n)
+Search forward through the history using a non\-incremental search for
+a string supplied by the user.
+.TP
+.B history\-search\-forward
+Search forward through the history for the string of characters
+between the start of the current line and the current point.  This
+is a non-incremental search.  By default, this command is unbound.
+.TP
+.B history\-search\-backward
+Search backward through the history for the string of characters
+between the start of the current line and the current point.  This
+is a non-incremental search.  By default, this command is unbound.
+.TP
+.B yank\-nth\-arg (M\-C\-y)
+Insert the first argument to the previous command (usually
+the second word on the previous line) at point (the current
+cursor position).  With an argument
+.IR n ,
+insert the \fIn\fPth word from the previous command (the words
+in the previous command begin with word 0).  A negative argument
+inserts the \fIn\fPth word from the end of the previous command.
+.TP
+.B
+yank\-last\-arg (M\-.\^, M\-_\^)
+Insert the last argument to the previous command (the last word on
+the previous line).  With an argument,
+behave exactly like \fByank-nth-arg\fP.
+.TP
+.B shell\-expand\-line (M\-C\-e)
+Expand the line the way the shell does when it reads it.  This
+performs alias and history expansion as well as all of the shell
+word expansions.  See
+.SM
+.B HISTORY EXPANSION
+below for a description of history expansion.
+.TP
+.B history\-expand\-line (M\-^)
+Perform history expansion on the current line.  See
+.SM
+.B HISTORY EXPANSION
+below for a description of history expansion.
+.TP
+.B insert\-last\-argument (M\-.\^, M\-_\^)
+A synonym for \fByank\-last\-arg\fP.
+.TP
+.B operate-and-get-next (C\-o)
+Accept the current line for execution and fetch the next line
+relative to the current line from the history for editing.  Any
+argument is ignored.
+.PD
+.SS Commands for Changing Text
+.PP
+.PD 0
+.TP
+.B delete\-char (C\-d)
+Delete the character under the cursor.  If point is at the
+beginning of the line, there are no characters in the line, and
+the last character typed was not
+.BR C\-d ,
+then return
+.SM
+.BR EOF .
+.TP
+.B backward\-delete\-char (Rubout)
+Delete the character behind the cursor.  When given a numeric argument,
+save the deleted text on the kill\-ring.
+.TP
+.B quoted\-insert (C\-q, C\-v)
+Add the next character that you type to the line verbatim.  This is
+how to insert characters like \fBC\-q\fP, for example.
+.TP
+.B tab\-insert (C-v TAB)
+Insert a tab character.
+.TP
+.B self\-insert (a,\ b,\ A,\ 1,\ !,\ ...)
+Insert the character typed.
+.TP
+.B transpose\-chars (C\-t)
+Drag the character before point forward over the character at point.
+Point moves forward as well.  If point is at the end of the line, then
+transpose the two characters before point.  Negative arguments don't work.
+.TP
+.B transpose\-words (M\-t)
+Drag the word behind the cursor past the word in front of the cursor
+moving the cursor over that word as well.
+.TP
+.B upcase\-word (M\-u)
+Uppercase the current (or following) word.  With a negative argument,
+do the previous word, but do not move point.
+.TP
+.B downcase\-word (M\-l)
+Lowercase the current (or following) word.  With a negative argument,
+do the previous word, but do not move point.
+.TP
+.B capitalize\-word (M\-c)
+Capitalize the current (or following) word.  With a negative argument,
+do the previous word, but do not move point.
+.PD
+.SS Killing and Yanking
+.PP
+.PD 0
+.TP
+.B kill\-line (C\-k)
+Kill the text from the current cursor position to the end of the line.
+.TP
+.B backward\-kill\-line (C\-x C\-Rubout)
+Kill backward to the beginning of the line.
+.TP
+.B unix\-line\-discard (C\-u)
+Kill backward from point to the beginning of the line.
+.\" There is no real difference between this and backward-kill-line
+.TP
+.B kill\-whole\-line
+Kill all characters on the current line, no matter where the
+cursor is.  By default, this is unbound.
+.TP
+.B kill\-word  (M\-d)
+Kill from the cursor to the end of the current word, or if between
+words, to the end of the next word.  Word boundaries are the same as
+those used by \fBforward\-word\fP.
+.TP
+.B backward\-kill\-word (M\-Rubout)
+Kill the word behind the cursor.  Word boundaries are the same as
+those used by \fBbackward\-word\fP.
+.TP
+.B unix\-word\-rubout (C\-w)
+Kill the word behind the cursor, using white space as a word boundary.
+The word boundaries are different from backward\-kill\-word.
+.TP
+.B delete\-horizontal\-space
+Delete all spaces and tabs around point.  By default, this is unbound.
+.TP
+.B yank (C\-y)
+Yank the top of the kill ring into the buffer at the cursor.
+.TP
+.B yank\-pop (M\-y)
+Rotate the kill\-ring, and yank the new top.  Only works following
+.B yank
+or
+.BR yank\-pop .
+.PD
+.SS Numeric Arguments
+.PP
+.PD 0
+.TP
+.B digit\-argument (M\-0, M\-1, ..., M\-\-)
+Add this digit to the argument already accumulating, or start a new
+argument.  M\-\- starts a negative argument.
+.TP
+.B universal\-argument
+Each time this is executed, the argument count is multiplied by four.
+The argument count is initially one, so executing this function the
+first time makes the argument count four.  By default, this is not
+bound to a key.
+.PD
+.SS Completing
+.PP
+.PD 0
+.TP
+.B complete (TAB)
+Attempt to perform completion on the text before point.
+.B Bash
+attempts completion treating the text as a variable (if the
+text begins with \fB$\fP), username (if the text begins with
+\fB~\fP), hostname (if the text begins with \fB@\fP), or
+command (including aliases and functions) in turn.  If none
+of these produces a match, filename completion is attempted.
+.TP
+.B possible\-completions (M-?)
+List the possible completions of the text before point.
+.TP
+.B insert\-completions
+Insert all completions of the text before point
+that would have been generated by
+\fBpossible\-completions\fP.  By default, this
+is not bound to a key.
+.TP
+.B complete\-filename (M\-/)
+Attempt filename completion on the text before point.
+.TP
+.B possible\-filename\-completions (C\-x /)
+List the possible completions of the text before point,
+treating it as a filename.
+.TP
+.B complete\-username (M\-~)
+Attempt completion on the text before point, treating
+it as a username.
+.TP
+.B possible\-username\-completions (C\-x ~)
+List the possible completions of the text before point,
+treating it as a username.
+.TP
+.B complete\-variable (M\-$)
+Attempt completion on the text before point, treating
+it as a shell variable.
+.TP
+.B possible\-variable\-completions (C\-x $)
+List the possible completions of the text before point,
+treating it as a shell variable.
+.TP
+.B complete\-hostname (M\-@)
+Attempt completion on the text before point, treating
+it as a hostname.
+.TP
+.B possible\-hostname\-completions (C\-x @)
+List the possible completions of the text before point,
+treating it as a hostname.
+.TP
+.B complete\-command (M\-!)
+Attempt completion on the text before point, treating
+it as a command name.  Command completion attempts to
+match the text against aliases, reserved words, shell
+functions, builtins, and finally executable filenames,
+in that order.
+.TP
+.B possible\-command\-completions (C\-x !)
+List the possible completions of the text before point,
+treating it as a command name.
+.TP
+.B dynamic\-complete\-history (M-TAB)
+Attempt completion on the text before point, comparing
+the text against lines from the history list for possible
+completion matches.
+.TP
+.B complete\-into\-braces (M\-{)
+Perform filename completion and return the list of possible completions
+enclosed within braces so the list is available to the shell (see
+.B Brace Expansion
+above).
+.PD
+.SS Keyboard Macros
+.PP
+.PD 0
+.TP
+.B start\-kbd\-macro (C-x (\^)
+Begin saving the characters typed into the current keyboard macro.
+.TP
+.B end\-kbd\-macro (C-x )\^)
+Stop saving the characters typed into the current keyboard macro
+and save the definition.
+.TP
+.B call\-last\-kbd\-macro (C-x e)
+Re-execute the last keyboard macro defined, by making the characters
+in the macro appear as if typed at the keyboard.
+.PD
+.SS Miscellaneous
+.PP
+.PD 0
+.TP
+.B re\-read\-init\-file (C\-x C\-r)
+Read in the contents of your init file, and incorporate
+any bindings or variable assignments found there.
+.TP
+.B abort (C\-g)
+Abort the current editing command and
+ring the terminal's bell (subject to the setting of
+.BR bell\-style ).
+.TP
+.B do\-uppercase\-version (M\-a, M\-b, ...)
+Run the command that is bound to the corresponding uppercase
+character.
+.TP
+.B prefix\-meta (ESC)
+Metafy the next character typed.
+.SM
+.B ESC
+.B f
+is equivalent to
+.BR Meta\-f .
+.TP
+.B undo (C\-_, C\-x C\-u)
+Incremental undo, separately remembered for each line.
+.TP
+.B revert\-line (M\-r)
+Undo all changes made to this line.  This is like typing the
+.B undo
+command enough times to return the line to its initial state.
+.TP
+.B tilde\-expand (M\-~)
+Perform tilde expansion on the current word.
+.TP
+.B dump\-functions
+Print all of the functions and their key bindings to the
+readline output stream.  If a numeric argument is supplied,
+the output is formatted in such a way that it can be made part
+of an \fIinputrc\fP file.
+.TP
+.B display\-shell\-version (C\-x C\-v)
+Display version information about the current instance of
+.BR bash .
+.PD
+.SH HISTORY
+When interactive, the shell provides access to the \fIcommand history\fP,
+the list of commands previously typed.  The text of the last
+.SM
+.B HISTSIZE
+commands (default 500) is saved in a history list.  The shell
+stores each command in the history list prior to parameter and
+variable expansion (see
+.SM
+.B EXPANSION
+above) but after history expansion is performed, subject to the
+values of the shell variables
+.B command_oriented_history
+and
+.SM
+.BR HISTCONTROL .
+On startup, the history is initialized from the file named by
+the variable
+.SM
+.B HISTFILE
+(default \fI~/.bash_history\fP).
+.SM
+.B HISTFILE
+is truncated, if necessary, to contain no more than
+.SM
+.B HISTFILESIZE
+lines.
+The builtin command
+.B fc
+(see
+.SM
+.B SHELL BUILTIN COMMANDS
+below) may be used to list or edit and re-execute a portion of
+the history list.
+The
+.B history
+builtin can be used to display the history list and manipulate the
+history file.  When using the command-line editing, search commands
+are available in each editing mode that provide access to the
+history list.  When an interactive shell exits, the last
+.SM
+.B HISTSIZE
+lines are copied from the history list to
+.SM
+.BR HISTFILE .
+If
+.SM
+.B HISTFILE
+is unset, or if the history file is unwritable, the history is
+not saved.
+.SH "HISTORY EXPANSION"
+.PP
+The shell supports a history expansion feature that
+is similar to the history expansion in
+.BR csh.
+This section describes what syntax features are available.  This
+feature is enabled by default for interactive shells, and can be
+disabled using the
+.B \+H
+option to the
+.B set
+builtin command (see
+.SM
+.B SHELL BUILTIN COMMANDS
+below).  Non-interactive shells do not perform history expansion.
+.PP
+History expansion is performed immediately after a complete line
+is read, before the shell breaks it into words.
+It takes place in two parts.  The first is to determine
+which line from the previous history to use during
+substitution.  The second is to select portions of that line for
+inclusion into the current one.  The line selected from the
+previous history is the \fIevent\fP, and the portions of that
+line that are acted upon are \fIwords\fP.  The line is broken
+into words in the same fashion as when reading input, so that
+several \fImetacharacter\fP\-separated words surrounded by quotes
+are considered as one word.  Only backslash (\^\fB\e\fP\^)
+and single quotes can quote
+the history escape character, which is \^\fB!\fP\^ by default.
+.PP
+The shell allows control of the various characters used by the
+history expansion mechanism (see the description of
+.B histchars
+above under
+.BR "Shell Variables" ).
+.SS Event Designators
+.PP
+An event designator is a reference to a command line entry in the
+history list.
+.PP
+.PD 0
+.TP
+.B !
+Start a history substitution, except when followed by a
+.BR blank ,
+newline, = or (.
+.TP
+.B !!
+Refer to the previous command.  This is a synonym for `!\-1'.
+.TP
+.B !\fIn\fR
+Refer to command line
+.IR n .
+.TP
+.B !\-\fIn\fR
+Refer to the current command line minus
+.IR n .
+.TP
+.B !\fIstring\fR
+Refer to the most recent command starting with 
+.IR string .
+.TP
+.B !?\fIstring\fR\fB[?]\fR
+Refer to the most recent command containing
+.IR string .
+.TP
+.B \d\s+2^\s-2\u\fIstring1\fP\d\s+2^\s-2\u\fIstring2\fP\d\s+2^\s-2\u
+Quick substitution.  Repeat the last command, replacing
+.I string1
+with
+.IR string2 .
+Equivalent to
+``!!:s/\fIstring1\fP/\fIstring2\fP/''
+(see \fBModifiers\fP below).
+.TP
+.B !#
+The entire command line typed so far.
+.PD
+.SS Word Designators
+.PP
+A 
+.B :
+separates the event specification from the word
+designator.  It can be omitted if the word designator begins with a
+.BR ^ ,
+.BR $ ,
+.BR * ,
+or
+.BR % .
+Words are numbered from the beginning of the line,
+with the first word being denoted by a 0 (zero).
+.PP
+.PD 0
+.TP
+.B 0 (zero)
+The zeroth word.  For the shell, this is the command
+word.
+.TP
+.I n
+The \fIn\fRth word.
+.TP
+.B ^
+The first argument.  That is, word 1.
+.TP
+.B $
+The last argument.
+.TP
+.B %
+The word matched by the most recent `?\fIstring\fR?' search.
+.TP
+.I x\fB\-\fPy
+A range of words; `\-\fIy\fR' abbreviates `0\-\fIy\fR'.
+.TP
+.B *
+All of the words but the zeroth.  This is a synonym
+for `\fI1\-$\fP'.  It is not an error to use
+.B *
+if there is just one
+word in the event; the empty string is returned in that case.
+.TP
+.B x*
+Abbreviates \fIx\-$\fP.
+.TP
+.B x\-
+Abbreviates \fIx\-$\fP like \fBx*\fP, but omits the last word.
+.PD
+.SS Modifiers
+.PP
+After the optional word designator, you can add a sequence of one
+or more of the following modifiers, each preceded by a `:'.
+.PP
+.PD 0
+.PP
+.TP
+.B h
+Remove a trailing pathname component, leaving only the head.
+.TP
+.B r
+Remove a trailing suffix of the form \fI.xxx\fP, leaving the
+basename.
+.TP
+.B e
+Remove all but the trailing suffix.
+.TP
+.B t
+Remove all leading pathname components, leaving the tail.
+.TP
+.B p
+Print the new command but do not execute it.
+.TP
+.B q
+Quote the substituted words, escaping further substitutions.
+.TP
+.B x
+Quote the substituted words as with
+.BR q ,
+but break into words at
+.B blanks
+and newlines.
+.TP
+.B s/\fIold\fP/\fInew\fP/
+Substitute
+.I new
+for the first occurrence of
+.I old
+in the event line.  Any delimiter can be used in place of /.  The
+final delimiter is optional if it is the last character of the
+event line.  The delimiter may be quoted in
+.I old
+and
+.I new
+with a single backslash.  If & appears in
+.IR new ,
+it is replaced by
+.IR old .
+A single backslash will quote the &.
+.TP
+.B &
+Repeat the previous substitution.
+.TP
+.B g
+Cause changes to be applied over the entire event line.  This is
+used in conjunction with `\fB:s\fP' (e.g., `\fB:gs/\fIold\fP/\fInew\fP/\fR')
+or `\fB:&\fP'.  If used with
+`\fB:s\fP', any delimiter can be used
+in place of /, and the final delimiter is optional
+if it is the last character of the event line.
+.PD
+.SH "ARITHMETIC EVALUATION"
+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, 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.
+.PP
+.PD 0
+.TP
+.B \- +
+unary minus and plus
+.TP
+.B ! ~
+logical and bitwise negation
+.TP
+.B * / %
+multiplication, division, remainder
+.TP
+.B + \-
+addition, subtraction
+.TP
+.B << >>
+left and right bitwise shifts
+.TP
+.B <= >= < >
+comparison
+.TP
+.B == !=
+equality and inequality
+.TP
+.B &
+bitwise AND
+.TP
+.B ^
+bitwise exclusive OR
+.TP
+.B |
+bitwise OR
+.TP
+.B &&
+logical AND
+.TP
+.B ||
+logical OR
+.TP
+.B = *= /= %= += \-= <<= >>= &= ^= |=
+assignment
+.PD
+.PP
+Shell variables are allowed as operands; parameter expansion is
+performed before the expression is evaluated. 
+The value of a parameter is coerced to a long integer within
+an expression.  A shell variable need not have its integer attribute
+turned on to be used in an expression.
+.PP
+Constants with a leading 0 are interpreted as octal numbers.
+A leading \fI0x\fP or \fI0X\fP denotes hexadecimal.  Otherwise,
+numbers take the form [\fIbase#\fP]n, where \fIbase\fP is a
+decimal number between 2 and 36 representing the arithmetic
+base, and \fIn\fP is a number in that base.  If \fIbase\fP is
+omitted, then base 10 is used.
+.PP
+Operators are evaluated in order of precedence.  Sub-expressions in
+parentheses are evaluated first and may override the precedence
+rules above.
+.SH "SHELL BUILTIN COMMANDS"
+.\" start of bash_builtins
+.zZ
+.PD 0
+.TP
+\fB:\fP [\fIarguments\fP]
+.PD
+No effect; the command does nothing beyond expanding
+.I arguments
+and performing any specified
+redirections.  A zero exit code is returned.
+.TP
+.PD 0
+\fB .\| \fP \fIfilename\fP [\fIarguments\fP]
+.TP
+\fBsource\fP \fIfilename\fP [\fIarguments\fP]
+.PD
+Read and execute commands from
+.I filename
+in the current
+shell environment and return the exit status of the last command
+executed from
+.IR filename .
+If
+.I filename
+does not contain a slash, pathnames in
+.SM
+.B PATH
+are used to find the directory containing
+.IR filename .
+The file searched for in
+.SM
+.B PATH
+need not be executable.  The current directory is
+searched if no file is found in
+.SM
+.BR PATH .
+If any \fIarguments\fP are supplied, they become the positional
+parameters when \fIfile\fP is executed.  Otherwise the positional
+parameters are unchanged.
+The return status is the status of the last command exited within
+the script (0 if no commands are executed), and false if
+.I filename
+is not found.
+.TP
+\fBalias\fP [\fIname\fP[=\fIvalue\fP] ...]
+\fBAlias\fP with no arguments prints the list of aliases in the form
+\fIname\fP=\fIvalue\fP on standard output.  When arguments are
+supplied, an alias is defined for
+each \fIname\fP
+whose \fIvalue\fP is given.  A trailing space in 
+\fIvalue\fP causes the next
+word to be checked for alias substitution when the alias is
+expanded.  For each \fIname\fP in the argument list for which
+no \fIvalue\fP is supplied, the name and value of the alias is
+printed.  \fBAlias\fP returns true
+unless a \fIname\fP is given for which no alias has been defined.
+.TP
+\fBbg\fP [\fIjobspec\fP]
+Place \fIjobspec\fP in the background, as if it had been started with
+.BR & .
+If \fIjobspec\fP is not present, the shell's notion of the
+\fIcurrent job\fP is used.
+.B bg
+.I jobspec
+returns 0 unless run when job control is disabled or, when run with
+job control enabled, if \fIjobspec\fP was not found or started without
+job control.
+.TP
+.PD 0
+\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lvd\fP] [\fB-q\fP \fIname\fP]
+.TP
+\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fB-f\fP \fIfilename\fP
+.TP
+\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fIkeyseq\fP:\fIfunction-name\fP
+.PD
+Display current
+.B readline
+key and function bindings, or bind a key sequence to a
+.B readline
+function or macro.  The binding syntax accepted is identical to that of
+.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:
+.RS
+.PD 0
+.TP
+.B \-m \fIkeymap\fP
+Use
+.I keymap
+as the keymap to be affected by the subsequent bindings.
+Acceptable
+.I keymap
+names are
+\fIemacs, emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,
+vi-command\fP, and
+.IR vi-insert .
+\fIvi\fP is equivalent to \fIvi-command\fP; \fIemacs\fP is
+equivalent to \fIemacs-standard\fP.
+.TP
+.B \-l
+List the names of all \fBreadline\fP functions
+.TP
+.B \-v
+List current function names and bindings
+.TP
+.B \-d
+Dump function names and bindings in such a way that they can be re-read
+.TP
+.B \-f \fIfilename\fP
+Read key bindings from \fIfilename\fP
+.TP
+.B \-q \fIfunction\fP
+Query about which keys invoke the named \fIfunction\fP
+.PD
+.PP
+The return value is 0 unless an unrecognized option is given or an
+error occurred.
+.RE
+.TP
+\fBbreak\fP [\fIn\fP]
+Exit from within a
+.BR for ,
+.BR while ,
+or
+.B until
+loop.  If \fIn\fP is specified, break \fIn\fP levels.
+.I n
+must be \(>= 1.  If
+.I n
+is greater than the number of enclosing loops, all enclosing loops
+are exited.  The return value is 0 unless the shell is not executing
+a loop when
+.B break
+is executed.
+.TP
+\fBbuiltin\fP \fIshell\-builtin\fP [\fIarguments\fP]
+Execute the specified shell builtin, passing it
+.IR arguments ,
+and return its exit status.
+This is useful when you wish to define a
+function whose name is the same as a shell builtin,
+but need the functionality of the
+builtin within the function itself.  The \fBcd\fP builtin is
+commonly redefined this way.  The return status is false if
+.I shell\-builtin
+is not a shell builtin command.
+.TP
+\fBcd\fP [\fIdir\fP]
+Change the current directory to \fIdir\fP.  The variable
+.SM
+.B HOME
+is the
+default
+.IR dir .
+The variable
+.SM
+.B CDPATH
+defines the search path for
+the directory containing
+.IR dir .
+Alternative directory names are
+separated by a colon (:).  A null directory name in
+.SM
+.B CDPATH
+is the same as
+the current directory, i.e., ``\fB.\fP''.  If
+.I dir
+begins with a slash (/),
+then
+.SM
+.B CDPATH
+is not used.  An argument of
+.B \-
+is equivalent to
+.SM
+.BR $OLDPWD .
+The return value is true if the directory was successfully changed;
+false otherwise.
+.TP
+\fBcommand\fP [\fB-pVv\fP] \fIcommand\fP [\fIarg\fP ...]
+Run
+.I command
+with
+.I args
+suppressing the normal shell function lookup. Only builtin
+commands or commands found in the
+.SM
+.B PATH
+are executed.  If the
+.B \-p
+option is given, the search for
+.I command
+is performed using a default value for
+.B PATH
+that is guaranteed to find all of the standard utilities.
+If either the
+.B \-V
+or
+.B \-v
+option is supplied, a description of
+.I command
+is printed.  The
+.B \-v
+option causes a single word indicating the command or pathname
+used to invoke
+.I command
+to be printed; the
+.B \-V
+option produces a more verbose description.
+An argument of
+.B \-\-
+disables option checking for the rest of the arguments.
+If the
+.B \-V
+or
+.B \-v
+option is supplied, the exit status is 0 if
+.I command
+was found, and 1 if not.  If neither option is supplied and
+an error occurred or
+.I command
+cannot be found, the exit status is 127.  Otherwise, the exit status of the
+.B command
+builtin is the exit status of
+.IR command .
+.TP
+\fBcontinue\fP [\fIn\fP]
+Resume the next iteration of the enclosing
+.BR for ,
+.BR while ,
+or
+.B until
+loop.
+If
+.I n
+is specified, resume at the \fIn\fPth enclosing loop.
+.I n
+must be \(>= 1.  If
+.I n
+is greater than the number of enclosing loops, the last enclosing loop
+(the `top\-level' loop) is resumed.  The return value is 0 unless the
+shell is not executing a loop when
+.B continue
+is executed.
+.TP
+.PD 0
+\fBdeclare\fP [\fB\-frxi\fP] [\fIname\fP[=\fIvalue\fP]]
+.TP
+\fBtypeset\fP [\fB\-frxi\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 instead.  The options can
+be used to restrict output to variables with the specified attribute.
+.RS
+.PD 0
+.TP
+.B \-f
+Use function names only
+.TP
+.B \-r
+Make \fIname\fPs readonly.  These names cannot then be assigned values
+by subsequent assignment statements.
+.TP
+.B \-x
+Mark \fIname\fPs for export to subsequent commands via the environment.
+.TP
+.B \-i
+The variable is treated as an integer; arithmetic evaluation (see
+.SM
+.B "ARITHMETIC EVALUATION" ") "
+is performed when the variable is assigned a value.
+.PD
+.PP
+Using `+' instead of `\-'
+turns off the attribute instead.  When used in a function, makes
+\fIname\fPs local, as with the 
+.B local
+command.  The return value is 0 unless an illegal option is encountered,
+an attempt is made to define a function using "-f foo=bar",
+one of the \fInames\fP is not a legal shell variable name,
+an attempt is made to turn off readonly status for a readonly variable,
+or an attempt is made to display a non-existant function with -f.
+.RE
+.TP
+.B dirs [\fB-l\fP] [\fB+/\-n\fP]
+Display the list of currently remembered directories.  Directories
+are added to the list with the 
+.B pushd
+command; the
+.B popd
+command moves back up through the list.
+.RS
+.PD 0
+.TP
+.B +n
+displays the \fIn\fPth entry counting from the left of the list
+shown by
+.B dirs
+when invoked without options, starting with zero.
+.TP
+.B \-n
+displays the \fIn\fPth entry counting from the right of the list
+shown by
+.B dirs
+when invoked without options, starting with zero.
+.TP
+.B \-l
+produces a longer listing; the default listing format uses a 
+tilde to denote the home directory.
+.PD
+.PP
+The return value is 0 unless an
+illegal option is supplied or \fIn\fP indexes beyond the end
+of the directory stack.
+.RE
+.TP
+\fBecho\fP [\fB\-neE\fP] [\fIarg\fP ...]
+Output the \fIarg\fPs, separated by spaces.  The return status is
+always 0.  If \fB\-n\fP is specified, the trailing newline is
+suppressed.  If the \fB\-e\fP option is given, interpretation of
+the following backslash-escaped characters is enabled.  The
+.B \-E
+option disables the interpretation of these escape characters,
+even on systems where they are interpreted by default.
+.RS
+.PD 0
+.TP
+.B \ea
+alert (bell)
+.TP
+.B \eb
+backspace
+.TP
+.B \ec
+suppress trailing newline
+.TP
+.B \ef
+form feed
+.TP
+.B \en
+new line
+.TP
+.B \er
+carriage return
+.TP
+.B \et
+horizontal tab
+.TP
+.B \ev
+vertical tab
+.TP
+.B \e\e
+backslash
+.TP
+.B \ennn
+the character whose ASCII code is \fInnn\fP (octal)
+.PD
+.RE
+.TP
+\fBenable\fP [\fB\-n\fP] [\fB\-all\fP] [\fIname\fP ...]
+Enable and disable builtin shell commands.  This allows
+the execution of a disk command which has the same name as a shell
+builtin without specifying a full pathname.
+If \fB\-n\fP is used, each \fIname\fP
+is disabled; otherwise,
+\fInames\fP are enabled.  For example, to use the
+.B test
+binary found via the
+.SM
+.B PATH
+instead of the shell builtin version, type
+``enable -n test''.  If no arguments are given,
+a list of all enabled shell builtins is printed.
+If only \fB\-n\fP is supplied, a list of all disabled
+builtins is printed.  If only \fB\-all\fP is supplied,
+the list printed includes all builtins, with an
+indication of whether or not each is enabled.
+.B enable
+accepts
+.B \-a
+as a synonym for
+.BR \-all .
+The return value is 0 unless a
+.I name
+is not a shell builtin.
+.TP
+\fBeval\fP [\fIarg\fP ...]
+The \fIarg\fPs are read and concatenated together into a single
+command.  This command is then read and executed by the shell, and
+its exit status is returned as the value of the
+.B eval
+command.  If there are no
+.IR args ,
+or only null arguments,
+.B eval
+returns true.
+.TP
+\fBexec\fP [[\fB\-\fP] \fIcommand\fP [\fIarguments\fP]]
+If
+.I command
+is specified, it replaces the shell.
+No new process is created.  The
+.I arguments
+become the arguments to \fIcommand\fP.
+If the first argument is 
+.BR \- ,
+the shell places a dash in the zeroth arg passed to 
+.IR command .
+This is what login does.  If the file
+cannot be executed for some reason, a non-interactive shell exits,
+unless the shell variable \fBno_exit_on_failed_exec\fP exists, in
+which case it returns failure.  An interactive shell returns failure
+if the file cannot be executed.
+If
+.I command
+is not specified, any redirections take effect in the current shell,
+and the return status is 0.
+.TP
+\fBexit\fP [\fIn\fP]
+Cause the shell to exit
+with a status of \fIn\fP.  If
+.I n
+is omitted, the exit status
+is that of the last command executed.
+A trap on
+.SM
+.B EXIT
+is executed before the shell terminates.
+.TP
+.PD 0
+\fBexport\fP [\fB\-nf\fP\^] [\fIname\fP[=\fIword\fP]] ...
+.TP
+.B export \-p
+.PD
+The supplied
+.I names
+are marked for automatic export to the environment of
+subsequently executed commands.  If the 
+.B \-f
+option is given,
+the 
+.I names
+refer to functions.
+If no
+.I names
+are given, or if the
+.B \-p
+option is supplied, a list
+of all names that are exported in this shell is printed.
+The
+.B \-n
+option causes the export property to be removed from the
+named variables.  An argument of
+.B \-\-
+disables option checking for the rest of the arguments.
+.B export
+returns an exit status of 0 unless an illegal option is
+encountered,
+one of the \fInames\fP is not a legal shell variable name, or
+.B \-f
+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]
+.TP
+\fBfc\fP \fB\-s\fP [\fIpat\fP=\fIrep\fP] [\fIcmd\fP]
+.PD
+Fix Command.  In the first form, a range of commands from
+.I first
+to
+.I last
+is selected from the history list.
+.I First
+and
+.I last
+may be specified as a string (to locate the last command beginning
+with that string) or as a number (an index into the history list,
+where a negative number is used as an offset from the current
+command number).  If 
+.I last
+is not specified it is set to
+the current command for listing (so that
+.B fc \-l \-10
+prints the last 10 commands) and to
+.I first
+otherwise.
+If
+.I first
+is not specified it is set to the previous
+command for editing and \-16 for listing.
+.sp 1
+The
+.B \-n
+flag suppresses
+the command numbers when listing.  The
+.B \-r
+flag reverses the order of
+the commands.  If the
+.B \-l
+flag is given,
+the commands are listed on
+standard output.  Otherwise, the editor given by
+.I ename
+is invoked
+on a file containing those commands.  If
+.I ename
+is not given, the
+value of the
+.SM
+.B FCEDIT
+variable is used, and
+the value of
+.SM
+.B EDITOR
+if
+.SM
+.B FCEDIT
+is not set.  If neither variable is set,
+.FN vi
+is used.  When editing is complete, the edited commands are
+echoed and executed.
+.sp 1
+In the second form, \fIcommand\fP is re-executed after each instance
+of \fIpat\fP is replaced by \fIrep\fP.
+A useful alias to use with this is ``r=fc \-s'',
+so that typing ``r cc''
+runs the last command beginning with ``cc'' and typing ``r''
+re-executes the last command.
+.sp 1
+If the first form is used, the return value is 0 unless an illegal
+option is encountered or
+.I first
+or
+.I last
+specify history lines out of range.
+If the
+.B \-e
+option is supplied, the return value is the value of the last
+command executed or failure if an error occurs with the temporary
+file of commands.  If the second form is used, the return status
+is that of the command re-executed, unless
+.I cmd
+does not specify a valid history line, in which case
+.B fc
+returns failure.
+.TP
+\fBfg\fP [\fIjobspec\fP]
+Place
+.I jobspec
+in the foreground, and make it the current job.  If
+.I jobspec
+is not present, the shell's notion of the \fIcurrent job\fP is used.
+The return value is that of the command placed into the foreground,
+or failure if run when job control is disabled or, when run with
+job control enabled, if
+.I jobspec
+does not specify a valid job or
+.I jobspec
+specifies a job that was started without job control.
+.TP
+\fBgetopts\fP \fIoptstring\fP \fIname\fP [\fIargs\fP]
+.B getopts
+is used by shell procedures to parse positional parameters.
+.I optstring
+contains the option letters to be recognized; if a letter
+is followed by a colon, the option is expected to have an
+argument, which should be separated from it by white space.
+Each time it is invoked,
+.B getopts
+places the next option in the shell variable
+.IR name ,
+initializing
+.I name
+if it does not exist,
+and the index of the next argument to be processed into the
+variable
+.SM
+.BR OPTIND .
+.SM
+.B OPTIND
+is initialized to 1 each time the shell or a shell script
+is invoked.  When an option requires an argument,
+.B getopts
+places that argument into the variable
+.SM
+.BR OPTARG .
+The shell does not reset
+.SM
+.B OPTIND
+automatically; it must be manually reset between multiple
+calls to
+.B getopts
+within the same shell invocation if a new set of parameters
+is to be used.
+.sp 1
+.B getopts
+can report errors in two ways.  If the first character of
+.I optstring
+is a colon,
+.I silent
+error reporting is used.  In normal operation diagnostic messages
+are printed when illegal options or missing option arguments are
+encountered.
+If the variable
+.SM
+.B OPTERR
+is set to 0, no error message will be displayed, even if the first
+character of 
+.I optstring
+is not a colon.
+.sp 1
+If an illegal option is seen,
+.B getopts
+places ? into
+.I name
+and, if not silent,
+prints an error message and unsets
+.SM
+.BR OPTARG .
+If
+.B getopts
+is silent,
+the option character found is placed in
+.SM
+.B OPTARG
+and no diagnostic message is printed.
+.sp 1
+If a required argument is not found, and
+.B getopts
+is not silent,
+a question mark (\^\fB?\fP\^) is placed in
+.IR name ,
+.B OPTARG
+is unset, and a diagnostic message is printed.
+If
+.B getopts
+is silent, then a colon (\^\fB:\fP\^) is placed in
+.I name
+and
+.SM
+.B OPTARG
+is set to the option character found.
+.sp 1
+.B getopts
+normally parses the positional parameters, but if more arguments are
+given in
+.IR args ,
+.B getopts
+parses those instead.
+.B getopts
+returns true if an option, specified or unspecified, is found.
+It returns false if the end of options is encountered or an
+error occurs.
+.TP
+\fBhash\fP [\fB\-r\fP] [\fIname\fP]
+For each
+.IR name ,
+the full pathname of the command is determined
+and remembered.  The
+.B \-r
+option causes the shell to forget all
+remembered locations.  If no arguments are given, information
+about remembered commands is printed.
+An argument of
+.B \-\-
+disables option checking for the rest of the arguments.  The return
+status is true unless a
+.I name
+is not found or an illegal option is supplied.
+.TP
+\fBhelp\fP [\fIpattern\fP]
+Display helpful information about builtin commands.  If
+.I pattern
+is specified,
+.B help
+gives detailed help on all commands matching
+.IR pattern ;
+otherwise a list of the builtins is printed.  The return status is 0
+unless no command matches
+.IR pattern .
+.TP
+.PD 0
+\fBhistory\fP [\fIn\fP]
+.TP
+\fBhistory\fP \fB\-rwan\fP [\fIfilename\fP]
+.\".TP
+.\"\fBhistory\fP \fB\-s\fP \fIargs\fP
+.PD
+With no options, display the command
+history list with line numbers.  Lines listed
+with a 
+.B *
+have been modified.  An argument of
+.I n
+lists only the last
+.I n
+lines.  If a non-option argument is supplied, it is used as the
+name of the history file; if not, the value of
+.SM
+.B HISTFILE
+is used.  Options, if supplied, have the following meanings:
+.RS
+.PD 0
+.TP
+.B \-a
+Append the ``new'' history lines (history lines entered since the
+beginning of the current \fBbash\fP session) to the history file
+.TP
+.B \-n
+Read the history lines not already read from the history
+file into the current history list.  These are lines
+appended to the history file since the beginning of the
+current \fBbash\fP session.
+.TP
+.B \-r
+Read the contents of the history file
+and use them as the current history
+.TP
+.B \-w
+Write the current history to the history file, overwriting the
+history file's contents.
+.\".TP
+.\".B \-s
+.\"perform history
+.\"substitution on the following \fIargs\fP and display
+.\"the result on the standard output.
+.PD
+.PP
+The return value is 0 unless an illegal option is encountered or an
+error occurs while reading or writing the history file.
+.RE
+.TP
+.PD 0
+\fBjobs\fP [\fB\-lnp\fP] [ \fIjobspec\fP ... ]
+.TP
+\fBjobs\fP \fB\-x\fP \fIcommand\fP [ \fIargs\fP ... ]
+.PD
+The first form lists the active jobs.  The
+.B \-l
+option lists process IDs
+in addition to the normal information; the
+.B \-p
+option lists only the process ID of the job's process group
+leader.  The
+.B \-n
+option displays only jobs that have changed status since
+last notified.  If
+.I jobspec
+is given, output is restricted to information about that job.
+The return status is 0 unless an illegal option is encountered
+or an illegal
+.I jobspec
+is supplied.
+.sp 1
+If the
+.B \-x
+option is supplied,
+.B jobs
+replaces any
+.I jobspec
+found in
+.I command
+or
+.I args
+with the corresponding process group ID, and executes
+.I command
+passing it
+.IR args ,
+returning its exit status.
+.TP
+.PD 0
+\fBkill\fP [\fB-s sigspec\fP | \fB\-sigspec\fP] [\fIpid\fP | \fIjobspec\fP] ...
+.TP
+\fBkill\fP \fB\-l\fP [\fIsignum\fP]
+.PD
+Send the signal named by
+.I sigspec
+to the processes named by
+.I pid
+or
+.IR jobspec .
+.I sigspec
+is either a signal name such as
+.SM
+.B SIGKILL
+or a signal number.  If
+.I sigspec
+is a signal name, the name is case insensitive and may be
+given with or without the
+.SM
+.B SIG
+prefix.
+If
+.I sigspec
+is not present, then
+.SM
+.B SIGTERM
+is assumed.  An argument of
+.B \-l
+lists the signal names.  If any arguments are supplied when
+.B \-l
+is given, the names of the specified signals are listed, and
+the return status is 0.
+An argument of
+.B \-\-
+disables option checking for the rest of the arguments.
+.B kill
+returns true if at least one signal was successfully sent, or false
+if an error occurs or an illegal option is encountered.
+.TP
+\fBlet\fP \fIarg\fP [\fIarg\fP ...]
+Each
+.I arg
+is an arithmetic expression to be evaluated (see
+.SM
+.BR "ARITHMETIC EVALUATION" ).
+If the last
+.I arg
+evaluates to 0,
+.B let
+returns 1; 0 is returned otherwise.
+.TP
+\fBlocal\fP [\fIname\fP[=\fIvalue\fP] ...]
+For each argument, create a local variable named
+.IR name ,
+and assign it
+.IR value .
+When
+.B local
+is used within a function, it causes the variable
+.I name
+to have a visible scope restricted to that function and its children.
+With no operands,
+.B local
+writes a list of local variables to the standard output.  It is
+an error to use
+.B local
+when not within a function.  The return status is 0 unless
+.B local
+is used outside a function, or an illegal
+.I name
+is supplied.
+.TP
+.B logout
+Exit a login shell.
+.TP
+\fBpopd\fP [\fB+/\-n\fP]
+Removes entries from the directory stack.  With no arguments,
+removes the top directory from the stack, and performs a
+.B cd
+to the new top directory.
+.RS
+.PD 0
+.TP
+.B +n
+removes the \fIn\fPth entry counting from the left of the list
+shown by
+.BR dirs ,
+starting with zero.  For example: ``popd +0''
+removes the first directory, ``popd +1'' the second.
+.TP
+.B \-n
+removes the \fIn\fPth entry counting from the right of the list
+shown by
+.BR dirs ,
+starting with zero.  For example: ``popd -0''
+removes the last directory, ``popd -1'' the next to last.
+.PD
+.PP
+If the
+.B popd
+command is successful, a 
+.B dirs
+is performed as well, and the return status is 0.
+.B popd
+returns false if an illegal option is encountered, the directory stack
+is empty, a non-existent directory stack entry is specified, or the
+directory change fails.
+.RE
+.TP
+.PD 0
+\fBpushd\fP [\fIdir\fP]
+.TP
+\fBpushd\fP \fB+/\-n\fP
+.PD
+Adds a directory to the top of the directory stack, or rotates
+the stack, making the new top of the stack the current working
+directory.  With no arguments, exchanges the top two directories
+and returns 0, unless the directory stack is empty.
+.RS
+.PD 0
+.TP
+.B +n
+Rotates the stack so that the \fIn\fPth directory
+(counting from the left of the list shown by
+.BR dirs )
+is at the top.
+.TP
+.B \-n
+Rotates the stack so that the \fIn\fPth directory
+(counting from the right) is at the top.
+.TP
+.B dir
+adds
+.I dir
+to the directory stack at the top, making it the
+new current working directory.
+.PD
+.PP
+If the
+.B pushd
+command is successful, a 
+.B dirs
+is performed as well.
+If the first form is used,
+.B pushd
+returns 0 unless the cd to
+.I dir
+fails.  With the second form,
+.B pushd
+returns 0 unless the directory stack is empty,
+a non-existant directory stack element is specified,
+or the directory change to the specified new current directory
+fails.
+.RE
+.TP
+\fBpwd\fP
+Print the absolute pathname of the current working directory.
+The path printed contains no symbolic links if the
+.B \-P
+option to the
+.B set
+builtin command is set.
+See also the description of 
+.B nolinks
+under
+.B Shell Variables
+above).  The return status is 0 unless an error occurs while
+reading the pathname of the current directory.
+.TP
+\fBread\fP [\fB\-r\fP] [\fIname\fP ...]
+One line is read from the standard input, and the first word
+is assigned to the first
+.IR name ,
+the second word to the second
+.IR name ,
+and so on, with leftover words assigned to the last
+.IR name .
+Only the
+characters in 
+.SM
+.B IFS
+are recognized as word delimiters.  If no
+.I names
+are supplied, the line read is assigned to the variable
+.SM
+.BR REPLY .
+The return code is zero, unless end-of-file is encountered.  If the
+.B \-r
+option
+is given, a backslash-newline pair is not ignored, and
+the backslash is considered to be part of the line.
+.TP
+.PD 0
+\fBreadonly\fP [\fB\-f\fP] [\fIname\fP ...]
+.TP
+\fBreadonly -p\fP
+.PD
+The given
+\fInames\fP are marked readonly and the values of these
+\fInames\fP
+may not be changed by subsequent assignment.
+If the
+.B \-f
+option is supplied, the functions corresponding to the
+\fInames\fP are so
+marked.  If no arguments are given, or if the
+.B \-p
+option is supplied, a list of all readonly names
+is printed.
+An argument of
+.B \-\-
+disables option checking for the rest of the arguments.  The
+return status is 0 unless an illegal option is encountered,
+one of the \fInames\fP is not a legal shell variable name, or
+.B \-f
+is supplied with a
+.I name
+that is not a function.
+.TP
+\fBreturn\fP [\fIn\fP]
+Causes a function to exit with the return value specified by
+.IR n .
+If 
+.I n
+is omitted, the return status is that of the last command
+executed in the function body.  If used outside a function,
+but during execution of a script by the 
+.B .
+(\fBsource\fP) command, it causes the shell to stop executing
+that script and return either
+.I n
+or the exit status of the last command executed within the
+script as the exit status of the script.  If used outside a
+function and not during execution of a script by \fB.\fP\^,
+the return status is false.
+.TP
+\fBset\fP [\fB\-\-abefhkmnptuvxldCHP\fP] [\fB-o\fP \fIoption\fP] [\fIarg\fP ...]
+.RS
+.PD 0
+.TP 8
+.B \-a
+Automatically mark variables which are modified or created for export
+to the environment of subsequent commands.
+.TP 8
+.B \-b
+Cause the status of terminated background jobs to be reported
+immediately, rather than before the next primary prompt.
+(Also see
+.B notify
+under
+.B Shell Variables
+above).
+.TP 8
+.B \-e
+Exit immediately if a \fIsimple-command\fP (see
+.SM
+.B SHELL GRAMMAR
+above) exits with a non\-zero status.  The shell does not exit if the
+command that fails is part of an
+.I until
+or
+.I while
+loop,
+part of an
+.I if
+statement, part of a
+.B &&
+or
+.B \(bv\|\(bv
+list, or if the command's return value is
+being inverted via
+.BR ! .
+.TP 8
+.B \-f
+Disable pathname expansion.
+.TP 8 
+.B \-h
+Locate and remember function commands as functions are
+defined.  Function commands are normally looked up when
+the function is executed.
+.TP 8
+.B \-k
+All keyword arguments are placed in the environment for a
+command, not just those that precede the command name.
+.TP 8
+.B \-m
+Monitor mode.  Job control is enabled.  This flag is on
+by default for interactive shells on systems that support
+it (see
+.SM
+.B JOB CONTROL
+above).  Background processes run in a separate process
+group and a line containing their exit status is printed
+upon their completion.
+.TP 8
+.B \-n
+Read commands but do not execute them.  This may be used to 
+check a shell script for syntax errors.  This is ignored for
+interactive shells.
+.TP 8
+.B \-o \fIoption-name\fP
+The \fIoption-name\fP can be one of the following:
+.RS
+.TP 8
+.B allexport
+Same as
+.BR \-a .
+.TP 8
+.B braceexpand
+The shell performs brace expansion (see
+.B Brace Expansion
+above).  This is on by default.
+.TP 8
+.B emacs
+Use an emacs-style command line editing interface.  This is enabled
+by default when the shell is interactive, unless the shell is started
+with the
+.B \-nolineediting
+option.
+.TP 8
+.B errexit
+Same as
+.BR \-e .
+.TP 8
+.B histexpand
+Same as
+.BR \-H .
+.TP 8
+.B ignoreeof
+The effect is as if the shell command `IGNOREEOF=10' had been executed
+(see
+.B Shell Variables
+above).
+.TP 8
+.B interactive\-comments
+Allow a word beginning with
+.B #
+to cause that word and all remaining characters on that
+line to be ignored in an interactive shell (see
+.SM
+.B COMMENTS
+above).
+.TP 8
+.B monitor
+Same as
+.BR \-m .
+.TP 8
+.B noclobber
+Same as
+.BR \-C .
+.TP 8
+.B noexec
+Same as
+.BR \-n .
+.TP 8
+.B noglob
+Same as
+.BR \-f .
+.TP 8
+.B nohash
+Same as
+.BR \-d .
+.TP 8
+.B notify
+Same as
+.BR \-b .
+.TP 8
+.B nounset
+Same as
+.BR \-u .
+.TP 8
+.B physical
+Same as
+.BR \-P .
+.TP 8
+.B posix
+Change the behavior of bash where the default operation differs
+from the Posix 1003.2 standard to match the standard.
+.TP 8
+.B privileged
+Same as
+.BR \-p .
+.TP 8
+.B verbose
+Same as
+.BR \-v .
+.TP 8
+.B vi
+Use a vi-style command line editing interface.
+.TP 8
+.B xtrace
+Same as
+.BR \-x .
+.PP
+If no \fIoption-name\fP is supplied, the values of the current options are
+printed.
+.RE
+.TP 8
+.B \-p
+Turn on
+.I privileged
+mode.  In this mode, the
+.B $ENV
+file is not processed, and shell functions
+are not inherited from the environment.  This is enabled automatically
+on startup if the effective user (group) id is not equal to the real
+user (group) id.  Turning this option off causes the effective user
+and group ids to be set to the real user and group ids.
+.TP 8
+.B \-t
+Exit after reading and executing one command.
+.TP 8
+.B \-u
+Treat unset variables as an error when performing
+parameter expansion.  If expansion is attempted on an
+unset variable, the shell prints an error message, and,
+if not interactive, exits with a non\-zero status.
+.TP 8
+.B \-v
+Print shell input lines as they are read.
+.TP 8
+.B \-x
+After expanding each
+.IR simple-command ,
+.B bash
+displays the expanded value of
+.SM
+.BR PS4 ,
+followed by the command and its expanded arguments.
+.TP 8
+.B \-l
+Save and restore the binding of \fIname\fP in a
+\fBfor\fP \fIname\fP [in \fBword\fP] command (see
+.SM
+.B SHELL GRAMMAR
+above).
+.TP 8
+.B \-d
+Disable the hashing of commands that are looked up for execution.
+Normally, commands are remembered in a hash table, and once
+found, do not have to be looked up again.
+.TP 8
+.B \-C
+The effect is as if the shell command `noclobber=' had been executed
+(see
+.B Shell Variables
+above).
+.TP 8
+.B \-H
+Enable
+.B !
+style history substitution.  This flag is on by
+default when the shell is interactive.
+.TP 8
+.B \-P
+If set, do not follow symbolic links when performing commands such as
+.B cd
+which change the current directory.  The physical directory is
+used instead.
+.TP 8
+.B \-\-
+If no arguments follow this flag, then the positional parameters are
+unset.  Otherwise, the positional parameters are set to the
+\fIarg\fPs, even if some of them begin with a
+.BR \- .
+.TP 8
+.B \-
+Signal the end of options, cause all remaining \fIarg\fPs to be
+assigned to the positional parameters.  The
+.B \-x
+and
+.B \-v
+options are turned off.
+If there are no \fIarg\fPs,
+the positional parameters remain unchanged.
+.PD
+.PP
+The flags are off by default
+unless otherwise noted.
+Using + rather than \- causes these flags
+to be turned off.  The
+flags can also be specified as options to an
+invocation of the shell.  The current
+set of flags may be found in
+.BR $\- .
+After the option arguments are processed,
+the remaining \fIn\fP \fIarg\fPs are treated
+as values for the positional
+parameters and are assigned, in order, to 
+.BR $1 ,
+.BR $2 ,
+.B ...
+.BR $\fIn\fP .
+If no options or \fIarg\fPs are supplied,
+all shell variables are printed.  The return status is always true
+unless an illegal option is encountered.
+.RE
+.TP
+\fBshift\fP [\fIn\fP]
+The positional parameters from \fIn\fP+1 ... are renamed to
+.B $1
+.B ....
+Parameters represented by the numbers \fB$#\fP
+down to \fB$#\fP\-\fIn\fP+1 are unset.
+If
+.I n
+is 0, no parameters are changed.
+If
+.I n 
+is not given, it is assumed to be 1.
+.I n
+must be a non-negative number less than or equal to \fB$#\fP.
+If
+.I n
+is greater than \fB$#\fP, the positional parameters are not changed.
+The return status is greater than 0 if
+.I n
+is greater than
+.B $#
+or less than 0; otherwise 0.
+.TP
+\fBsuspend\fP [\fB\-f\fP]
+Suspend the execution of this shell until it receives a
+.SM
+.B SIGCONT
+signal.  The
+.B \-f
+option says not to complain if this is 
+a login shell; just suspend anyway.  The return status is 0 unless
+the shell is a login shell and
+.B \-f
+is not supplied, or if job control is not enabled.
+.TP
+.PD 0
+\fBtest\fP \fIexpr\fP
+.TP
+\fB[\fP \fIexpr\fP \fB]\fP
+Return a status of 0 (true) or 1 (false) depending on
+the evaluation of the conditional expression
+.IR expr .
+Expressions may be unary or binary.  Unary
+expressions are often used to examine the status of a file.  There
+are string operators and numeric comparison operators as well.  Each
+operator and operand must be a separate argument.  If \fIfile\fP
+is of the form /dev/fd/\fIn\fP, then file descriptor \fIn\fP is
+checked.
+.RS
+.PD 0
+.TP
+.B \-b \fIfile\fP
+True if \fIfile\fP exists and is block special.
+.TP
+.B \-c \fIfile\fP
+True if \fIfile\fP exists and is character special.
+.TP
+.B \-d \fIfile\fP
+True if \fIfile\fP exists and is a directory.
+.TP
+.B \-e \fIfile\fP
+True if \fIfile\fP exists.
+.TP
+.B \-f \fIfile\fP
+True if \fIfile\fP exists and is a regular file.
+.TP
+.B \-g \fIfile\fP
+True if \fIfile\fP exists and is set-group-id.
+.TP
+.B \-k \fIfile\fP
+True if \fIfile\fP has its ``sticky'' bit set.
+.TP
+.B \-L \fIfile\fP
+True if \fIfile\fP exists and is a symbolic link.
+.TP
+.B \-p \fIfile\fP
+True if \fIfile\fP exists and is a named pipe.
+.TP
+.B \-r \fIfile\fP
+True if \fIfile\fP exists and is readable.
+.TP
+.B \-s \fIfile\fP
+True if \fIfile\fP exists and has a size greater than zero.
+.TP
+.B \-S \fIfile\fP
+True if \fIfile\fP exists and is a socket.
+.TP
+.B \-t \fIfd\fP
+True if
+.I fd
+is opened on a terminal.
+.TP
+.B \-u \fIfile\fP
+True if \fIfile\fP exists and its set-user-id bit is set.
+.TP
+.B \-w \fIfile\fP
+True if \fIfile\fP exists and is writable.
+.TP
+.B \-x \fIfile\fP
+True if \fIfile\fP exists and is executable.
+.TP
+.B \-O \fIfile\fP
+True if \fIfile\fP exists and is owned by the effective user id.
+.TP
+.B \-G \fIfile\fP
+True if \fIfile\fP exists and is owned by the effective group id.
+.TP
+\fIfile1\fP \-\fBnt\fP \fIfile2\fP
+True if \fIfile1\fP is newer (according to
+modification date) than \fIfile2\fP.
+.TP
+\fIfile1\fP \-\fBot\fP \fIfile2\fP
+True if \fIfile1\fP is older than file2.
+.TP
+\fIfile1\fP \fB\-ef\fP \fIfile\fP
+True if \fIfile1\fP and \fIfile2\fP have the same device and
+inode numbers.
+.TP
+.B \-z \fIstring\fP
+True if the length of \fIstring\fP is zero.
+.TP
+.B \-n \fIstring\fP
+.TP
+\fIstring\fP
+True if the length of
+.I string
+is non\-zero.
+.TP
+\fIstring1\fP \fB=\fP \fIstring2\fP
+True if the strings are equal.
+.TP
+\fIstring1\fP \fB!=\fP \fIstring2\fP
+True if the strings are not equal.
+.TP
+.B ! \fIexpr\fP
+True if
+.I expr
+is false.
+.TP
+\fIexpr1\fP \-\fBa\fP \fIexpr2\fP
+True if both
+.I expr1
+AND
+.I expr2
+are true.
+.TP
+\fIexpr1\fP \-\fBo\fP \fIexpr2\fP
+True if either
+.I expr1
+OR
+.I expr2
+is true.
+.TP
+.I arg1 \fBOP\fP arg2
+.SM
+.B OP
+is one of
+.BR \-eq ,
+.BR \-ne ,
+.BR \-lt ,
+.BR \-le ,
+.BR \-gt ,
+or
+.BR \-ge .
+These arithmetic binary operators return true if \fIarg1\fP
+is equal, not-equal, less-than, less-than-or-equal,
+greater-than, or greater-than-or-equal than \fIarg2\fP,
+respectively.
+.I Arg1
+and
+.I arg2
+may be positive integers, negative integers, or the special
+expression \fB\-l\fP \fIstring\fP, which evaluates to the
+length of 
+.IR string .
+.PD
+.RE
+.TP
+.B times
+Print the accumulated user and system times for the shell and
+for processes run from the shell.  The return status is 0.
+.TP
+\fBtrap\fP [\fB\-l\fP] [\fIarg\fP] [\fIsigspec\fP]
+The command
+.I arg
+is to be read and executed when the shell receives
+signal(s)
+.IR sigspec .
+If
+.I arg
+is absent or
+.BR \- ,
+all specified signals are
+reset to their original values (the values they had
+upon entrance to the shell).  If 
+.I arg
+is the null string this
+signal is ignored by the shell and by the
+commands it invokes.
+.I sigspec
+is either
+a signal name defined in <\fIsignal.h\fP>, or a signal number. 
+If
+.I sigspec
+is
+.SM
+.B EXIT
+(0) the command
+.I arg
+is executed on exit from
+the shell.  With no arguments,
+.B trap
+prints the list of commands associated with each signal number.
+The 
+.B \-l
+option causes the shell to
+print a list of signal names and their corresponding
+numbers.  An argument of
+.B \-\-
+disables option checking for the rest of the arguments.
+Signals ignored upon entry to the shell cannot be trapped or reset.
+Trapped signals are reset to their original values in a child
+process when it is created.  The return status is false if either
+the trap name or number is invalid; otherwise
+.B trap
+returns true.
+.TP
+\fBtype\fP [\fB\-all\fP] [\fB\-type\fP | \fB\-path\fP] \fIname\fP [\fIname\fP ...]
+With no options, 
+indicate how each
+.I name
+would be interpreted if used as a command name.
+If the
+.B \-type
+flag is used,
+.B type
+prints a phrase which is one of
+.IR alias ,
+.IR keyword ,
+.IR function ,
+.IR builtin ,
+or
+.I file 
+if
+.I name
+is an alias, shell reserved word, function, builtin, or disk file,
+respectively. If the name is not found, then nothing is printed,
+and an exit status of false is returned.
+If the
+.B \-path
+flag is used,
+.B type
+either returns the name of the disk file
+that would be executed if
+.I name
+were specified as a command name,
+or nothing if
+.B \-type
+would not return
+.IR file .
+If a command is hashed,
+.B \-path
+prints the hashed value, not necessarily the file that appears
+first in 
+.SM
+.BR PATH .
+If the
+.B \-all
+flag is used, 
+.B type
+prints all of the places that contain
+an executable named 
+.IR name .
+This includes aliases and functions,
+if and only if the 
+.B \-path
+flag is not also used.
+The table of hashed commands is not consulted
+when using
+.BR \-all .
+.B type
+accepts
+.BR \-a ,
+.BR \-t ,
+and
+.B \-p
+in place of
+.BR \-all ,
+.BR \-type ,
+and
+.BR \-path ,
+respectively.
+An argument of
+.B \-\-
+disables option checking for the rest of the arguments.
+.B type
+returns true if any of the arguments are found, false if
+none are found.
+.TP
+\fBulimit\fP [\fB\-SHacdfmstpnuv\fP [\fIlimit\fP]]
+.B Ulimit
+provides control over the resources available to the shell and to
+processes started by it, on systems that allow such control.  The
+value of
+.I limit
+can be a number in the unit specified for the resource, or the
+value
+.BR unlimited .
+The \fBH\fP and \fBS\fP options specify that the hard or soft limit is
+set for the given resource.  A hard limit cannot be increased once it
+is set; a soft limit may be increased up to the value of the hard limit.
+If neither \fBH\fP nor \fBS\fP is specified, the command applies to the
+soft limit.  If
+.I limit
+is omitted, the current value of the soft limit of the resource is
+printed, unless the \fBH\fP option is given.  When more than one resource
+is specified, the limit name and unit is printed before the value.
+Other options are interpreted as follows:
+.RS
+.PD 0
+.TP
+.B \-a
+all current limits are reported
+.TP
+.B \-c
+the maximum size of core files created
+.TP
+.B \-d
+the maximum size of a process's data segment
+.TP
+.B \-f
+the maximum size of files created by the shell
+.TP
+.B \-m
+the maximum resident set size
+.TP
+.B \-s
+the maximum stack size
+.TP
+.B \-t
+the maximum amount of cpu time in seconds
+.TP
+.B \-p
+the pipe size in 512-byte blocks (this may not be set)
+.TP
+.B \-n
+the maximum number of open file descriptors (most systems do not
+allow this value to be set, only displayed)
+.TP
+.B \-u
+the maximum number of processes available to a single user
+.TP
+.B \-v
+The maximum amount of virtual memory available to the shell
+.PD
+.PP
+An argument of
+.B \-\-
+disables option checking for the rest of the arguments.  If
+.I limit
+is given, it is the new value of the specified resource (the
+.B \-a
+option is display only).
+If no option is given, then
+.B \-f
+is assumed.  Values are in 1024-byte increments, except for
+.BR \-t ,
+which is in seconds,
+.BR \-p ,
+which is in units of 512-byte blocks,
+and
+.B \-n
+and
+.BR \-u ,
+which are unscaled values.  The return status is 0
+unless an illegal option is encountered, a non-numeric argument
+other than \fBunlimited\fP is supplied as \fIlimit\fP, or an
+error occurs while setting a new limit.
+.RE
+.TP
+\fBumask\fP [\fB\-S\fP] [\fImode\fP]
+The user file-creation mask is set to 
+.IR mode .
+If
+.I mode
+begins with a digit, it
+is interpreted as an octal number; otherwise
+it is interpreted as a symbolic mode mask similar
+to that accepted by
+.IR chmod (1).
+If
+.I mode
+is omitted, or if the 
+.B \-S
+option is supplied, the
+current value of the mask is printed.  The
+.B \-S
+option causes the mask to be printed in symbolic form; the
+default output is an octal number.
+An argument of
+.B \-\-
+disables option checking for the rest of the arguments.  The
+return status is 0 if the mode was successfully changed or if
+no \fImode\fP argument was supplied, and false otherwise.
+.TP
+\fBunalias\fP [\-\fBa\fP] [\fIname\fP ...]
+Remove \fIname\fPs from the list of defined aliases.  If
+.B \-a
+is supplied, all alias definitions are removed.  The return
+value is true unless a supplied
+.I name
+is not a defined alias.
+.TP
+\fBunset\fP [\-\fBfv\fP] [\fIname\fP ...]
+For each
+.IR name ,
+remove the corresponding variable or, given the
+.B \-f
+option, function.
+An argument of
+.B \-\-
+disables option checking for the rest of the arguments.
+Note that
+.SM
+.BR PATH ,
+.SM
+.BR IFS ,
+.SM
+.BR PPID ,
+.SM
+.BR PS1 ,
+.SM
+.BR PS2 ,
+.SM
+.BR UID ,
+and
+.SM
+.B EUID
+cannot be unset.  If any of
+.SM
+.BR RANDOM ,
+.SM
+.BR SECONDS ,
+.SM
+.BR LINENO ,
+or
+.SM
+.B HISTCMD
+are unset, they lose their special properties, even if they are
+subsequently reset.  The exit status is true unless a
+.I name
+does not exist or is non-unsettable.
+.TP
+\fBwait\fP [\fIn\fP]
+Wait for the specified process and return its termination
+status.
+.I n
+may be a process
+ID or a job specification; if a job spec is given, all processes
+in that job's pipeline are waited for.  If
+.I n
+is not given, all currently active child processes
+are waited for, and the return status is zero.  If
+.I n
+specifies a non-existant process or job, the return status is
+127.  Otherwise, the return status is the exit status of the last
+process or job waited for.
+.\" bash_builtins
+.if \n(zZ=1 .ig zZ
+.SH INVOCATION
+A \fIlogin shell\fP is one whose first character of argument zero is a
+.BR \- ,
+or one started with the 
+.B \-login
+flag.
+.PP
+An \fIinteractive\fP shell is one whose standard input and output are
+both connected to terminals (as determined by
+.IR isatty (3)),
+or one started with the
+.B \-i
+option.
+.SM
+.B PS1
+is set and
+.B $\-
+includes
+.B i
+if
+.B bash
+is interactive,
+allowing a shell script or a startup file to test this state.
+.PP
+.nf
+Login shells:
+  On login (subject to the \fB\-noprofile\fP option):
+        if \fI/etc/profile\fP exists, source it.
+
+        if \fI~/.bash_profile\fP exists, source it,
+          else if \fI~/.bash_login\fP exists, source it,
+            else if \fI~/.profile\fP exists, source it.
+
+  On exit:
+        if \fI~/.bash_logout\fP exists, source it.
+
+Non-login interactive shells:
+  On startup (subject to the \fB\-norc\fP and \fB\-rcfile\fP options):
+        if \fI~/.bashrc\fP exists, source it.
+
+Non-interactive shells:
+  On startup:
+        if the environment variable \fBENV\fP is non-null, expand
+        it and source the file it names, as if the command
+                if [ "$ENV" ]; then . $ENV; fi
+        had been executed, but do not use \fBPATH\fP to search
+        for the pathname.  When not started in Posix mode, bash
+        looks for \fBBASH_ENV\fP before \fBENV\fP.
+.PP
+.fi
+.PP
+If Bash is invoked as
+.BR sh ,
+it tries to mimic the behavior of
+.B sh
+as closely as possible.  For a login shell, it attempts to
+source only
+.I /etc/profile
+and
+.IR ~/.profile ,
+in that order.  The
+.B \-noprofile
+option may still be used to disable this behavior.
+A shell invoked as 
+.B sh
+does not attempt to source any other startup files.
+.PP
+When
+.B bash 
+is started in
+.I posix
+mode, as with the
+.B \-posix
+command line option, it follows the Posix standard for
+startup files.  In this mode, the
+.B ENV
+variable is expanded and that file sourced; no other startup
+files are read.
+.SH "SEE ALSO"
+.PD 0
+.TP
+\fIBash Features\fP, Brian Fox and Chet Ramey
+.TP
+\fIThe Gnu Readline Library\fP, Brian Fox and Chet Ramey
+.TP
+\fIThe Gnu History Library\fP, Brian Fox and Chet Ramey
+.TP
+\fIA System V Compatible Implementation of 4.2\s-1BSD\s+1 Job Control\fP, David Lennert
+.TP
+\fIPortable Operating System Interface (POSIX) Part 2: Shell and Utilities\fP, IEEE
+.TP
+\fIsh\fP(1), \fIksh\fP(1), \fIcsh\fP(1)
+.TP
+\fIemacs\fP(1), \fIvi\fP(1)
+.TP
+\fIreadline\fP(3)
+.PD
+.SH FILES
+.PD 0
+.TP
+.FN /bin/bash
+The \fBbash\fP executable
+.TP
+.FN /etc/profile
+The systemwide initialization file, executed for login shells
+.TP
+.FN ~/.bash_profile
+The personal initialization file, executed for login shells
+.TP
+.FN ~/.bashrc
+The individual per-interactive-shell startup file
+.TP
+.FN ~/.inputrc
+Individual \fIreadline\fP initialization file
+.PD
+.SH AUTHORS
+.RS
+Brian Fox, Free Software Foundation (primary author)
+.br
+bfox@ai.MIT.Edu
+.PP
+Chet Ramey, Case Western Reserve University
+.br
+chet@ins.CWRU.Edu
+.SH BUG REPORTS
+If you find a bug in
+.B bash,
+you should report it.  But first, you should
+make sure that it really is a bug, and that it appears in the latest
+version of
+.B bash
+that you have.
+.PP
+Once you have determined that a bug actually exists, use the
+.I bashbug
+command to submit a bug report.
+If you have a fix, you are welcome to mail that
+as well!
+Suggestions and `philosophical' bug reports may be mailed
+to \fPbug-bash\fP@\fIprep.ai.MIT.Edu\fP or posted to the Usenet
+newsgroup
+.BR gnu.bash.bug .
+.PP
+ALL bug reports should include:
+.PP
+.PD 0
+.TP 20
+The version number of \fBbash\fR
+.TP
+The hardware and operating system
+.TP
+The compiler used to compile
+.TP
+A description of the bug behaviour
+.TP
+A short script or `recipe' which exercises the bug
+.PD
+.PP
+.I bashbug
+inserts the first three items automatically into the template
+it provides for filing a bug report.
+.PP
+Comments and bug reports concerning
+this manual page should be directed to
+.IR chet@ins.CWRU.Edu .
+.SH BUGS
+.PP
+It's too big and too slow.
+.PP
+There are some subtle differences between 
+.B bash
+and traditional versions of
+.BR sh ,
+mostly because of the
+.SM
+.B POSIX
+specification.
+.PP
+Aliases are confusing in some uses.
+.zZ
diff --git a/documentation/bash.ps b/documentation/bash.ps
new file mode 100644 (file)
index 0000000..c3a4643
--- /dev/null
@@ -0,0 +1,3959 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%+ font Symbol
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 37
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+%%IncludeResource: font Symbol
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Times-Italic@0 ENC0/Times-Italic RE
+/Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 9/Times-Bold@0 SF -.18(NA)72 84 S(ME).18 E F0(bash \255 GNU Bourne\255Ag)
+108 96 Q(ain SHell)-.05 E F1(SYNOPSIS)72 112.8 Q/F2 10/Times-Bold@0 SF(bash)108
+124.8 Q F0([options] [\214le])2.5 E F1(COPYRIGHT)72 141.6 Q F0(Bash is Cop)108
+153.6 Q(yright \251 1989, 1991 by the Free Softw)-.1 E(are F)-.1 E
+(oundation, Inc.)-.15 E F1(DESCRIPTION)72 170.4 Q F2(Bash)108 182.4 Q F0 .796
+(is an)3.296 F F2(sh)3.296 E F0 .795
+(\255compatible command language interpreter that e)B -.15(xe)-.15 G .795
+(cutes commands read from the standard).15 F(input or from a \214le.)108 194.4
+Q F2(Bash)5 E F0(also incorporates useful features from the)2.5 E/F3 10
+/Times-Italic@0 SF -.4(Ko)2.5 G(rn).4 E F0(and)2.5 E F3(C)2.5 E F0(shells \()
+2.5 E F2(ksh)A F0(and)2.5 E F2(csh)2.5 E F0(\).)A F2(Bash)108 211.2 Q F0 .488(\
+is ultimately intended to be a conformant implementation of the IEEE Posix She\
+ll and T)2.988 F .489(ools speci\214-)-.8 F(cation \(IEEE W)108 223.2 Q
+(orking Group 1003.2\).)-.8 E F1(OPTIONS)72 240 Q F0 .366(In addition to the s\
+ingle\255character shell options documented in the description of the)108 252 R
+F2(set)2.866 E F0 -.2(bu)2.866 G .366(iltin command,).2 F F2(bash)108 264 Q F0
+(interprets the follo)2.5 E(wing \215ags when it is in)-.25 E -.2(vo)-.4 G -.1
+(ke).2 G(d:).1 E F2<ad63>108 280.8 Q F3(string)4.166 E F0 .504(If the)158 280.8
+R F2<ad63>3.004 E F0 .505(\215ag is present, then commands are read from)3.004
+F F3(string)3.005 E F0 5.505(.I).22 G 3.005(ft)417.425 280.8 S .505
+(here are ar)426.54 280.8 R .505(guments after the)-.18 F F3(string)158 292.8 Q
+F0 2.5(,t).22 G(he)189.34 292.8 Q 2.5(ya)-.15 G
+(re assigned to the positional parameters, starting with)210.57 292.8 Q F2($0)
+2.5 E F0(.)A F2<ad69>108 304.8 Q F0(If the)158 304.8 Q F2<ad69>2.5 E F0
+(\215ag is present, the shell is)2.5 E F3(inter)2.5 E(active)-.15 E F0(.).18 E
+F2<ad73>108 316.8 Q F0 .305(If the)158 316.8 R F2<ad73>2.805 E F0 .305
+(\215ag is present, or if no ar)2.805 F .305
+(guments remain after option processing, then commands are)-.18 F 1.711
+(read from the standard input.)158 328.8 R 1.711(This option allo)6.711 F 1.712
+(ws the positional parameters to be set when)-.25 F(in)158 340.8 Q -.2(vo)-.4 G
+(king an interacti).2 E .3 -.15(ve s)-.25 H(hell.).15 E F2<ad>108 352.8 Q F0
+3.373(As)158 352.8 S(ingle)172.483 352.8 Q F2<ad>3.373 E F0 .873
+(signals the end of options and disables further option processing.)3.373 F(An)
+5.872 E 3.372(ya)-.15 G -.18(rg)502.96 352.8 S(uments).18 E .044(after the)158
+364.8 R F2<ad>2.544 E F0 .044(are treated as \214lenames and ar)2.544 F 2.544
+(guments. An)-.18 F(ar)2.544 E .044(gument of)-.18 F F2<adad>2.544 E F0 .044
+(is equi)2.544 F -.25(va)-.25 G .045(lent to an ar).25 F(gu-)-.18 E(ment of)158
+376.8 Q F2<ad>2.5 E F0(.)A F2(Bash)108 393.6 Q F0 .15
+(also interprets a number of multi\255character options.)2.65 F .149
+(These options must appear on the command line)5.149 F
+(before the single\255character options to be recognized.)108 405.6 Q F2
+(\255nor)108 422.4 Q(c)-.18 E F0 .282(Do not read and e)158 422.4 R -.15(xe)
+-.15 G .282(cute the personal initialization \214le).15 F F3(~/.bashr)2.782 E
+(c)-.37 E F0 .282(if the shell is interacti)2.782 F -.15(ve)-.25 G 5.282(.T).15
+G(his)528.33 422.4 Q(option is on by def)158 434.4 Q(ault if the shell is in)
+-.1 E -.2(vo)-.4 G -.1(ke).2 G 2.5(da).1 G(s)342.75 434.4 Q F2(sh)2.5 E F0(.)A
+F2(\255nopr)108 446.4 Q(o\214le)-.18 E F0 .223
+(Do not read either the system\255wide startup \214le)6.14 F F3(/etc/pr)4.389 E
+(o\214le)-.45 E F0 .223(or an)4.389 F 2.722(yo)-.15 G 2.722(ft)431.844 446.4 S
+.222(he personal initialization)440.676 446.4 R(\214les)158 458.4 Q F3
+(~/.bash_pr)4.066 E(o\214le)-.45 E F0(,).18 E F3(~/.bash_lo)4.066 E(gin)-.1 E
+F0 4.066(,o).24 G(r)308.408 458.4 Q F3(~/.pr)4.066 E(o\214le)-.45 E F0 6.566
+(.B).18 G 4.066(yd)365.99 458.4 S(ef)380.056 458.4 Q(ault,)-.1 E F2(bash)4.066
+E F0 1.567(normally reads these \214les)4.067 F(when it is in)158 470.4 Q -.2
+(vo)-.4 G -.1(ke).2 G 2.5(da).1 G 2.5(sal)237.85 470.4 S(ogin shell \(see)
+253.96 470.4 Q F1(INV)2.5 E(OCA)-.405 E(TION)-.855 E F0(belo)2.25 E(w\).)-.25 E
+F2<ad72>108 482.4 Q(c\214le)-.18 E F3(\214le)2.5 E F0(Ex)8.1 E .452
+(ecute commands from)-.15 F F3(\214le)2.952 E F0 .452
+(instead of the standard personal initialization \214le)2.952 F F3(~/.bashr)
+2.951 E(c)-.37 E F0 2.951(,i).31 G 2.951(ft)521.499 482.4 S(he)530.56 482.4 Q
+(shell is interacti)158 494.4 Q .3 -.15(ve \()-.25 H(see).15 E F1(INV)2.5 E
+(OCA)-.405 E(TION)-.855 E F0(belo)2.25 E(w\).)-.25 E F2<ad76>108 506.4 Q
+(ersion)-.1 E F0(Sho)158 506.4 Q 2.5(wt)-.25 G(he v)185.81 506.4 Q
+(ersion number of this instance of)-.15 E F2(bash)2.5 E F0(when starting.)2.5 E
+F2(\255quiet)108 518.4 Q F0 .71(Do not be v)158 518.4 R .71
+(erbose when starting up \(do not sho)-.15 F 3.21(wt)-.25 G .71(he shell v)
+366.9 518.4 R .71(ersion or an)-.15 F 3.21(yo)-.15 G .71(ther information\).)
+468.19 518.4 R(This is the def)158 530.4 Q(ault.)-.1 E F2(\255login)108 542.4 Q
+F0(Mak)158 542.4 Q(e)-.1 E F2(bash)2.5 E F0(act as if it had been in)2.5 E -.2
+(vo)-.4 G -.1(ke).2 G 2.5(da).1 G 2.5(sal)324.12 542.4 S(ogin shell.)340.23
+542.4 Q F2(\255nobraceexpansion)108 554.4 Q F0(Do not perform curly brace e)158
+566.4 Q(xpansion \(see)-.15 E F2(Brace Expansion)2.5 E F0(belo)2.5 E(w\).)-.25
+E F2(\255nolineediting)108 578.4 Q F0(Do not use the GNU)158 590.4 Q F3 -.37
+(re)2.5 G(adline).37 E F0(library to read command lines if interacti)2.5 E -.15
+(ve)-.25 G(.).15 E F2(\255posix)108 602.4 Q F0 1.001(Change the beha)158 602.4
+R 1.001(vior of bash where the def)-.2 F 1.001(ault operation dif)-.1 F 1
+(fers from the Posix 1003.2 stan-)-.25 F(dard to match the standard)158 614.4 Q
+F1(ARGUMENTS)72 631.2 Q F0 .016(If ar)108 643.2 R .016
+(guments remain after option processing, and neither the)-.18 F F2<ad63>2.516 E
+F0 .016(nor the)2.516 F F2<ad73>2.516 E F0 .016
+(option has been supplied, the \214rst)2.516 F(ar)108 655.2 Q .041
+(gument is assumed to be the name of a \214le containing shell commands.)-.18 F
+(If)5.041 E F2(bash)2.541 E F0 .041(is in)2.541 F -.2(vo)-.4 G -.1(ke).2 G
+2.541(di).1 G 2.541(nt)483.628 655.2 S .041(his f)493.949 655.2 R(ashion,)-.1 E
+F2($0)108 667.2 Q F0 .936(is set to the name of the \214le, and the positional\
+ parameters are set to the remaining ar)3.435 F(guments.)-.18 E F2(Bash)5.936 E
+F0 .225(reads and e)108 679.2 R -.15(xe)-.15 G .224
+(cutes commands from this \214le, then e).15 F(xits.)-.15 E F2(Bash')5.224 E(s)
+-.37 E F0 -.15(ex)2.724 G .224(it status is the e).15 F .224
+(xit status of the last com-)-.15 F(mand e)108 691.2 Q -.15(xe)-.15 G
+(cuted in the script.).15 E 185.675(GNU 1995)72 768 R(May 5)2.5 E(1)535 768 Q
+EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 9/Times-Bold@0 SF(DEFINITIONS)72 84 Q/F2 10/Times-Bold@0 SF(blank)108 96 Q
+F0 2.5(As)144 96 S(pace or tab)157.61 96 Q(.)-.4 E F2 -.1(wo)108 108 S(rd).1 E
+F0 2.5(As)144 108 S
+(equence of characters considered as a single unit by the shell.)157.61 108 Q
+(Also kno)5 E(wn as a)-.25 E F2(tok)2.5 E(en)-.1 E F0(.)A F2(name)108 120 Q F0
+(A)144 120 Q/F3 10/Times-Italic@0 SF(wor)2.75 E(d)-.37 E F0 .251
+(consisting only of alphanumeric characters and underscores, and be)2.75 F .251
+(ginning with an alpha-)-.15 F(betic character or an underscore.)144 132 Q
+(Also referred to as an)5 E F2(identi\214er)2.5 E F0(.)A F2(metacharacter)108
+144 Q F0 2.5(Ac)144 156 S(haracter that, when unquoted, separates w)158.16 156
+Q 2.5(ords. One)-.1 F(of the follo)2.5 E(wing:)-.25 E F2 5(|&;\(\)<>s)144 168 S
+2.5(pace tab)214.81 168 R(contr)108 180 Q(ol operator)-.18 E F0(A)144 192 Q F3
+(tok)2.5 E(en)-.1 E F0(that performs a control function.)2.5 E
+(It is one of the follo)5 E(wing symbols:)-.25 E/F4 10/Symbol SF 1.666<efef>144
+204 S F2 5(&&)3.334 G 5(&;;)182.206 204 S 5(;\(\)|<)207.196 204 S(newline>)
+245.086 204 Q F1(RESER)72 220.8 Q(VED W)-.495 E(ORDS)-.09 E F3 .307
+(Reserved wor)108 232.8 R(ds)-.37 E F0 .307(are w)2.807 F .307(ords that ha)-.1
+F .607 -.15(ve a s)-.2 H .306(pecial meaning to the shell.).15 F .306
+(The follo)5.306 F .306(wing w)-.25 F .306(ords are recognized as)-.1 F(reserv)
+108 244.8 Q .227(ed when unquoted and either the \214rst w)-.15 F .227
+(ord of a simple command \(see)-.1 F F1 .227(SHELL GRAMMAR)2.727 F F0(belo)
+2.477 E .227(w\) or)-.25 F(the third w)108 256.8 Q(ord of a)-.1 E F2(case)2.5 E
+F0(or)2.5 E F2 -.25(fo)2.5 G(r).25 E F0(command:)2.5 E F2 11.916(!c)144 273.6 S
+9.416(ase do done elif else esac \214 f)163.686 273.6 R 9.415
+(or function if in select then until)-.25 F 7.5(while { })144 285.6 R F1
+(SHELL GRAMMAR)72 302.4 Q F2(Simple Commands)87 314.4 Q F0(A)108 326.4 Q F3
+.383(simple command)2.883 F F0 .383(is a sequence of optional v)2.883 F .384
+(ariable assignments follo)-.25 F .384(wed by)-.25 F F3(blank)2.884 E F0 .384
+(\255separated w)B .384(ords and)-.1 F .816(redirections, and terminated by a)
+108 338.4 R F3(contr)3.316 E .815(ol oper)-.45 F(ator)-.15 E F0 5.815(.T)C .815
+(he \214rst w)326.97 338.4 R .815(ord speci\214es the command to be e)-.1 F
+-.15(xe)-.15 G(cuted.).15 E(The remaining w)108 350.4 Q(ords are passed as ar)
+-.1 E(guments to the in)-.18 E -.2(vo)-.4 G -.1(ke).2 G 2.5(dc).1 G(ommand.)
+358.08 350.4 Q .175(The return v)108 367.2 R .175(alue of a)-.25 F F3 .175
+(simple command)2.675 F F0 .175(is its e)2.675 F .175(xit status, or 128+)-.15
+F F3(n)A F0 .176(if the command is terminated by signal)3.508 F F3(n)2.676 E F0
+(.).24 E F2(Pipelines)87 384 Q F0(A)108 396 Q F3(pipeline)2.92 E F0 .42
+(is a sequence of one or more commands separated by the character)2.92 F F2(|)
+2.919 E F0 5.419(.T)C .419(he format for a pipeline)443.904 396 R(is:)108 408 Q
+2.5([!])144 424.8 S F3(command)A F0([)2.5 E F2(|)2.5 E F3(command2)2.5 E F0
+(... ])2.5 E .418(The standard output of)108 441.6 R F3(command)2.918 E F0 .418
+(is connected to the standard input of)2.918 F F3(command2)2.918 E F0 5.418(.T)
+.02 G .419(his connection is per)453.124 441.6 R(-)-.2 E(formed before an)108
+453.6 Q 2.5(yr)-.15 G(edirections speci\214ed by the command \(see)187.54 453.6
+Q F1(REDIRECTION)2.5 E F0(belo)2.25 E(w\).)-.25 E .238(If the reserv)108 470.4
+R .238(ed w)-.15 F(ord)-.1 E F2(!)2.737 E F0 .237(precedes a pipeline, the e)
+5.237 F .237(xit status of that pipeline is the logical NO)-.15 F 2.737(To)-.4
+G 2.737(ft)486.949 470.4 S .237(he e)495.796 470.4 R .237(xit sta-)-.15 F .612
+(tus of the last command.)108 482.4 R .612
+(Otherwise, the status of the pipeline is the e)5.612 F .612
+(xit status of the last command.)-.15 F(The)5.613 E(shell w)108 494.4 Q
+(aits for all commands in the pipeline to terminate before returning a v)-.1 E
+(alue.)-.25 E(Each command in a pipeline is e)108 511.2 Q -.15(xe)-.15 G
+(cuted as a separate process \(i.e., in a subshell\).).15 E F2(Lists)87 528 Q
+F0(A)108 540 Q F3(list)2.727 E F0 .227
+(is a sequence of one or more pipelines separated by one of the operators)2.727
+F F2(;)2.727 E F0(,)A F2(&)2.727 E F0(,)A F2(&&)2.727 E F0 2.727(,o)C(r)475.563
+540 Q F4 1.666<efef>2.727 G F0 2.727(,a)-1.666 G .227(nd termi-)502.833 540 R
+(nated by one of)108 552 Q F2(;)2.5 E F0(,)A F2(&)2.5 E F0 2.5(,o)C(r)199.09
+552 Q F2(<newline>)2.5 E F0(.)A .563(Of these list operators,)108 568.8 R F2
+(&&)3.063 E F0(and)3.063 E F4 1.666<efef>3.063 G F0(ha)1.397 E .863 -.15(ve e)
+-.2 H .564(qual precedence, follo).15 F .564(wed by)-.25 F F2(;)3.064 E F0(and)
+3.064 E F2(&,)3.064 E F0 .564(which ha)3.064 F .864 -.15(ve e)-.2 H .564
+(qual prece-).15 F(dence.)108 580.8 Q .029
+(If a command is terminated by the control operator)108 597.6 R F2(&)2.529 E F0
+2.529(,t)C .029(he shell e)330.75 597.6 R -.15(xe)-.15 G .029
+(cutes the command in the).15 F F3(bac)2.528 E(kgr)-.2 E(ound)-.45 E F0(in)
+2.528 E 2.875(as)108 609.6 S 2.875(ubshell. The)119.205 609.6 R .375
+(shell does not w)2.875 F .375
+(ait for the command to \214nish, and the return status is 0.)-.1 F .376
+(Commands sepa-)5.376 F .849(rated by a)108 621.6 R F2(;)3.349 E F0 .849(are e)
+3.349 F -.15(xe)-.15 G .848(cuted sequentially; the shell w).15 F .848
+(aits for each command to terminate in turn.)-.1 F .848(The return)5.848 F
+(status is the e)108 633.6 Q(xit status of the last command e)-.15 E -.15(xe)
+-.15 G(cuted.).15 E(The control operators)108 650.4 Q F2(&&)2.5 E F0(and)2.5 E
+F4 1.666<efef>2.5 G F0(denote AND lists and OR lists, respecti).834 E -.15(ve)
+-.25 G(ly).15 E 5(.A)-.65 G 2.5(nA)435.116 650.4 S(ND list has the form)449.836
+650.4 Q F3(command)144 667.2 Q F2(&&)2.5 E F3(command2)2.5 E(command2)108 684 Q
+F0(is e)2.5 E -.15(xe)-.15 G(cuted if, and only if,).15 E F3(command)2.5 E F0
+(returns an e)2.5 E(xit status of zero.)-.15 E(An OR list has the form)108
+700.8 Q F3(command)144 717.6 Q F4 1.666<efef>2.5 G F3(command2).834 E F0
+185.675(GNU 1995)72 768 R(May 5)2.5 E(2)535 768 Q EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Italic@0 SF(command2)108 84 Q F0 .911(is e)3.411 F -.15(xe)-.15 G
+.911(cuted if and only if).15 F F1(command)3.412 E F0 .912
+(returns a non\255zero e)3.412 F .912(xit status.)-.15 F .912
+(The return status of AND)5.912 F(and OR lists is the e)108 96 Q
+(xit status of the last command e)-.15 E -.15(xe)-.15 G(cuted in the list.).15
+E/F2 10/Times-Bold@0 SF(Compound Commands)87 112.8 Q F0(A)108 124.8 Q F1
+(compound command)2.5 E F0(is one of the follo)2.5 E(wing:)-.25 E(\()108 141.6
+Q F1(list)A F0(\))A F1(list)144 141.6 Q F0 1.12(is e)3.62 F -.15(xe)-.15 G 1.12
+(cuted in a subshell.).15 F -1.11(Va)6.119 G 1.119(riable assignments and b)
+1.11 F 1.119(uiltin commands that af)-.2 F 1.119(fect the shell')-.25 F(s)-.55
+E(en)144 153.6 Q 1.068(vironment do not remain in ef)-.4 F 1.069
+(fect after the command completes.)-.25 F 1.069(The return status is the e)
+6.069 F(xit)-.15 E(status of)144 165.6 Q F1(list)2.5 E F0(.)A({)108 182.4 Q F1
+(list)2.5 E F0 2.5(;})C F1(list)3.89 E F0 .326(is simply e)2.826 F -.15(xe)-.15
+G .326(cuted in the current shell en).15 F 2.826(vironment. This)-.4 F .325
+(is kno)2.826 F .325(wn as a)-.25 F F1(gr)2.825 E .325(oup command)-.45 F F0
+5.325(.T)C(he)530.56 182.4 Q(return status is the e)144 194.4 Q(xit status of)
+-.15 E F1(list)2.5 E F0(.)A F2 -.25(fo)108 211.2 S(r).25 E F1(name)2.5 E F0([)
+2.5 E F2(in)2.5 E F1(wor)2.5 E(d)-.37 E F0 2.5(;])C F2(do)A F1(list)2.5 E F0(;)
+2.5 E F2(done)2.5 E F0 .423(The list of w)144 223.2 R .423(ords follo)-.1 F
+(wing)-.25 E F2(in)2.923 E F0 .423(is e)2.923 F .423
+(xpanded, generating a list of items.)-.15 F .424(The v)5.424 F(ariable)-.25 E
+F1(name)2.924 E F0 .424(is set to)2.924 F .653
+(each element of this list in turn, and)144 235.2 R F1(list)3.153 E F0 .653
+(is e)3.153 F -.15(xe)-.15 G .653(cuted each time.).15 F .653(If the)5.653 F F2
+(in)3.153 E F1(wor)3.153 E(d)-.37 E F0 .653(is omitted, the)3.153 F F2 -.25(fo)
+3.153 G(r).25 E F0(command e)144 247.2 Q -.15(xe)-.15 G(cutes).15 E F1(list)2.5
+E F0(once for each positional parameter that is set \(see)2.5 E/F3 9
+/Times-Bold@0 SF -.666(PA)2.5 G(RAMETERS).666 E F0(belo)2.25 E(w\).)-.25 E F2
+(select)108 264 Q F1(name)2.5 E F0([)2.5 E F2(in)2.5 E F1(wor)2.5 E(d)-.37 E F0
+2.5(;])C F2(do)A F1(list)2.5 E F0(;)2.5 E F2(done)2.5 E F0 .432(The list of w)
+144 276 R .432(ords follo)-.1 F(wing)-.25 E F2(in)2.932 E F0 .432(is e)2.932 F
+.432(xpanded, generating a list of items.)-.15 F .433(The set of e)5.433 F .433
+(xpanded w)-.15 F(ords)-.1 E .843(is printed on the standard error)144 288 R
+3.342(,e)-.4 G .842(ach preceded by a number)281.126 288 R 5.842(.I)-.55 G
+3.342(ft)400.576 288 S(he)410.028 288 Q F2(in)3.342 E F1(wor)3.342 E(d)-.37 E
+F0 .842(is omitted, the posi-)3.342 F .064(tional parameters are printed \(see)
+144 300 R F3 -.666(PA)2.564 G(RAMETERS).666 E F0(belo)2.314 E 2.564(w\). The)
+-.25 F F2(PS3)2.564 E F0 .064(prompt is then displayed and a)2.564 F .798
+(line read from the standard input.)144 312 R .797
+(If the line consists of the number corresponding to one of the)5.798 F .951
+(displayed w)144 324 R .951(ords, then the v)-.1 F .951(alue of)-.25 F F1(name)
+3.451 E F0 .952(is set to that w)3.451 F 3.452(ord. If)-.1 F .952
+(the line is empty)3.452 F 3.452(,t)-.65 G .952(he w)484.876 324 R .952
+(ords and)-.1 F .066(prompt are displayed ag)144 336 R 2.566(ain. If)-.05 F
+.065(EOF is read, the command completes.)2.566 F(An)5.065 E 2.565(yo)-.15 G
+.065(ther v)452.035 336 R .065(alue read causes)-.25 F F1(name)144 348 Q F0
+.809(to be set to null.)3.309 F .809(The line read is sa)5.809 F -.15(ve)-.2 G
+3.31(di).15 G 3.31(nt)338.36 348 S .81(he v)349.45 348 R(ariable)-.25 E F2
+(REPL)3.31 E(Y)-.92 E F0 5.81(.T)C(he)444.86 348 Q F1(list)3.31 E F0 .81(is e)
+3.31 F -.15(xe)-.15 G .81(cuted after).15 F .667(each selection until a)144 360
+R F2(br)3.167 E(eak)-.18 E F0(or)3.167 E F2 -.18(re)3.167 G(tur).18 E(n)-.15 E
+F0 .667(command is e)3.167 F -.15(xe)-.15 G 3.167(cuted. The).15 F -.15(ex)
+3.167 G .667(it status of).15 F F2(select)3.167 E F0 .667(is the e)3.167 F(xit)
+-.15 E(status of the last command e)144 372 Q -.15(xe)-.15 G(cuted in).15 E F1
+(list)2.5 E F0 2.5(,o).68 G 2.5(rz)324.09 372 S(ero if no commands were e)
+334.36 372 Q -.15(xe)-.15 G(cuted.).15 E F2(case)108 388.8 Q F1(wor)2.5 E(d)
+-.37 E F2(in)2.5 E F0([)2.5 E F1(pattern)2.5 E F0([)2.5 E F2(|)2.5 E F1
+(pattern)2.5 E F0 2.5(].)2.5 G(.. \))249.27 388.8 Q F1(list)2.5 E F0(;; ] ...)
+2.5 E F2(esac)2.5 E F0(A)144 400.8 Q F2(case)3.264 E F0 .764(command \214rst e)
+3.264 F(xpands)-.15 E F1(wor)3.264 E(d)-.37 E F0 3.264(,a)C .764
+(nd tries to match it ag)303.324 400.8 R .764(ainst each)-.05 F F1(pattern)
+3.264 E F0 .765(in turn, using the)3.264 F 2.028
+(same matching rules as for pathname e)144 412.8 R 2.027(xpansion \(see)-.15 F
+F2 -.1(Pa)4.527 G 2.027(thname Expansion).1 F F0(belo)4.527 E 4.527(w\). When)
+-.25 F(a)4.527 E .89(match is found, the corresponding)144 424.8 R F1(list)3.39
+E F0 .89(is e)3.39 F -.15(xe)-.15 G 3.39(cuted. After).15 F .89
+(the \214rst match, no subsequent matches)3.39 F .308(are attempted.)144 436.8
+R .308(The e)5.308 F .307(xit status is zero if no patterns are matches.)-.15 F
+.307(Otherwise, it is the e)5.307 F .307(xit status of)-.15 F
+(the last command e)144 448.8 Q -.15(xe)-.15 G(cuted in).15 E F1(list)2.5 E F0
+(.)A F2(if)108 465.6 Q F1(list)2.5 E F2(then)2.5 E F1(list)2.5 E F0([)2.5 E F2
+(elif)2.5 E F1(list)2.5 E F2(then)2.5 E F1(list)2.5 E F0 2.5(].)2.5 G(.. [)
+248.3 465.6 Q F2(else)2.5 E F1(list)2.5 E F0(])2.5 E F2<8c>2.5 E F0(The)144
+477.6 Q F2(if)2.534 E F1(list)2.534 E F0 .034(is e)2.534 F -.15(xe)-.15 G 2.534
+(cuted. If).15 F .034(its e)2.534 F .034(xit status is zero, the)-.15 F F2
+(then)2.534 E F1(list)2.534 E F0 .034(is e)2.534 F -.15(xe)-.15 G 2.534
+(cuted. Otherwise,).15 F(each)2.534 E F2(elif)2.534 E F1(list)2.534 E F0(is)
+2.534 E -.15(exe)144 489.6 S .316(cuted in turn, and if its e).15 F .316
+(xit status is zero, the corresponding)-.15 F F2(then)2.816 E F1(list)2.816 E
+F0 .316(is e)2.816 F -.15(xe)-.15 G .316(cuted and the com-).15 F .658
+(mand completes.)144 501.6 R .658(Otherwise, the)5.658 F F2(else)3.158 E F1
+(list)3.158 E F0 .658(is e)3.158 F -.15(xe)-.15 G .658(cuted, if present.).15 F
+.658(The e)5.658 F .658(xit status is the e)-.15 F .659(xit status)-.15 F
+(of the last command e)144 513.6 Q -.15(xe)-.15 G
+(cuted, or zero if no condition tested true.).15 E F2(while)108 530.4 Q F1
+(list)2.5 E F2(do)2.5 E F1(list)2.5 E F2(done)2.5 E(until)108 542.4 Q F1(list)
+2.5 E F2(do)2.5 E F1(list)2.5 E F2(done)2.5 E F0(The)144 554.4 Q F2(while)3.104
+E F0 .603(command continuously e)3.104 F -.15(xe)-.15 G .603(cutes the).15 F F2
+(do)3.103 E F1(list)3.103 E F0 .603(as long as the last command in)3.103 F F1
+(list)3.103 E F0(returns)3.103 E .47(an e)144 566.4 R .47(xit status of zero.)
+-.15 F(The)5.47 E F2(until)2.97 E F0 .471(command is identical to the)2.97 F F2
+(while)2.971 E F0 .471(command, e)2.971 F .471(xcept that the test)-.15 F .055
+(is ne)144 578.4 R -.05(ga)-.15 G .055(ted; the).05 F F2(do)2.555 E F1(list)
+2.555 E F0 .055(is e)2.555 F -.15(xe)-.15 G .055
+(cuted as long as the last command in).15 F F1(list)2.555 E F0 .054
+(returns a non\255zero e)2.554 F .054(xit status.)-.15 F 1.306(The e)144 590.4
+R 1.306(xit status of the)-.15 F F2(while)3.806 E F0(and)3.806 E F2(until)3.807
+E F0 1.307(commands is the e)3.807 F 1.307(xit status of the last)-.15 F F2(do)
+3.807 E F1(list)3.807 E F0(command)3.807 E -.15(exe)144 602.4 S
+(cuted, or zero if none w).15 E(as e)-.1 E -.15(xe)-.15 G(cuted.).15 E([)108
+619.2 Q F2(function)2.5 E F0(])2.5 E F1(name)2.5 E F0(\(\) {)2.5 E F1(list)2.5
+E F0 2.5(;})C .385(This de\214nes a function named)144 631.2 R F1(name)2.884 E
+F0 5.384(.T)C(he)304.616 631.2 Q F1(body)2.884 E F0 .384
+(of the function is the)2.884 F F1(list)2.884 E F0 .384(of commands between {)
+2.884 F .785(and }.)144 643.2 R .785(This list is e)5.785 F -.15(xe)-.15 G .785
+(cuted whene).15 F -.15(ve)-.25 G(r).15 E F1(name)3.285 E F0 .785
+(is speci\214ed as the name of a simple command.)3.285 F(The)5.786 E -.15(ex)
+144 655.2 S .64(it status of a function is the e).15 F .64
+(xit status of the last command e)-.15 F -.15(xe)-.15 G .64(cuted in the body)
+.15 F 5.64(.\()-.65 G(See)494.43 655.2 Q F3(FUNC-)3.14 E(TIONS)144 667.2 Q F0
+(belo)2.25 E -.65(w.)-.25 G(\)).65 E F3(COMMENTS)72 684 Q F0 .785
+(In a non\255interacti)108 696 R 1.085 -.15(ve s)-.25 H .785
+(hell, or an interacti).15 F 1.086 -.15(ve s)-.25 H .786(hell in which the).15
+F F2 .786(-o interacti)3.286 F -.1(ve)-.1 G(\255comments).1 E F0 .786
+(option to the)3.286 F F2(set)3.286 E F0 -.2(bu)108 708 S .343
+(iltin is enabled, a w).2 F .342(ord be)-.1 F .342(ginning with)-.15 F F2(#)
+2.842 E F0 .342(causes that w)2.842 F .342
+(ord and all remaining characters on that line to be)-.1 F 5.693(ignored. An)
+108 720 R(interacti)5.693 E 3.493 -.15(ve s)-.25 H 3.193(hell without the).15 F
+F2 3.193(-o interacti)5.693 F -.1(ve)-.1 G(\255comments).1 E F0 3.194
+(option enabled does not allo)5.693 F(w)-.25 E 185.675(GNU 1995)72 768 R(May 5)
+2.5 E(3)535 768 Q EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+(comments.)108 84 Q/F1 9/Times-Bold@0 SF -.09(QU)72 100.8 S -.36(OT).09 G(ING)
+.36 E/F2 10/Times-Italic@0 SF(Quoting)108 112.8 Q F0 .478(is used to remo)2.978
+F .777 -.15(ve t)-.15 H .477(he special meaning of certain characters or w).15
+F .477(ords to the shell.)-.1 F .477(Quoting can be)5.477 F .184
+(used to disable special treatment for special characters, to pre)108 124.8 R
+-.15(ve)-.25 G .185(nt reserv).15 F .185(ed w)-.15 F .185
+(ords from being recognized as)-.1 F(such, and to pre)108 136.8 Q -.15(ve)-.25
+G(nt parameter e).15 E(xpansion.)-.15 E .289(Each of the)108 153.6 R F2(metac)
+2.789 E(har)-.15 E(acter)-.15 E(s)-.1 E F0 .288(listed abo)2.789 F .588 -.15
+(ve u)-.15 H(nder).15 E F1(DEFINITIONS)2.788 E F0 .288
+(has special meaning to the shell and must be)2.538 F .242(quoted if the)108
+165.6 R 2.742(ya)-.15 G .242(re to represent themselv)171.066 165.6 R 2.742
+(es. There)-.15 F .242(are three quoting mechanisms: the)2.742 F F2 .242
+(escape c)2.742 F(har)-.15 E(acter)-.15 E F0 2.742(,s).73 G(in-)528.89 165.6 Q
+(gle quotes, and double quotes.)108 177.6 Q 2.975(An)108 194.4 S .475
+(on-quoted backslash \()123.195 194.4 R/F3 10/Times-Bold@0 SF(\\)A F0 2.974
+(\)i)C 2.974(st)223.768 194.4 S(he)233.412 194.4 Q F2 .474(escape c)2.974 F
+(har)-.15 E(acter)-.15 E F0 5.474(.I).73 G 2.974(tp)326.624 194.4 S(reserv)
+337.378 194.4 Q .474(es the literal v)-.15 F .474(alue of the ne)-.25 F .474
+(xt character that)-.15 F(follo)108 206.4 Q .024(ws, with the e)-.25 F .024
+(xception of <ne)-.15 F 2.524(wline>. If)-.25 F(a)2.524 E F3(\\)2.524 E F0(<ne)
+A .024(wline> pair appears, and the backslash is not quoted, the)-.25 F F3(\\)
+108 218.4 Q F0(<ne)A
+(wline> is treated as a line continuation \(that is, it is ef)-.25 E(fecti)-.25
+E -.15(ve)-.25 G(ly ignored\).).15 E .295
+(Enclosing characters in single quotes preserv)108 235.2 R .295
+(es the literal v)-.15 F .295(alue of each character within the quotes.)-.25 F
+2.795(As)5.295 G(in-)528.89 235.2 Q
+(gle quote may not occur between single quotes, e)108 247.2 Q -.15(ve)-.25 G
+2.5(nw).15 G(hen preceded by a backslash.)328.67 247.2 Q .033
+(Enclosing characters in double quotes preserv)108 264 R .034(es the literal v)
+-.15 F .034(alue of all characters within the quotes, with the)-.25 F -.15(ex)
+108 276 S 1.267(ception of).15 F F3($)3.767 E F0(,)A F3(`)3.766 E F0 3.766(,a)C
+(nd)187.896 276 Q F3(\\)3.766 E F0 6.266(.T)C 1.266(he characters)219.318 276 R
+F3($)3.766 E F0(and)3.766 E F3(`)3.766 E F0 1.266
+(retain their special meaning within double quotes.)3.766 F(The)6.266 E .637
+(backslash retains its special meaning only when follo)108 288 R .637
+(wed by one of the follo)-.25 F .637(wing characters:)-.25 F F3($)3.137 E F0(,)
+A F3(`)3.137 E F0(,)A F3(")3.97 E F0(,).833 E F3(\\)3.137 E F0 3.137(,o)C(r)
+536.67 288 Q F3(<newline>)108 300 Q F0 5(.A)C(double quote may be quoted withi\
+n double quotes by preceding it with a backslash.)169.4 300 Q
+(The special parameters)108 316.8 Q F3(*)2.5 E F0(and)2.5 E F3(@)2.5 E F0(ha)
+2.5 E .3 -.15(ve s)-.2 H(pecial meaning when in double quotes \(see).15 E F1
+-.666(PA)2.5 G(RAMETERS).666 E F0(belo)2.25 E(w\).)-.25 E F1 -.666(PA)72 333.6
+S(RAMETERS).666 E F0(A)108 345.6 Q F2(par)3.334 E(ameter)-.15 E F0 .833
+(is an entity that stores v)3.334 F .833(alues, some)-.25 F .833(what lik)-.25
+F 3.333(eav)-.1 G .833(ariable in a con)362.805 345.6 R -.15(ve)-.4 G .833
+(ntional programming lan-).15 F 2.51(guage. It)108 357.6 R .01(can be a)2.51 F
+F2(name)2.51 E F0 2.51(,an).18 G(umber)222.1 357.6 Q 2.51(,o)-.4 G 2.511(ro)
+257.26 357.6 S .011(ne of the special characters listed belo)268.101 357.6 R
+2.511(wu)-.25 G(nder)434.828 357.6 Q F3 .011(Special P)2.511 F(arameters)-.1 E
+F0(.)A -.15(Fo)108 369.6 S 2.5(rt).15 G(he shell')127.02 369.6 Q 2.5(sp)-.55 G
+(urposes, a)172.02 369.6 Q F2(variable)2.5 E F0(is a parameter denoted by a)2.5
+E F2(name)2.5 E F0(.).18 E 2.755(Ap)108 386.4 S .255
+(arameter is set if it has been assigned a v)122.975 386.4 R 2.754(alue. The)
+-.25 F .254(null string is a v)2.754 F .254(alid v)-.25 F 2.754(alue. Once)-.25
+F 2.754(av)2.754 G .254(ariable is set, it)478.688 386.4 R
+(may be unset only by using the)108 398.4 Q F3(unset)2.5 E F0 -.2(bu)2.5 G
+(iltin command \(see).2 E F1(SHELL B)2.5 E(UIL)-.09 E(TIN COMMANDS)-.828 E F0
+(belo)2.25 E(w\).)-.25 E(A)108 415.2 Q F2(variable)2.5 E F0
+(may be assigned to by a statement of the form)2.5 E F2(name)144 432 Q F0(=[)A
+F2(value)A F0(])A(If)108 448.8 Q F2(value)2.792 E F0 .293(is not gi)2.793 F
+-.15(ve)-.25 G .293(n, the v).15 F .293(ariable is assigned the null string.)
+-.25 F(All)5.293 E F2(values)2.793 E F0(under)2.793 E .293(go tilde e)-.18 F
+.293(xpansion, parameter)-.15 F 1.314(and v)108 460.8 R 1.314(ariable e)-.25 F
+1.314(xpansion, command substitution, arithmetic e)-.15 F 1.313
+(xpansion, and quote remo)-.15 F -.25(va)-.15 G 3.813(l. If).25 F 1.313(the v)
+3.813 F(ariable)-.25 E .432(has its)108 472.8 R F3<ad69>2.932 E F0(attrib)2.932
+E .432(ute set \(see)-.2 F F3(declar)2.932 E(e)-.18 E F0(belo)2.932 E 2.932(wi)
+-.25 G(n)280.946 472.8 Q F1 .432(SHELL B)2.932 F(UIL)-.09 E .432(TIN COMMANDS)
+-.828 F/F4 9/Times-Roman@0 SF(\))A F0(then)2.682 E F2(value)2.933 E F0 .433
+(is subject to arith-)2.933 F .455(metic e)108 484.8 R .455(xpansion e)-.15 F
+-.15(ve)-.25 G 2.955(ni).15 G 2.955(ft)200.745 484.8 S .455
+(he $[...] syntax does not appear)209.81 484.8 R 5.455(.W)-.55 G .454
+(ord splitting is not performed, with the e)353.1 484.8 R(xcep-)-.15 E(tion of)
+108 496.8 Q F3("$@")2.5 E F0(as e)2.5 E(xplained belo)-.15 E 2.5(wu)-.25 G
+(nder)248.54 496.8 Q F3(Special P)2.5 E(arameters)-.1 E F0 5(.P)C(athname e)
+364.1 496.8 Q(xpansion is not performed.)-.15 E F3 -.2(Po)87 513.6 S
+(sitional P).2 E(arameters)-.1 E F0(A)108 525.6 Q F2 .815(positional par)3.315
+F(ameter)-.15 E F0 .816
+(is a parameter denoted by one or more digits, other than the single digit 0.)
+3.315 F(Posi-)5.816 E .445(tional parameters are assigned from the shell')108
+537.6 R 2.944(sa)-.55 G -.18(rg)303.574 537.6 S .444(uments when it is in).18 F
+-.2(vo)-.4 G -.1(ke).2 G .444(d, and may be reassigned using).1 F(the)108 549.6
+Q F3(set)3.333 E F0 -.2(bu)3.333 G .833(iltin command.).2 F .834
+(Positional parameters may not be assigned to with assignment statements.)5.833
+F(The)5.834 E .334
+(positional parameters are temporarily replaced when a shell function is e)108
+561.6 R -.15(xe)-.15 G .333(cuted \(see).15 F F1(FUNCTIONS)2.833 E F0(belo)
+2.583 E(w\).)-.25 E 1.403
+(When a positional parameter consisting of more than a single digit is e)108
+578.4 R 1.404(xpanded, it must be enclosed in)-.15 F(braces \(see)108 590.4 Q
+F1(EXP)2.5 E(ANSION)-.666 E F0(belo)2.25 E(w\).)-.25 E F3(Special P)87 607.2 Q
+(arameters)-.1 E F0 1.675(The shell treats se)108 619.2 R -.15(ve)-.25 G 1.675
+(ral parameters specially).15 F 6.675(.T)-.65 G 1.674
+(hese parameters may only be referenced; assignment to)306.95 619.2 R
+(them is not allo)108 631.2 Q(wed.)-.25 E F3(*)108 643.2 Q F0 .605
+(Expands to the positional parameters, starting from one.)144 643.2 R .606
+(When the e)5.605 F .606(xpansion occurs within dou-)-.15 F .084
+(ble quotes, it e)144 655.2 R .084(xpands to a single w)-.15 F .084
+(ord with the v)-.1 F .084
+(alue of each parameter separated by the \214rst char)-.25 F(-)-.2 E .943
+(acter of the)144 667.2 R F1(IFS)3.444 E F0 .944(special v)3.194 F 3.444
+(ariable. That)-.25 F .944(is, `)3.444 F(`)-.74 E F3($*)A F0 2.424 -.74('' i)D
+3.444(se).74 G(qui)357.352 667.2 Q -.25(va)-.25 G .944(lent to `).25 F(`)-.74 E
+F3($1)A F2(c)A F3($2)A F2(c)A F3(...)A F0 -.74('')C 3.444(,w).74 G(here)470.124
+667.2 Q F2(c)3.444 E F0 .944(is the \214rst)3.444 F .583(character of the v)144
+679.2 R .583(alue of the)-.25 F F1(IFS)3.083 E F0 -.25(va)2.833 G 3.083
+(riable. If).25 F F1(IFS)3.083 E F0 .583
+(is null or unset, the parameters are separated by)2.833 F(spaces.)144 691.2 Q
+F3(@)108 703.2 Q F0 .605
+(Expands to the positional parameters, starting from one.)144 703.2 R .606
+(When the e)5.605 F .606(xpansion occurs within dou-)-.15 F 1.387
+(ble quotes, each parameter e)144 715.2 R 1.386(xpands as a separate w)-.15 F
+3.886(ord. That)-.1 F 1.386(is, `)3.886 F(`)-.74 E F3($@)3.886 E F0 2.866 -.74
+('' i)D 3.886(se).74 G(qui)465.888 715.2 Q -.25(va)-.25 G 1.386(lent to `).25 F
+(`)-.74 E F3($1)A F0 -.74('')C -.74(``)144 727.2 S F3($2).74 E F0 1.666 -.74
+('' .)D 2.686(.. When).74 F .186(there are no positional parameters, `)2.686 F
+(`)-.74 E F3($@)A F0 1.666 -.74('' a)D(nd).74 E F3($@)2.686 E F0 -.15(ex)2.686
+G .187(pand to nothing \(i.e., the).15 F 2.687(ya)-.15 G(re)532.23 727.2 Q
+185.675(GNU 1995)72 768 R(May 5)2.5 E(4)535 768 Q EP
+%%Page: 5 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+(remo)144 84 Q -.15(ve)-.15 G(d\).).15 E/F1 10/Times-Bold@0 SF(#)108 96 Q F0
+(Expands to the number of positional parameters in decimal.)144 96 Q F1(?)108
+108 Q F0(Expands to the status of the most recently e)144 108 Q -.15(xe)-.15 G
+(cuted fore).15 E(ground pipeline.)-.15 E F1<ad>108 120 Q F0 .882
+(Expands to the current option \215ags as speci\214ed upon in)144 120 R -.2(vo)
+-.4 G .881(cation, by the).2 F F1(set)3.381 E F0 -.2(bu)3.381 G .881
+(iltin command, or).2 F(those set by the shell itself \(such as the)144 132 Q
+F1<ad69>2.5 E F0(\215ag\).)2.5 E F1($)108 144 Q F0 .214
+(Expands to the process ID of the shell.)144 144 R .214
+(In a \(\) subshell, it e)5.214 F .214(xpands to the process ID of the current)
+-.15 F(shell, not the subshell.)144 156 Q F1(!)108 168 Q F0
+(Expands to the process ID of the most recently e)144 168 Q -.15(xe)-.15 G
+(cuted background \(asynchronous\) command.).15 E F1(0)108 180 Q F0 1.692
+(Expands to the name of the shell or shell script.)144 180 R 1.691
+(This is set at shell initialization.)6.692 F(If)6.691 E F1(bash)4.191 E F0(is)
+4.191 E(in)144 192 Q -.2(vo)-.4 G -.1(ke).2 G 3.077(dw).1 G .577
+(ith a \214le of commands,)185.817 192 R F1($0)3.077 E F0 .578
+(is set to the name of that \214le.)3.077 F(If)5.578 E F1(bash)3.078 E F0 .578
+(is started with the)3.078 F F1<ad63>3.078 E F0 .369(option, then)144 204 R F1
+($0)2.869 E F0 .369(is set to the \214rst ar)2.869 F .369
+(gument after the string to be e)-.18 F -.15(xe)-.15 G .369
+(cuted, if one is present.).15 F(Other)5.368 E(-)-.2 E
+(wise, it is set to the pathname used to in)144 216 Q -.2(vo)-.4 G -.1(ke).2 G
+F1(bash)2.6 E F0 2.5(,a)C 2.5(sg)354.13 216 S -2.15 -.25(iv e)365.52 216 T 2.5
+(nb).25 G 2.5(ya)389.84 216 S -.18(rg)401.78 216 S(ument zero.).18 E F1(_)108
+228 Q F0 .361(Expands to the last ar)144 228 R .362(gument to the pre)-.18 F
+.362(vious command, after e)-.25 F 2.862(xpansion. Also)-.15 F .362
+(set to the full path-)2.862 F(name of each command e)144 240 Q -.15(xe)-.15 G
+(cuted and placed in the en).15 E(vironment e)-.4 E(xported to that command.)
+-.15 E F1(Shell V)87 256.8 Q(ariables)-.92 E F0(The follo)108 268.8 Q(wing v)
+-.25 E(ariables are set by the shell:)-.25 E F1(PPID)108 285.6 Q F0
+(The process ID of the shell')144 285.6 Q 2.5(sp)-.55 G(arent.)266.2 285.6 Q F1
+(PWD)108 297.6 Q F0(The current w)144 297.6 Q(orking directory as set by the)
+-.1 E F1(cd)2.5 E F0(command.)2.5 E F1(OLDPWD)108 309.6 Q F0(The pre)144 321.6
+Q(vious w)-.25 E(orking directory as set by the)-.1 E F1(cd)2.5 E F0(command.)
+2.5 E F1(REPL)108 333.6 Q(Y)-.92 E F0(Set to the line of input read by the)144
+345.6 Q F1 -.18(re)2.5 G(ad).18 E F0 -.2(bu)2.5 G(iltin command when no ar).2 E
+(guments are supplied.)-.18 E F1(UID)108 357.6 Q F0
+(Expands to the user ID of the current user)144 357.6 Q 2.5(,i)-.4 G
+(nitialized at shell startup.)318.56 357.6 Q F1(EUID)108 369.6 Q F0
+(Expands to the ef)144 369.6 Q(fecti)-.25 E .3 -.15(ve u)-.25 H
+(ser ID of the current user).15 E 2.5(,i)-.4 G(nitialized at shell startup.)
+355.39 369.6 Q F1 -.3(BA)108 381.6 S(SH).3 E F0
+(Expands to the full pathname used to in)9.07 E -.2(vo)-.4 G .2 -.1(ke t).2 H
+(his instance of).1 E F1(bash)2.5 E F0(.)A F1 -.3(BA)108 393.6 S(SH_VERSION).3
+E F0(Expands to the v)144 405.6 Q(ersion number of this instance of)-.15 E F1
+(bash)2.5 E F0(.)A F1(SHL)108 417.6 Q(VL)-.92 E F0
+(Incremented by one each time an instance of)144 429.6 Q F1(bash)2.5 E F0
+(is started.)2.5 E F1(RANDOM)108 441.6 Q F0 .944
+(Each time this parameter is referenced, a random inte)144 453.6 R .943
+(ger is generated.)-.15 F .943(The sequence of random)5.943 F .91
+(numbers may be initialized by assigning a v)144 465.6 R .91(alue to)-.25 F/F2
+9/Times-Bold@0 SF(RANDOM)3.41 E/F3 9/Times-Roman@0 SF(.)A F0(If)5.41 E F2
+(RANDOM)3.41 E F0 .91(is unset, it loses its)3.16 F(special properties, e)144
+477.6 Q -.15(ve)-.25 G 2.5(ni).15 G 2.5(fi)243.02 477.6 S 2.5(ti)251.63 477.6 S
+2.5(ss)259.69 477.6 S(ubsequently reset.)269.97 477.6 Q F1(SECONDS)108 489.6 Q
+F0 .795
+(Each time this parameter is referenced, the number of seconds since shell in)
+144 501.6 R -.2(vo)-.4 G .795(cation is returned.).2 F .712(If a v)144 513.6 R
+.712(alue is assigned to)-.25 F F2(SECONDS)3.212 E F3(,)A F0 .712(the v)2.962 F
+.712(alue returned upon subsequent references is the number)-.25 F .408
+(of seconds since the assignment plus the v)144 525.6 R .408(alue assigned.)
+-.25 F(If)5.408 E F2(SECONDS)2.908 E F0 .407(is unset, it loses its special)
+2.658 F(properties, e)144 537.6 Q -.15(ve)-.25 G 2.5(ni).15 G 2.5(fi)212.75
+537.6 S 2.5(ti)221.36 537.6 S 2.5(ss)229.42 537.6 S(ubsequently reset.)239.7
+537.6 Q F1(LINENO)108 549.6 Q F0 1.408(Each time this parameter is referenced,\
+ the shell substitutes a decimal number representing the)144 561.6 R .078(curr\
+ent sequential line number \(starting with 1\) within a script or function.)144
+573.6 R .078(When not in a script or)5.078 F .603(function, the v)144 585.6 R
+.603(alue substituted is not guaranteed to be meaningful.)-.25 F .604
+(When in a function, the v)5.603 F(alue)-.25 E .601(is not the number of the s\
+ource line that the command appears on \(that information has been lost)144
+597.6 R .461(by the time the function is e)144 609.6 R -.15(xe)-.15 G .461
+(cuted\), b).15 F .461(ut is an approximation of the number of)-.2 F/F4 10
+/Times-Italic@0 SF .462(simple commands)2.962 F F0 -.15(exe)144 621.6 S 1.02
+(cuted in the current function.).15 F(If)6.019 E F2(LINENO)3.519 E F0 1.019
+(is unset, it loses its special properties, e)3.269 F -.15(ve)-.25 G 3.519(ni)
+.15 G 3.519(fi)517.402 621.6 S 3.519(ti)527.031 621.6 S(s)536.11 621.6 Q
+(subsequently reset.)144 633.6 Q F1(HISTCMD)108 645.6 Q F0 .355
+(The history number)144 657.6 R 2.855(,o)-.4 G 2.855(ri)233.545 657.6 S(nde)
+242.51 657.6 Q 2.856(xi)-.15 G 2.856(nt)267.436 657.6 S .356
+(he history list, of the current command.)278.072 657.6 R(If)5.356 E F2
+(HISTCMD)2.856 E F0 .356(is unset, it)2.606 F(loses its special properties, e)
+144 669.6 Q -.15(ve)-.25 G 2.5(ni).15 G 2.5(fi)277.47 669.6 S 2.5(ti)286.08
+669.6 S 2.5(ss)294.14 669.6 S(ubsequently reset.)304.42 669.6 Q F1(OPT)108
+681.6 Q(ARG)-.9 E F0 1.627(The v)144 693.6 R 1.627(alue of the last option ar)
+-.25 F 1.627(gument processed by the)-.18 F F1(getopts)4.127 E F0 -.2(bu)4.127
+G 1.626(iltin command \(see).2 F F2(SHELL)4.126 E -.09(BU)144 705.6 S(IL).09 E
+(TIN COMMANDS)-.828 E F0(belo)2.25 E(w\).)-.25 E 185.675(GNU 1995)72 768 R
+(May 5)2.5 E(5)535 768 Q EP
+%%Page: 6 6
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF(OPTIND)108 84 Q F0 1.651(The inde)144 96 R 4.151(xo)-.15
+G 4.151(ft)194.922 96 S 1.651(he ne)205.183 96 R 1.651(xt ar)-.15 F 1.652
+(gument to be processed by the)-.18 F F1(getopts)4.152 E F0 -.2(bu)4.152 G
+1.652(iltin command \(see).2 F/F2 9/Times-Bold@0 SF(SHELL)4.152 E -.09(BU)144
+108 S(IL).09 E(TIN COMMANDS)-.828 E F0(belo)2.25 E(w\).)-.25 E F1(HOSTTYPE)108
+120 Q F0 .223(Automatically set to a string that uniquely describes the type o\
+f machine on which)144 132 R F1(bash)2.722 E F0 .222(is e)2.722 F -.15(xe)-.15
+G(cut-).15 E 2.5(ing. The)144 144 R(def)2.5 E(ault is system-dependent.)-.1 E
+F1(OSTYPE)108 156 Q F0 .329
+(Automatically set to a string that describes the operating system on which)144
+168 R F1(bash)2.83 E F0 .33(is e)2.83 F -.15(xe)-.15 G 2.83(cuting. The).15 F
+(def)144 180 Q(ault is system-dependent.)-.1 E .994(The follo)108 196.8 R .994
+(wing v)-.25 F .994(ariables are used by the shell.)-.25 F .994(In some cases,)
+5.994 F F1(bash)3.494 E F0 .994(assigns a def)3.494 F .994(ault v)-.1 F .993
+(alue to a v)-.25 F(ariable;)-.25 E(these cases are noted belo)108 208.8 Q -.65
+(w.)-.25 G F1(IFS)108 225.6 Q F0(The)144 225.6 Q/F3 10/Times-Italic@0 SF .637
+(Internal F)3.137 F .637(ield Separ)-.45 F(ator)-.15 E F0 .637
+(that is used for w)3.137 F .638(ord splitting after e)-.1 F .638
+(xpansion and to split lines into)-.15 F -.1(wo)144 237.6 S(rds with the).1 E
+F1 -.18(re)2.5 G(ad).18 E F0 -.2(bu)2.5 G(iltin command.).2 E(The def)5 E
+(ault v)-.1 E(alue is `)-.25 E(`<space><tab><ne)-.74 E(wline>')-.25 E('.)-.74 E
+F1 -.74(PA)108 249.6 S(TH)-.21 E F0 .588(The search path for commands.)9.91 F
+.587(It is a colon-separated list of directories in which the shell looks)5.588
+F .211(for commands \(see)144 261.6 R F2 .212(COMMAND EXECUTION)2.712 F F0
+(belo)2.462 E 2.712(w\). The)-.25 F(def)2.712 E .212
+(ault path is system\255dependent, and)-.1 F 12.209
+(is set by the administrator who installs)144 273.6 R F1(bash)385.854 273.6 Q
+F0 17.209(.A)C 12.209(common v)447.502 273.6 R 12.209(alue is)-.25 F -.74(``)
+144 285.6 S(/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:.).74 E -.74('')
+-.7 G(.).74 E F1(HOME)108 297.6 Q F0
+(The home directory of the current user; the def)144 309.6 Q(ault ar)-.1 E
+(gument for the)-.18 E F1(cd)2.5 E F0 -.2(bu)2.5 G(iltin command.).2 E F1(CDP)
+108 321.6 Q -.95(AT)-.74 G(H).95 E F0 1.247(The search path for the)144 333.6 R
+F1(cd)3.747 E F0 3.747(command. This)3.747 F 1.248
+(is a colon-separated list of directories in which the)3.747 F
+(shell looks for destination directories speci\214ed by the)144 345.6 Q F1(cd)
+2.5 E F0 2.5(command. A)2.5 F(sample v)2.5 E(alue is `)-.25 E(`.:~:/usr')-.74 E
+('.)-.74 E F1(ENV)108 357.6 Q F0 .506(If this parameter is set when)144 357.6 R
+F1(bash)3.006 E F0 .506(is e)3.006 F -.15(xe)-.15 G .505
+(cuting a shell script, its v).15 F .505(alue is interpreted as a \214lename)
+-.25 F 1.968(containing commands to initialize the shell, as in)144 369.6 R F3
+(.bashr)4.469 E(c)-.37 E F0 6.969(.T).31 G 1.969(he v)403.037 369.6 R 1.969
+(alue of)-.25 F F2(ENV)4.469 E F0 1.969(is subjected to)4.219 F .47
+(parameter e)144 381.6 R .47(xpansion, command substitution, and arithmetic e)
+-.15 F .47(xpansion before being interpreted as)-.15 F 2.5(ap)144 393.6 S
+(athname.)155.94 393.6 Q F2 -.666(PA)5 G(TH)-.189 E F0
+(is not used to search for the resultant pathname.)2.25 E F1(MAIL)108 405.6 Q
+F0 .336(If this parameter is set to a \214lename and the)8.78 F F2(MAILP)2.837
+E -.855(AT)-.666 G(H).855 E F0 -.25(va)2.587 G .337(riable is not set,).25 F F1
+(bash)2.837 E F0 .337(informs the user)2.837 F(of the arri)144 417.6 Q -.25(va)
+-.25 G 2.5(lo).25 G 2.5(fm)202.65 417.6 S(ail in the speci\214ed \214le.)216.26
+417.6 Q F1(MAILCHECK)108 429.6 Q F0 .099(Speci\214es ho)144 441.6 R 2.599(wo)
+-.25 G .099(ften \(in seconds\))207.278 441.6 R F1(bash)2.598 E F0 .098
+(checks for mail.)2.598 F .098(The def)5.098 F .098(ault is 60 seconds.)-.1 F
+.098(When it is time)5.098 F .779
+(to check for mail, the shell does so before prompting.)144 453.6 R .779
+(If this v)5.779 F .779(ariable is unset, the shell disables)-.25 F
+(mail checking.)144 465.6 Q F1(MAILP)108 477.6 Q -.95(AT)-.74 G(H).95 E F0
+3.512(Ac)144 489.6 S 1.012(olon-separated list of pathnames to be check)159.172
+489.6 R 1.011(ed for mail.)-.1 F 1.011(The message to be printed may be)6.011 F
+.635(speci\214ed by separating the pathname from the message with a `?'.)144
+501.6 R .636($_ stands for the name of the)5.635 F(current mail\214le.)144
+513.6 Q(Example:)5 E F1(MAILP)144 525.6 Q -.95(AT)-.74 G(H).95 E F0
+(='/usr/spool/mail/bfox?"Y)A(ou ha)-1.1 E .3 -.15(ve m)-.2 H
+(ail":~/shell-mail?"$_ has mail!"').15 E F1(Bash)144 537.6 Q F0 .389
+(supplies a def)2.889 F .389(ault v)-.1 F .389(alue for this v)-.25 F .389
+(ariable, b)-.25 F .388
+(ut the location of the user mail \214les that it uses is)-.2 F
+(system dependent \(e.g., /usr/spool/mail/)144 549.6 Q F1($USER)A F0(\).)A F1
+(MAIL_W)108 561.6 Q(ARNING)-1.2 E F0 1.932(If set, and a \214le that)144 573.6
+R F1(bash)4.432 E F0 1.932
+(is checking for mail has been accessed since the last time it w)4.432 F(as)-.1
+E(check)144 585.6 Q(ed, the message `)-.1 E(`The mail in)-.74 E F3(mail\214le)
+2.5 E F0(has been read')2.5 E 2.5('i)-.74 G 2.5(sp)385.41 585.6 S(rinted.)396.8
+585.6 Q F1(PS1)108 597.6 Q F0 .065(The v)144 597.6 R .065
+(alue of this parameter is e)-.25 F .065(xpanded \(see)-.15 F F2(PR)2.565 E
+(OMPTING)-.27 E F0(belo)2.315 E .065(w\) and used as the primary prompt)-.25 F
+2.5(string. The)144 609.6 R(def)2.5 E(ault v)-.1 E(alue is `)-.25 E(`)-.74 E F1
+(bash\\$)A F0 -.74('')2.5 G(.).74 E F1(PS2)108 621.6 Q F0 .688(The v)144 621.6
+R .688(alue of this parameter is e)-.25 F .689
+(xpanded and used as the secondary prompt string.)-.15 F .689(The def)5.689 F
+.689(ault is)-.1 F -.74(``)144 633.6 S F1(>).74 E F0 -.74('')2.5 G(.).74 E F1
+(PS3)108 645.6 Q F0 1.15(The v)144 645.6 R 1.15
+(alue of this parameter is used as the prompt for the)-.25 F F3(select)3.649 E
+F0 1.149(command \(see)3.649 F F2 1.149(SHELL GRAM-)3.649 F(MAR)144 657.6 Q F0
+(abo)2.25 E -.15(ve)-.15 G(\).).15 E F1(PS4)108 669.6 Q F0 .628(The v)144 669.6
+R .628(alue of this parameter is e)-.25 F .629(xpanded and the v)-.15 F .629
+(alue is printed before each command)-.25 F F1(bash)3.129 E F0(dis-)3.129 E
+.702(plays during an e)144 681.6 R -.15(xe)-.15 G .701(cution trace.).15 F .701
+(The \214rst character of)5.701 F F2(PS4)3.201 E F0 .701
+(is replicated multiple times, as neces-)2.951 F(sary)144 693.6 Q 2.5(,t)-.65 G
+2.5(oi)167.79 693.6 S(ndicate multiple le)178.07 693.6 Q -.15(ve)-.25 G
+(ls of indirection.).15 E(The def)5 E(ault is `)-.1 E(`)-.74 E F1(+)A F0 -.74
+('')2.5 G(.).74 E F1(HISTSIZE)108 705.6 Q F0 1.942
+(The number of commands to remember in the command history \(see)144 717.6 R F2
+(HIST)4.443 E(OR)-.162 E(Y)-.315 E F0(belo)4.193 E 4.443(w\). The)-.25 F(def)
+144 729.6 Q(ault v)-.1 E(alue is 500.)-.25 E 185.675(GNU 1995)72 768 R(May 5)
+2.5 E(6)535 768 Q EP
+%%Page: 7 7
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF(HISTFILE)108 84 Q F0 1.386
+(The name of the \214le in which command history is sa)144 96 R -.15(ve)-.2 G
+3.886(d. \(See).15 F/F2 9/Times-Bold@0 SF(HIST)3.886 E(OR)-.162 E(Y)-.315 E F0
+(belo)3.636 E -.65(w.)-.25 G 6.386(\)T).65 G 1.385(he def)499.005 96 R(ault)-.1
+E -.25(va)144 108 S .034(lue is).25 F/F3 10/Times-Italic@0 SF(~/.bash_history)
+2.534 E F0 5.034(.I)C 2.534(fu)248.292 108 S .035
+(nset, the command history is not sa)259.156 108 R -.15(ve)-.2 G 2.535(dw).15 G
+.035(hen an interacti)424.04 108 R .335 -.15(ve s)-.25 H .035(hell e).15 F
+(xits.)-.15 E F1(HISTFILESIZE)108 120 Q F0 1.623
+(The maximum number of lines contained in the history \214le.)144 132 R 1.622
+(When this v)6.623 F 1.622(ariable is assigned a)-.25 F -.25(va)144 144 S .311
+(lue, the history \214le is truncated, if necessary).25 F 2.811(,t)-.65 G 2.811
+(oc)339.168 144 S .311(ontain no more than that number of lines.)351.419 144 R
+(The)5.312 E(def)144 156 Q(ault v)-.1 E(alue is 500.)-.25 E F1(OPTERR)108 168 Q
+F0 .39(If set to the v)144 180 R .39(alue 1,)-.25 F F1(bash)2.89 E F0 .389
+(displays error messages generated by the)2.889 F F1(getopts)2.889 E F0 -.2(bu)
+2.889 G .389(iltin command \(see).2 F F2 .359(SHELL B)144 192 R(UIL)-.09 E .359
+(TIN COMMANDS)-.828 F F0(belo)2.609 E(w\).)-.25 E F2(OPTERR)5.359 E F0 .36
+(is initialized to 1 each time the shell is in)2.609 F -.2(vo)-.4 G -.1(ke).2 G
+(d).1 E(or a shell script is e)144 204 Q -.15(xe)-.15 G(cuted.).15 E F1(PR)108
+216 Q(OMPT_COMMAND)-.3 E F0(If set, the v)144 228 Q(alue is e)-.25 E -.15(xe)
+-.15 G(cuted as a command prior to issuing each primary prompt.).15 E F1
+(IGNOREEOF)108 240 Q F0 .14(Controls the action of the shell on receipt of an)
+144 252 R F2(EOF)2.639 E F0 .139(character as the sole input.)2.389 F .139
+(If set, the v)5.139 F .139(alue is)-.25 F 1.493(the number of consecuti)144
+264 R -.15(ve)-.25 G F2(EOF)4.143 E F0 1.494
+(characters typed as the \214rst characters on an input line before)3.744 F F1
+(bash)144 276 Q F0 -.15(ex)3.333 G 3.333(its. If).15 F .833(the v)3.333 F .832
+(ariable e)-.25 F .832(xists b)-.15 F .832(ut does not ha)-.2 F 1.132 -.15
+(ve a n)-.2 H .832(umeric v).15 F .832(alue, or has no v)-.25 F .832
+(alue, the def)-.25 F(ault)-.1 E -.25(va)144 288 S .585(lue is 10.).25 F .585
+(If it does not e)5.585 F(xist,)-.15 E F2(EOF)3.085 E F0 .586
+(signi\214es the end of input to the shell.)2.835 F .586(This is only in ef)
+5.586 F(fect)-.25 E(for interacti)144 300 Q .3 -.15(ve s)-.25 H(hells.).15 E F1
+(TMOUT)108 312 Q F0 1.113(If set to a v)144 324 R 1.113
+(alue greater than zero, the v)-.25 F 1.112
+(alue is interpreted as the number of seconds to w)-.25 F 1.112(ait for)-.1 F
+.558(input after issuing the primary prompt.)144 336 R F1(Bash)5.558 E F0 .558
+(terminates after w)3.058 F .558(aiting for that number of seconds)-.1 F
+(if input does not arri)144 348 Q -.15(ve)-.25 G(.).15 E F1(FCEDIT)108 360 Q F0
+(The def)144 372 Q(ault editor for the)-.1 E F1(fc)2.5 E F0 -.2(bu)2.5 G
+(iltin command.).2 E F1(FIGNORE)108 384 Q F0 2.599(Ac)144 396 S .098
+(olon-separated list of suf)158.259 396 R<8c78>-.25 E .098
+(es to ignore when performing \214lename completion \(see)-.15 F F2(READLINE)
+2.598 E F0(belo)144 408 Q 2.704(w\). A)-.25 F .204(\214lename whose suf)2.704 F
+.205(\214x matches one of the entries in)-.25 F F2(FIGNORE)2.705 E F0 .205
+(is e)2.455 F .205(xcluded from the list)-.15 F(of matched \214lenames.)144 420
+Q 2.5(As)5 G(ample v)250.65 420 Q(alue is `)-.25 E(`.o:~')-.74 E('.)-.74 E F1
+(INPUTRC)108 432 Q F0 1.637(The \214lename for the readline startup \214le, o)
+144 444 R -.15(ve)-.15 G 1.637(rriding the def).15 F 1.636(ault of)-.1 F F3
+(~/.inputr)5.802 E(c)-.37 E F0(\(see)5.802 E F2(READLINE)4.136 E F0(belo)144
+456 Q(w\).)-.25 E F1(notify)108 468 Q F0 .031(If set,)144 468 R F1(bash)2.531 E
+F0 .031(reports terminated background jobs immediately)2.531 F 2.532(,r)-.65 G
+.032(ather than w)394.13 468 R .032(aiting until before print-)-.1 F
+(ing the ne)144 480 Q(xt primary prompt \(see also the)-.15 E F1<ad62>2.5 E F0
+(option to the)2.5 E F1(set)2.5 E F0 -.2(bu)2.5 G(iltin command\).).2 E F1
+(history_contr)108 492 Q(ol)-.18 E(HISTCONTR)108 504 Q(OL)-.3 E F0 .881
+(If set to a v)144 516 R .881(alue of)-.25 F F3(ignor)3.381 E(espace)-.37 E F0
+3.381(,l).18 G .881(ines which be)281.367 516 R .881(gin with a)-.15 F F1
+(space)3.38 E F0 .88(character are not entered on the)3.38 F .401
+(history list.)144 528 R .401(If set to a v)5.401 F .401(alue of)-.25 F F3
+(ignor)2.901 E(edups)-.37 E F0 2.901(,l).27 G .401
+(ines matching the last history line are not entered.)325.029 528 R(A)5.402 E
+-.25(va)144 540 S 1.304(lue of).25 F F3(ignor)3.804 E(eboth)-.37 E F0 1.304
+(combines the tw)3.804 F 3.804(oo)-.1 G 3.804(ptions. If)310.534 540 R 1.303
+(unset, or if set to an)3.804 F 3.803(yo)-.15 G 1.303(ther v)453.301 540 R
+1.303(alue than those)-.25 F(abo)144 552 Q -.15(ve)-.15 G 2.5(,a).15 G
+(ll lines read by the parser are sa)177.02 552 Q -.15(ve)-.2 G 2.5(do).15 G 2.5
+(nt)324.96 552 S(he history list.)335.24 552 Q F1(command_oriented_history)108
+568.8 Q F0 .472(If set,)144 580.8 R F1(bash)2.973 E F0 .473(attempts to sa)
+2.973 F .773 -.15(ve a)-.2 H .473
+(ll lines of a multiple\255line command in the same history entry).15 F 5.473
+(.T)-.65 G(his)528.33 580.8 Q(allo)144 592.8 Q
+(ws easy re\255editing of multi\255line commands.)-.25 E F1
+(glob_dot_\214lenames)108 609.6 Q F0(If set,)144 621.6 Q F1(bash)2.5 E F0
+(includes \214lenames be)2.5 E(ginning with a `.)-.15 E 2.5('i)-.7 G 2.5(nt)
+351.75 621.6 S(he results of pathname e)362.03 621.6 Q(xpansion.)-.15 E F1
+(allo)108 638.4 Q(w_null_glob_expansion)-.1 E F0 .652(If set,)144 650.4 R F1
+(bash)3.152 E F0(allo)3.152 E .651
+(ws pathname patterns which match no \214les \(see)-.25 F F1 -.1(Pa)3.151 G
+.651(thname Expansion).1 F F0(belo)3.151 E .651(w\) to)-.25 F -.15(ex)144 662.4
+S(pand to a null string, rather than themselv).15 E(es.)-.15 E F1(histchars)108
+679.2 Q F0 2.069(The tw)144 691.2 R 4.57(oo)-.1 G 4.57(rt)188.589 691.2 S 2.07
+(hree characters which control history e)199.269 691.2 R 2.07(xpansion and tok)
+-.15 F 2.07(enization \(see)-.1 F F2(HIST)4.57 E(OR)-.162 E(Y)-.315 E(EXP)144
+703.2 Q(ANSION)-.666 E F0(belo)2.965 E 3.215(w\). The)-.25 F .714
+(\214rst character is the)3.215 F F3 .714(history e)3.214 F .714(xpansion c)-.2
+F(har)-.15 E(acter)-.15 E F0 3.214(,t).73 G .714(hat is, the character)460.108
+703.2 R .141(which signals the start of a history e)144 715.2 R .141
+(xpansion, normally `)-.15 F F1(!)A F0 2.641('. The)B .142
+(second character is the)2.641 F F3(quic)2.642 E 2.642(ks)-.2 G(ub-)526.67
+715.2 Q(stitution)144 727.2 Q F0(character)4.635 E 4.635(,w)-.4 G 2.134
+(hich is used as shorthand for re-running the pre)232.02 727.2 R 2.134
+(vious command entered,)-.25 F 185.675(GNU 1995)72 768 R(May 5)2.5 E(7)535 768
+Q EP
+%%Page: 8 8
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+.466(substituting one string for another in the command.)144 84 R .466(The def)
+5.466 F .466(ault is `)-.1 F/F1 10/Times-Bold@0 SF(^)A F0 2.966('. The)B .466
+(optional third charac-)2.966 F .414(ter is the character which signi\214es th\
+at the remainder of the line is a comment, when found as the)144 96 R .389
+(\214rst character of a w)144 108 R .389(ord, normally `)-.1 F F1(#)A F0 2.889
+('. The)B .39(history comment character causes history substitution)2.889 F .25
+(to be skipped for the remaining w)144 120 R .25(ords on the line.)-.1 F .25
+(It does not necessarily cause the shell parser to)5.25 F
+(treat the rest of the line as a comment.)144 132 Q F1(nolinks)108 148.8 Q F0
+.44(If set, the shell does not follo)144 160.8 R 2.94(ws)-.25 G .44
+(ymbolic links when e)276.82 160.8 R -.15(xe)-.15 G .44
+(cuting commands that change the current).15 F -.1(wo)144 172.8 S .981
+(rking directory).1 F 5.981(.I)-.65 G 3.481(tu)227.972 172.8 S .981(ses the ph)
+239.233 172.8 R .981(ysical directory structure instead.)-.05 F .981(By def)
+5.981 F(ault,)-.1 E F1(bash)3.48 E F0(follo)3.48 E .98(ws the)-.25 F .585(logi\
+cal chain of directories when performing commands which change the current dir\
+ectory)144 184.8 R 3.085(,s)-.65 G(uch)525.56 184.8 Q(as)144 196.8 Q F1(cd)2.65
+E F0 5.15(.S)C .149(ee also the description of the)178.19 196.8 R F1<ad50>2.649
+E F0 .149(option to the)2.649 F F1(set)2.649 E F0 -.2(bu)2.649 G .149(iltin \()
+.2 F/F2 9/Times-Bold@0 SF .149(SHELL B)2.649 F(UIL)-.09 E .149(TIN COMMANDS)
+-.828 F F0(belo)144 208.8 Q(w\).)-.25 E F1(hostname_completion_\214le)108 220.8
+Q(HOSTFILE)108 232.8 Q F0 1.015
+(Contains the name of a \214le in the same format as)144 244.8 R/F3 10
+/Times-Italic@0 SF(/etc/hosts)5.181 E F0 1.015
+(that should be read when the shell)5.181 F 1.425
+(needs to complete a hostname.)144 256.8 R 1.424
+(The \214le may be changed interacti)6.424 F -.15(ve)-.25 G 1.424(ly; the ne)
+.15 F 1.424(xt time hostname)-.15 F(completion is attempted)144 268.8 Q F1
+(bash)2.5 E F0(adds the contents of the ne)2.5 E 2.5<778c>-.25 G
+(le to the already e)386.52 268.8 Q(xisting database.)-.15 E F1(noclob)108
+285.6 Q(ber)-.1 E F0 .38(If set,)144 297.6 R F1(bash)2.88 E F0 .38(does not o)
+2.88 F -.15(ve)-.15 G .38(rwrite an e).15 F .381(xisting \214le with the)-.15 F
+F1(>)2.881 E F0(,)A F1(>&)2.881 E F0 2.881(,a)C(nd)403.766 297.6 Q F1(<>)2.881
+E F0 .381(redirection operators.)2.881 F(This)5.381 E -.25(va)144 309.6 S .465
+(riable may be o).25 F -.15(ve)-.15 G .464
+(rridden when creating output \214les by using the redirection operator).15 F
+F1(>|)2.964 E F0(instead)2.964 E(of)144 321.6 Q F1(>)2.5 E F0(\(see also the)
+2.5 E F1<ad43>2.5 E F0(option to the)2.5 E F1(set)2.5 E F0 -.2(bu)2.5 G
+(iltin command\).).2 E F1(auto_r)108 338.4 Q(esume)-.18 E F0 .53(This v)144
+350.4 R .53(ariable controls ho)-.25 F 3.03(wt)-.25 G .531
+(he shell interacts with the user and job control.)257.83 350.4 R .531
+(If this v)5.531 F .531(ariable is set,)-.25 F .539(single w)144 362.4 R .538(\
+ord simple commands without redirections are treated as candidates for resumpt\
+ion of an)-.1 F -.15(ex)144 374.4 S .366(isting stopped job).15 F 5.366(.T)-.4
+G .366(here is no ambiguity allo)238.718 374.4 R .366
+(wed; if there is more than one job be)-.25 F .367(ginning with)-.15 F 1.157
+(the string typed, the job most recently accessed is selected.)144 386.4 R(The)
+6.156 E F3(name)3.656 E F0 1.156(of a stopped job, in this)3.656 F(conte)144
+398.4 Q 1.132(xt, is the command line used to start it.)-.15 F 1.133
+(If set to the v)6.133 F(alue)-.25 E F3 -.2(ex)3.633 G(act).2 E F0 3.633(,t).68
+G 1.133(he string supplied must)443.541 398.4 R .625
+(match the name of a stopped job e)144 410.4 R .624(xactly; if set to)-.15 F F3
+(substring)3.124 E F0 3.124(,t).22 G .624(he string supplied needs to match a)
+395.716 410.4 R .924(substring of the name of a stopped job)144 422.4 R 5.924
+(.T)-.4 G(he)317.642 422.4 Q F3(substring)3.424 E F0 -.25(va)3.424 G .925
+(lue pro).25 F .925(vides functionality analogous to)-.15 F(the)144 434.4 Q F1
+(%?)2.545 E F0 .045(job id \(see)5.045 F F2 .044(JOB CONTR)2.545 F(OL)-.27 E F0
+(belo)2.294 E 2.544(w\). If)-.25 F .044(set to an)2.544 F 2.544(yo)-.15 G .044
+(ther v)380.512 434.4 R .044(alue, the supplied string must be a)-.25 F
+(pre\214x of a stopped job')144 446.4 Q 2.5(sn)-.55 G(ame; this pro)248.16
+446.4 Q(vides functionality analogous to the)-.15 E F1(%)2.5 E F0(job id.)2.5 E
+F1(no_exit_on_failed_exec)108 463.2 Q F0 .69(If this v)144 475.2 R .69
+(ariable e)-.25 F .69(xists, a non-interacti)-.15 F .99 -.15(ve s)-.25 H .691
+(hell will not e).15 F .691(xit if it cannot e)-.15 F -.15(xe)-.15 G .691
+(cute the \214le speci\214ed in).15 F(the)144 487.2 Q F1(exec)2.5 E F0 -.2(bu)
+2.5 G(iltin command.).2 E(An interacti)5 E .3 -.15(ve s)-.25 H(hell does not e)
+.15 E(xit if)-.15 E F1(exec)2.5 E F0 -.1(fa)2.5 G(ils.).1 E F1(cdable_v)108 504
+Q(ars)-.1 E F0 .834(If this is set, an ar)144 516 R .834(gument to the)-.18 F
+F1(cd)3.334 E F0 -.2(bu)3.334 G .834
+(iltin command that is not a directory is assumed to be the).2 F(name of a v)
+144 528 Q(ariable whose v)-.25 E(alue is the directory to change to.)-.25 E F2
+(EXP)72 544.8 Q(ANSION)-.666 E F0 .76
+(Expansion is performed on the command line after it has been split into w)108
+556.8 R 3.26(ords. There)-.1 F .76(are se)3.26 F -.15(ve)-.25 G 3.26(nk).15 G
+.76(inds of)511.74 556.8 R -.15(ex)108 568.8 S .37(pansion performed:).15 F F3
+(br)2.869 E .369(ace e)-.15 F(xpansion)-.2 E F0(,).24 E F3 .369(tilde e)2.869 F
+(xpansion)-.2 E F0(,).24 E F3(par)2.869 E .369(ameter and variable e)-.15 F
+(xpansion)-.2 E F0(,).24 E F3 .369(command sub-)2.869 F(stitution)108 580.8 Q
+F0(,).24 E F3(arithmetic e)2.5 E(xpansion)-.2 E F0(,).24 E F3(wor)2.5 E 2.5(ds)
+-.37 G(plitting)261.81 580.8 Q F0 2.5(,a).22 G(nd)300.37 580.8 Q F3(pathname e)
+2.5 E(xpansion)-.2 E F0(.).24 E .16(The order of e)108 597.6 R .16
+(xpansions is: brace e)-.15 F .16(xpansion, tilde e)-.15 F .16
+(xpansion, parameter)-.15 F 2.66(,v)-.4 G .16(ariable, command, and arithmetic)
+405.38 597.6 R(substitution \(done in a left\255to\255right f)108 609.6 Q
+(ashion\), w)-.1 E(ord splitting, and pathname e)-.1 E(xpansion.)-.15 E
+(On systems that can support it, there is an additional e)108 626.4 Q
+(xpansion a)-.15 E -.25(va)-.2 G(ilable:).25 E F3(pr)2.5 E(ocess substitution)
+-.45 E F0(.)A 1.487(Only brace e)108 643.2 R 1.487(xpansion, w)-.15 F 1.487
+(ord splitting, and pathname e)-.1 F 1.487(xpansion can change the number of w)
+-.15 F 1.486(ords of the)-.1 F -.15(ex)108 655.2 S 1.36(pansion; other e).15 F
+1.36(xpansions e)-.15 F 1.36(xpand a single w)-.15 F 1.36(ord to a single w)-.1
+F 3.86(ord. The)-.1 F 1.36(single e)3.86 F 1.36(xception to this is the)-.15 F
+-.15(ex)108 667.2 S(pansion of `).15 E(`)-.74 E F1($@)A F0 1.48 -.74('' a)D 2.5
+(se).74 G(xplained abo)205.49 667.2 Q .3 -.15(ve \()-.15 H(see).15 E F2 -.666
+(PA)2.5 G(RAMETERS).666 E/F4 9/Times-Roman@0 SF(\).)A F1(Brace Expansion)87 684
+Q F3(Br)108 696 Q .661(ace e)-.15 F(xpansion)-.2 E F0 .661
+(is a mechanism by which arbitrary strings may be generated.)3.161 F .66
+(This mechanism is similar)5.66 F(to)108 708 Q F3 .415(pathname e)2.915 F
+(xpansion)-.2 E F0 2.915(,b)C .415(ut the \214lenames generated need not e)
+211.615 708 R 2.915(xist. P)-.15 F .415(atterns to be brace e)-.15 F .415
+(xpanded tak)-.15 F 2.915(et)-.1 G(he)530.56 708 Q .889(form of an optional)108
+720 R F3(pr)3.388 E(eamble)-.37 E F0 3.388(,f).18 G(ollo)238.342 720 Q .888
+(wed by a series of comma-separated strings between a pair of braces,)-.25 F
+185.675(GNU 1995)72 768 R(May 5)2.5 E(8)535 768 Q EP
+%%Page: 9 9
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+(follo)108 84 Q .402(wed by an optional)-.25 F/F1 10/Times-Italic@0 SF
+(postamble)2.902 E F0 5.402(.T).18 G .402
+(he preamble is prepended to each string contained within the braces,)262.43 84
+R(and the postamble is then appended to each resulting string, e)108 96 Q
+(xpanding left to right.)-.15 E .719(Brace e)108 112.8 R .719
+(xpansions may be nested.)-.15 F .719(The results of each e)5.719 F .719
+(xpanded string are not sorted; left to right order is)-.15 F(preserv)108 124.8
+Q 2.5(ed. F)-.15 F(or e)-.15 E(xample, a)-.15 E/F2 10/Times-Bold@0 SF({)A F0
+(d,c,b)A F2(})A F0 2.5(ee)C(xpands into `ade ace abe'.)252.18 124.8 Q .581
+(Brace e)108 141.6 R .581(xpansion is performed before an)-.15 F 3.081(yo)-.15
+G .581(ther e)283.356 141.6 R .581(xpansions, and an)-.15 F 3.082(yc)-.15 G
+.582(haracters special to other e)391.192 141.6 R(xpansions)-.15 E .016
+(are preserv)108 153.6 R .016(ed in the result.)-.15 F .016(It is strictly te)
+5.016 F(xtual.)-.15 E F2(Bash)5.016 E F0 .015(does not apply an)2.516 F 2.515
+(ys)-.15 G .015(yntactic interpretation to the con-)406.63 153.6 R(te)108 165.6
+Q(xt of the e)-.15 E(xpansion or the te)-.15 E(xt between the braces.)-.15 E
+3.632(Ac)108 182.4 S 1.132(orrectly-formed brace e)123.292 182.4 R 1.132
+(xpansion must contain unquoted opening and closing braces, and at least one)
+-.15 F(unquoted comma.)108 194.4 Q(An)5 E 2.5(yi)-.15 G
+(ncorrectly formed brace e)207.01 194.4 Q(xpansion is left unchanged.)-.15 E
+1.476(This construct is typically used as shorthand when the common pre\214x o\
+f the strings to be generated is)108 211.2 R(longer than in the abo)108 223.2 Q
+.3 -.15(ve ex)-.15 H(ample:).15 E(mkdir /usr/local/src/bash/{old,ne)144 240 Q
+-.65(w,)-.25 G(dist,b).65 E(ugs})-.2 E(or)108 252 Q(cho)144 264 Q
+(wn root /usr/{ucb/{e)-.25 E(x,edit},lib/{e)-.15 E(x?.?*,ho)-.15 E(w_e)-.25 E
+(x}})-.15 E 1.177(Brace e)108 280.8 R 1.177
+(xpansion introduces a slight incompatibility with traditional v)-.15 F 1.177
+(ersions of)-.15 F F2(sh)3.677 E F0 3.677(,t)C 1.177(he Bourne shell.)456.747
+280.8 R F2(sh)6.178 E F0 .015
+(does not treat opening or closing braces specially when the)108 292.8 R 2.515
+(ya)-.15 G .015(ppear as part of a w)355.73 292.8 R .014(ord, and preserv)-.1 F
+.014(es them in)-.15 F .693(the output.)108 304.8 R F2(Bash)5.693 E F0(remo)
+3.193 E -.15(ve)-.15 G 3.193(sb).15 G .694(races from w)223.252 304.8 R .694
+(ords as a consequence of brace e)-.1 F 3.194(xpansion. F)-.15 F .694(or e)-.15
+F .694(xample, a w)-.15 F(ord)-.1 E 1.45(entered to)108 316.8 R F2(sh)3.95 E F0
+(as)3.95 E F1(\214le{1,2})3.95 E F0 1.45(appears identically in the output.)
+3.95 F 1.45(The same w)6.45 F 1.45(ord is output as)-.1 F F1 1.45
+(\214le1 \214le2)3.95 F F0(after)3.95 E -.15(ex)108 328.8 S .576(pansion by).15
+F F2(bash)3.076 E F0 5.576(.I)C 3.076(fs)195.968 328.8 S .576
+(trict compatibility with)206.264 328.8 R F2(sh)3.077 E F0 .577
+(is desired, start)3.077 F F2(bash)3.077 E F0 .577(with the)3.077 F F2
+(\255nobraceexpansion)3.077 E F0(\215ag)3.077 E(\(see)108 340.8 Q/F3 9
+/Times-Bold@0 SF(OPTIONS)2.598 E F0(abo)2.348 E -.15(ve)-.15 G 2.598(\)o).15 G
+2.598(rd)204.063 340.8 S .098(isable brace e)214.991 340.8 R .098
+(xpansion with the)-.15 F F2 .097(+o braceexpand)2.598 F F0 .097(option to the)
+2.597 F F2(set)2.597 E F0 .097(command \(see)2.597 F F3(SHELL B)108 352.8 Q
+(UIL)-.09 E(TIN COMMANDS)-.828 E F0(belo)2.25 E(w\).)-.25 E F2 -.18(Ti)87 369.6
+S(lde Expansion).18 E F0 .432(If a w)108 381.6 R .432(ord be)-.1 F .432
+(gins with a tilde character \(`)-.15 F F2(~)A F0 .433
+('\), all of the characters preceding the \214rst slash \(or all characters,)B
+.986(if there is no slash\) are treated as a possible)108 393.6 R F1(lo)3.486 E
+.985(gin name)-.1 F F0 3.485(.I)C 3.485(ft)348.85 393.6 S(his)358.445 393.6 Q
+F1(lo)3.485 E .985(gin name)-.1 F F0 .985(is the null string, the tilde is)
+3.485 F .353(replaced with the v)108 405.6 R .353(alue of the parameter)-.25 F
+F3(HOME)2.853 E/F4 9/Times-Roman@0 SF(.)A F0(If)4.853 E F3(HOME)2.854 E F0 .354
+(is unset, the home directory of the user e)2.604 F -.15(xe)-.15 G(cut-).15 E
+(ing the shell is substituted instead.)108 417.6 Q .638(If a `+' follo)108
+434.4 R .638(ws the tilde, the v)-.25 F .638(alue of)-.25 F F3(PWD)3.138 E F0
+.638(replaces the tilde and `+'.)2.888 F .638(If a `\255' follo)5.638 F .638
+(ws, the v)-.25 F .637(alue of)-.25 F F3(OLD-)3.137 E(PWD)108 446.4 Q F0 1.345
+(is substituted.)3.595 F 1.345(If the v)6.345 F 1.345(alue follo)-.25 F 1.345
+(wing the tilde is a v)-.25 F(alid)-.25 E F1(lo)3.846 E 1.346(gin name)-.1 F F0
+3.846(,t)C 1.346(he tilde and)424.78 446.4 R F1(lo)3.846 E 1.346(gin name)-.1 F
+F0(are)3.846 E .659
+(replaced with the home directory associated with that name.)108 458.4 R .659
+(If the name is in)5.659 F -.25(va)-.4 G .658(lid, or the tilde e).25 F
+(xpansion)-.15 E -.1(fa)108 470.4 S(ils, the w).1 E(ord is unchanged.)-.1 E
+1.162(Each v)108 487.2 R 1.162(ariable assignment is check)-.25 F 1.162
+(ed for unquoted instances of tildes follo)-.1 F 1.162(wing a)-.25 F F2(:)3.663
+E F0(or)3.663 E F2(=)3.663 E F0 6.163(.I)C 3.663(nt)483.524 487.2 S 1.163
+(hese cases,)494.967 487.2 R 1.043(tilde substitution is also performed.)108
+499.2 R(Consequently)6.043 E 3.543(,o)-.65 G 1.043
+(ne may use pathnames with tildes in assignments to)324.998 499.2 R F3 -.666
+(PA)108 511.2 S(TH)-.189 E F4(,)A F3(MAILP)2.25 E -.855(AT)-.666 G(H).855 E F4
+(,)A F0(and)2.25 E F3(CDP)2.5 E -.855(AT)-.666 G(H).855 E F4(,)A F0
+(and the shell assigns the e)2.25 E(xpanded v)-.15 E(alue.)-.25 E F2 -.1(Pa)87
+528 S(rameter Expansion).1 E F0 1.605(The `)108 540 R F2($)A F0 4.105('c)C
+1.605(haracter introduces parameter e)147.86 540 R 1.606
+(xpansion, command substitution, or arithmetic e)-.15 F 4.106(xpansion. The)
+-.15 F .407(parameter name or symbol to be e)108 552 R .407
+(xpanded may be enclosed in braces, which are optional b)-.15 F .406(ut serv)
+-.2 F 2.906(et)-.15 G 2.906(op)515.434 552 S(ro-)528.34 552 Q .032(tect the v)
+108 564 R .032(ariable to be e)-.25 F .032
+(xpanded from characters immediately follo)-.15 F .033
+(wing it which could be interpreted as part)-.25 F(of the name.)108 576 Q(${)
+108 592.8 Q F1(par)A(ameter)-.15 E F0(})A 1.346(The v)144 604.8 R 1.346
+(alue of)-.25 F F1(par)3.846 E(ameter)-.15 E F0 1.346(is substituted.)3.846 F
+1.346(The braces are required when)6.346 F F1(par)3.845 E(ameter)-.15 E F0
+1.345(is a positional)3.845 F .38(parameter with more than one digit, or when)
+144 616.8 R F1(par)2.881 E(ameter)-.15 E F0 .381(is follo)2.881 F .381
+(wed by a character which is not to)-.25 F(be interpreted as part of its name.)
+144 628.8 Q .334(In each of the cases belo)108 645.6 R -.65(w,)-.25 G F1(wor)
+3.484 E(d)-.37 E F0 .334(is subject to tilde e)2.834 F .334
+(xpansion, parameter e)-.15 F .334(xpansion, command substitution,)-.15 F .861
+(and arithmetic e)108 657.6 R(xpansion.)-.15 E F2(Bash)5.861 E F0 .862
+(tests for a parameter that is unset or null; omitting the colon results in a)
+3.361 F(test only for a parameter that is unset.)108 669.6 Q(${)108 686.4 Q F1
+(par)A(ameter)-.15 E F2<3aad>A F1(wor)A(d)-.37 E F0(})A F2 .929(Use Default V)
+144 698.4 R(alues)-.92 E F0 5.929(.I)C(f)237.797 698.4 Q F1(par)3.429 E(ameter)
+-.15 E F0 .929(is unset or null, the e)3.429 F .928(xpansion of)-.15 F F1(wor)
+3.428 E(d)-.37 E F0 .928(is substituted.)3.428 F(Other)5.928 E(-)-.2 E
+(wise, the v)144 710.4 Q(alue of)-.25 E F1(par)2.5 E(ameter)-.15 E F0
+(is substituted.)2.5 E 185.675(GNU 1995)72 768 R(May 5)2.5 E(9)535 768 Q EP
+%%Page: 10 10
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+(${)108 84 Q/F1 10/Times-Italic@0 SF(par)A(ameter)-.15 E/F2 10/Times-Bold@0 SF
+(:=)A F1(wor)A(d)-.37 E F0(})A F2 .085(Assign Default V)144 96 R(alues)-.92 E
+F0 5.085(.I)C(f)248.055 96 Q F1(par)2.585 E(ameter)-.15 E F0 .086
+(is unset or null, the e)2.585 F .086(xpansion of)-.15 F F1(wor)2.586 E(d)-.37
+E F0 .086(is assigned to)2.586 F F1(par)2.586 E(am-)-.15 E(eter)144 108 Q F0
+6.311(.T).73 G 1.311(he v)175.201 108 R 1.311(alue of)-.25 F F1(par)3.811 E
+(ameter)-.15 E F0 1.311(is then substituted.)3.811 F 1.311
+(Positional parameters and special parameters)6.311 F
+(may not be assigned to in this w)144 120 Q(ay)-.1 E(.)-.65 E(${)108 132 Q F1
+(par)A(ameter)-.15 E F2(:?)A F1(wor)A(d)-.37 E F0(})A F2 .645(Display Err)144
+144 R .645(or if Null or Unset)-.18 F F0 5.645(.I)C(f)286.57 144 Q F1(par)3.145
+E(ameter)-.15 E F0 .645(is null or unset, the e)3.145 F .645(xpansion of)-.15 F
+F1(wor)3.145 E(d)-.37 E F0 .645(\(or a mes-)3.145 F .715(sage to that ef)144
+156 R .715(fect if)-.25 F F1(wor)3.215 E(d)-.37 E F0 .714
+(is not present\) is written to the standard error and the shell, if it is not)
+3.215 F(interacti)144 168 Q -.15(ve)-.25 G 2.5(,e).15 G 2.5(xits. Otherwise,)
+195.1 168 R(the v)2.5 E(alue of)-.25 E F1(par)2.5 E(ameter)-.15 E F0
+(is substituted.)2.5 E(${)108 180 Q F1(par)A(ameter)-.15 E F2(:+)A F1(wor)A(d)
+-.37 E F0(})A F2 .886(Use Alter)144 192 R .886(nate V)-.15 F(alue)-.92 E F0
+5.886(.I)C(f)242.508 192 Q F1(par)3.386 E(ameter)-.15 E F0 .887
+(is null or unset, nothing is substituted, otherwise the e)3.386 F(xpan-)-.15 E
+(sion of)144 204 Q F1(wor)2.5 E(d)-.37 E F0(is substituted.)2.5 E(${)108 216 Q
+F2(#)A F1(par)A(ameter)-.15 E F0(})A 1.509(The length in characters of the v)
+144 228 R 1.508(alue of)-.25 F F1(par)4.008 E(ameter)-.15 E F0 1.508
+(is substituted.)4.008 F(If)6.508 E F1(par)4.008 E(ameter)-.15 E F0(is)4.008 E
+F2(*)4.008 E F0(or)4.008 E F2(@)4.008 E F0 4.008(,t)C(he)530.56 228 Q
+(length substituted is the length of)144 240 Q F2(*)2.5 E F0 -.15(ex)2.5 G
+(panded within double quotes.).15 E(${)108 252 Q F1(par)A(ameter)-.15 E F2(#)A
+F1(wor)A(d)-.37 E F0(})A(${)108 264 Q F1(par)A(ameter)-.15 E F2(##)A F1(wor)A
+(d)-.37 E F0(})A(The)144 276 Q F1(wor)3.06 E(d)-.37 E F0 .56(is e)3.06 F .56
+(xpanded to produce a pattern just as in pathname e)-.15 F 3.06(xpansion. If)
+-.15 F .56(the pattern matches)3.06 F 1.183(the be)144 288 R 1.183
+(ginning of the v)-.15 F 1.183(alue of)-.25 F F1(par)3.683 E(ameter)-.15 E F0
+3.683(,t).73 G 1.183(hen the e)319.661 288 R 1.182(xpansion is the v)-.15 F
+1.182(alue of)-.25 F F1(par)3.682 E(ameter)-.15 E F0 1.182(with the)3.682 F .17
+(shortest matching pattern deleted \(the `)144 300 R(`)-.74 E F2(#)A F0 1.651
+-.74('' c)D .171(ase\) or the longest matching pattern deleted \(the `).74 F(`)
+-.74 E F2(##)A F0 -.74('')C(case\).)144 312 Q(${)108 328.8 Q F1(par)A(ameter)
+-.15 E F2(%)A F1(wor)A(d)-.37 E F0(})A(${)108 340.8 Q F1(par)A(ameter)-.15 E F2
+(%%)A F1(wor)A(d)-.37 E F0(})A(The)144 352.8 Q F1(wor)2.619 E(d)-.37 E F0 .119
+(is e)2.619 F .119(xpanded to produce a pattern just as in pathname e)-.15 F
+2.619(xpansion. If)-.15 F .118(the pattern matches a)2.619 F .825
+(trailing portion of the v)144 364.8 R .825(alue of)-.25 F F1(par)3.325 E
+(ameter)-.15 E F0 3.326(,t).73 G .826(hen the e)322.866 364.8 R .826
+(xpansion is the v)-.15 F .826(alue of)-.25 F F1(par)3.326 E(ameter)-.15 E F0
+.826(with the)3.326 F 1.672(shortest matching pattern deleted \(the `)144 376.8
+R(`)-.74 E F2(%)A F0 3.152 -.74('' c)D 1.671
+(ase\) or the longest matching pattern deleted \(the).74 F -.74(``)144 388.8 S
+F2(%%).74 E F0 1.48 -.74('' c)D(ase\).).74 E F2(Command Substitution)87 405.6 Q
+F1 1.697(Command substitution)108 417.6 R F0(allo)4.197 E 1.697
+(ws the output of a command to replace the command name.)-.25 F 1.698
+(There are tw)6.698 F(o)-.1 E(forms:)108 429.6 Q F2($\()144 451.2 Q F1(command)
+A F2(\))1.666 E F0(or)108 463.2 Q F2(`)144 475.2 Q F1(command)A F2(`)A(Bash)108
+492 Q F0 .02(performs the e)2.52 F .02(xpansion by e)-.15 F -.15(xe)-.15 G
+(cuting).15 E F1(command)2.519 E F0 .019
+(and replacing the command substitution with the stan-)2.519 F
+(dard output of the command, with an)108 504 Q 2.5(yt)-.15 G(railing ne)266.17
+504 Q(wlines deleted.)-.25 E 1.559(When the old\255style backquote form of sub\
+stitution is used, backslash retains its literal meaning e)108 520.8 R(xcept)
+-.15 E 1.259(when follo)108 532.8 R 1.259(wed by)-.25 F F2($)3.759 E F0(,)A F2
+(`)3.758 E F0 3.758(,o)C(r)212.083 532.8 Q F2(\\)3.758 E F0 6.258(.W)C 1.258
+(hen using the $\()240.149 532.8 R F1(command).833 E F0 3.758(\)f)1.666 G 1.258
+(orm, all characters between the parentheses)359.88 532.8 R(mak)108 544.8 Q 2.5
+(eu)-.1 G 2.5(pt)137.06 544.8 S(he command; none are treated specially)147.34
+544.8 Q(.)-.65 E .229(Command substitutions may be nested.)108 561.6 R 1.829
+-.8(To n)5.229 H .23
+(est when using the old form, escape the inner backquotes with).8 F
+(backslashes.)108 573.6 Q .422
+(If the substitution appears within double quotes, w)108 590.4 R .422
+(ord splitting and pathname e)-.1 F .422(xpansion are not performed)-.15 F
+(on the results.)108 602.4 Q F2(Arithmetic Expansion)87 619.2 Q F0 1.034
+(Arithmetic e)108 631.2 R 1.034(xpansion allo)-.15 F 1.034(ws the e)-.25 F -.25
+(va)-.25 G 1.034(luation of an arithmetic e).25 F 1.035
+(xpression and the substitution of the result.)-.15 F(There are tw)108 643.2 Q
+2.5(of)-.1 G(ormats for arithmetic e)169.26 643.2 Q(xpansion:)-.15 E F2($[)144
+660 Q F1 -.2(ex)C(pr).2 E(ession)-.37 E F2(])A($\(\()144 676.8 Q F1 -.2(ex)C
+(pr).2 E(ession)-.37 E F2(\)\))A F0(The)108 693.6 Q F1 -.2(ex)3.03 G(pr).2 E
+(ession)-.37 E F0 .53(is treated as if it were within double quotes, b)3.03 F
+.53(ut a double quote inside the braces or paren-)-.2 F .215
+(theses is not treated specially)108 705.6 R 5.215(.A)-.65 G .215(ll tok)
+239.795 705.6 R .215(ens in the e)-.1 F .215(xpression under)-.15 F .215
+(go parameter e)-.18 F .215(xpansion, command substi-)-.15 F
+(tution, and quote remo)108 717.6 Q -.25(va)-.15 G 2.5(l. Arithmetic).25 F
+(substitutions may be nested.)2.5 E 185.675(GNU 1995)72 768 R(May 5)2.5 E(10)
+530 768 Q EP
+%%Page: 11 11
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+1.379(The e)108 84 R -.25(va)-.25 G 1.378
+(luation is performed according to the rules listed belo).25 F 3.878(wu)-.25 G
+(nder)381.541 84 Q/F1 9/Times-Bold@0 SF 1.378(ARITHMETIC EV)3.878 F(ALU)-1.215
+E -.855(AT)-.54 G(ION).855 E/F2 9/Times-Roman@0 SF(.)A F0(If)5.878 E/F3 10
+/Times-Italic@0 SF -.2(ex)108 96 S(pr).2 E(ession)-.37 E F0(is in)2.5 E -.25
+(va)-.4 G(lid,).25 E/F4 10/Times-Bold@0 SF(bash)2.5 E F0
+(prints a message indicating f)2.5 E(ailure and no substitution occurs.)-.1 E
+F4(Pr)87 112.8 Q(ocess Substitution)-.18 E F3(Pr)108 124.8 Q .97
+(ocess substitution)-.45 F F0 .971
+(is supported on systems that support named pipes \()3.47 F F3(FIFOs)A F0 3.471
+(\)o)C 3.471(rt)442.936 124.8 S(he)452.517 124.8 Q F4(/de)3.471 E(v/fd)-.15 E
+F0 .971(method of)3.471 F .022(naming open \214les.)108 136.8 R .021(It tak)
+5.022 F .021(es the form of)-.1 F F4(<\()2.521 E F3(list)A F4(\)).833 E F0(or)
+2.521 E F4(>\()2.521 E F3(list)A F4(\)).833 E F0 5.021(.T)C .021(he process)
+343.68 136.8 R F3(list)2.521 E F0 .021(is run with its input or output con-)
+2.521 F .058(nected to a)108 148.8 R F3(FIFO)2.558 E F0 .058(or some \214le in)
+2.558 F F4(/de)2.558 E(v/fd)-.15 E F0 5.058(.T)C .058
+(he name of this \214le is passed as an ar)282.522 148.8 R .059
+(gument to the current com-)-.18 F .131(mand as the result of the e)108 160.8 R
+2.631(xpansion. If)-.15 F(the)2.63 E F4(>\()2.63 E F3(list)A F4(\)).833 E F0
+.13(form is used, writing to the \214le will pro)2.63 F .13(vide input for)-.15
+F F3(list)2.63 E F0(.)A(If the)108 172.8 Q F4(<\()2.5 E F3(list)A F4(\)).833 E
+F0(form is used, the \214le passed as an ar)2.5 E
+(gument should be read to obtain the output of)-.18 E F3(list)2.5 E F0(.)A .713
+(On systems that support it,)108 189.6 R F3(pr)3.213 E .713(ocess substitution)
+-.45 F F0 .713(is performed simultaneously with)3.213 F F3(par)3.213 E .713
+(ameter and variable)-.15 F -.2(ex)108 201.6 S(pansion).2 E F0(,).24 E F3
+(command substitution)2.5 E F0 2.5(,a).24 G(nd)251.33 201.6 Q F3(arithmetic e)
+2.5 E(xpansion)-.2 E F0(.).24 E F4 -.75(Wo)87 218.4 S(rd Splitting).75 E F0
+1.143(The shell scans the results of parameter e)108 230.4 R 1.142
+(xpansion, command substitution, and arithmetic e)-.15 F 1.142(xpansion that)
+-.15 F(did not occur within double quotes for)108 242.4 Q F3(wor)2.5 E 2.5(ds)
+-.37 G(plitting)290.4 242.4 Q F0(.).22 E .063
+(The shell treats each character of)108 259.2 R F1(IFS)2.563 E F0 .063
+(as a delimiter)2.313 F 2.563(,a)-.4 G .063
+(nd splits the results of the other e)322.193 259.2 R .063(xpansions into w)
+-.15 F(ords)-.1 E .227(on these characters.)108 271.2 R .227(If the v)5.227 F
+.227(alue of)-.25 F F1(IFS)2.726 E F0 .226(is e)2.476 F(xactly)-.15 E F4
+(<space><tab><newline>)2.726 E F0 2.726(,t)C .226(he def)421.326 271.2 R .226
+(ault, then an)-.1 F 2.726(ys)-.15 G(equence)507.24 271.2 Q(of)108 283.2 Q F1
+(IFS)3.211 E F0 .711(characters serv)2.961 F .711(es to delimit w)-.15 F 3.212
+(ords. If)-.1 F F1(IFS)3.212 E F0 .712(has a v)2.962 F .712
+(alue other than the def)-.25 F .712(ault, then sequences of the)-.1 F 1.628
+(whitespace characters)108 295.2 R F4(space)4.128 E F0(and)4.128 E F4(tab)4.128
+E F0 1.627(are ignored at the be)4.127 F 1.627(ginning and end of the w)-.15 F
+1.627(ord, as long as the)-.1 F .563(whitespace character is in the v)108 307.2
+R .564(alue of)-.25 F F1(IFS)3.064 E F0(\(an)2.814 E F1(IFS)3.064 E F0 .564
+(whitespace character\).)2.814 F(An)5.564 E 3.064(yc)-.15 G .564(haracter in)
+436.496 307.2 R F1(IFS)3.064 E F0 .564(that is not)2.814 F F1(IFS)108 319.2 Q
+F0 1.29(whitespace, along with an)3.54 F 3.789(ya)-.15 G(djacent)246.362 319.2
+Q F1(IFS)3.789 E F0 1.289(whitespace characters, delimits a \214eld.)3.539 F
+3.789(As)6.289 G 1.289(equence of)477.328 319.2 R F1(IFS)3.789 E F0 .04
+(whitespace characters is also treated as a delimiter)108 331.2 R 5.041(.I)-.55
+G 2.541(ft)319.931 331.2 S .041(he v)328.582 331.2 R .041(alue of)-.25 F F1
+(IFS)2.541 E F0 .041(is null, no w)2.291 F .041(ord splitting occurs.)-.1 F F1
+(IFS)5.041 E F0(cannot be unset.)108 343.2 Q .857(Explicit null ar)108 360 R
+.857(guments \()-.18 F F4 .833("").833 G F0(or)2.524 E F4 .833('')4.19 G F0
+3.357(\)a)C .857(re retained.)258.207 360 R .857(Implicit null ar)5.857 F .857
+(guments, resulting from the e)-.18 F .857(xpansion of)-.15 F F3(par)108 372 Q
+(ameter)-.15 E(s)-.1 E F0(that ha)2.5 E .3 -.15(ve n)-.2 H 2.5(ov).15 G
+(alues, are remo)211.58 372 Q -.15(ve)-.15 G(d.).15 E(Note that if no e)108
+388.8 Q(xpansion occurs, no splitting is performed.)-.15 E F4 -.1(Pa)87 405.6 S
+(thname Expansion).1 E F0 .383(After w)108 417.6 R .383
+(ord splitting, unless the)-.1 F F4<ad66>2.883 E F0 .383(option has been set,)
+2.883 F F4(bash)2.883 E F0 .384(scans each)2.884 F F3(wor)2.884 E(d)-.37 E F0
+.384(for the characters)2.884 F F4(*)2.884 E F0(,)A F4(?)2.884 E F0 2.884(,a)C
+(nd)521.286 417.6 Q F4([)2.884 E F0(.)A .678
+(If one of these characters appears, then the w)108 429.6 R .677(ord is re)-.1
+F -.05(ga)-.15 G .677(rded as a).05 F F3(pattern)3.177 E F0 3.177(,a).24 G .677
+(nd replaced with an alphabeti-)416.212 429.6 R .071
+(cally sorted list of pathnames matching the pattern.)108 441.6 R .071
+(If no matching pathnames are found, and the shell v)5.071 F(ari-)-.25 E(able)
+108 453.6 Q F4(allo)2.516 E(w_null_glob_expansion)-.1 E F0 .016
+(is unset, the w)2.516 F .016(ord is left unchanged.)-.1 F .016(If the v)5.016
+F .015(ariable is set, and no matches)-.25 F .487(are found, the w)108 465.6 R
+.487(ord is remo)-.1 F -.15(ve)-.15 G 2.988(d. When).15 F 2.988(ap)2.988 G .488
+(attern is used for pathname generation, the character)282.29 465.6 R F4 -.63
+(``)2.988 G -.55(.').63 G(')-.08 E F0 .488(at the)5.488 F 1.789
+(start of a name or immediately follo)108 477.6 R 1.789
+(wing a slash must be matched e)-.25 F(xplicitly)-.15 E 4.288(,u)-.65 G 1.788
+(nless the shell v)444.066 477.6 R(ariable)-.25 E F4(glob_dot_\214lenames)108
+489.6 Q F0 .418(is set.)2.918 F .418(The slash character must al)5.418 F -.1
+(wa)-.1 G .418(ys be matched e).1 F(xplicitly)-.15 E 5.418(.I)-.65 G 2.918(no)
+452.948 489.6 S .418(ther cases, the)465.866 489.6 R F4 -.63(``)2.918 G -.55
+(.').63 G(')-.08 E F0(character is not treated specially)108 501.6 Q(.)-.65 E
+(The special pattern characters ha)108 518.4 Q .3 -.15(ve t)-.2 H(he follo).15
+E(wing meanings:)-.25 E F4(*)108 535.2 Q F0(Matches an)144 535.2 Q 2.5(ys)-.15
+G(tring, including the null string.)201.06 535.2 Q F4(?)108 547.2 Q F0
+(Matches an)144 547.2 Q 2.5(ys)-.15 G(ingle character)201.06 547.2 Q(.)-.55 E
+F4([...])108 559.2 Q F0 1.992(Matches an)144 559.2 R 4.492(yo)-.15 G 1.992
+(ne of the enclosed characters.)206.154 559.2 R 4.491(Ap)6.991 G 1.991
+(air of characters separated by a minus sign)355.833 559.2 R 1.113(denotes a)
+144 571.2 R F3 -.15(ra)3.613 G(ng).15 E(e)-.1 E F0 3.613(;a).18 G 1.413 -.15
+(ny c)220.309 571.2 T 1.113(haracter le).15 F 1.113(xically between those tw)
+-.15 F 3.613(oc)-.1 G 1.113(haracters, inclusi)396.537 571.2 R -.15(ve)-.25 G
+3.613(,i).15 G 3.613(sm)483.343 571.2 S 3.614(atched. If)498.626 571.2 R .15
+(the \214rst character follo)144 583.2 R .15(wing the)-.25 F F4([)2.65 E F0 .15
+(is a)2.65 F F4(!)2.65 E F0 .15(or a)5.15 F F4(^)2.65 E F0 .15(then an)2.65 F
+2.65(yc)-.15 G .15(haracter not enclosed is matched.)368.7 583.2 R(A)5.15 E F4
+<ad>2.65 E F0(or)2.65 E F4(])2.65 E F0
+(may be matched by including it as the \214rst or last character in the set.)
+144 595.2 Q F4(Quote Remo)87 612 Q -.1(va)-.1 G(l).1 E F0
+(After the preceding e)108 624 Q
+(xpansions, all unquoted occurrences of the characters)-.15 E F4(\\)2.5 E F0(,)
+A F4(`)2.5 E F0 2.5(,a)C(nd)429.14 624 Q F4(")3.333 E F0(are remo)3.333 E -.15
+(ve)-.15 G(d.).15 E F1(REDIRECTION)72 640.8 Q F0 .593(Before a command is e)108
+652.8 R -.15(xe)-.15 G .593(cuted, its input and output may be).15 F F3 -.37
+(re)3.093 G(dir).37 E(ected)-.37 E F0 .593
+(using a special notation interpreted)3.093 F .617(by the shell.)108 664.8 R
+.617(Redirection may also be used to open and close \214les for the current sh\
+ell e)5.617 F -.15(xe)-.15 G .616(cution en).15 F(viron-)-.4 E 3.353(ment. The)
+108 676.8 R(follo)3.353 E .853
+(wing redirection operators may precede or appear an)-.25 F .854
+(ywhere within a)-.15 F F3 .854(simple command)3.354 F F0(or)3.354 E(may follo)
+108 688.8 Q 2.5(wa)-.25 G F3(command)A F0 5(.R).77 G
+(edirections are processed in the order the)216.84 688.8 Q 2.5(ya)-.15 G(ppear)
+392.47 688.8 Q 2.5(,f)-.4 G(rom left to right.)422.61 688.8 Q .448
+(In the follo)108 705.6 R .447(wing descriptions, if the \214le descriptor num\
+ber is omitted, and the \214rst character of the redirec-)-.25 F .365
+(tion operator is)108 717.6 R F4(<)2.865 E F0 2.865(,t)C .366
+(he redirection refers to the standard input \(\214le descriptor 0\).)185.99
+717.6 R .366(If the \214rst character of the)5.366 F(redirection operator is)
+108 729.6 Q F4(>)2.5 E F0 2.5(,t)C
+(he redirection refers to the standard output \(\214le descriptor 1\).)212.29
+729.6 Q 185.675(GNU 1995)72 768 R(May 5)2.5 E(11)530 768 Q EP
+%%Page: 12 12
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+.077(The w)108 84 R .077(ord that follo)-.1 F .077
+(ws the redirection operator in the follo)-.25 F .076
+(wing descriptions is subjected to brace e)-.25 F(xpansion,)-.15 E 1.984
+(tilde e)108 96 R 1.984(xpansion, parameter e)-.15 F 1.984
+(xpansion, command substitution, arithmetic e)-.15 F 1.984
+(xpansion, quote remo)-.15 F -.25(va)-.15 G 1.984(l, and).25 F(pathname e)108
+108 Q 2.5(xpansion. If)-.15 F(it e)2.5 E(xpands to more than one w)-.15 E(ord,)
+-.1 E/F1 10/Times-Bold@0 SF(bash)2.5 E F0(reports an error)2.5 E(.)-.55 E
+(Note that the order of redirections is signi\214cant.)108 124.8 Q -.15(Fo)5 G
+2.5(re).15 G(xample, the command)325.17 124.8 Q(ls)144 141.6 Q F1(>)2.5 E F0
+(dirlist 2)2.5 E F1(>&)A F0(1)A
+(directs both standard output and standard error to the \214le)108 158.4 Q/F2
+10/Times-Italic@0 SF(dirlist)2.5 E F0 2.5(,w).68 G(hile the command)374.21
+158.4 Q(ls 2)144 175.2 Q F1(>&)A F0(1)A F1(>)2.5 E F0(dirlist)2.5 E .388
+(directs only the standard output to \214le)108 192 R F2(dirlist)2.888 E F0
+2.888(,b).68 G .387(ecause the standard error w)299.844 192 R .387
+(as duplicated as standard output)-.1 F(before the standard output w)108 204 Q
+(as redirected to)-.1 E F2(dirlist)2.5 E F0(.).68 E F1(Redir)87 220.8 Q
+(ecting Input)-.18 E F0 .453
+(Redirection of input causes the \214le whose name results from the e)108 232.8
+R .453(xpansion of)-.15 F F2(wor)2.953 E(d)-.37 E F0 .453
+(to be opened for read-)2.953 F(ing on \214le descriptor)108 244.8 Q F2(n)2.5 E
+F0 2.5(,o).24 G 2.5(rt)208.79 244.8 S
+(he standard input \(\214le descriptor 0\) if)217.4 244.8 Q F2(n)2.5 E F0
+(is not speci\214ed.)2.5 E(The general format for redirecting input is:)108
+261.6 Q([)144 278.4 Q F2(n)A F0(])A F1(<)A F2(wor)A(d)-.37 E F1(Redir)87 295.2
+Q(ecting Output)-.18 E F0 .236
+(Redirection of output causes the \214le whose name results from the e)108
+307.2 R .236(xpansion of)-.15 F F2(wor)2.736 E(d)-.37 E F0 .236
+(to be opened for writ-)2.736 F .852(ing on \214le descriptor)108 319.2 R F2(n)
+3.353 E F0 3.353(,o).24 G 3.353(rt)213.052 319.2 S .853
+(he standard output \(\214le descriptor 1\) if)222.515 319.2 R F2(n)3.353 E F0
+.853(is not speci\214ed.)3.353 F .853(If the \214le does not)5.853 F -.15(ex)
+108 331.2 S(ist it is created; if it does e).15 E
+(xist it is truncated to zero size.)-.15 E
+(The general format for redirecting output is:)108 348 Q([)144 364.8 Q F2(n)A
+F0(])A F1(>)A F2(wor)A(d)-.37 E F0 .127(If the redirection operator is)108
+381.6 R F1(>|)2.627 E F0 2.627(,t)C .127(hen the v)239.132 381.6 R .127
+(alue of the)-.25 F F1(-C)2.627 E F0 .127(option to the)2.627 F F1(set)2.626 E
+F0 -.2(bu)2.626 G .126(iltin command is not tested, and).2 F
+(\214le creation is attempted.)108 393.6 Q(\(See also the description of)5 E F1
+(noclob)2.5 E(ber)-.1 E F0(under)2.5 E F1(Shell V)2.5 E(ariables)-.92 E F0(abo)
+2.5 E -.15(ve)-.15 G(.\)).15 E F1 -.25(Ap)87 410.4 S(pending Redir).25 E
+(ected Output)-.18 E F0 .703(Redirection of output in this f)108 422.4 R .703
+(ashion causes the \214le whose name results from the e)-.1 F .704(xpansion of)
+-.15 F F2(wor)3.204 E(d)-.37 E F0 .704(to be)3.204 F .506
+(opened for appending on \214le descriptor)108 434.4 R F2(n)3.005 E F0 3.005
+(,o).24 G 3.005(rt)286.75 434.4 S .505
+(he standard output \(\214le descriptor 1\) if)295.865 434.4 R F2(n)3.005 E F0
+.505(is not speci\214ed.)3.005 F(If)5.505 E(the \214le does not e)108 446.4 Q
+(xist it is created.)-.15 E(The general format for appending output is:)108
+463.2 Q([)144 480 Q F2(n)A F0(])A F1(>>)A F2(wor)A(d)-.37 E F1(Redir)87 501.6 Q
+(ecting Standard Output and Standard Err)-.18 E(or)-.18 E(Bash)108 513.6 Q F0
+(allo)3.141 E .642(ws both the standard output \(\214le descriptor 1\) and the\
+ standard error output \(\214le descriptor 2\) to)-.25 F
+(be redirected to the \214le whose name is the e)108 525.6 Q(xpansion of)-.15 E
+F2(wor)2.5 E(d)-.37 E F0(with this construct.)2.5 E(There are tw)108 542.4 Q
+2.5(of)-.1 G(ormats for redirecting standard output and standard error:)169.26
+542.4 Q F1(&>)144 559.2 Q F2(wor)A(d)-.37 E F0(and)108 571.2 Q F1(>&)144 583.2
+Q F2(wor)A(d)-.37 E F0(Of the tw)108 600 Q 2.5(of)-.1 G
+(orms, the \214rst is preferred.)156.5 600 Q(This is semantically equi)5 E -.25
+(va)-.25 G(lent to).25 E F1(>)144 616.8 Q F2(wor)A(d)-.37 E F0(2)2.5 E F1(>&)A
+F0(1)A F1(Her)87 633.6 Q 2.5(eD)-.18 G(ocuments)117.64 633.6 Q F0 .33(This typ\
+e of redirection instructs the shell to read input from the current source unt\
+il a line containing only)108 645.6 R F2(wor)108 657.6 Q(d)-.37 E F0 .736
+(\(with no trailing blanks\) is seen.)3.236 F .737
+(All of the lines read up to that point are then used as the standard)5.736 F
+(input for a command.)108 669.6 Q(The format of here-documents is as follo)108
+686.4 Q(ws:)-.25 E F1(<<)144 703.2 Q F0([)A F1<ad>A F0(])A F2(wor)A(d)-.37 E
+(her)164 715.2 Q(e-document)-.37 E(delimiter)144 727.2 Q F0 185.675(GNU 1995)72
+768 R(May 5)2.5 E(12)530 768 Q EP
+%%Page: 13 13
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+.128(No parameter e)108 84 R .127(xpansion, command substitution, pathname e)
+-.15 F .127(xpansion, or arithmetic e)-.15 F .127(xpansion is performed)-.15 F
+(on)108 96 Q/F1 10/Times-Italic@0 SF(wor)2.609 E(d)-.37 E F0 5.109(.I).77 G
+2.609(fa)152.508 96 S .409 -.15(ny c)162.887 96 T .109(haracters in).15 F F1
+(wor)2.609 E(d)-.37 E F0 .109(are quoted, the)2.609 F F1(delimiter)2.609 E F0
+.109(is the result of quote remo)2.609 F -.25(va)-.15 G 2.609(lo).25 G(n)
+477.053 96 Q F1(wor)2.609 E(d)-.37 E F0 2.609(,a).77 G .109(nd the)515.171 96 R
+1.113(lines in the here-document are not e)108 108 R 3.613(xpanded. Otherwise,)
+-.15 F 1.112(all lines of the here-document are subjected to)3.613 F .769
+(parameter e)108 120 R .769(xpansion, command substitution, and arithmetic e)
+-.15 F 3.269(xpansion. In)-.15 F .769(the latter case, the pair)3.269 F/F2 10
+/Times-Bold@0 SF(\\<new-)3.27 E(line>)108 132 Q F0(is ignored, and)2.5 E F2(\\)
+2.5 E F0(must be used to quote the characters)2.5 E F2(\\)2.5 E F0(,)A F2($)2.5
+E F0 2.5(,a)C(nd)368.39 132 Q F2(`)2.5 E F0(.)A .602
+(If the redirection operator is)108 148.8 R F2(<<\255)3.101 E F0 3.101(,t)C
+.601(hen all leading tab characters are stripped from input lines and the line)
+251.178 148.8 R(containing)108 160.8 Q F1(delimiter)2.5 E F0 5(.T).73 G
+(his allo)203.17 160.8 Q
+(ws here-documents within shell scripts to be indented in a natural f)-.25 E
+(ashion.)-.1 E F2(Duplicating File Descriptors)87 177.6 Q F0
+(The redirection operator)108 189.6 Q([)144 206.4 Q F1(n)A F0(])A F2(<&)A F1
+(wor)A(d)-.37 E F0 .188(is used to duplicate input \214le descriptors.)108
+223.2 R(If)5.188 E F1(wor)2.688 E(d)-.37 E F0 -.15(ex)2.688 G .189
+(pands to one or more digits, the \214le descriptor denoted).15 F(by)108 235.2
+Q F1(n)3.095 E F0 .594(is made to be a cop)3.095 F 3.094(yo)-.1 G 3.094(ft)
+222.086 235.2 S .594(hat \214le descriptor)231.29 235.2 R 5.594(.I)-.55 G(f)
+313.342 235.2 Q F1(wor)3.094 E(d)-.37 E F0 -.25(eva)3.094 G .594(luates to).25
+F F2<ad>3.094 E F0 3.094<2c8c>C .594(le descriptor)410.582 235.2 R F1(n)3.094 E
+F0 .594(is closed.)3.094 F(If)5.594 E F1(n)3.094 E F0(is)3.094 E
+(not speci\214ed, the standard input \(\214le descriptor 0\) is used.)108 247.2
+Q(The operator)108 264 Q([)144 280.8 Q F1(n)A F0(])A F2(>&)A F1(wor)A(d)-.37 E
+F0 .021(is used similarly to duplicate output \214le descriptors.)108 297.6 R
+(If)5.021 E F1(n)2.521 E F0 .021
+(is not speci\214ed, the standard output \(\214le descriptor)2.521 F .382
+(1\) is used.)108 309.6 R .382(As a special case, if)5.382 F F1(n)2.882 E F0
+.382(is omitted, and)2.882 F F1(wor)2.882 E(d)-.37 E F0 .382(does not e)2.882 F
+.381(xpand to one or more digits, the standard)-.15 F
+(output and standard error are redirected as described pre)108 321.6 Q(viously)
+-.25 E(.)-.65 E F2(Opening File Descriptors f)87 338.4 Q
+(or Reading and Writing)-.25 E F0(The redirection operator)108 350.4 Q([)144
+367.2 Q F1(n)A F0(])A F2(<>)A F1(wor)A(d)-.37 E F0 1.407
+(causes the \214le whose name is the e)108 384 R 1.407(xpansion of)-.15 F F1
+(wor)3.907 E(d)-.37 E F0 1.408
+(to be opened for both reading and writing on \214le)3.907 F(descriptor)108 396
+Q F1(n)2.715 E F0 2.715(,o).24 G 2.715(ra)166.16 396 S 2.715(st)176.645 396 S
+.215(he standard input and standard output if)186.03 396 R F1(n)2.715 E F0 .214
+(is not speci\214ed.)2.715 F .214(If the \214le does not e)5.214 F .214
+(xist, it is)-.15 F(created.)108 408 Q/F3 9/Times-Bold@0 SF(FUNCTIONS)72 424.8
+Q F0 3.467(As)108 436.8 S .967(hell function, de\214ned as described abo)
+122.577 436.8 R 1.267 -.15(ve u)-.15 H(nder).15 E F3 .967(SHELL GRAMMAR)3.467 F
+/F4 9/Times-Roman@0 SF(,)A F0 .968(stores a series of commands for)3.217 F
+1.277(later e)108 448.8 R -.15(xe)-.15 G 3.777(cution. Functions).15 F 1.277
+(are e)3.777 F -.15(xe)-.15 G 1.277(cuted in the conte).15 F 1.276
+(xt of the current shell; no ne)-.15 F 3.776(wp)-.25 G 1.276
+(rocess is created to)460.362 448.8 R .952
+(interpret them \(contrast this with the e)108 460.8 R -.15(xe)-.15 G .952
+(cution of a shell script\).).15 F .953(When a function is e)5.952 F -.15(xe)
+-.15 G .953(cuted, the ar).15 F(gu-)-.18 E 1.102
+(ments to the function become the positional parameters during its e)108 472.8
+R -.15(xe)-.15 G 3.602(cution. The).15 F 1.102(special parameter)3.602 F F2(#)
+3.602 E F0(is)3.602 E(updated to re\215ect the change.)108 484.8 Q
+(Positional parameter 0 is unchanged.)5 E -1.11(Va)108 501.6 S .655
+(riables local to the function may be declared with the)1.11 F F2(local)3.155 E
+F0 -.2(bu)3.156 G .656(iltin command.).2 F(Ordinarily)5.656 E 3.156(,v)-.65 G
+.656(ariables and)491.304 501.6 R(their v)108 513.6 Q
+(alues are shared between the function and its caller)-.25 E(.)-.55 E .044
+(If the b)108 530.4 R .043(uiltin command)-.2 F F2 -.18(re)2.543 G(tur).18 E(n)
+-.15 E F0 .043(is e)2.543 F -.15(xe)-.15 G .043
+(cuted in a function, the function completes and e).15 F -.15(xe)-.15 G .043
+(cution resumes with).15 F .311(the ne)108 542.4 R .311
+(xt command after the function call.)-.15 F .311
+(When a function completes, the v)5.311 F .312(alues of the positional parame-)
+-.25 F(ters and the special parameter)108 554.4 Q F2(#)2.5 E F0
+(are restored to the v)2.5 E(alues the)-.25 E 2.5(yh)-.15 G
+(ad prior to function e)363.64 554.4 Q -.15(xe)-.15 G(cution.).15 E 1.359
+(Function names and de\214nitions may be listed with the)108 571.2 R F2<ad66>
+3.858 E F0 1.358(option to the)3.858 F F2(declar)3.858 E(e)-.18 E F0(or)3.858 E
+F2(typeset)3.858 E F0 -.2(bu)3.858 G 1.358(iltin com-).2 F 2.787
+(mands. Functions)108 583.2 R .287(may be e)2.787 F .287
+(xported so that subshells automatically ha)-.15 F .588 -.15(ve t)-.2 H .288
+(hem de\214ned with the).15 F F2<ad66>2.788 E F0 .288(option to)2.788 F(the)108
+595.2 Q F2(export)2.5 E F0 -.2(bu)2.5 G(iltin.).2 E(Functions may be recursi)
+108 612 Q -.15(ve)-.25 G 5(.N).15 G 2.5(ol)232.58 612 S
+(imit is imposed on the number of recursi)242.86 612 Q .3 -.15(ve c)-.25 H
+(alls.).15 E F3(ALIASES)72 628.8 Q F0 .335(The shell maintains a list of)108
+640.8 R F1(aliases)2.835 E F0 .335(that may be set and unset with the)2.835 F
+F2(alias)2.834 E F0(and)2.834 E F2(unalias)2.834 E F0 -.2(bu)2.834 G .334
+(iltin commands).2 F(\(see)108 652.8 Q F3 .763(SHELL B)3.263 F(UIL)-.09 E .763
+(TIN COMMANDS)-.828 F F0(belo)3.013 E 3.263(w\). The)-.25 F .763(\214rst w)
+3.263 F .763(ord of each command, if unquoted, is check)-.1 F .764(ed to)-.1 F
+.634(see if it has an alias.)108 664.8 R .634(If so, that w)5.634 F .633
+(ord is replaced by the te)-.1 F .633(xt of the alias.)-.15 F .633
+(The alias name and the replace-)5.633 F .58(ment te)108 676.8 R .58
+(xt may contain an)-.15 F 3.08(yv)-.15 G .581(alid shell input, including the)
+223.95 676.8 R F1(metac)3.081 E(har)-.15 E(acter)-.15 E(s)-.1 E F0 .581
+(listed abo)3.081 F -.15(ve)-.15 G 3.081(,w).15 G .581(ith the e)472.328 676.8
+R(xception)-.15 E .997(that the alias name may not contain)108 688.8 R F1(=)
+3.497 E F0 5.997(.T)C .997(he \214rst w)280.486 688.8 R .996
+(ord of the replacement te)-.1 F .996(xt is tested for aliases, b)-.15 F .996
+(ut a)-.2 F -.1(wo)108 700.8 S .494(rd that is identical to an alias being e).1
+F .495(xpanded is not e)-.15 F .495(xpanded a second time.)-.15 F .495
+(This means that one may)5.495 F(alias)108 712.8 Q F2(ls)3.02 E F0(to)3.02 E F2
+.52(ls \255F)3.02 F F0 3.02(,f)C .52(or instance, and)180.19 712.8 R F2(bash)
+3.02 E F0 .519(does not try to recursi)3.02 F -.15(ve)-.25 G .519(ly e).15 F
+.519(xpand the replacement te)-.15 F 3.019(xt. If)-.15 F .519(the last)3.019 F
+.441(character of the alias v)108 724.8 R .441(alue is a)-.25 F F1(blank)2.941
+E F0 2.941(,t).67 G .441(hen the ne)267.738 724.8 R .441(xt command w)-.15 F
+.441(ord follo)-.1 F .441(wing the alias is also check)-.25 F .442(ed for)-.1 F
+185.675(GNU 1995)72 768 R(May 5)2.5 E(13)530 768 Q EP
+%%Page: 14 14
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+(alias e)108 84 Q(xpansion.)-.15 E(Aliases are created and listed with the)108
+100.8 Q/F1 10/Times-Bold@0 SF(alias)2.5 E F0(command, and remo)2.5 E -.15(ve)
+-.15 G 2.5(dw).15 G(ith the)389.87 100.8 Q F1(unalias)2.5 E F0(command.)2.5 E
+.546(There is no mechanism for using ar)108 117.6 R .546
+(guments in the replacement te)-.18 F .545(xt, as in)-.15 F F1(csh)3.045 E F0
+5.545(.I)C 3.045(fa)435.54 117.6 S -.18(rg)446.355 117.6 S .545
+(uments are needed, a).18 F(shell function should be used.)108 129.6 Q
+(Aliases are not e)108 146.4 Q(xpanded when the shell is not interacti)-.15 E
+-.15(ve)-.25 G(.).15 E .435
+(The rules concerning the de\214nition and use of aliases are some)108 163.2 R
+.436(what confusing.)-.25 F F1(Bash)5.436 E F0(al)2.936 E -.1(wa)-.1 G .436
+(ys reads at least).1 F .338(one complete line of input before e)108 175.2 R
+-.15(xe)-.15 G .338(cuting an).15 F 2.838(yo)-.15 G 2.838(ft)309.104 175.2 S
+.338(he commands on that line.)318.052 175.2 R .337(Aliases are e)5.337 F .337
+(xpanded when)-.15 F 3.403(ac)108 187.2 S .904
+(ommand is read, not when it is e)120.283 187.2 R -.15(xe)-.15 G 3.404
+(cuted. Therefore,).15 F .904
+(an alias de\214nition appearing on the same line as)3.404 F .729
+(another command does not tak)108 199.2 R 3.229(ee)-.1 G -.25(ff)245.685 199.2
+S .728(ect until the ne).25 F .728(xt line of input is read.)-.15 F .728
+(This means that the commands)5.728 F(follo)108 211.2 Q .699
+(wing the alias de\214nition on that line are not af)-.25 F .699
+(fected by the ne)-.25 F 3.199(wa)-.25 G 3.199(lias. This)397.126 211.2 R(beha)
+3.199 E .699(vior is also an issue)-.2 F .073(when functions are e)108 223.2 R
+-.15(xe)-.15 G 2.573(cuted. Aliases).15 F .073(are e)2.573 F .072
+(xpanded when the function de\214nition is read, not when the func-)-.15 F .88
+(tion is e)108 235.2 R -.15(xe)-.15 G .88
+(cuted, because a function de\214nition is itself a compound command.).15 F .88
+(As a consequence, aliases)5.88 F .085(de\214ned in a function are not a)108
+247.2 R -.25(va)-.2 G .085(ilable until after that function is e).25 F -.15(xe)
+-.15 G 2.585(cuted. T).15 F 2.585(ob)-.8 G 2.584(es)427.03 247.2 S .084
+(afe, al)437.944 247.2 R -.1(wa)-.1 G .084(ys put alias de\214-).1 F
+(nitions on a separate line, and do not use)108 259.2 Q F1(alias)2.5 E F0
+(in compound commands.)2.5 E(Note that for almost e)108 276 Q -.15(ve)-.25 G
+(ry purpose, aliases are superseded by shell functions.).15 E/F2 9/Times-Bold@0
+SF(JOB CONTR)72 292.8 Q(OL)-.27 E/F3 10/Times-Italic@0 SF -.25(Jo)108 304.8 S
+4.601(bc).25 G(ontr)131.231 304.8 Q(ol)-.45 E F0 2.101
+(refers to the ability to selecti)4.601 F -.15(ve)-.25 G 2.101(ly stop \().15 F
+F3(suspend)A F0 4.601(\)t)C 2.102(he e)373.44 304.8 R -.15(xe)-.15 G 2.102
+(cution of processes and continue).15 F(\()108 316.8 Q F3 -.37(re)C(sume).37 E
+F0 3.202(\)t)C .702(heir e)149.152 316.8 R -.15(xe)-.15 G .702
+(cution at a later point.).15 F 3.202(Au)5.702 G .702(ser typically emplo)
+292.906 316.8 R .702(ys this f)-.1 F .702(acility via an interacti)-.1 F 1.001
+-.15(ve i)-.25 H(nterf).15 E(ace)-.1 E(supplied jointly by the system')108
+328.8 Q 2.5(st)-.55 G(erminal dri)239.96 328.8 Q -.15(ve)-.25 G 2.5(ra).15 G
+(nd)303.43 328.8 Q F1(bash)2.5 E F0(.)A .893(The shell associates a)108 345.6 R
+F3(job)3.394 E F0 .894(with each pipeline.)3.394 F .894(It k)5.894 F .894
+(eeps a table of currently e)-.1 F -.15(xe)-.15 G .894
+(cuting jobs, which may be).15 F .341(listed with the)108 357.6 R F1(jobs)2.841
+E F0 2.841(command. When)2.841 F F1(bash)2.841 E F0 .341
+(starts a job asynchronously \(in the)2.841 F F3(bac)2.84 E(kgr)-.2 E(ound)-.45
+E F0 .34(\), it prints a line).77 F(that looks lik)108 369.6 Q(e:)-.1 E
+([1] 25647)144 386.4 Q .241(indicating that this job is job number 1 and that \
+the process ID of the last process in the pipeline associated)108 403.2 R .733
+(with this job is 25647.)108 415.2 R .732
+(All of the processes in a single pipeline are members of the same job)5.733 F
+(.)-.4 E F1(Bash)5.732 E F0(uses)3.232 E(the)108 427.2 Q F3(job)2.5 E F0
+(abstraction as the basis for job control.)2.5 E 2.563 -.8(To f)108 444 T .963
+(acilitate the implementation of the user interf).7 F .964
+(ace to job control, the system maintains the notion of a)-.1 F F3(curr)108 456
+Q .723(ent terminal pr)-.37 F .723(ocess gr)-.45 F .723(oup ID)-.45 F F0 5.723
+(.M)C .723(embers of this process group \(processes whose process group ID is)
+265.055 456 R .341(equal to the current terminal process group ID\) recei)108
+468 R .642 -.15(ve k)-.25 H -.15(ey).05 G .342(board-generated signals such as)
+.15 F F2(SIGINT)2.842 E/F4 9/Times-Roman@0 SF(.)A F0(These)4.842 E .216
+(processes are said to be in the)108 480 R F3(for)2.716 E -.4(eg)-.37 G -.45
+(ro).4 G(und).45 E F0(.).77 E F3(Bac)5.216 E(kgr)-.2 E(ound)-.45 E F0 .215
+(processes are those whose process group ID dif)2.716 F(fers)-.25 E .3
+(from the terminal')108 492 R .3(s; such processes are immune to k)-.55 F -.15
+(ey)-.1 G .3(board-generated signals.).15 F .3(Only fore)5.3 F .3
+(ground processes)-.15 F .253(are allo)108 504 R .253
+(wed to read from or write to the terminal.)-.25 F .252
+(Background processes which attempt to read from \(write)5.252 F 1.03
+(to\) the terminal are sent a)108 516 R F2 1.031(SIGTTIN \(SIGTT)3.531 F(OU\))
+-.162 E F0 1.031(signal by the terminal dri)3.281 F -.15(ve)-.25 G 1.831 -.4
+(r, w).15 H 1.031(hich, unless caught, sus-).4 F(pends the process.)108 528 Q
+.679(If the operating system on which)108 544.8 R F1(bash)3.179 E F0 .678
+(is running supports job control,)3.178 F F1(bash)3.178 E F0(allo)3.178 E .678
+(ws you to use it.)-.25 F -.8(Ty)5.678 G(ping).8 E(the)108 556.8 Q F3(suspend)
+2.681 E F0 .182(character \(typically)2.681 F F1(^Z)2.682 E F0 2.682(,C)C .182
+(ontrol-Z\) while a process is running causes that process to be stopped)
+259.988 556.8 R .007(and returns you to)108 568.8 R F1(bash)2.507 E F0 5.007
+(.T)C .007(yping the)215.845 568.8 R F3 .007(delayed suspend)2.507 F F0 .007
+(character \(typically)2.507 F F1(^Y)2.506 E F0 2.506(,C)C .006
+(ontrol-Y\) causes the process)426.402 568.8 R .004(to be stopped when it atte\
+mpts to read input from the terminal, and control to be returned to)108 580.8 R
+F1(bash)2.504 E F0 5.004(.Y)C .004(ou may)510.276 580.8 R .619
+(then manipulate the state of this job, using the)108 592.8 R F1(bg)3.118 E F0
+.618(command to continue it in the background, the)3.118 F F1(fg)3.118 E F0
+(com-)3.118 E .825(mand to continue it in the fore)108 604.8 R .825
+(ground, or the)-.15 F F1(kill)3.325 E F0 .825(command to kill it.)3.325 F(A)
+5.825 E F1(^Z)3.326 E F0(tak)3.326 E .826(es ef)-.1 F .826(fect immediately)
+-.25 F 3.326(,a)-.65 G(nd)530 604.8 Q(has the additional side ef)108 616.8 Q
+(fect of causing pending output and typeahead to be discarded.)-.25 E 1.098
+(There are a number of w)108 633.6 R 1.097(ays to refer to a job in the shell.)
+-.1 F 1.097(The character)6.097 F F1(%)3.597 E F0 1.097(introduces a job name.)
+3.597 F(Job)6.097 E(number)108 645.6 Q F3(n)2.796 E F0 .296
+(may be referred to as)2.796 F F1(%n)2.796 E F0 5.296(.A)C .296
+(job may also be referred to using a pre\214x of the name used to start)270.904
+645.6 R .277(it, or using a substring that appears in its command line.)108
+657.6 R -.15(Fo)5.277 G 2.777(re).15 G(xample,)360.737 657.6 Q F1(%ce)2.777 E
+F0 .277(refers to a stopped)2.777 F F1(ce)2.777 E F0(job)2.777 E 5.277(.I)-.4 G
+2.777(fa)529.453 657.6 S .38(pre\214x matches more than one job,)108 669.6 R F1
+(bash)2.88 E F0 .38(reports an error)2.88 F 5.38(.U)-.55 G(sing)348.71 669.6 Q
+F1(%?ce)2.88 E F0 2.88(,o)C 2.88(nt)402.52 669.6 S .38
+(he other hand, refers to an)413.18 669.6 R 2.88(yj)-.15 G(ob)530 669.6 Q .623
+(containing the string)108 681.6 R F1(ce)3.123 E F0 .622(in its command line.)
+3.123 F .622(If the substring matches more than one job,)5.622 F F1(bash)3.122
+E F0 .622(reports an)3.122 F(error)108 693.6 Q 5.143(.T)-.55 G .143(he symbols)
+140.633 693.6 R F1(%%)2.643 E F0(and)2.643 E F1(%+)2.643 E F0 .143
+(refer to the shell')2.643 F 2.643(sn)-.55 G .143(otion of the)326.77 693.6 R
+F3(curr)2.643 E .143(ent job)-.37 F F0 2.643(,w).23 G .143
+(hich is the last job stopped)432.895 693.6 R .119(while it w)108 705.6 R .119
+(as in the fore)-.1 F 2.619(ground. The)-.15 F F3(pr)2.618 E -.15(ev)-.37 G
+.118(ious job).15 F F0 .118(may be referenced using)2.618 F F1<25ad>2.618 E F0
+5.118(.I)C 2.618(no)433.968 705.6 S .118(utput pertaining to jobs)446.586 705.6
+R .076(\(e.g., the output of the)108 717.6 R F1(jobs)2.576 E F0 .076
+(command\), the current job is al)2.576 F -.1(wa)-.1 G .076
+(ys \215agged with a).1 F F1(+)2.576 E F0 2.576(,a)C .076(nd the pre)442.726
+717.6 R .076(vious job with)-.25 F(a)108 729.6 Q F1<ad>2.5 E F0(.)A 185.675
+(GNU 1995)72 768 R(May 5)2.5 E(14)530 768 Q EP
+%%Page: 15 15
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+.444(Simply naming a job can be used to bring it into the fore)108 84 R
+(ground:)-.15 E/F1 10/Times-Bold@0 SF(%1)2.943 E F0 .443(is a synon)2.943 F
+.443(ym for)-.15 F F1 -.63(``)2.943 G .443(fg %1').63 F(')-.63 E F0 2.943(,b)C
+(ringing)511.11 84 Q 1.472(job 1 from the background into the fore)108 96 R
+3.972(ground. Similarly)-.15 F(,)-.65 E F1 -.63(``)3.973 G 1.473(%1 &').63 F(')
+-.63 E F0 1.473(resumes job 1 in the background,)3.973 F(equi)108 108 Q -.25
+(va)-.25 G(lent to).25 E F1 -.63(``)2.5 G(bg %1').63 E(')-.63 E F0(.)A .131
+(The shell learns immediately whene)108 124.8 R -.15(ve)-.25 G 2.631(raj).15 G
+.131(ob changes state.)277.796 124.8 R(Normally)5.131 E(,)-.65 E F1(bash)2.631
+E F0 -.1(wa)2.63 G .13(its until it is about to print a).1 F .276
+(prompt before reporting changes in a job')108 136.8 R 2.776(ss)-.55 G .276
+(tatus so as to not interrupt an)286.292 136.8 R 2.776(yo)-.15 G .276
+(ther output.)416.124 136.8 R .276(If the)5.276 F F1(-b)2.776 E F0 .276
+(option to)2.776 F(the)108 148.8 Q F1(set)2.872 E F0 -.2(bu)2.872 G .372
+(iltin command is set,).2 F F1(bash)2.871 E F0 .371
+(reports such changes immediately)2.871 F 5.371(.\()-.65 G .371
+(See also the description of)405.105 148.8 R F1(notify)2.871 E F0 -.25(va)108
+160.8 S(riable under).25 E F1(Shell V)2.5 E(ariables)-.92 E F0(abo)2.5 E -.15
+(ve)-.15 G(.\)).15 E .529(If you attempt to e)108 177.6 R(xit)-.15 E F1(bash)
+3.029 E F0 .529(while jobs are stopped, the shell prints a message w)3.029 F
+.529(arning you.)-.1 F -1.1(Yo)5.529 G 3.029(um)1.1 G .529(ay then)510.311
+177.6 R .644(use the)108 189.6 R F1(jobs)3.144 E F0 .644
+(command to inspect their status.)3.144 F .644(If you do this, or try to e)
+5.644 F .644(xit ag)-.15 F .644(ain immediately)-.05 F 3.144(,y)-.65 G .644
+(ou are not)498.722 189.6 R -.1(wa)108 201.6 S(rned ag).1 E
+(ain, and the stopped jobs are terminated.)-.05 E/F2 9/Times-Bold@0 SF(SIGN)72
+218.4 Q(ALS)-.18 E F0(When)108 230.4 Q F1(bash)2.632 E F0 .132(is interacti)
+2.632 F -.15(ve)-.25 G 2.632(,i).15 G 2.632(ti)216.178 230.4 S(gnores)224.37
+230.4 Q F2(SIGTERM)2.632 E F0 .132(\(so that)2.382 F F1 .132(kill 0)2.632 F F0
+.133(does not kill an interacti)2.633 F .433 -.15(ve s)-.25 H .133(hell\), and)
+.15 F F2(SIGINT)2.633 E F0 .331(is caught and handled \(so that the)108 242.4 R
+F1(wait)2.831 E F0 -.2(bu)2.831 G .331(iltin is interruptible\).).2 F .33
+(In all cases,)5.33 F F1(bash)2.83 E F0(ignores)2.83 E F2(SIGQ)2.83 E(UIT)-.09
+E/F3 9/Times-Roman@0 SF(.)A F0 .33(If job)4.83 F(control is in ef)108 254.4 Q
+(fect,)-.25 E F1(bash)2.5 E F0(ignores)2.5 E F2(SIGTTIN)2.5 E F3(,)A F2(SIGTT)
+2.25 E(OU)-.162 E F3(,)A F0(and)2.25 E F2(SIGTSTP)2.5 E F3(.)A F0 1.657
+(Synchronous jobs started by)108 271.2 R F1(bash)4.157 E F0(ha)4.157 E 1.957
+-.15(ve s)-.2 H 1.658(ignals set to the v).15 F 1.658
+(alues inherited by the shell from its parent.)-.25 F 1.43
+(When job control is not in ef)108 283.2 R 1.429
+(fect, background jobs \(jobs started with)-.25 F F1(&)3.929 E F0 3.929(\)i)C
+(gnore)419.073 283.2 Q F2(SIGINT)3.929 E F0(and)3.679 E F2(SIGQ)3.929 E(UIT)
+-.09 E F3(.)A F0 1.95
+(Commands run as a result of command substitution ignore the k)108 295.2 R -.15
+(ey)-.1 G 1.95(board-generated job control signals).15 F F2(SIGTTIN)108 307.2 Q
+F3(,)A F2(SIGTT)2.25 E(OU)-.162 E F3(,)A F0(and)2.25 E F2(SIGTSTP)2.5 E F3(.)A
+F2(COMMAND EXECUTION)72 324 Q F0 .547(After a command has been split into w)108
+336 R .546(ords, if it results in a simple command and an optional list of ar)
+-.1 F(gu-)-.18 E(ments, the follo)108 348 Q(wing actions are tak)-.25 E(en.)-.1
+E .379
+(If the command name contains no slashes, the shell attempts to locate it.)108
+364.8 R .379(If there e)5.379 F .379(xists a shell function by)-.15 F .246
+(that name, that function is in)108 376.8 R -.2(vo)-.4 G -.1(ke).2 G 2.746(da)
+.1 G 2.746(sd)254.597 376.8 S .246(escribed abo)266.233 376.8 R .546 -.15(ve i)
+-.15 H(n).15 E F2(FUNCTIONS)2.746 E F3(.)A F0 .246
+(If the name does not match a func-)4.746 F
+(tion, the shell searches for it in the list of shell b)108 388.8 Q 2.5
+(uiltins. If)-.2 F 2.5(am)2.5 G(atch is found, that b)356.4 388.8 Q
+(uiltin is in)-.2 E -.2(vo)-.4 G -.1(ke).2 G(d.).1 E .309
+(If the name is neither a shell function nor a b)108 405.6 R .31
+(uiltin, and contains no slashes,)-.2 F F1(bash)2.81 E F0 .31
+(searches each element of)2.81 F(the)108 417.6 Q F2 -.666(PA)2.778 G(TH)-.189 E
+F0 .277(for a directory containing an e)2.528 F -.15(xe)-.15 G .277
+(cutable \214le by that name.).15 F .277
+(If the search is unsuccessful, the shell)5.277 F
+(prints an error message and returns a nonzero e)108 429.6 Q(xit status.)-.15 E
+1.089(If the search is successful, or if the command name contains one or more\
+ slashes, the shell e)108 446.4 R -.15(xe)-.15 G 1.09(cutes the).15 F .049
+(named program.)108 458.4 R(Ar)5.049 E .049(gument 0 is set to the name gi)-.18
+F -.15(ve)-.25 G .049(n, and the remaining ar).15 F .049
+(guments to the command are set)-.18 F(to the ar)108 470.4 Q(guments gi)-.18 E
+-.15(ve)-.25 G(n, if an).15 E -.65(y.)-.15 G 1.809(If this e)108 487.2 R -.15
+(xe)-.15 G 1.809(cution f).15 F 1.809(ails because the \214le is not in e)-.1 F
+-.15(xe)-.15 G 1.809(cutable format, and the \214le is not a directory).15 F
+4.309(,i)-.65 G 4.309(ti)526.241 487.2 S(s)536.11 487.2 Q .678(assumed to be a)
+108 499.2 R/F4 10/Times-Italic@0 SF .678(shell script)3.178 F F0 3.178(,a\214)C
+.678(le containing shell commands.)240.516 499.2 R 3.178(As)5.678 G .678
+(ubshell is spa)384.176 499.2 R .677(wned to e)-.15 F -.15(xe)-.15 G .677
+(cute it.).15 F(This)5.677 E .329
+(subshell reinitializes itself, so that the ef)108 511.2 R .329
+(fect is as if a ne)-.25 F 2.83(ws)-.25 G .33(hell had been in)348.36 511.2 R
+-.2(vo)-.4 G -.1(ke).2 G 2.83(dt).1 G 2.83(oh)442.3 511.2 S .33
+(andle the script, with)455.13 511.2 R 1.219(the e)108 523.2 R 1.219
+(xception that the locations of commands remembered by the parent \(see)-.15 F
+F1(hash)3.719 E F0(belo)3.719 E 3.719(wu)-.25 G(nder)488.496 523.2 Q F2(SHELL)
+3.719 E -.09(BU)108 535.2 S(IL).09 E(TIN COMMANDS)-.828 E F3(\))A F0
+(are retained by the child.)2.25 E .347(If the program is a \214le be)108 552 R
+.347(ginning with)-.15 F F1(#!)2.847 E F0 2.847(,t)C .348
+(he remainder of the \214rst line speci\214es an interpreter for the pro-)
+281.513 552 R 3.178(gram. The)108 564 R .678(shell e)3.178 F -.15(xe)-.15 G
+.678(cutes the speci\214ed interpreter on operating systems that do not handle\
+ this e).15 F -.15(xe)-.15 G(cutable).15 E 1.192(format themselv)108 576 R
+3.692(es. The)-.15 F(ar)3.693 E 1.193
+(guments to the interpreter consist of a single optional ar)-.18 F 1.193
+(gument follo)-.18 F 1.193(wing the)-.25 F 1.131
+(interpreter name on the \214rst line of the program, follo)108 588 R 1.13
+(wed by the name of the program, follo)-.25 F 1.13(wed by the)-.25 F
+(command ar)108 600 Q(guments, if an)-.18 E -.65(y.)-.15 G F2(ENVIR)72 616.8 Q
+(ONMENT)-.27 E F0 2.353(When a program is in)108 628.8 R -.2(vo)-.4 G -.1(ke).2
+G 4.853(di).1 G 4.853(ti)235.435 628.8 S 4.853(sg)245.848 628.8 S -2.15 -.25
+(iv e)259.591 628.8 T 4.853(na).25 G 4.853(na)285.704 628.8 S 2.353
+(rray of strings called the)299.997 628.8 R F4(en)4.853 E(vir)-.4 E(onment)-.45
+E F0 7.353(.T).68 G 2.354(his is a list of)477.245 628.8 R F4(name)108 640.8 Q
+F0<ad>A F4(value)A F0(pairs, of the form)2.5 E F4(name)2.5 E F0(=)A F4(value)A
+F0(.).18 E .173(The shell allo)108 657.6 R .173(ws you to manipulate the en)
+-.25 F .172(vironment in se)-.4 F -.15(ve)-.25 G .172(ral w).15 F 2.672
+(ays. On)-.1 F(in)2.672 E -.2(vo)-.4 G .172(cation, the shell scans its o).2 F
+(wn)-.25 E(en)108 669.6 Q .186(vironment and creates a parameter for each name\
+ found, automatically marking it for)-.4 F F4 -.2(ex)2.687 G(port).2 E F0 .187
+(to child pro-)2.687 F 2.704(cesses. Ex)108 681.6 R .203
+(ecuted commands inherit the en)-.15 F 2.703(vironment. The)-.4 F F1(export)
+2.703 E F0(and)2.703 E F1(declar)2.703 E 2.703<65ad>-.18 G(x)433.271 681.6 Q F0
+.203(commands allo)2.703 F 2.703(wp)-.25 G(aram-)516.68 681.6 Q 1.153
+(eters and functions to be added to and deleted from the en)108 693.6 R 3.653
+(vironment. If)-.4 F 1.153(the v)3.653 F 1.154(alue of a parameter in the)-.25
+F(en)108 705.6 Q .64(vironment is modi\214ed, the ne)-.4 F 3.14(wv)-.25 G .64
+(alue becomes part of the en)251.96 705.6 R .64(vironment, replacing the old.)
+-.4 F .64(The en)5.64 F(viron-)-.4 E .58(ment inherited by an)108 717.6 R 3.08
+(ye)-.15 G -.15(xe)204.45 717.6 S .58(cuted command consists of the shell').15
+F 3.08(si)-.55 G .58(nitial en)373.88 717.6 R .58(vironment, whose v)-.4 F .58
+(alues may be)-.25 F .301(modi\214ed in the shell, less an)108 729.6 R 2.801
+(yp)-.15 G .301(airs remo)236.046 729.6 R -.15(ve)-.15 G 2.801(db).15 G 2.801
+(yt)295.778 729.6 S(he)306.359 729.6 Q F1(unset)2.801 E F0 .3(command, plus an)
+2.8 F 2.8(ya)-.15 G .3(dditions via the)429.92 729.6 R F1(export)2.8 E F0(and)
+2.8 E 185.675(GNU 1995)72 768 R(May 5)2.5 E(15)530 768 Q EP
+%%Page: 16 16
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF(declar)108 84 Q 2.5<65ad>-.18 G(x)147.12 84 Q F0
+(commands.)2.5 E .636(The en)108 100.8 R .636(vironment for an)-.4 F(y)-.15 E
+/F2 10/Times-Italic@0 SF .636(simple command)3.136 F F0 .637
+(or function may be augmented temporarily by pre\214xing it with)3.137 F .203
+(parameter assignments, as described abo)108 112.8 R .502 -.15(ve i)-.15 H(n)
+.15 E/F3 9/Times-Bold@0 SF -.666(PA)2.702 G(RAMETERS).666 E/F4 9/Times-Roman@0
+SF(.)A F0 .202(These assignment statements af)4.702 F .202(fect only the)-.25 F
+(en)108 124.8 Q(vironment seen by that command.)-.4 E .592(If the)108 141.6 R
+F1<ad6b>3.092 E F0 .592(\215ag is set \(see the)3.092 F F1(set)3.093 E F0 -.2
+(bu)3.093 G .593(iltin command belo).2 F .593(w\), then)-.25 F F2(all)3.093 E
+F0 .593(parameter assignments are placed in the)3.093 F(en)108 153.6 Q
+(vironment for a command, not just those that precede the command name.)-.4 E
+(When)108 170.4 Q F1(bash)3.164 E F0(in)3.164 E -.2(vo)-.4 G -.1(ke).2 G 3.164
+(sa).1 G 3.163(ne)196.232 170.4 S .663(xternal command, the v)208.685 170.4 R
+(ariable)-.25 E F1(_)3.163 E F0 .663
+(is set to the full path name of the command and)3.163 F
+(passed to that command in its en)108 182.4 Q(vironment.)-.4 E F3(EXIT ST)72
+199.2 Q -.855(AT)-.81 G(US).855 E F0 -.15(Fo)108 211.2 S 2.903(rt).15 G .403
+(he purposes of the shell, a command which e)127.423 211.2 R .403
+(xits with a zero e)-.15 F .403(xit status has succeeded.)-.15 F .404(An e)
+5.404 F .404(xit status)-.15 F .322(of zero indicates success.)108 223.2 R
+2.821(An)5.322 G .321(on\255zero e)230.409 223.2 R .321(xit status indicates f)
+-.15 F 2.821(ailure. When)-.1 F 2.821(ac)2.821 G .321(ommand terminates on a f)
+419.946 223.2 R(atal)-.1 E(signal,)108 235.2 Q F1(bash)2.5 E F0(uses the v)2.5
+E(alue of 128+)-.25 E F1(signal)A F0(as the e)2.5 E(xit status.)-.15 E .404
+(If a command is not found, the child process created to e)108 252 R -.15(xe)
+-.15 G .404(cute it returns a status of 127.).15 F .405(If a command is)5.405 F
+(found b)108 264 Q(ut is not e)-.2 E -.15(xe)-.15 G
+(cutable, the return status is 126.).15 E F1(Bash)108 280.8 Q F0 .202
+(itself returns the e)2.702 F .202(xit status of the last command e)-.15 F -.15
+(xe)-.15 G .201(cuted, unless a syntax error occurs, in which case).15 F(it e)
+108 292.8 Q(xits with a non\255zero v)-.15 E 2.5(alue. See)-.25 F(also the)2.5
+E F1(exit)2.5 E F0 -.2(bu)2.5 G(iltin command belo).2 E -.65(w.)-.25 G F3(PR)72
+309.6 Q(OMPTING)-.27 E F0 .644(When e)108 321.6 R -.15(xe)-.15 G .644
+(cuting interacti).15 F -.15(ve)-.25 G(ly).15 E(,)-.65 E F1(bash)3.144 E F0
+.645(displays the primary prompt)3.145 F F3(PS1)3.145 E F0 .645
+(when it is ready to read a command,)2.895 F 1.826(and the secondary prompt)108
+333.6 R F3(PS2)4.326 E F0 1.825
+(when it needs more input to complete a command.)4.076 F F1(Bash)6.825 E F0
+(allo)4.325 E 1.825(ws these)-.25 F 1.499(prompt strings to be customized by i\
+nserting a number of backslash-escaped special characters that are)108 345.6 R
+(decoded as follo)108 357.6 Q(ws:)-.25 E F1(\\t)144 369.6 Q F0
+(the current time in HH:MM:SS format)180 369.6 Q F1(\\d)144 381.6 Q F0
+(the date in "W)180 381.6 Q(eekday Month Date" format \(e.g., "T)-.8 E
+(ue May 26"\))-.45 E F1(\\n)144 393.6 Q F0(ne)180 393.6 Q(wline)-.25 E F1(\\s)
+144 405.6 Q F0(the name of the shell, the basename of)180 405.6 Q F1($0)2.5 E
+F0(\(the portion follo)2.5 E(wing the \214nal slash\))-.25 E F1(\\w)144 417.6 Q
+F0(the current w)180 417.6 Q(orking directory)-.1 E F1(\\W)144 429.6 Q F0
+(the basename of the current w)180 429.6 Q(orking directory)-.1 E F1(\\u)144
+441.6 Q F0(the username of the current user)180 441.6 Q F1(\\h)144 453.6 Q F0
+(the hostname)180 453.6 Q F1(\\#)144 465.6 Q F0
+(the command number of this command)180 465.6 Q F1(\\!)144 477.6 Q F0
+(the history number of this command)180 477.6 Q F1(\\$)144 489.6 Q F0
+(if the ef)180 489.6 Q(fecti)-.25 E .3 -.15(ve U)-.25 H(ID is 0, a).15 E F1(#)
+2.5 E F0 2.5(,o)C(therwise a)301.54 489.6 Q F1($)2.5 E(\\nnn)144 501.6 Q F0
+(the character corresponding to the octal number)180 501.6 Q F1(nnn)2.5 E(\\\\)
+144 513.6 Q F0 2.5(ab)180 513.6 S(ackslash)191.94 513.6 Q F1(\\[)144 525.6 Q F0
+(be)180 525.6 Q 1.257(gin a sequence of non-printing characters, which could b\
+e used to embed a terminal)-.15 F(control sequence into the prompt)180 537.6 Q
+F1(\\])144 549.6 Q F0(end a sequence of non-printing characters)180 549.6 Q
+.119(The command number and the history number are usually dif)108 566.4 R .12
+(ferent: the history number of a command is its)-.25 F 1.585(position in the h\
+istory list, which may include commands restored from the history \214le \(see)
+108 578.4 R F3(HIST)4.084 E(OR)-.162 E(Y)-.315 E F0(belo)108 590.4 Q .541
+(w\), while the command number is the position in the sequence of commands e)
+-.25 F -.15(xe)-.15 G .541(cuted during the cur).15 F(-)-.2 E .546
+(rent shell session.)108 602.4 R .546(After the string is decoded, it is e)
+5.546 F .546(xpanded via parameter e)-.15 F .546(xpansion, command substitu-)
+-.15 F(tion, arithmetic e)108 614.4 Q(xpansion, and w)-.15 E(ord splitting.)-.1
+E F3(READLINE)72 631.2 Q F0 1.374
+(This is the library that handles reading input when using an interacti)108
+643.2 R 1.674 -.15(ve s)-.25 H 1.374(hell, unless the).15 F F1
+(\255nolineediting)3.874 E F0 .033(option is gi)108 655.2 R -.15(ve)-.25 G
+2.533(n. By).15 F(def)2.533 E .032
+(ault, the line editing commands are similar to those of emacs.)-.1 F 2.532(Av)
+5.032 G .032(i-style line editing)467.156 655.2 R(interf)108 667.2 Q
+(ace is also a)-.1 E -.25(va)-.2 G(ilable.).25 E .567
+(In this section, the emacs-style notation is used to denote k)108 684 R -.15
+(ey)-.1 G(strok).15 E 3.068(es. Control)-.1 F -.1(ke)3.068 G .568
+(ys are denoted by C\255)-.05 F F2 -.1(ke)C(y)-.2 E F0(,)A 1.196
+(e.g., C\255n means Control\255N.)108 696 R(Similarly)6.196 E(,)-.65 E F2(meta)
+3.696 E F0 -.1(ke)3.695 G 1.195(ys are denoted by M\255)-.05 F F2 -.1(ke)C(y)
+-.2 E F0 3.695(,s)C 3.695(oM)421.18 696 S 1.195(\255x means Meta\255X.)438.765
+696 R(\(On)6.195 E -.1(ke)108 708 S .932(yboards without a)-.05 F F2(meta)3.432
+E F0 -.1(ke)3.432 G 2.232 -.65(y, M)-.05 H<ad>.65 E F2(x)A F0 .932(means ESC)
+3.432 F F2(x)3.433 E F0 3.433(,i)C .933(.e., press the Escape k)322.8 708 R
+1.233 -.15(ey t)-.1 H .933(hen the).15 F F2(x)3.433 E F0 -.1(ke)3.433 G 4.733
+-.65(y. T)-.05 H .933(his mak).65 F(es)-.1 E .6(ESC the)108 720 R F2 .6
+(meta pr)3.1 F(e\214x)-.37 E F0 5.6(.T)C .6(he combination M\255C\255)203.91
+720 R F2(x)A F0 .599(means ESC\255Control\255)3.099 F F2(x)A F0 3.099(,o)C
+3.099(rp)407.796 720 S .599(ress the Escape k)419.225 720 R .899 -.15(ey t)-.1
+H .599(hen hold).15 F 185.675(GNU 1995)72 768 R(May 5)2.5 E(16)530 768 Q EP
+%%Page: 17 17
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+(the Control k)108 84 Q .3 -.15(ey w)-.1 H(hile pressing the).15 E/F1 10
+/Times-Italic@0 SF(x)2.5 E F0 -.1(ke)2.5 G -.65(y.)-.05 G(\)).65 E 1.125
+(The def)108 100.8 R 1.126(ault k)-.1 F -.15(ey)-.1 G 1.126
+(-bindings may be changed with an).15 F F1(~/.inputr)5.292 E(c)-.37 E F0 3.626
+(\214le. The)5.292 F -.25(va)3.626 G 1.126(lue of the shell v).25 F(ariable)
+-.25 E/F2 9/Times-Bold@0 SF(INPU-)3.626 E(TRC)108 112.8 Q/F3 9/Times-Roman@0 SF
+(,)A F0 .106(if set, is used instead of)2.357 F F1(~/.inputr)2.606 E(c)-.37 E
+F0 5.106(.O).31 G .106(ther programs that use this library may add their o)
+280.89 112.8 R .106(wn commands)-.25 F(and bindings.)108 124.8 Q -.15(Fo)108
+141.6 S 2.5(re).15 G(xample, placing)128.53 141.6 Q(M\255Control\255u: uni)144
+158.4 Q -.15(ve)-.25 G(rsal\255ar).15 E(gument)-.18 E(or)108 170.4 Q
+(C\255Meta\255u: uni)144 182.4 Q -.15(ve)-.25 G(rsal\255ar).15 E(gument)-.18 E
+(into the)108 194.4 Q F1(~/.inputr)4.166 E(c)-.37 E F0 -.1(wo)4.166 G(uld mak)
+.1 E 2.5(eM)-.1 G(\255C\255u e)244.092 194.4 Q -.15(xe)-.15 G
+(cute the readline command).15 E F1(univer)2.5 E(sal\255ar)-.1 E(gument)-.37 E
+F0(.).68 E 1.26(The follo)108 211.2 R 1.261
+(wing symbolic character names are recognized:)-.25 F F1 -.4(RU)3.761 G(BOUT).4
+E F0(,)1.27 E F1(DEL)3.761 E F0(,).53 E F1(ESC)3.761 E F0(,).72 E F1(LFD)3.761
+E F0(,).28 E F1(NEWLINE)3.761 E F0(,).73 E F1(RET)3.761 E F0(,)1.27 E F1
+(RETURN)108 223.2 Q F0(,)1.1 E F1(SPC)3.155 E F0(,).72 E F1(SP)3.155 E -.3(AC)
+-.9 G(E).3 E F0 3.155(,a).73 G(nd)216.315 223.2 Q F1 -.5(TA)3.155 G(B).5 E F0
+5.655(.I).27 G 3.155(na)258.505 223.2 S .655
+(ddition to command names, readline allo)271.1 223.2 R .655(ws k)-.25 F -.15
+(ey)-.1 G 3.154(st).15 G 3.154(ob)475.724 223.2 S 3.154(eb)488.878 223.2 S .654
+(ound to a)501.472 223.2 R(string that is inserted when the k)108 235.2 Q .3
+-.15(ey i)-.1 H 2.5(sp).15 G(ressed \(a)263.85 235.2 Q F1(macr)2.5 E(o)-.45 E
+F0(\).)A .827
+(Readline is customized by putting commands in an initialization \214le.)108
+252 R .827(The name of this \214le is tak)5.827 F .828(en from)-.1 F 1.325
+(the v)108 264 R 1.325(alue of the)-.25 F F2(INPUTRC)3.825 E F0 -.25(va)3.575 G
+3.825(riable. If).25 F 1.324(that v)3.825 F 1.324(ariable is unset, the def)
+-.25 F 1.324(ault is)-.1 F F1(~/.inputr)3.824 E(c)-.37 E F0 6.324(.W).31 G
+1.324(hen a program)479.592 264 R 1.158
+(which uses the readline library starts up, the init \214le is read, and the k)
+108 276 R 1.459 -.15(ey b)-.1 H 1.159(indings and v).15 F 1.159
+(ariables are set.)-.25 F .029(There are only a fe)108 288 R 2.529(wb)-.25 G
+.029(asic constructs allo)198.135 288 R .028(wed in the readline init \214le.)
+-.25 F .028(Blank lines are ignored.)5.028 F .028(Lines be)5.028 F(gin-)-.15 E
+.553(ning with a)108 300 R/F4 10/Times-Bold@0 SF(#)3.053 E F0 .554
+(are comments.)3.053 F .554(Lines be)5.554 F .554(ginning with a)-.15 F F4($)
+3.054 E F0 .554(indicate conditional constructs.)3.054 F .554
+(Other lines denote)5.554 F -.1(ke)108 312 S 2.5(yb)-.05 G(indings and v)129.69
+312 Q(ariable settings.)-.25 E .724(The syntax for controlling k)108 328.8 R
+1.024 -.15(ey b)-.1 H .724(indings in the).15 F F1(~/.inputr)3.224 E(c)-.37 E
+F0 .724(\214le is simple.)3.224 F .723(All that is required is the name of)
+5.724 F .938(the command or the te)108 340.8 R .938(xt of a macro and a k)-.15
+F 1.238 -.15(ey s)-.1 H .938
+(equence to which it should be bound. The name may be).15 F .168
+(speci\214ed in one of tw)108 352.8 R 2.668(ow)-.1 G .168(ays: as a symbolic k)
+209.46 352.8 R .468 -.15(ey n)-.1 H .167(ame, possibly with).15 F F1(Meta-)
+2.667 E F0(or)2.667 E F1(Contr)2.667 E(ol-)-.45 E F0(pre\214x)2.667 E .167
+(es, or as a k)-.15 F -.15(ey)-.1 G 3.2(sequence. When)108 364.8 R .7
+(using the form)3.2 F F4 -.1(ke)3.2 G(yname).1 E F0(:)A F1(function-name)A F0
+(or)3.201 E F1(macr)3.201 E(o)-.45 E F0(,)A F1 -.1(ke)3.201 G(yname)-.2 E F0
+.701(is the name of a k)3.201 F 1.001 -.15(ey s)-.1 H(pelled).15 E
+(out in English.)108 376.8 Q -.15(Fo)5 G 2.5(re).15 G(xample:)192.15 376.8 Q
+(Control-u: uni)144 400.8 Q -.15(ve)-.25 G(rsal\255ar).15 E(gument)-.18 E
+(Meta-Rubout: backw)144 412.8 Q(ard-kill-w)-.1 E(ord)-.1 E
+(Control-o: ">&output")144 424.8 Q .443(In the abo)108 441.6 R .743 -.15(ve ex)
+-.15 H(ample,).15 E F1(C-u)2.943 E F0 .443(is bound to the function)2.943 F F4
+(uni)2.942 E -.1(ve)-.1 G(rsal\255ar).1 E(gument)-.1 E F0(,)A F1(M-DEL)2.942 E
+F0 .442(is bound to the function)2.942 F F4(backward\255kill\255w)108 453.6 Q
+(ord)-.1 E F0 2.579(,a)C(nd)207.719 453.6 Q F1(C-o)2.579 E F0 .079
+(is bound to run the macro e)2.579 F .08
+(xpressed on the right hand side \(that is, to insert)-.15 F(the te)108 465.6 Q
+(xt)-.15 E F1(>&output)2.5 E F0(into the line\).)2.5 E .36(In the second form,)
+108 482.4 R F4("k)2.86 E(eyseq")-.1 E F0(:)A F1(function-name)A F0(or)2.859 E
+F1(macr)2.859 E(o)-.45 E F0(,)A F4 -.1(ke)2.859 G(yseq).1 E F0(dif)2.859 E .359
+(fers from)-.25 F F4 -.1(ke)2.859 G(yname).1 E F0(abo)2.859 E .659 -.15(ve i)
+-.15 H 2.859(nt).15 G .359(hat strings)498.251 482.4 R 1.284
+(denoting an entire k)108 494.4 R 1.584 -.15(ey s)-.1 H 1.284
+(equence may be speci\214ed by placing the sequence within double quotes.).15 F
+(Some)6.284 E(GNU Emacs style k)108 506.4 Q .3 -.15(ey e)-.1 H
+(scapes can be used, as in the follo).15 E(wing e)-.25 E(xample.)-.15 E
+("\\C-u": uni)144 530.4 Q -.15(ve)-.25 G(rsal\255ar).15 E(gument)-.18 E
+("\\C-x\\C-r": re\255read\255init\255\214le)144 542.4 Q("\\e[11~": "Function K)
+144 554.4 Q .3 -.15(ey 1)-.25 H(").15 E .238(In this e)108 571.2 R(xample,)-.15
+E F1(C-u)2.738 E F0 .238(is ag)2.738 F .238(ain bound to the function)-.05 F F4
+(uni)2.738 E -.1(ve)-.1 G(rsal\255ar).1 E(gument)-.1 E F0(.)A F1 .237(C-x C-r)
+5.238 F F0 .237(is bound to the function)2.737 F F4 -.18(re)108 583.2 S<ad72>
+.18 E(ead\255init\255\214le)-.18 E F0 3.909(,a)C(nd)191.139 583.2 Q F1 1.409
+(ESC [ 1 1 ~)3.909 F F0 1.409(is bound to insert the te)3.909 F(xt)-.15 E F4
+1.41(Function K)3.91 F 1.41(ey 1)-.25 F F0 6.41(.T)C 1.41
+(he full set of escape)454.94 583.2 R(sequences is)108 595.2 Q F4<5c43ad>144
+612 Q F0(control pre\214x)180 612 Q F4(\\M-)144 628.8 Q F0(meta pre\214x)180
+628.8 Q F4(\\e)144 645.6 Q F0(an escape character)180 645.6 Q F4(\\\\)144 662.4
+Q F0(backslash)180 662.4 Q F4(\\")144 679.2 Q F0(literal ")180 679.2 Q F4(\\')
+144 696 Q F0(literal ')180 696 Q .74(When entering the te)108 712.8 R .74(xt o\
+f a macro, single or double quotes should be used to indicate a macro de\214ni\
+tion.)-.15 F 1.226(Unquoted te)108 724.8 R 1.226
+(xt is assumed to be a function name.)-.15 F 1.227(Backslash will quote an)
+6.226 F 3.727(yc)-.15 G 1.227(haracter in the macro te)430.552 724.8 R(xt,)-.15
+E 185.675(GNU 1995)72 768 R(May 5)2.5 E(17)530 768 Q EP
+%%Page: 18 18
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+(including " and '.)108 84 Q/F1 10/Times-Bold@0 SF(Bash)108 100.8 Q F0(allo)
+2.93 E .43(ws the current readline k)-.25 F .73 -.15(ey b)-.1 H .429
+(indings to be displayed or modi\214ed with the).15 F F1(bind)2.929 E F0 -.2
+(bu)2.929 G .429(iltin command.).2 F .045
+(The editing mode may be switched during interacti)108 112.8 R .345 -.15(ve u)
+-.25 H .046(se by using the).15 F F1<ad6f>2.546 E F0 .046(option to the)2.546 F
+F1(set)2.546 E F0 -.2(bu)2.546 G .046(iltin command).2 F(\(see)108 124.8 Q/F2 9
+/Times-Bold@0 SF(SHELL B)2.5 E(UIL)-.09 E(TIN COMMANDS)-.828 E F0(belo)2.25 E
+(w\).)-.25 E .044(Readline has v)108 141.6 R .044
+(ariables that can be used to further customize its beha)-.25 F(vior)-.2 E
+5.044(.A)-.55 G -.25(va)413.902 141.6 S .043(riable may be set in the).25 F/F3
+10/Times-Italic@0 SF(inpu-)2.543 E(tr)108 153.6 Q(c)-.37 E F0
+(\214le with a statement of the form)2.5 E F1(set)144 170.4 Q F3
+(variable\255name value)2.5 E F0 .488(Except where noted, readline v)108 187.2
+R .489(ariables can tak)-.25 F 2.989(et)-.1 G .489(he v)307.12 187.2 R(alues)
+-.25 E F1(On)2.989 E F0(or)2.989 E F1(Off)2.989 E F0 5.489(.T)C .489(he v)
+404.025 187.2 R .489(ariables and their def)-.25 F .489(ault v)-.1 F(al-)-.25 E
+(ues are:)108 199.2 Q F1(horizontal\255scr)108 216 Q(oll\255mode \(Off\))-.18 E
+F0 .449(When set to)144 228 R F1(On)2.949 E F0 2.949(,m)C(ak)222.186 228 Q .448
+(es readline use a single line for display)-.1 F 2.948(,s)-.65 G .448
+(crolling the input horizontally on a)398.6 228 R 1.194(single screen line whe\
+n it becomes longer than the screen width rather than wrapping to a ne)144 240
+R(w)-.25 E(line.)144 252 Q F1(editing\255mode \(emacs\))108 264 Q F0 .253
+(Controls whether readline be)144 276 R .253(gins with a set of k)-.15 F .553
+-.15(ey b)-.1 H .253(indings similar to).15 F F3(emacs)2.752 E F0(or)2.752 E F3
+(vi)2.752 E F0(.)A F1(editing\255mode)5.252 E F0(can be set to either)144 288 Q
+F1(emacs)2.5 E F0(or)2.5 E F1(vi)2.5 E F0(.)A F1
+(mark\255modi\214ed\255lines \(Off\))108 300 Q F0(If set to)144 312 Q F1(On)2.5
+E F0 2.5(,h)C(istory lines that ha)200.39 312 Q .3 -.15(ve b)-.2 H
+(een modi\214ed are displayed with a preceding asterisk \().15 E F1(*)A F0(\).)
+A F1(bell\255style \(audible\))108 324 Q F0 .01
+(Controls what happens when readline w)144 336 R .011
+(ants to ring the terminal bell.)-.1 F .011(If set to)5.011 F F1(none)2.511 E
+F0 2.511(,r)C .011(eadline ne)486.799 336 R -.15(ve)-.25 G(r).15 E .94
+(rings the bell.)144 348 R .94(If set to)5.94 F F1(visible)3.44 E F0 3.44(,r)C
+.94(eadline uses a visible bell if one is a)278.91 348 R -.25(va)-.2 G 3.44
+(ilable. If).25 F .94(set to)3.44 F F1(audible)3.44 E F0(,)A
+(readline attempts to ring the terminal')144 360 Q 2.5(sb)-.55 G(ell.)306.21
+360 Q F1(comment\255begin \(`)108 372 Q(`#')-.63 E('\))-.63 E F0
+(The string that is inserted in)144 384 Q F1(vi)2.5 E F0(mode when the)2.5 E F1
+(vi\255comment)2.5 E F0(command is e)2.5 E -.15(xe)-.15 G(cuted.).15 E F1
+(meta\255\215ag \(Off\))108 396 Q F0 .227(If set to)144 408 R F1(On)2.727 E F0
+2.727(,r)C .228(eadline will enable eight-bit input \(that is, it will not str\
+ip the high bit from the char)199.628 408 R(-)-.2 E(acters it reads\), re)144
+420 Q -.05(ga)-.15 G(rdless of what the terminal claims it can support.).05 E
+F1(con)108 432 Q -.1(ve)-.4 G(rt\255meta \(On\)).1 E F0 .613(If set to)144 444
+R F1(On)3.113 E F0 3.113(,r)C .613(eadline will con)201.172 444 R -.15(ve)-.4 G
+.613(rt characters with the eighth bit set to an ASCII k).15 F .912 -.15(ey s)
+-.1 H .612(equence by).15 F 1.238
+(stripping the eighth bit and prepending an escape character \(in ef)144 456 R
+1.238(fect, using escape as the)-.25 F F3(meta)3.738 E(pr)144 468 Q(e\214x)-.37
+E F0(\).)A F1(output\255meta \(Off\))108 480 Q F0 .507(If set to)144 492 R F1
+(On)3.007 E F0 3.007(,r)C .507(eadline will display characters with the eighth\
+ bit set directly rather than as a meta-)200.748 492 R(pre\214x)144 504 Q
+(ed escape sequence.)-.15 E F1(completion\255query\255items \(100\))108 516 Q
+F0 .529(This determines when the user is queried about vie)144 528 R .53
+(wing the number of possible completions gen-)-.25 F .561(erated by the)144 540
+R F1(possible\255completions)3.061 E F0 3.061(command. It)3.061 F .561
+(may be set to an)3.061 F 3.06(yi)-.15 G(nte)428.2 540 Q .56(ger v)-.15 F .56
+(alue greater than or)-.25 F .782(equal to zero.)144 552 R .783
+(If the number of possible completions is greater than or equal to the v)5.782
+F .783(alue of this)-.25 F -.25(va)144 564 S .237(riable, the user is ask).25 F
+.237(ed whether or not he wishes to vie)-.1 F 2.737(wt)-.25 G .237
+(hem; otherwise the)389.255 564 R 2.737(ya)-.15 G .237(re simply listed)477.856
+564 R(on the terminal.)144 576 Q F1 -.1(ke)108 588 S(ymap \(emacs\)).1 E F0
+2.323(Set the current readline k)144 600 R -.15(ey)-.1 G 4.823(map. The).15 F
+2.323(set of le)4.823 F -.05(ga)-.15 G 4.823(lk).05 G -.15(ey)368.477 600 S
+2.323(map names is).15 F F3 2.324(emacs, emacs-standar)4.823 F(d,)-.37 E .809
+(emacs-meta, emacs-ctlx, vi, vi-mo)144 612 R(ve)-.1 E 3.308(,v)-.1 G(i-command)
+300.864 612 Q F0 3.308(,a)C(nd)356.102 612 Q F3(vi-insert)3.308 E F0(.).68 E F3
+(vi)5.808 E F0 .808(is equi)3.308 F -.25(va)-.25 G .808(lent to).25 F F3
+(vi-command)3.308 E F0(;)A F3(emacs)144 624 Q F0 1.123(is equi)3.623 F -.25(va)
+-.25 G 1.124(lent to).25 F F3(emacs-standar)3.624 E(d)-.37 E F0 6.124(.T)C
+1.124(he def)317.338 624 R 1.124(ault v)-.1 F 1.124(alue is)-.25 F F3(emacs)
+3.624 E F0 3.624(;t).27 G 1.124(he v)431.468 624 R 1.124(alue of)-.25 F F1
+(editing\255mode)3.624 E F0(also af)144 636 Q(fects the def)-.25 E(ault k)-.1 E
+-.15(ey)-.1 G(map.).15 E F1(sho)108 648 Q(w\255all\255if\255ambiguous \(Off\))
+-.1 E F0 .478(This alters the def)144 660 R .478(ault beha)-.1 F .478
+(vior of the completion functions.)-.2 F .477(If set to)5.477 F F1(on)2.977 E
+F0 2.977(,w)C .477(ords which ha)450.329 660 R .777 -.15(ve m)-.2 H(ore).15 E
+1.264(than one possible completion cause the matches to be listed immediately \
+instead of ringing the)144 672 R(bell.)144 684 Q F1(expand\255tilde \(Off\))108
+696 Q F0(If set to)144 708 Q F1(on)2.5 E F0 2.5(,t)C(ilde e)195.39 708 Q
+(xpansion is performed when readline attempts w)-.15 E(ord completion.)-.1 E
+.05(Readline implements a f)108 724.8 R .05(acility similar in spirit to the c\
+onditional compilation features of the C preprocessor)-.1 F 185.675(GNU 1995)72
+768 R(May 5)2.5 E(18)530 768 Q EP
+%%Page: 19 19
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+1.49(which allo)108 84 R 1.49(ws k)-.25 F 1.79 -.15(ey b)-.1 H 1.49
+(indings and v).15 F 1.49
+(ariable settings to be performed as the result of tests.)-.25 F 1.49
+(There are three)6.49 F(parser directi)108 96 Q -.15(ve)-.25 G 2.5(su).15 G
+(sed.)180.91 96 Q/F1 10/Times-Bold@0 SF($if)108 112.8 Q F0(The)144 112.8 Q F1
+($if)2.963 E F0 .463(construct allo)2.963 F .462
+(ws bindings to be made based on the editing mode, the terminal being used,)
+-.25 F .477(or the application using readline.)144 124.8 R .477(The te)5.477 F
+.477(xt of the test e)-.15 F .477(xtends to the end of the line; no characters)
+-.15 F(are required to isolate it.)144 136.8 Q F1(mode)144 153.6 Q F0(The)180
+153.6 Q F1(mode=)3.712 E F0 1.212(form of the)3.712 F F1($if)3.711 E F0
+(directi)3.711 E 1.511 -.15(ve i)-.25 H 3.711(su).15 G 1.211
+(sed to test whether readline is in emacs or vi)351.631 153.6 R 3.065
+(mode. This)180 165.6 R .565(may be used in conjunction with the)3.065 F F1
+.565(set k)3.065 F(eymap)-.1 E F0 .565(command, for instance, to)3.065 F .03
+(set bindings in the)180 177.6 R/F2 10/Times-Italic@0 SF(emacs-standar)2.529 E
+(d)-.37 E F0(and)2.529 E F2(emacs-ctlx)2.529 E F0 -.1(ke)2.529 G .029
+(ymaps only if readline is starting out)-.05 F(in emacs mode.)180 189.6 Q F1
+(term)144 206.4 Q F0(The)180 206.4 Q F1(term=)3.196 E F0 .696
+(form may be used to include terminal-speci\214c k)3.196 F .996 -.15(ey b)-.1 H
+.697(indings, perhaps to bind).15 F .654(the k)180 218.4 R .954 -.15(ey s)-.1 H
+.654(equences output by the terminal').15 F 3.154(sf)-.55 G .654(unction k)
+360.138 218.4 R -.15(ey)-.1 G 3.154(s. The).15 F -.1(wo)3.154 G .654
+(rd on the right side of).1 F(the)180 230.4 Q F1(=)3.003 E F0 .503
+(is tested ag)3.003 F .504
+(ainst the full name of the terminal and the portion of the terminal name)-.05
+F(before the \214rst)180 242.4 Q F1<ad>2.5 E F0 5(.T)C(his allo)260.13 242.4 Q
+(ws)-.25 E F2(sun)2.5 E F0(to match both)2.5 E F2(sun)2.5 E F0(and)2.5 E F2
+(sun\255cmd)2.5 E F0 2.5(,f).77 G(or instance.)456.28 242.4 Q F1(application)
+144 259.2 Q F0(The)180 271.2 Q F1(application)2.772 E F0 .272
+(construct is used to include application\255speci\214c settings.)2.772 F .272
+(Each program)5.272 F .114(using the readline library sets the)180 283.2 R F2
+.114(application name)2.614 F F0 2.614(,a)C .114
+(nd an initialization \214le can test for a)395.052 283.2 R .501(particular v)
+180 295.2 R 3.001(alue. This)-.25 F .501(could be used to bind k)3.001 F .801
+-.15(ey s)-.1 H .5(equences to functions useful for a spe-).15 F .396
+(ci\214c program.)180 307.2 R -.15(Fo)5.396 G 2.896(ri).15 G .396
+(nstance, the follo)261.308 307.2 R .396(wing command adds a k)-.25 F .696 -.15
+(ey s)-.1 H .397(equence that quotes the).15 F(current or pre)180 319.2 Q
+(vious w)-.25 E(ord in Bash:)-.1 E F1($if)180 331.2 Q F0(Bash)2.5 E 2.5(#Q)180
+343.2 S(uote the current or pre)194.72 343.2 Q(vious w)-.25 E(ord)-.1 E
+("\\C-xq": "\\eb\\"\\ef\\"")180 355.2 Q F1($endif)180 367.2 Q($endif)108 384 Q
+F0(This command, as you sa)9.33 E 2.5(wi)-.15 G 2.5(nt)257.73 384 S(he pre)
+268.01 384 Q(vious e)-.25 E(xample, terminates an)-.15 E F1($if)2.5 E F0
+(command.)2.5 E F1($else)108 400.8 Q F0(Commands in this branch of the)144
+400.8 Q F1($if)2.5 E F0(directi)2.5 E .3 -.15(ve a)-.25 H(re e).15 E -.15(xe)
+-.15 G(cuted if the test f).15 E(ails.)-.1 E .62(Readline commands may be gi)
+108 417.6 R -.15(ve)-.25 G 3.119(nn).15 G(umeric)255.959 417.6 Q F2(ar)3.119 E
+(guments)-.37 E F0 3.119(,w).27 G .619(hich normally act as a repeat count.)
+341.807 417.6 R(Sometimes,)5.619 E(ho)108 429.6 Q(we)-.25 E -.15(ve)-.25 G
+1.418 -.4(r, i).15 H 3.118(ti).4 G 3.119(st)158.456 429.6 S .619
+(he sign of the ar)168.245 429.6 R .619(gument that is signi\214cant.)-.18 F
+-.15(Pa)5.619 G .619(ssing a ne).15 F -.05(ga)-.15 G(ti).05 E .919 -.15(ve a)
+-.25 H -.18(rg).15 G .619(ument to a command that).18 F 1.019(acts in the forw)
+108 441.6 R 1.018(ard direction \(e.g.,)-.1 F F1(kill\255line)3.518 E F0 3.518
+(\)c)C 1.018(auses that command to act in a backw)298.478 441.6 R 1.018
+(ard direction.)-.1 F(Com-)6.018 E(mands whose beha)108 453.6 Q(vior with ar)
+-.2 E(guments de)-.18 E(viates from this are noted.)-.25 E .811
+(When a command is described as)108 470.4 R F2(killing)3.311 E F0(te)3.311 E
+.811(xt, the te)-.15 F .811(xt deleted is sa)-.15 F -.15(ve)-.2 G 3.311(df).15
+G .812(or possible future retrie)403.403 470.4 R -.25(va)-.25 G 3.312(l\().25 G
+F2(yank-)517.79 470.4 Q(ing)108 482.4 Q F0 3.439(\). The)B .939(killed te)3.439
+F .939(xt is sa)-.15 F -.15(ve)-.2 G 3.439(di).15 G 3.438(na)234.794 482.4 S F2
+(kill\255ring)A F0 5.938(.C)C(onsecuti)302.418 482.4 Q 1.238 -.15(ve k)-.25 H
+.938(ills cause the te).15 F .938(xt to be accumulated into one)-.15 F .331
+(unit, which can be yank)108 494.4 R .331(ed all at once.)-.1 F .331
+(Commands which do not kill te)5.331 F .331(xt separate the chunks of te)-.15 F
+.331(xt on the)-.15 F(kill\255ring.)108 506.4 Q 1.392(The follo)108 523.2 R
+1.391(wing is a list of the names of the commands and the def)-.25 F 1.391
+(ault k)-.1 F 1.691 -.15(ey s)-.1 H 1.391(equences to which the).15 F 3.891(ya)
+-.15 G(re)532.23 523.2 Q(bound.)108 535.2 Q F1(Commands f)87 552 Q(or Mo)-.25 E
+(ving)-.1 E(beginning\255of\255line \(C\255a\))108 564 Q F0(Mo)144 576 Q .3
+-.15(ve t)-.15 H 2.5(ot).15 G(he start of the current line.)182.59 576 Q F1
+(end\255of\255line \(C\255e\))108 588 Q F0(Mo)144 600 Q .3 -.15(ve t)-.15 H 2.5
+(ot).15 G(he end of the line.)182.59 600 Q F1 -.25(fo)108 612 S
+(rward\255char \(C\255f\)).25 E F0(Mo)144 624 Q .3 -.15(ve f)-.15 H(orw).15 E
+(ard a character)-.1 E(.)-.55 E F1(backward\255char \(C\255b\))108 636 Q F0(Mo)
+144 648 Q .3 -.15(ve b)-.15 H(ack a character).15 E(.)-.55 E F1 -.25(fo)108 660
+S(rward\255w).25 E(ord \(M\255f\))-.1 E F0(Mo)144 672 Q .822 -.15(ve f)-.15 H
+(orw).15 E .522(ard to the end of the ne)-.1 F .523(xt w)-.15 F 3.023(ord. W)
+-.1 F .523(ords are composed of alphanumeric characters \(let-)-.8 F
+(ters and digits\).)144 684 Q F1(backward\255w)108 696 Q(ord \(M\255b\))-.1 E
+F0(Mo)144 708 Q .749 -.15(ve b)-.15 H .449
+(ack to the start of this, or the pre).15 F .449(vious, w)-.25 F 2.949(ord. W)
+-.1 F .448(ords are composed of alphanumeric char)-.8 F(-)-.2 E
+(acters \(letters and digits\).)144 720 Q 185.675(GNU 1995)72 768 R(May 5)2.5 E
+(19)530 768 Q EP
+%%Page: 20 20
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF(clear\255scr)108 84 Q(een \(C\255l\))-.18 E F0 .993
+(Clear the screen lea)144 96 R .993
+(ving the current line at the top of the screen.)-.2 F -.4(Wi)5.993 G .993
+(th an ar).4 F .993(gument, refresh the)-.18 F
+(current line without clearing the screen.)144 108 Q F1 -.18(re)108 120 S
+(draw\255curr).18 E(ent\255line)-.18 E F0(Refresh the current line.)144 132 Q
+(By def)5 E(ault, this is unbound.)-.1 E F1(Commands f)87 148.8 Q
+(or Manipulating the History)-.25 E(accept\255line \(Newline, Retur)108 160.8 Q
+(n\))-.15 E F0 .037(Accept the line re)144 172.8 R -.05(ga)-.15 G .037
+(rdless of where the cursor is.).05 F .037(If this line is non\255empty)5.037 F
+2.537(,a)-.65 G .036(dd it to the history list)451.748 172.8 R .699
+(according to the state of the)144 184.8 R/F2 9/Times-Bold@0 SF(HISTCONTR)3.199
+E(OL)-.27 E F0 -.25(va)2.949 G 3.199(riable. If).25 F .699
+(the line is a modi\214ed history line, then)3.199 F
+(restore the history line to its original state.)144 196.8 Q F1(pr)108 208.8 Q
+-.15(ev)-.18 G(ious\255history \(C\255p\)).15 E F0(Fetch the pre)144 220.8 Q
+(vious command from the history list, mo)-.25 E(ving back in the list.)-.15 E
+F1(next\255history \(C\255n\))108 232.8 Q F0(Fetch the ne)144 244.8 Q
+(xt command from the history list, mo)-.15 E(ving forw)-.15 E(ard in the list.)
+-.1 E F1(beginning\255of\255history \(M\255<\))108 256.8 Q F0(Mo)144 268.8 Q .3
+-.15(ve t)-.15 H 2.5(ot).15 G(he \214rst line in the history)182.59 268.8 Q(.)
+-.65 E F1(end\255of\255history \(M\255>\))108 280.8 Q F0(Mo)144 292.8 Q .3 -.15
+(ve t)-.15 H 2.5(ot).15 G(he end of the input history)182.59 292.8 Q 2.5(,i)
+-.65 G(.e., the line currently being entered.)294.99 292.8 Q F1 -2.29 -.18
+(re v)108 304.8 T(erse\255sear).08 E(ch\255history \(C\255r\))-.18 E F0 1.471
+(Search backw)144 316.8 R 1.471(ard starting at the current line and mo)-.1 F
+1.47(ving `up' through the history as necessary)-.15 F(.)-.65 E
+(This is an incremental search.)144 328.8 Q F1 -.25(fo)108 340.8 S
+(rward\255sear).25 E(ch\255history \(C\255s\))-.18 E F0 1.131(Search forw)144
+352.8 R 1.131(ard starting at the current line and mo)-.1 F 1.132(ving `do)-.15
+F 1.132(wn' through the history as necessary)-.25 F(.)-.65 E
+(This is an incremental search.)144 364.8 Q F1(non\255incr)108 376.8 Q
+(emental\255r)-.18 E -2.3 -.15(ev e)-.18 H(rse\255sear).15 E
+(ch\255history \(M\255p\))-.18 E F0 1.089(Search backw)144 388.8 R 1.088(ard t\
+hrough the history starting at the current line using a non\255incremental sea\
+rch)-.1 F(for a string supplied by the user)144 400.8 Q(.)-.55 E F1
+(non\255incr)108 412.8 Q(emental\255f)-.18 E(orward\255sear)-.25 E
+(ch\255history \(M\255n\))-.18 E F0 1.188(Search forw)144 424.8 R 1.189(ard th\
+rough the history using a non\255incremental search for a string supplied by t\
+he)-.1 F(user)144 436.8 Q(.)-.55 E F1(history\255sear)108 448.8 Q(ch\255f)-.18
+E(orward)-.25 E F0 .249(Search forw)144 460.8 R .249(ard through the history f\
+or the string of characters between the start of the current line)-.1 F
+(and the current point.)144 472.8 Q(This is a non-incremental search.)5 E
+(By def)5 E(ault, this command is unbound.)-.1 E F1(history\255sear)108 484.8 Q
+(ch\255backward)-.18 E F0 .95(Search backw)144 496.8 R .951(ard through the hi\
+story for the string of characters between the start of the current)-.1 F 2.721
+(line and the current point.)144 508.8 R 2.721
+(This is a non-incremental search.)7.721 F 2.72(By def)7.721 F 2.72
+(ault, this command is)-.1 F(unbound.)144 520.8 Q F1(yank\255nth\255ar)108
+532.8 Q 2.5(g\()-.1 G<4dad43ad7929>175.14 532.8 Q F0 .622
+(Insert the \214rst ar)144 544.8 R .622(gument to the pre)-.18 F .622
+(vious command \(usually the second w)-.25 F .622(ord on the pre)-.1 F .622
+(vious line\))-.25 F .682(at point \(the current cursor position\).)144 556.8 R
+-.4(Wi)5.682 G .682(th an ar).4 F(gument)-.18 E/F3 10/Times-Italic@0 SF(n)3.182
+E F0 3.182(,i).24 G .682(nsert the)390.17 556.8 R F3(n)3.182 E F0 .682(th w)B
+.681(ord from the pre)-.1 F(vious)-.25 E .729(command \(the w)144 568.8 R .729
+(ords in the pre)-.1 F .729(vious command be)-.25 F .729(gin with w)-.15 F .729
+(ord 0\).)-.1 F 3.23(An)5.73 G -2.25 -.15(eg a)441.56 568.8 T(ti).15 E 1.03
+-.15(ve a)-.25 H -.18(rg).15 G .73(ument inserts).18 F(the)144 580.8 Q F3(n)2.5
+E F0(th w)A(ord from the end of the pre)-.1 E(vious command.)-.25 E F1
+(yank\255last\255ar)108 592.8 Q 2.5(g\()-.1 G -1.667(M\255. ,)175.69 592.8 R
+-1.667(M\255_ \))2.5 F F0 1.077(Insert the last ar)144 604.8 R 1.077
+(gument to the pre)-.18 F 1.077(vious command \(the last w)-.25 F 1.077
+(ord on the pre)-.1 F 1.077(vious line\).)-.25 F -.4(Wi)6.076 G 1.076(th an).4
+F(ar)144 616.8 Q(gument, beha)-.18 E .3 -.15(ve ex)-.2 H(actly lik).15 E(e)-.1
+E F1(yank-nth-ar)2.5 E(g)-.1 E F0(.)A F1
+(shell\255expand\255line \(M\255C\255e\))108 628.8 Q F0 .223
+(Expand the line the w)144 640.8 R .223(ay the shell does when it reads it.)-.1
+F .224(This performs alias and history e)5.224 F(xpansion)-.15 E .161
+(as well as all of the shell w)144 652.8 R .161(ord e)-.1 F 2.661
+(xpansions. See)-.15 F F2(HIST)2.661 E(OR)-.162 E 2.411(YE)-.315 G(XP)387.555
+652.8 Q(ANSION)-.666 E F0(belo)2.411 E 2.661(wf)-.25 G .16(or a description of)
+466.479 652.8 R(history e)144 664.8 Q(xpansion.)-.15 E F1
+(history\255expand\255line \(M\255^\))108 676.8 Q F0 .938(Perform history e)144
+688.8 R .939(xpansion on the current line.)-.15 F(See)5.939 E F2(HIST)3.439 E
+(OR)-.162 E 3.189(YE)-.315 G(XP)407.662 688.8 Q(ANSION)-.666 E F0(belo)3.189 E
+3.439(wf)-.25 G .939(or a descrip-)488.142 688.8 R(tion of history e)144 700.8
+Q(xpansion.)-.15 E 185.675(GNU 1995)72 768 R(May 5)2.5 E(20)530 768 Q EP
+%%Page: 21 21
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF(insert\255last\255ar)108 84 Q(gument \(M\255.)-.1 E 2.5
+(,M).833 G -1.667(\255_ \))239.143 84 R F0 2.5(As)144 96 S(ynon)157.61 96 Q
+(ym for)-.15 E F1(yank\255last\255ar)2.5 E(g)-.1 E F0(.)A F1
+(operate-and-get-next \(C\255o\))108 108 Q F0 .948
+(Accept the current line for e)144 120 R -.15(xe)-.15 G .948
+(cution and fetch the ne).15 F .948(xt line relati)-.15 F 1.247 -.15(ve t)-.25
+H 3.447(ot).15 G .947(he current line from the)441.792 120 R
+(history for editing.)144 132 Q(An)5 E 2.5(ya)-.15 G -.18(rg)247.73 132 S
+(ument is ignored.).18 E F1(Commands f)87 148.8 Q(or Changing T)-.25 E(ext)-.92
+E(delete\255char \(C\255d\))108 160.8 Q F0 .486
+(Delete the character under the cursor)144 172.8 R 5.486(.I)-.55 G 2.987(fp)
+304.636 172.8 S .487(oint is at the be)315.953 172.8 R .487
+(ginning of the line, there are no charac-)-.15 F
+(ters in the line, and the last character typed w)144 184.8 Q(as not)-.1 E F1
+(C\255d)2.5 E F0 2.5(,t)C(hen return)377.34 184.8 Q/F2 9/Times-Bold@0 SF(EOF)
+2.5 E/F3 9/Times-Roman@0 SF(.)A F1(backward\255delete\255char \(Rubout\))108
+196.8 Q F0 .553(Delete the character behind the cursor)144 208.8 R 5.553(.W)
+-.55 G .553(hen gi)315.598 208.8 R -.15(ve)-.25 G 3.053(nan).15 G .553
+(umeric ar)370.457 208.8 R .552(gument, sa)-.18 F .852 -.15(ve t)-.2 H .552
+(he deleted te).15 F .552(xt on)-.15 F(the kill\255ring.)144 220.8 Q F1
+(quoted\255insert \(C\255q, C\255v\))108 232.8 Q F0 1.228(Add the ne)144 244.8
+R 1.228(xt character that you type to the line v)-.15 F 3.728(erbatim. This)
+-.15 F 1.228(is ho)3.728 F 3.729(wt)-.25 G 3.729(oi)446.163 244.8 S 1.229
+(nsert characters lik)457.672 244.8 R(e)-.1 E F1(C\255q)144 256.8 Q F0 2.5(,f)C
+(or e)170.81 256.8 Q(xample.)-.15 E F1(tab\255insert \(C-v T)108 268.8 Q(AB\))
+-.9 E F0(Insert a tab character)144 280.8 Q(.)-.55 E F1
+(self\255insert \(a, b, A, 1, !, ...\))108 292.8 Q F0
+(Insert the character typed.)144 304.8 Q F1(transpose\255chars \(C\255t\))108
+316.8 Q F0 .424(Drag the character before point forw)144 328.8 R .424(ard o)-.1
+F -.15(ve)-.15 G 2.924(rt).15 G .424(he character at point.)331.218 328.8 R
+.424(Point mo)5.424 F -.15(ve)-.15 G 2.924(sf).15 G(orw)477.882 328.8 Q .424
+(ard as well.)-.1 F 1.03
+(If point is at the end of the line, then transpose the tw)144 340.8 R 3.531
+(oc)-.1 G 1.031(haracters before point.)382.266 340.8 R(Ne)6.031 E -.05(ga)-.15
+G(ti).05 E 1.331 -.15(ve a)-.25 H -.18(rg).15 G(u-).18 E(ments don')144 352.8 Q
+2.5(tw)-.18 G(ork.)200.94 352.8 Q F1(transpose\255w)108 364.8 Q
+(ords \(M\255t\))-.1 E F0 .683(Drag the w)144 376.8 R .682
+(ord behind the cursor past the w)-.1 F .682(ord in front of the cursor mo)-.1
+F .682(ving the cursor o)-.15 F -.15(ve)-.15 G 3.182(rt).15 G(hat)527.78 376.8
+Q -.1(wo)144 388.8 S(rd as well.).1 E F1(upcase\255w)108 400.8 Q
+(ord \(M\255u\))-.1 E F0 .702(Uppercase the current \(or follo)144 412.8 R .702
+(wing\) w)-.25 F 3.202(ord. W)-.1 F .702(ith a ne)-.4 F -.05(ga)-.15 G(ti).05 E
+1.002 -.15(ve a)-.25 H -.18(rg).15 G .702(ument, do the pre).18 F .703(vious w)
+-.25 F .703(ord, b)-.1 F(ut)-.2 E(do not mo)144 424.8 Q .3 -.15(ve p)-.15 H
+(oint.).15 E F1(do)108 436.8 Q(wncase\255w)-.1 E(ord \(M\255l\))-.1 E F0(Lo)144
+448.8 Q .641(wercase the current \(or follo)-.25 F .641(wing\) w)-.25 F 3.141
+(ord. W)-.1 F .641(ith a ne)-.4 F -.05(ga)-.15 G(ti).05 E .941 -.15(ve a)-.25 H
+-.18(rg).15 G .64(ument, do the pre).18 F .64(vious w)-.25 F .64(ord, b)-.1 F
+(ut)-.2 E(do not mo)144 460.8 Q .3 -.15(ve p)-.15 H(oint.).15 E F1
+(capitalize\255w)108 472.8 Q(ord \(M\255c\))-.1 E F0 .82
+(Capitalize the current \(or follo)144 484.8 R .82(wing\) w)-.25 F 3.32(ord. W)
+-.1 F .82(ith a ne)-.4 F -.05(ga)-.15 G(ti).05 E 1.12 -.15(ve a)-.25 H -.18(rg)
+.15 G .82(ument, do the pre).18 F .82(vious w)-.25 F .82(ord, b)-.1 F(ut)-.2 E
+(do not mo)144 496.8 Q .3 -.15(ve p)-.15 H(oint.).15 E F1(Killing and Y)87
+513.6 Q(anking)-.85 E(kill\255line \(C\255k\))108 525.6 Q F0(Kill the te)144
+537.6 Q(xt from the current cursor position to the end of the line.)-.15 E F1
+(backward\255kill\255line \(C\255x C\255Rubout\))108 549.6 Q F0(Kill backw)144
+561.6 Q(ard to the be)-.1 E(ginning of the line.)-.15 E F1
+(unix\255line\255discard \(C\255u\))108 573.6 Q F0(Kill backw)144 585.6 Q
+(ard from point to the be)-.1 E(ginning of the line.)-.15 E F1
+(kill\255whole\255line)108 597.6 Q F0
+(Kill all characters on the current line, no matter where the cursor is.)144
+609.6 Q(By def)5 E(ault, this is unbound.)-.1 E F1(kill\255w)108 621.6 Q
+(ord \(M\255d\))-.1 E F0 1.044
+(Kill from the cursor to the end of the current w)144 633.6 R 1.043
+(ord, or if between w)-.1 F 1.043(ords, to the end of the ne)-.1 F(xt)-.15 E
+-.1(wo)144 645.6 S 2.5(rd. W).1 F(ord boundaries are the same as those used by)
+-.8 E F1 -.25(fo)2.5 G(rward\255w).25 E(ord)-.1 E F0(.)A F1
+(backward\255kill\255w)108 657.6 Q(ord \(M\255Rubout\))-.1 E F0 3.26
+(Kill the w)144 669.6 R 3.26(ord behind the cursor)-.1 F 8.26(.W)-.55 G 3.26
+(ord boundaries are the same as those used by)304.31 669.6 R F1(back-)5.76 E
+(ward\255w)144 681.6 Q(ord)-.1 E F0(.)A F1(unix\255w)108 693.6 Q
+(ord\255rubout \(C\255w\))-.1 E F0 .482(Kill the w)144 705.6 R .482
+(ord behind the cursor)-.1 F 2.982(,u)-.4 G .482(sing white space as a w)
+281.652 705.6 R .482(ord boundary)-.1 F 5.482(.T)-.65 G .482(he w)445.076 705.6
+R .481(ord boundaries are)-.1 F(dif)144 717.6 Q(ferent from backw)-.25 E
+(ard\255kill\255w)-.1 E(ord.)-.1 E 185.675(GNU 1995)72 768 R(May 5)2.5 E(21)530
+768 Q EP
+%%Page: 22 22
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF(delete\255horizontal\255space)108 84 Q F0
+(Delete all spaces and tabs around point.)144 96 Q(By def)5 E
+(ault, this is unbound.)-.1 E F1(yank \(C\255y\))108 108 Q F0 -1(Ya)144 120 S
+(nk the top of the kill ring into the b)1 E(uf)-.2 E(fer at the cursor)-.25 E
+(.)-.55 E F1(yank\255pop \(M\255y\))108 132 Q F0
+(Rotate the kill\255ring, and yank the ne)144 144 Q 2.5(wt)-.25 G 2.5(op. Only)
+302.71 144 R -.1(wo)2.5 G(rks follo).1 E(wing)-.25 E F1(yank)2.5 E F0(or)2.5 E
+F1(yank\255pop)2.5 E F0(.)A F1(Numeric Ar)87 160.8 Q(guments)-.1 E(digit\255ar)
+108 172.8 Q(gument \(M\2550, M\2551, ..., M\255\255\))-.1 E F0 .641
+(Add this digit to the ar)144 184.8 R .641
+(gument already accumulating, or start a ne)-.18 F 3.141(wa)-.25 G -.18(rg)
+425.942 184.8 S 3.142(ument. M\255\255).18 F .642(starts a ne)3.142 F(g-)-.15 E
+(ati)144 196.8 Q .3 -.15(ve a)-.25 H -.18(rg).15 G(ument.).18 E F1(uni)108
+208.8 Q -.1(ve)-.1 G(rsal\255ar).1 E(gument)-.1 E F0 .783(Each time this is e)
+144 220.8 R -.15(xe)-.15 G .783(cuted, the ar).15 F .782
+(gument count is multiplied by four)-.18 F 5.782(.T)-.55 G .782(he ar)437.062
+220.8 R .782(gument count is ini-)-.18 F .175(tially one, so e)144 232.8 R -.15
+(xe)-.15 G .175(cuting this function the \214rst time mak).15 F .176(es the ar)
+-.1 F .176(gument count four)-.18 F 5.176(.B)-.55 G 2.676(yd)485.028 232.8 S
+(ef)497.704 232.8 Q .176(ault, this)-.1 F(is not bound to a k)144 244.8 Q -.15
+(ey)-.1 G(.)-.5 E F1(Completing)87 261.6 Q(complete \(T)108 273.6 Q(AB\))-.9 E
+F0 1.137(Attempt to perform completion on the te)144 285.6 R 1.137
+(xt before point.)-.15 F F1(Bash)6.137 E F0 1.137
+(attempts completion treating the)3.637 F(te)144 297.6 Q .532(xt as a v)-.15 F
+.532(ariable \(if the te)-.25 F .532(xt be)-.15 F .533(gins with)-.15 F F1($)
+3.033 E F0 .533(\), username \(if the te)B .533(xt be)-.15 F .533(gins with)
+-.15 F F1(~)3.033 E F0 .533(\), hostname \(if the)B(te)144 309.6 Q .702(xt be)
+-.15 F .702(gins with)-.15 F F1(@)3.202 E F0 .701
+(\), or command \(including aliases and functions\) in turn.)B .701
+(If none of these pro-)5.701 F
+(duces a match, \214lename completion is attempted.)144 321.6 Q F1
+(possible\255completions \(M-?\))108 333.6 Q F0
+(List the possible completions of the te)144 345.6 Q(xt before point.)-.15 E F1
+(insert\255completions)108 357.6 Q F0 3.372(Insert all completions of the te)
+144 369.6 R 3.372(xt before point that w)-.15 F 3.372(ould ha)-.1 F 3.672 -.15
+(ve b)-.2 H 3.372(een generated by).15 F F1(possi-)5.873 E(ble\255completions)
+144 381.6 Q F0 5(.B)C 2.5(yd)227.76 381.6 S(ef)240.26 381.6 Q
+(ault, this is not bound to a k)-.1 E -.15(ey)-.1 G(.)-.5 E F1
+(complete\255\214lename \(M\255/\))108 393.6 Q F0
+(Attempt \214lename completion on the te)144 405.6 Q(xt before point.)-.15 E F1
+(possible\255\214lename\255completions \(C\255x /\))108 417.6 Q F0
+(List the possible completions of the te)144 429.6 Q
+(xt before point, treating it as a \214lename.)-.15 E F1(complete\255user)108
+441.6 Q(name \(M\255~\))-.15 E F0(Attempt completion on the te)144 453.6 Q
+(xt before point, treating it as a username.)-.15 E F1(possible\255user)108
+465.6 Q(name\255completions \(C\255x ~\))-.15 E F0
+(List the possible completions of the te)144 477.6 Q
+(xt before point, treating it as a username.)-.15 E F1(complete\255v)108 489.6
+Q(ariable \(M\255$\))-.1 E F0(Attempt completion on the te)144 501.6 Q
+(xt before point, treating it as a shell v)-.15 E(ariable.)-.25 E F1
+(possible\255v)108 513.6 Q(ariable\255completions \(C\255x $\))-.1 E F0
+(List the possible completions of the te)144 525.6 Q
+(xt before point, treating it as a shell v)-.15 E(ariable.)-.25 E F1
+(complete\255hostname \(M\255@\))108 537.6 Q F0(Attempt completion on the te)
+144 549.6 Q(xt before point, treating it as a hostname.)-.15 E F1
+(possible\255hostname\255completions \(C\255x @\))108 561.6 Q F0
+(List the possible completions of the te)144 573.6 Q
+(xt before point, treating it as a hostname.)-.15 E F1
+(complete\255command \(M\255!\))108 585.6 Q F0 .581
+(Attempt completion on the te)144 597.6 R .581
+(xt before point, treating it as a command name.)-.15 F .58(Command comple-)
+5.58 F .238(tion attempts to match the te)144 609.6 R .238(xt ag)-.15 F .239
+(ainst aliases, reserv)-.05 F .239(ed w)-.15 F .239(ords, shell functions, b)
+-.1 F .239(uiltins, and \214nally)-.2 F -.15(exe)144 621.6 S
+(cutable \214lenames, in that order).15 E(.)-.55 E F1
+(possible\255command\255completions \(C\255x !\))108 633.6 Q F0
+(List the possible completions of the te)144 645.6 Q
+(xt before point, treating it as a command name.)-.15 E F1
+(dynamic\255complete\255history \(M-T)108 657.6 Q(AB\))-.9 E F0 .425
+(Attempt completion on the te)144 669.6 R .425
+(xt before point, comparing the te)-.15 F .425(xt ag)-.15 F .424
+(ainst lines from the history list)-.05 F(for possible completion matches.)144
+681.6 Q F1(complete\255into\255braces \(M\255{\))108 693.6 Q F0 .272(Perform \
+\214lename completion and return the list of possible completions enclosed wit\
+hin braces so)144 705.6 R(the list is a)144 717.6 Q -.25(va)-.2 G
+(ilable to the shell \(see).25 E F1(Brace Expansion)2.5 E F0(abo)2.5 E -.15(ve)
+-.15 G(\).).15 E 185.675(GNU 1995)72 768 R(May 5)2.5 E(22)530 768 Q EP
+%%Page: 23 23
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF -.25(Ke)87 84 S(yboard Macr).25 E(os)-.18 E
+(start\255kbd\255macr)108 96 Q 2.5(o\()-.18 G(C-x \()188.93 96 Q(\)).833 E F0
+(Be)144 108 Q(gin sa)-.15 E(ving the characters typed into the current k)-.2 E
+-.15(ey)-.1 G(board macro.).15 E F1(end\255kbd\255macr)108 120 Q 2.5(o\()-.18 G
+(C-x \))184.5 120 Q(\)).833 E F0(Stop sa)144 132 Q
+(ving the characters typed into the current k)-.2 E -.15(ey)-.1 G
+(board macro and sa).15 E .3 -.15(ve t)-.2 H(he de\214nition.).15 E F1
+(call\255last\255kbd\255macr)108 144 Q 2.5(o\()-.18 G(C-x e\))204.64 144 Q F0
+(Re-e)144 156 Q -.15(xe)-.15 G 1(cute the last k).15 F -.15(ey)-.1 G .999
+(board macro de\214ned, by making the characters in the macro appear as if).15
+F(typed at the k)144 168 Q -.15(ey)-.1 G(board.).15 E F1(Miscellaneous)87 184.8
+Q -.18(re)108 196.8 S<ad72>.18 E(ead\255init\255\214le \(C\255x C\255r\))-.18 E
+F0 .54(Read in the contents of your init \214le, and incorporate an)144 208.8 R
+3.041(yb)-.15 G .541(indings or v)385.876 208.8 R .541
+(ariable assignments found)-.25 F(there.)144 220.8 Q F1(abort \(C\255g\))108
+232.8 Q F0 3.249(Abort the current editing command and ring the terminal')144
+244.8 R 5.748(sb)-.55 G 3.248(ell \(subject to the setting of)414.6 244.8 R F1
+(bell\255style)144 256.8 Q F0(\).)A F1(do\255upper)108 268.8 Q(case\255v)-.18 E
+(ersion \(M\255a, M\255b, ...\))-.1 E F0
+(Run the command that is bound to the corresponding uppercase character)144
+280.8 Q(.)-.55 E F1(pr)108 292.8 Q(e\214x\255meta \(ESC\))-.18 E F0
+(Metafy the ne)144 304.8 Q(xt character typed.)-.15 E/F2 9/Times-Bold@0 SF(ESC)
+5 E F1(f)2.25 E F0(is equi)2.5 E -.25(va)-.25 G(lent to).25 E F1(Meta\255f)2.5
+E F0(.)A F1(undo \(C\255_, C\255x C\255u\))108 316.8 Q F0
+(Incremental undo, separately remembered for each line.)144 328.8 Q F1 -2.29
+-.18(re v)108 340.8 T(ert\255line \(M\255r\)).08 E F0 .244
+(Undo all changes made to this line.)144 352.8 R .245(This is lik)5.245 F 2.745
+(et)-.1 G .245(yping the)341.895 352.8 R F1(undo)2.745 E F0 .245
+(command enough times to return)2.745 F(the line to its initial state.)144
+364.8 Q F1(tilde\255expand \(M\255~\))108 376.8 Q F0(Perform tilde e)144 388.8
+Q(xpansion on the current w)-.15 E(ord.)-.1 E F1(dump\255functions)108 400.8 Q
+F0 .627(Print all of the functions and their k)144 412.8 R .927 -.15(ey b)-.1 H
+.626(indings to the readline output stream.).15 F .626(If a numeric ar)5.626 F
+(gu-)-.18 E(ment is supplied, the output is formatted in such a w)144 424.8 Q
+(ay that it can be made part of an)-.1 E/F3 10/Times-Italic@0 SF(inputr)2.5 E
+(c)-.37 E F0(\214le.)2.5 E F1(display\255shell\255v)108 436.8 Q
+(ersion \(C\255x C\255v\))-.1 E F0(Display v)144 448.8 Q
+(ersion information about the current instance of)-.15 E F1(bash)2.5 E F0(.)A
+F2(HIST)72 465.6 Q(OR)-.162 E(Y)-.315 E F0 .227(When interacti)108 477.6 R -.15
+(ve)-.25 G 2.727(,t).15 G .227(he shell pro)184.424 477.6 R .227
+(vides access to the)-.15 F F3 .227(command history)2.727 F F0 2.727(,t)C .228
+(he list of commands pre)386.34 477.6 R .228(viously typed.)-.25 F .12(The te)
+108 489.6 R .12(xt of the last)-.15 F F2(HISTSIZE)2.62 E F0 .12(commands \(def)
+2.37 F .119(ault 500\) is sa)-.1 F -.15(ve)-.2 G 2.619(di).15 G 2.619(nah)
+367.958 489.6 S .119(istory list.)387.636 489.6 R .119
+(The shell stores each com-)5.119 F .124
+(mand in the history list prior to parameter and v)108 501.6 R .125(ariable e)
+-.25 F .125(xpansion \(see)-.15 F F2(EXP)2.625 E(ANSION)-.666 E F0(abo)2.375 E
+-.15(ve)-.15 G 2.625(\)b).15 G .125(ut after history)480.87 501.6 R -.15(ex)108
+513.6 S .267(pansion is performed, subject to the v).15 F .267
+(alues of the shell v)-.25 F(ariables)-.25 E F1(command_oriented_history)2.767
+E F0(and)2.767 E F2(HIST)2.767 E(-)-.828 E(CONTR)108 525.6 Q(OL)-.27 E/F4 9
+/Times-Roman@0 SF(.)A F0 1.191
+(On startup, the history is initialized from the \214le named by the v)5.69 F
+(ariable)-.25 E F2(HISTFILE)3.691 E F0(\(def)3.441 E(ault)-.1 E F3
+(~/.bash_history)108 537.6 Q F0(\).)A F2(HISTFILE)5.632 E F0 .632
+(is truncated, if necessary)2.882 F 3.131(,t)-.65 G 3.131(oc)333.656 537.6 S
+.631(ontain no more than)346.227 537.6 R F2(HISTFILESIZE)3.131 E F0 3.131
+(lines. The)2.881 F -.2(bu)108 549.6 S .168(iltin command).2 F F1(fc)2.668 E F0
+(\(see)2.668 E F2 .168(SHELL B)2.668 F(UIL)-.09 E .168(TIN COMMANDS)-.828 F F0
+(belo)2.418 E .168(w\) may be used to list or edit and re-e)-.25 F -.15(xe)-.15
+G .168(cute a).15 F .102(portion of the history list.)108 561.6 R(The)5.102 E
+F1(history)2.602 E F0 -.2(bu)2.602 G .101
+(iltin can be used to display the history list and manipulate the his-).2 F
+.464(tory \214le.)108 573.6 R .464
+(When using the command-line editing, search commands are a)5.464 F -.25(va)-.2
+G .464(ilable in each editing mode that).25 F(pro)108 585.6 Q .483
+(vide access to the history list.)-.15 F .483(When an interacti)5.483 F .783
+-.15(ve s)-.25 H .483(hell e).15 F .483(xits, the last)-.15 F F2(HISTSIZE)2.983
+E F0 .482(lines are copied from)2.733 F 1.047(the history list to)108 597.6 R
+F2(HISTFILE)3.547 E F4(.)A F0(If)5.548 E F2(HISTFILE)3.548 E F0 1.048
+(is unset, or if the history \214le is unwritable, the history is not)3.298 F
+(sa)108 609.6 Q -.15(ve)-.2 G(d.).15 E F2(HIST)72 626.4 Q(OR)-.162 E 2.25(YE)
+-.315 G(XP)121.284 626.4 Q(ANSION)-.666 E F0 .611
+(The shell supports a history e)108 638.4 R .611
+(xpansion feature that is similar to the history e)-.15 F .61(xpansion in)-.15
+F F1(csh.)3.11 E F0 .61(This section)5.61 F .87
+(describes what syntax features are a)108 650.4 R -.25(va)-.2 G 3.371
+(ilable. This).25 F .871(feature is enabled by def)3.371 F .871
+(ault for interacti)-.1 F 1.171 -.15(ve s)-.25 H .871(hells, and).15 F 2.014
+(can be disabled using the)108 662.4 R F1(+H)4.514 E F0 2.014(option to the)
+4.514 F F1(set)4.514 E F0 -.2(bu)4.514 G 2.014(iltin command \(see).2 F F2
+2.013(SHELL B)4.513 F(UIL)-.09 E 2.013(TIN COMMANDS)-.828 F F0(belo)108 674.4 Q
+2.5(w\). Non-interacti)-.25 F .3 -.15(ve s)-.25 H
+(hells do not perform history e).15 E(xpansion.)-.15 E 1.163(History e)108
+691.2 R 1.163(xpansion is performed immediately after a complete line is read,\
+ before the shell breaks it into)-.15 F -.1(wo)108 703.2 S 2.585(rds. It).1 F
+(tak)2.585 E .085(es place in tw)-.1 F 2.585(op)-.1 G 2.585(arts. The)228.19
+703.2 R .084(\214rst is to determine which line from the pre)2.585 F .084
+(vious history to use dur)-.25 F(-)-.2 E .915(ing substitution.)108 715.2 R
+.915(The second is to select portions of that line for inclusion into the curr\
+ent one.)5.915 F .915(The line)5.915 F .603(selected from the pre)108 727.2 R
+.603(vious history is the)-.25 F F3 -.15(ev)3.103 G(ent).15 E F0 3.103(,a)C
+.602(nd the portions of that line that are acted upon are)305.444 727.2 R F3
+(wor)3.102 E(ds)-.37 E F0(.)A 185.675(GNU 1995)72 768 R(May 5)2.5 E(23)530 768
+Q EP
+%%Page: 24 24
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+1.748(The line is brok)108 84 R 1.749(en into w)-.1 F 1.749(ords in the same f)
+-.1 F 1.749(ashion as when reading input, so that se)-.1 F -.15(ve)-.25 G(ral)
+.15 E/F1 10/Times-Italic@0 SF(metac)4.249 E(har)-.15 E(ac-)-.15 E(ter)108 96 Q
+F0 1.785(\255separated w)B 1.785
+(ords surrounded by quotes are considered as one w)-.1 F 4.284(ord. Only)-.1 F
+1.784(backslash \()4.284 F/F2 10/Times-Bold@0 SF(\\).833 E F0 4.284(\)a).833 G
+1.784(nd single)501.826 96 R(quotes can quote the history escape character)108
+108 Q 2.5(,w)-.4 G(hich is)300.32 108 Q F2(!)3.333 E F0(by def)3.333 E(ault.)
+-.1 E 2.2(The shell allo)108 124.8 R 2.2(ws control of the v)-.25 F 2.2
+(arious characters used by the history e)-.25 F 2.2
+(xpansion mechanism \(see the)-.15 F(description of)108 136.8 Q F2(histchars)
+2.5 E F0(abo)2.5 E .3 -.15(ve u)-.15 H(nder).15 E F2(Shell V)2.5 E(ariables)
+-.92 E F0(\).)A F2(Ev)87 153.6 Q(ent Designators)-.1 E F0(An e)108 165.6 Q -.15
+(ve)-.25 G
+(nt designator is a reference to a command line entry in the history list.).15
+E F2(!)108 182.4 Q F0(Start a history substitution, e)144 182.4 Q
+(xcept when follo)-.15 E(wed by a)-.25 E F2(blank)2.5 E F0 2.5(,n)C -.25(ew)
+398.6 182.4 S(line, = or \(.).25 E F2(!!)108 194.4 Q F0(Refer to the pre)144
+194.4 Q(vious command.)-.25 E(This is a synon)5 E(ym for `!\2551'.)-.15 E F2(!)
+108 206.4 Q F1(n)A F0(Refer to command line)144 206.4 Q F1(n)2.5 E F0(.).24 E
+F2<21ad>108 218.4 Q F1(n)A F0(Refer to the current command line minus)144 218.4
+Q F1(n)2.5 E F0(.).24 E F2(!)108 230.4 Q F1(string)A F0
+(Refer to the most recent command starting with)9.33 E F1(string)2.5 E F0(.).22
+E F2(!?)108 242.4 Q F1(string)A F2([?])A F0
+(Refer to the most recent command containing)144 254.4 Q F1(string)2.5 E F0(.)
+.22 E/F3 12/Times-Bold@0 SF(^)108 271.4 Q F1(string1)111.996 266.4 Q F3(^)
+140.336 271.4 Q F1(string2)144.332 266.4 Q F3(^)172.672 271.4 Q F0 2.66
+(Quick substitution.)144 278.4 R 2.66(Repeat the last command, replacing)7.66 F
+F1(string1)5.16 E F0(with)5.16 E F1(string2)5.16 E F0 7.66(.E).02 G(qui)490.34
+278.4 Q -.25(va)-.25 G 2.66(lent to).25 F -.74(``)144 290.4 S(!!:s/).74 E F1
+(string1)A F0(/)A F1(string2)A F0(/')A 2.5('\()-.74 G(see)240.02 290.4 Q F2
+(Modi\214ers)2.5 E F0(belo)2.5 E(w\).)-.25 E F2(!#)108 302.4 Q F0
+(The entire command line typed so f)144 302.4 Q(ar)-.1 E(.)-.55 E F2 -.75(Wo)87
+319.2 S(rd Designators).75 E F0(A)108 331.2 Q F2(:)3.654 E F0 1.154
+(separates the e)3.654 F -.15(ve)-.25 G 1.154(nt speci\214cation from the w).15
+F 1.154(ord designator)-.1 F 6.154(.I)-.55 G 3.654(tc)377.32 331.2 S 1.154
+(an be omitted if the w)388.194 331.2 R 1.155(ord designator)-.1 F(be)108 343.2
+Q .539(gins with a)-.15 F F2(^)3.039 E F0(,)A F2($)3.039 E F0(,)A F2(*)3.039 E
+F0 3.039(,o)C(r)200.244 343.2 Q F2(%)3.039 E F0 5.539(.W)C .539
+(ords are numbered from the be)233.292 343.2 R .538
+(ginning of the line, with the \214rst w)-.15 F .538(ord being)-.1 F
+(denoted by a 0 \(zero\).)108 355.2 Q F2 2.5(0\()108 372 S(zer)118.83 372 Q
+(o\))-.18 E F0(The zeroth w)144 384 Q 2.5(ord. F)-.1 F
+(or the shell, this is the command w)-.15 E(ord.)-.1 E F1(n)108 396 Q F0(The)
+144 396 Q F1(n)2.5 E F0(th w)A(ord.)-.1 E F2(^)108 408 Q F0(The \214rst ar)144
+408 Q 2.5(gument. That)-.18 F(is, w)2.5 E(ord 1.)-.1 E F2($)108 420 Q F0
+(The last ar)144 420 Q(gument.)-.18 E F2(%)108 432 Q F0(The w)144 432 Q
+(ord matched by the most recent `?)-.1 E F1(string)A F0(?' search.)A F1(x)108
+444 Q F2<ad>A F1(y)A F0 2.5(Ar)144 444 S(ange of w)157.05 444 Q(ords; `\255)-.1
+E F1(y)A F0 2.5('a)C(bbre)242.56 444 Q(viates `0\255)-.25 E F1(y)A F0('.)A F2
+(*)108 456 Q F0 .315(All of the w)144 456 R .315(ords b)-.1 F .315
+(ut the zeroth.)-.2 F .315(This is a synon)5.315 F .315(ym for `)-.15 F F1
+(1\255$)A F0 2.815('. It)B .315(is not an error to use)2.815 F F2(*)2.816 E F0
+.316(if there is)2.816 F(just one w)144 468 Q(ord in the e)-.1 E -.15(ve)-.25 G
+(nt; the empty string is returned in that case.).15 E F2(x*)108 480 Q F0(Abbre)
+144 480 Q(viates)-.25 E F1(x\255$)2.5 E F0(.)A F2<78ad>108 492 Q F0(Abbre)144
+492 Q(viates)-.25 E F1(x\255$)2.5 E F0(lik)2.5 E(e)-.1 E F2(x*)2.5 E F0 2.5(,b)
+C(ut omits the last w)250.46 492 Q(ord.)-.1 E F2(Modi\214ers)87 508.8 Q F0 .158
+(After the optional w)108 520.8 R .158(ord designator)-.1 F 2.658(,y)-.4 G .158
+(ou can add a sequence of one or more of the follo)256.6 520.8 R .157
+(wing modi\214ers, each)-.25 F(preceded by a `:'.)108 532.8 Q F2(h)108 549.6 Q
+F0(Remo)144 549.6 Q .3 -.15(ve a t)-.15 H(railing pathname component, lea).15 E
+(ving only the head.)-.2 E F2(r)108 561.6 Q F0(Remo)144 561.6 Q .3 -.15(ve a t)
+-.15 H(railing suf).15 E(\214x of the form)-.25 E F1(.xxx)2.5 E F0 2.5(,l)C(ea)
+313.98 561.6 Q(ving the basename.)-.2 E F2(e)108 573.6 Q F0(Remo)144 573.6 Q .3
+-.15(ve a)-.15 H(ll b).15 E(ut the trailing suf)-.2 E(\214x.)-.25 E F2(t)108
+585.6 Q F0(Remo)144 585.6 Q .3 -.15(ve a)-.15 H
+(ll leading pathname components, lea).15 E(ving the tail.)-.2 E F2(p)108 597.6
+Q F0(Print the ne)144 597.6 Q 2.5(wc)-.25 G(ommand b)204.02 597.6 Q
+(ut do not e)-.2 E -.15(xe)-.15 G(cute it.).15 E F2(q)108 609.6 Q F0
+(Quote the substituted w)144 609.6 Q(ords, escaping further substitutions.)-.1
+E F2(x)108 621.6 Q F0(Quote the substituted w)144 621.6 Q(ords as with)-.1 E F2
+(q)2.5 E F0 2.5(,b)C(ut break into w)304.81 621.6 Q(ords at)-.1 E F2(blanks)2.5
+E F0(and ne)2.5 E(wlines.)-.25 E F2(s/)108 633.6 Q F1(old)A F2(/)A F1(ne)A(w)
+-.15 E F2(/)A F0(Substitute)144 645.6 Q F1(ne)2.813 E(w)-.15 E F0 .314
+(for the \214rst occurrence of)2.813 F F1(old)2.814 E F0 .314(in the e)2.814 F
+-.15(ve)-.25 G .314(nt line.).15 F(An)5.314 E 2.814(yd)-.15 G .314
+(elimiter can be used in place)424.29 645.6 R .617(of /.)144 657.6 R .617
+(The \214nal delimiter is optional if it is the last character of the e)5.617 F
+-.15(ve)-.25 G .617(nt line.).15 F .616(The delimiter may)5.616 F .749
+(be quoted in)144 669.6 R F1(old)3.249 E F0(and)3.249 E F1(ne)3.249 E(w)-.15 E
+F0 .749(with a single backslash.)3.249 F .75(If & appears in)5.749 F F1(ne)3.25
+E(w)-.15 E F0 3.25(,i).31 G 3.25(ti)444.66 669.6 S 3.25(sr)453.47 669.6 S .75
+(eplaced by)463.94 669.6 R F1(old)3.25 E F0 5.75(.A).77 G
+(single backslash will quote the &.)144 681.6 Q F2(&)108 693.6 Q F0
+(Repeat the pre)144 693.6 Q(vious substitution.)-.25 E F2(g)108 705.6 Q F0 .398
+(Cause changes to be applied o)144 705.6 R -.15(ve)-.15 G 2.898(rt).15 G .398
+(he entire e)284.948 705.6 R -.15(ve)-.25 G .398(nt line.).15 F .397
+(This is used in conjunction with `)5.398 F F2(:s)A F0 2.897('\()C(e.g.,)523.06
+705.6 Q(`)144 717.6 Q F2(:gs/)A F1(old)A F2(/)A F1(ne)A(w)-.15 E F2(/)A F0
+1.218('\) or `)B F2(:&)A F0 3.718('. If)B 1.218(used with `)3.718 F F2(:s)A F0
+1.218(', an)B 3.718(yd)-.15 G 1.219
+(elimiter can be used in place of /, and the \214nal)343.124 717.6 R
+(delimiter is optional if it is the last character of the e)144 729.6 Q -.15
+(ve)-.25 G(nt line.).15 E 185.675(GNU 1995)72 768 R(May 5)2.5 E(24)530 768 Q EP
+%%Page: 25 25
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 9/Times-Bold@0 SF(ARITHMETIC EV)72 84 Q(ALU)-1.215 E -.855(AT)-.54 G(ION)
+.855 E F0 1.478(The shell allo)108 96 R 1.477(ws arithmetic e)-.25 F 1.477
+(xpressions to be e)-.15 F -.25(va)-.25 G 1.477
+(luated, under certain circumstances \(see the).25 F/F2 10/Times-Bold@0 SF(let)
+3.977 E F0 -.2(bu)3.977 G(iltin).2 E 1.232(command and)108 108 R F2 1.232
+(Arithmetic Expansion)3.732 F F0 3.732(\). Ev)B 1.232
+(aluation is done in long inte)-.25 F 1.232(gers with no check for o)-.15 F
+-.15(ve)-.15 G(r\215o).15 E -.65(w,)-.25 G .279(though di)108 120 R .279
+(vision by 0 is trapped and \215agged as an error)-.25 F 5.278(.T)-.55 G .278
+(he follo)341.626 120 R .278(wing list of operators is grouped into le)-.25 F
+(v-)-.25 E(els of equal-precedence operators.)108 132 Q(The le)5 E -.15(ve)-.25
+G(ls are listed in order of decreasing precedence.).15 E F2 2.5<ad2b>108 148.8
+S F0(unary minus and plus)144 148.8 Q F2 2.5(!~)108 160.8 S F0
+(logical and bitwise ne)144 160.8 Q -.05(ga)-.15 G(tion).05 E F2 2.5(*/%)108
+172.8 S F0(multiplication, di)144 172.8 Q(vision, remainder)-.25 E F2 2.5<2bad>
+108 184.8 S F0(addition, subtraction)144 184.8 Q F2(<< >>)108 196.8 Q F0
+(left and right bitwise shifts)144 196.8 Q F2(<= >= < >)108 208.8 Q F0
+(comparison)144 220.8 Q F2(== !=)108 232.8 Q F0(equality and inequality)144
+232.8 Q F2(&)108 244.8 Q F0(bitwise AND)144 244.8 Q F2(^)108 256.8 Q F0
+(bitwise e)144 256.8 Q(xclusi)-.15 E .3 -.15(ve O)-.25 H(R).15 E F2(|)108 268.8
+Q F0(bitwise OR)144 268.8 Q F2(&&)108 280.8 Q F0(logical AND)144 280.8 Q F2(||)
+108 292.8 Q F0(logical OR)144 292.8 Q F2 2.5(=*)108 304.8 S 2.5(=/)121.2 304.8
+S 2.5(=%)132.18 304.8 S 2.5(=+)150.38 304.8 S 2.5<3dad>164.28 304.8 S 2.5(=<)
+178.18 304.8 S(<= >>= &= ^= |=)192.08 304.8 Q F0(assignment)144 316.8 Q .68
+(Shell v)108 333.6 R .68(ariables are allo)-.25 F .68
+(wed as operands; parameter e)-.25 F .68(xpansion is performed before the e)
+-.15 F .68(xpression is e)-.15 F -.25(va)-.25 G(lu-).25 E 2.785(ated. The)108
+345.6 R -.25(va)2.785 G .284(lue of a parameter is coerced to a long inte).25 F
+.284(ger within an e)-.15 F 2.784(xpression. A)-.15 F .284(shell v)2.784 F .284
+(ariable need not)-.25 F(ha)108 357.6 Q .3 -.15(ve i)-.2 H(ts inte).15 E
+(ger attrib)-.15 E(ute turned on to be used in an e)-.2 E(xpression.)-.15 E
+.049(Constants with a leading 0 are interpreted as octal numbers.)108 374.4 R
+2.55(Al)5.049 G(eading)364.89 374.4 Q/F3 10/Times-Italic@0 SF(0x)2.55 E F0(or)
+2.55 E F3(0X)2.55 E F0 .05(denotes he)2.55 F 2.55(xadecimal. Oth-)-.15 F .016
+(erwise, numbers tak)108 386.4 R 2.516(et)-.1 G .016(he form [)197.928 386.4 R
+F3(base#)A F0 .015(]n, where)B F3(base)2.515 E F0 .015
+(is a decimal number between 2 and 36 representing the)2.515 F
+(arithmetic base, and)108 398.4 Q F3(n)2.5 E F0(is a number in that base.)2.5 E
+(If)5 E F3(base)2.5 E F0(is omitted, then base 10 is used.)2.5 E .234
+(Operators are e)108 415.2 R -.25(va)-.25 G .234
+(luated in order of precedence.).25 F(Sub-e)5.234 E .234
+(xpressions in parentheses are e)-.15 F -.25(va)-.25 G .235
+(luated \214rst and may).25 F -.15(ove)108 427.2 S
+(rride the precedence rules abo).15 E -.15(ve)-.15 G(.).15 E F1(SHELL B)72 444
+Q(UIL)-.09 E(TIN COMMANDS)-.828 E F2(:)108 456 Q F0([)2.5 E F3(ar)A(guments)
+-.37 E F0(])A .502(No ef)144 468 R .502(fect; the command does nothing be)-.25
+F .502(yond e)-.15 F(xpanding)-.15 E F3(ar)3.002 E(guments)-.37 E F0 .501
+(and performing an)3.001 F 3.001(ys)-.15 G(peci\214ed)508.34 468 Q 2.5
+(redirections. A)144 480 R(zero e)2.5 E(xit code is returned.)-.15 E F2(.)110.5
+496.8 Q F3(\214lename)6.666 E F0([)2.5 E F3(ar)A(guments)-.37 E F0(])A F2(sour)
+108 508.8 Q(ce)-.18 E F3(\214lename)2.5 E F0([)2.5 E F3(ar)A(guments)-.37 E F0
+(])A 1.169(Read and e)144 520.8 R -.15(xe)-.15 G 1.169(cute commands from).15 F
+F3(\214lename)3.669 E F0 1.169(in the current shell en)3.669 F 1.17
+(vironment and return the e)-.4 F(xit)-.15 E 1.302
+(status of the last command e)144 532.8 R -.15(xe)-.15 G 1.301(cuted from).15 F
+F3(\214lename)3.801 E F0 6.301(.I).18 G(f)368.143 532.8 Q F3(\214lename)3.801 E
+F0 1.301(does not contain a slash, path-)3.801 F .608(names in)144 544.8 R F1
+-.666(PA)3.108 G(TH)-.189 E F0 .608
+(are used to \214nd the directory containing)2.858 F F3(\214lename)3.108 E F0
+5.608(.T).18 G .608(he \214le searched for in)424.339 544.8 R F1 -.666(PA)3.108
+G(TH)-.189 E F0 .201(need not be e)144 556.8 R -.15(xe)-.15 G 2.701
+(cutable. The).15 F .201
+(current directory is searched if no \214le is found in)2.701 F F1 -.666(PA)
+2.701 G(TH)-.189 E/F4 9/Times-Roman@0 SF(.)A F0 .201(If an)4.701 F(y)-.15 E F3
+(ar)2.701 E(gu-)-.37 E(ments)144 568.8 Q F0 1.057(are supplied, the)3.557 F
+3.557(yb)-.15 G 1.058(ecome the positional parameters when)252.228 568.8 R F3
+(\214le)3.558 E F0 1.058(is e)3.558 F -.15(xe)-.15 G 3.558(cuted. Otherwise).15
+F(the)3.558 E 1.079(positional parameters are unchanged.)144 580.8 R 1.078
+(The return status is the status of the last command e)6.079 F(xited)-.15 E
+(within the script \(0 if no commands are e)144 592.8 Q -.15(xe)-.15 G
+(cuted\), and f).15 E(alse if)-.1 E F3(\214lename)2.5 E F0(is not found.)2.5 E
+F2(alias)108 609.6 Q F0([)2.5 E F3(name)A F0([=)A F3(value)A F0 2.5(].)C(..])
+193.9 609.6 Q F2(Alias)144 621.6 Q F0 1.667(with no ar)4.167 F 1.667
+(guments prints the list of aliases in the form)-.18 F F3(name)4.168 E F0(=)A
+F3(value)A F0 1.668(on standard output.)4.168 F .607(When ar)144 633.6 R .607
+(guments are supplied, an alias is de\214ned for each)-.18 F F3(name)3.107 E F0
+(whose)3.107 E F3(value)3.107 E F0 .607(is gi)3.107 F -.15(ve)-.25 G 3.106
+(n. A).15 F(trailing)3.106 E 2.692(space in)144 645.6 R F3(value)5.192 E F0
+2.692(causes the ne)5.192 F 2.692(xt w)-.15 F 2.692(ord to be check)-.1 F 2.693
+(ed for alias substitution when the alias is)-.1 F -.15(ex)144 657.6 S 2.868
+(panded. F).15 F .367(or each)-.15 F F3(name)2.867 E F0 .367(in the ar)2.867 F
+.367(gument list for which no)-.18 F F3(value)2.867 E F0 .367
+(is supplied, the name and v)2.867 F(alue)-.25 E 1.716
+(of the alias is printed.)144 669.6 R F2(Alias)6.716 E F0 1.717
+(returns true unless a)4.216 F F3(name)4.217 E F0 1.717(is gi)4.217 F -.15(ve)
+-.25 G 4.217(nf).15 G 1.717(or which no alias has been)425.605 669.6 R
+(de\214ned.)144 681.6 Q F2(bg)108 698.4 Q F0([)2.5 E F3(jobspec)A F0(])A(Place)
+144 710.4 Q F3(jobspec)3.485 E F0 .985
+(in the background, as if it had been started with)3.485 F F2(&)3.485 E F0
+5.985(.I)C(f)425.645 710.4 Q F3(jobspec)3.485 E F0 .985(is not present, the)
+3.485 F(shell')144 722.4 Q 4.166(sn)-.55 G 1.666(otion of the)178.726 722.4 R
+F3(curr)4.166 E 1.666(ent job)-.37 F F0 1.666(is used.)4.166 F F2(bg)6.666 E F3
+(jobspec)4.166 E F0 1.667(returns 0 unless run when job control is)4.167 F
+185.675(GNU 1995)72 768 R(May 5)2.5 E(25)530 768 Q EP
+%%Page: 26 26
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+1.139(disabled or)144 84 R 3.639(,w)-.4 G 1.138
+(hen run with job control enabled, if)202.258 84 R/F1 10/Times-Italic@0 SF
+(jobspec)3.638 E F0 -.1(wa)3.638 G 3.638(sn).1 G 1.138
+(ot found or started without job)412.37 84 R(control.)144 96 Q/F2 10
+/Times-Bold@0 SF(bind)108 112.8 Q F0([)2.5 E F2<ad6d>A F1 -.1(ke)2.5 G(ymap)-.2
+E F0 2.5(][)C F2(\255lvd)189.12 112.8 Q F0 2.5(][)C F2(-q)217.32 112.8 Q F1
+(name)2.5 E F0(])A F2(bind)108 124.8 Q F0([)2.5 E F2<ad6d>A F1 -.1(ke)2.5 G
+(ymap)-.2 E F0(])A F2(-f)2.5 E F1(\214lename)2.5 E F2(bind)108 136.8 Q F0([)2.5
+E F2<ad6d>A F1 -.1(ke)2.5 G(ymap)-.2 E F0(])A F1 -.1(ke)2.5 G(yseq)-.2 E F0(:)A
+F1(function-name)A F0 .238(Display current)144 148.8 R F2 -.18(re)2.738 G
+(adline).18 E F0 -.1(ke)2.738 G 2.738(ya)-.05 G .239
+(nd function bindings, or bind a k)267.832 148.8 R .539 -.15(ey s)-.1 H .239
+(equence to a).15 F F2 -.18(re)2.739 G(adline).18 E F0(function)2.739 E .88
+(or macro.)144 160.8 R .88(The binding syntax accepted is identical to that of)
+5.88 F F1(.inputr)3.38 E(c)-.37 E F0 3.38(,b).31 G .88(ut each binding must be)
+440.93 160.8 R .38(passed as a separate ar)144 172.8 R .381
+(gument; e.g., '"\\C-x\\C-r": re\255read\255init\255\214le'.)-.18 F .381
+(Options, if supplied, ha)5.381 F .681 -.15(ve t)-.2 H(he).15 E(follo)144 184.8
+Q(wing meanings:)-.25 E F2<ad6d>144 196.8 Q F1 -.1(ke)2.5 G(ymap)-.2 E F0(Use)
+180 208.8 Q F1 -.1(ke)5.175 G(ymap)-.2 E F0 2.674(as the k)5.175 F -.15(ey)-.1
+G 2.674(map to be af).15 F 2.674(fected by the subsequent bindings.)-.25 F
+(Acceptable)7.674 E F1 -.1(ke)180 220.8 S(ymap)-.2 E F0 2.929(names are)5.428 F
+F1 2.929(emacs, emacs-standar)5.429 F 2.929
+(d, emacs-meta, emacs-ctlx, vi, vi-mo)-.37 F(ve)-.1 E 5.429(,v)-.1 G(i-)533.89
+220.8 Q(command)180 232.8 Q F0 3.435(,a)C(nd)229.255 232.8 Q F1(vi-insert)3.435
+E F0(.).68 E F1(vi)5.934 E F0 .934(is equi)3.434 F -.25(va)-.25 G .934(lent to)
+.25 F F1(vi-command)3.434 E F0(;)A F1(emacs)3.434 E F0 .934(is equi)3.434 F
+-.25(va)-.25 G .934(lent to).25 F F1(emacs-)3.434 E(standar)180 244.8 Q(d)-.37
+E F0(.)A F2<ad6c>144 256.8 Q F0(List the names of all)180 256.8 Q F2 -.18(re)
+2.5 G(adline).18 E F0(functions)2.5 E F2<ad76>144 268.8 Q F0
+(List current function names and bindings)180 268.8 Q F2<ad64>144 280.8 Q F0
+(Dump function names and bindings in such a w)180 280.8 Q(ay that the)-.1 E 2.5
+(yc)-.15 G(an be re-read)423.89 280.8 Q F2<ad66>144 292.8 Q F1(\214lename)2.5 E
+F0(Read k)180 304.8 Q .3 -.15(ey b)-.1 H(indings from).15 E F1(\214lename)2.5 E
+F2<ad71>144 316.8 Q F1(function)2.5 E F0(Query about which k)180 328.8 Q -.15
+(ey)-.1 G 2.5(si).15 G -1.9 -.4(nv o)282.51 328.8 T .2 -.1(ke t).4 H(he named)
+.1 E F1(function)2.5 E F0(The return v)144 345.6 Q
+(alue is 0 unless an unrecognized option is gi)-.25 E -.15(ve)-.25 G 2.5(no).15
+G 2.5(ra)391.37 345.6 S 2.5(ne)401.64 345.6 S(rror occurred.)413.58 345.6 Q F2
+(br)108 362.4 Q(eak)-.18 E F0([)2.5 E F1(n)A F0(])A .075(Exit from within a)144
+374.4 R F2 -.25(fo)2.575 G(r).25 E F0(,)A F2(while)2.575 E F0 2.575(,o)C(r)
+270.86 374.4 Q F2(until)2.575 E F0 2.576(loop. If)2.575 F F1(n)2.576 E F0 .076
+(is speci\214ed, break)2.576 F F1(n)2.576 E F0(le)2.576 E -.15(ve)-.25 G(ls.)
+.15 E F1(n)5.076 E F0 .076(must be)2.576 F/F3 10/Symbol SF<b3>2.576 E F0 2.576
+(1. If)2.576 F F1(n)2.576 E F0(is)2.576 E .838
+(greater than the number of enclosing loops, all enclosing loops are e)144
+386.4 R 3.338(xited. The)-.15 F .838(return v)3.338 F .838(alue is 0)-.25 F
+(unless the shell is not e)144 398.4 Q -.15(xe)-.15 G(cuting a loop when).15 E
+F2(br)2.5 E(eak)-.18 E F0(is e)2.5 E -.15(xe)-.15 G(cuted.).15 E F2 -.2(bu)108
+415.2 S(iltin).2 E F1(shell\255b)2.5 E(uiltin)-.2 E F0([)2.5 E F1(ar)A(guments)
+-.37 E F0(])A(Ex)144 427.2 Q .792(ecute the speci\214ed shell b)-.15 F .792
+(uiltin, passing it)-.2 F F1(ar)3.293 E(guments)-.37 E F0 3.293(,a).27 G .793
+(nd return its e)382.099 427.2 R .793(xit status.)-.15 F .793(This is useful)
+5.793 F .603
+(when you wish to de\214ne a function whose name is the same as a shell b)144
+439.2 R .602(uiltin, b)-.2 F .602(ut need the func-)-.2 F .772
+(tionality of the b)144 451.2 R .772(uiltin within the function itself.)-.2 F
+(The)5.773 E F2(cd)3.273 E F0 -.2(bu)3.273 G .773
+(iltin is commonly rede\214ned this w).2 F(ay)-.1 E(.)-.65 E
+(The return status is f)144 463.2 Q(alse if)-.1 E F1(shell\255b)2.5 E(uiltin)
+-.2 E F0(is not a shell b)2.5 E(uiltin command.)-.2 E F2(cd)108 480 Q F0([)2.5
+E F1(dir)A F0 5.17(]C)C .21(hange the current directory to)150.67 480 R F1(dir)
+2.71 E F0 5.21(.T)C .21(he v)298.01 480 R(ariable)-.25 E/F4 9/Times-Bold@0 SF
+(HOME)2.71 E F0 .21(is the def)2.46 F(ault)-.1 E F1(dir)2.71 E F0 5.21(.T).73 G
+.21(he v)456.703 480 R(ariable)-.25 E F4(CDP)2.71 E -.855(AT)-.666 G(H).855 E
+F0 .337(de\214nes the search path for the directory containing)144 492 R F1
+(dir)2.837 E F0 5.337(.A).73 G(lternati)379.662 492 Q .637 -.15(ve d)-.25 H
+.337(irectory names are separated).15 F .31(by a colon \(:\).)144 504 R 2.809
+(An)5.309 G .309(ull directory name in)221.367 504 R F4(CDP)2.809 E -.855(AT)
+-.666 G(H).855 E F0 .309(is the same as the current directory)2.559 F 2.809(,i)
+-.65 G .309(.e., `)496.442 504 R(`)-.74 E F2(.)A F0 -.74('')C 5.309(.I).74 G(f)
+536.67 504 Q F1(dir)144 516 Q F0(be)3.418 E .918(gins with a slash \(/\), then)
+-.15 F F4(CDP)3.418 E -.855(AT)-.666 G(H).855 E F0 .918(is not used.)3.168 F
+.919(An ar)5.919 F .919(gument of)-.18 F F2<ad>3.419 E F0 .919(is equi)3.419 F
+-.25(va)-.25 G .919(lent to).25 F F4($OLD-)3.419 E(PWD)144 528 Q/F5 9
+/Times-Roman@0 SF(.)A F0(The return v)4.5 E(alue is true if the directory w)
+-.25 E(as successfully changed; f)-.1 E(alse otherwise.)-.1 E F2(command)108
+544.8 Q F0([)2.5 E F2(-pVv)A F0(])A F1(command)2.5 E F0([)2.5 E F1(ar)A(g)-.37
+E F0(...])2.5 E(Run)144 556.8 Q F1(command)2.878 E F0(with)2.878 E F1(ar)2.878
+E(gs)-.37 E F0 .378(suppressing the normal shell function lookup. Only b)2.878
+F .377(uiltin commands or)-.2 F .558(commands found in the)144 568.8 R F4 -.666
+(PA)3.058 G(TH)-.189 E F0 .559(are e)2.809 F -.15(xe)-.15 G 3.059(cuted. If).15
+F(the)3.059 E F2<ad70>3.059 E F0 .559(option is gi)3.059 F -.15(ve)-.25 G .559
+(n, the search for).15 F F1(command)3.059 E F0(is)3.059 E .232
+(performed using a def)144 580.8 R .231(ault v)-.1 F .231(alue for)-.25 F F2
+-.74(PA)2.731 G(TH)-.21 E F0 .231
+(that is guaranteed to \214nd all of the standard utilities.)2.731 F(If)5.231 E
+.231(either the)144 592.8 R F2<ad56>2.731 E F0(or)2.731 E F2<ad76>2.731 E F0
+.232(option is supplied, a description of)2.732 F F1(command)2.732 E F0 .232
+(is printed.)2.732 F(The)5.232 E F2<ad76>2.732 E F0 .232(option causes)2.732 F
+2.711(as)144 604.8 S .211(ingle w)155.041 604.8 R .211
+(ord indicating the command or pathname used to in)-.1 F -.2(vo)-.4 G -.1(ke).2
+G F1(command)2.81 E F0 .21(to be printed; the)2.71 F F2<ad56>2.71 E F0 .475
+(option produces a more v)144 616.8 R .476(erbose description.)-.15 F .476
+(An ar)5.476 F .476(gument of)-.18 F F2<adad>2.976 E F0 .476
+(disables option checking for the)2.976 F 1.349(rest of the ar)144 628.8 R
+3.849(guments. If)-.18 F(the)3.849 E F2<ad56>3.849 E F0(or)3.849 E F2<ad76>
+3.849 E F0 1.348(option is supplied, the e)3.848 F 1.348(xit status is 0 if)
+-.15 F F1(command)3.848 E F0 -.1(wa)3.848 G(s).1 E 1.305(found, and 1 if not.)
+144 640.8 R 1.305(If neither option is supplied and an error occurred or)6.305
+F F1(command)3.806 E F0 1.306(cannot be)3.806 F .093(found, the e)144 652.8 R
+.093(xit status is 127.)-.15 F .092(Otherwise, the e)5.092 F .092
+(xit status of the)-.15 F F2(command)2.592 E F0 -.2(bu)2.592 G .092
+(iltin is the e).2 F .092(xit status of)-.15 F F1(command)144 664.8 Q F0(.).77
+E F2(continue)108 681.6 Q F0([)2.5 E F1(n)A F0(])A .064(Resume the ne)144 693.6
+R .064(xt iteration of the enclosing)-.15 F F2 -.25(fo)2.564 G(r).25 E F0(,)A
+F2(while)2.564 E F0 2.564(,o)C(r)366.096 693.6 Q F2(until)2.564 E F0 2.565
+(loop. If)2.565 F F1(n)2.565 E F0 .065(is speci\214ed, resume at the)2.565 F F1
+(n)144 705.6 Q F0 1.169(th enclosing loop.)B F1(n)6.169 E F0 1.169(must be)
+3.669 F F3<b3>3.669 E F0 3.669(1. If)3.669 F F1(n)3.669 E F0 1.169
+(is greater than the number of enclosing loops, the last)3.669 F 1.593
+(enclosing loop \(the `top\255le)144 717.6 R -.15(ve)-.25 G 1.593
+(l' loop\) is resumed.).15 F 1.593(The return v)6.593 F 1.593
+(alue is 0 unless the shell is not)-.25 F -.15(exe)144 729.6 S
+(cuting a loop when).15 E F2(continue)2.5 E F0(is e)2.5 E -.15(xe)-.15 G
+(cuted.).15 E 185.675(GNU 1995)72 768 R(May 5)2.5 E(26)530 768 Q EP
+%%Page: 27 27
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF(declar)108 84 Q(e)-.18 E F0([)2.5 E F1(\255frxi)A F0 2.5
+(][)C/F2 10/Times-Italic@0 SF(name)175.16 84 Q F0([=)A F2(value)A F0(]])A F1
+(typeset)108 96 Q F0([)2.5 E F1(\255frxi)A F0 2.5(][)C F2(name)174.23 96 Q F0
+([=)A F2(value)A F0(]])A 1.098(Declare v)144 108 R 1.098(ariables and/or gi)
+-.25 F 1.398 -.15(ve t)-.25 H 1.098(hem attrib).15 F 3.598(utes. If)-.2 F(no)
+3.598 E F2(name)3.598 E F0 3.598(sa)C 1.098(re gi)394.362 108 R -.15(ve)-.25 G
+1.098(n, then display the v).15 F 1.098(alues of)-.25 F -.25(va)144 120 S 2.491
+(riables instead.).25 F 2.491(The options can be used to restrict output to v)
+7.491 F 2.492(ariables with the speci\214ed)-.25 F(attrib)144 132 Q(ute.)-.2 E
+F1<ad66>144 144 Q F0(Use function names only)180 144 Q F1<ad72>144 156 Q F0
+(Mak)180 156 Q(e)-.1 E F2(name)5.047 E F0 5.047(sr)C(eadonly)241.644 156 Q
+7.547(.T)-.65 G 2.546(hese names cannot then be assigned v)288.811 156 R 2.546
+(alues by subsequent)-.25 F(assignment statements.)180 168 Q F1<ad78>144 180 Q
+F0(Mark)180 180 Q F2(name)2.5 E F0 2.5(sf)C(or e)235.54 180 Q
+(xport to subsequent commands via the en)-.15 E(vironment.)-.4 E F1<ad69>144
+192 Q F0 .557(The v)180 192 R .558(ariable is treated as an inte)-.25 F .558
+(ger; arithmetic e)-.15 F -.25(va)-.25 G .558(luation \(see).25 F/F3 9
+/Times-Bold@0 SF .558(ARITHMETIC EV)3.058 F(ALU)-1.215 E(A-)-.54 E(TION \))180
+204 Q F0(is performed when the v)2.25 E(ariable is assigned a v)-.25 E(alue.)
+-.25 E 1.219(Using `+' instead of `\255' turns of)144 220.8 R 3.719(ft)-.25 G
+1.219(he attrib)289.373 220.8 R 1.219(ute instead.)-.2 F 1.218
+(When used in a function, mak)6.219 F(es)-.1 E F2(name)3.718 E F0(s)A .235
+(local, as with the)144 232.8 R F1(local)2.735 E F0 2.735(command. The)2.735 F
+.235(return v)2.735 F .235(alue is 0 unless an ille)-.25 F -.05(ga)-.15 G 2.736
+(lo).05 G .236(ption is encountered, an)443.752 232.8 R .435
+(attempt is made to de\214ne a function using "-f foo=bar", one of the)144
+244.8 R F2(names)2.935 E F0 .434(is not a le)2.935 F -.05(ga)-.15 G 2.934(ls)
+.05 G .434(hell v)503.436 244.8 R(ari-)-.25 E .519
+(able name, an attempt is made to turn of)144 256.8 R 3.019(fr)-.25 G .52
+(eadonly status for a readonly v)318.391 256.8 R .52(ariable, or an attempt is)
+-.25 F(made to display a non-e)144 268.8 Q(xistant function with -f.)-.15 E F1
+(dirs [-l] [+/\255n])108 285.6 Q F0 1.505
+(Display the list of currently remembered directories.)144 297.6 R 1.505
+(Directories are added to the list with the)6.505 F F1(pushd)144 309.6 Q F0
+(command; the)2.5 E F1(popd)2.5 E F0(command mo)2.5 E -.15(ve)-.15 G 2.5(sb).15
+G(ack up through the list.)331.5 309.6 Q F1(+n)144 321.6 Q F0 .13(displays the)
+180 321.6 R F2(n)2.63 E F0 .13(th entry counting from the left of the list sho)
+B .13(wn by)-.25 F F1(dirs)2.63 E F0 .13(when in)2.63 F -.2(vo)-.4 G -.1(ke).2
+G 2.63(dw).1 G(ith-)526.11 321.6 Q(out options, starting with zero.)180 333.6 Q
+F1<ad6e>144 345.6 Q F0 1.342(displays the)180 345.6 R F2(n)3.842 E F0 1.342
+(th entry counting from the right of the list sho)B 1.342(wn by)-.25 F F1(dirs)
+3.842 E F0 1.342(when in)3.842 F -.2(vo)-.4 G -.1(ke).2 G(d).1 E
+(without options, starting with zero.)180 357.6 Q F1<ad6c>144 369.6 Q F0 .361
+(produces a longer listing; the def)180 369.6 R .361
+(ault listing format uses a tilde to denote the home direc-)-.1 F(tory)180
+381.6 Q(.)-.65 E .381(The return v)144 398.4 R .381(alue is 0 unless an ille)
+-.25 F -.05(ga)-.15 G 2.881(lo).05 G .381(ption is supplied or)303.798 398.4 R
+F2(n)2.88 E F0(inde)2.88 E -.15(xe)-.15 G 2.88(sb).15 G -.15(ey)430.78 398.4 S
+.38(ond the end of the direc-).15 F(tory stack.)144 410.4 Q F1(echo)108 427.2 Q
+F0([)2.5 E F1(\255neE)A F0 2.5(][)C F2(ar)164.8 427.2 Q(g)-.37 E F0(...])2.5 E
+.266(Output the)144 439.2 R F2(ar)2.766 E(g)-.37 E F0 .266
+(s, separated by spaces.)B .266(The return status is al)5.266 F -.1(wa)-.1 G
+.267(ys 0.).1 F(If)5.267 E F1<ad6e>2.767 E F0 .267
+(is speci\214ed, the trailing)2.767 F(ne)144 451.2 Q .311(wline is suppressed.)
+-.25 F .311(If the)5.311 F F1<ad65>2.811 E F0 .311(option is gi)2.811 F -.15
+(ve)-.25 G .311(n, interpretation of the follo).15 F .31
+(wing backslash-escaped)-.25 F .873(characters is enabled.)144 463.2 R(The)
+5.874 E F1<ad45>3.374 E F0 .874
+(option disables the interpretation of these escape characters, e)3.374 F -.15
+(ve)-.25 G(n).15 E(on systems where the)144 475.2 Q 2.5(ya)-.15 G
+(re interpreted by def)241.61 475.2 Q(ault.)-.1 E F1(\\a)144 487.2 Q F0
+(alert \(bell\))180 487.2 Q F1(\\b)144 499.2 Q F0(backspace)180 499.2 Q F1(\\c)
+144 511.2 Q F0(suppress trailing ne)180 511.2 Q(wline)-.25 E F1(\\f)144 523.2 Q
+F0(form feed)180 523.2 Q F1(\\n)144 535.2 Q F0(ne)180 535.2 Q 2.5(wl)-.25 G
+(ine)201.69 535.2 Q F1(\\r)144 547.2 Q F0(carriage return)180 547.2 Q F1(\\t)
+144 559.2 Q F0(horizontal tab)180 559.2 Q F1(\\v)144 571.2 Q F0 -.15(ve)180
+571.2 S(rtical tab).15 E F1(\\\\)144 583.2 Q F0(backslash)180 583.2 Q F1(\\nnn)
+144 595.2 Q F0(the character whose ASCII code is)180 595.2 Q F2(nnn)2.5 E F0
+(\(octal\))2.5 E F1(enable)108 612 Q F0([)2.5 E F1<ad6e>A F0 2.5(][)C F1
+(\255all)162.03 612 Q F0 2.5(][)C F2(name)187.45 612 Q F0(...])2.5 E .683
+(Enable and disable b)144 624 R .683(uiltin shell commands.)-.2 F .683
+(This allo)5.683 F .683(ws the e)-.25 F -.15(xe)-.15 G .683
+(cution of a disk command which).15 F .324(has the same name as a shell b)144
+636 R .324(uiltin without specifying a full pathname.)-.2 F(If)5.324 E F1<ad6e>
+2.824 E F0 .324(is used, each)2.824 F F2(name)2.824 E F0 .181
+(is disabled; otherwise,)144 648 R F2(names)2.681 E F0 .181(are enabled.)2.681
+F -.15(Fo)5.181 G 2.681(re).15 G .181(xample, to use the)338.817 648 R F1(test)
+2.68 E F0 .18(binary found via the)2.68 F F3 -.666(PA)2.68 G(TH)-.189 E F0 .748
+(instead of the shell b)144 660 R .748(uiltin v)-.2 F .748(ersion, type `)-.15
+F .748(`enable -n test')-.74 F 3.248('. If)-.74 F .748(no ar)3.248 F .749
+(guments are gi)-.18 F -.15(ve)-.25 G .749(n, a list of all).15 F .425
+(enabled shell b)144 672 R .425(uiltins is printed.)-.2 F .425(If only)5.425 F
+F1<ad6e>2.925 E F0 .424(is supplied, a list of all disabled b)2.925 F .424
+(uiltins is printed.)-.2 F(If)5.424 E(only)144 684 Q F1(\255all)2.546 E F0 .046
+(is supplied, the list printed includes all b)2.546 F .047
+(uiltins, with an indication of whether or not each)-.2 F .281(is enabled.)144
+696 R F1(enable)5.281 E F0(accepts)2.781 E F1<ad61>2.781 E F0 .281(as a synon)
+2.781 F .281(ym for)-.15 F F1(\255all)2.781 E F0 5.281(.T)C .28(he return v)
+370.81 696 R .28(alue is 0 unless a)-.25 F F2(name)2.78 E F0 .28(is not a)2.78
+F(shell b)144 708 Q(uiltin.)-.2 E 185.675(GNU 1995)72 768 R(May 5)2.5 E(27)530
+768 Q EP
+%%Page: 28 28
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF -2.3 -.15(ev a)108 84 T(l).15 E F0([)2.5 E/F2 10
+/Times-Italic@0 SF(ar)A(g)-.37 E F0(...])2.5 E(The)144 96 Q F2(ar)3.17 E(g)-.37
+E F0 3.17(sa)C .671(re read and concatenated together into a single command.)
+187.74 96 R .671(This command is then read)5.671 F .165(and e)144 108 R -.15
+(xe)-.15 G .165(cuted by the shell, and its e).15 F .165
+(xit status is returned as the v)-.15 F .165(alue of the)-.25 F F1 -2.3 -.15
+(ev a)2.664 H(l).15 E F0 2.664(command. If)2.664 F(there)2.664 E(are no)144 120
+Q F2(ar)2.5 E(gs)-.37 E F0 2.5(,o).27 G 2.5(ro)198.89 120 S(nly null ar)209.72
+120 Q(guments,)-.18 E F1 -2.3 -.15(ev a)2.5 H(l).15 E F0(returns true.)2.5 E F1
+(exec)108 136.8 Q F0([[)2.5 E F1<ad>A F0(])A F2(command)2.5 E F0([)2.5 E F2(ar)
+A(guments)-.37 E F0(]])A(If)144 148.8 Q F2(command)2.91 E F0 .41
+(is speci\214ed, it replaces the shell.)2.91 F .41(No ne)5.41 F 2.91(wp)-.25 G
+.41(rocess is created.)371.42 148.8 R(The)5.41 E F2(ar)2.91 E(guments)-.37 E F0
+(become)2.91 E 1.239(the ar)144 160.8 R 1.239(guments to)-.18 F F2(command)
+3.739 E F0 6.239(.I)C 3.739(ft)267.646 160.8 S 1.239(he \214rst ar)277.495
+160.8 R 1.238(gument is)-.18 F F1<ad>3.738 E F0 3.738(,t)C 1.238
+(he shell places a dash in the zeroth ar)376.426 160.8 R(g)-.18 E 1.048
+(passed to)144 172.8 R F2(command)3.548 E F0 6.048(.T).77 G 1.048
+(his is what login does.)239.844 172.8 R 1.048(If the \214le cannot be e)6.048
+F -.15(xe)-.15 G 1.049(cuted for some reason, a).15 F(non-interacti)144 184.8 Q
+.911 -.15(ve s)-.25 H .611(hell e).15 F .611(xits, unless the shell v)-.15 F
+(ariable)-.25 E F1(no_exit_on_failed_exec)3.111 E F0 -.15(ex)3.111 G .611
+(ists, in which case).15 F .332(it returns f)144 196.8 R 2.832(ailure. An)-.1 F
+(interacti)2.832 E .632 -.15(ve s)-.25 H .332(hell returns f).15 F .333
+(ailure if the \214le cannot be e)-.1 F -.15(xe)-.15 G 2.833(cuted. If).15 F F2
+(command)2.833 E F0(is)2.833 E(not speci\214ed, an)144 208.8 Q 2.5(yr)-.15 G
+(edirections tak)219.95 208.8 Q 2.5(ee)-.1 G -.25(ff)289.83 208.8 S
+(ect in the current shell, and the return status is 0.).25 E F1(exit)108 225.6
+Q F0([)2.5 E F2(n)A F0 6.29(]C)C .123(ause the shell to e)150.67 225.6 R .123
+(xit with a status of)-.15 F F2(n)2.623 E F0 5.123(.I)C(f)315.07 225.6 Q F2(n)
+2.623 E F0 .123(is omitted, the e)2.623 F .122
+(xit status is that of the last command)-.15 F -.15(exe)144 237.6 S 2.5
+(cuted. A).15 F(trap on)2.5 E/F3 9/Times-Bold@0 SF(EXIT)2.5 E F0(is e)2.25 E
+-.15(xe)-.15 G(cuted before the shell terminates.).15 E F1(export)108 254.4 Q
+F0([)2.5 E F1(\255nf)A F0 2.5(][).833 G F2(name)166.183 254.4 Q F0([=)A F2(wor)
+A(d)-.37 E F0(]] ...)A F1(export \255p)108 266.4 Q F0 .305(The supplied)144
+278.4 R F2(names)2.805 E F0 .305(are mark)2.805 F .305(ed for automatic e)-.1 F
+.306(xport to the en)-.15 F .306(vironment of subsequently e)-.4 F -.15(xe)-.15
+G(cuted).15 E 2.694(commands. If)144 290.4 R(the)2.694 E F1<ad66>2.694 E F0
+.193(option is gi)2.693 F -.15(ve)-.25 G .193(n, the).15 F F2(names)2.693 E F0
+.193(refer to functions.)2.693 F .193(If no)5.193 F F2(names)2.693 E F0 .193
+(are gi)2.693 F -.15(ve)-.25 G .193(n, or if the).15 F F1<ad70>144 302.4 Q F0
+.659(option is supplied, a list of all names that are e)3.159 F .66
+(xported in this shell is printed.)-.15 F(The)5.66 E F1<ad6e>3.16 E F0(option)
+3.16 E .538(causes the e)144 314.4 R .538(xport property to be remo)-.15 F -.15
+(ve)-.15 G 3.037(df).15 G .537(rom the named v)318.104 314.4 R 3.037
+(ariables. An)-.25 F(ar)3.037 E .537(gument of)-.18 F F1<adad>3.037 E F0
+(disables)3.037 E .665(option checking for the rest of the ar)144 326.4 R
+(guments.)-.18 E F1(export)5.665 E F0 .665(returns an e)3.165 F .666
+(xit status of 0 unless an ille)-.15 F -.05(ga)-.15 G(l).05 E .32
+(option is encountered, one of the)144 338.4 R F2(names)2.82 E F0 .32
+(is not a le)2.82 F -.05(ga)-.15 G 2.82(ls).05 G .32(hell v)366.18 338.4 R .32
+(ariable name, or)-.25 F F1<ad66>2.82 E F0 .32(is supplied with a)2.82 F F2
+(name)144 350.4 Q F0(that is not a function.)2.5 E F1(fc)108 367.2 Q F0([)2.5 E
+F1<ad65>A F2(ename)2.5 E F0 2.5(][)C F1(\255nlr)169.5 367.2 Q F0 2.5(][)C F2
+<8c72>197.14 367.2 Q(st)-.1 E F0 2.5(][)C F2(last)221.76 367.2 Q F0(])A F1
+(fc \255s)108 379.2 Q F0([)2.5 E F2(pat)A F0(=)A F2 -.37(re)C(p).37 E F0 2.5
+(][)C F2(cmd)174.23 379.2 Q F0(])A .664(Fix Command.)144 391.2 R .664
+(In the \214rst form, a range of commands from)5.664 F F2<8c72>3.165 E(st)-.1 E
+F0(to)3.165 E F2(last)3.165 E F0 .665(is selected from the his-)3.165 F .968
+(tory list.)144 403.2 R F2 -.45(Fi)5.967 G -.1(rs).45 G(t).1 E F0(and)3.467 E
+F2(last)3.467 E F0 .967
+(may be speci\214ed as a string \(to locate the last command be)3.467 F .967
+(ginning with)-.15 F .797(that string\) or as a number \(an inde)144 415.2 R
+3.297(xi)-.15 G .797(nto the history list, where a ne)300.753 415.2 R -.05(ga)
+-.15 G(ti).05 E 1.097 -.15(ve n)-.25 H .797(umber is used as an).15 F(of)144
+427.2 Q .322(fset from the current command number\).)-.25 F(If)5.322 E F2(last)
+2.822 E F0 .322(is not speci\214ed it is set to the current command)2.822 F
+.019(for listing \(so that)144 439.2 R F1 .019(fc \255l \25510)2.519 F F0 .019
+(prints the last 10 commands\) and to)2.519 F F2<8c72>2.519 E(st)-.1 E F0 2.519
+(otherwise. If)2.519 F F2<8c72>2.519 E(st)-.1 E F0 .019(is not spec-)2.519 F
+(i\214ed it is set to the pre)144 451.2 Q
+(vious command for editing and \25516 for listing.)-.25 E(The)144 475.2 Q F1
+<ad6e>2.921 E F0 .421(\215ag suppresses the command numbers when listing.)2.921
+F(The)5.421 E F1<ad72>2.921 E F0 .42(\215ag re)2.92 F -.15(ve)-.25 G .42
+(rses the order of the).15 F 3.642(commands. If)144 487.2 R(the)3.642 E F1
+<ad6c>3.642 E F0 1.142(\215ag is gi)3.642 F -.15(ve)-.25 G 1.142
+(n, the commands are listed on standard output.).15 F 1.142(Otherwise, the)
+6.142 F .379(editor gi)144 499.2 R -.15(ve)-.25 G 2.879(nb).15 G(y)199.908
+499.2 Q F2(ename)2.879 E F0 .378(is in)2.879 F -.2(vo)-.4 G -.1(ke).2 G 2.878
+(do).1 G 2.878(na\214)285.712 499.2 S .378(le containing those commands.)
+306.468 499.2 R(If)5.378 E F2(ename)2.878 E F0 .378(is not gi)2.878 F -.15(ve)
+-.25 G .378(n, the).15 F -.25(va)144 511.2 S .804(lue of the).25 F F3(FCEDIT)
+3.304 E F0 -.25(va)3.054 G .804(riable is used, and the v).25 F .805(alue of)
+-.25 F F3(EDIT)3.305 E(OR)-.162 E F0(if)3.055 E F3(FCEDIT)3.305 E F0 .805
+(is not set.)3.055 F .805(If neither)5.805 F -.25(va)144 523.2 S 2.218
+(riable is set,).25 F F2(vi)6.384 E F0 2.217(is used.)6.383 F 2.217
+(When editing is complete, the edited commands are echoed and)7.217 F -.15(exe)
+144 535.2 S(cuted.).15 E .039(In the second form,)144 559.2 R F2(command)2.539
+E F0 .039(is re-e)2.539 F -.15(xe)-.15 G .039(cuted after each instance of).15
+F F2(pat)2.54 E F0 .04(is replaced by)2.54 F F2 -.37(re)2.54 G(p).37 E F0 5.04
+(.A)C(useful)515.56 559.2 Q 1.009(alias to use with this is `)144 571.2 R 1.008
+(`r=fc \255s')-.74 F 1.008(', so that typing `)-.74 F 1.008(`r cc')-.74 F 3.508
+('r)-.74 G 1.008(uns the last command be)385.39 571.2 R 1.008(ginning with)-.15
+F -.74(``)144 583.2 S(cc').74 E 2.5('a)-.74 G(nd typing `)171.66 583.2 Q(`r')
+-.74 E 2.5('r)-.74 G(e-e)233.22 583.2 Q -.15(xe)-.15 G(cutes the last command.)
+.15 E .426(If the \214rst form is used, the return v)144 607.2 R .427
+(alue is 0 unless an ille)-.25 F -.05(ga)-.15 G 2.927(lo).05 G .427
+(ption is encountered or)399.768 607.2 R F2<8c72>2.927 E(st)-.1 E F0(or)2.927 E
+F2(last)2.927 E F0 .455(specify history lines out of range.)144 619.2 R .454
+(If the)5.454 F F1<ad65>2.954 E F0 .454(option is supplied, the return v)2.954
+F .454(alue is the v)-.25 F .454(alue of the)-.25 F .787(last command e)144
+631.2 R -.15(xe)-.15 G .787(cuted or f).15 F .788
+(ailure if an error occurs with the temporary \214le of commands.)-.1 F .788
+(If the)5.788 F 1.196
+(second form is used, the return status is that of the command re-e)144 643.2 R
+-.15(xe)-.15 G 1.196(cuted, unless).15 F F2(cmd)3.696 E F0 1.196(does not)3.696
+F(specify a v)144 655.2 Q(alid history line, in which case)-.25 E F1(fc)2.5 E
+F0(returns f)2.5 E(ailure.)-.1 E F1(fg)108 672 Q F0([)2.5 E F2(jobspec)A F0(])A
+(Place)144 684 Q F2(jobspec)3.041 E F0 .541(in the fore)3.041 F .542
+(ground, and mak)-.15 F 3.042(ei)-.1 G 3.042(tt)323.06 684 S .542
+(he current job)331.662 684 R 5.542(.I)-.4 G(f)399.258 684 Q F2(jobspec)3.042 E
+F0 .542(is not present, the shell')3.042 F(s)-.55 E .958(notion of the)144 696
+R F2(curr)3.458 E .958(ent job)-.37 F F0 .957(is used.)3.457 F .957
+(The return v)5.957 F .957(alue is that of the command placed into the fore-)
+-.25 F .194(ground, or f)144 708 R .194
+(ailure if run when job control is disabled or)-.1 F 2.695(,w)-.4 G .195
+(hen run with job control enabled, if)378.655 708 R F2(job-)2.695 E(spec)144
+720 Q F0(does not specify a v)2.5 E(alid job or)-.25 E F2(jobspec)2.5 E F0
+(speci\214es a job that w)2.5 E(as started without job control.)-.1 E 185.675
+(GNU 1995)72 768 R(May 5)2.5 E(28)530 768 Q EP
+%%Page: 29 29
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF(getopts)108 84 Q/F2 10/Times-Italic@0 SF(optstring name)
+2.5 E F0([)2.5 E F2(ar)A(gs)-.37 E F0(])A F1(getopts)144 96 Q F0 .828
+(is used by shell procedures to parse positional parameters.)3.328 F F2
+(optstring)5.827 E F0 .827(contains the option)3.327 F .602
+(letters to be recognized; if a letter is follo)144 108 R .603
+(wed by a colon, the option is e)-.25 F .603(xpected to ha)-.15 F .903 -.15
+(ve a)-.2 H 3.103(na).15 G -.18(rg)523.52 108 S(u-).18 E .7
+(ment, which should be separated from it by white space.)144 120 R .7
+(Each time it is in)5.7 F -.2(vo)-.4 G -.1(ke).2 G(d,).1 E F1(getopts)3.2 E F0
+(places)3.2 E .008(the ne)144 132 R .008(xt option in the shell v)-.15 F
+(ariable)-.25 E F2(name)2.508 E F0 2.508(,i).18 G(nitializing)316.884 132 Q F2
+(name)2.508 E F0 .009(if it does not e)2.508 F .009(xist, and the inde)-.15 F
+2.509(xo)-.15 G 2.509(ft)521.941 132 S(he)530.56 132 Q(ne)144 144 Q .199(xt ar)
+-.15 F .199(gument to be processed into the v)-.18 F(ariable)-.25 E/F3 9
+/Times-Bold@0 SF(OPTIND)2.699 E/F4 9/Times-Roman@0 SF(.)A F3(OPTIND)4.699 E F0
+.198(is initialized to 1 each time the)2.449 F .497
+(shell or a shell script is in)144 156 R -.2(vo)-.4 G -.1(ke).2 G 2.997
+(d. When).1 F .498(an option requires an ar)2.997 F(gument,)-.18 E F1(getopts)
+2.998 E F0 .498(places that ar)2.998 F(gu-)-.18 E .028(ment into the v)144 168
+R(ariable)-.25 E F3(OPT)2.528 E(ARG)-.81 E F4(.)A F0 .028
+(The shell does not reset)4.528 F F3(OPTIND)2.528 E F0 .027
+(automatically; it must be manu-)2.278 F .161
+(ally reset between multiple calls to)144 180 R F1(getopts)2.661 E F0 .161
+(within the same shell in)2.661 F -.2(vo)-.4 G .161(cation if a ne).2 F 2.662
+(ws)-.25 G .162(et of param-)490.806 180 R(eters is to be used.)144 192 Q F1
+(getopts)144 216 Q F0 1.252(can report errors in tw)3.752 F 3.752(ow)-.1 G
+3.752(ays. If)287.942 216 R 1.252(the \214rst character of)3.752 F F2
+(optstring)3.752 E F0 1.251(is a colon,)3.752 F F2(silent)3.751 E F0(error)
+3.751 E 1.442(reporting is used.)144 228 R 1.442
+(In normal operation diagnostic messages are printed when ille)6.442 F -.05(ga)
+-.15 G 3.943(lo).05 G 1.443(ptions or)503.277 228 R .654(missing option ar)144
+240 R .653(guments are encountered.)-.18 F .653(If the v)5.653 F(ariable)-.25 E
+F3(OPTERR)3.153 E F0 .653(is set to 0, no error message)2.903 F
+(will be displayed, e)144 252 Q -.15(ve)-.25 G 2.5(ni).15 G 2.5(ft)241.09 252 S
+(he \214rst character of)249.7 252 Q F2(optstring)2.5 E F0(is not a colon.)2.5
+E .826(If an ille)144 276 R -.05(ga)-.15 G 3.326(lo).05 G .826(ption is seen,)
+199.878 276 R F1(getopts)3.326 E F0 .826(places ? into)3.326 F F2(name)3.326 E
+F0 .826(and, if not silent, prints an error message)3.326 F .4(and unsets)144
+288 R F3(OPT)2.9 E(ARG)-.81 E F4(.)A F0(If)4.899 E F1(getopts)2.899 E F0 .399
+(is silent, the option character found is placed in)2.899 F F3(OPT)2.899 E(ARG)
+-.81 E F0 .399(and no)2.649 F(diagnostic message is printed.)144 300 Q 1.241
+(If a required ar)144 324 R 1.241(gument is not found, and)-.18 F F1(getopts)
+3.741 E F0 1.241(is not silent, a question mark \()3.741 F F1(?).833 E F0 3.742
+(\)i).833 G 3.742(sp)494.746 324 S 1.242(laced in)507.378 324 R F2(name)144 336
+Q F0(,).18 E F1(OPT)3.357 E(ARG)-.9 E F0 .856
+(is unset, and a diagnostic message is printed.)3.357 F(If)5.856 E F1(getopts)
+3.356 E F0 .856(is silent, then a colon)3.356 F(\()144 348 Q F1(:).833 E F0 2.5
+(\)i).833 G 2.5(sp)160.936 348 S(laced in)172.326 348 Q F2(name)2.5 E F0(and)
+2.5 E F3(OPT)2.5 E(ARG)-.81 E F0(is set to the option character found.)2.25 E
+F1(getopts)144 372 Q F0 2.392(normally parses the positional parameters, b)
+4.892 F 2.392(ut if more ar)-.2 F 2.393(guments are gi)-.18 F -.15(ve)-.25 G
+4.893(ni).15 G(n)509.927 372 Q F2(ar)4.893 E(gs)-.37 E F0(,).27 E F1(getopts)
+144 384 Q F0 .651(parses those instead.)3.151 F F1(getopts)5.651 E F0 .651
+(returns true if an option, speci\214ed or unspeci\214ed, is found.)3.151 F
+(It returns f)144 396 Q
+(alse if the end of options is encountered or an error occurs.)-.1 E F1(hash)
+108 412.8 Q F0([)2.5 E F1<ad72>A F0 2.5(][)C F2(name)153.14 412.8 Q F0(])A -.15
+(Fo)144 424.8 S 2.819(re).15 G(ach)164.999 424.8 Q F2(name)2.819 E F0 2.819(,t)
+.18 G .319(he full pathname of the command is determined and remembered.)
+211.637 424.8 R(The)5.32 E F1<ad72>2.82 E F0(option)2.82 E .508
+(causes the shell to for)144 436.8 R .508(get all remembered locations.)-.18 F
+.508(If no ar)5.508 F .508(guments are gi)-.18 F -.15(ve)-.25 G .507
+(n, information about).15 F .193(remembered commands is printed.)144 448.8 R
+.193(An ar)5.193 F .193(gument of)-.18 F F1<adad>2.693 E F0 .194
+(disables option checking for the rest of the)2.693 F(ar)144 460.8 Q 2.5
+(guments. The)-.18 F(return status is true unless a)2.5 E F2(name)2.5 E F0
+(is not found or an ille)2.5 E -.05(ga)-.15 G 2.5(lo).05 G(ption is supplied.)
+453.86 460.8 Q F1(help)108 477.6 Q F0([)2.5 E F2(pattern)A F0(])A .991
+(Display helpful information about b)144 489.6 R .991(uiltin commands.)-.2 F
+(If)5.991 E F2(pattern)3.491 E F0 .991(is speci\214ed,)3.491 F F1(help)3.491 E
+F0(gi)3.49 E -.15(ve)-.25 G 3.49(sd).15 G(etailed)513.34 489.6 Q .408
+(help on all commands matching)144 501.6 R F2(pattern)2.909 E F0 2.909(;o).24 G
+.409(therwise a list of the b)316.13 501.6 R .409(uiltins is printed.)-.2 F
+.409(The return sta-)5.409 F(tus is 0 unless no command matches)144 513.6 Q F2
+(pattern)2.5 E F0(.).24 E F1(history)108 530.4 Q F0([)2.5 E F2(n)A F0(])A F1
+(history \255rwan)108 542.4 Q F0([)2.5 E F2(\214lename)A F0(])A -.4(Wi)144
+554.4 S .752
+(th no options, display the command history list with line numbers.).4 F .752
+(Lines listed with a)5.752 F F1(*)3.251 E F0(ha)3.251 E -.15(ve)-.2 G .375
+(been modi\214ed.)144 566.4 R .375(An ar)5.375 F .375(gument of)-.18 F F2(n)
+2.875 E F0 .375(lists only the last)2.875 F F2(n)2.875 E F0 2.875(lines. If)
+2.875 F 2.876(an)2.876 G .376(on-option ar)411.832 566.4 R .376
+(gument is supplied,)-.18 F .811
+(it is used as the name of the history \214le; if not, the v)144 578.4 R .811
+(alue of)-.25 F F3(HISTFILE)3.311 E F0 .811(is used.)3.061 F .811
+(Options, if sup-)5.811 F(plied, ha)144 590.4 Q .3 -.15(ve t)-.2 H(he follo).15
+E(wing meanings:)-.25 E F1<ad61>144 602.4 Q F0 .598(Append the `)180 602.4 R
+(`ne)-.74 E(w')-.25 E 3.098('h)-.74 G .598
+(istory lines \(history lines entered since the be)266.424 602.4 R .599
+(ginning of the current)-.15 F F1(bash)180 614.4 Q F0
+(session\) to the history \214le)2.5 E F1<ad6e>144 626.4 Q F0 .854(Read the hi\
+story lines not already read from the history \214le into the current history \
+list.)180 626.4 R .772
+(These are lines appended to the history \214le since the be)180 638.4 R .773
+(ginning of the current)-.15 F F1(bash)3.273 E F0(ses-)3.273 E(sion.)180 650.4
+Q F1<ad72>144 662.4 Q F0
+(Read the contents of the history \214le and use them as the current history)
+180 662.4 Q F1<ad77>144 674.4 Q F0
+(Write the current history to the history \214le, o)180 674.4 Q -.15(ve)-.15 G
+(rwriting the history \214le').15 E 2.5(sc)-.55 G(ontents.)474.4 674.4 Q .989
+(The return v)144 691.2 R .989(alue is 0 unless an ille)-.25 F -.05(ga)-.15 G
+3.489(lo).05 G .989(ption is encountered or an error occurs while reading or)
+308.662 691.2 R(writing the history \214le.)144 703.2 Q 185.675(GNU 1995)72 768
+R(May 5)2.5 E(29)530 768 Q EP
+%%Page: 30 30
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF(jobs)108 84 Q F0([)2.5 E F1(\255lnp)A F0 2.5(][)C/F2 10
+/Times-Italic@0 SF(jobspec)A F0(... ])2.5 E F1(jobs \255x)108 96 Q F2(command)
+2.5 E F0([)2.5 E F2(ar)2.5 E(gs)-.37 E F0(... ])2.5 E .297
+(The \214rst form lists the acti)144 108 R .598 -.15(ve j)-.25 H 2.798
+(obs. The).15 F F1<ad6c>2.798 E F0 .298
+(option lists process IDs in addition to the normal infor)2.798 F(-)-.2 E .746
+(mation; the)144 120 R F1<ad70>3.246 E F0 .745
+(option lists only the process ID of the job')3.246 F 3.245(sp)-.55 G .745
+(rocess group leader)394.205 120 R 5.745(.T)-.55 G(he)487.25 120 Q F1<ad6e>
+3.245 E F0(option)3.245 E 2.08(displays only jobs that ha)144 132 R 2.38 -.15
+(ve c)-.2 H 2.081(hanged status since last noti\214ed.).15 F(If)7.081 E F2
+(jobspec)4.581 E F0 2.081(is gi)4.581 F -.15(ve)-.25 G 2.081(n, output is).15 F
+.727(restricted to information about that job)144 144 R 5.727(.T)-.4 G .727
+(he return status is 0 unless an ille)316.282 144 R -.05(ga)-.15 G 3.227(lo).05
+G .726(ption is encoun-)474.108 144 R(tered or an ille)144 156 Q -.05(ga)-.15 G
+(l).05 E F2(jobspec)2.5 E F0(is supplied.)2.5 E .607(If the)144 180 R F1<ad78>
+3.107 E F0 .607(option is supplied,)3.107 F F1(jobs)3.107 E F0 .607
+(replaces an)3.107 F(y)-.15 E F2(jobspec)3.107 E F0 .607(found in)3.107 F F2
+(command)3.107 E F0(or)3.107 E F2(ar)3.107 E(gs)-.37 E F0 .607(with the corre-)
+3.107 F(sponding process group ID, and e)144 192 Q -.15(xe)-.15 G(cutes).15 E
+F2(command)2.5 E F0(passing it)2.5 E F2(ar)2.5 E(gs)-.37 E F0 2.5(,r).27 G
+(eturning its e)418.56 192 Q(xit status.)-.15 E F1(kill)108 208.8 Q F0([)2.5 E
+F1(-s sigspec)A F0(|)2.5 E F1(\255sigspec)2.5 E F0 2.5(][)C F2(pid)219.31 208.8
+Q F0(|)2.5 E F2(jobspec)2.5 E F0 2.5(].)C(..)277.97 208.8 Q F1(kill \255l)108
+220.8 Q F0([)2.5 E F2(signum)A F0(])A .943(Send the signal named by)144 232.8 R
+F2(sigspec)3.443 E F0 .942(to the processes named by)3.443 F F2(pid)3.442 E F0
+(or)3.442 E F2(jobspec)3.442 E F0(.).31 E F2(sigspec)5.942 E F0 .942
+(is either a)3.442 F .908(signal name such as)144 244.8 R/F3 9/Times-Bold@0 SF
+(SIGKILL)3.408 E F0 .908(or a signal number)3.158 F 5.908(.I)-.55 G(f)359.638
+244.8 Q F2(sigspec)3.408 E F0 .908(is a signal name, the name is case)3.408 F
+(insensiti)144 256.8 Q 2.43 -.15(ve a)-.25 H 2.13(nd may be gi).15 F -.15(ve)
+-.25 G 4.63(nw).15 G 2.13(ith or without the)279.67 256.8 R F3(SIG)4.63 E F0
+4.629(pre\214x. If)4.379 F F2(sigspec)4.629 E F0 2.129(is not present, then)
+4.629 F F3(SIGTERM)144 268.8 Q F0 .813(is assumed.)3.063 F .813(An ar)5.813 F
+.813(gument of)-.18 F F1<ad6c>3.313 E F0 .814(lists the signal names.)3.313 F
+.814(If an)5.814 F 3.314(ya)-.15 G -.18(rg)450.232 268.8 S .814
+(uments are supplied).18 F(when)144 280.8 Q F1<ad6c>2.827 E F0 .327(is gi)2.827
+F -.15(ve)-.25 G .327(n, the names of the speci\214ed signals are listed, and \
+the return status is 0.).15 F .326(An ar)5.326 F(gu-)-.18 E .484(ment of)144
+292.8 R F1<adad>2.984 E F0 .484
+(disables option checking for the rest of the ar)2.984 F(guments.)-.18 E F1
+(kill)5.485 E F0 .485(returns true if at least one)2.985 F(signal w)144 304.8 Q
+(as successfully sent, or f)-.1 E(alse if an error occurs or an ille)-.1 E -.05
+(ga)-.15 G 2.5(lo).05 G(ption is encountered.)419.09 304.8 Q F1(let)108 321.6 Q
+F2(ar)2.5 E(g)-.37 E F0([)2.5 E F2(ar)A(g)-.37 E F0(...])2.5 E(Each)144 333.6 Q
+F2(ar)3.677 E(g)-.37 E F0 1.177(is an arithmetic e)3.677 F 1.177
+(xpression to be e)-.15 F -.25(va)-.25 G 1.177(luated \(see).25 F F3 1.176
+(ARITHMETIC EV)3.677 F(ALU)-1.215 E -.855(AT)-.54 G(ION).855 E/F4 9
+/Times-Roman@0 SF(\).)A F0 1.176(If the)5.676 F(last)144 345.6 Q F2(ar)2.5 E(g)
+-.37 E F0 -.25(eva)2.5 G(luates to 0,).25 E F1(let)2.5 E F0
+(returns 1; 0 is returned otherwise.)2.5 E F1(local)108 362.4 Q F0([)2.5 E F2
+(name)A F0([=)A F2(value)A F0 2.5(].)C(..])194.45 362.4 Q -.15(Fo)144 374.4 S
+3.276(re).15 G .776(ach ar)165.456 374.4 R .776(gument, create a local v)-.18 F
+.776(ariable named)-.25 F F2(name)3.276 E F0 3.276(,a).18 G .776(nd assign it)
+380.784 374.4 R F2(value)3.276 E F0 5.777(.W).18 G(hen)470.729 374.4 Q F1
+(local)3.277 E F0 .777(is used)3.277 F .131(within a function, it causes the v)
+144 386.4 R(ariable)-.25 E F2(name)2.631 E F0 .131(to ha)2.631 F .431 -.15
+(ve a v)-.2 H .13(isible scope restricted to that function and).15 F .232
+(its children.)144 398.4 R -.4(Wi)5.232 G .232(th no operands,).4 F F1(local)
+2.733 E F0 .233(writes a list of local v)2.733 F .233
+(ariables to the standard output.)-.25 F .233(It is an)5.233 F .42
+(error to use)144 410.4 R F1(local)2.92 E F0 .42(when not within a function.)
+2.92 F .42(The return status is 0 unless)5.42 F F1(local)2.92 E F0 .42
+(is used outside a)2.92 F(function, or an ille)144 422.4 Q -.05(ga)-.15 G(l).05
+E F2(name)2.5 E F0(is supplied.)2.5 E F1(logout)108 439.2 Q F0
+(Exit a login shell.)9.33 E F1(popd)108 456 Q F0([)2.5 E F1(+/\255n)A F0(])A
+(Remo)144 468 Q -.15(ve)-.15 G 2.799(se).15 G .299
+(ntries from the directory stack.)188.159 468 R -.4(Wi)5.299 G .299(th no ar).4
+F .299(guments, remo)-.18 F -.15(ve)-.15 G 2.799(st).15 G .3
+(he top directory from the)438.82 468 R(stack, and performs a)144 480 Q F1(cd)
+2.5 E F0(to the ne)2.5 E 2.5(wt)-.25 G(op directory)291.22 480 Q(.)-.65 E F1
+(+n)144 492 Q F0(remo)180 492 Q -.15(ve)-.15 G 2.849(st).15 G(he)219.209 492 Q
+F2(n)2.849 E F0 .349(th entry counting from the left of the list sho)B .349
+(wn by)-.25 F F1(dirs)2.848 E F0 2.848(,s)C .348(tarting with zero.)470.704 492
+R -.15(Fo)180 504 S 2.5(re).15 G(xample: `)200.53 504 Q(`popd +0')-.74 E 2.5
+('r)-.74 G(emo)286.06 504 Q -.15(ve)-.15 G 2.5(st).15 G(he \214rst directory)
+321.59 504 Q 2.5(,`)-.65 G(`popd +1')394.63 504 Q 2.5('t)-.74 G(he second.)
+442.3 504 Q F1<ad6e>144 516 Q F0(remo)180 516 Q -.15(ve)-.15 G 2.501(st).15 G
+(he)218.861 516 Q F2(n)2.501 E F0 .001
+(th entry counting from the right of the list sho)B .001(wn by)-.25 F F1(dirs)
+2.502 E F0 2.502(,s)C .002(tarting with zero.)471.396 516 R -.15(Fo)180 528 S
+2.5(re).15 G(xample: `)200.53 528 Q(`popd -0')-.74 E 2.5('r)-.74 G(emo)283.75
+528 Q -.15(ve)-.15 G 2.5(st).15 G(he last directory)319.28 528 Q 2.5(,`)-.65 G
+(`popd -1')390.65 528 Q 2.5('t)-.74 G(he ne)436.01 528 Q(xt to last.)-.15 E
+.644(If the)144 544.8 R F1(popd)3.144 E F0 .644(command is successful, a)3.144
+F F1(dirs)3.143 E F0 .643(is performed as well, and the return status is 0.)
+3.143 F F1(popd)5.643 E F0 .57(returns f)144 556.8 R .57(alse if an ille)-.1 F
+-.05(ga)-.15 G 3.07(lo).05 G .571
+(ption is encountered, the directory stack is empty)251.25 556.8 R 3.071(,an)
+-.65 G(on-e)469.319 556.8 Q .571(xistent direc-)-.15 F
+(tory stack entry is speci\214ed, or the directory change f)144 568.8 Q(ails.)
+-.1 E F1(pushd)108 585.6 Q F0([)2.5 E F2(dir)A F0(])A F1(pushd +/\255n)108
+597.6 Q F0 .64(Adds a directory to the top of the directory stack, or rotates \
+the stack, making the ne)144 609.6 R 3.139(wt)-.25 G .639(op of the)503.172
+609.6 R 1.315(stack the current w)144 621.6 R 1.315(orking directory)-.1 F
+6.315(.W)-.65 G 1.315(ith no ar)306.885 621.6 R 1.315(guments, e)-.18 F 1.316
+(xchanges the top tw)-.15 F 3.816(od)-.1 G 1.316(irectories and)484.534 621.6 R
+(returns 0, unless the directory stack is empty)144 633.6 Q(.)-.65 E F1(+n)144
+645.6 Q F0 1.268(Rotates the stack so that the)180 645.6 R F2(n)3.768 E F0
+1.267(th directory \(counting from the left of the list sho)B 1.267(wn by)-.25
+F F1(dirs)180 657.6 Q F0 2.5(\)i)C 2.5(sa)205.28 657.6 S 2.5(tt)216.11 657.6 S
+(he top.)224.17 657.6 Q F1<ad6e>144 669.6 Q F0(Rotates the stack so that the)
+180 669.6 Q F2(n)2.5 E F0
+(th directory \(counting from the right\) is at the top.)A F1(dir)144 681.6 Q
+F0(adds)180 681.6 Q F2(dir)2.5 E F0
+(to the directory stack at the top, making it the ne)2.5 E 2.5(wc)-.25 G
+(urrent w)422.5 681.6 Q(orking directory)-.1 E(.)-.65 E .488(If the)144 698.4 R
+F1(pushd)2.988 E F0 .488(command is successful, a)2.988 F F1(dirs)2.988 E F0
+.488(is performed as well.)2.988 F .489(If the \214rst form is used,)5.488 F F1
+(pushd)2.989 E F0 1.103(returns 0 unless the cd to)144 710.4 R F2(dir)3.603 E
+F0 -.1(fa)3.603 G 3.603(ils. W).1 F 1.103(ith the second form,)-.4 F F1(pushd)
+3.603 E F0 1.103(returns 0 unless the directory)3.603 F .846(stack is empty)144
+722.4 R 3.346(,an)-.65 G(on-e)220.894 722.4 Q .847(xistant directory stack ele\
+ment is speci\214ed, or the directory change to the)-.15 F 185.675(GNU 1995)72
+768 R(May 5)2.5 E(30)530 768 Q EP
+%%Page: 31 31
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+(speci\214ed ne)144 84 Q 2.5(wc)-.25 G(urrent directory f)205.4 84 Q(ails.)-.1
+E/F1 10/Times-Bold@0 SF(pwd)108 100.8 Q F0 .725
+(Print the absolute pathname of the current w)144 100.8 R .724
+(orking directory)-.1 F 5.724(.T)-.65 G .724(he path printed contains no sym-)
+405.56 100.8 R .521(bolic links if the)144 112.8 R F1<ad50>3.021 E F0 .521
+(option to the)3.021 F F1(set)3.021 E F0 -.2(bu)3.021 G .521
+(iltin command is set.).2 F .521(See also the description of)5.521 F F1
+(nolinks)3.022 E F0(under)144 124.8 Q F1 .074(Shell V)2.574 F(ariables)-.92 E
+F0(abo)2.574 E -.15(ve)-.15 G 2.574(\). The).15 F .074
+(return status is 0 unless an error occurs while reading the path-)2.574 F
+(name of the current directory)144 136.8 Q(.)-.65 E F1 -.18(re)108 153.6 S(ad)
+.18 E F0([)2.5 E F1<ad72>A F0 2.5(][)C/F2 10/Times-Italic@0 SF(name)152.39
+153.6 Q F0(...])2.5 E .036
+(One line is read from the standard input, and the \214rst w)144 165.6 R .037
+(ord is assigned to the \214rst)-.1 F F2(name)2.537 E F0 2.537(,t).18 G .037
+(he second)500.253 165.6 R -.1(wo)144 177.6 S .109(rd to the second).1 F F2
+(name)2.609 E F0 2.609(,a).18 G .109(nd so on, with lefto)254.045 177.6 R -.15
+(ve)-.15 G 2.609(rw).15 G .109(ords assigned to the last)354.18 177.6 R F2
+(name)2.609 E F0 5.109(.O).18 G .108(nly the char)489.444 177.6 R(-)-.2 E .143
+(acters in)144 189.6 R/F3 9/Times-Bold@0 SF(IFS)2.643 E F0 .143
+(are recognized as w)2.393 F .143(ord delimiters.)-.1 F .143(If no)5.143 F F2
+(names)2.643 E F0 .144(are supplied, the line read is assigned)2.643 F .194
+(to the v)144 201.6 R(ariable)-.25 E F3(REPL)2.694 E(Y)-.828 E/F4 9
+/Times-Roman@0 SF(.)A F0 .194
+(The return code is zero, unless end-of-\214le is encountered.)4.694 F .193
+(If the)5.193 F F1<ad72>2.693 E F0(option)2.693 E .444(is gi)144 213.6 R -.15
+(ve)-.25 G .444(n, a backslash-ne).15 F .444
+(wline pair is not ignored, and the backslash is considered to be part of the)
+-.25 F(line.)144 225.6 Q F1 -.18(re)108 242.4 S(adonly).18 E F0([)2.5 E F1
+<ad66>A F0 2.5(][)C F2(name)169.62 242.4 Q F0(...])2.5 E F1 -.18(re)108 254.4 S
+(adonly -p).18 E F0 .419(The gi)144 266.4 R -.15(ve)-.25 G(n).15 E F2(names)
+2.919 E F0 .419(are mark)2.919 F .419(ed readonly and the v)-.1 F .419
+(alues of these)-.25 F F2(names)2.919 E F0 .418(may not be changed by sub-)
+2.919 F .541(sequent assignment.)144 278.4 R .541(If the)5.541 F F1<ad66>3.041
+E F0 .541(option is supplied, the functions corresponding to the)3.041 F F2
+(names)3.042 E F0 .542(are so)3.042 F(mark)144 290.4 Q 3.037(ed. If)-.1 F .537
+(no ar)3.037 F .537(guments are gi)-.18 F -.15(ve)-.25 G .536(n, or if the).15
+F F1<ad70>3.036 E F0 .536(option is supplied, a list of all readonly names is)
+3.036 F 2.501(printed. An)144 302.4 R(ar)2.501 E .002(gument of)-.18 F F1<adad>
+2.502 E F0 .002(disables option checking for the rest of the ar)2.502 F 2.502
+(guments. The)-.18 F .002(return sta-)2.502 F .192(tus is 0 unless an ille)144
+314.4 R -.05(ga)-.15 G 2.692(lo).05 G .192(ption is encountered, one of the)
+247.732 314.4 R F2(names)2.691 E F0 .191(is not a le)2.691 F -.05(ga)-.15 G
+2.691(ls).05 G .191(hell v)463.498 314.4 R .191(ariable name,)-.25 F(or)144
+326.4 Q F1<ad66>2.5 E F0(is supplied with a)2.5 E F2(name)2.5 E F0
+(that is not a function.)2.5 E F1 -.18(re)108 343.2 S(tur).18 E(n)-.15 E F0([)
+2.5 E F2(n)A F0(])A .618(Causes a function to e)144 355.2 R .618
+(xit with the return v)-.15 F .618(alue speci\214ed by)-.25 F F2(n)3.118 E F0
+5.619(.I).24 G(f)404.557 355.2 Q F2(n)3.119 E F0 .619
+(is omitted, the return status is)3.119 F 1.335(that of the last command e)144
+367.2 R -.15(xe)-.15 G 1.335(cuted in the function body).15 F 6.335(.I)-.65 G
+3.835(fu)387.48 367.2 S 1.335(sed outside a function, b)399.645 367.2 R 1.335
+(ut during)-.2 F -.15(exe)144 379.2 S .794(cution of a script by the).15 F F1
+(.)3.294 E F0(\()5.794 E F1(sour)A(ce)-.18 E F0 3.294(\)c)C .794
+(ommand, it causes the shell to stop e)309.832 379.2 R -.15(xe)-.15 G .795
+(cuting that script).15 F .278(and return either)144 391.2 R F2(n)2.778 E F0
+.278(or the e)2.778 F .277(xit status of the last command e)-.15 F -.15(xe)-.15
+G .277(cuted within the script as the e).15 F .277(xit sta-)-.15 F .081
+(tus of the script.)144 403.2 R .082
+(If used outside a function and not during e)5.082 F -.15(xe)-.15 G .082
+(cution of a script by).15 F F1(.)2.582 E F0 2.582(,t).833 G .082
+(he return sta-)487.076 403.2 R(tus is f)144 415.2 Q(alse.)-.1 E F1(set)108 432
+Q F0([)2.5 E F1(\255\255abefhkmnptuvxldCHP)A F0 2.5(][)C F1(-o)243.29 432 Q F2
+(option)2.5 E F0 2.5(][)C F2(ar)288.84 432 Q(g)-.37 E F0(...])2.5 E F1<ad61>144
+444 Q F0 1.036(Automatically mark v)184 444 R 1.036
+(ariables which are modi\214ed or created for e)-.25 F 1.035(xport to the en)
+-.15 F(viron-)-.4 E(ment of subsequent commands.)184 456 Q F1<ad62>144 468 Q F0
+.721(Cause the status of terminated background jobs to be reported immediately)
+184 468 R 3.221(,r)-.65 G .721(ather than)499.569 468 R(before the ne)184 480 Q
+(xt primary prompt.)-.15 E(\(Also see)5 E F1(notify)2.5 E F0(under)2.5 E F1
+(Shell V)2.5 E(ariables)-.92 E F0(abo)2.5 E -.15(ve)-.15 G(\).).15 E F1<ad65>
+144 492 Q F0 1.772(Exit immediately if a)184 492 R F2(simple-command)4.272 E F0
+(\(see)4.272 E F3 1.772(SHELL GRAMMAR)4.272 F F0(abo)4.022 E -.15(ve)-.15 G
+4.271(\)e).15 G 1.771(xits with a)494.788 492 R .642(non\255zero status.)184
+504 R .642(The shell does not e)5.642 F .642(xit if the command that f)-.15 F
+.643(ails is part of an)-.1 F F2(until)3.143 E F0(or)3.143 E F2(while)184 516 Q
+F0 .728(loop, part of an)3.228 F F2(if)3.228 E F0 .728(statement, part of a)
+3.228 F F1(&&)3.228 E F0(or)3.228 E/F5 10/Symbol SF 1.666<efef>3.228 G F0 .728
+(list, or if the command')1.562 F 3.228(sr)-.55 G(eturn)519.45 516 Q -.25(va)
+184 528 S(lue is being in).25 E -.15(ve)-.4 G(rted via).15 E F1(!)2.5 E F0(.)A
+F1<ad66>144 540 Q F0(Disable pathname e)184 540 Q(xpansion.)-.15 E F1<ad68>144
+552 Q F0 .106
+(Locate and remember function commands as functions are de\214ned.)184 552 R
+.106(Function commands)5.106 F(are normally look)184 564 Q
+(ed up when the function is e)-.1 E -.15(xe)-.15 G(cuted.).15 E F1<ad6b>144 576
+Q F0 .162(All k)184 576 R -.15(ey)-.1 G -.1(wo).15 G .162(rd ar).1 F .162
+(guments are placed in the en)-.18 F .161
+(vironment for a command, not just those that)-.4 F(precede the command name.)
+184 588 Q F1<ad6d>144 600 Q F0 .009(Monitor mode.)184 600 R .009
+(Job control is enabled.)5.009 F .009(This \215ag is on by def)5.009 F .01
+(ault for interacti)-.1 F .31 -.15(ve s)-.25 H .01(hells on).15 F .124
+(systems that support it \(see)184 612 R F3 .124(JOB CONTR)2.624 F(OL)-.27 E F0
+(abo)2.374 E -.15(ve)-.15 G 2.624(\). Background).15 F .124
+(processes run in a sep-)2.624 F .72
+(arate process group and a line containing their e)184 624 R .721
+(xit status is printed upon their comple-)-.15 F(tion.)184 636 Q F1<ad6e>144
+648 Q F0 .653(Read commands b)184 648 R .653(ut do not e)-.2 F -.15(xe)-.15 G
+.653(cute them.).15 F .652(This may be used to check a shell script for)5.653 F
+(syntax errors.)184 660 Q(This is ignored for interacti)5 E .3 -.15(ve s)-.25 H
+(hells.).15 E F1<ad6f>144 672 Q F2(option-name)2.5 E F0(The)184 684 Q F2
+(option-name)2.5 E F0(can be one of the follo)2.5 E(wing:)-.25 E F1(allexport)
+184 696 Q F0(Same as)224 708 Q F1<ad61>2.5 E F0(.)A 185.675(GNU 1995)72 768 R
+(May 5)2.5 E(31)530 768 Q EP
+%%Page: 32 32
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF(braceexpand)184 84 Q F0 .312(The shell performs brace e)
+224 96 R .313(xpansion \(see)-.15 F F1 .313(Brace Expansion)2.813 F F0(abo)
+2.813 E -.15(ve)-.15 G 2.813(\). This).15 F .313(is on)2.813 F(by def)224 108 Q
+(ault.)-.1 E F1(emacs)184 120 Q F0 .089
+(Use an emacs-style command line editing interf)224 120 R 2.589(ace. This)-.1 F
+.089(is enabled by def)2.589 F(ault)-.1 E .128(when the shell is interacti)224
+132 R -.15(ve)-.25 G 2.628(,u).15 G .128(nless the shell is started with the)
+345.89 132 R F1(\255nolineediting)2.629 E F0(option.)224 144 Q F1(err)184 156 Q
+(exit)-.18 E F0(Same as)224 156 Q F1<ad65>2.5 E F0(.)A F1(histexpand)184 168 Q
+F0(Same as)224 180 Q F1<ad48>2.5 E F0(.)A F1(ignor)184 192 Q(eeof)-.18 E F0
+1.024(The ef)224 204 R 1.024
+(fect is as if the shell command `IGNOREEOF=10' had been e)-.25 F -.15(xe)-.15
+G(cuted).15 E(\(see)224 216 Q F1(Shell V)2.5 E(ariables)-.92 E F0(abo)2.5 E
+-.15(ve)-.15 G(\).).15 E F1(interacti)184 228 Q -.1(ve)-.1 G(\255comments).1 E
+F0(Allo)224 240 Q 2.52(waw)-.25 G .02(ord be)265.35 240 R .021(ginning with)
+-.15 F F1(#)2.521 E F0 .021(to cause that w)2.521 F .021
+(ord and all remaining characters)-.1 F
+(on that line to be ignored in an interacti)224 252 Q .3 -.15(ve s)-.25 H
+(hell \(see).15 E/F2 9/Times-Bold@0 SF(COMMENTS)2.5 E F0(abo)2.25 E -.15(ve)
+-.15 G(\).).15 E F1(monitor)184 264 Q F0(Same as)5.56 E F1<ad6d>2.5 E F0(.)A F1
+(noclob)184 276 Q(ber)-.1 E F0(Same as)224 288 Q F1<ad43>2.5 E F0(.)A F1
+(noexec)184 300 Q F0(Same as)224 300 Q F1<ad6e>2.5 E F0(.)A F1(noglob)184 312 Q
+F0(Same as)224 312 Q F1<ad66>2.5 E F0(.)A F1(nohash)184 324 Q F0(Same as)9.43 E
+F1<ad64>2.5 E F0(.)A F1(notify)184 336 Q F0(Same as)224 336 Q F1<ad62>2.5 E F0
+(.)A F1(nounset)184 348 Q F0(Same as)6.66 E F1<ad75>2.5 E F0(.)A F1(ph)184 360
+Q(ysical)-.15 E F0(Same as)5.14 E F1<ad50>2.5 E F0(.)A F1(posix)184 372 Q F0
+2.244(Change the beha)224 372 R 2.244(vior of bash where the def)-.2 F 2.243
+(ault operation dif)-.1 F 2.243(fers from the)-.25 F
+(Posix 1003.2 standard to match the standard.)224 384 Q F1(pri)184 396 Q
+(vileged)-.1 E F0(Same as)224 408 Q F1<ad70>2.5 E F0(.)A F1 -.1(ve)184 420 S
+(rbose).1 E F0(Same as)7.33 E F1<ad76>2.5 E F0(.)A F1(vi)184 432 Q F0
+(Use a vi-style command line editing interf)224 432 Q(ace.)-.1 E F1(xtrace)184
+444 Q F0(Same as)224 444 Q F1<ad78>2.5 E F0(.)A(If no)184 456 Q/F3 10
+/Times-Italic@0 SF(option-name)2.5 E F0(is supplied, the v)2.5 E
+(alues of the current options are printed.)-.25 E F1<ad70>144 468 Q F0 -.45(Tu)
+184 468 S .521(rn on).45 F F3(privile)3.021 E -.1(ge)-.4 G(d).1 E F0 3.021
+(mode. In)3.021 F .521(this mode, the)3.021 F F1($ENV)3.021 E F0 .522
+(\214le is not processed, and shell func-)3.021 F .26
+(tions are not inherited from the en)184 480 R 2.76(vironment. This)-.4 F .26
+(is enabled automatically on startup if)2.76 F .481(the ef)184 492 R(fecti)-.25
+E .781 -.15(ve u)-.25 H .482
+(ser \(group\) id is not equal to the real user \(group\) id.).15 F -.45(Tu)
+5.482 G .482(rning this option).45 F(of)184 504 Q 2.5(fc)-.25 G(auses the ef)
+202.35 504 Q(fecti)-.25 E .3 -.15(ve u)-.25 H
+(ser and group ids to be set to the real user and group ids.).15 E F1<ad74>144
+516 Q F0(Exit after reading and e)184 516 Q -.15(xe)-.15 G(cuting one command.)
+.15 E F1<ad75>144 528 Q F0 -.35(Tr)184 528 S .445(eat unset v).35 F .444
+(ariables as an error when performing parameter e)-.25 F 2.944(xpansion. If)
+-.15 F -.15(ex)2.944 G .444(pansion is).15 F .519(attempted on an unset v)184
+540 R .519(ariable, the shell prints an error message, and, if not interacti)
+-.25 F -.15(ve)-.25 G(,).15 E -.15(ex)184 552 S(its with a non\255zero status.)
+.15 E F1<ad76>144 564 Q F0(Print shell input lines as the)184 564 Q 2.5(ya)-.15
+G(re read.)306.63 564 Q F1<ad78>144 576 Q F0 1.057(After e)184 576 R 1.056
+(xpanding each)-.15 F F3(simple-command)3.556 E F0(,).77 E F1(bash)3.556 E F0
+1.056(displays the e)3.556 F 1.056(xpanded v)-.15 F 1.056(alue of)-.25 F F2
+(PS4)3.556 E/F4 9/Times-Roman@0 SF(,)A F0(fol-)3.306 E(lo)184 588 Q
+(wed by the command and its e)-.25 E(xpanded ar)-.15 E(guments.)-.18 E F1<ad6c>
+144 600 Q F0(Sa)184 600 Q 1.398 -.15(ve a)-.2 H 1.098
+(nd restore the binding of).15 F F3(name)3.598 E F0 1.098(in a)3.598 F F1 -.25
+(fo)3.598 G(r).25 E F3(name)3.598 E F0([in)3.599 E F1 -.1(wo)3.599 G(rd).1 E F0
+3.599(]c)C 1.099(ommand \(see)451.687 600 R F2(SHELL)3.599 E(GRAMMAR)184 612 Q
+F0(abo)2.25 E -.15(ve)-.15 G(\).).15 E F1<ad64>144 624 Q F0 1.68
+(Disable the hashing of commands that are look)184 624 R 1.68(ed up for e)-.1 F
+-.15(xe)-.15 G 4.18(cution. Normally).15 F 4.18(,c)-.65 G(om-)523.89 624 Q
+1.275(mands are remembered in a hash table, and once found, do not ha)184 636 R
+1.576 -.15(ve t)-.2 H 3.776(ob).15 G 3.776(el)490.888 636 S(ook)501.884 636 Q
+1.276(ed up)-.1 F(ag)184 648 Q(ain.)-.05 E F1<ad43>144 660 Q F0 .812(The ef)184
+660 R .812(fect is as if the shell command `noclobber=' had been e)-.25 F -.15
+(xe)-.15 G .811(cuted \(see).15 F F1 .811(Shell V)3.311 F(ari-)-.92 E(ables)184
+672 Q F0(abo)2.5 E -.15(ve)-.15 G(\).).15 E F1<ad48>144 684 Q F0(Enable)184 684
+Q F1(!)3.13 E F0 .63(style history substitution.)5.63 F .63
+(This \215ag is on by def)5.63 F .63(ault when the shell is interac-)-.1 F(ti)
+184 696 Q -.15(ve)-.25 G(.).15 E F1<ad50>144 708 Q F0 2.107
+(If set, do not follo)184 708 R 4.607(ws)-.25 G 2.107
+(ymbolic links when performing commands such as)279.835 708 R F1(cd)4.607 E F0
+(which)4.606 E(change the current directory)184 720 Q 5(.T)-.65 G(he ph)309.42
+720 Q(ysical directory is used instead.)-.05 E 185.675(GNU 1995)72 768 R(May 5)
+2.5 E(32)530 768 Q EP
+%%Page: 33 33
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF<adad>144 84 Q F0 .05(If no ar)184 84 R .05
+(guments follo)-.18 F 2.55(wt)-.25 G .05
+(his \215ag, then the positional parameters are unset.)280.98 84 R .05
+(Otherwise, the)5.05 F(positional parameters are set to the)184 96 Q/F2 10
+/Times-Italic@0 SF(ar)2.5 E(g)-.37 E F0(s, e)A -.15(ve)-.25 G 2.5(ni).15 G 2.5
+(fs)371.81 96 S(ome of them be)381.53 96 Q(gin with a)-.15 E F1<ad>2.5 E F0(.)A
+F1<ad>144 108 Q F0 1.945(Signal the end of options, cause all remaining)184 108
+R F2(ar)4.444 E(g)-.37 E F0 4.444(st)C 4.444(ob)409.45 108 S 4.444(ea)423.894
+108 S 1.944(ssigned to the positional)437.218 108 R 3.445(parameters. The)184
+120 R F1<ad78>3.445 E F0(and)3.445 E F1<ad76>3.445 E F0 .945
+(options are turned of)3.445 F 3.445(f. If)-.25 F .946(there are no)3.445 F F2
+(ar)3.446 E(g)-.37 E F0 .946(s, the positional)B(parameters remain unchanged.)
+184 132 Q .317(The \215ags are of)144 148.8 R 2.817(fb)-.25 G 2.817(yd)218.328
+148.8 S(ef)231.145 148.8 Q .317(ault unless otherwise noted.)-.1 F .316
+(Using + rather than \255 causes these \215ags to be)5.317 F .198(turned of)144
+160.8 R 2.698(f. The)-.25 F .199
+(\215ags can also be speci\214ed as options to an in)2.699 F -.2(vo)-.4 G .199
+(cation of the shell.).2 F .199(The current set)5.199 F .643
+(of \215ags may be found in)144 172.8 R F1<24ad>3.143 E F0 5.642(.A)C .642
+(fter the option ar)273.91 172.8 R .642(guments are processed, the remaining)
+-.18 F F2 3.142(na)3.142 G -.37(rg)512.238 172.8 S F0 3.142(sa).37 G(re)532.23
+172.8 Q .775(treated as v)144 184.8 R .775
+(alues for the positional parameters and are assigned, in order)-.25 F 3.275
+(,t)-.4 G(o)448.69 184.8 Q F1($1)3.275 E F0(,)A F1($2)3.275 E F0(,)A F1 3.275
+(... $)3.275 F F2(n)A F0 5.775(.I)C 3.275(fn)523.395 184.8 S(o)535 184.8 Q .309
+(options or)144 196.8 R F2(ar)2.809 E(g)-.37 E F0 2.808(sa)C .308
+(re supplied, all shell v)212.056 196.8 R .308(ariables are printed.)-.25 F
+.308(The return status is al)5.308 F -.1(wa)-.1 G .308(ys true unless).1 F
+(an ille)144 208.8 Q -.05(ga)-.15 G 2.5(lo).05 G(ption is encountered.)188.24
+208.8 Q F1(shift)108 225.6 Q F0([)2.5 E F2(n)A F0(])A .428
+(The positional parameters from)144 237.6 R F2(n)2.928 E F0 .429
+(+1 ... are renamed to)B F1 .429($1 ....)2.929 F F0 -.15(Pa)5.429 G .429
+(rameters represented by the num-).15 F(bers)144 249.6 Q F1($#)3.434 E F0(do)
+3.434 E .934(wn to)-.25 F F1($#)3.434 E F0<ad>A F2(n)A F0 .934(+1 are unset.)B
+(If)5.934 E F2(n)3.433 E F0 .933(is 0, no parameters are changed.)3.433 F(If)
+5.933 E F2(n)3.433 E F0 .933(is not gi)3.433 F -.15(ve)-.25 G .933(n, it is).15
+F .026(assumed to be 1.)144 261.6 R F2(n)5.026 E F0 .026(must be a non-ne)2.526
+F -.05(ga)-.15 G(ti).05 E .326 -.15(ve n)-.25 H .026
+(umber less than or equal to).15 F F1($#)2.526 E F0 5.026(.I)C(f)454.886 261.6
+Q F2(n)2.526 E F0 .027(is greater than)2.527 F F1($#)2.527 E F0(,)A .03
+(the positional parameters are not changed.)144 273.6 R .029
+(The return status is greater than 0 if)5.03 F F2(n)2.529 E F0 .029
+(is greater than)2.529 F F1($#)2.529 E F0(or less than 0; otherwise 0.)144
+285.6 Q F1(suspend)108 302.4 Q F0([)2.5 E F1<ad66>A F0(])A .492(Suspend the e)
+144 314.4 R -.15(xe)-.15 G .492(cution of this shell until it recei).15 F -.15
+(ve)-.25 G 2.992(sa).15 G/F3 9/Times-Bold@0 SF(SIGCONT).001 E F0 2.993
+(signal. The)2.743 F F1<ad66>2.993 E F0 .493(option says not to)2.993 F .759
+(complain if this is a login shell; just suspend an)144 326.4 R(yw)-.15 E(ay)
+-.1 E 5.758(.T)-.65 G .758(he return status is 0 unless the shell is a)375.688
+326.4 R(login shell and)144 338.4 Q F1<ad66>2.5 E F0
+(is not supplied, or if job control is not enabled.)2.5 E F1(test)108 355.2 Q
+F2 -.2(ex)2.5 G(pr).2 E F1([)108 367.2 Q F2 -.2(ex)2.5 G(pr).2 E F1(])2.5 E F0
+.877(Return a status of 0 \(true\) or 1 \(f)6.77 F .878
+(alse\) depending on the e)-.1 F -.25(va)-.25 G .878
+(luation of the conditional e).25 F(xpression)-.15 E F2 -.2(ex)144 379.2 S(pr)
+.2 E F0 5.008(.E).73 G .008(xpressions may be unary or binary)175.918 379.2 R
+5.007(.U)-.65 G .007(nary e)328.064 379.2 R .007
+(xpressions are often used to e)-.15 F .007(xamine the status)-.15 F .203
+(of a \214le.)144 391.2 R .203
+(There are string operators and numeric comparison operators as well.)5.203 F
+.204(Each operator and)5.204 F 1.592(operand must be a separate ar)144 403.2 R
+4.091(gument. If)-.18 F F2(\214le)4.091 E F0 1.591(is of the form /de)4.091 F
+(v/fd/)-.25 E F2(n)A F0 4.091(,t)C 1.591(hen \214le descriptor)444.756 403.2 R
+F2(n)4.091 E F0(is)4.091 E(check)144 415.2 Q(ed.)-.1 E F1<ad62>144 427.2 Q F2
+(\214le)2.5 E F0 -.35(Tr)180 427.2 S(ue if).35 E F2(\214le)2.5 E F0 -.15(ex)2.5
+G(ists and is block special.).15 E F1<ad63>144 439.2 Q F2(\214le)2.5 E F0 -.35
+(Tr)180 439.2 S(ue if).35 E F2(\214le)2.5 E F0 -.15(ex)2.5 G
+(ists and is character special.).15 E F1<ad64>144 451.2 Q F2(\214le)2.5 E F0
+-.35(Tr)180 451.2 S(ue if).35 E F2(\214le)2.5 E F0 -.15(ex)2.5 G
+(ists and is a directory).15 E(.)-.65 E F1<ad65>144 463.2 Q F2(\214le)2.5 E F0
+-.35(Tr)180 463.2 S(ue if).35 E F2(\214le)2.5 E F0 -.15(ex)2.5 G(ists.).15 E F1
+<ad66>144 475.2 Q F2(\214le)2.5 E F0 -.35(Tr)180 475.2 S(ue if).35 E F2(\214le)
+2.5 E F0 -.15(ex)2.5 G(ists and is a re).15 E(gular \214le.)-.15 E F1<ad67>144
+487.2 Q F2(\214le)2.5 E F0 -.35(Tr)180 487.2 S(ue if).35 E F2(\214le)2.5 E F0
+-.15(ex)2.5 G(ists and is set-group-id.).15 E F1<ad6b>144 499.2 Q F2(\214le)2.5
+E F0 -.35(Tr)180 499.2 S(ue if).35 E F2(\214le)2.5 E F0(has its `)2.5 E(`stick)
+-.74 E(y')-.15 E 2.5('b)-.74 G(it set.)295.22 499.2 Q F1<ad4c>144 511.2 Q F2
+(\214le)2.5 E F0 -.35(Tr)8.91 G(ue if).35 E F2(\214le)2.5 E F0 -.15(ex)2.5 G
+(ists and is a symbolic link.).15 E F1<ad70>144 523.2 Q F2(\214le)2.5 E F0 -.35
+(Tr)180 523.2 S(ue if).35 E F2(\214le)2.5 E F0 -.15(ex)2.5 G
+(ists and is a named pipe.).15 E F1<ad72>144 535.2 Q F2(\214le)2.5 E F0 -.35
+(Tr)180 535.2 S(ue if).35 E F2(\214le)2.5 E F0 -.15(ex)2.5 G
+(ists and is readable.).15 E F1<ad73>144 547.2 Q F2(\214le)2.5 E F0 -.35(Tr)180
+547.2 S(ue if).35 E F2(\214le)2.5 E F0 -.15(ex)2.5 G
+(ists and has a size greater than zero.).15 E F1<ad53>144 559.2 Q F2(\214le)2.5
+E F0 -.35(Tr)180 559.2 S(ue if).35 E F2(\214le)2.5 E F0 -.15(ex)2.5 G
+(ists and is a sock).15 E(et.)-.1 E F1<ad74>144 571.2 Q F2(fd)2.5 E F0 -.35(Tr)
+180 571.2 S(ue if).35 E F2(fd)2.5 E F0(is opened on a terminal.)2.5 E F1<ad75>
+144 583.2 Q F2(\214le)2.5 E F0 -.35(Tr)180 583.2 S(ue if).35 E F2(\214le)2.5 E
+F0 -.15(ex)2.5 G(ists and its set-user).15 E(-id bit is set.)-.2 E F1<ad77>144
+595.2 Q F2(\214le)2.5 E F0 -.35(Tr)8.36 G(ue if).35 E F2(\214le)2.5 E F0 -.15
+(ex)2.5 G(ists and is writable.).15 E F1<ad78>144 607.2 Q F2(\214le)2.5 E F0
+-.35(Tr)180 607.2 S(ue if).35 E F2(\214le)2.5 E F0 -.15(ex)2.5 G(ists and is e)
+.15 E -.15(xe)-.15 G(cutable.).15 E F1<ad4f>144 619.2 Q F2(\214le)2.5 E F0 -.35
+(Tr)7.8 G(ue if).35 E F2(\214le)2.5 E F0 -.15(ex)2.5 G(ists and is o).15 E
+(wned by the ef)-.25 E(fecti)-.25 E .3 -.15(ve u)-.25 H(ser id.).15 E F1<ad47>
+144 631.2 Q F2(\214le)2.5 E F0 -.35(Tr)7.8 G(ue if).35 E F2(\214le)2.5 E F0
+-.15(ex)2.5 G(ists and is o).15 E(wned by the ef)-.25 E(fecti)-.25 E .3 -.15
+(ve g)-.25 H(roup id.).15 E F2(\214le1)144 643.2 Q F0<ad>2.5 E F1(nt)A F2
+(\214le2)2.5 E F0 -.35(Tr)180 655.2 S(ue if).35 E F2(\214le1)2.5 E F0(is ne)2.5
+E(wer \(according to modi\214cation date\) than)-.25 E F2(\214le2)2.5 E F0(.)A
+F2(\214le1)144 667.2 Q F0<ad>2.5 E F1(ot)A F2(\214le2)2.5 E F0 -.35(Tr)180
+679.2 S(ue if).35 E F2(\214le1)2.5 E F0(is older than \214le2.)2.5 E F2
+(\214le1)144 691.2 Q F1(\255ef)2.5 E F2(\214le)2.5 E F0 -.35(Tr)180 703.2 S
+(ue if).35 E F2(\214le1)2.5 E F0(and)2.5 E F2(\214le2)2.5 E F0(ha)2.5 E .3 -.15
+(ve t)-.2 H(he same de).15 E(vice and inode numbers.)-.25 E 185.675(GNU 1995)72
+768 R(May 5)2.5 E(33)530 768 Q EP
+%%Page: 34 34
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF<ad7a>144 84 Q/F2 10/Times-Italic@0 SF(string)2.5 E F0
+-.35(Tr)180 96 S(ue if the length of).35 E F2(string)2.5 E F0(is zero.)2.5 E F1
+<ad6e>144 108 Q F2(string)2.5 E(string)144 120 Q F0 -.35(Tr)180 120 S
+(ue if the length of).35 E F2(string)2.5 E F0(is non\255zero.)2.5 E F2(string1)
+144 132 Q F1(=)2.5 E F2(string2)2.5 E F0 -.35(Tr)180 144 S
+(ue if the strings are equal.).35 E F2(string1)144 156 Q F1(!=)2.5 E F2
+(string2)2.5 E F0 -.35(Tr)180 168 S(ue if the strings are not equal.).35 E F1
+(!)144 180 Q F2 -.2(ex)2.5 G(pr).2 E F0 -.35(Tr)180 180 S(ue if).35 E F2 -.2
+(ex)2.5 G(pr).2 E F0(is f)2.5 E(alse.)-.1 E F2 -.2(ex)144 192 S(pr1).2 E F0<ad>
+2.5 E F1(a)A F2 -.2(ex)2.5 G(pr2).2 E F0 -.35(Tr)180 204 S(ue if both).35 E F2
+-.2(ex)2.5 G(pr1).2 E F0(AND)2.5 E F2 -.2(ex)2.5 G(pr2).2 E F0(are true.)2.5 E
+F2 -.2(ex)144 216 S(pr1).2 E F0<ad>2.5 E F1(o)A F2 -.2(ex)2.5 G(pr2).2 E F0
+-.35(Tr)180 228 S(ue if either).35 E F2 -.2(ex)2.5 G(pr1).2 E F0(OR)2.5 E F2
+-.2(ex)2.5 G(pr2).2 E F0(is true.)2.5 E F2(ar)144 240 Q(g1)-.37 E F1(OP)2.5 E
+F2(ar)2.5 E(g2)-.37 E/F3 9/Times-Bold@0 SF(OP)180 252 Q F0 .035(is one of)2.284
+F F1(\255eq)2.535 E F0(,)A F1(\255ne)2.535 E F0(,)A F1(\255lt)2.535 E F0(,)A F1
+(\255le)2.535 E F0(,)A F1(\255gt)2.535 E F0 2.535(,o)C(r)332.165 252 Q F1
+(\255ge)2.535 E F0 5.035(.T)C .035
+(hese arithmetic binary operators return true)366.815 252 R(if)180 264 Q F2(ar)
+3.32 E(g1)-.37 E F0 .82(is equal, not-equal, less-than, less-than-or)3.32 F .82
+(-equal, greater)-.2 F .82(-than, or greater)-.2 F(-than-or)-.2 E(-)-.2 E .5
+(equal than)180 276 R F2(ar)3 E(g2)-.37 E F0 3.001(,r)C(especti)252.231 276 Q
+-.15(ve)-.25 G(ly).15 E(.)-.65 E F2(Ar)5.501 E(g1)-.37 E F0(and)3.001 E F2(ar)
+3.001 E(g2)-.37 E F0 .501(may be positi)3.001 F .801 -.15(ve i)-.25 H(nte).15 E
+.501(gers, ne)-.15 F -.05(ga)-.15 G(ti).05 E .801 -.15(ve i)-.25 H(nte).15 E
+(gers,)-.15 E(or the special e)180 288 Q(xpression)-.15 E F1<ad6c>2.5 E F2
+(string)2.5 E F0 2.5(,w)C(hich e)327.48 288 Q -.25(va)-.25 G
+(luates to the length of).25 E F2(string)2.5 E F0(.).22 E F1(times)108 304.8 Q
+F0 1.229(Print the accumulated user and system times for the shell and for pro\
+cesses run from the shell.)144 304.8 R(The return status is 0.)144 316.8 Q F1
+(trap)108 333.6 Q F0([)2.5 E F1<ad6c>A F0 2.5(][)C F2(ar)149.8 333.6 Q(g)-.37 E
+F0 2.5(][)C F2(sigspec)172.48 333.6 Q F0(])A .767(The command)144 345.6 R F2
+(ar)3.267 E(g)-.37 E F0 .767(is to be read and e)3.267 F -.15(xe)-.15 G .767
+(cuted when the shell recei).15 F -.15(ve)-.25 G 3.267(ss).15 G(ignal\(s\))
+434.781 345.6 Q F2(sigspec)3.267 E F0 5.767(.I).31 G(f)509.945 345.6 Q F2(ar)
+3.267 E(g)-.37 E F0(is)3.268 E 2.164(absent or)144 357.6 R F1<ad>4.664 E F0
+4.664(,a)C 2.164(ll speci\214ed signals are reset to their original v)204.512
+357.6 R 2.164(alues \(the v)-.25 F 2.163(alues the)-.25 F 4.663(yh)-.15 G 2.163
+(ad upon)505.897 357.6 R .681(entrance to the shell\).)144 369.6 R(If)5.681 E
+F2(ar)3.181 E(g)-.37 E F0 .681
+(is the null string this signal is ignored by the shell and by the com-)3.181 F
+1.174(mands it in)144 381.6 R -.2(vo)-.4 G -.1(ke).2 G(s.).1 E F2(sigspec)6.174
+E F0 1.174(is either a signal name de\214ned in <)3.674 F F2(signal.h)A F0
+1.173(>, or a signal number)B 6.173(.I)-.55 G(f)536.67 381.6 Q F2(sigspec)144
+393.6 Q F0(is)2.769 E F3(EXIT)2.769 E F0 .269(\(0\) the command)2.519 F F2(ar)
+2.769 E(g)-.37 E F0 .269(is e)2.769 F -.15(xe)-.15 G .269(cuted on e).15 F .269
+(xit from the shell.)-.15 F -.4(Wi)5.269 G .269(th no ar).4 F(guments,)-.18 E
+F1(trap)2.77 E F0 .403
+(prints the list of commands associated with each signal number)144 405.6 R
+5.402(.T)-.55 G(he)414.118 405.6 Q F1<ad6c>2.902 E F0 .402
+(option causes the shell to)2.902 F .562
+(print a list of signal names and their corresponding numbers.)144 417.6 R .562
+(An ar)5.562 F .562(gument of)-.18 F F1<adad>3.062 E F0 .562(disables option)
+3.062 F .564(checking for the rest of the ar)144 429.6 R 3.064
+(guments. Signals)-.18 F .564
+(ignored upon entry to the shell cannot be trapped)3.064 F 1.144(or reset.)144
+441.6 R -.35(Tr)6.144 G 1.145(apped signals are reset to their original v).35 F
+1.145(alues in a child process when it is created.)-.25 F
+(The return status is f)144 453.6 Q
+(alse if either the trap name or number is in)-.1 E -.25(va)-.4 G
+(lid; otherwise).25 E F1(trap)2.5 E F0(returns true.)2.5 E F1(type)108 470.4 Q
+F0([)2.5 E F1(\255all)A F0 2.5(][)C F1(\255type)157.58 470.4 Q F0(|)2.5 E F1
+(\255path)2.5 E F0(])A F2(name)2.5 E F0([)2.5 E F2(name)A F0(...])2.5 E -.4(Wi)
+144 482.4 S .206(th no options, indicate ho).4 F 2.706(we)-.25 G(ach)272.15
+482.4 Q F2(name)2.705 E F0 -.1(wo)2.705 G .205
+(uld be interpreted if used as a command name.).1 F .205(If the)5.205 F F1
+(\255type)144 494.4 Q F0 .527(\215ag is used,)3.027 F F1(type)3.027 E F0 .528
+(prints a phrase which is one of)3.028 F F2(alias)3.028 E F0(,).27 E F2 -.1(ke)
+3.028 G(ywor)-.2 E(d)-.37 E F0(,).77 E F2(function)3.028 E F0(,).24 E F2 -.2
+(bu)3.028 G(iltin).2 E F0 3.028(,o).24 G(r)512.284 494.4 Q F2(\214le)3.028 E F0
+(if)3.028 E F2(name)144 506.4 Q F0 .297(is an alias, shell reserv)2.798 F .297
+(ed w)-.15 F .297(ord, function, b)-.1 F .297(uiltin, or disk \214le, respecti)
+-.2 F -.15(ve)-.25 G(ly).15 E 2.797(.I)-.65 G 2.797(ft)472.152 506.4 S .297
+(he name is not)481.059 506.4 R 1.097(found, then nothing is printed, and an e)
+144 518.4 R 1.097(xit status of f)-.15 F 1.097(alse is returned.)-.1 F 1.097
+(If the)6.097 F F1(\255path)3.598 E F0 1.098(\215ag is used,)3.598 F F1(type)
+144 530.4 Q F0 1.009(either returns the name of the disk \214le that w)3.509 F
+1.008(ould be e)-.1 F -.15(xe)-.15 G 1.008(cuted if).15 F F2(name)3.508 E F0
+1.008(were speci\214ed as a)3.508 F .562(command name, or nothing if)144 542.4
+R F1(\255type)3.062 E F0 -.1(wo)3.062 G .562(uld not return).1 F F2(\214le)
+3.063 E F0 5.563(.I).18 G 3.063(fac)389.542 542.4 S .563(ommand is hashed,)
+407.878 542.4 R F1(\255path)3.063 E F0(prints)3.063 E .684(the hashed v)144
+554.4 R .684(alue, not necessarily the \214le that appears \214rst in)-.25 F F3
+-.666(PA)3.184 G(TH)-.189 E/F4 9/Times-Roman@0 SF(.)A F0 .684(If the)5.184 F F1
+(\255all)3.184 E F0 .683(\215ag is used,)3.184 F F1(type)3.183 E F0 1.135
+(prints all of the places that contain an e)144 566.4 R -.15(xe)-.15 G 1.135
+(cutable named).15 F F2(name)3.635 E F0 6.136(.T).18 G 1.136
+(his includes aliases and func-)418.256 566.4 R 1.011
+(tions, if and only if the)144 578.4 R F1(\255path)3.511 E F0 1.011
+(\215ag is not also used.)3.511 F 1.011
+(The table of hashed commands is not con-)6.011 F .786(sulted when using)144
+590.4 R F1(\255all)3.286 E F0(.)A F1(type)5.786 E F0(accepts)3.286 E F1<ad61>
+3.286 E F0(,)A F1<ad74>3.286 E F0 3.286(,a)C(nd)335.698 590.4 Q F1<ad70>3.286 E
+F0 .787(in place of)3.287 F F1(\255all)3.287 E F0(,)A F1(\255type)3.287 E F0
+3.287(,a)C(nd)466.906 590.4 Q F1(\255path)3.287 E F0 3.287(,r)C(espec-)514.46
+590.4 Q(ti)144 602.4 Q -.15(ve)-.25 G(ly).15 E 6.127(.A)-.65 G 3.627(na)181.577
+602.4 S -.18(rg)194.644 602.4 S 1.127(ument of).18 F F1<adad>3.627 E F0 1.127
+(disables option checking for the rest of the ar)3.627 F(guments.)-.18 E F1
+(type)6.126 E F0(returns)3.626 E(true if an)144 614.4 Q 2.5(yo)-.15 G 2.5(ft)
+192.45 614.4 S(he ar)201.06 614.4 Q(guments are found, f)-.18 E
+(alse if none are found.)-.1 E F1(ulimit)108 631.2 Q F0([)2.5 E F1
+(\255SHacdfmstpnuv)A F0([)2.5 E F2(limit)A F0(]])A F1(Ulimit)144 643.2 Q F0
+(pro)3.056 E .556(vides control o)-.15 F -.15(ve)-.15 G 3.057(rt).15 G .557
+(he resources a)266.316 643.2 R -.25(va)-.2 G .557
+(ilable to the shell and to processes started by it, on).25 F .765
+(systems that allo)144 655.2 R 3.265(ws)-.25 G .765(uch control.)226.325 655.2
+R .765(The v)5.765 F .765(alue of)-.25 F F2(limit)3.265 E F0 .765
+(can be a number in the unit speci\214ed for the)3.265 F .301
+(resource, or the v)144 667.2 R(alue)-.25 E F1(unlimited)2.801 E F0 5.301(.T)C
+(he)288.565 667.2 Q F1(H)2.801 E F0(and)2.801 E F1(S)2.801 E F0 .302
+(options specify that the hard or soft limit is set for)2.802 F .005(the gi)144
+679.2 R -.15(ve)-.25 G 2.505(nr).15 G 2.505(esource. A)186.38 679.2 R .004(har\
+d limit cannot be increased once it is set; a soft limit may be increased up)
+2.505 F .008(to the v)144 691.2 R .008(alue of the hard limit.)-.25 F .008
+(If neither)5.008 F F1(H)2.508 E F0(nor)2.508 E F1(S)2.508 E F0 .008
+(is speci\214ed, the command applies to the soft limit.)2.508 F(If)144 703.2 Q
+F2(limit)2.758 E F0 .258(is omitted, the current v)2.758 F .257
+(alue of the soft limit of the resource is printed, unless the)-.25 F F1(H)
+2.757 E F0(option)2.757 E .575(is gi)144 715.2 R -.15(ve)-.25 G 3.075(n. When)
+.15 F .576(more than one resource is speci\214ed, the limit name and unit is p\
+rinted before the)3.076 F -.25(va)144 727.2 S 2.5(lue. Other).25 F
+(options are interpreted as follo)2.5 E(ws:)-.25 E 185.675(GNU 1995)72 768 R
+(May 5)2.5 E(34)530 768 Q EP
+%%Page: 35 35
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+/F1 10/Times-Bold@0 SF<ad61>144 84 Q F0(all current limits are reported)180 84
+Q F1<ad63>144 96 Q F0(the maximum size of core \214les created)180 96 Q F1
+<ad64>144 108 Q F0(the maximum size of a process')180 108 Q 2.5(sd)-.55 G
+(ata se)317.76 108 Q(gment)-.15 E F1<ad66>144 120 Q F0
+(the maximum size of \214les created by the shell)180 120 Q F1<ad6d>144 132 Q
+F0(the maximum resident set size)180 132 Q F1<ad73>144 144 Q F0
+(the maximum stack size)180 144 Q F1<ad74>144 156 Q F0
+(the maximum amount of cpu time in seconds)180 156 Q F1<ad70>144 168 Q F0
+(the pipe size in 512-byte blocks \(this may not be set\))180 168 Q F1<ad6e>144
+180 Q F0 .164
+(the maximum number of open \214le descriptors \(most systems do not allo)180
+180 R 2.664(wt)-.25 G .164(his v)481.708 180 R .164(alue to be)-.25 F
+(set, only displayed\))180 192 Q F1<ad75>144 204 Q F0
+(the maximum number of processes a)180 204 Q -.25(va)-.2 G
+(ilable to a single user).25 E F1<ad76>144 216 Q F0
+(The maximum amount of virtual memory a)180 216 Q -.25(va)-.2 G
+(ilable to the shell).25 E .778(An ar)144 232.8 R .778(gument of)-.18 F F1
+<adad>3.278 E F0 .778(disables option checking for the rest of the ar)3.278 F
+3.279(guments. If)-.18 F/F2 10/Times-Italic@0 SF(limit)3.279 E F0 .779(is gi)
+3.279 F -.15(ve)-.25 G .779(n, it is).15 F .394(the ne)144 244.8 R 2.894(wv)
+-.25 G .394(alue of the speci\214ed resource \(the)183.168 244.8 R F1<ad61>
+2.893 E F0 .393(option is display only\).)2.893 F .393(If no option is gi)5.393
+F -.15(ve)-.25 G .393(n, then).15 F F1<ad66>144 256.8 Q F0 .43(is assumed.)2.93
+F -1.11(Va)5.43 G .43(lues are in 1024-byte increments, e)1.11 F .431
+(xcept for)-.15 F F1<ad74>2.931 E F0 2.931(,w)C .431(hich is in seconds,)
+421.315 256.8 R F1<ad70>2.931 E F0 2.931(,w)C(hich)522.78 256.8 Q .828
+(is in units of 512-byte blocks, and)144 268.8 R F1<ad6e>3.327 E F0(and)3.327 E
+F1<ad75>3.327 E F0 3.327(,w)C .827(hich are unscaled v)344.784 268.8 R 3.327
+(alues. The)-.25 F .827(return status is 0)3.327 F .621(unless an ille)144
+280.8 R -.05(ga)-.15 G 3.121(lo).05 G .621
+(ption is encountered, a non-numeric ar)217.603 280.8 R .622(gument other than)
+-.18 F F1(unlimited)3.122 E F0 .622(is supplied)3.122 F(as)144 292.8 Q F2
+(limit)2.5 E F0 2.5(,o)C 2.5(ra)183.17 292.8 S 2.5(ne)193.44 292.8 S
+(rror occurs while setting a ne)205.38 292.8 Q 2.5(wl)-.25 G(imit.)333.99 292.8
+Q F1(umask)108 309.6 Q F0([)2.5 E F1<ad53>A F0 2.5(][)C F2(mode)162.59 309.6 Q
+F0(])A .23(The user \214le-creation mask is set to)144 321.6 R F2(mode)2.73 E
+F0 5.23(.I).18 G(f)323.21 321.6 Q F2(mode)2.73 E F0(be)2.729 E .229
+(gins with a digit, it is interpreted as an octal)-.15 F .066(number; otherwis\
+e it is interpreted as a symbolic mode mask similar to that accepted by)144
+333.6 R F2 -.15(ch)2.566 G(mod).15 E F0(\(1\).).77 E(If)144 345.6 Q F2(mode)
+2.55 E F0 .05(is omitted, or if the)2.55 F F1<ad53>2.55 E F0 .049
+(option is supplied, the current v)2.55 F .049(alue of the mask is printed.)
+-.25 F(The)5.049 E F1<ad53>2.549 E F0 .475
+(option causes the mask to be printed in symbolic form; the def)144 357.6 R
+.475(ault output is an octal number)-.1 F 5.475(.A)-.55 G(n)535 357.6 Q(ar)144
+369.6 Q .125(gument of)-.18 F F1<adad>2.625 E F0 .125
+(disables option checking for the rest of the ar)2.625 F 2.624(guments. The)
+-.18 F .124(return status is 0 if the)2.624 F(mode w)144 381.6 Q
+(as successfully changed or if no)-.1 E F2(mode)2.5 E F0(ar)2.5 E(gument w)-.18
+E(as supplied, and f)-.1 E(alse otherwise.)-.1 E F1(unalias)108 398.4 Q F0
+<5bad>2.5 E F1(a)A F0 2.5(][)C F2(name)164.2 398.4 Q F0(...])2.5 E(Remo)144
+410.4 Q -.15(ve)-.15 G F2(name)2.882 E F0 2.732(sf)C .232
+(rom the list of de\214ned aliases.)211.374 410.4 R(If)5.232 E F1<ad61>2.733 E
+F0 .233(is supplied, all alias de\214nitions are remo)2.733 F -.15(ve)-.15 G
+(d.).15 E(The return v)144 422.4 Q(alue is true unless a supplied)-.25 E F2
+(name)2.5 E F0(is not a de\214ned alias.)2.5 E F1(unset)108 439.2 Q F0<5bad>2.5
+E F1(fv)A F0 2.5(][)C F2(name)159.74 439.2 Q F0(...])2.5 E -.15(Fo)144 451.2 S
+2.773(re).15 G(ach)164.953 451.2 Q F2(name)2.773 E F0 2.773(,r).18 G(emo)
+212.049 451.2 Q .573 -.15(ve t)-.15 H .273(he corresponding v).15 F .273
+(ariable or)-.25 F 2.773(,g)-.4 G -2.15 -.25(iv e)369.094 451.2 T 2.773(nt).25
+G(he)391.467 451.2 Q F1<ad66>2.773 E F0 .273(option, function.)2.773 F .272
+(An ar)5.272 F(gument)-.18 E(of)144 463.2 Q F1<adad>2.58 E F0 .08
+(disables option checking for the rest of the ar)2.58 F 2.58(guments. Note)-.18
+F(that)2.58 E/F3 9/Times-Bold@0 SF -.666(PA)2.58 G(TH)-.189 E/F4 9
+/Times-Roman@0 SF(,)A F3(IFS)2.33 E F4(,)A F3(PPID)2.33 E F4(,)A F3(PS1)2.331 E
+F4(,)A F3(PS2)2.331 E F4(,)A F3(UID)144 475.2 Q F4(,)A F0(and)4.074 E F3(EUID)
+4.324 E F0 1.824(cannot be unset.)4.074 F 1.824(If an)6.824 F 4.323(yo)-.15 G
+(f)321.938 475.2 Q F3(RANDOM)4.323 E F4(,)A F3(SECONDS)4.073 E F4(,)A F3
+(LINENO)4.073 E F4(,)A F0(or)4.073 E F3(HISTCMD)4.323 E F0(are)4.073 E .328
+(unset, the)144 487.2 R 2.828(yl)-.15 G .328(ose their special properties, e)
+193.116 487.2 R -.15(ve)-.25 G 2.828(ni).15 G 2.828(ft)330.436 487.2 S(he)
+339.374 487.2 Q 2.828(ya)-.15 G .328(re subsequently reset.)360.932 487.2 R
+.328(The e)5.328 F .329(xit status is true)-.15 F(unless a)144 499.2 Q F2(name)
+2.5 E F0(does not e)2.5 E(xist or is non-unsettable.)-.15 E F1(wait)108 516 Q
+F0([)2.5 E F2(n)A F0(])A -.8(Wa)144 528 S 1.061
+(it for the speci\214ed process and return its termination status.).8 F F2(n)
+6.061 E F0 1.06(may be a process ID or a job)3.56 F .753
+(speci\214cation; if a job spec is gi)144 540 R -.15(ve)-.25 G .754
+(n, all processes in that job').15 F 3.254(sp)-.55 G .754(ipeline are w)404.012
+540 R .754(aited for)-.1 F 5.754(.I)-.55 G(f)502.458 540 Q F2(n)3.254 E F0 .754
+(is not)3.254 F(gi)144 552 Q -.15(ve)-.25 G .027(n, all currently acti).15 F
+.327 -.15(ve c)-.25 H .027(hild processes are w).15 F .027(aited for)-.1 F
+2.526(,a)-.4 G .026(nd the return status is zero.)375.932 552 R(If)5.026 E F2
+(n)2.526 E F0(speci\214es)2.526 E 2.595(an)144 564 S(on-e)156.035 564 Q .095
+(xistant process or job, the return status is 127.)-.15 F .096
+(Otherwise, the return status is the e)5.095 F .096(xit status)-.15 F
+(of the last process or job w)144 576 Q(aited for)-.1 E(.)-.55 E F3(INV)72
+592.8 Q(OCA)-.405 E(TION)-.855 E F0(A)108 604.8 Q F2(lo)2.5 E(gin shell)-.1 E
+F0(is one whose \214rst character of ar)2.5 E(gument zero is a)-.18 E F1<ad>2.5
+E F0 2.5(,o)C 2.5(ro)375.87 604.8 S(ne started with the)386.7 604.8 Q F1
+(\255login)2.5 E F0(\215ag.)2.5 E(An)108 621.6 Q F2(inter)2.812 E(active)-.15 E
+F0 .312(shell is one whose standard input and output are both connected to ter\
+minals \(as determined)2.812 F(by)108 633.6 Q F2(isatty)2.57 E F0 .07
+(\(3\)\), or one started with the).32 F F1<ad69>2.57 E F0(option.)2.57 E F3
+(PS1)5.07 E F0 .07(is set and)2.32 F F1<24ad>2.57 E F0(includes)2.57 E F1(i)
+2.571 E F0(if)2.571 E F1(bash)2.571 E F0 .071(is interacti)2.571 F -.15(ve)-.25
+G 2.571(,a).15 G(llo)502.679 633.6 Q .071(wing a)-.25 F
+(shell script or a startup \214le to test this state.)108 645.6 Q
+(Login shells:)108 662.4 Q(On login \(subject to the)113 674.4 Q F1(\255nopr)
+2.5 E(o\214le)-.18 E F0(option\):)2.5 E(if)128 686.4 Q F2(/etc/pr)2.5 E
+(o\214le)-.45 E F0 -.15(ex)2.5 G(ists, source it.).15 E(if)128 710.4 Q F2
+(~/.bash_pr)2.5 E(o\214le)-.45 E F0 -.15(ex)2.5 G(ists, source it,).15 E
+(else if)133 722.4 Q F2(~/.bash_lo)2.5 E(gin)-.1 E F0 -.15(ex)2.5 G
+(ists, source it,).15 E 185.675(GNU 1995)72 768 R(May 5)2.5 E(35)530 768 Q EP
+%%Page: 36 36
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+(else if)138 84 Q/F1 10/Times-Italic@0 SF(~/.pr)2.5 E(o\214le)-.45 E F0 -.15
+(ex)2.5 G(ists, source it.).15 E(On e)113 108 Q(xit:)-.15 E(if)128 120 Q F1
+(~/.bash_lo)2.5 E(gout)-.1 E F0 -.15(ex)2.5 G(ists, source it.).15 E
+(Non-login interacti)108 144 Q .3 -.15(ve s)-.25 H(hells:).15 E
+(On startup \(subject to the)113 156 Q/F2 10/Times-Bold@0 SF(\255nor)2.5 E(c)
+-.18 E F0(and)2.5 E F2<ad72>2.5 E(c\214le)-.18 E F0(options\):)2.5 E(if)128 168
+Q F1(~/.bashr)2.5 E(c)-.37 E F0 -.15(ex)2.5 G(ists, source it.).15 E
+(Non-interacti)108 192 Q .3 -.15(ve s)-.25 H(hells:).15 E(On startup:)113 204 Q
+(if the en)128 216 Q(vironment v)-.4 E(ariable)-.25 E F2(ENV)2.5 E F0
+(is non-null, e)2.5 E(xpand)-.15 E
+(it and source the \214le it names, as if the command)128 228 Q
+(if [ "$ENV" ]; then . $ENV)148 240 Q 2.5<3b8c>-.74 G(had been e)128 252 Q -.15
+(xe)-.15 G(cuted, b).15 E(ut do not use)-.2 E F2 -.74(PA)2.5 G(TH)-.21 E F0
+(to search)2.5 E(for the pathname.)128 264 Q
+(When not started in Posix mode, bash)5 E(looks for)128 276 Q F2 -.3(BA)2.5 G
+(SH_ENV).3 E F0(before)2.5 E F2(ENV)2.5 E F0(.)A 1.023(If Bash is in)108 297.6
+R -.2(vo)-.4 G -.1(ke).2 G 3.523(da).1 G(s)191.382 297.6 Q F2(sh)3.523 E F0
+3.523(,i)C 3.523(tt)217.048 297.6 S 1.023(ries to mimic the beha)226.131 297.6
+R 1.023(vior of)-.2 F F2(sh)3.523 E F0 1.023(as closely as possible.)3.523 F
+-.15(Fo)6.022 G 3.522(ral).15 G 1.022(ogin shell, it)488.226 297.6 R .505
+(attempts to source only)108 309.6 R F1(/etc/pr)3.006 E(o\214le)-.45 E F0(and)
+3.006 E F1(~/.pr)3.006 E(o\214le)-.45 E F0 3.006(,i).18 G 3.006(nt)311.64 309.6
+S .506(hat order)322.426 309.6 R 5.506(.T)-.55 G(he)372.318 309.6 Q F2
+(\255nopr)3.006 E(o\214le)-.18 E F0 .506(option may still be used to)3.006 F
+(disable this beha)108 321.6 Q(vior)-.2 E 5(.A)-.55 G(shell in)207.24 321.6 Q
+-.2(vo)-.4 G -.1(ke).2 G 2.5(da).1 G(s)267.09 321.6 Q F2(sh)2.5 E F0
+(does not attempt to source an)2.5 E 2.5(yo)-.15 G(ther startup \214les.)414.71
+321.6 Q(When)108 338.4 Q F2(bash)2.71 E F0 .21(is started in)2.71 F F1(posix)
+2.71 E F0 .21(mode, as with the)2.71 F F2(\255posix)2.709 E F0 .209
+(command line option, it follo)2.709 F .209(ws the Posix standard)-.25 F .187
+(for startup \214les.)108 350.4 R .188(In this mode, the)5.188 F F2(ENV)2.688 E
+F0 -.25(va)2.688 G .188(riable is e).25 F .188
+(xpanded and that \214le sourced; no other startup \214les are)-.15 F(read.)108
+362.4 Q/F3 9/Times-Bold@0 SF(SEE ALSO)72 379.2 Q F1(Bash F)108 391.2 Q(eatur)
+-.75 E(es)-.37 E F0 2.5(,B)C(rian F)176.6 391.2 Q(ox and Chet Rame)-.15 E(y)
+-.15 E F1(The Gnu Readline Libr)108 403.2 Q(ary)-.15 E F0 2.5(,B)C(rian F)
+225.35 403.2 Q(ox and Chet Rame)-.15 E(y)-.15 E F1(The Gnu History Libr)108
+415.2 Q(ary)-.15 E F0 2.5(,B)C(rian F)219.8 415.2 Q(ox and Chet Rame)-.15 E(y)
+-.15 E F1 2.5(AS)108 427.2 S(ystem V Compatible Implementation of 4.2)121.61
+427.2 Q/F4 9/Times-Italic@0 SF(BSD)A F1 -.25(Jo)2.5 G 2.5(bC).25 G(ontr)335.067
+427.2 Q(ol)-.45 E F0 2.5(,D)C -.2(av)371.287 427.2 S(id Lennert).2 E F1 -.8(Po)
+108 439.2 S(rtable Oper).8 E(ating System Interface \(POSIX\) P)-.15 E
+(art 2: Shell and Utilities)-.8 E F0 2.5(,I)C(EEE)404.83 439.2 Q F1(sh)108
+451.2 Q F0(\(1\),)A F1(ksh)2.5 E F0(\(1\),)A F1(csh)2.5 E F0(\(1\))A F1(emacs)
+108 463.2 Q F0(\(1\),)A F1(vi)2.5 E F0(\(1\))A F1 -.37(re)108 475.2 S(adline)
+.37 E F0(\(3\))A F3(FILES)72 492 Q F1(/bin/bash)109.666 504 Q F0(The)144 516 Q
+F2(bash)2.5 E F0 -.15(exe)2.5 G(cutable).15 E F1(/etc/pr)109.666 528 Q(o\214le)
+-.45 E F0(The systemwide initialization \214le, e)144 540 Q -.15(xe)-.15 G
+(cuted for login shells).15 E F1(~/.bash_pr)109.666 552 Q(o\214le)-.45 E F0
+(The personal initialization \214le, e)144 564 Q -.15(xe)-.15 G
+(cuted for login shells).15 E F1(~/.bashr)109.666 576 Q(c)-.37 E F0(The indi)
+144 588 Q(vidual per)-.25 E(-interacti)-.2 E -.15(ve)-.25 G
+(-shell startup \214le).15 E F1(~/.inputr)109.666 600 Q(c)-.37 E F0(Indi)144
+612 Q(vidual)-.25 E F1 -.37(re)2.5 G(adline).37 E F0(initialization \214le)2.5
+E F3 -.45(AU)72 628.8 S(THORS).45 E F0(Brian F)144 640.8 Q(ox, Free Softw)-.15
+E(are F)-.1 E(oundation \(primary author\))-.15 E(bfox@ai.MIT)144 652.8 Q(.Edu)
+-.74 E(Chet Rame)144 669.6 Q 1.3 -.65(y, C)-.15 H(ase W).65 E(estern Reserv)-.8
+E 2.5(eU)-.15 G(ni)296.66 669.6 Q -.15(ve)-.25 G(rsity).15 E(chet@ins.CWR)144
+681.6 Q(U.Edu)-.4 E F3 -.09(BU)72 698.4 S 2.25(GR).09 G(EPOR)100.161 698.4 Q
+(TS)-.36 E F0 .568(If you \214nd a b)108 710.4 R .568(ug in)-.2 F F2(bash,)
+3.068 E F0 .568(you should report it.)3.068 F .568(But \214rst, you should mak)
+5.568 F 3.068(es)-.1 G .568(ure that it really is a b)419.578 710.4 R .567
+(ug, and)-.2 F(that it appears in the latest v)108 722.4 Q(ersion of)-.15 E F2
+(bash)2.5 E F0(that you ha)2.5 E -.15(ve)-.2 G(.).15 E 185.675(GNU 1995)72 768
+R(May 5)2.5 E(36)530 768 Q EP
+%%Page: 37 37
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S 389.54(SH\(1\) B).35 F(ASH\(1\))-.35 E
+.437(Once you ha)108 84 R .737 -.15(ve d)-.2 H .438(etermined that a b).15 F
+.438(ug actually e)-.2 F .438(xists, use the)-.15 F/F1 10/Times-Italic@0 SF
+(bashb)2.938 E(ug)-.2 E F0 .438(command to submit a b)2.938 F .438(ug report.)
+-.2 F(If)5.438 E .454(you ha)108 96 R .754 -.15(ve a \214)-.2 H .453
+(x, you are welcome to mail that as well!).15 F .453
+(Suggestions and `philosophical' b)5.453 F .453(ug reports may be)-.2 F
+(mailed to)108 108 Q F1 -.2(bu)2.5 G(g-bash).2 E F0(@)A F1(pr)A(ep.ai.MIT)-.37
+E(.Edu)-.74 E F0(or posted to the Usenet ne)2.5 E(wsgroup)-.25 E/F2 10
+/Times-Bold@0 SF(gnu.bash.b)2.5 E(ug)-.2 E F0(.)A(ALL b)108 124.8 Q
+(ug reports should include:)-.2 E(The v)108 141.6 Q(ersion number of)-.15 E F2
+(bash)2.5 E F0(The hardw)108 153.6 Q(are and operating system)-.1 E
+(The compiler used to compile)108 165.6 Q 2.5(Ad)108 177.6 S
+(escription of the b)122.72 177.6 Q(ug beha)-.2 E(viour)-.2 E 2.5(As)108 189.6
+S(hort script or `recipe' which e)121.61 189.6 Q -.15(xe)-.15 G(rcises the b)
+.15 E(ug)-.2 E F1(bashb)108 206.4 Q(ug)-.2 E F0
+(inserts the \214rst three items automatically into the template it pro)2.5 E
+(vides for \214ling a b)-.15 E(ug report.)-.2 E(Comments and b)108 223.2 Q
+(ug reports concerning this manual page should be directed to)-.2 E F1 -.15(ch)
+2.5 G(et@ins.CWR).15 E -.25(U.)-.4 G(Edu).25 E F0(.).25 E/F3 9/Times-Bold@0 SF
+-.09(BU)72 240 S(GS).09 E F0(It')108 252 Q 2.5(st)-.55 G(oo big and too slo)
+126.06 252 Q -.65(w.)-.25 G 1.868(There are some subtle dif)108 268.8 R 1.868
+(ferences between)-.25 F F2(bash)4.369 E F0 1.869(and traditional v)4.369 F
+1.869(ersions of)-.15 F F2(sh)4.369 E F0 4.369(,m)C 1.869(ostly because of the)
+455.243 268.8 R F3(POSIX)108 280.8 Q F0(speci\214cation.)2.25 E
+(Aliases are confusing in some uses.)108 297.6 Q 185.675(GNU 1995)72 768 R
+(May 5)2.5 E(37)530 768 Q EP
+%%Trailer
+end
+%%EOF
diff --git a/documentation/bash.txt b/documentation/bash.txt
new file mode 100644 (file)
index 0000000..c23f298
--- /dev/null
@@ -0,0 +1,3960 @@
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+NAME
+     bash - GNU Bourne-Again SHell
+
+SYNOPSIS
+     bash [options] [file]
+
+COPYRIGHT
+     Bash is Copyright (C) 1989, 1991 by the Free Software  Foun-
+     dation, Inc.
+
+DESCRIPTION
+     Bash is an sh-compatible command language  interpreter  that
+     executes  commands  read  from  the standard input or from a
+     file.  Bash also incorporates useful features from the  _\bK_\bo_\br_\bn
+     and _\bC shells (ksh and csh).
+
+     Bash is ultimately intended to be a  conformant  implementa-
+     tion  of  the IEEE Posix Shell and Tools specification (IEEE
+     Working Group 1003.2).
+
+OPTIONS
+     In addition to the single-character shell options documented
+     in  the  description of the set builtin command, bash inter-
+     prets the following flags when it is invoked:
+
+     -c _\bs_\bt_\br_\bi_\bn_\bg If the -c flag is present, then commands are  read
+               from  _\bs_\bt_\br_\bi_\bn_\bg.   If  there  are arguments after the
+               _\bs_\bt_\br_\bi_\bn_\bg, they are assigned to the positional param-
+               eters, starting with $0.
+     -i        If the -i flag is present, the shell  is  _\bi_\bn_\bt_\be_\br_\ba_\bc_\b-
+               _\bt_\bi_\bv_\be.
+     -s        If the -s flag is  present,  or  if  no  arguments
+               remain  after option processing, then commands are
+               read from the standard input.  This option  allows
+               the  positional parameters to be set when invoking
+               an interactive shell.
+     -         A single - signals the end of options and disables
+               further  option  processing.   Any arguments after
+               the - are treated as filenames and arguments.   An
+               argument of -- is equivalent to an argument of -.
+
+     Bash also interprets a number  of  multi-character  options.
+     These  options  must  appear  on the command line before the
+     single-character options to be recognized.
+
+     -norc     Do not read and execute the  personal  initializa-
+               tion  file  ~/._\bb_\ba_\bs_\bh_\br_\bc if the shell is interactive.
+               This option is on  by  default  if  the  shell  is
+               invoked as sh.
+     -noprofile
+               Do not read either the  system-wide  startup  file
+               /_\be_\bt_\bc/_\bp_\br_\bo_\bf_\bi_\bl_\be or any of the personal initialization
+
+
+
+GNU                  Last change: 1995 May 5                    1
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+               files ~/._\bb_\ba_\bs_\bh__\bp_\br_\bo_\bf_\bi_\bl_\be, ~/._\bb_\ba_\bs_\bh__\bl_\bo_\bg_\bi_\bn,  or  ~/._\bp_\br_\bo_\b-
+               _\bf_\bi_\bl_\be.  By default, bash normally reads these files
+               when it is invoked as a login shell  (see  INVOCA-
+               TION below).
+     -rcfile _\bf_\bi_\bl_\be
+               Execute commands from _\bf_\bi_\bl_\be instead of the standard
+               personal  initialization  file  ~/._\bb_\ba_\bs_\bh_\br_\bc,  if the
+               shell is interactive (see INVOCATION below).
+     -version  Show the version number of this instance  of  bash
+               when starting.
+     -quiet    Do not be verbose when starting up  (do  not  show
+               the shell version or any other information).  This
+               is the default.
+     -login    Make bash act as if it had been invoked as a login
+               shell.
+     -nobraceexpansion
+               Do not perform curly brace  expansion  (see  Brace
+               Expansion below).
+     -nolineediting
+               Do not use the GNU _\br_\be_\ba_\bd_\bl_\bi_\bn_\be library to  read  com-
+               mand lines if interactive.
+     -posix    Change the behavior  of  bash  where  the  default
+               operation  differs  from the Posix 1003.2 standard
+               to match the standard
+
+ARGUMENTS
+     If arguments remain after option processing, and neither the
+     -c  nor  the -s option has been supplied, the first argument
+     is assumed to be the name of a file  containing  shell  com-
+     mands.  If bash is invoked in this fashion, $0 is set to the
+     name of the file, and the positional parameters are  set  to
+     the  remaining  arguments.  Bash reads and executes commands
+     from this file, then exits.  Bash's exit status is the  exit
+     status of the last command executed in the script.
+
+DEFINITIONS
+     blank
+          A space or tab.
+     word A sequence of characters considered as a single unit by
+          the shell.  Also known as a token.
+     name A _\bw_\bo_\br_\bd consisting only of alphanumeric  characters  and
+          underscores, and beginning with an alphabetic character
+          or an underscore.  Also referred to as an identifier.
+     metacharacter
+          A character that, when unquoted, separates words.   One
+          of the following:
+          |  & ; ( ) < > space tab
+     control operator
+          A _\bt_\bo_\bk_\be_\bn that performs a control function.  It is one of
+          the following symbols:
+          || & && ; ;; ( ) | <newline>
+
+
+
+
+GNU                  Last change: 1995 May 5                    2
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+RESERVED WORDS
+     _\bR_\be_\bs_\be_\br_\bv_\be_\bd _\bw_\bo_\br_\bd_\bs are words that have a special meaning to  the
+     shell.   The following words are recognized as reserved when
+     unquoted and either the first word of a simple command  (see
+     SHELL GRAMMAR below) or the third word of a case or for com-
+     mand:
+
+     ! case  do done elif else esac fi for function if in  select
+     then until while { }
+
+SHELL GRAMMAR
+  Simple Commands
+     A _\bs_\bi_\bm_\bp_\bl_\be _\bc_\bo_\bm_\bm_\ba_\bn_\bd is a sequence of optional variable  assign-
+     ments  followed  by  _\bb_\bl_\ba_\bn_\bk-separated words and redirections,
+     and terminated by a _\bc_\bo_\bn_\bt_\br_\bo_\bl _\bo_\bp_\be_\br_\ba_\bt_\bo_\br.  The first word speci-
+     fies  the  command  to be executed.  The remaining words are
+     passed as arguments to the invoked command.
+
+     The return value of a _\bs_\bi_\bm_\bp_\bl_\be _\bc_\bo_\bm_\bm_\ba_\bn_\bd is its exit status,  or
+     128+_\bn if the command is terminated by signal _\bn.
+
+  Pipelines
+     A _\bp_\bi_\bp_\be_\bl_\bi_\bn_\be is a sequence of one or more  commands  separated
+     by the character |.  The format for a pipeline is:
+
+          [ ! ] _\bc_\bo_\bm_\bm_\ba_\bn_\bd [ | _\bc_\bo_\bm_\bm_\ba_\bn_\bd_\b2 ... ]
+
+     The standard output of _\bc_\bo_\bm_\bm_\ba_\bn_\bd is connected to the  standard
+     input  of _\bc_\bo_\bm_\bm_\ba_\bn_\bd_\b2.  This connection is performed before any
+     redirections  specified  by  the  command  (see  REDIRECTION
+     below).
+
+     If the reserved word ! precedes a pipeline, the exit  status
+     of  that  pipeline  is the logical NOT of the exit status of
+     the last command.  Otherwise, the status of the pipeline  is
+     the  exit  status  of the last command.  The shell waits for
+     all commands in the pipeline to terminate before returning a
+     value.
+
+     Each command in a pipeline is executed as a separate process
+     (i.e., in a subshell).
+
+  Lists
+     A _\bl_\bi_\bs_\bt is a sequence of one or more pipelines  separated  by
+     one  of the operators ;, &, &&, or ||, and terminated by one
+     of ;, &, or <newline>.
+
+     Of these list operators, && and ||  have  equal  precedence,
+     followed by ; and &, which have equal precedence.
+
+     If a command is terminated by the control  operator  &,  the
+     shell  executes the command in the _\bb_\ba_\bc_\bk_\bg_\br_\bo_\bu_\bn_\bd in a subshell.
+
+
+
+GNU                  Last change: 1995 May 5                    3
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     The shell does not wait for the command to finish,  and  the
+     return  status is 0.  Commands separated by a ; are executed
+     sequentially; the shell waits for each command to  terminate
+     in  turn.   The return status is the exit status of the last
+     command executed.
+
+     The control operators && and ||  denote  AND  lists  and  OR
+     lists, respectively.  An AND list has the form
+
+          _\bc_\bo_\bm_\bm_\ba_\bn_\bd && _\bc_\bo_\bm_\bm_\ba_\bn_\bd_\b2
+
+     _\bc_\bo_\bm_\bm_\ba_\bn_\bd_\b2 is executed if, and only  if,  _\bc_\bo_\bm_\bm_\ba_\bn_\bd  returns  an
+     exit status of zero.
+
+     An OR list has the form
+
+          _\bc_\bo_\bm_\bm_\ba_\bn_\bd || _\bc_\bo_\bm_\bm_\ba_\bn_\bd_\b2
+
+     _\bc_\bo_\bm_\bm_\ba_\bn_\bd_\b2 is executed  if  and  only  if  _\bc_\bo_\bm_\bm_\ba_\bn_\bd  returns  a
+     non-zero exit status.  The return status of AND and OR lists
+     is the exit status of the last command executed in the list.
+
+  Compound Commands
+     A _\bc_\bo_\bm_\bp_\bo_\bu_\bn_\bd _\bc_\bo_\bm_\bm_\ba_\bn_\bd is one of the following:
+
+     (_\bl_\bi_\bs_\bt)
+          _\bl_\bi_\bs_\bt is executed in a subshell.   Variable  assignments
+          and  builtin  commands that affect the shell's environ-
+          ment do not remain in effect  after  the  command  com-
+          pletes.  The return status is the exit status of _\bl_\bi_\bs_\bt.
+
+     { _\bl_\bi_\bs_\bt; }
+          _\bl_\bi_\bs_\bt is simply executed in the current  shell  environ-
+          ment.   This  is  known as a _\bg_\br_\bo_\bu_\bp _\bc_\bo_\bm_\bm_\ba_\bn_\bd.  The return
+          status is the exit status of _\bl_\bi_\bs_\bt.
+
+     for _\bn_\ba_\bm_\be [ in _\bw_\bo_\br_\bd; ] do _\bl_\bi_\bs_\bt ; done
+          The list of words following in is expanded,  generating
+          a list of items.  The variable _\bn_\ba_\bm_\be is set to each ele-
+          ment of this list in turn, and _\bl_\bi_\bs_\bt  is  executed  each
+          time.   If the in _\bw_\bo_\br_\bd is omitted, the for command exe-
+          cutes _\bl_\bi_\bs_\bt once for each positional parameter  that  is
+          set (see PARAMETERS below).
+
+     select _\bn_\ba_\bm_\be [ in _\bw_\bo_\br_\bd; ] do _\bl_\bi_\bs_\bt ; done
+          The list of words following in is expanded,  generating
+          a  list of items.  The set of expanded words is printed
+          on the standard error, each preceded by a  number.   If
+          the  in  _\bw_\bo_\br_\bd is omitted, the positional parameters are
+          printed (see PARAMETERS below).  The PS3 prompt is then
+          displayed  and a line read from the standard input.  If
+          the line consists of the number corresponding to one of
+
+
+
+GNU                  Last change: 1995 May 5                    4
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          the  displayed  words, then the value of _\bn_\ba_\bm_\be is set to
+          that word.  If the line is empty, the words and  prompt
+          are  displayed again.  If EOF is read, the command com-
+          pletes.  Any other value read causes _\bn_\ba_\bm_\be to be set  to
+          null.   The  line  read is saved in the variable REPLY.
+          The _\bl_\bi_\bs_\bt is executed after each selection until a break
+          or  return  command  is  executed.   The exit status of
+          select is the exit status of the last command  executed
+          in _\bl_\bi_\bs_\bt, or zero if no commands were executed.
+
+     case _\bw_\bo_\br_\bd in [ _\bp_\ba_\bt_\bt_\be_\br_\bn [ | _\bp_\ba_\bt_\bt_\be_\br_\bn ] ... ) _\bl_\bi_\bs_\bt ;; ] ... esac
+          A  case  command first expands _\bw_\bo_\br_\bd, and tries to match
+          it against each _\bp_\ba_\bt_\bt_\be_\br_\bn in turn, using the same  match-
+          ing  rules  as  for  pathname  expansion  (see Pathname
+          Expansion  below).   When  a  match   is   found,   the
+          corresponding _\bl_\bi_\bs_\bt is executed.  After the first match,
+          no subsequent matches are attempted.  The  exit  status
+          is  zero  if no patterns are matches.  Otherwise, it is
+          the exit status of the last command executed in _\bl_\bi_\bs_\bt.
+
+     if _\bl_\bi_\bs_\bt then _\bl_\bi_\bs_\bt [ elif _\bl_\bi_\bs_\bt then _\bl_\bi_\bs_\bt ] ... [ else _\bl_\bi_\bs_\bt ] fi
+          The  if  _\bl_\bi_\bs_\bt is executed.  If its exit status is zero,
+          the then _\bl_\bi_\bs_\bt is executed.  Otherwise, each  elif  _\bl_\bi_\bs_\bt
+          is  executed  in  turn, and if its exit status is zero,
+          the corresponding then _\bl_\bi_\bs_\bt is executed and the command
+          completes.   Otherwise,  the  else _\bl_\bi_\bs_\bt is executed, if
+          present.  The exit status is the  exit  status  of  the
+          last  command  executed, or zero if no condition tested
+          true.
+
+     while _\bl_\bi_\bs_\bt do _\bl_\bi_\bs_\bt done
+     until _\bl_\bi_\bs_\bt do _\bl_\bi_\bs_\bt done
+          The while command continuously executes the do _\bl_\bi_\bs_\bt  as
+          long as the last command in _\bl_\bi_\bs_\bt returns an exit status
+          of zero.  The until command is identical to  the  while
+          command,  except  that the test is negated; the do _\bl_\bi_\bs_\bt
+          is executed as long as the last command in _\bl_\bi_\bs_\bt returns
+          a  non-zero  exit status.  The exit status of the while
+          and until commands is the exit status of  the  last  do
+          _\bl_\bi_\bs_\bt command executed, or zero if none was executed.
+
+     [ function ] _\bn_\ba_\bm_\be () { _\bl_\bi_\bs_\bt; }
+          This defines a function named _\bn_\ba_\bm_\be.  The  _\bb_\bo_\bd_\by  of  the
+          function is the _\bl_\bi_\bs_\bt of commands between { and }.  This
+          list is executed whenever _\bn_\ba_\bm_\be is specified as the name
+          of  a simple command.  The exit status of a function is
+          the exit status of the last  command  executed  in  the
+          body.  (See FUNCTIONS below.)
+
+COMMENTS
+     In a non-interactive shell, or an interactive shell in which
+     the  -o  interactive-comments  option  to the set builtin is
+
+
+
+GNU                  Last change: 1995 May 5                    5
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     enabled, a word beginning with # causes that  word  and  all
+     remaining  characters  on  that  line  to  be  ignored.   An
+     interactive shell without the -o interactive-comments option
+     enabled does not allow comments.
+
+QUOTING
+     _\bQ_\bu_\bo_\bt_\bi_\bn_\bg is used to remove the  special  meaning  of  certain
+     characters  or  words  to the shell.  Quoting can be used to
+     disable special treatment for special characters, to prevent
+     reserved words from being recognized as such, and to prevent
+     parameter expansion.
+
+     Each of the _\bm_\be_\bt_\ba_\bc_\bh_\ba_\br_\ba_\bc_\bt_\be_\br_\bs listed  above  under  DEFINITIONS
+     has  special meaning to the shell and must be quoted if they
+     are  to  represent  themselves.   There  are  three  quoting
+     mechanisms:  the _\be_\bs_\bc_\ba_\bp_\be _\bc_\bh_\ba_\br_\ba_\bc_\bt_\be_\br, single quotes, and double
+     quotes.
+
+     A non-quoted backslash (\)  is  the  _\be_\bs_\bc_\ba_\bp_\be  _\bc_\bh_\ba_\br_\ba_\bc_\bt_\be_\br.   It
+     preserves  the literal value of the next character that fol-
+     lows, with the exception of <newline>.  If a \<newline> pair
+     appears,  and the backslash is not quoted, the \<newline> is
+     treated as a line continuation (that is, it  is  effectively
+     ignored).
+
+     Enclosing characters in single quotes preserves the  literal
+     value  of  each character within the quotes.  A single quote
+     may not occur between single quotes, even when preceded by a
+     backslash.
+
+     Enclosing characters in double quotes preserves the  literal
+     value  of  all characters within the quotes, with the excep-
+     tion of $, `, and \.  The characters $ and  `  retain  their
+     special meaning within double quotes.  The backslash retains
+     its special meaning only when followed by one of the follow-
+     ing  characters:  $,  `, ", \, or <newline>.  A double quote
+     may be quoted within double quotes by preceding  it  with  a
+     backslash.
+
+     The special parameters * and @ have special meaning when  in
+     double quotes (see PARAMETERS below).
+
+PARAMETERS
+     A _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br is an entity that stores values, somewhat like a
+     variable  in a conventional programming language.  It can be
+     a _\bn_\ba_\bm_\be, a number, or one of the  special  characters  listed
+     below under Special Parameters.  For the shell's purposes, a
+     _\bv_\ba_\br_\bi_\ba_\bb_\bl_\be is a parameter denoted by a _\bn_\ba_\bm_\be.
+
+     A parameter is set if it has been  assigned  a  value.   The
+     null  string  is  a valid value.  Once a variable is set, it
+     may be unset only by using the unset  builtin  command  (see
+
+
+
+GNU                  Last change: 1995 May 5                    6
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     SHELL BUILTIN COMMANDS below).
+
+     A _\bv_\ba_\br_\bi_\ba_\bb_\bl_\be may be assigned to by a statement of the form
+
+          _\bn_\ba_\bm_\be=[_\bv_\ba_\bl_\bu_\be]
+
+     If _\bv_\ba_\bl_\bu_\be is not given, the variable  is  assigned  the  null
+     string.   All  _\bv_\ba_\bl_\bu_\be_\bs undergo tilde expansion, parameter and
+     variable expansion, command substitution, arithmetic  expan-
+     sion,  and quote removal.  If the variable has its -i attri-
+     bute set (see declare below in SHELL BUILTIN COMMANDS)  then
+     _\bv_\ba_\bl_\bu_\be  is subject to arithmetic expansion even if the $[...]
+     syntax does not appear.  Word splitting  is  not  performed,
+     with  the exception of "$@" as explained below under Special
+     Parameters.  Pathname expansion is not performed.
+
+  Positional Parameters
+     A _\bp_\bo_\bs_\bi_\bt_\bi_\bo_\bn_\ba_\bl _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br is a parameter denoted by one or more
+     digits,  other  than the single digit 0.  Positional parame-
+     ters are assigned from the  shell's  arguments  when  it  is
+     invoked,  and  may  be reassigned using the set builtin com-
+     mand.  Positional parameters may not  be  assigned  to  with
+     assignment  statements.   The positional parameters are tem-
+     porarily replaced when a shell  function  is  executed  (see
+     FUNCTIONS below).
+
+     When a positional parameter consisting of more than a single
+     digit is expanded, it must be enclosed in braces (see EXPAN-
+     SION below).
+
+  Special Parameters
+     The shell treats several parameters specially.  These param-
+     eters  may  only  be  referenced;  assignment to them is not
+     allowed.
+     *    Expands to the  positional  parameters,  starting  from
+          one.   When  the expansion occurs within double quotes,
+          it expands to a single word  with  the  value  of  each
+          parameter  separated  by the first character of the IFS
+          special variable.  That is,  ``$*''  is  equivalent  to
+          ``$1_\bc$2_\bc...'',  where  _\bc  is the first character of the
+          value of the IFS variable.  If IFS is  null  or  unset,
+          the parameters are separated by spaces.
+     @    Expands to the  positional  parameters,  starting  from
+          one.   When  the expansion occurs within double quotes,
+          each parameter expands as a separate word.  That is, ``
+          $@'' is equivalent to ``$1'' ``$2'' ...  When there are
+          no positional parameters, ``$@'' and $@ expand to noth-
+          ing (i.e., they are removed).
+     #    Expands to  the  number  of  positional  parameters  in
+          decimal.
+     ?    Expands to the status of  the  most  recently  executed
+          foreground pipeline.
+
+
+
+GNU                  Last change: 1995 May 5                    7
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     -    Expands to the current option flags as  specified  upon
+          invocation, by the set builtin command, or those set by
+          the shell itself (such as the -i flag).
+     $    Expands to the process ID of the shell.  In a  ()  sub-
+          shell,  it  expands  to  the  process ID of the current
+          shell, not the subshell.
+     !    Expands to the process ID of the most recently executed
+          background (asynchronous) command.
+     0    Expands to the name of the shell or shell script.  This
+          is  set  at  shell  initialization.  If bash is invoked
+          with a file of commands, $0 is set to the name of  that
+          file.   If  bash is started with the -c option, then $0
+          is set to the first argument after  the  string  to  be
+          executed,  if  one is present.  Otherwise, it is set to
+          the pathname used to invoke bash, as given by  argument
+          zero.
+     _    Expands to the last argument to the  previous  command,
+          after expansion.  Also set to the full pathname of each
+          command executed and placed in the environment exported
+          to that command.
+
+  Shell Variables
+     The following variables are set by the shell:
+
+     PPID The process ID of the shell's parent.
+     PWD  The current working directory as set by the cd command.
+     OLDPWD
+          The previous working directory as set by  the  cd  com-
+          mand.
+     REPLY
+          Set to the line of input read by the read builtin  com-
+          mand when no arguments are supplied.
+     UID  Expands to the user ID of the current user, initialized
+          at shell startup.
+     EUID Expands to the effective user ID of the  current  user,
+          initialized at shell startup.
+     BASH Expands to  the  full  pathname  used  to  invoke  this
+          instance of bash.
+     BASH_VERSION
+          Expands to the version number of this instance of bash.
+     SHLVL
+          Incremented by one each time an  instance  of  bash  is
+          started.
+     RANDOM
+          Each  time  this  parameter  is  referenced,  a  random
+          integer  is  generated.  The sequence of random numbers
+          may be initialized by assigning a value to RANDOM.   If
+          RANDOM  is unset, it loses its special properties, even
+          if it is subsequently reset.
+     SECONDS
+          Each time this parameter is referenced, the  number  of
+          seconds since shell invocation is returned.  If a value
+
+
+
+GNU                  Last change: 1995 May 5                    8
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          is assigned to SECONDS, the value returned upon  subse-
+          quent  references  is  the  number of seconds since the
+          assignment plus the  value  assigned.   If  SECONDS  is
+          unset,  it  loses its special properties, even if it is
+          subsequently reset.
+     LINENO
+          Each time this parameter is referenced, the shell  sub-
+          stitutes  a  decimal  number  representing  the current
+          sequential line  number  (starting  with  1)  within  a
+          script  or function.  When not in a script or function,
+          the value substituted is not guaranteed to be  meaning-
+          ful.   When  in a function, the value is not the number
+          of the source line that the command  appears  on  (that
+          information  has  been lost by the time the function is
+          executed), but is an approximation  of  the  number  of
+          _\bs_\bi_\bm_\bp_\bl_\be  _\bc_\bo_\bm_\bm_\ba_\bn_\bd_\bs  executed in the current function.  If
+          LINENO is unset, it loses its special properties,  even
+          if it is subsequently reset.
+     HISTCMD
+          The history number, or index in the  history  list,  of
+          the current command.  If HISTCMD is unset, it loses its
+          special properties, even if it is subsequently reset.
+     OPTARG
+          The value of the last option argument processed by  the
+          getopts  builtin  command  (see  SHELL BUILTIN COMMANDS
+          below).
+     OPTIND
+          The index of the next argument to be processed  by  the
+          getopts  builtin  command  (see  SHELL BUILTIN COMMANDS
+          below).
+     HOSTTYPE
+          Automatically set to a string that  uniquely  describes
+          the  type  of  machine on which bash is executing.  The
+          default is system-dependent.
+     OSTYPE
+          Automatically  set  to  a  string  that  describes  the
+          operating  system  on  which  bash  is  executing.  The
+          default is system-dependent.
+
+     The following variables are used  by  the  shell.   In  some
+     cases,  bash  assigns  a  default value to a variable; these
+     cases are noted below.
+
+     IFS  The _\bI_\bn_\bt_\be_\br_\bn_\ba_\bl _\bF_\bi_\be_\bl_\bd _\bS_\be_\bp_\ba_\br_\ba_\bt_\bo_\br  that  is  used  for  word
+          splitting after expansion and to split lines into words
+          with the read builtin command.  The  default  value  is
+          ``<space><tab><newline>''.
+     PATH The search path for commands.  It is a  colon-separated
+          list  of  directories in which the shell looks for com-
+          mands (see COMMAND EXECUTION below).  The default  path
+          is  system-dependent,  and  is set by the administrator
+          who    installs    bash.     A    common    value    is
+
+
+
+GNU                  Last change: 1995 May 5                    9
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          ``/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:.''.
+     HOME The home directory of the  current  user;  the  default
+          argument for the cd builtin command.
+     CDPATH
+          The search path for the cd command.  This is  a  colon-
+          separated  list of directories in which the shell looks
+          for destination directories specified by  the  cd  com-
+          mand.  A sample value is ``.:~:/usr''.
+     ENV  If this parameter is set when bash is executing a shell
+          script, its value is interpreted as a filename contain-
+          ing commands to initialize the shell,  as  in  ._\bb_\ba_\bs_\bh_\br_\bc.
+          The  value  of ENV is subjected to parameter expansion,
+          command substitution, and arithmetic  expansion  before
+          being  interpreted  as a pathname.  PATH is not used to
+          search for the resultant pathname.
+     MAIL If this parameter is set to a filename and the MAILPATH
+          variable  is  not  set,  bash  informs  the user of the
+          arrival of mail in the specified file.
+     MAILCHECK
+          Specifies how often (in seconds) bash checks for  mail.
+          The  default  is  60 seconds.  When it is time to check
+          for mail, the shell does so before prompting.  If  this
+          variable is unset, the shell disables mail checking.
+     MAILPATH
+          A colon-separated list of pathnames to be  checked  for
+          mail.  The  message  to  be printed may be specified by
+          separating the pathname from the message  with  a  `?'.
+          $_  stands  for the name of the current mailfile. Exam-
+          ple:
+          MAILPATH='/usr/spool/mail/bfox?"You                have
+          mail":~/shell-mail?"$_ has mail!"'
+          Bash supplies a default value for  this  variable,  but
+          the  location  of  the  user mail files that it uses is
+          system dependent (e.g., /usr/spool/mail/$USER).
+     MAIL_WARNING
+          If set, and a file that bash is checking for  mail  has
+          been  accessed  since the last time it was checked, the
+          message ``The mail  in  _\bm_\ba_\bi_\bl_\bf_\bi_\bl_\be  has  been  read''  is
+          printed.
+     PS1  The value of this parameter is expanded (see  PROMPTING
+          below)  and  used  as  the  primary prompt string.  The
+          default value is ``bash\$ ''.
+     PS2  The value of this parameter is expanded and used as the
+          secondary prompt string.  The default is ``> ''.
+     PS3  The value of this parameter is used as the  prompt  for
+          the _\bs_\be_\bl_\be_\bc_\bt command (see SHELL GRAMMAR above).
+     PS4  The value of this parameter is expanded and  the  value
+          is  printed before each command bash displays during an
+          execution trace.  The first character of PS4 is  repli-
+          cated  multiple times, as necessary, to indicate multi-
+          ple levels of indirection.  The default is ``+ ''.
+     HISTSIZE
+
+
+
+GNU                  Last change: 1995 May 5                   10
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          The number of commands to remember in the command  his-
+          tory (see HISTORY below).  The default value is 500.
+     HISTFILE
+          The name of the file in which command history is saved.
+          (See    HISTORY   below.)    The   default   value   is
+          ~/._\bb_\ba_\bs_\bh__\bh_\bi_\bs_\bt_\bo_\br_\by.  If unset, the command history is  not
+          saved when an interactive shell exits.
+     HISTFILESIZE
+          The maximum number of lines contained  in  the  history
+          file.  When this variable is assigned a value, the his-
+          tory file is truncated, if  necessary,  to  contain  no
+          more  than  that number of lines.  The default value is
+          500.
+     OPTERR
+          If set to the value 1,  bash  displays  error  messages
+          generated  by  the  getopts  builtin command (see SHELL
+          BUILTIN COMMANDS below).  OPTERR is  initialized  to  1
+          each  time  the  shell  is invoked or a shell script is
+          executed.
+     PROMPT_COMMAND
+          If set, the value is executed as  a  command  prior  to
+          issuing each primary prompt.
+     IGNOREEOF
+          Controls the action of the shell on receipt of  an  EOF
+          character  as the sole input.  If set, the value is the
+          number of consecutive EOF characters typed as the first
+          characters  on an input line before bash exits.  If the
+          variable exists but does not have a numeric  value,  or
+          has  no value, the default value is 10.  If it does not
+          exist, EOF signifies the end of  input  to  the  shell.
+          This is only in effect for interactive shells.
+     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.   Bash  terminates
+          after  waiting for that number of seconds if input does
+          not arrive.
+     FCEDIT
+          The default editor for the fc builtin command.
+     FIGNORE
+          A colon-separated list of suffixes to ignore when  per-
+          forming  filename  completion  (see READLINE below).  A
+          filename whose suffix matches one  of  the  entries  in
+          FIGNORE is excluded from the list of matched filenames.
+          A sample value is ``.o:~''.
+     INPUTRC
+          The filename for the readline startup file,  overriding
+          the default of ~/._\bi_\bn_\bp_\bu_\bt_\br_\bc (see READLINE below).
+     notify
+          If set, bash reports terminated background jobs immedi-
+          ately,  rather  than  waiting until before printing the
+          next primary prompt (see also the -b option to the  set
+
+
+
+GNU                  Last change: 1995 May 5                   11
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          builtin command).
+     history_control
+     HISTCONTROL
+          If set to a value of  _\bi_\bg_\bn_\bo_\br_\be_\bs_\bp_\ba_\bc_\be,  lines  which  begin
+          with  a  space character are not entered on the history
+          list.  If set to a value of _\bi_\bg_\bn_\bo_\br_\be_\bd_\bu_\bp_\bs, lines  matching
+          the  last  history  line  are  not entered.  A value of
+          _\bi_\bg_\bn_\bo_\br_\be_\bb_\bo_\bt_\bh combines the two options.  If unset,  or  if
+          set to any other value than those above, all lines read
+          by the parser are saved on the history list.
+
+     command_oriented_history
+          If  set,  bash  attempts  to  save  all  lines   of   a
+          multiple-line  command in the same history entry.  This
+          allows easy re-editing of multi-line commands.
+
+     glob_dot_filenames
+          If set, bash includes filenames beginning with a `.' in
+          the results of pathname expansion.
+
+     allow_null_glob_expansion
+          If set, bash allows pathname patterns  which  match  no
+          files  (see  Pathname  Expansion  below) to expand to a
+          null string, rather than themselves.
+
+     histchars
+          The two  or  three  characters  which  control  history
+          expansion   and  tokenization  (see  HISTORY  EXPANSION
+          below).  The first character is the  _\bh_\bi_\bs_\bt_\bo_\br_\by  _\be_\bx_\bp_\ba_\bn_\bs_\bi_\bo_\bn
+          _\bc_\bh_\ba_\br_\ba_\bc_\bt_\be_\br,  that  is,  the  character which signals the
+          start of a history expansion, normally `!'.  The second
+          character is the _\bq_\bu_\bi_\bc_\bk _\bs_\bu_\bb_\bs_\bt_\bi_\bt_\bu_\bt_\bi_\bo_\bn character, which is
+          used as shorthand for re-running the  previous  command
+          entered,  substituting  one  string  for another in the
+          command.  The default is `^'.  The optional third char-
+          acter   is  the  character  which  signifies  that  the
+          remainder of the line is a comment, when found  as  the
+          first  character  of a word, normally `#'.  The history
+          comment character causes  history  substitution  to  be
+          skipped  for  the remaining words on the line.  It does
+          not necessarily cause the shell  parser  to  treat  the
+          rest of the line as a comment.
+
+     nolinks
+          If set, the shell does not follow symbolic  links  when
+          executing  commands  that  change  the  current working
+          directory.  It uses the  physical  directory  structure
+          instead.  By default, bash follows the logical chain of
+          directories when performing commands which  change  the
+          current  directory,  such as cd.  See also the descrip-
+          tion of the -P option to the set builtin ( SHELL  BUIL-
+          TIN COMMANDS below).
+
+
+
+GNU                  Last change: 1995 May 5                   12
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     hostname_completion_file
+     HOSTFILE
+          Contains the name of a  file  in  the  same  format  as
+          /_\be_\bt_\bc/_\bh_\bo_\bs_\bt_\bs  that should be read when the shell needs to
+          complete a hostname.  The file may be changed  interac-
+          tively;  the next time hostname completion is attempted
+          bash adds the contents of the new file to  the  already
+          existing database.
+
+     noclobber
+          If set, bash does not overwrite an existing  file  with
+          the >, >&, and <> redirection operators.  This variable
+          may be overridden when creating output files  by  using
+          the  redirection operator >| instead of > (see also the
+          -C option to the set builtin command).
+
+     auto_resume
+          This variable controls how the shell interacts with the
+          user  and job control.  If this variable is set, single
+          word simple commands without redirections  are  treated
+          as  candidates  for  resumption  of an existing stopped
+          job.  There is no ambiguity allowed; if there  is  more
+          than  one  job beginning with the string typed, the job
+          most recently accessed is  selected.   The  _\bn_\ba_\bm_\be  of  a
+          stopped  job, in this context, is the command line used
+          to start it.  If set to the  value  _\be_\bx_\ba_\bc_\bt,  the  string
+          supplied  must match the name of a stopped job exactly;
+          if set to _\bs_\bu_\bb_\bs_\bt_\br_\bi_\bn_\bg, the string supplied needs to match
+          a  substring  of  the  name of a stopped job.  The _\bs_\bu_\bb_\b-
+          _\bs_\bt_\br_\bi_\bn_\bg value provides functionality analogous to the %?
+          job  id  (see  JOB CONTROL below).  If set to any other
+          value, the supplied  string  must  be  a  prefix  of  a
+          stopped  job's name; this provides functionality analo-
+          gous to the % job id.
+
+     no_exit_on_failed_exec
+          If this variable exists, a non-interactive  shell  will
+          not exit if it cannot execute the file specified in the
+          exec builtin command.  An interactive  shell  does  not
+          exit if exec fails.
+
+     cdable_vars
+          If this is set, an argument to the cd  builtin  command
+          that  is not a directory is assumed to be the name of a
+          variable whose value is the directory to change to.
+
+EXPANSION
+     Expansion is performed on the command line after it has been
+     split  into  words.  There are seven kinds of expansion per-
+     formed: _\bb_\br_\ba_\bc_\be  _\be_\bx_\bp_\ba_\bn_\bs_\bi_\bo_\bn,  _\bt_\bi_\bl_\bd_\be  _\be_\bx_\bp_\ba_\bn_\bs_\bi_\bo_\bn,  _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br  _\ba_\bn_\bd
+     _\bv_\ba_\br_\bi_\ba_\bb_\bl_\be  _\be_\bx_\bp_\ba_\bn_\bs_\bi_\bo_\bn, _\bc_\bo_\bm_\bm_\ba_\bn_\bd _\bs_\bu_\bb_\bs_\bt_\bi_\bt_\bu_\bt_\bi_\bo_\bn, _\ba_\br_\bi_\bt_\bh_\bm_\be_\bt_\bi_\bc _\be_\bx_\bp_\ba_\bn_\b-
+     _\bs_\bi_\bo_\bn, _\bw_\bo_\br_\bd _\bs_\bp_\bl_\bi_\bt_\bt_\bi_\bn_\bg, and _\bp_\ba_\bt_\bh_\bn_\ba_\bm_\be _\be_\bx_\bp_\ba_\bn_\bs_\bi_\bo_\bn.
+
+
+
+GNU                  Last change: 1995 May 5                   13
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     The order of expansions is: brace  expansion,  tilde  expan-
+     sion, parameter, variable, command, and arithmetic substitu-
+     tion (done in a left-to-right fashion), word splitting,  and
+     pathname expansion.
+
+     On systems that can  support  it,  there  is  an  additional
+     expansion available: _\bp_\br_\bo_\bc_\be_\bs_\bs _\bs_\bu_\bb_\bs_\bt_\bi_\bt_\bu_\bt_\bi_\bo_\bn.
+
+     Only brace expansion, word splitting, and pathname expansion
+     can  change  the  number  of  words  of the expansion; other
+     expansions expand a single word to a single word.  The  sin-
+     gle  exception  to  this  is  the  expansion  of  ``$@''  as
+     explained above (see PARAMETERS).
+
+  Brace Expansion
+     _\bB_\br_\ba_\bc_\be _\be_\bx_\bp_\ba_\bn_\bs_\bi_\bo_\bn is a mechanism by  which  arbitrary  strings
+     may  be  generated.   This  mechanism is similar to _\bp_\ba_\bt_\bh_\bn_\ba_\bm_\be
+     _\be_\bx_\bp_\ba_\bn_\bs_\bi_\bo_\bn, but the filenames generated need not exist.  Pat-
+     terns  to  be  brace  expanded  take the form of an optional
+     _\bp_\br_\be_\ba_\bm_\bb_\bl_\be, followed by a series  of  comma-separated  strings
+     between a pair of braces, followed by an optional _\bp_\bo_\bs_\bt_\ba_\bm_\bb_\bl_\be.
+     The preamble is prepended to each  string  contained  within
+     the  braces,  and  the  postamble  is  then appended to each
+     resulting string, expanding left to right.
+
+     Brace  expansions  may  be  nested.   The  results  of  each
+     expanded  string  are  not  sorted;  left  to right order is
+     preserved.  For example, a{d,c,b}e  expands  into  `ade  ace
+     abe'.
+
+     Brace expansion is performed before  any  other  expansions,
+     and any characters special to other expansions are preserved
+     in the result.  It is strictly textual.  Bash does not apply
+     any syntactic interpretation to the context of the expansion
+     or the text between the braces.
+
+     A correctly-formed brace  expansion  must  contain  unquoted
+     opening and closing braces, and at least one unquoted comma.
+     Any incorrectly formed brace expansion is left unchanged.
+
+     This construct is typically used as shorthand when the  com-
+     mon  prefix of the strings to be generated is longer than in
+     the above example:
+
+          mkdir /usr/local/src/bash/{old,new,dist,bugs}
+     or
+          chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
+
+     Brace expansion introduces  a  slight  incompatibility  with
+     traditional  versions  of sh, the Bourne shell.  sh does not
+     treat opening or closing braces specially when  they  appear
+     as  part  of a word, and preserves them in the output.  Bash
+
+
+
+GNU                  Last change: 1995 May 5                   14
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     removes braces from words as a consequence of  brace  expan-
+     sion.   For  example,  a  word  entered  to  sh as _\bf_\bi_\bl_\be{_\b1,_\b2}
+     appears identically in the output.  The same word is  output
+     as  _\bf_\bi_\bl_\be_\b1 _\bf_\bi_\bl_\be_\b2 after expansion by bash.  If strict compati-
+     bility with sh is desired, start bash with  the  -nobraceex-
+     pansion  flag (see OPTIONS above) or disable brace expansion
+     with the +o braceexpand option to the set command (see SHELL
+     BUILTIN COMMANDS below).
+
+  Tilde Expansion
+     If a word begins with a tilde character (`~'),  all  of  the
+     characters  preceding the first slash (or all characters, if
+     there is no slash) are treated as a possible _\bl_\bo_\bg_\bi_\bn _\bn_\ba_\bm_\be.  If
+     this  _\bl_\bo_\bg_\bi_\bn  _\bn_\ba_\bm_\be  is the null string, the tilde is replaced
+     with the value of the parameter HOME.  If HOME is unset, the
+     home  directory  of  the user executing the shell is substi-
+     tuted instead.
+
+     If a `+' follows the tilde, the value of  PWD  replaces  the
+     tilde  and  `+'.   If  a `-' follows, the value of OLDPWD is
+     substituted.  If the value following the tilde  is  a  valid
+     _\bl_\bo_\bg_\bi_\bn  _\bn_\ba_\bm_\be,  the tilde and _\bl_\bo_\bg_\bi_\bn _\bn_\ba_\bm_\be are replaced with the
+     home directory associated with that name.  If  the  name  is
+     invalid,   or   the  tilde  expansion  fails,  the  word  is
+     unchanged.
+
+     Each variable assignment is checked for  unquoted  instances
+     of tildes following a : or =.  In these cases, tilde substi-
+     tution is also performed.  Consequently, one may  use  path-
+     names  with  tildes  in  assignments  to PATH, MAILPATH, and
+     CDPATH, and the shell assigns the expanded value.
+
+  Parameter Expansion
+     The `$' character introduces  parameter  expansion,  command
+     substitution,  or  arithmetic expansion.  The parameter name
+     or symbol to be expanded may be enclosed  in  braces,  which
+     are  optional  but  serve  to  protect  the  variable  to be
+     expanded from  characters  immediately  following  it  which
+     could be interpreted as part of the name.
+
+     ${_\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br}
+          The value of _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br is substituted.  The braces  are
+          required  when _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br is a positional parameter with
+          more than one digit, or when _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br is followed by a
+          character which is not to be interpreted as part of its
+          name.
+
+     In each of the cases below, _\bw_\bo_\br_\bd is subject to tilde  expan-
+     sion,  parameter expansion, command substitution, and arith-
+     metic expansion.  Bash tests for a parameter that  is  unset
+     or  null;  omitting  the  colon results in a test only for a
+     parameter that is unset.
+
+
+
+GNU                  Last change: 1995 May 5                   15
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     ${_\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br:-_\bw_\bo_\br_\bd}
+          Use Default Values.  If _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br is unset or null, the
+          expansion of _\bw_\bo_\br_\bd is substituted.  Otherwise, the value
+          of _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br is substituted.
+     ${_\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br:=_\bw_\bo_\br_\bd}
+          Assign Default Values.  If _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br is unset or  null,
+          the  expansion  of  _\bw_\bo_\br_\bd is assigned to _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br.  The
+          value of _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br  is  then  substituted.   Positional
+          parameters  and  special parameters may not be assigned
+          to in this way.
+     ${_\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br:?_\bw_\bo_\br_\bd}
+          Display Error if Null or Unset.  If _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br  is  null
+          or  unset,  the expansion of _\bw_\bo_\br_\bd (or a message to that
+          effect if _\bw_\bo_\br_\bd is not present) is written to the  stan-
+          dard  error  and  the  shell, if it is not interactive,
+          exits.  Otherwise, the value of  _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br  is  substi-
+          tuted.
+     ${_\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br:+_\bw_\bo_\br_\bd}
+          Use Alternate Value.  If _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br is  null  or  unset,
+          nothing is substituted, otherwise the expansion of _\bw_\bo_\br_\bd
+          is substituted.
+     ${#_\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br}
+          The length in characters of the value of  _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br  is
+          substituted.   If  _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br is * or @, the length sub-
+          stituted is the length  of  *  expanded  within  double
+          quotes.
+     ${_\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br#_\bw_\bo_\br_\bd}
+     ${_\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br##_\bw_\bo_\br_\bd}
+          The _\bw_\bo_\br_\bd is expanded to produce a pattern  just  as  in
+          pathname  expansion.  If the pattern matches the begin-
+          ning of the value of _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br, then the  expansion  is
+          the  value of _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br with the shortest matching pat-
+          tern deleted (the ``#'' case) or the  longest  matching
+          pattern deleted (the ``##'' case).
+
+     ${_\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br%_\bw_\bo_\br_\bd}
+     ${_\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br%%_\bw_\bo_\br_\bd}
+          The _\bw_\bo_\br_\bd is expanded to produce a pattern  just  as  in
+          pathname  expansion.  If the pattern matches a trailing
+          portion of the value of _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br, then  the  expansion
+          is  the  value  of _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br with the shortest matching
+          pattern deleted (the ``%'' case) or the longest  match-
+          ing pattern deleted (the ``%%'' case).
+
+  Command Substitution
+     _\bC_\bo_\bm_\bm_\ba_\bn_\bd _\bs_\bu_\bb_\bs_\bt_\bi_\bt_\bu_\bt_\bi_\bo_\bn allows  the  output  of  a  command  to
+     replace the command name.  There are two forms:
+
+          $(_\bc_\bo_\bm_\bm_\ba_\bn_\bd)
+     or
+          `_\bc_\bo_\bm_\bm_\ba_\bn_\bd`
+
+
+
+
+GNU                  Last change: 1995 May 5                   16
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     Bash performs the expansion by executing _\bc_\bo_\bm_\bm_\ba_\bn_\bd and replac-
+     ing the command substitution with the standard output of the
+     command, with any trailing newlines deleted.
+
+     When the old-style backquote form of substitution  is  used,
+     backslash  retains  its literal meaning except when followed
+     by $, `, or \.  When using the $(_\bc_\bo_\bm_\bm_\ba_\bn_\bd) form, all  charac-
+     ters  between  the parentheses make up the command; none are
+     treated specially.
+
+     Command substitutions may be nested.  To nest when using the
+     old form, escape the inner backquotes with backslashes.
+
+     If the  substitution  appears  within  double  quotes,  word
+     splitting  and  pathname  expansion are not performed on the
+     results.
+
+  Arithmetic Expansion
+     Arithmetic expansion allows the evaluation of an  arithmetic
+     expression  and  the  substitution of the result.  There are
+     two formats for arithmetic expansion:
+
+          $[_\be_\bx_\bp_\br_\be_\bs_\bs_\bi_\bo_\bn]
+
+          $((_\be_\bx_\bp_\br_\be_\bs_\bs_\bi_\bo_\bn))
+
+     The _\be_\bx_\bp_\br_\be_\bs_\bs_\bi_\bo_\bn is  treated  as  if  it  were  within  double
+     quotes,  but a double quote inside the braces or parentheses
+     is not treated specially.   All  tokens  in  the  expression
+     undergo parameter expansion, command substitution, and quote
+     removal.  Arithmetic substitutions may be nested.
+
+     The evaluation is performed according to  the  rules  listed
+     below   under   ARITHMETIC  EVALUATION.   If  _\be_\bx_\bp_\br_\be_\bs_\bs_\bi_\bo_\bn  is
+     invalid, bash prints a message  indicating  failure  and  no
+     substitution occurs.
+
+  Process Substitution
+     _\bP_\br_\bo_\bc_\be_\bs_\bs _\bs_\bu_\bb_\bs_\bt_\bi_\bt_\bu_\bt_\bi_\bo_\bn is supported on  systems  that  support
+     named  pipes  (_\bF_\bI_\bF_\bO_\bs)  or  the /dev/fd method of naming open
+     files.  It takes the form of <(_\bl_\bi_\bs_\bt) or >(_\bl_\bi_\bs_\bt).   The  pro-
+     cess  _\bl_\bi_\bs_\bt  is  run  with its input or output connected to a
+     _\bF_\bI_\bF_\bO or some file in /dev/fd.  The  name  of  this  file  is
+     passed  as  an argument to the current command as the result
+     of the expansion.  If the >(_\bl_\bi_\bs_\bt) form is used,  writing  to
+     the  file  will provide input for _\bl_\bi_\bs_\bt.  If the <(_\bl_\bi_\bs_\bt) form
+     is used, the file passed as an argument should  be  read  to
+     obtain the output of _\bl_\bi_\bs_\bt.
+
+     On systems that support it,  _\bp_\br_\bo_\bc_\be_\bs_\bs  _\bs_\bu_\bb_\bs_\bt_\bi_\bt_\bu_\bt_\bi_\bo_\bn  is  per-
+     formed simultaneously with _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br _\ba_\bn_\bd _\bv_\ba_\br_\bi_\ba_\bb_\bl_\be _\be_\bx_\bp_\ba_\bn_\bs_\bi_\bo_\bn,
+     _\bc_\bo_\bm_\bm_\ba_\bn_\bd _\bs_\bu_\bb_\bs_\bt_\bi_\bt_\bu_\bt_\bi_\bo_\bn, and _\ba_\br_\bi_\bt_\bh_\bm_\be_\bt_\bi_\bc _\be_\bx_\bp_\ba_\bn_\bs_\bi_\bo_\bn.
+
+
+
+GNU                  Last change: 1995 May 5                   17
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+  Word Splitting
+     The shell scans the results of parameter expansion,  command
+     substitution,  and  arithmetic  expansion that did not occur
+     within double quotes for _\bw_\bo_\br_\bd _\bs_\bp_\bl_\bi_\bt_\bt_\bi_\bn_\bg.
+
+     The shell treats each character of IFS as a  delimiter,  and
+     splits  the  results  of  the other expansions into words on
+     these  characters.   If  the  value  of   IFS   is   exactly
+     <space><tab><newline>, the default, then any sequence of IFS
+     characters serves to delimit words.   If  IFS  has  a  value
+     other  than  the  default,  then sequences of the whitespace
+     characters space and tab are ignored at  the  beginning  and
+     end  of  the word, as long as the whitespace character is in
+     the value of IFS (an IFS whitespace character).  Any charac-
+     ter  in IFS that is not IFS whitespace, along with any adja-
+     cent  IFS  whitespace  characters,  delimits  a  field.    A
+     sequence  of  IFS whitespace characters is also treated as a
+     delimiter.  If the value of IFS is null, no  word  splitting
+     occurs.  IFS cannot be unset.
+
+     Explicit null arguments ("" or '') are  retained.   Implicit
+     null  arguments,  resulting from the expansion of _\bp_\ba_\br_\ba_\bm_\be_\bt_\be_\br_\bs
+     that have no values, are removed.
+
+     Note that if no expansion occurs, no splitting is performed.
+
+  Pathname Expansion
+     After word splitting, unless the -f  option  has  been  set,
+     bash scans each _\bw_\bo_\br_\bd for the characters *, ?, and [.  If one
+     of these characters appears, then the word is regarded as  a
+     _\bp_\ba_\bt_\bt_\be_\br_\bn,  and replaced with an alphabetically sorted list of
+     pathnames matching the pattern.  If  no  matching  pathnames
+     are  found, and the shell variable allow_null_glob_expansion
+     is unset, the word is left unchanged.  If  the  variable  is
+     set,  and no matches are found, the word is removed.  When a
+     pattern is used for pathname generation, the character ``.''
+     at the start of a name or immediately following a slash must
+     be   matched   explicitly,   unless   the   shell   variable
+     glob_dot_filenames  is set.  The slash character must always
+     be matched explicitly.  In other cases, the ``.''  character
+     is not treated specially.
+
+     The special pattern characters have the following meanings:
+
+     *    Matches any string, including the null string.
+     ?    Matches any single character.
+     [...]
+          Matches any one of the enclosed characters.  A pair  of
+          characters  separated  by a minus sign denotes a _\br_\ba_\bn_\bg_\be;
+          any character lexically between those  two  characters,
+          inclusive,  is matched.  If the first character follow-
+          ing the [ is a ! or a ^ then any character not enclosed
+
+
+
+GNU                  Last change: 1995 May 5                   18
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          is matched.  A - or ] may be matched by including it as
+          the first or last character in the set.
+
+  Quote Removal
+     After the preceding expansions, all unquoted occurrences  of
+     the characters \, `, and " are removed.
+
+REDIRECTION
+     Before a command is executed, its input and  output  may  be
+     _\br_\be_\bd_\bi_\br_\be_\bc_\bt_\be_\bd  using  a  special  notation  interpreted  by the
+     shell.  Redirection may also be used to open and close files
+     for  the current shell execution environment.  The following
+     redirection operators may precede or appear anywhere  within
+     a  _\bs_\bi_\bm_\bp_\bl_\be _\bc_\bo_\bm_\bm_\ba_\bn_\bd or may follow a _\bc_\bo_\bm_\bm_\ba_\bn_\bd.  Redirections are
+     processed in the order they appear, from left to right.
+
+     In the following descriptions, if the file descriptor number
+     is  omitted,  and  the  first  character  of the redirection
+     operator is <, the redirection refers to the standard  input
+     (file descriptor 0).  If the first character of the redirec-
+     tion operator is >, the redirection refers to  the  standard
+     output (file descriptor 1).
+
+     The word that follows the redirection operator in  the  fol-
+     lowing  descriptions  is subjected to brace expansion, tilde
+     expansion, parameter expansion, command substitution, arith-
+     metic  expansion, quote removal, and pathname expansion.  If
+     it expands to more than one word, bash reports an error.
+
+     Note that the order of  redirections  is  significant.   For
+     example, the command
+
+          ls > dirlist 2>&1
+
+     directs both standard output and standard error to the  file
+     _\bd_\bi_\br_\bl_\bi_\bs_\bt, while the command
+
+          ls 2>&1 > dirlist
+
+     directs only the standard output to  file  _\bd_\bi_\br_\bl_\bi_\bs_\bt,  because
+     the  standard error was duplicated as standard output before
+     the standard output was redirected to _\bd_\bi_\br_\bl_\bi_\bs_\bt.
+
+  Redirecting Input
+     Redirection of input causes the file whose name results from
+     the  expansion  of  _\bw_\bo_\br_\bd  to  be  opened for reading on file
+     descriptor _\bn, or the standard input (file descriptor 0) if _\bn
+     is not specified.
+
+     The general format for redirecting input is:
+
+
+
+
+
+GNU                  Last change: 1995 May 5                   19
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          [_\bn]<_\bw_\bo_\br_\bd
+
+  Redirecting Output
+     Redirection of output causes the  file  whose  name  results
+     from  the expansion of _\bw_\bo_\br_\bd to be opened for writing on file
+     descriptor _\bn, or the standard output (file descriptor 1)  if
+     _\bn  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:
+
+          [_\bn]>_\bw_\bo_\br_\bd
+
+     If the redirection operator is >|, then the value of the  -C
+     option  to  the  set builtin command is not tested, and file
+     creation  is  attempted.   (See  also  the  description   of
+     noclobber under Shell Variables above.)
+
+  Appending Redirected Output
+     Redirection of output in this fashion causes the file  whose
+     name  results  from  the  expansion of _\bw_\bo_\br_\bd to be opened for
+     appending on file descriptor _\bn, or the standard output (file
+     descriptor  1)  if _\bn is not specified.  If the file does not
+     exist it is created.
+
+     The general format for appending output is:
+
+          [_\bn]>>_\bw_\bo_\br_\bd
+
+  Redirecting Standard Output and Standard Error
+     Bash allows both the standard output (file descriptor 1) and
+     the   standard  error  output  (file  descriptor  2)  to  be
+     redirected to the file whose name is the expansion  of  _\bw_\bo_\br_\bd
+     with this construct.
+
+     There are two formats for redirecting  standard  output  and
+     standard error:
+
+          &>_\bw_\bo_\br_\bd
+     and
+          >&_\bw_\bo_\br_\bd
+
+     Of the two forms, the first is preferred.  This is  semanti-
+     cally equivalent to
+
+          >_\bw_\bo_\br_\bd 2>&1
+
+  Here Documents
+     This type of redirection instructs the shell to  read  input
+     from  the  current  source until a line containing only _\bw_\bo_\br_\bd
+     (with no trailing blanks) is seen.  All of the lines read up
+     to  that  point  are  then  used as the standard input for a
+
+
+
+GNU                  Last change: 1995 May 5                   20
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     command.
+
+     The format of here-documents is as follows:
+
+          <<[-]_\bw_\bo_\br_\bd
+                  _\bh_\be_\br_\be-_\bd_\bo_\bc_\bu_\bm_\be_\bn_\bt
+          _\bd_\be_\bl_\bi_\bm_\bi_\bt_\be_\br
+
+     No  parameter  expansion,  command  substitution,   pathname
+     expansion, or arithmetic expansion is performed on _\bw_\bo_\br_\bd.  If
+     any characters in _\bw_\bo_\br_\bd are  quoted,  the  _\bd_\be_\bl_\bi_\bm_\bi_\bt_\be_\br  is  the
+     result  of quote removal on _\bw_\bo_\br_\bd, and the lines in the here-
+     document are not expanded.   Otherwise,  all  lines  of  the
+     here-document  are subjected to parameter expansion, command
+     substitution, and arithmetic expansion.  In the latter case,
+     the  pair \<newline> is ignored, and \ must be used to quote
+     the characters \, $, and `.
+
+     If the redirection operator is <<-,  then  all  leading  tab
+     characters  are  stripped from input lines and the line con-
+     taining _\bd_\be_\bl_\bi_\bm_\bi_\bt_\be_\br.  This allows here-documents within  shell
+     scripts to be indented in a natural fashion.
+
+  Duplicating File Descriptors
+     The redirection operator
+
+          [_\bn]<&_\bw_\bo_\br_\bd
+
+     is used  to  duplicate  input  file  descriptors.   If  _\bw_\bo_\br_\bd
+     expands  to  one or more digits, the file descriptor denoted
+     by _\bn is made to be a copy of that file descriptor.  If  _\bw_\bo_\br_\bd
+     evaluates  to  -,  file descriptor _\bn is closed.  If _\bn is not
+     specified, the standard input (file descriptor 0) is used.
+
+     The operator
+
+          [_\bn]>&_\bw_\bo_\br_\bd
+
+     is used similarly to duplicate output file descriptors.   If
+     _\bn  is not specified, the standard output (file descriptor 1)
+     is used.  As a special case, if _\bn is omitted, and _\bw_\bo_\br_\bd  does
+     not  expand  to  one or more digits, the standard output and
+     standard error are redirected as described previously.
+
+  Opening File Descriptors for Reading and Writing
+     The redirection operator
+
+          [_\bn]<>_\bw_\bo_\br_\bd
+
+     causes the file whose name is the expansion of  _\bw_\bo_\br_\bd  to  be
+     opened for both reading and writing on file descriptor _\bn, or
+     as the standard input  and  standard  output  if  _\bn  is  not
+
+
+
+GNU                  Last change: 1995 May 5                   21
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     specified.  If the file does not exist, it is created.
+
+FUNCTIONS
+     A shell function, defined as  described  above  under  SHELL
+     GRAMMAR,  stores  a  series of commands for later execution.
+     Functions are executed in the context of the current  shell;
+     no  new  process is created to interpret them (contrast this
+     with the execution of a shell script).  When a  function  is
+     executed,  the  arguments  to  the function become the posi-
+     tional parameters during its execution.  The special parame-
+     ter  # is updated to reflect the change.  Positional parame-
+     ter 0 is unchanged.
+
+     Variables local to the function may  be  declared  with  the
+     local  builtin  command.   Ordinarily,  variables  and their
+     values are shared between the function and its caller.
+
+     If the builtin command return is executed in a function, the
+     function  completes and execution resumes with the next com-
+     mand after the function call.  When  a  function  completes,
+     the  values  of  the  positional  parameters and the special
+     parameter # are restored to the values  they  had  prior  to
+     function execution.
+
+     Function names and definitions may be  listed  with  the  -f
+     option  to  the  declare or typeset builtin commands.  Func-
+     tions may be exported so that subshells  automatically  have
+     them defined with the -f option to the export builtin.
+
+     Functions may be recursive.  No  limit  is  imposed  on  the
+     number of recursive calls.
+
+ALIASES
+     The shell maintains a list of _\ba_\bl_\bi_\ba_\bs_\be_\bs that may  be  set  and
+     unset with the alias and unalias builtin commands (see SHELL
+     BUILTIN COMMANDS below).  The first word of each command, if
+     unquoted, is checked to see if it has an alias.  If so, that
+     word is replaced by the text of the alias.  The  alias  name
+     and  the replacement text may contain any valid shell input,
+     including the _\bm_\be_\bt_\ba_\bc_\bh_\ba_\br_\ba_\bc_\bt_\be_\br_\bs listed above, with  the  excep-
+     tion  that the alias name may not contain =.  The first word
+     of the replacement text is tested for aliases,  but  a  word
+     that is identical to an alias being expanded is not expanded
+     a second time.  This means that one may alias ls to  ls  -F,
+     for  instance,  and  bash does not try to recursively expand
+     the replacement text.  If the last character  of  the  alias
+     value  is  a _\bb_\bl_\ba_\bn_\bk, then the next command word following the
+     alias is also checked for alias expansion.
+
+     Aliases are created and listed with the alias  command,  and
+     removed with the unalias command.
+
+
+
+
+GNU                  Last change: 1995 May 5                   22
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     There is no mechanism for using arguments in the replacement
+     text,  as in csh.  If arguments are needed, a shell function
+     should be used.
+
+     Aliases are not expanded when the shell is not interactive.
+
+     The rules concerning the definition and use of  aliases  are
+     somewhat confusing.  Bash always reads at least one complete
+     line of input before executing any of the commands  on  that
+     line.  Aliases are expanded when a command is read, not when
+     it is executed.  Therefore, an alias definition appearing on
+     the  same line as another command does not take effect until
+     the next line of input is read.  This means  that  the  com-
+     mands  following  the  alias definition on that line are not
+     affected by the new alias.  This behavior is also  an  issue
+     when  functions are executed.  Aliases are expanded when the
+     function definition is read, not when the function  is  exe-
+     cuted,  because  a  function definition is itself a compound
+     command.  As a consequence, aliases defined  in  a  function
+     are not available until after that function is executed.  To
+     be safe, always put alias definitions on  a  separate  line,
+     and do not use alias in compound commands.
+
+     Note that for almost every purpose, aliases  are  superseded
+     by shell functions.
+
+JOB CONTROL
+     _\bJ_\bo_\bb _\bc_\bo_\bn_\bt_\br_\bo_\bl  refers  to  the  ability  to  selectively  stop
+     (_\bs_\bu_\bs_\bp_\be_\bn_\bd)  the  execution of processes and continue (_\br_\be_\bs_\bu_\bm_\be)
+     their execution at a later point.  A user typically  employs
+     this  facility via an interactive interface supplied jointly
+     by the system's terminal driver and bash.
+
+     The shell associates a _\bj_\bo_\bb with each pipeline.  It  keeps  a
+     table  of currently executing jobs, which may be listed with
+     the jobs command.  When bash starts a job asynchronously (in
+     the _\bb_\ba_\bc_\bk_\bg_\br_\bo_\bu_\bn_\bd), it prints a line that looks like:
+
+          [1] 25647
+
+     indicating that this job is job number 1 and that  the  pro-
+     cess  ID of the last process in the pipeline associated with
+     this job is 25647.  All of the processes in a  single  pipe-
+     line  are  members  of  the  same  job.   Bash  uses the _\bj_\bo_\bb
+     abstraction as the basis for job control.
+
+     To facilitate the implementation of the  user  interface  to
+     job  control,  the  system maintains the notion of a _\bc_\bu_\br_\br_\be_\bn_\bt
+     _\bt_\be_\br_\bm_\bi_\bn_\ba_\bl _\bp_\br_\bo_\bc_\be_\bs_\bs _\bg_\br_\bo_\bu_\bp _\bI_\bD.  Members of  this  process  group
+     (processes  whose  process  group ID is equal to the current
+     terminal process group ID) receive  keyboard-generated  sig-
+     nals  such as SIGINT.  These processes are said to be in the
+
+
+
+GNU                  Last change: 1995 May 5                   23
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     _\bf_\bo_\br_\be_\bg_\br_\bo_\bu_\bn_\bd.  _\bB_\ba_\bc_\bk_\bg_\br_\bo_\bu_\bn_\bd processes are  those  whose  process
+     group  ID  differs  from  the terminal's; such processes are
+     immune  to  keyboard-generated  signals.   Only   foreground
+     processes are allowed to read from or write to the terminal.
+     Background processes which attempt to read from  (write  to)
+     the terminal are sent a SIGTTIN (SIGTTOU) signal by the ter-
+     minal driver, which, unless caught, suspends the process.
+
+     If the operating system on which bash  is  running  supports
+     job  control, bash allows you to use it.  Typing the _\bs_\bu_\bs_\bp_\be_\bn_\bd
+     character (typically ^Z, Control-Z) while a process is  run-
+     ning  causes  that  process to be stopped and returns you to
+     bash.  Typing the _\bd_\be_\bl_\ba_\by_\be_\bd _\bs_\bu_\bs_\bp_\be_\bn_\bd character  (typically  ^Y,
+     Control-Y) causes the process to be stopped when it attempts
+     to read input from the terminal, and control to be  returned
+     to  bash.   You  may  then manipulate the state of this job,
+     using the bg command to continue it in the  background,  the
+     fg  command  to  continue  it in the foreground, or the kill
+     command to kill it.  A ^Z takes effect immediately, and  has
+     the  additional  side  effect  of causing pending output and
+     typeahead to be discarded.
+
+     There are a number of ways to refer to a job in  the  shell.
+     The  character % introduces a job name.  Job number _\bn may be
+     referred to as %n.  A job may also be referred  to  using  a
+     prefix  of  the  name used to start it, or using a substring
+     that appears in its command line.  For example,  %ce  refers
+     to a stopped ce job.  If a prefix matches more than one job,
+     bash reports an error.   Using  %?ce,  on  the  other  hand,
+     refers  to  any  job containing the string ce in its command
+     line.  If the substring matches  more  than  one  job,  bash
+     reports  an  error.   The  symbols  %%  and  %+ refer to the
+     shell's notion of the _\bc_\bu_\br_\br_\be_\bn_\bt _\bj_\bo_\bb, which  is  the  last  job
+     stopped  while  it  was in the foreground.  The _\bp_\br_\be_\bv_\bi_\bo_\bu_\bs _\bj_\bo_\bb
+     may be referenced using %-.  In output  pertaining  to  jobs
+     (e.g.,  the  output of the jobs command), the current job is
+     always flagged with a +, and the previous job with a -.
+
+     Simply naming a job can be used to bring it into  the  fore-
+     ground:  %1  is a synonym for ``fg %1'', bringing job 1 from
+     the background into the  foreground.   Similarly,  ``%1  &''
+     resumes job 1 in the background, equivalent to ``bg %1''.
+
+     The shell learns immediately whenever a job  changes  state.
+     Normally,  bash  waits  until  it is about to print a prompt
+     before reporting changes in a job's  status  so  as  to  not
+     interrupt  any  other  output.   If the -b option to the set
+     builtin command is set, bash reports  such  changes  immedi-
+     ately.   (See  also the description of notify variable under
+     Shell Variables above.)
+
+
+
+
+
+GNU                  Last change: 1995 May 5                   24
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     If you attempt to exit bash  while  jobs  are  stopped,  the
+     shell  prints  a  message warning you.  You may then use the
+     jobs command to inspect their status.  If you  do  this,  or
+     try to exit again immediately, you are not warned again, and
+     the stopped jobs are terminated.
+
+SIGNALS
+     When bash is interactive, it ignores SIGTERM (so that kill 0
+     does  not  kill  an interactive shell), and SIGINT is caught
+     and handled (so that the wait builtin is interruptible).  In
+     all  cases,  bash  ignores  SIGQUIT.   If  job control is in
+     effect, bash ignores SIGTTIN, SIGTTOU, and SIGTSTP.
+
+     Synchronous jobs started by bash have  signals  set  to  the
+     values  inherited  by  the  shell from its parent.  When job
+     control is not in effect, background jobs (jobs started with
+     &)  ignore  SIGINT and SIGQUIT.  Commands run as a result of
+     command substitution ignore the keyboard-generated job  con-
+     trol signals SIGTTIN, SIGTTOU, and SIGTSTP.
+
+COMMAND EXECUTION
+     After a command has been split into words, if it results  in
+     a simple command and an optional list of arguments, the fol-
+     lowing actions are taken.
+
+     If the command name contains no slashes, the shell  attempts
+     to  locate  it.   If  there  exists a shell function by that
+     name, that function is invoked as described above  in  FUNC-
+     TIONS.   If  the  name  does not match a function, the shell
+     searches for it in the list of shell builtins.  If  a  match
+     is found, that builtin is invoked.
+
+     If the name is neither a shell function nor a  builtin,  and
+     contains  no slashes, bash searches each element of the PATH
+     for a directory containing an executable file by that  name.
+     If  the  search  is  unsuccessful, the shell prints an error
+     message and returns a nonzero exit status.
+
+     If the search is successful, or if the command name contains
+     one  or  more slashes, the shell executes the named program.
+     Argument 0 is set to the name given, and the remaining argu-
+     ments to the command are set to the arguments given, if any.
+
+     If this execution fails because the file is not  in  execut-
+     able  format, and the file is not a directory, it is assumed
+     to be a _\bs_\bh_\be_\bl_\bl _\bs_\bc_\br_\bi_\bp_\bt, a file containing shell  commands.   A
+     subshell is spawned to execute it.  This subshell reinitial-
+     izes itself, so that the effect is as if  a  new  shell  had
+     been  invoked  to handle the script, with the exception that
+     the locations of commands remembered by the parent (see hash
+     below  under  SHELL  BUILTIN  COMMANDS)  are retained by the
+     child.
+
+
+
+GNU                  Last change: 1995 May 5                   25
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     If the program is a file beginning with #!, the remainder of
+     the  first  line  specifies  an interpreter for the program.
+     The shell executes the specified  interpreter  on  operating
+     systems  that  do  not  handle  this executable format them-
+     selves.  The arguments to the interpreter consist of a  sin-
+     gle  optional argument following the interpreter name on the
+     first line of the program, followed by the name of the  pro-
+     gram, followed by the command arguments, if any.
+
+ENVIRONMENT
+     When a program is invoked it is given an  array  of  strings
+     called the _\be_\bn_\bv_\bi_\br_\bo_\bn_\bm_\be_\bn_\bt.  This is a list of _\bn_\ba_\bm_\be-_\bv_\ba_\bl_\bu_\be pairs,
+     of the form _\bn_\ba_\bm_\be=_\bv_\ba_\bl_\bu_\be.
+
+     The shell  allows  you  to  manipulate  the  environment  in
+     several  ways.   On  invocation,  the  shell  scans  its own
+     environment and creates a parameter  for  each  name  found,
+     automatically  marking  it  for  _\be_\bx_\bp_\bo_\br_\bt  to child processes.
+     Executed commands inherit the environment.  The  export  and
+     declare  -x  commands  allow  parameters and functions to be
+     added to and deleted from the environment.  If the value  of
+     a  parameter  in  the environment is modified, the new value
+     becomes part of the environment,  replacing  the  old.   The
+     environment  inherited  by  any executed command consists of
+     the shell's initial environment, whose values may  be  modi-
+     fied  in the shell, less any pairs removed by the unset com-
+     mand, plus any additions via the export and declare -x  com-
+     mands.
+
+     The environment for any _\bs_\bi_\bm_\bp_\bl_\be _\bc_\bo_\bm_\bm_\ba_\bn_\bd or  function  may  be
+     augmented temporarily by prefixing it with parameter assign-
+     ments, as described above in PARAMETERS.   These  assignment
+     statements affect only the environment seen by that command.
+
+     If the -k flag is set (see the set builtin  command  below),
+     then _\ba_\bl_\bl parameter assignments are placed in the environment
+     for a command, not just those that precede the command name.
+
+     When bash invokes an external command, the variable _ is set
+     to the full path name of the command and passed to that com-
+     mand in its environment.
+
+EXIT STATUS
+     For the purposes of the shell, a command which exits with  a
+     zero  exit  status  has  succeeded.   An exit status of zero
+     indicates  success.   A  non-zero  exit   status   indicates
+     failure.   When a command terminates on a fatal signal, bash
+     uses the value of 128+signal as the exit status.
+
+     If a command is not found, the child process created to exe-
+     cute  it returns a status of 127.  If a command is found but
+     is not executable, the return status is 126.
+
+
+
+GNU                  Last change: 1995 May 5                   26
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     Bash itself returns the exit status of the last command exe-
+     cuted,  unless a syntax error occurs, in which case it exits
+     with a non-zero value.  See also the  exit  builtin  command
+     below.
+
+PROMPTING
+     When executing  interactively,  bash  displays  the  primary
+     prompt  PS1  when  it  is  ready  to read a command, and the
+     secondary prompt PS2 when it needs more input to complete  a
+     command.   Bash allows these prompt strings to be customized
+     by inserting a number of backslash-escaped  special  charac-
+     ters that are decoded as follows:
+          \t   the current time in HH:MM:SS format
+          \d   the date in "Weekday  Month  Date"  format  (e.g.,
+               "Tue May 26")
+          \n   newline
+          \s   the name of the shell, the  basename  of  $0  (the
+               portion following the final slash)
+          \w   the current working directory
+          \W   the basename of the current working directory
+          \u   the username of the current user
+          \h   the hostname
+          \#   the command number of this command
+          \!   the history number of this command
+          \$   if the effective UID is 0, a #, otherwise a $
+          \nnn the character corresponding to  the  octal  number
+               nnn
+          \\   a backslash
+          \[   begin a sequence of non-printing characters, which
+               could be used to embed a terminal control sequence
+               into the prompt
+          \]   end a sequence of non-printing characters
+
+     The command number and the history number are  usually  dif-
+     ferent:  the  history number of a command is its position in
+     the history list, which may include commands  restored  from
+     the  history  file  (see  HISTORY  below), while the command
+     number is the position in the sequence of commands  executed
+     during  the  current  shell  session.   After  the string is
+     decoded, it is expanded  via  parameter  expansion,  command
+     substitution, arithmetic expansion, and word splitting.
+
+READLINE
+     This is the library that handles reading input when using an
+     interactive  shell,  unless  the  -nolineediting  option  is
+     given.  By default, the line editing commands are similar to
+     those  of  emacs.  A vi-style line editing interface is also
+     available.
+
+     In this section, the emacs-style notation is used to  denote
+     keystrokes.   Control  keys  are denoted by C-_\bk_\be_\by, e.g., C-n
+     means Control-N.  Similarly, _\bm_\be_\bt_\ba keys are denoted by M-_\bk_\be_\by,
+
+
+
+GNU                  Last change: 1995 May 5                   27
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     so  M-x means Meta-X.  (On keyboards without a _\bm_\be_\bt_\ba key, M-_\bx
+     means ESC _\bx, i.e., press the Escape  key  then  the  _\bx  key.
+     This makes ESC the _\bm_\be_\bt_\ba _\bp_\br_\be_\bf_\bi_\bx.  The combination M-C-_\bx means
+     ESC-Control-_\bx, or press the Escape key then hold the Control
+     key while pressing the _\bx key.)
+
+     The default key-bindings may be changed with  an  ~/._\bi_\bn_\bp_\bu_\bt_\br_\bc
+     file.   The  value of the shell variable INPUTRC, if set, is
+     used instead of ~/._\bi_\bn_\bp_\bu_\bt_\br_\bc.  Other programs  that  use  this
+     library may add their own commands and bindings.
+
+     For example, placing
+
+          M-Control-u: universal-argument
+     or
+          C-Meta-u: universal-argument
+     into the ~/._\bi_\bn_\bp_\bu_\bt_\br_\bc would make M-C-u  execute  the  readline
+     command _\bu_\bn_\bi_\bv_\be_\br_\bs_\ba_\bl-_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt.
+
+     The  following  symbolic  character  names  are  recognized:
+     _\bR_\bU_\bB_\bO_\bU_\bT, _\bD_\bE_\bL, _\bE_\bS_\bC, _\bL_\bF_\bD, _\bN_\bE_\bW_\bL_\bI_\bN_\bE, _\bR_\bE_\bT, _\bR_\bE_\bT_\bU_\bR_\bN, _\bS_\bP_\bC, _\bS_\bP_\bA_\bC_\bE, and
+     _\bT_\bA_\bB.  In addition to command names, readline allows keys  to
+     be  bound  to  a  string  that  is  inserted when the key is
+     pressed (a _\bm_\ba_\bc_\br_\bo).
+
+     Readline is customized by putting commands in an initializa-
+     tion file.  The name of this file is taken from the value of
+     the INPUTRC  variable.   If  that  variable  is  unset,  the
+     default  is ~/._\bi_\bn_\bp_\bu_\bt_\br_\bc.  When a program which uses the read-
+     line library starts up, the init file is read, and  the  key
+     bindings  and variables are set.  There are only a few basic
+     constructs allowed in the readline init file.   Blank  lines
+     are  ignored.  Lines beginning with a # are comments.  Lines
+     beginning with a $ indicate conditional  constructs.   Other
+     lines denote key bindings and variable settings.
+
+     The syntax for controlling key bindings  in  the  ~/._\bi_\bn_\bp_\bu_\bt_\br_\bc
+     file  is  simple.   All  that is required is the name of the
+     command or the text of a macro and a key sequence  to  which
+     it  should be bound. The name may be specified in one of two
+     ways: as  a  symbolic  key  name,  possibly  with  _\bM_\be_\bt_\ba-  or
+     _\bC_\bo_\bn_\bt_\br_\bo_\bl-  prefixes,  or  as  a key sequence.  When using the
+     form keyname:_\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn-_\bn_\ba_\bm_\be or _\bm_\ba_\bc_\br_\bo, _\bk_\be_\by_\bn_\ba_\bm_\be is the name  of
+     a key spelled out in English.  For example:
+
+          Control-u: universal-argument
+          Meta-Rubout: backward-kill-word
+          Control-o: ">&output"
+
+     In  the  above  example,  _\bC-_\bu  is  bound  to  the   function
+     universal-argument,   _\bM-_\bD_\bE_\bL   is   bound   to  the  function
+     backward-kill-word, and  _\bC-_\bo  is  bound  to  run  the  macro
+
+
+
+GNU                  Last change: 1995 May 5                   28
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     expressed  on  the  right  hand side (that is, to insert the
+     text >&_\bo_\bu_\bt_\bp_\bu_\bt into the line).
+
+     In the second form, "keyseq":_\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn-_\bn_\ba_\bm_\be or _\bm_\ba_\bc_\br_\bo,  keyseq
+     differs  from  keyname  above  in  that  strings denoting an
+     entire key sequence may be specified by placing the sequence
+     within  double quotes.  Some GNU Emacs style key escapes can
+     be used, as in the following example.
+
+          "\C-u": universal-argument
+          "\C-x\C-r": re-read-init-file
+          "\e[11~": "Function Key 1"
+
+     In  this  example,  _\bC-_\bu  is  again  bound  to  the  function
+     universal-argument.   _\bC-_\bx  _\bC-_\br  is  bound  to  the  function
+     re-read-init-file, and _\bE_\bS_\bC [ _\b1 _\b1 ~ is bound  to  insert  the
+     text Function Key 1.  The full set of escape sequences is
+
+          \C-  control prefix
+
+          \M-  meta prefix
+
+          \e   an escape character
+
+          \\   backslash
+
+          " \" literal "
+
+          \'   literal '
+
+     When entering the text of a macro, single or  double  quotes
+     should  be  used  to  indicate a macro definition.  Unquoted
+     text is assumed to be a function name.  Backslash will quote
+     any character in the macro text, including " and '.
+
+     Bash  allows  the  current  readline  key  bindings  to   be
+     displayed  or  modified  with the bind builtin command.  The
+     editing mode may be switched during interactive use by using
+     the  -o option to the set builtin command (see SHELL BUILTIN
+     COMMANDS below).
+
+     Readline has variables that can be used to further customize
+     its  behavior.   A  variable  may be set in the _\bi_\bn_\bp_\bu_\bt_\br_\bc file
+     with a statement of the form
+
+          set _\bv_\ba_\br_\bi_\ba_\bb_\bl_\be-_\bn_\ba_\bm_\be _\bv_\ba_\bl_\bu_\be
+
+     Except where noted, readline variables can take  the  values
+     On or Off.  The variables and their default values are:
+
+     horizontal-scroll-mode (Off)
+          When set to On, makes readline use a  single  line  for
+
+
+
+GNU                  Last change: 1995 May 5                   29
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          display,  scrolling  the input horizontally on a single
+          screen line when it  becomes  longer  than  the  screen
+          width rather than wrapping to a new line.
+     editing-mode (emacs)
+          Controls whether readline begins  with  a  set  of  key
+          bindings  similar  to _\be_\bm_\ba_\bc_\bs or _\bv_\bi.  editing-mode can be
+          set to either emacs or vi.
+     mark-modified-lines (Off)
+          If set to On, history lines that have been modified are
+          displayed with a preceding asterisk (*).
+     bell-style (audible)
+          Controls what happens when readline wants to  ring  the
+          terminal  bell.   If  set to none, readline never rings
+          the bell.  If set to visible, readline uses  a  visible
+          bell  if one is available.  If set to audible, readline
+          attempts to ring the terminal's bell.
+     comment-begin (``#'')
+          The string  that  is  inserted  in  vi  mode  when  the
+          vi-comment command is executed.
+     meta-flag (Off)
+          If set to On,  readline  will  enable  eight-bit  input
+          (that is, it will not strip the high bit from the char-
+          acters it  reads),  regardless  of  what  the  terminal
+          claims it can support.
+     convert-meta (On)
+          If set to On, readline will convert characters with the
+          eighth  bit  set  to an ASCII key sequence by stripping
+          the eighth bit and prepending an escape  character  (in
+          effect, using escape as the _\bm_\be_\bt_\ba _\bp_\br_\be_\bf_\bi_\bx).
+     output-meta (Off)
+          If set to On, readline will display characters with the
+          eighth  bit set directly rather than as a meta-prefixed
+          escape sequence.
+     completion-query-items (100)
+          This determines when the user is queried about  viewing
+          the  number  of  possible  completions generated by the
+          possible-completions command.  It may  be  set  to  any
+          integer  value  greater  than or equal to zero.  If the
+          number of possible completions is greater than or equal
+          to  the  value  of  this  variable,  the  user is asked
+          whether or not he wishes to view them;  otherwise  they
+          are simply listed on the terminal.
+     keymap (emacs)
+          Set the current readline keymap.  The set of legal key-
+          map  names is _\be_\bm_\ba_\bc_\bs, _\be_\bm_\ba_\bc_\bs-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd, _\be_\bm_\ba_\bc_\bs-_\bm_\be_\bt_\ba, _\be_\bm_\ba_\bc_\bs-
+          _\bc_\bt_\bl_\bx, _\bv_\bi, _\bv_\bi-_\bm_\bo_\bv_\be, _\bv_\bi-_\bc_\bo_\bm_\bm_\ba_\bn_\bd, and  _\bv_\bi-_\bi_\bn_\bs_\be_\br_\bt.   _\bv_\bi  is
+          equivalent   to  _\bv_\bi-_\bc_\bo_\bm_\bm_\ba_\bn_\bd;  _\be_\bm_\ba_\bc_\bs  is  equivalent  to
+          _\be_\bm_\ba_\bc_\bs-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd.  The default value is _\be_\bm_\ba_\bc_\bs; the  value
+          of editing-mode also affects the default keymap.
+     show-all-if-ambiguous (Off)
+          This alters the  default  behavior  of  the  completion
+          functions.   If  set  to on, words which have more than
+
+
+
+GNU                  Last change: 1995 May 5                   30
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          one possible completion cause the matches to be  listed
+          immediately instead of ringing the bell.
+     expand-tilde (Off)
+          If set to on, tilde expansion is performed  when  read-
+          line attempts word completion.
+
+     Readline implements a facility similar in spirit to the con-
+     ditional  compilation  features  of the C preprocessor which
+     allows key bindings and variable settings to be performed as
+     the  result  of  tests.   There  are three parser directives
+     used.
+
+     $if  The $if construct allows bindings to be made  based  on
+          the  editing  mode,  the  terminal  being  used, or the
+          application using  readline.   The  text  of  the  test
+          extends  to  the  end  of  the  line; no characters are
+          required to isolate it.
+
+          mode The mode= form of the $if  directive  is  used  to
+               test  whether  readline  is  in  emacs or vi mode.
+               This may be used in conjunction with the set  key-
+               map  command, for instance, to set bindings in the
+               _\be_\bm_\ba_\bc_\bs-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd  and  _\be_\bm_\ba_\bc_\bs-_\bc_\bt_\bl_\bx  keymaps  only  if
+               readline is starting out in emacs mode.
+
+          term The term= form may be used  to  include  terminal-
+               specific  key  bindings,  perhaps  to bind the key
+               sequences output by the terminal's function  keys.
+               The  word  on  the  right  side of the = is tested
+               against the full name of the terminal and the por-
+               tion  of  the  terminal  name  before the first -.
+               This allows _\bs_\bu_\bn to match both _\bs_\bu_\bn and _\bs_\bu_\bn-_\bc_\bm_\bd, for
+               instance.
+
+          application
+               The  application  construct  is  used  to  include
+               application-specific settings.  Each program using
+               the readline library sets  the  _\ba_\bp_\bp_\bl_\bi_\bc_\ba_\bt_\bi_\bo_\bn  _\bn_\ba_\bm_\be,
+               and an initialization file can test for a particu-
+               lar  value.   This  could  be  used  to  bind  key
+               sequences  to functions useful for a specific pro-
+               gram.  For instance, the following command adds  a
+               key  sequence  that quotes the current or previous
+               word in Bash:
+               $if Bash
+               # Quote the current or previous word
+               "\C-xq": "\eb\"\ef\""
+               $endif
+
+     $endif
+          This command, as you saw in the previous example,  ter-
+          minates an $if command.
+
+
+
+GNU                  Last change: 1995 May 5                   31
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     $else
+          Commands in this branch of the $if directive  are  exe-
+          cuted if the test fails.
+
+     Readline commands may be given numeric _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs, which nor-
+     mally  act as a repeat count.  Sometimes, however, it is the
+     sign of the argument that is significant.  Passing  a  nega-
+     tive  argument  to a command that acts in the forward direc-
+     tion (e.g., kill-line) causes that command to act in a back-
+     ward  direction.   Commands  whose  behavior  with arguments
+     deviates from this are noted.
+
+     When a command  is  described  as  _\bk_\bi_\bl_\bl_\bi_\bn_\bg  text,  the  text
+     deleted  is  saved  for possible future retrieval (_\by_\ba_\bn_\bk_\bi_\bn_\bg).
+     The killed text is saved in a _\bk_\bi_\bl_\bl-_\br_\bi_\bn_\bg.  Consecutive  kills
+     cause the text to be accumulated into one unit, which can be
+     yanked all at once. Commands which do not kill text separate
+     the chunks of text on the kill-ring.
+
+     The following is a list of the names of the commands and the
+     default key sequences to which they are bound.
+
+  Commands for Moving
+     beginning-of-line (C-a)
+          Move to the start of the current line.
+     end-of-line (C-e)
+          Move to the end of the line.
+     forward-char (C-f)
+          Move forward a character.
+     backward-char (C-b)
+          Move back a character.
+     forward-word (M-f)
+          Move forward to the end of the next  word.   Words  are
+          composed   of   alphanumeric  characters  (letters  and
+          digits).
+     backward-word (M-b)
+          Move back to the start of this, or the previous,  word.
+          Words  are composed of alphanumeric characters (letters
+          and digits).
+     clear-screen (C-l)
+          Clear the screen leaving the current line at the top of
+          the screen.  With an argument, refresh the current line
+          without clearing the screen.
+     redraw-current-line
+          Refresh the current line.  By default, this is unbound.
+
+  Commands for Manipulating the History
+     accept-line (Newline, Return)
+          Accept the line regardless of where the cursor is.   If
+          this  line  is  non-empty,  add  it to the history list
+          according to the state of the HISTCONTROL variable.  If
+          the  line  is a modified history line, then restore the
+
+
+
+GNU                  Last change: 1995 May 5                   32
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          history line to its original state.
+     previous-history (C-p)
+          Fetch the previous command from the history list,  mov-
+          ing back in the list.
+     next-history (C-n)
+          Fetch the next command from the  history  list,  moving
+          forward in the list.
+     beginning-of-history (M-<)
+          Move to the first line in the history.
+     end-of-history (M->)
+          Move to the end of the input history,  i.e.,  the  line
+          currently being entered.
+     reverse-search-history (C-r)
+          Search backward starting at the current line and moving
+          `up'  through  the  history  as  necessary.  This is an
+          incremental search.
+     forward-search-history (C-s)
+          Search forward starting at the current line and  moving
+          `down'  through  the  history as necessary.  This is an
+          incremental search.
+     non-incremental-reverse-search-history (M-p)
+          Search backward through the  history  starting  at  the
+          current  line  using  a  non-incremental  search  for a
+          string supplied by the user.
+     non-incremental-forward-search-history (M-n)
+          Search   forward   through   the   history   using    a
+          non-incremental  search  for  a  string supplied by the
+          user.
+     history-search-forward
+          Search forward through the history for  the  string  of
+          characters  between  the  start of the current line and
+          the current point.  This is a  non-incremental  search.
+          By default, this command is unbound.
+     history-search-backward
+          Search backward through the history for the  string  of
+          characters  between  the  start of the current line and
+          the current point.  This is a  non-incremental  search.
+          By default, this command is unbound.
+     yank-nth-arg (M-C-y)
+          Insert the first argument to the previous command (usu-
+          ally  the  second  word  on the previous line) at point
+          (the current cursor position).   With  an  argument  _\bn,
+          insert  the  _\bnth  word  from  the previous command (the
+          words in the previous command begin with  word  0).   A
+          negative  argument inserts the _\bnth word from the end of
+          the previous command.
+     yank-last-arg (M-., M-_)
+          Insert the last argument to the previous  command  (the
+          last  word  on  the  previous line).  With an argument,
+          behave exactly like yank-nth-arg.
+     shell-expand-line (M-C-e)
+          Expand the line the way the shell does  when  it  reads
+
+
+
+GNU                  Last change: 1995 May 5                   33
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          it.   This performs alias and history expansion as well
+          as all of  the  shell  word  expansions.   See  HISTORY
+          EXPANSION below for a description of history expansion.
+     history-expand-line (M-^)
+          Perform history expansion on  the  current  line.   See
+          HISTORY  EXPANSION  below  for a description of history
+          expansion.
+     insert-last-argument (M-., M-_)
+          A synonym for yank-last-arg.
+     operate-and-get-next (C-o)
+          Accept the current line for  execution  and  fetch  the
+          next line relative to the current line from the history
+          for editing.  Any argument is ignored.
+
+  Commands for Changing Text
+     delete-char (C-d)
+          Delete the character under the cursor.  If point is  at
+          the  beginning  of the line, there are no characters in
+          the line, and the last character  typed  was  not  C-d,
+          then return EOF.
+     backward-delete-char (Rubout)
+          Delete the character behind the cursor.  When  given  a
+          numeric   argument,   save  the  deleted  text  on  the
+          kill-ring.
+     quoted-insert (C-q, C-v)
+          Add the next character that you type to the line verba-
+          tim.   This  is  how to insert characters like C-q, for
+          example.
+     tab-insert (C-v TAB)
+          Insert a tab character.
+     self-insert (a, b, A, 1, !, ...)
+          Insert the character typed.
+     transpose-chars (C-t)
+          Drag the character before point forward over the  char-
+          acter at point.  Point moves forward as well.  If point
+          is at the end of the line, then transpose the two char-
+          acters before point.  Negative arguments don't work.
+     transpose-words (M-t)
+          Drag the word behind the cursor past the word in  front
+          of the cursor moving the cursor over that word as well.
+     upcase-word (M-u)
+          Uppercase the current  (or  following)  word.   With  a
+          negative  argument,  do  the  previous word, but do not
+          move point.
+     downcase-word (M-l)
+          Lowercase the current  (or  following)  word.   With  a
+          negative  argument,  do  the  previous word, but do not
+          move point.
+     capitalize-word (M-c)
+          Capitalize the current (or  following)  word.   With  a
+          negative  argument,  do  the  previous word, but do not
+          move point.
+
+
+
+GNU                  Last change: 1995 May 5                   34
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+  Killing and Yanking
+     kill-line (C-k)
+          Kill the text from the current cursor position  to  the
+          end of the line.
+     backward-kill-line (C-x C-Rubout)
+          Kill backward to the beginning of the line.
+     unix-line-discard (C-u)
+          Kill backward from point to the beginning of the line.
+     kill-whole-line
+          Kill all characters on  the  current  line,  no  matter
+          where the cursor is.  By default, this is unbound.
+     kill-word (M-d)
+          Kill from the cursor to the end of the current word, or
+          if  between  words,  to the end of the next word.  Word
+          boundaries are the same as those used by forward-word.
+     backward-kill-word (M-Rubout)
+          Kill the word behind the cursor.  Word  boundaries  are
+          the same as those used by backward-word.
+     unix-word-rubout (C-w)
+          Kill the word behind the cursor, using white space as a
+          word  boundary.  The word boundaries are different from
+          backward-kill-word.
+     delete-horizontal-space
+          Delete all spaces and tabs around point.   By  default,
+          this is unbound.
+     yank (C-y)
+          Yank the top of the kill ring into the  buffer  at  the
+          cursor.
+     yank-pop (M-y)
+          Rotate the kill-ring, and yank the new top.  Only works
+          following yank or yank-pop.
+
+  Numeric Arguments
+     digit-argument (M-0, M-1, ..., M--)
+          Add this digit to the argument already accumulating, or
+          start a new argument.  M-- starts a negative argument.
+     universal-argument
+          Each time this is executed, the argument count is  mul-
+          tiplied  by four.  The argument count is initially one,
+          so executing this function the  first  time  makes  the
+          argument  count four.  By default, this is not bound to
+          a key.
+
+  Completing
+     complete (TAB)
+          Attempt to perform completion on the text before point.
+          Bash  attempts  completion treating the text as a vari-
+          able (if the text begins with $), username (if the text
+          begins  with  ~), hostname (if the text begins with @),
+          or command (including aliases and functions)  in  turn.
+          If  none of these produces a match, filename completion
+          is attempted.
+
+
+
+GNU                  Last change: 1995 May 5                   35
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     possible-completions (M-?)
+          List the possible completions of the text before point.
+     insert-completions
+          Insert all completions of the text  before  point  that
+          would  have been generated by possible-completions.  By
+          default, this is not bound to a key.
+     complete-filename (M-/)
+          Attempt filename completion on the text before point.
+     possible-filename-completions (C-x /)
+          List the possible completions of the text before point,
+          treating it as a filename.
+     complete-username (M-~)
+          Attempt completion on the text before  point,  treating
+          it as a username.
+     possible-username-completions (C-x ~)
+          List the possible completions of the text before point,
+          treating it as a username.
+     complete-variable (M-$)
+          Attempt completion on the text before  point,  treating
+          it as a shell variable.
+     possible-variable-completions (C-x $)
+          List the possible completions of the text before point,
+          treating it as a shell variable.
+     complete-hostname (M-@)
+          Attempt completion on the text before  point,  treating
+          it as a hostname.
+     possible-hostname-completions (C-x @)
+          List the possible completions of the text before point,
+          treating it as a hostname.
+     complete-command (M-!)
+          Attempt completion on the text before  point,  treating
+          it  as  a command name.  Command completion attempts to
+          match the text against aliases, reserved  words,  shell
+          functions,  builtins, and finally executable filenames,
+          in that order.
+     possible-command-completions (C-x !)
+          List the possible completions of the text before point,
+          treating it as a command name.
+     dynamic-complete-history (M-TAB)
+          Attempt completion on the text before point,  comparing
+          the text against lines from the history list for possi-
+          ble completion matches.
+     complete-into-braces (M-{)
+          Perform filename completion and return the list of pos-
+          sible completions enclosed within braces so the list is
+          available to the shell (see Brace Expansion above).
+
+  Keyboard Macros
+     start-kbd-macro (C-x ()
+          Begin saving the characters typed into the current key-
+          board macro.
+     end-kbd-macro (C-x ))
+
+
+
+GNU                  Last change: 1995 May 5                   36
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          Stop saving the characters typed into the current  key-
+          board macro and save the definition.
+     call-last-kbd-macro (C-x e)
+          Re-execute the last keyboard macro defined,  by  making
+          the  characters  in the macro appear as if typed at the
+          keyboard.
+
+  Miscellaneous
+     re-read-init-file (C-x C-r)
+          Read in the contents of your init file, and incorporate
+          any bindings or variable assignments found there.
+     abort (C-g)
+          Abort  the  current  editing  command  and   ring   the
+          terminal's bell (subject to the setting of bell-style).
+     do-uppercase-version (M-a, M-b, ...)
+          Run the command that  is  bound  to  the  corresponding
+          uppercase character.
+     prefix-meta (ESC)
+          Metafy the next character typed.  ESC f  is  equivalent
+          to Meta-f.
+     undo (C-_, C-x C-u)
+          Incremental undo, separately remembered for each line.
+     revert-line (M-r)
+          Undo all changes made to this line.  This is like  typ-
+          ing the undo command enough times to return the line to
+          its initial state.
+     tilde-expand (M-~)
+          Perform tilde expansion on the current word.
+     dump-functions
+          Print all of the functions and their  key  bindings  to
+          the  readline  output stream.  If a numeric argument is
+          supplied, the output is formatted in such a way that it
+          can be made part of an _\bi_\bn_\bp_\bu_\bt_\br_\bc file.
+     display-shell-version (C-x C-v)
+          Display version information about the current  instance
+          of bash.
+
+HISTORY
+     When interactive, the shell provides access to  the  _\bc_\bo_\bm_\bm_\ba_\bn_\bd
+     _\bh_\bi_\bs_\bt_\bo_\br_\by, the list of commands previously typed.  The text of
+     the last HISTSIZE commands (default 500) is saved in a  his-
+     tory  list.   The  shell  stores each command in the history
+     list prior to parameter and variable expansion  (see  EXPAN-
+     SION  above)  but after history expansion is performed, sub-
+     ject   to   the    values    of    the    shell    variables
+     command_oriented_history  and  HISTCONTROL.  On startup, the
+     history is initialized from the file named by  the  variable
+     HISTFILE  (default ~/._\bb_\ba_\bs_\bh__\bh_\bi_\bs_\bt_\bo_\br_\by).  HISTFILE is truncated,
+     if necessary, to contain no more  than  HISTFILESIZE  lines.
+     The  builtin  command  fc (see SHELL BUILTIN COMMANDS below)
+     may be used to list or edit and re-execute a portion of  the
+     history  list.   The  history builtin can be used to display
+
+
+
+GNU                  Last change: 1995 May 5                   37
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     the history list and  manipulate  the  history  file.   When
+     using  the  command-line editing, search commands are avail-
+     able in each editing mode that provide access to the history
+     list.   When  an  interactive shell exits, the last HISTSIZE
+     lines are copied from the  history  list  to  HISTFILE.   If
+     HISTFILE is unset, or if the history file is unwritable, the
+     history is not saved.
+
+HISTORY EXPANSION
+     The shell supports a history expansion feature that is simi-
+     lar to the history expansion in csh.  This section describes
+     what syntax features are available.  This feature is enabled
+     by default for interactive shells, and can be disabled using
+     the +H option to the set builtin command (see SHELL  BUILTIN
+     COMMANDS below).  Non-interactive shells do not perform his-
+     tory expansion.
+
+     History expansion is performed immediately after a  complete
+     line  is  read,  before  the shell breaks it into words.  It
+     takes place in two parts.  The first is to  determine  which
+     line  from  the previous history to use during substitution.
+     The second is to select portions of that line for  inclusion
+     into  the  current one.  The line selected from the previous
+     history is the _\be_\bv_\be_\bn_\bt, and the portions of that line that are
+     acted  upon are _\bw_\bo_\br_\bd_\bs.  The line is broken into words in the
+     same  fashion  as  when  reading  input,  so  that   several
+     _\bm_\be_\bt_\ba_\bc_\bh_\ba_\br_\ba_\bc_\bt_\be_\br-separated  words surrounded by quotes are con-
+     sidered as one word.  Only backslash (\) and  single  quotes
+     can  quote  the  history  escape  character,  which  is ! by
+     default.
+
+     The shell allows control of the various characters  used  by
+     the  history  expansion  mechanism  (see  the description of
+     histchars above under Shell Variables).
+
+  Event Designators
+     An event designator is a reference to a command  line  entry
+     in the history list.
+
+     !    Start a history substitution, except when followed by a
+          blank, newline, = or (.
+     !!   Refer to the previous command.  This is a  synonym  for
+          `!-1'.
+     !_\bn   Refer to command line _\bn.
+     !-_\bn  Refer to the current command line minus _\bn.
+     !_\bs_\bt_\br_\bi_\bn_\bg
+          Refer to the most recent command starting with _\bs_\bt_\br_\bi_\bn_\bg.
+     !?_\bs_\bt_\br_\bi_\bn_\bg[?]
+          Refer to the most recent command containing _\bs_\bt_\br_\bi_\bn_\bg.
+\e9     ^\e8_\bs_\bt_\br_\bi_\bn_\bg_\b1\e9^\e8_\bs_\bt_\br_\bi_\bn_\bg_\b2\e9^
+\e8          Quick substitution.  Repeat the last command, replacing
+          _\bs_\bt_\br_\bi_\bn_\bg_\b1      with      _\bs_\bt_\br_\bi_\bn_\bg_\b2.       Equivalent     to
+
+
+
+GNU                  Last change: 1995 May 5                   38
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          ``!!:s/_\bs_\bt_\br_\bi_\bn_\bg_\b1/_\bs_\bt_\br_\bi_\bn_\bg_\b2/'' (see Modifiers below).
+     !#   The entire command line typed so far.
+
+  Word Designators
+     A : separates the event specification from the word designa-
+     tor.  It can be omitted if the word designator begins with a
+     ^, $, *, or %.  Words are numbered from the beginning of the
+     line, with the first word being denoted by a 0 (zero).
+
+     0 (zero)
+          The zeroth word.  For the shell, this  is  the  command
+          word.
+     _\bn    The _\bnth word.
+     ^    The first argument.  That is, word 1.
+     $    The last argument.
+     %    The word matched by the most recent `?_\bs_\bt_\br_\bi_\bn_\bg?' search.
+     _\bx-_\by  A range of words; `-_\by' abbreviates `0-_\by'.
+     *    All of the words but the zeroth.  This is a synonym for
+          `_\b1-$'.   It  is  not an error to use * if there is just
+          one word in the event; the empty string is returned  in
+          that case.
+     x*   Abbreviates _\bx-$.
+     x-   Abbreviates _\bx-$ like x*, but omits the last word.
+
+  Modifiers
+     After the optional word designator, you can add  a  sequence
+     of  one or more of the following modifiers, each preceded by
+     a `:'.
+
+     h    Remove a trailing pathname component, leaving only  the
+          head.
+     r    Remove a trailing suffix of the form ._\bx_\bx_\bx, leaving  the
+          basename.
+     e    Remove all but the trailing suffix.
+     t    Remove all leading  pathname  components,  leaving  the
+          tail.
+     p    Print the new command but do not execute it.
+     q    Quote the substituted words, escaping further substitu-
+          tions.
+     x    Quote the substituted words as with q, but  break  into
+          words at blanks and newlines.
+     s/_\bo_\bl_\bd/_\bn_\be_\bw/
+          Substitute _\bn_\be_\bw for the first occurrence of _\bo_\bl_\bd  in  the
+          event  line.   Any delimiter can be used in place of /.
+          The final delimiter is optional if it is the last char-
+          acter  of  the event line.  The delimiter may be quoted
+          in _\bo_\bl_\bd and _\bn_\be_\bw with a single backslash.  If  &  appears
+          in _\bn_\be_\bw, it is replaced by _\bo_\bl_\bd.  A single backslash will
+          quote the &.
+     &    Repeat the previous substitution.
+     g    Cause changes to be applied over the entire event line.
+          This   is   used   in   conjunction  with  `:s'  (e.g.,
+
+
+
+GNU                  Last change: 1995 May 5                   39
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          `:gs/_\bo_\bl_\bd/_\bn_\be_\bw/') or `:&'.  If used with `:s', any delim-
+          iter can be used in place of /, and the final delimiter
+          is optional if it is the last character  of  the  event
+          line.
+
+ARITHMETIC EVALUATION
+     The shell allows arithmetic  expressions  to  be  evaluated,
+     under certain circumstances (see the let builtin command and
+     Arithmetic Expansion).  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.  The lev-
+     els are listed in order of decreasing precedence.
+
+     - +  unary minus and plus
+     ! ~  logical and bitwise negation
+     * / %
+          multiplication, division, remainder
+     + -  addition, subtraction
+     << >>
+          left and right bitwise shifts
+     <= >= < >
+          comparison
+     == !=
+          equality and inequality
+     &    bitwise AND
+     ^    bitwise exclusive OR
+     |    bitwise OR
+     &&   logical AND
+     ||   logical OR
+     = *= /= %= += -=
+          assignment
+
+     Shell variables are allowed as operands; parameter expansion
+     is  performed  before the expression is evaluated. The value
+     of a parameter is  coerced  to  a  long  integer  within  an
+     expression.   A  shell  variable  need  not have its integer
+     attribute turned on to be used in an expression.
+
+     Constants with a leading 0 are interpreted as octal numbers.
+     A  leading _\b0_\bx or _\b0_\bX denotes hexadecimal.  Otherwise, numbers
+     take the form [_\bb_\ba_\bs_\be#]n,  where  _\bb_\ba_\bs_\be  is  a  decimal  number
+     between  2 and 36 representing the arithmetic base, and _\bn is
+     a number in that base.  If _\bb_\ba_\bs_\be is omitted, then base 10  is
+     used.
+
+     Operators  are  evaluated  in  order  of  precedence.   Sub-
+     expressions in parentheses are evaluated first and may over-
+     ride the precedence rules above.
+
+SHELL BUILTIN COMMANDS
+     : [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]
+
+
+
+GNU                  Last change: 1995 May 5                   40
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          No effect; the command does  nothing  beyond  expanding
+          _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs and performing any specified redirections.  A
+          zero exit code is returned.
+
+      .  _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]
+     source _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]
+          Read and execute commands from _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be in the  current
+          shell  environment  and  return  the exit status of the
+          last command executed from _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be.  If _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be  does
+          not contain a slash, pathnames in PATH are used to find
+          the directory containing _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be.  The  file  searched
+          for in PATH need not be executable.  The current direc-
+          tory is searched if no file is found in PATH.   If  any
+          _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs  are  supplied,  they  become  the positional
+          parameters when _\bf_\bi_\bl_\be is executed.  Otherwise the  posi-
+          tional  parameters are unchanged.  The return status is
+          the status of the last command exited within the script
+          (0  if no commands are executed), and false if _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be
+          is not found.
+
+     alias [_\bn_\ba_\bm_\be[=_\bv_\ba_\bl_\bu_\be] ...]
+          Alias with no arguments prints the list of  aliases  in
+          the form _\bn_\ba_\bm_\be=_\bv_\ba_\bl_\bu_\be on standard output.  When arguments
+          are supplied, an alias is defined for each  _\bn_\ba_\bm_\be  whose
+          _\bv_\ba_\bl_\bu_\be  is  given.  A trailing space in _\bv_\ba_\bl_\bu_\be causes the
+          next word to be checked for alias substitution when the
+          alias  is expanded.  For each _\bn_\ba_\bm_\be in the argument list
+          for which no _\bv_\ba_\bl_\bu_\be is supplied, the name and  value  of
+          the alias is printed.  Alias returns true unless a _\bn_\ba_\bm_\be
+          is given for which no alias has been defined.
+
+     bg [_\bj_\bo_\bb_\bs_\bp_\be_\bc]
+          Place _\bj_\bo_\bb_\bs_\bp_\be_\bc in the background,  as  if  it  had  been
+          started with &.  If _\bj_\bo_\bb_\bs_\bp_\be_\bc is not present, the shell's
+          notion of the _\bc_\bu_\br_\br_\be_\bn_\bt _\bj_\bo_\bb is used.  bg _\bj_\bo_\bb_\bs_\bp_\be_\bc  returns
+          0  unless run when job control is disabled or, when run
+          with job control enabled, if _\bj_\bo_\bb_\bs_\bp_\be_\bc was not  found  or
+          started without job control.
+
+     bind [-m _\bk_\be_\by_\bm_\ba_\bp] [-lvd] [-q _\bn_\ba_\bm_\be]
+     bind [-m _\bk_\be_\by_\bm_\ba_\bp] -f _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be
+     bind [-m _\bk_\be_\by_\bm_\ba_\bp] _\bk_\be_\by_\bs_\be_\bq:_\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn-_\bn_\ba_\bm_\be
+          Display current readline key and function bindings,  or
+          bind  a  key  sequence to a readline function or macro.
+          The binding syntax accepted is  identical  to  that  of
+          ._\bi_\bn_\bp_\bu_\bt_\br_\bc, but each binding must be passed as a separate
+          argument;   e.g.,   '"\C-x\C-r":    re-read-init-file'.
+          Options, if supplied, have the following meanings:
+          -m _\bk_\be_\by_\bm_\ba_\bp
+               Use _\bk_\be_\by_\bm_\ba_\bp as the keymap to  be  affected  by  the
+               subsequent  bindings.  Acceptable _\bk_\be_\by_\bm_\ba_\bp names are
+               _\be_\bm_\ba_\bc_\bs, _\be_\bm_\ba_\bc_\bs-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd, _\be_\bm_\ba_\bc_\bs-_\bm_\be_\bt_\ba, _\be_\bm_\ba_\bc_\bs-_\bc_\bt_\bl_\bx, _\bv_\bi,
+
+
+
+GNU                  Last change: 1995 May 5                   41
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+               _\bv_\bi-_\bm_\bo_\bv_\be,   _\bv_\bi-_\bc_\bo_\bm_\bm_\ba_\bn_\bd,   and   _\bv_\bi-_\bi_\bn_\bs_\be_\br_\bt.   _\bv_\bi  is
+               equivalent to _\bv_\bi-_\bc_\bo_\bm_\bm_\ba_\bn_\bd; _\be_\bm_\ba_\bc_\bs is  equivalent  to
+               _\be_\bm_\ba_\bc_\bs-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd.
+          -l   List the names of all readline functions
+          -v   List current function names and bindings
+          -d   Dump function names and bindings  in  such  a  way
+               that they can be re-read
+          -f _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be
+               Read key bindings from _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be
+          -q _\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn
+               Query about which keys invoke the named _\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn
+
+          The return value is 0 unless an unrecognized option  is
+          given or an error occurred.
+
+     break [_\bn]
+          Exit from within a for, while, or until loop.  If _\bn  is
+          specified,  break  _\bn  levels.   _\bn must be >\b_ 1.  If _\bn is
+          greater than the number of enclosing loops, all enclos-
+          ing loops are exited.  The return value is 0 unless the
+          shell is not executing a loop when break is executed.
+
+     builtin _\bs_\bh_\be_\bl_\bl-_\bb_\bu_\bi_\bl_\bt_\bi_\bn [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]
+          Execute the specified shell builtin, passing  it  _\ba_\br_\bg_\bu_\b-
+          _\bm_\be_\bn_\bt_\bs, and return its exit status.  This is useful when
+          you wish to define a function whose name is the same as
+          a  shell  builtin,  but  need  the functionality of the
+          builtin within the function itself.  The cd builtin  is
+          commonly  redefined  this  way.   The  return status is
+          false if _\bs_\bh_\be_\bl_\bl-_\bb_\bu_\bi_\bl_\bt_\bi_\bn is not a shell builtin command.
+
+     cd [_\bd_\bi_\br]
+          Change the current directory to _\bd_\bi_\br.  The variable HOME
+          is  the  default  _\bd_\bi_\br.  The variable CDPATH defines the
+          search path for the directory containing _\bd_\bi_\br.  Alterna-
+          tive  directory  names are separated by a colon (:).  A
+          null directory name  in  CDPATH  is  the  same  as  the
+          current  directory,  i.e., ``.''.  If _\bd_\bi_\br begins with a
+          slash (/), then CDPATH is not used.  An argument  of  -
+          is  equivalent to $OLDPWD.  The return value is true if
+          the directory was successfully  changed;  false  other-
+          wise.
+
+     command [-pVv] _\bc_\bo_\bm_\bm_\ba_\bn_\bd [_\ba_\br_\bg ...]
+          Run _\bc_\bo_\bm_\bm_\ba_\bn_\bd with  _\ba_\br_\bg_\bs  suppressing  the  normal  shell
+          function  lookup.  Only  builtin  commands  or commands
+          found in the PATH are executed.  If the  -p  option  is
+          given,  the  search  for  _\bc_\bo_\bm_\bm_\ba_\bn_\bd  is performed using a
+          default value for PATH that is guaranteed to  find  all
+          of  the  standard  utilities.   If  either the -V or -v
+          option  is  supplied,  a  description  of  _\bc_\bo_\bm_\bm_\ba_\bn_\bd   is
+          printed.  The -v option causes a single word indicating
+
+
+
+GNU                  Last change: 1995 May 5                   42
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          the command or pathname used to invoke  _\bc_\bo_\bm_\bm_\ba_\bn_\bd  to  be
+          printed; the -V option produces a more verbose descrip-
+          tion.  An argument of -- disables option  checking  for
+          the  rest  of the arguments.  If the -V or -v option is
+          supplied, the exit status is 0 if  _\bc_\bo_\bm_\bm_\ba_\bn_\bd  was  found,
+          and  1  if  not.   If neither option is supplied and an
+          error occurred or _\bc_\bo_\bm_\bm_\ba_\bn_\bd cannot  be  found,  the  exit
+          status  is 127.  Otherwise, the exit status of the com-
+          mand builtin is the exit status of _\bc_\bo_\bm_\bm_\ba_\bn_\bd.
+
+     continue [_\bn]
+          Resume the next iteration of the enclosing for,  while,
+          or  until  loop.   If _\bn is specified, resume at the _\bnth
+          enclosing loop.  _\bn must be >\b_ 1.  If _\bn is  greater  than
+          the  number of enclosing loops, the last enclosing loop
+          (the `top-level' loop) is resumed.  The return value is
+          0  unless  the  shell is not executing a loop when con-
+          tinue is executed.
+
+     declare [-frxi] [_\bn_\ba_\bm_\be[=_\bv_\ba_\bl_\bu_\be]]
+     typeset [-frxi] [_\bn_\ba_\bm_\be[=_\bv_\ba_\bl_\bu_\be]]
+          Declare variables and/or give them attributes.   If  no
+          _\bn_\ba_\bm_\bes  are  given, then display the values of variables
+          instead.  The options can be used to restrict output to
+          variables with the specified attribute.
+          -f   Use function names only
+          -r   Make _\bn_\ba_\bm_\bes readonly.  These names cannot  then  be
+               assigned  values  by  subsequent assignment state-
+               ments.
+          -x   Mark _\bn_\ba_\bm_\bes for export to subsequent  commands  via
+               the environment.
+          -i   The variable is treated as an integer;  arithmetic
+               evaluation  (see  ARITHMETIC  EVALUATION ) is per-
+               formed when the variable is assigned a value.
+
+          Using `+'  instead  of  `-'  turns  off  the  attribute
+          instead.   When  used in a function, makes _\bn_\ba_\bm_\bes local,
+          as with the local  command.   The  return  value  is  0
+          unless  an illegal option is encountered, an attempt is
+          made to define a function using "-f  foo=bar",  one  of
+          the  _\bn_\ba_\bm_\be_\bs  is  not  a  legal  shell  variable name, an
+          attempt is made to  turn  off  readonly  status  for  a
+          readonly  variable,  or an attempt is made to display a
+          non-existant function with -f.
+
+     dirs [-l] [+/-n]
+          Display the list of currently  remembered  directories.
+          Directories  are  added to the list with the pushd com-
+          mand; the popd command moves back up through the list.
+          +n   displays the _\bnth entry counting from the  left  of
+               the  list  shown  by  dirs  when  invoked  without
+               options, starting with zero.
+
+
+
+GNU                  Last change: 1995 May 5                   43
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          -n   displays the _\bnth entry counting from the right  of
+               the  list  shown  by  dirs  when  invoked  without
+               options, starting with zero.
+          -l   produces a longer  listing;  the  default  listing
+               format uses a tilde to denote the home directory.
+
+          The return value is 0 unless an illegal option is  sup-
+          plied  or  _\bn  indexes  beyond  the end of the directory
+          stack.
+
+     echo [-neE] [_\ba_\br_\bg ...]
+          Output the  _\ba_\br_\bgs,  separated  by  spaces.   The  return
+          status  is  always 0.  If -n is specified, the trailing
+          newline is suppressed.  If  the  -e  option  is  given,
+          interpretation of the following backslash-escaped char-
+          acters  is  enabled.   The  -E  option   disables   the
+          interpretation of these escape characters, even on sys-
+          tems where they are interpreted by default.
+          \a   alert (bell)
+          \b   backspace
+          \c   suppress trailing newline
+          \f   form feed
+          \n   new line
+          \r   carriage return
+          \t   horizontal tab
+          \v   vertical tab
+          \\   backslash
+          \nnn the character whose ASCII code is _\bn_\bn_\bn (octal)
+
+     enable [-n] [-all] [_\bn_\ba_\bm_\be ...]
+          Enable and disable builtin shell commands.  This allows
+          the execution of a disk command which has the same name
+          as a shell builtin without specifying a full  pathname.
+          If  -n is used, each _\bn_\ba_\bm_\be is disabled; otherwise, _\bn_\ba_\bm_\be_\bs
+          are enabled.  For example, to use the test binary found
+          via the PATH instead of the shell builtin version, type
+          ``enable -n test''.  If no arguments are given, a  list
+          of  all  enabled shell builtins is printed.  If only -n
+          is  supplied,  a  list  of  all  disabled  builtins  is
+          printed.   If  only  -all is supplied, the list printed
+          includes all builtins, with an indication of whether or
+          not  each  is  enabled.  enable accepts -a as a synonym
+          for -all.  The return value is 0 unless a _\bn_\ba_\bm_\be is not a
+          shell builtin.
+
+     eval [_\ba_\br_\bg ...]
+          The _\ba_\br_\bgs are read and concatenated together into a sin-
+          gle command.  This command is then read and executed by
+          the shell, and its exit status is returned as the value
+          of  the  eval  command.   If there are no _\ba_\br_\bg_\bs, or only
+          null arguments, eval returns true.
+
+
+
+
+GNU                  Last change: 1995 May 5                   44
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     exec [[-] _\bc_\bo_\bm_\bm_\ba_\bn_\bd [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]]
+          If _\bc_\bo_\bm_\bm_\ba_\bn_\bd is specified, it replaces the shell.  No new
+          process is created.  The _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs become the arguments
+          to _\bc_\bo_\bm_\bm_\ba_\bn_\bd.  If the first  argument  is  -,  the  shell
+          places  a  dash  in  the  zeroth arg passed to _\bc_\bo_\bm_\bm_\ba_\bn_\bd.
+          This is what login does.  If the file  cannot  be  exe-
+          cuted  for  some reason, a non-interactive shell exits,
+          unless  the   shell   variable   no_exit_on_failed_exec
+          exists,  in which case it returns failure.  An interac-
+          tive shell returns failure if the file cannot  be  exe-
+          cuted.   If  _\bc_\bo_\bm_\bm_\ba_\bn_\bd is not specified, any redirections
+          take effect in the current shell, and the return status
+          is 0.
+
+     exit [_\bn]
+          Cause the shell to exit with a status of _\bn.   If  _\bn  is
+          omitted,  the  exit  status is that of the last command
+          executed.  A trap on EXIT is executed before the  shell
+          terminates.
+
+     export [-nf] [_\bn_\ba_\bm_\be[=_\bw_\bo_\br_\bd]] ...
+     export -p
+          The supplied _\bn_\ba_\bm_\be_\bs are marked for automatic  export  to
+          the  environment of subsequently executed commands.  If
+          the -f option is given, the _\bn_\ba_\bm_\be_\bs refer  to  functions.
+          If no _\bn_\ba_\bm_\be_\bs are given, or if the -p option is supplied,
+          a list of all names that are exported in this shell  is
+          printed.   The  -n option causes the export property to
+          be removed from the named variables.  An argument of --
+          disables option checking for the rest of the arguments.
+          export returns an exit status of 0  unless  an  illegal
+          option  is encountered, one of the _\bn_\ba_\bm_\be_\bs is not a legal
+          shell variable name, or -f is supplied with a _\bn_\ba_\bm_\be that
+          is not a function.
+
+     fc [-e _\be_\bn_\ba_\bm_\be] [-nlr] [_\bf_\bi_\br_\bs_\bt] [_\bl_\ba_\bs_\bt]
+     fc -s [_\bp_\ba_\bt=_\br_\be_\bp] [_\bc_\bm_\bd]
+          Fix Command.  In the first form, a  range  of  commands
+          from  _\bf_\bi_\br_\bs_\bt  to _\bl_\ba_\bs_\bt is selected from the history list.
+          _\bF_\bi_\br_\bs_\bt and _\bl_\ba_\bs_\bt may be specified as a string (to  locate
+          the  last  command  beginning with that string) or as a
+          number (an index into the history list, where  a  nega-
+          tive  number is used as an offset from the current com-
+          mand number).  If _\bl_\ba_\bs_\bt is not specified it  is  set  to
+          the  current  command  for  listing  (so that fc -l -10
+          prints the last 10 commands) and  to  _\bf_\bi_\br_\bs_\bt  otherwise.
+          If  _\bf_\bi_\br_\bs_\bt  is  not  specified it is set to the previous
+          command for editing and -16 for listing.
+
+          The -n flag suppresses the command numbers  when  list-
+          ing.   The  -r flag reverses the order of the commands.
+          If the -l flag is given, the  commands  are  listed  on
+
+
+
+GNU                  Last change: 1995 May 5                   45
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          standard  output.  Otherwise, the editor given by _\be_\bn_\ba_\bm_\be
+          is invoked on a file  containing  those  commands.   If
+          _\be_\bn_\ba_\bm_\be is not given, the value of the FCEDIT variable is
+          used, and the value of EDITOR if FCEDIT is not set.  If
+          neither  variable  is set, _\bv_\bi is used.  When editing is
+          complete, the edited commands are echoed and executed.
+
+          In the second form, _\bc_\bo_\bm_\bm_\ba_\bn_\bd is re-executed  after  each
+          instance  of _\bp_\ba_\bt is replaced by _\br_\be_\bp.  A useful alias to
+          use with this is ``r=fc -s'', so that typing  ``r  cc''
+          runs  the last command beginning with ``cc'' and typing
+          ``r'' re-executes the last command.
+
+          If the first form is used, the return value is 0 unless
+          an  illegal  option  is  encountered  or  _\bf_\bi_\br_\bs_\bt or _\bl_\ba_\bs_\bt
+          specify history lines out of range.  If the  -e  option
+          is  supplied, the return value is the value of the last
+          command executed or failure if an error occurs with the
+          temporary  file  of  commands.   If  the second form is
+          used, the return status is  that  of  the  command  re-
+          executed,  unless  _\bc_\bm_\bd does not specify a valid history
+          line, in which case fc returns failure.
+
+     fg [_\bj_\bo_\bb_\bs_\bp_\be_\bc]
+          Place _\bj_\bo_\bb_\bs_\bp_\be_\bc  in  the  foreground,  and  make  it  the
+          current  job.   If  _\bj_\bo_\bb_\bs_\bp_\be_\bc is not present, the shell's
+          notion of the _\bc_\bu_\br_\br_\be_\bn_\bt _\bj_\bo_\bb is used.  The return value is
+          that  of  the  command  placed  into the foreground, or
+          failure if run when job control is  disabled  or,  when
+          run  with  job  control  enabled,  if  _\bj_\bo_\bb_\bs_\bp_\be_\bc does not
+          specify a valid job or _\bj_\bo_\bb_\bs_\bp_\be_\bc specifies a job that was
+          started without job control.
+
+     getopts _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg _\bn_\ba_\bm_\be [_\ba_\br_\bg_\bs]
+          getopts is used by shell procedures to parse positional
+          parameters.   _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg  contains the option letters to
+          be recognized; if a letter is followed by a colon,  the
+          option is expected to have an argument, which should be
+          separated from it by white  space.   Each  time  it  is
+          invoked,  getopts  places  the next option in the shell
+          variable _\bn_\ba_\bm_\be, initializing _\bn_\ba_\bm_\be if it does not  exist,
+          and the index of the next argument to be processed into
+          the variable OPTIND.  OPTIND is initialized to  1  each
+          time  the  shell or a shell script is invoked.  When an
+          option requires an argument, getopts places that  argu-
+          ment  into  the  variable  OPTARG.   The shell does not
+          reset OPTIND automatically; it must be  manually  reset
+          between multiple calls to getopts within the same shell
+          invocation if a new set of parameters is to be used.
+
+          getopts can report errors in two ways.   If  the  first
+          character   of  _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg  is  a  colon,  _\bs_\bi_\bl_\be_\bn_\bt  error
+
+
+
+GNU                  Last change: 1995 May 5                   46
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          reporting is used.  In normal operation diagnostic mes-
+          sages  are  printed  when  illegal  options  or missing
+          option arguments  are  encountered.   If  the  variable
+          OPTERR is set to 0, no error message will be displayed,
+          even if the first  character  of  _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg  is  not  a
+          colon.
+
+          If an illegal option is seen,  getopts  places  ?  into
+          _\bn_\ba_\bm_\be  and,  if  not silent, prints an error message and
+          unsets OPTARG.  If getopts is silent, the option  char-
+          acter  found is placed in OPTARG and no diagnostic mes-
+          sage is printed.
+
+          If a required argument is not found, and getopts is not
+          silent,  a  question mark (?) is placed in _\bn_\ba_\bm_\be, OPTARG
+          is unset, and a  diagnostic  message  is  printed.   If
+          getopts  is  silent, then a colon (:) is placed in _\bn_\ba_\bm_\be
+          and OPTARG is set to the option character found.
+
+          getopts normally parses the positional parameters,  but
+          if  more  arguments  are  given in _\ba_\br_\bg_\bs, getopts parses
+          those instead.  getopts  returns  true  if  an  option,
+          specified  or  unspecified, is found.  It returns false
+          if the end  of  options  is  encountered  or  an  error
+          occurs.
+
+     hash [-r] [_\bn_\ba_\bm_\be]
+          For each _\bn_\ba_\bm_\be, the full  pathname  of  the  command  is
+          determined  and  remembered.   The -r option causes the
+          shell to forget all remembered locations.  If no  argu-
+          ments  are given, information about remembered commands
+          is printed.  An argument of -- disables option checking
+          for  the  rest  of the arguments.  The return status is
+          true unless a _\bn_\ba_\bm_\be is not found or an illegal option is
+          supplied.
+
+     help [_\bp_\ba_\bt_\bt_\be_\br_\bn]
+          Display helpful information about builtin commands.  If
+          _\bp_\ba_\bt_\bt_\be_\br_\bn  is  specified, help gives detailed help on all
+          commands matching _\bp_\ba_\bt_\bt_\be_\br_\bn;  otherwise  a  list  of  the
+          builtins  is printed.  The return status is 0 unless no
+          command matches _\bp_\ba_\bt_\bt_\be_\br_\bn.
+
+     history [_\bn]
+     history -rwan [_\bf_\bi_\bl_\be_\bn_\ba_\bm_\be]
+          With no options, display the command history list  with
+          line  numbers.   Lines  listed with a * have been modi-
+          fied.  An argument of _\bn lists only the  last  _\bn  lines.
+          If a non-option argument is supplied, it is used as the
+          name of the history file; if not, the value of HISTFILE
+          is  used.   Options,  if  supplied,  have the following
+          meanings:
+
+
+
+GNU                  Last change: 1995 May 5                   47
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          -a   Append the ``new'' history  lines  (history  lines
+               entered  since  the  beginning of the current bash
+               session) to the history file
+          -n   Read the history lines not already read  from  the
+               history file into the current history list.  These
+               are lines appended to the history file  since  the
+               beginning of the current bash session.
+          -r   Read the contents of the history file and use them
+               as the current history
+          -w   Write the current history  to  the  history  file,
+               overwriting the history file's contents.
+
+          The return value is  0  unless  an  illegal  option  is
+          encountered or an error occurs while reading or writing
+          the history file.
+
+     jobs [-lnp] [ _\bj_\bo_\bb_\bs_\bp_\be_\bc ... ]
+     jobs -x _\bc_\bo_\bm_\bm_\ba_\bn_\bd [ _\ba_\br_\bg_\bs ... ]
+          The first form lists the active jobs.   The  -l  option
+          lists  process  IDs  in addition to the normal informa-
+          tion; the -p option lists only the process  ID  of  the
+          job's  process  group  leader.   The -n option displays
+          only jobs that have changed status since last notified.
+          If  _\bj_\bo_\bb_\bs_\bp_\be_\bc  is given, output is restricted to informa-
+          tion about that job.  The return status is 0 unless  an
+          illegal  option is encountered or an illegal _\bj_\bo_\bb_\bs_\bp_\be_\bc is
+          supplied.
+
+          If the -x option is supplied, jobs replaces any _\bj_\bo_\bb_\bs_\bp_\be_\bc
+          found in _\bc_\bo_\bm_\bm_\ba_\bn_\bd or _\ba_\br_\bg_\bs with the corresponding process
+          group ID, and executes _\bc_\bo_\bm_\bm_\ba_\bn_\bd passing it _\ba_\br_\bg_\bs, return-
+          ing its exit status.
+
+     kill [-s sigspec | -sigspec] [_\bp_\bi_\bd | _\bj_\bo_\bb_\bs_\bp_\be_\bc] ...
+     kill -l [_\bs_\bi_\bg_\bn_\bu_\bm]
+          Send the signal named by _\bs_\bi_\bg_\bs_\bp_\be_\bc to the processes named
+          by  _\bp_\bi_\bd  or  _\bj_\bo_\bb_\bs_\bp_\be_\bc.   _\bs_\bi_\bg_\bs_\bp_\be_\bc is either a signal name
+          such as SIGKILL or a signal number.  If  _\bs_\bi_\bg_\bs_\bp_\be_\bc  is  a
+          signal  name,  the  name is case insensitive and may be
+          given with or without the SIG prefix.   If  _\bs_\bi_\bg_\bs_\bp_\be_\bc  is
+          not  present,  then SIGTERM is assumed.  An argument of
+          -l lists the signal names.  If any arguments  are  sup-
+          plied when -l is given, the names of the specified sig-
+          nals are listed, and the return status is 0.  An  argu-
+          ment of -- disables option checking for the rest of the
+          arguments.  kill returns true if at  least  one  signal
+          was  successfully  sent, or false if an error occurs or
+          an illegal option is encountered.
+
+     let _\ba_\br_\bg [_\ba_\br_\bg ...]
+          Each _\ba_\br_\bg is an arithmetic expression  to  be  evaluated
+          (see ARITHMETIC EVALUATION).  If the last _\ba_\br_\bg evaluates
+
+
+
+GNU                  Last change: 1995 May 5                   48
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          to 0, let returns 1; 0 is returned otherwise.
+
+     local [_\bn_\ba_\bm_\be[=_\bv_\ba_\bl_\bu_\be] ...]
+          For each argument, create a local variable named  _\bn_\ba_\bm_\be,
+          and assign it _\bv_\ba_\bl_\bu_\be.  When local is used within a func-
+          tion, it causes the variable _\bn_\ba_\bm_\be  to  have  a  visible
+          scope  restricted  to  that  function and its children.
+          With no operands, local writes a list  of  local  vari-
+          ables  to  the  standard output.  It is an error to use
+          local when not within a function.  The return status is
+          0  unless local is used outside a function, or an ille-
+          gal _\bn_\ba_\bm_\be is supplied.
+
+     logout
+          Exit a login shell.
+
+     popd [+/-n]
+          Removes entries from  the  directory  stack.   With  no
+          arguments,  removes  the  top directory from the stack,
+          and performs a cd to the new top directory.
+          +n   removes the _\bnth entry counting from  the  left  of
+               the  list  shown by dirs, starting with zero.  For
+               example: ``popd +0'' removes the first  directory,
+               ``popd +1'' the second.
+          -n   removes the _\bnth entry counting from the  right  of
+               the  list  shown by dirs, starting with zero.  For
+               example: ``popd -0'' removes the  last  directory,
+               ``popd -1'' the next to last.
+
+          If the popd command is successful, a dirs is  performed
+          as  well,  and  the  return  status is 0.  popd returns
+          false if an illegal option is encountered,  the  direc-
+          tory  stack  is  empty,  a non-existent directory stack
+          entry is specified, or the directory change fails.
+
+     pushd [_\bd_\bi_\br]
+     pushd +/-n
+          Adds a directory to the top of the directory stack,  or
+          rotates  the stack, making the new top of the stack the
+          current  working   directory.    With   no   arguments,
+          exchanges the top two directories and returns 0, unless
+          the directory stack is empty.
+          +n   Rotates  the  stack  so  that  the  _\bnth  directory
+               (counting from the left of the list shown by dirs)
+               is at the top.
+          -n   Rotates  the  stack  so  that  the  _\bnth  directory
+               (counting from the right) is at the top.
+          dir  adds _\bd_\bi_\br to the directory stack at the top, making
+               it the new current working directory.
+
+          If the pushd command is successful, a dirs is performed
+          as  well.   If  the first form is used, pushd returns 0
+
+
+
+GNU                  Last change: 1995 May 5                   49
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          unless the cd to _\bd_\bi_\br  fails.   With  the  second  form,
+          pushd  returns 0 unless the directory stack is empty, a
+          non-existant directory stack element is  specified,  or
+          the  directory  change  to  the  specified  new current
+          directory fails.
+
+     pwd  Print the absolute  pathname  of  the  current  working
+          directory.  The path printed contains no symbolic links
+          if the -P option to the set  builtin  command  is  set.
+          See  also  the description of nolinks under Shell Vari-
+          ables above).  The return status is 0 unless  an  error
+          occurs while reading the pathname of the current direc-
+          tory.
+
+     read [-r] [_\bn_\ba_\bm_\be ...]
+          One line is read from the standard input, and the first
+          word  is assigned to the first _\bn_\ba_\bm_\be, the second word to
+          the  second  _\bn_\ba_\bm_\be,  and  so  on,  with  leftover  words
+          assigned  to the last _\bn_\ba_\bm_\be.  Only the characters in IFS
+          are recognized as word delimiters.   If  no  _\bn_\ba_\bm_\be_\bs  are
+          supplied,  the  line  read  is assigned to the variable
+          REPLY.  The return code is zero, unless end-of-file  is
+          encountered.   If  the -r option is given, a backslash-
+          newline pair is not ignored, and the backslash is  con-
+          sidered to be part of the line.
+
+     readonly [-f] [_\bn_\ba_\bm_\be ...]
+     readonly -p
+          The given _\bn_\ba_\bm_\be_\bs are marked readonly and the  values  of
+          these  _\bn_\ba_\bm_\be_\bs  may  not be changed by subsequent assign-
+          ment.  If the -f  option  is  supplied,  the  functions
+          corresponding  to the _\bn_\ba_\bm_\be_\bs are so marked.  If no argu-
+          ments are given, or if the -p  option  is  supplied,  a
+          list  of all readonly names is printed.  An argument of
+          -- disables option checking for the rest of  the  argu-
+          ments.  The return status is 0 unless an illegal option
+          is encountered, one of the _\bn_\ba_\bm_\be_\bs is not a  legal  shell
+          variable  name,  or  -f is supplied with a _\bn_\ba_\bm_\be that is
+          not a function.
+
+     return [_\bn]
+          Causes a function to exit with the return value  speci-
+          fied  by _\bn.  If _\bn is omitted, the return status is that
+          of the last command executed in the function body.   If
+          used  outside  a  function,  but  during execution of a
+          script by the . (source) command, it causes  the  shell
+          to  stop  executing  that script and return either _\bn or
+          the exit status of the last command executed within the
+          script  as the exit status of the script.  If used out-
+          side a function and not during execution of a script by
+          ., the return status is false.
+
+
+
+
+GNU                  Last change: 1995 May 5                   50
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     set [--abefhkmnptuvxldCHP] [-o _\bo_\bp_\bt_\bi_\bo_\bn] [_\ba_\br_\bg ...]
+          -a      Automatically mark variables which are modified
+                  or  created  for  export  to the environment of
+                  subsequent commands.
+          -b      Cause the status of terminated background  jobs
+                  to  be reported immediately, rather than before
+                  the next  primary  prompt.   (Also  see  notify
+                  under Shell Variables above).
+          -e      Exit immediately if a _\bs_\bi_\bm_\bp_\bl_\be-_\bc_\bo_\bm_\bm_\ba_\bn_\bd (see SHELL
+                  GRAMMAR  above)  exits  with a non-zero status.
+                  The shell does not exit  if  the  command  that
+                  fails  is  part of an _\bu_\bn_\bt_\bi_\bl or _\bw_\bh_\bi_\bl_\be loop, part
+                  of an _\bi_\bf statement, part of a && or || list, or
+                  if the command's return value is being inverted
+                  via !.
+          -f      Disable pathname expansion.
+          -h      Locate and remember function commands as  func-
+                  tions  are defined.  Function commands are nor-
+                  mally looked up when the function is executed.
+          -k      All  keyword  arguments  are  placed   in   the
+                  environment  for a command, not just those that
+                  precede the command name.
+          -m      Monitor mode.  Job control  is  enabled.   This
+                  flag is on by default for interactive shells on
+                  systems  that  support  it  (see  JOB   CONTROL
+                  above).  Background processes run in a separate
+                  process group and a line containing their  exit
+                  status is printed upon their completion.
+          -n      Read commands but do not  execute  them.   This
+                  may  be used to check a shell script for syntax
+                  errors.   This  is  ignored   for   interactive
+                  shells.
+          -o _\bo_\bp_\bt_\bi_\bo_\bn-_\bn_\ba_\bm_\be
+                  The _\bo_\bp_\bt_\bi_\bo_\bn-_\bn_\ba_\bm_\be can be one of the following:
+                  allexport
+                          Same as -a.
+                  braceexpand
+                          The shell performs brace expansion (see
+                          Brace  Expansion above).  This is on by
+                          default.
+                  emacs   Use an emacs-style command line editing
+                          interface.   This is enabled by default
+                          when the shell is  interactive,  unless
+                          the  shell  is  started  with the -nol-
+                          ineediting option.
+                  errexit Same as -e.
+                  histexpand
+                          Same as -H.
+                  ignoreeof
+                          The effect is as if the  shell  command
+                          `IGNOREEOF=10'  had  been executed (see
+                          Shell Variables above).
+
+
+
+GNU                  Last change: 1995 May 5                   51
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+                  interactive-comments
+                          Allow a word beginning with # to  cause
+                          that  word and all remaining characters
+                          on  that  line  to  be  ignored  in  an
+                          interactive shell (see COMMENTS above).
+                  monitor Same as -m.
+                  noclobber
+                          Same as -C.
+                  noexec  Same as -n.
+                  noglob  Same as -f.
+                  nohash  Same as -d.
+                  notify  Same as -b.
+                  nounset Same as -u.
+                  physical
+                          Same as -P.
+                  posix   Change the behavior of bash  where  the
+                          default   operation  differs  from  the
+                          Posix  1003.2  standard  to  match  the
+                          standard.
+                  privileged
+                          Same as -p.
+                  verbose Same as -v.
+                  vi      Use a  vi-style  command  line  editing
+                          interface.
+                  xtrace  Same as -x.
+                  If no _\bo_\bp_\bt_\bi_\bo_\bn-_\bn_\ba_\bm_\be is supplied,  the  values  of
+                  the current options are printed.
+          -p      Turn on _\bp_\br_\bi_\bv_\bi_\bl_\be_\bg_\be_\bd mode.   In  this  mode,  the
+                  $ENV file is not processed, and shell functions
+                  are not inherited from the  environment.   This
+                  is  enabled  automatically  on  startup  if the
+                  effective user (group) id is not equal  to  the
+                  real  user (group) id.  Turning this option off
+                  causes the effective user and group ids  to  be
+                  set to the real user and group ids.
+          -t      Exit after reading and executing one command.
+          -u      Treat unset variables as an error when perform-
+                  ing   parameter  expansion.   If  expansion  is
+                  attempted  on  an  unset  variable,  the  shell
+                  prints  an  error message, and, if not interac-
+                  tive, exits with a non-zero status.
+          -v      Print shell input lines as they are read.
+          -x      After  expanding  each   _\bs_\bi_\bm_\bp_\bl_\be-_\bc_\bo_\bm_\bm_\ba_\bn_\bd,   bash
+                  displays the expanded value of PS4, followed by
+                  the command and its expanded arguments.
+          -l      Save and restore the binding of _\bn_\ba_\bm_\be in  a  for
+                  _\bn_\ba_\bm_\be  [in  word]  command  (see  SHELL  GRAMMAR
+                  above).
+          -d      Disable the hashing of commands that are looked
+                  up   for  execution.   Normally,  commands  are
+                  remembered in a hash table, and once found,  do
+                  not have to be looked up again.
+
+
+
+GNU                  Last change: 1995 May 5                   52
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          -C      The  effect  is  as  if   the   shell   command
+                  `noclobber=' had been executed (see Shell Vari-
+                  ables above).
+          -H      Enable ! style history substitution.  This flag
+                  is on by default when the shell is interactive.
+          -P      If set, do not follow symbolic links when  per-
+                  forming  commands  such  as cd which change the
+                  current directory.  The physical  directory  is
+                  used instead.
+          --      If no arguments  follow  this  flag,  then  the
+                  positional  parameters  are  unset.  Otherwise,
+                  the positional parameters are set to the  _\ba_\br_\bgs,
+                  even if some of them begin with a -.
+          -       Signal the end of options, cause all  remaining
+                  _\ba_\br_\bgs  to  be assigned to the positional parame-
+                  ters.  The -x and -v options  are  turned  off.
+                  If there are no _\ba_\br_\bgs, the positional parameters
+                  remain unchanged.
+
+          The flags are off by default  unless  otherwise  noted.
+          Using  +  rather than - causes these flags to be turned
+          off.  The flags can also be specified as options to  an
+          invocation  of the shell.  The current set of flags may
+          be found in $-.  After the option  arguments  are  pro-
+          cessed,  the remaining _\bn _\ba_\br_\bgs are treated as values for
+          the positional parameters and are assigned,  in  order,
+          to $1, $2, ... $_\bn.  If no options or _\ba_\br_\bgs are supplied,
+          all shell variables are printed.  The return status  is
+          always true unless an illegal option is encountered.
+
+     shift [_\bn]
+          The positional parameters from _\bn+1 ... are  renamed  to
+          $1  ....  Parameters represented by the numbers $# down
+          to $#-_\bn+1 are unset.  If _\bn  is  0,  no  parameters  are
+          changed.   If _\bn is not given, it is assumed to be 1.  _\bn
+          must be a non-negative number less than or equal to $#.
+          If  _\bn is greater than $#, the positional parameters are
+          not changed.  The return status is greater than 0 if  _\bn
+          is greater than $# or less than 0; otherwise 0.
+
+     suspend [-f]
+          Suspend the execution of this shell until it receives a
+          SIGCONT  signal.  The -f option says not to complain if
+          this is a login shell; just suspend anyway.  The return
+          status is 0 unless the shell is a login shell and -f is
+          not supplied, or if job control is not enabled.
+
+     test _\be_\bx_\bp_\br
+     [ _\be_\bx_\bp_\br ]
+          Return a status of 0 (true) or 1 (false)  depending  on
+          the  evaluation  of  the  conditional  expression _\be_\bx_\bp_\br.
+          Expressions may be unary or binary.  Unary  expressions
+
+
+
+GNU                  Last change: 1995 May 5                   53
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          are  often used to examine the status of a file.  There
+          are string operators and numeric  comparison  operators
+          as  well.  Each operator and operand must be a separate
+          argument.  If _\bf_\bi_\bl_\be is of the form /dev/fd/_\bn, then  file
+          descriptor _\bn is checked.
+          -b _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is block special.
+          -c _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is character special.
+          -d _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is a directory.
+          -e _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists.
+          -f _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is a regular file.
+          -g _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is set-group-id.
+          -k _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be has its ``sticky'' bit set.
+          -L _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is a symbolic link.
+          -p _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is a named pipe.
+          -r _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is readable.
+          -s _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and has a  size  greater  than
+               zero.
+          -S _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is a socket.
+          -t _\bf_\bd
+               True if _\bf_\bd is opened on a terminal.
+          -u _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and  its  set-user-id  bit  is
+               set.
+          -w _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is writable.
+          -x _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is executable.
+          -O _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is owned by the  effective
+               user id.
+          -G _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is owned by the  effective
+               group id.
+          _\bf_\bi_\bl_\be_\b1 -nt _\bf_\bi_\bl_\be_\b2
+               True if _\bf_\bi_\bl_\be_\b1 is newer (according to  modification
+               date) than _\bf_\bi_\bl_\be_\b2.
+          _\bf_\bi_\bl_\be_\b1 -ot _\bf_\bi_\bl_\be_\b2
+               True if _\bf_\bi_\bl_\be_\b1 is older than file2.
+          _\bf_\bi_\bl_\be_\b1 -ef _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be_\b1 and _\bf_\bi_\bl_\be_\b2 have the same  device  and
+
+
+
+GNU                  Last change: 1995 May 5                   54
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+               inode numbers.
+          -z _\bs_\bt_\br_\bi_\bn_\bg
+               True if the length of _\bs_\bt_\br_\bi_\bn_\bg is zero.
+          -n _\bs_\bt_\br_\bi_\bn_\bg
+          _\bs_\bt_\br_\bi_\bn_\bg
+               True if the length of _\bs_\bt_\br_\bi_\bn_\bg is non-zero.
+          _\bs_\bt_\br_\bi_\bn_\bg_\b1 = _\bs_\bt_\br_\bi_\bn_\bg_\b2
+               True if the strings are equal.
+          _\bs_\bt_\br_\bi_\bn_\bg_\b1 != _\bs_\bt_\br_\bi_\bn_\bg_\b2
+               True if the strings are not equal.
+          ! _\be_\bx_\bp_\br
+               True if _\be_\bx_\bp_\br is false.
+          _\be_\bx_\bp_\br_\b1 -a _\be_\bx_\bp_\br_\b2
+               True if both _\be_\bx_\bp_\br_\b1 AND _\be_\bx_\bp_\br_\b2 are true.
+          _\be_\bx_\bp_\br_\b1 -o _\be_\bx_\bp_\br_\b2
+               True if either _\be_\bx_\bp_\br_\b1 OR _\be_\bx_\bp_\br_\b2 is true.
+          _\ba_\br_\bg_\b1 OP _\ba_\br_\bg_\b2
+               OP is one of -eq, -ne,  -lt,  -le,  -gt,  or  -ge.
+               These  arithmetic  binary operators return true if
+               _\ba_\br_\bg_\b1 is equal,  not-equal,  less-than,  less-than-
+               or-equal,  greater-than,  or greater-than-or-equal
+               than _\ba_\br_\bg_\b2, respectively.  _\bA_\br_\bg_\b1  and  _\ba_\br_\bg_\b2  may  be
+               positive  integers, negative integers, or the spe-
+               cial expression -l _\bs_\bt_\br_\bi_\bn_\bg, which evaluates to  the
+               length of _\bs_\bt_\br_\bi_\bn_\bg.
+
+     times
+          Print the accumulated user and  system  times  for  the
+          shell and for processes run from the shell.  The return
+          status is 0.
+
+     trap [-l] [_\ba_\br_\bg] [_\bs_\bi_\bg_\bs_\bp_\be_\bc]
+          The command _\ba_\br_\bg is to be read  and  executed  when  the
+          shell  receives signal(s) _\bs_\bi_\bg_\bs_\bp_\be_\bc.  If _\ba_\br_\bg is absent or
+          -, all specified signals are reset  to  their  original
+          values  (the  values  they  had  upon  entrance  to the
+          shell).  If _\ba_\br_\bg is  the  null  string  this  signal  is
+          ignored  by  the  shell and by the commands it invokes.
+          _\bs_\bi_\bg_\bs_\bp_\be_\bc is either a signal name defined in  <_\bs_\bi_\bg_\bn_\ba_\bl._\bh>,
+          or  a signal number. If _\bs_\bi_\bg_\bs_\bp_\be_\bc is EXIT (0) the command
+          _\ba_\br_\bg is executed on exit from the shell.  With no  argu-
+          ments, trap prints the list of commands associated with
+          each signal number.  The -l option causes the shell  to
+          print  a  list  of signal names and their corresponding
+          numbers.  An argument of --  disables  option  checking
+          for  the  rest  of the arguments.  Signals ignored upon
+          entry to the shell cannot be trapped or reset.  Trapped
+          signals  are  reset to their original values in a child
+          process when it is created.  The return status is false
+          if either the trap name or number is invalid; otherwise
+          trap returns true.
+
+
+
+
+GNU                  Last change: 1995 May 5                   55
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     type [-all] [-type | -path] _\bn_\ba_\bm_\be [_\bn_\ba_\bm_\be ...]
+          With no options, indicate how each _\bn_\ba_\bm_\be would be inter-
+          preted if used as a command name.  If the -type flag is
+          used, type prints a phrase which is one of _\ba_\bl_\bi_\ba_\bs,  _\bk_\be_\by_\b-
+          _\bw_\bo_\br_\bd,  _\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn,  _\bb_\bu_\bi_\bl_\bt_\bi_\bn, or _\bf_\bi_\bl_\be if _\bn_\ba_\bm_\be is an alias,
+          shell reserved word, function, builtin, or  disk  file,
+          respectively. If the name is not found, then nothing is
+          printed, and an exit status of false is  returned.   If
+          the -path flag is used, type either returns the name of
+          the disk file that  would  be  executed  if  _\bn_\ba_\bm_\be  were
+          specified  as a command name, or nothing if -type would
+          not return _\bf_\bi_\bl_\be.  If a command is hashed, -path  prints
+          the hashed value, not necessarily the file that appears
+          first in PATH.  If the -all flag is used,  type  prints
+          all  of  the  places  that  contain an executable named
+          _\bn_\ba_\bm_\be.  This includes aliases and functions, if and only
+          if  the  -path  flag  is  not  also used.  The table of
+          hashed commands is not consulted when using -all.  type
+          accepts  -a,  -t,  and  -p in place of -all, -type, and
+          -path, respectively.  An argument of -- disables option
+          checking  for  the rest of the arguments.  type returns
+          true if any of the arguments are found, false  if  none
+          are found.
+
+     ulimit [-SHacdfmstpnuv [_\bl_\bi_\bm_\bi_\bt]]
+          Ulimit provides control over the resources available to
+          the  shell  and  to processes started by it, on systems
+          that allow such control.  The value of _\bl_\bi_\bm_\bi_\bt can  be  a
+          number  in  the unit specified for the resource, or the
+          value unlimited.  The H and S options specify that  the
+          hard  or  soft  limit is set for the given resource.  A
+          hard limit cannot be increased once it is set;  a  soft
+          limit  may  be  increased  up  to the value of the hard
+          limit.  If neither H nor S is  specified,  the  command
+          applies  to  the  soft limit.  If _\bl_\bi_\bm_\bi_\bt is omitted, the
+          current value of the soft  limit  of  the  resource  is
+          printed,  unless the H option is given.  When more than
+          one resource is specified, the limit name and  unit  is
+          printed  before  the  value.   Other options are inter-
+          preted as follows:
+          -a   all current limits are reported
+          -c   the maximum size of core files created
+          -d   the maximum size of a process's data segment
+          -f   the maximum size of files created by the shell
+          -m   the maximum resident set size
+          -s   the maximum stack size
+          -t   the maximum amount of cpu time in seconds
+          -p   the pipe size in 512-byte blocks (this may not  be
+               set)
+          -n   the maximum number of open file descriptors  (most
+               systems  do  not  allow this value to be set, only
+               displayed)
+
+
+
+GNU                  Last change: 1995 May 5                   56
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          -u   the maximum number of  processes  available  to  a
+               single user
+          -v   The maximum amount of virtual memory available  to
+               the shell
+
+          An argument of -- disables option checking for the rest
+          of  the  arguments.   If  _\bl_\bi_\bm_\bi_\bt is given, it is the new
+          value of the  specified  resource  (the  -a  option  is
+          display  only).   If  no  option  is  given, then -f is
+          assumed.  Values are in  1024-byte  increments,  except
+          for  -t,  which is in seconds, -p, which is in units of
+          512-byte blocks, and -n  and  -u,  which  are  unscaled
+          values.   The  return  status  is  0  unless an illegal
+          option is encountered,  a  non-numeric  argument  other
+          than unlimited is supplied as _\bl_\bi_\bm_\bi_\bt, or an error occurs
+          while setting a new limit.
+
+     umask [-S] [_\bm_\bo_\bd_\be]
+          The user file-creation mask is set to  _\bm_\bo_\bd_\be.   If  _\bm_\bo_\bd_\be
+          begins  with  a  digit,  it  is interpreted as an octal
+          number; otherwise it is interpreted as a symbolic  mode
+          mask  similar to that accepted by _\bc_\bh_\bm_\bo_\bd(1).  If _\bm_\bo_\bd_\be is
+          omitted, or if the -S option is supplied,  the  current
+          value of the mask is printed.  The -S option causes the
+          mask to be printed in symbolic form; the default output
+          is  an octal number.  An argument of -- disables option
+          checking for the rest of  the  arguments.   The  return
+          status  is 0 if the mode was successfully changed or if
+          no _\bm_\bo_\bd_\be argument was supplied, and false otherwise.
+
+     unalias [-a] [_\bn_\ba_\bm_\be ...]
+          Remove _\bn_\ba_\bm_\bes from the list of defined aliases.   If  -a
+          is  supplied,  all  alias definitions are removed.  The
+          return value is true unless a supplied _\bn_\ba_\bm_\be  is  not  a
+          defined alias.
+
+     unset [-fv] [_\bn_\ba_\bm_\be ...]
+          For each _\bn_\ba_\bm_\be, remove the  corresponding  variable  or,
+          given  the -f option, function.  An argument of -- dis-
+          ables option checking for the rest  of  the  arguments.
+          Note that PATH, IFS, PPID, PS1, PS2, UID, and EUID can-
+          not be unset.  If any of RANDOM,  SECONDS,  LINENO,  or
+          HISTCMD  are unset, they lose their special properties,
+          even if they are subsequently reset.  The  exit  status
+          is  true  unless  a  _\bn_\ba_\bm_\be  does  not  exist  or is non-
+          unsettable.
+
+     wait [_\bn]
+          Wait for the specified process and return its  termina-
+          tion status.  _\bn may be a process ID or a job specifica-
+          tion; if a job spec is given,  all  processes  in  that
+          job's  pipeline are waited for.  If _\bn is not given, all
+
+
+
+GNU                  Last change: 1995 May 5                   57
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+          currently active child processes are  waited  for,  and
+          the  return  status  is  zero.   If  _\bn specifies a non-
+          existant process or job,  the  return  status  is  127.
+          Otherwise,  the return status is the exit status of the
+          last process or job waited for.
+
+INVOCATION
+     A _\bl_\bo_\bg_\bi_\bn _\bs_\bh_\be_\bl_\bl is one whose first character of argument  zero
+     is a -, or one started with the -login flag.
+
+     An _\bi_\bn_\bt_\be_\br_\ba_\bc_\bt_\bi_\bv_\be shell is one whose standard input and  output
+     are   both   connected   to   terminals  (as  determined  by
+     _\bi_\bs_\ba_\bt_\bt_\by(3)), or one started with the -i option.  PS1  is  set
+     and  $-  includes i if bash is interactive, allowing a shell
+     script or a startup file to test this state.
+
+     Login shells:
+       On login (subject to the -noprofile option):
+             if /_\be_\bt_\bc/_\bp_\br_\bo_\bf_\bi_\bl_\be exists, source it.
+
+             if ~/._\bb_\ba_\bs_\bh__\bp_\br_\bo_\bf_\bi_\bl_\be exists, source it,
+               else if ~/._\bb_\ba_\bs_\bh__\bl_\bo_\bg_\bi_\bn exists, source it,
+                 else if ~/._\bp_\br_\bo_\bf_\bi_\bl_\be exists, source it.
+
+       On exit:
+             if ~/._\bb_\ba_\bs_\bh__\bl_\bo_\bg_\bo_\bu_\bt exists, source it.
+
+     Non-login interactive shells:
+       On startup (subject to the -norc and -rcfile options):
+             if ~/._\bb_\ba_\bs_\bh_\br_\bc exists, source it.
+
+     Non-interactive shells:
+       On startup:
+             if the environment variable ENV is non-null, expand
+             it and source the file it names, as if the command
+                     if [ "$ENV" ]; then . $ENV; fi
+             had been executed, but do not use PATH to search
+             for the pathname.  When not started in Posix mode, bash
+             looks for BASH_ENV before ENV.
+
+     If Bash is invoked as sh, it tries to mimic the behavior  of
+     sh  as  closely as possible.  For a login shell, it attempts
+     to source only /_\be_\bt_\bc/_\bp_\br_\bo_\bf_\bi_\bl_\be and ~/._\bp_\br_\bo_\bf_\bi_\bl_\be, in  that  order.
+     The  -noprofile  option  may  still  be used to disable this
+     behavior.  A shell invoked as sh does not attempt to  source
+     any other startup files.
+
+     When bash is started in _\bp_\bo_\bs_\bi_\bx mode, as with the -posix  com-
+     mand  line option, it follows the Posix standard for startup
+     files.  In this mode, the ENV variable is expanded and  that
+     file sourced; no other startup files are read.
+
+
+
+
+GNU                  Last change: 1995 May 5                   58
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+SEE ALSO
+     _\bB_\ba_\bs_\bh _\bF_\be_\ba_\bt_\bu_\br_\be_\bs, Brian Fox and Chet Ramey
+     _\bT_\bh_\be _\bG_\bn_\bu _\bR_\be_\ba_\bd_\bl_\bi_\bn_\be _\bL_\bi_\bb_\br_\ba_\br_\by, Brian Fox and Chet Ramey
+     _\bT_\bh_\be _\bG_\bn_\bu _\bH_\bi_\bs_\bt_\bo_\br_\by _\bL_\bi_\bb_\br_\ba_\br_\by, Brian Fox and Chet Ramey
+Lennert
+     _\bA _\bS_\by_\bs_\bt_\be_\bm _\bV _\bC_\bo_\bm_\bp_\ba_\bt_\bi_\bb_\bl_\be _\bI_\bm_\bp_\bl_\be_\bm_\be_\bn_\bt_\ba_\bt_\bi_\bo_\bn _\bo_\bf _\b4._\b2_\bB_\bS_\bD _\bJ_\bo_\bb _\bC_\bo_\bn_\bt_\br_\bo_\bl, David
+_\bU_\bt_\bi_\bl_\bi_\bt_\bi_\be_\bs, IEEE
+     _\bP_\bo_\br_\bt_\ba_\bb_\bl_\be  _\bO_\bp_\be_\br_\ba_\bt_\bi_\bn_\bg  _\bS_\by_\bs_\bt_\be_\bm  _\bI_\bn_\bt_\be_\br_\bf_\ba_\bc_\be  (_\bP_\bO_\bS_\bI_\bX) _\bP_\ba_\br_\bt _\b2: _\bS_\bh_\be_\bl_\bl _\ba_\bn_\bd
+     _\bs_\bh(1), _\bk_\bs_\bh(1), _\bc_\bs_\bh(1)
+     _\be_\bm_\ba_\bc_\bs(1), _\bv_\bi(1)
+     _\br_\be_\ba_\bd_\bl_\bi_\bn_\be(3)
+
+FILES
+     /_\bb_\bi_\bn/_\bb_\ba_\bs_\bh
+          The bash executable
+     /_\be_\bt_\bc/_\bp_\br_\bo_\bf_\bi_\bl_\be
+          The systemwide initialization file, executed for  login
+          shells
+     ~/._\bb_\ba_\bs_\bh__\bp_\br_\bo_\bf_\bi_\bl_\be
+          The personal initialization file,  executed  for  login
+          shells
+     ~/._\bb_\ba_\bs_\bh_\br_\bc
+          The individual per-interactive-shell startup file
+     ~/._\bi_\bn_\bp_\bu_\bt_\br_\bc
+          Individual _\br_\be_\ba_\bd_\bl_\bi_\bn_\be initialization file
+
+AUTHORS
+          Brian Fox, Free Software Foundation (primary author)
+          bfox@ai.MIT.Edu
+
+          Chet Ramey, Case Western Reserve University
+          chet@ins.CWRU.Edu
+
+BUG REPORTS
+     If you find a bug in bash, you should report it.  But first,
+     you  should  make  sure that it really is a bug, and that it
+     appears in the latest version of bash that you have.
+
+     Once you have determined that a bug actually exists, use the
+     _\bb_\ba_\bs_\bh_\bb_\bu_\bg  command to submit a bug report.  If you have a fix,
+     you are welcome to mail that as well!  Suggestions and `phi-
+     losophical'    bug   reports   may   be   mailed   to   _\bb_\bu_\bg-
+     _\bb_\ba_\bs_\bh@_\bp_\br_\be_\bp._\ba_\bi._\bM_\bI_\bT._\bE_\bd_\bu  or  posted  to  the  Usenet  newsgroup
+     gnu.bash.bug.
+
+     ALL bug reports should include:
+
+     The version number of bash
+     The hardware and operating system
+     The compiler used to compile
+     A description of the bug behaviour
+     A short script or `recipe' which exercises the bug
+
+
+
+GNU                  Last change: 1995 May 5                   59
+
+
+
+
+
+
+BASH(1)                  USER COMMANDS                    BASH(1)
+
+
+
+     _\bb_\ba_\bs_\bh_\bb_\bu_\bg inserts the first three items automatically into the
+     template it provides for filing a bug report.
+
+     Comments and bug reports concerning this manual page  should
+     be directed to _\bc_\bh_\be_\bt@_\bi_\bn_\bs._\bC_\bW_\bR_\bU._\bE_\bd_\bu.
+
+BUGS
+     It's too big and too slow.
+
+     There are some subtle differences between  bash  and  tradi-
+     tional  versions of sh, mostly because of the POSIX specifi-
+     cation.
+
+     Aliases are confusing in some uses.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+GNU                  Last change: 1995 May 5                   60
+
+
+
diff --git a/documentation/builtins.1 b/documentation/builtins.1
new file mode 100644 (file)
index 0000000..553c107
--- /dev/null
@@ -0,0 +1,15 @@
+.\" 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 "1993 September 16" GNU
+.SH NAME
+bash, :, ., alias, bg, bind, break, builtin, bye, case, cd, command,
+continue, declare, dirs, echo, enable, eval, exec, exit, export, fc,
+fg, for, getopts, hash, help, history, if, jobs, kill, let, local,
+logout, popd, pushd, pwd, read, readonly, return, set, shift, source,
+suspend, test, times, trap, type, typeset, ulimit, umask, unalias,
+unset, until, wait, while \- bash built-in commands, see \fBbash\fR(1)
+.SH BASH BUILTIN COMMANDS
+.nr zZ 1
+.so bash.1
+.SH SEE ALSO
+bash(1), sh(1)
diff --git a/documentation/builtins.ps b/documentation/builtins.ps
new file mode 100644 (file)
index 0000000..ebac7d1
--- /dev/null
@@ -0,0 +1,1367 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%+ font Symbol
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 11
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+%%IncludeResource: font Symbol
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Times-Italic@0 ENC0/Times-Italic RE
+/Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S(SH_B).35 E(UIL)-.1 E 290.48
+(TINS\(1\) B)-.92 F(ASH_B)-.35 E(UIL)-.1 E(TINS\(1\))-.92 E/F1 9/Times-Bold@0
+SF -.18(NA)72 84 S(ME).18 E F0 .393(bash, :, ., alias, bg, bind, break, b)108
+96 R .392
+(uiltin, bye, case, cd, command, continue, declare, dirs, echo, enable, e)-.2 F
+-.25(va)-.25 G(l,).25 E -.15(exe)108 108 S .559(c, e).15 F .559(xit, e)-.15 F
+.559(xport, fc, fg, for)-.15 F 3.059(,g)-.4 G .559(etopts, hash, help, history)
+231.984 108 R 3.059(,i)-.65 G .56
+(f, jobs, kill, let, local, logout, popd, pushd, pwd,)343.57 108 R 1.562
+(read, readonly)108 120 R 4.062(,r)-.65 G 1.561(eturn, set, shift, source, sus\
+pend, test, times, trap, type, typeset, ulimit, umask, unalias,)176.004 120 R
+(unset, until, w)108 132 Q(ait, while \255 bash b)-.1 E(uilt-in commands, see)
+-.2 E/F2 10/Times-Bold@0 SF(bash)2.5 E F0(\(1\))A F1 -.27(BA)72 148.8 S(SH B)
+.27 E(UIL)-.09 E(TIN COMMANDS)-.828 E F2(:)108 160.8 Q F0([)2.5 E/F3 10
+/Times-Italic@0 SF(ar)A(guments)-.37 E F0(])A .501(No ef)144 172.8 R .501
+(fect; the command does nothing be)-.25 F .502(yond e)-.15 F(xpanding)-.15 E F3
+(ar)3.002 E(guments)-.37 E F0 .502(and performing an)3.002 F 3.002(ys)-.15 G
+(peci\214ed)508.34 172.8 Q 2.5(redirections. A)144 184.8 R(zero e)2.5 E
+(xit code is returned.)-.15 E F2(.)110.5 201.6 Q F3(\214lename)6.666 E F0([)2.5
+E F3(ar)A(guments)-.37 E F0(])A F2(sour)108 213.6 Q(ce)-.18 E F3(\214lename)2.5
+E F0([)2.5 E F3(ar)A(guments)-.37 E F0(])A 1.17(Read and e)144 225.6 R -.15(xe)
+-.15 G 1.17(cute commands from).15 F F3(\214lename)3.669 E F0 1.169
+(in the current shell en)3.669 F 1.169(vironment and return the e)-.4 F(xit)
+-.15 E 1.301(status of the last command e)144 237.6 R -.15(xe)-.15 G 1.301
+(cuted from).15 F F3(\214lename)3.801 E F0 6.301(.I).18 G(f)368.138 237.6 Q F3
+(\214lename)3.801 E F0 1.302(does not contain a slash, path-)3.801 F .608
+(names in)144 249.6 R F1 -.666(PA)3.108 G(TH)-.189 E F0 .608
+(are used to \214nd the directory containing)2.858 F F3(\214lename)3.108 E F0
+5.608(.T).18 G .608(he \214le searched for in)424.339 249.6 R F1 -.666(PA)3.108
+G(TH)-.189 E F0 .201(need not be e)144 261.6 R -.15(xe)-.15 G 2.701
+(cutable. The).15 F .201
+(current directory is searched if no \214le is found in)2.701 F F1 -.666(PA)
+2.701 G(TH)-.189 E/F4 9/Times-Roman@0 SF(.)A F0 .201(If an)4.701 F(y)-.15 E F3
+(ar)2.702 E(gu-)-.37 E(ments)144 273.6 Q F0 1.058(are supplied, the)3.558 F
+3.558(yb)-.15 G 1.058(ecome the positional parameters when)252.232 273.6 R F3
+(\214le)3.558 E F0 1.057(is e)3.557 F -.15(xe)-.15 G 3.557(cuted. Otherwise).15
+F(the)3.557 E 1.078(positional parameters are unchanged.)144 285.6 R 1.079
+(The return status is the status of the last command e)6.078 F(xited)-.15 E
+(within the script \(0 if no commands are e)144 297.6 Q -.15(xe)-.15 G
+(cuted\), and f).15 E(alse if)-.1 E F3(\214lename)2.5 E F0(is not found.)2.5 E
+F2(alias)108 314.4 Q F0([)2.5 E F3(name)A F0([=)A F3(value)A F0 2.5(].)C(..])
+193.9 314.4 Q F2(Alias)144 326.4 Q F0 1.668(with no ar)4.168 F 1.667
+(guments prints the list of aliases in the form)-.18 F F3(name)4.167 E F0(=)A
+F3(value)A F0 1.667(on standard output.)4.167 F .606(When ar)144 338.4 R .607
+(guments are supplied, an alias is de\214ned for each)-.18 F F3(name)3.107 E F0
+(whose)3.107 E F3(value)3.107 E F0 .607(is gi)3.107 F -.15(ve)-.25 G 3.107
+(n. A).15 F(trailing)3.107 E 2.693(space in)144 350.4 R F3(value)5.193 E F0
+2.693(causes the ne)5.193 F 2.693(xt w)-.15 F 2.693(ord to be check)-.1 F 2.692
+(ed for alias substitution when the alias is)-.1 F -.15(ex)144 362.4 S 2.867
+(panded. F).15 F .367(or each)-.15 F F3(name)2.867 E F0 .367(in the ar)2.867 F
+.367(gument list for which no)-.18 F F3(value)2.867 E F0 .367
+(is supplied, the name and v)2.867 F(alue)-.25 E 1.717
+(of the alias is printed.)144 374.4 R F2(Alias)6.717 E F0 1.717
+(returns true unless a)4.217 F F3(name)4.217 E F0 1.717(is gi)4.217 F -.15(ve)
+-.25 G 4.216(nf).15 G 1.716(or which no alias has been)425.61 374.4 R
+(de\214ned.)144 386.4 Q F2(bg)108 403.2 Q F0([)2.5 E F3(jobspec)A F0(])A(Place)
+144 415.2 Q F3(jobspec)3.485 E F0 .985
+(in the background, as if it had been started with)3.485 F F2(&)3.485 E F0
+5.985(.I)C(f)425.645 415.2 Q F3(jobspec)3.485 E F0 .985(is not present, the)
+3.485 F(shell')144 427.2 Q 3.102(sn)-.55 G .602(otion of the)177.662 427.2 R F3
+(curr)3.102 E .602(ent job)-.37 F F0 .602(is used.)3.102 F F2(bg)5.602 E F3
+(jobspec)3.102 E F0 .601(returns 0 unless run when job control is dis-)3.102 F
+.565(abled or)144 439.2 R 3.065(,w)-.4 G .565
+(hen run with job control enabled, if)189.44 439.2 R F3(jobspec)3.065 E F0 -.1
+(wa)3.065 G 3.065(sn).1 G .566(ot found or started without job con-)394.395
+439.2 R(trol.)144 451.2 Q F2(bind)108 468 Q F0([)2.5 E F2<ad6d>A F3 -.1(ke)2.5
+G(ymap)-.2 E F0 2.5(][)C F2(\255lvd)189.12 468 Q F0 2.5(][)C F2(-q)217.32 468 Q
+F3(name)2.5 E F0(])A F2(bind)108 480 Q F0([)2.5 E F2<ad6d>A F3 -.1(ke)2.5 G
+(ymap)-.2 E F0(])A F2(-f)2.5 E F3(\214lename)2.5 E F2(bind)108 492 Q F0([)2.5 E
+F2<ad6d>A F3 -.1(ke)2.5 G(ymap)-.2 E F0(])A F3 -.1(ke)2.5 G(yseq)-.2 E F0(:)A
+F3(function-name)A F0 .239(Display current)144 504 R F2 -.18(re)2.739 G(adline)
+.18 E F0 -.1(ke)2.739 G 2.739(ya)-.05 G .239(nd function bindings, or bind a k)
+267.836 504 R .538 -.15(ey s)-.1 H .238(equence to a).15 F F2 -.18(re)2.738 G
+(adline).18 E F0(function)2.738 E .88(or macro.)144 516 R .88
+(The binding syntax accepted is identical to that of)5.88 F F3(.inputr)3.38 E
+(c)-.37 E F0 3.38(,b).31 G .88(ut each binding must be)440.93 516 R .381
+(passed as a separate ar)144 528 R .381
+(gument; e.g., '"\\C-x\\C-r": re\255read\255init\255\214le'.)-.18 F .381
+(Options, if supplied, ha)5.381 F .68 -.15(ve t)-.2 H(he).15 E(follo)144 540 Q
+(wing meanings:)-.25 E F2<ad6d>144 552 Q F3 -.1(ke)2.5 G(ymap)-.2 E F0(Use)180
+564 Q F3 -.1(ke)5.174 G(ymap)-.2 E F0 2.674(as the k)5.174 F -.15(ey)-.1 G
+2.674(map to be af).15 F 2.674(fected by the subsequent bindings.)-.25 F
+(Acceptable)7.675 E F3 -.1(ke)180 576 S(ymap)-.2 E F0 2.929(names are)5.429 F
+F3 2.929(emacs, emacs-standar)5.429 F 2.929
+(d, emacs-meta, emacs-ctlx, vi, vi-mo)-.37 F(ve)-.1 E 5.428(,v)-.1 G(i-)533.89
+576 Q(command)180 588 Q F0 3.434(,a)C(nd)229.254 588 Q F3(vi-insert)3.434 E F0
+(.).68 E F3(vi)5.934 E F0 .934(is equi)3.434 F -.25(va)-.25 G .934(lent to).25
+F F3(vi-command)3.434 E F0(;)A F3(emacs)3.434 E F0 .934(is equi)3.434 F -.25
+(va)-.25 G .935(lent to).25 F F3(emacs-)3.435 E(standar)180 600 Q(d)-.37 E F0
+(.)A F2<ad6c>144 612 Q F0(List the names of all)180 612 Q F2 -.18(re)2.5 G
+(adline).18 E F0(functions)2.5 E F2<ad76>144 624 Q F0
+(List current function names and bindings)180 624 Q F2<ad64>144 636 Q F0
+(Dump function names and bindings in such a w)180 636 Q(ay that the)-.1 E 2.5
+(yc)-.15 G(an be re-read)423.89 636 Q F2<ad66>144 648 Q F3(\214lename)2.5 E F0
+(Read k)180 660 Q .3 -.15(ey b)-.1 H(indings from).15 E F3(\214lename)2.5 E F2
+<ad71>144 672 Q F3(function)2.5 E F0(Query about which k)180 684 Q -.15(ey)-.1
+G 2.5(si).15 G -1.9 -.4(nv o)282.51 684 T .2 -.1(ke t).4 H(he named).1 E F3
+(function)2.5 E F0(The return v)144 700.8 Q
+(alue is 0 unless an unrecognized option is gi)-.25 E -.15(ve)-.25 G 2.5(no).15
+G 2.5(ra)391.37 700.8 S 2.5(ne)401.64 700.8 S(rror occurred.)413.58 700.8 Q
+170.955(GNU 1993)72 768 R(September 16)2.5 E(1)535 768 Q EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S(SH_B).35 E(UIL)-.1 E 290.48
+(TINS\(1\) B)-.92 F(ASH_B)-.35 E(UIL)-.1 E(TINS\(1\))-.92 E/F1 10/Times-Bold@0
+SF(br)108 84 Q(eak)-.18 E F0([)2.5 E/F2 10/Times-Italic@0 SF(n)A F0(])A .076
+(Exit from within a)144 96 R F1 -.25(fo)2.576 G(r).25 E F0(,)A F1(while)2.576 E
+F0 2.576(,o)C(r)270.866 96 Q F1(until)2.576 E F0 2.576(loop. If)2.576 F F2(n)
+2.576 E F0 .076(is speci\214ed, break)2.576 F F2(n)2.576 E F0(le)2.576 E -.15
+(ve)-.25 G(ls.).15 E F2(n)5.075 E F0 .075(must be)2.575 F/F3 10/Symbol SF<b3>
+2.575 E F0 2.575(1. If)2.575 F F2(n)2.575 E F0(is)2.575 E .838
+(greater than the number of enclosing loops, all enclosing loops are e)144 108
+R 3.338(xited. The)-.15 F .838(return v)3.338 F .839(alue is 0)-.25 F
+(unless the shell is not e)144 120 Q -.15(xe)-.15 G(cuting a loop when).15 E F1
+(br)2.5 E(eak)-.18 E F0(is e)2.5 E -.15(xe)-.15 G(cuted.).15 E F1 -.2(bu)108
+136.8 S(iltin).2 E F2(shell\255b)2.5 E(uiltin)-.2 E F0([)2.5 E F2(ar)A(guments)
+-.37 E F0(])A(Ex)144 148.8 Q .793(ecute the speci\214ed shell b)-.15 F .793
+(uiltin, passing it)-.2 F F2(ar)3.293 E(guments)-.37 E F0 3.293(,a).27 G .793
+(nd return its e)382.104 148.8 R .792(xit status.)-.15 F .792(This is useful)
+5.792 F .603
+(when you wish to de\214ne a function whose name is the same as a shell b)144
+160.8 R .603(uiltin, b)-.2 F .603(ut need the func-)-.2 F .773
+(tionality of the b)144 172.8 R .773(uiltin within the function itself.)-.2 F
+(The)5.773 E F1(cd)3.273 E F0 -.2(bu)3.273 G .772
+(iltin is commonly rede\214ned this w).2 F(ay)-.1 E(.)-.65 E
+(The return status is f)144 184.8 Q(alse if)-.1 E F2(shell\255b)2.5 E(uiltin)
+-.2 E F0(is not a shell b)2.5 E(uiltin command.)-.2 E F1(cd)108 201.6 Q F0([)
+2.5 E F2(dir)A F0 5.17(]C)C .21(hange the current directory to)150.67 201.6 R
+F2(dir)2.71 E F0 5.21(.T)C .21(he v)298.01 201.6 R(ariable)-.25 E/F4 9
+/Times-Bold@0 SF(HOME)2.71 E F0 .21(is the def)2.46 F(ault)-.1 E F2(dir)2.71 E
+F0 5.21(.T).73 G .21(he v)456.703 201.6 R(ariable)-.25 E F4(CDP)2.71 E -.855
+(AT)-.666 G(H).855 E F0 .337
+(de\214nes the search path for the directory containing)144 213.6 R F2(dir)
+2.837 E F0 5.337(.A).73 G(lternati)379.663 213.6 Q .637 -.15(ve d)-.25 H .337
+(irectory names are separated).15 F .309(by a colon \(:\).)144 225.6 R 2.809
+(An)5.309 G .309(ull directory name in)221.365 225.6 R F4(CDP)2.809 E -.855(AT)
+-.666 G(H).855 E F0 .309(is the same as the current directory)2.559 F 2.809(,i)
+-.65 G .31(.e., `)496.44 225.6 R(`)-.74 E F1(.)A F0 -.74('')C 5.31(.I).74 G(f)
+536.67 225.6 Q F2(dir)144 237.6 Q F0(be)3.419 E .919
+(gins with a slash \(/\), then)-.15 F F4(CDP)3.419 E -.855(AT)-.666 G(H).855 E
+F0 .919(is not used.)3.169 F .918(An ar)5.918 F .918(gument of)-.18 F F1<ad>
+3.418 E F0 .918(is equi)3.418 F -.25(va)-.25 G .918(lent to).25 F F4($OLD-)
+3.418 E(PWD)144 249.6 Q/F5 9/Times-Roman@0 SF(.)A F0(The return v)4.5 E
+(alue is true if the directory w)-.25 E(as successfully changed; f)-.1 E
+(alse otherwise.)-.1 E F1(command)108 266.4 Q F0([)2.5 E F1(-pVv)A F0(])A F2
+(command)2.5 E F0([)2.5 E F2(ar)A(g)-.37 E F0(...])2.5 E(Run)144 278.4 Q F2
+(command)2.877 E F0(with)2.877 E F2(ar)2.877 E(gs)-.37 E F0 .378
+(suppressing the normal shell function lookup. Only b)2.877 F .378
+(uiltin commands or)-.2 F .559(commands found in the)144 290.4 R F4 -.666(PA)
+3.059 G(TH)-.189 E F0 .559(are e)2.809 F -.15(xe)-.15 G 3.059(cuted. If).15 F
+(the)3.059 E F1<ad70>3.059 E F0 .559(option is gi)3.059 F -.15(ve)-.25 G .558
+(n, the search for).15 F F2(command)3.058 E F0(is)3.058 E .231
+(performed using a def)144 302.4 R .231(ault v)-.1 F .231(alue for)-.25 F F1
+-.74(PA)2.731 G(TH)-.21 E F0 .231
+(that is guaranteed to \214nd all of the standard utilities.)2.731 F(If)5.232 E
+.232(either the)144 314.4 R F1<ad56>2.732 E F0(or)2.732 E F1<ad76>2.732 E F0
+.232(option is supplied, a description of)2.732 F F2(command)2.732 E F0 .232
+(is printed.)2.732 F(The)5.231 E F1<ad76>2.731 E F0 .231(option causes)2.731 F
+2.71(as)144 326.4 S .21(ingle w)155.04 326.4 R .21
+(ord indicating the command or pathname used to in)-.1 F -.2(vo)-.4 G -.1(ke).2
+G F2(command)2.811 E F0 .211(to be printed; the)2.711 F F1<ad56>2.711 E F0 .476
+(option produces a more v)144 338.4 R .476(erbose description.)-.15 F .476
+(An ar)5.476 F .476(gument of)-.18 F F1<adad>2.976 E F0 .475
+(disables option checking for the)2.976 F 1.348(rest of the ar)144 350.4 R
+3.848(guments. If)-.18 F(the)3.848 E F1<ad56>3.848 E F0(or)3.848 E F1<ad76>
+3.848 E F0 1.348(option is supplied, the e)3.848 F 1.349(xit status is 0 if)
+-.15 F F2(command)3.849 E F0 -.1(wa)3.849 G(s).1 E 1.306(found, and 1 if not.)
+144 362.4 R 1.305(If neither option is supplied and an error occurred or)6.306
+F F2(command)3.805 E F0 1.305(cannot be)3.805 F .092(found, the e)144 374.4 R
+.092(xit status is 127.)-.15 F .092(Otherwise, the e)5.092 F .092
+(xit status of the)-.15 F F1(command)2.592 E F0 -.2(bu)2.592 G .093
+(iltin is the e).2 F .093(xit status of)-.15 F F2(command)144 386.4 Q F0(.).77
+E F1(continue)108 403.2 Q F0([)2.5 E F2(n)A F0(])A .065(Resume the ne)144 415.2
+R .065(xt iteration of the enclosing)-.15 F F1 -.25(fo)2.565 G(r).25 E F0(,)A
+F1(while)2.565 E F0 2.564(,o)C(r)366.104 415.2 Q F1(until)2.564 E F0 2.564
+(loop. If)2.564 F F2(n)2.564 E F0 .064(is speci\214ed, resume at the)2.564 F F2
+(n)144 427.2 Q F0 1.168(th enclosing loop.)B F2(n)6.169 E F0 1.169(must be)
+3.669 F F3<b3>3.669 E F0 3.669(1. If)3.669 F F2(n)3.669 E F0 1.169
+(is greater than the number of enclosing loops, the last)3.669 F 1.594
+(enclosing loop \(the `top\255le)144 439.2 R -.15(ve)-.25 G 1.593
+(l' loop\) is resumed.).15 F 1.593(The return v)6.593 F 1.593
+(alue is 0 unless the shell is not)-.25 F -.15(exe)144 451.2 S
+(cuting a loop when).15 E F1(continue)2.5 E F0(is e)2.5 E -.15(xe)-.15 G
+(cuted.).15 E F1(declar)108 468 Q(e)-.18 E F0([)2.5 E F1(\255frxi)A F0 2.5(][)C
+F2(name)175.16 468 Q F0([=)A F2(value)A F0(]])A F1(typeset)108 480 Q F0([)2.5 E
+F1(\255frxi)A F0 2.5(][)C F2(name)174.23 480 Q F0([=)A F2(value)A F0(]])A 1.098
+(Declare v)144 492 R 1.098(ariables and/or gi)-.25 F 1.398 -.15(ve t)-.25 H
+1.098(hem attrib).15 F 3.598(utes. If)-.2 F(no)3.598 E F2(name)3.598 E F0 3.598
+(sa)C 1.098(re gi)394.362 492 R -.15(ve)-.25 G 1.098(n, then display the v).15
+F 1.098(alues of)-.25 F -.25(va)144 504 S 2.492(riables instead.).25 F 2.491
+(The options can be used to restrict output to v)7.492 F 2.491
+(ariables with the speci\214ed)-.25 F(attrib)144 516 Q(ute.)-.2 E F1<ad66>144
+528 Q F0(Use function names only)180 528 Q F1<ad72>144 540 Q F0(Mak)180 540 Q
+(e)-.1 E F2(name)5.046 E F0 5.046(sr)C(eadonly)241.642 540 Q 7.546(.T)-.65 G
+2.546(hese names cannot then be assigned v)288.808 540 R 2.547
+(alues by subsequent)-.25 F(assignment statements.)180 552 Q F1<ad78>144 564 Q
+F0(Mark)180 564 Q F2(name)2.5 E F0 2.5(sf)C(or e)235.54 564 Q
+(xport to subsequent commands via the en)-.15 E(vironment.)-.4 E F1<ad69>144
+576 Q F0 .558(The v)180 576 R .558(ariable is treated as an inte)-.25 F .558
+(ger; arithmetic e)-.15 F -.25(va)-.25 G .558(luation \(see).25 F F4 .557
+(ARITHMETIC EV)3.058 F(ALU)-1.215 E(A-)-.54 E(TION \))180 588 Q F0
+(is performed when the v)2.25 E(ariable is assigned a v)-.25 E(alue.)-.25 E
+1.218(Using `+' instead of `\255' turns of)144 604.8 R 3.719(ft)-.25 G 1.219
+(he attrib)289.369 604.8 R 1.219(ute instead.)-.2 F 1.219
+(When used in a function, mak)6.219 F(es)-.1 E F2(name)3.719 E F0(s)A .236
+(local, as with the)144 616.8 R F1(local)2.736 E F0 2.735(command. The)2.736 F
+.235(return v)2.735 F .235(alue is 0 unless an ille)-.25 F -.05(ga)-.15 G 2.735
+(lo).05 G .235(ption is encountered, an)443.755 616.8 R .435
+(attempt is made to de\214ne a function using "-f foo=bar", one of the)144
+628.8 R F2(names)2.935 E F0 .435(is not a le)2.935 F -.05(ga)-.15 G 2.935(ls)
+.05 G .435(hell v)503.435 628.8 R(ari-)-.25 E .52
+(able name, an attempt is made to turn of)144 640.8 R 3.019(fr)-.25 G .519
+(eadonly status for a readonly v)318.399 640.8 R .519
+(ariable, or an attempt is)-.25 F(made to display a non-e)144 652.8 Q
+(xistant function with -f.)-.15 E F1(dirs [-l] [+/\255n])108 669.6 Q F0 1.505
+(Display the list of currently remembered directories.)144 681.6 R 1.505
+(Directories are added to the list with the)6.505 F F1(pushd)144 693.6 Q F0
+(command; the)2.5 E F1(popd)2.5 E F0(command mo)2.5 E -.15(ve)-.15 G 2.5(sb).15
+G(ack up through the list.)331.5 693.6 Q F1(+n)144 705.6 Q F0 .13(displays the)
+180 705.6 R F2(n)2.63 E F0 .13(th entry counting from the left of the list sho)
+B .13(wn by)-.25 F F1(dirs)2.63 E F0 .13(when in)2.63 F -.2(vo)-.4 G -.1(ke).2
+G 2.63(dw).1 G(ith-)526.11 705.6 Q(out options, starting with zero.)180 717.6 Q
+170.955(GNU 1993)72 768 R(September 16)2.5 E(2)535 768 Q EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S(SH_B).35 E(UIL)-.1 E 290.48
+(TINS\(1\) B)-.92 F(ASH_B)-.35 E(UIL)-.1 E(TINS\(1\))-.92 E/F1 10/Times-Bold@0
+SF<ad6e>144 84 Q F0 1.342(displays the)180 84 R/F2 10/Times-Italic@0 SF(n)3.842
+E F0 1.342(th entry counting from the right of the list sho)B 1.342(wn by)-.25
+F F1(dirs)3.842 E F0 1.342(when in)3.842 F -.2(vo)-.4 G -.1(ke).2 G(d).1 E
+(without options, starting with zero.)180 96 Q F1<ad6c>144 108 Q F0 .362
+(produces a longer listing; the def)180 108 R .361
+(ault listing format uses a tilde to denote the home direc-)-.1 F(tory)180 120
+Q(.)-.65 E .38(The return v)144 136.8 R .38(alue is 0 unless an ille)-.25 F
+-.05(ga)-.15 G 2.88(lo).05 G .381(ption is supplied or)303.79 136.8 R F2(n)
+2.881 E F0(inde)2.881 E -.15(xe)-.15 G 2.881(sb).15 G -.15(ey)430.775 136.8 S
+.381(ond the end of the direc-).15 F(tory stack.)144 148.8 Q F1(echo)108 165.6
+Q F0([)2.5 E F1(\255neE)A F0 2.5(][)C F2(ar)164.8 165.6 Q(g)-.37 E F0(...])2.5
+E .267(Output the)144 177.6 R F2(ar)2.767 E(g)-.37 E F0 .267
+(s, separated by spaces.)B .267(The return status is al)5.267 F -.1(wa)-.1 G
+.266(ys 0.).1 F(If)5.266 E F1<ad6e>2.766 E F0 .266
+(is speci\214ed, the trailing)2.766 F(ne)144 189.6 Q .31(wline is suppressed.)
+-.25 F .311(If the)5.31 F F1<ad65>2.811 E F0 .311(option is gi)2.811 F -.15(ve)
+-.25 G .311(n, interpretation of the follo).15 F .311(wing backslash-escaped)
+-.25 F .874(characters is enabled.)144 201.6 R(The)5.874 E F1<ad45>3.374 E F0
+.874(option disables the interpretation of these escape characters, e)3.374 F
+-.15(ve)-.25 G(n).15 E(on systems where the)144 213.6 Q 2.5(ya)-.15 G
+(re interpreted by def)241.61 213.6 Q(ault.)-.1 E F1(\\a)144 225.6 Q F0
+(alert \(bell\))180 225.6 Q F1(\\b)144 237.6 Q F0(backspace)180 237.6 Q F1(\\c)
+144 249.6 Q F0(suppress trailing ne)180 249.6 Q(wline)-.25 E F1(\\f)144 261.6 Q
+F0(form feed)180 261.6 Q F1(\\n)144 273.6 Q F0(ne)180 273.6 Q 2.5(wl)-.25 G
+(ine)201.69 273.6 Q F1(\\r)144 285.6 Q F0(carriage return)180 285.6 Q F1(\\t)
+144 297.6 Q F0(horizontal tab)180 297.6 Q F1(\\v)144 309.6 Q F0 -.15(ve)180
+309.6 S(rtical tab).15 E F1(\\\\)144 321.6 Q F0(backslash)180 321.6 Q F1(\\nnn)
+144 333.6 Q F0(the character whose ASCII code is)180 333.6 Q F2(nnn)2.5 E F0
+(\(octal\))2.5 E F1(enable)108 350.4 Q F0([)2.5 E F1<ad6e>A F0 2.5(][)C F1
+(\255all)162.03 350.4 Q F0 2.5(][)C F2(name)187.45 350.4 Q F0(...])2.5 E .682
+(Enable and disable b)144 362.4 R .683(uiltin shell commands.)-.2 F .683
+(This allo)5.683 F .683(ws the e)-.25 F -.15(xe)-.15 G .683
+(cution of a disk command which).15 F .324(has the same name as a shell b)144
+374.4 R .324(uiltin without specifying a full pathname.)-.2 F(If)5.324 E F1
+<ad6e>2.824 E F0 .324(is used, each)2.824 F F2(name)2.823 E F0 .18
+(is disabled; otherwise,)144 386.4 R F2(names)2.68 E F0 .18(are enabled.)2.68 F
+-.15(Fo)5.18 G 2.68(re).15 G .181(xample, to use the)338.81 386.4 R F1(test)
+2.681 E F0 .181(binary found via the)2.681 F/F3 9/Times-Bold@0 SF -.666(PA)
+2.681 G(TH)-.189 E F0 .749(instead of the shell b)144 398.4 R .749(uiltin v)-.2
+F .749(ersion, type `)-.15 F .748(`enable -n test')-.74 F 3.248('. If)-.74 F
+.748(no ar)3.248 F .748(guments are gi)-.18 F -.15(ve)-.25 G .748
+(n, a list of all).15 F .424(enabled shell b)144 410.4 R .424
+(uiltins is printed.)-.2 F .424(If only)5.424 F F1<ad6e>2.924 E F0 .425
+(is supplied, a list of all disabled b)2.924 F .425(uiltins is printed.)-.2 F
+(If)5.425 E(only)144 422.4 Q F1(\255all)2.547 E F0 .047
+(is supplied, the list printed includes all b)2.547 F .046
+(uiltins, with an indication of whether or not each)-.2 F .28(is enabled.)144
+434.4 R F1(enable)5.28 E F0(accepts)2.78 E F1<ad61>2.78 E F0 .28(as a synon)
+2.78 F .28(ym for)-.15 F F1(\255all)2.78 E F0 5.28(.T)C .281(he return v)370.8
+434.4 R .281(alue is 0 unless a)-.25 F F2(name)2.781 E F0 .281(is not a)2.781 F
+(shell b)144 446.4 Q(uiltin.)-.2 E F1 -2.3 -.15(ev a)108 463.2 T(l).15 E F0([)
+2.5 E F2(ar)A(g)-.37 E F0(...])2.5 E(The)144 475.2 Q F2(ar)3.171 E(g)-.37 E F0
+3.171(sa)C .671(re read and concatenated together into a single command.)
+187.742 475.2 R .67(This command is then read)5.67 F .164(and e)144 487.2 R
+-.15(xe)-.15 G .164(cuted by the shell, and its e).15 F .165
+(xit status is returned as the v)-.15 F .165(alue of the)-.25 F F1 -2.3 -.15
+(ev a)2.665 H(l).15 E F0 2.665(command. If)2.665 F(there)2.665 E(are no)144
+499.2 Q F2(ar)2.5 E(gs)-.37 E F0 2.5(,o).27 G 2.5(ro)198.89 499.2 S
+(nly null ar)209.72 499.2 Q(guments,)-.18 E F1 -2.3 -.15(ev a)2.5 H(l).15 E F0
+(returns true.)2.5 E F1(exec)108 516 Q F0([[)2.5 E F1<ad>A F0(])A F2(command)
+2.5 E F0([)2.5 E F2(ar)A(guments)-.37 E F0(]])A(If)144 528 Q F2(command)2.91 E
+F0 .41(is speci\214ed, it replaces the shell.)2.91 F .41(No ne)5.41 F 2.91(wp)
+-.25 G .41(rocess is created.)371.42 528 R(The)5.41 E F2(ar)2.91 E(guments)-.37
+E F0(become)2.91 E 1.238(the ar)144 540 R 1.238(guments to)-.18 F F2(command)
+3.738 E F0 6.238(.I)C 3.738(ft)267.642 540 S 1.238(he \214rst ar)277.49 540 R
+1.238(gument is)-.18 F F1<ad>3.738 E F0 3.738(,t)C 1.239
+(he shell places a dash in the zeroth ar)376.42 540 R(g)-.18 E 1.049(passed to)
+144 552 R F2(command)3.549 E F0 6.049(.T).77 G 1.048(his is what login does.)
+239.847 552 R 1.048(If the \214le cannot be e)6.048 F -.15(xe)-.15 G 1.048
+(cuted for some reason, a).15 F(non-interacti)144 564 Q .91 -.15(ve s)-.25 H
+.611(hell e).15 F .611(xits, unless the shell v)-.15 F(ariable)-.25 E F1
+(no_exit_on_failed_exec)3.111 E F0 -.15(ex)3.111 G .611(ists, in which case).15
+F .333(it returns f)144 576 R 2.833(ailure. An)-.1 F(interacti)2.833 E .633
+-.15(ve s)-.25 H .333(hell returns f).15 F .332
+(ailure if the \214le cannot be e)-.1 F -.15(xe)-.15 G 2.832(cuted. If).15 F F2
+(command)2.832 E F0(is)2.832 E(not speci\214ed, an)144 588 Q 2.5(yr)-.15 G
+(edirections tak)219.95 588 Q 2.5(ee)-.1 G -.25(ff)289.83 588 S
+(ect in the current shell, and the return status is 0.).25 E F1(exit)108 604.8
+Q F0([)2.5 E F2(n)A F0 6.29(]C)C .122(ause the shell to e)150.67 604.8 R .122
+(xit with a status of)-.15 F F2(n)2.623 E F0 5.123(.I)C(f)315.064 604.8 Q F2(n)
+2.623 E F0 .123(is omitted, the e)2.623 F .123
+(xit status is that of the last command)-.15 F -.15(exe)144 616.8 S 2.5
+(cuted. A).15 F(trap on)2.5 E F3(EXIT)2.5 E F0(is e)2.25 E -.15(xe)-.15 G
+(cuted before the shell terminates.).15 E F1(export)108 633.6 Q F0([)2.5 E F1
+(\255nf)A F0 2.5(][).833 G F2(name)166.183 633.6 Q F0([=)A F2(wor)A(d)-.37 E F0
+(]] ...)A F1(export \255p)108 645.6 Q F0 .306(The supplied)144 657.6 R F2
+(names)2.806 E F0 .306(are mark)2.806 F .305(ed for automatic e)-.1 F .305
+(xport to the en)-.15 F .305(vironment of subsequently e)-.4 F -.15(xe)-.15 G
+(cuted).15 E 2.693(commands. If)144 669.6 R(the)2.693 E F1<ad66>2.693 E F0 .193
+(option is gi)2.693 F -.15(ve)-.25 G .193(n, the).15 F F2(names)2.693 E F0 .193
+(refer to functions.)2.693 F .193(If no)5.193 F F2(names)2.693 E F0 .193
+(are gi)2.693 F -.15(ve)-.25 G .194(n, or if the).15 F F1<ad70>144 681.6 Q F0
+.66(option is supplied, a list of all names that are e)3.16 F .659
+(xported in this shell is printed.)-.15 F(The)5.659 E F1<ad6e>3.159 E F0
+(option)3.159 E .537(causes the e)144 693.6 R .537(xport property to be remo)
+-.15 F -.15(ve)-.15 G 3.037(df).15 G .537(rom the named v)318.099 693.6 R 3.038
+(ariables. An)-.25 F(ar)3.038 E .538(gument of)-.18 F F1<adad>3.038 E F0
+(disables)3.038 E .666(option checking for the rest of the ar)144 705.6 R
+(guments.)-.18 E F1(export)5.665 E F0 .665(returns an e)3.165 F .665
+(xit status of 0 unless an ille)-.15 F -.05(ga)-.15 G(l).05 E .32
+(option is encountered, one of the)144 717.6 R F2(names)2.82 E F0 .32
+(is not a le)2.82 F -.05(ga)-.15 G 2.82(ls).05 G .32(hell v)366.18 717.6 R .32
+(ariable name, or)-.25 F F1<ad66>2.82 E F0 .32(is supplied with a)2.82 F F2
+(name)144 729.6 Q F0(that is not a function.)2.5 E 170.955(GNU 1993)72 768 R
+(September 16)2.5 E(3)535 768 Q EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S(SH_B).35 E(UIL)-.1 E 290.48
+(TINS\(1\) B)-.92 F(ASH_B)-.35 E(UIL)-.1 E(TINS\(1\))-.92 E/F1 10/Times-Bold@0
+SF(fc)108 84 Q F0([)2.5 E F1<ad65>A/F2 10/Times-Italic@0 SF(ename)2.5 E F0 2.5
+(][)C F1(\255nlr)169.5 84 Q F0 2.5(][)C F2<8c72>197.14 84 Q(st)-.1 E F0 2.5(][)
+C F2(last)221.76 84 Q F0(])A F1(fc \255s)108 96 Q F0([)2.5 E F2(pat)A F0(=)A F2
+-.37(re)C(p).37 E F0 2.5(][)C F2(cmd)174.23 96 Q F0(])A .665(Fix Command.)144
+108 R .665(In the \214rst form, a range of commands from)5.665 F F2<8c72>3.164
+E(st)-.1 E F0(to)3.164 E F2(last)3.164 E F0 .664(is selected from the his-)
+3.164 F .967(tory list.)144 120 R F2 -.45(Fi)5.967 G -.1(rs).45 G(t).1 E F0
+(and)3.467 E F2(last)3.467 E F0 .967
+(may be speci\214ed as a string \(to locate the last command be)3.467 F .968
+(ginning with)-.15 F .797(that string\) or as a number \(an inde)144 132 R
+3.297(xi)-.15 G .797(nto the history list, where a ne)300.756 132 R -.05(ga)
+-.15 G(ti).05 E 1.097 -.15(ve n)-.25 H .796(umber is used as an).15 F(of)144
+144 Q .321(fset from the current command number\).)-.25 F(If)5.322 E F2(last)
+2.822 E F0 .322(is not speci\214ed it is set to the current command)2.822 F
+.019(for listing \(so that)144 156 R F1 .019(fc \255l \25510)2.519 F F0 .019
+(prints the last 10 commands\) and to)2.519 F F2<8c72>2.519 E(st)-.1 E F0 2.519
+(otherwise. If)2.519 F F2<8c72>2.519 E(st)-.1 E F0 .019(is not spec-)2.519 F
+(i\214ed it is set to the pre)144 168 Q
+(vious command for editing and \25516 for listing.)-.25 E(The)144 192 Q F1
+<ad6e>2.92 E F0 .42(\215ag suppresses the command numbers when listing.)2.92 F
+(The)5.421 E F1<ad72>2.921 E F0 .421(\215ag re)2.921 F -.15(ve)-.25 G .421
+(rses the order of the).15 F 3.642(commands. If)144 204 R(the)3.642 E F1<ad6c>
+3.642 E F0 1.142(\215ag is gi)3.642 F -.15(ve)-.25 G 1.142
+(n, the commands are listed on standard output.).15 F 1.142(Otherwise, the)
+6.142 F .378(editor gi)144 216 R -.15(ve)-.25 G 2.878(nb).15 G(y)199.906 216 Q
+F2(ename)2.878 E F0 .378(is in)2.878 F -.2(vo)-.4 G -.1(ke).2 G 2.878(do).1 G
+2.878(na\214)285.708 216 S .378(le containing those commands.)306.464 216 R(If)
+5.378 E F2(ename)2.878 E F0 .379(is not gi)2.879 F -.15(ve)-.25 G .379(n, the)
+.15 F -.25(va)144 228 S .805(lue of the).25 F/F3 9/Times-Bold@0 SF(FCEDIT)3.305
+E F0 -.25(va)3.055 G .805(riable is used, and the v).25 F .805(alue of)-.25 F
+F3(EDIT)3.305 E(OR)-.162 E F0(if)3.054 E F3(FCEDIT)3.304 E F0 .804(is not set.)
+3.054 F .804(If neither)5.804 F -.25(va)144 240 S(riable is set, is used.).25 E
+(When editing is complete, the edited commands are echoed and e)5 E -.15(xe)
+-.15 G(cuted.).15 E .039(In the second form,)144 264 R F2(command)2.539 E F0
+.039(is re-e)2.539 F -.15(xe)-.15 G .039(cuted after each instance of).15 F F2
+(pat)2.54 E F0 .04(is replaced by)2.54 F F2 -.37(re)2.54 G(p).37 E F0 5.04(.A)C
+(useful)515.56 264 Q 1.009(alias to use with this is `)144 276 R 1.008
+(`r=fc \255s')-.74 F 1.008(', so that typing `)-.74 F 1.008(`r cc')-.74 F 3.508
+('r)-.74 G 1.008(uns the last command be)385.39 276 R 1.008(ginning with)-.15 F
+-.74(``)144 288 S(cc').74 E 2.5('a)-.74 G(nd typing `)171.66 288 Q(`r')-.74 E
+2.5('r)-.74 G(e-e)233.22 288 Q -.15(xe)-.15 G(cutes the last command.).15 E
+.426(If the \214rst form is used, the return v)144 312 R .427
+(alue is 0 unless an ille)-.25 F -.05(ga)-.15 G 2.927(lo).05 G .427
+(ption is encountered or)399.768 312 R F2<8c72>2.927 E(st)-.1 E F0(or)2.927 E
+F2(last)2.927 E F0 .455(specify history lines out of range.)144 324 R .454
+(If the)5.454 F F1<ad65>2.954 E F0 .454(option is supplied, the return v)2.954
+F .454(alue is the v)-.25 F .454(alue of the)-.25 F .787(last command e)144 336
+R -.15(xe)-.15 G .787(cuted or f).15 F .788
+(ailure if an error occurs with the temporary \214le of commands.)-.1 F .788
+(If the)5.788 F 1.196
+(second form is used, the return status is that of the command re-e)144 348 R
+-.15(xe)-.15 G 1.196(cuted, unless).15 F F2(cmd)3.696 E F0 1.196(does not)3.696
+F(specify a v)144 360 Q(alid history line, in which case)-.25 E F1(fc)2.5 E F0
+(returns f)2.5 E(ailure.)-.1 E F1(fg)108 376.8 Q F0([)2.5 E F2(jobspec)A F0(])A
+(Place)144 388.8 Q F2(jobspec)3.041 E F0 .541(in the fore)3.041 F .542
+(ground, and mak)-.15 F 3.042(ei)-.1 G 3.042(tt)323.06 388.8 S .542
+(he current job)331.662 388.8 R 5.542(.I)-.4 G(f)399.258 388.8 Q F2(jobspec)
+3.042 E F0 .542(is not present, the shell')3.042 F(s)-.55 E .958(notion of the)
+144 400.8 R F2(curr)3.458 E .958(ent job)-.37 F F0 .957(is used.)3.457 F .957
+(The return v)5.957 F .957(alue is that of the command placed into the fore-)
+-.25 F .194(ground, or f)144 412.8 R .194
+(ailure if run when job control is disabled or)-.1 F 2.695(,w)-.4 G .195
+(hen run with job control enabled, if)378.655 412.8 R F2(job-)2.695 E(spec)144
+424.8 Q F0(does not specify a v)2.5 E(alid job or)-.25 E F2(jobspec)2.5 E F0
+(speci\214es a job that w)2.5 E(as started without job control.)-.1 E F1
+(getopts)108 441.6 Q F2(optstring name)2.5 E F0([)2.5 E F2(ar)A(gs)-.37 E F0(])
+A F1(getopts)144 453.6 Q F0 .828
+(is used by shell procedures to parse positional parameters.)3.328 F F2
+(optstring)5.827 E F0 .827(contains the option)3.327 F .602
+(letters to be recognized; if a letter is follo)144 465.6 R .603
+(wed by a colon, the option is e)-.25 F .603(xpected to ha)-.15 F .903 -.15
+(ve a)-.2 H 3.103(na).15 G -.18(rg)523.52 465.6 S(u-).18 E .7
+(ment, which should be separated from it by white space.)144 477.6 R .7
+(Each time it is in)5.7 F -.2(vo)-.4 G -.1(ke).2 G(d,).1 E F1(getopts)3.2 E F0
+(places)3.2 E .008(the ne)144 489.6 R .008(xt option in the shell v)-.15 F
+(ariable)-.25 E F2(name)2.508 E F0 2.508(,i).18 G(nitializing)316.884 489.6 Q
+F2(name)2.508 E F0 .009(if it does not e)2.508 F .009(xist, and the inde)-.15 F
+2.509(xo)-.15 G 2.509(ft)521.941 489.6 S(he)530.56 489.6 Q(ne)144 501.6 Q .199
+(xt ar)-.15 F .199(gument to be processed into the v)-.18 F(ariable)-.25 E F3
+(OPTIND)2.699 E/F4 9/Times-Roman@0 SF(.)A F3(OPTIND)4.699 E F0 .198
+(is initialized to 1 each time the)2.449 F .497(shell or a shell script is in)
+144 513.6 R -.2(vo)-.4 G -.1(ke).2 G 2.997(d. When).1 F .498
+(an option requires an ar)2.997 F(gument,)-.18 E F1(getopts)2.998 E F0 .498
+(places that ar)2.998 F(gu-)-.18 E .028(ment into the v)144 525.6 R(ariable)
+-.25 E F3(OPT)2.528 E(ARG)-.81 E F4(.)A F0 .028(The shell does not reset)4.528
+F F3(OPTIND)2.528 E F0 .027(automatically; it must be manu-)2.278 F .161
+(ally reset between multiple calls to)144 537.6 R F1(getopts)2.661 E F0 .161
+(within the same shell in)2.661 F -.2(vo)-.4 G .161(cation if a ne).2 F 2.662
+(ws)-.25 G .162(et of param-)490.806 537.6 R(eters is to be used.)144 549.6 Q
+F1(getopts)144 573.6 Q F0 1.252(can report errors in tw)3.752 F 3.752(ow)-.1 G
+3.752(ays. If)287.942 573.6 R 1.252(the \214rst character of)3.752 F F2
+(optstring)3.752 E F0 1.251(is a colon,)3.752 F F2(silent)3.751 E F0(error)
+3.751 E 1.442(reporting is used.)144 585.6 R 1.442
+(In normal operation diagnostic messages are printed when ille)6.442 F -.05(ga)
+-.15 G 3.943(lo).05 G 1.443(ptions or)503.277 585.6 R .654(missing option ar)
+144 597.6 R .653(guments are encountered.)-.18 F .653(If the v)5.653 F(ariable)
+-.25 E F3(OPTERR)3.153 E F0 .653(is set to 0, no error message)2.903 F
+(will be displayed, e)144 609.6 Q -.15(ve)-.25 G 2.5(ni).15 G 2.5(ft)241.09
+609.6 S(he \214rst character of)249.7 609.6 Q F2(optstring)2.5 E F0
+(is not a colon.)2.5 E .826(If an ille)144 633.6 R -.05(ga)-.15 G 3.326(lo).05
+G .826(ption is seen,)199.878 633.6 R F1(getopts)3.326 E F0 .826(places ? into)
+3.326 F F2(name)3.326 E F0 .826(and, if not silent, prints an error message)
+3.326 F .4(and unsets)144 645.6 R F3(OPT)2.9 E(ARG)-.81 E F4(.)A F0(If)4.899 E
+F1(getopts)2.899 E F0 .399(is silent, the option character found is placed in)
+2.899 F F3(OPT)2.899 E(ARG)-.81 E F0 .399(and no)2.649 F
+(diagnostic message is printed.)144 657.6 Q 1.241(If a required ar)144 681.6 R
+1.241(gument is not found, and)-.18 F F1(getopts)3.741 E F0 1.241
+(is not silent, a question mark \()3.741 F F1(?).833 E F0 3.742(\)i).833 G
+3.742(sp)494.746 681.6 S 1.242(laced in)507.378 681.6 R F2(name)144 693.6 Q F0
+(,).18 E F1(OPT)3.357 E(ARG)-.9 E F0 .856
+(is unset, and a diagnostic message is printed.)3.357 F(If)5.856 E F1(getopts)
+3.356 E F0 .856(is silent, then a colon)3.356 F(\()144 705.6 Q F1(:).833 E F0
+2.5(\)i).833 G 2.5(sp)160.936 705.6 S(laced in)172.326 705.6 Q F2(name)2.5 E F0
+(and)2.5 E F3(OPT)2.5 E(ARG)-.81 E F0(is set to the option character found.)
+2.25 E F1(getopts)144 729.6 Q F0 2.392
+(normally parses the positional parameters, b)4.892 F 2.392(ut if more ar)-.2 F
+2.393(guments are gi)-.18 F -.15(ve)-.25 G 4.893(ni).15 G(n)509.927 729.6 Q F2
+(ar)4.893 E(gs)-.37 E F0(,).27 E 170.955(GNU 1993)72 768 R(September 16)2.5 E
+(4)535 768 Q EP
+%%Page: 5 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S(SH_B).35 E(UIL)-.1 E 290.48
+(TINS\(1\) B)-.92 F(ASH_B)-.35 E(UIL)-.1 E(TINS\(1\))-.92 E/F1 10/Times-Bold@0
+SF(getopts)144 84 Q F0 .651(parses those instead.)3.151 F F1(getopts)5.651 E F0
+.651(returns true if an option, speci\214ed or unspeci\214ed, is found.)3.151 F
+(It returns f)144 96 Q
+(alse if the end of options is encountered or an error occurs.)-.1 E F1(hash)
+108 112.8 Q F0([)2.5 E F1<ad72>A F0 2.5(][)C/F2 10/Times-Italic@0 SF(name)
+153.14 112.8 Q F0(])A -.15(Fo)144 124.8 S 2.819(re).15 G(ach)164.999 124.8 Q F2
+(name)2.819 E F0 2.819(,t).18 G .319
+(he full pathname of the command is determined and remembered.)211.637 124.8 R
+(The)5.32 E F1<ad72>2.82 E F0(option)2.82 E .508(causes the shell to for)144
+136.8 R .508(get all remembered locations.)-.18 F .508(If no ar)5.508 F .508
+(guments are gi)-.18 F -.15(ve)-.25 G .507(n, information about).15 F .193
+(remembered commands is printed.)144 148.8 R .193(An ar)5.193 F .193(gument of)
+-.18 F F1<adad>2.693 E F0 .194(disables option checking for the rest of the)
+2.693 F(ar)144 160.8 Q 2.5(guments. The)-.18 F(return status is true unless a)
+2.5 E F2(name)2.5 E F0(is not found or an ille)2.5 E -.05(ga)-.15 G 2.5(lo).05
+G(ption is supplied.)453.86 160.8 Q F1(help)108 177.6 Q F0([)2.5 E F2(pattern)A
+F0(])A .991(Display helpful information about b)144 189.6 R .991
+(uiltin commands.)-.2 F(If)5.991 E F2(pattern)3.491 E F0 .991(is speci\214ed,)
+3.491 F F1(help)3.491 E F0(gi)3.49 E -.15(ve)-.25 G 3.49(sd).15 G(etailed)
+513.34 189.6 Q .408(help on all commands matching)144 201.6 R F2(pattern)2.909
+E F0 2.909(;o).24 G .409(therwise a list of the b)316.13 201.6 R .409
+(uiltins is printed.)-.2 F .409(The return sta-)5.409 F
+(tus is 0 unless no command matches)144 213.6 Q F2(pattern)2.5 E F0(.).24 E F1
+(history)108 230.4 Q F0([)2.5 E F2(n)A F0(])A F1(history \255rwan)108 242.4 Q
+F0([)2.5 E F2(\214lename)A F0(])A -.4(Wi)144 254.4 S .752
+(th no options, display the command history list with line numbers.).4 F .752
+(Lines listed with a)5.752 F F1(*)3.251 E F0(ha)3.251 E -.15(ve)-.2 G .375
+(been modi\214ed.)144 266.4 R .375(An ar)5.375 F .375(gument of)-.18 F F2(n)
+2.875 E F0 .375(lists only the last)2.875 F F2(n)2.875 E F0 2.875(lines. If)
+2.875 F 2.876(an)2.876 G .376(on-option ar)411.832 266.4 R .376
+(gument is supplied,)-.18 F .811
+(it is used as the name of the history \214le; if not, the v)144 278.4 R .811
+(alue of)-.25 F/F3 9/Times-Bold@0 SF(HISTFILE)3.311 E F0 .811(is used.)3.061 F
+.811(Options, if sup-)5.811 F(plied, ha)144 290.4 Q .3 -.15(ve t)-.2 H
+(he follo).15 E(wing meanings:)-.25 E F1<ad61>144 302.4 Q F0 .598(Append the `)
+180 302.4 R(`ne)-.74 E(w')-.25 E 3.098('h)-.74 G .598
+(istory lines \(history lines entered since the be)266.424 302.4 R .599
+(ginning of the current)-.15 F F1(bash)180 314.4 Q F0
+(session\) to the history \214le)2.5 E F1<ad6e>144 326.4 Q F0 .854(Read the hi\
+story lines not already read from the history \214le into the current history \
+list.)180 326.4 R .772
+(These are lines appended to the history \214le since the be)180 338.4 R .773
+(ginning of the current)-.15 F F1(bash)3.273 E F0(ses-)3.273 E(sion.)180 350.4
+Q F1<ad72>144 362.4 Q F0
+(Read the contents of the history \214le and use them as the current history)
+180 362.4 Q F1<ad77>144 374.4 Q F0
+(Write the current history to the history \214le, o)180 374.4 Q -.15(ve)-.15 G
+(rwriting the history \214le').15 E 2.5(sc)-.55 G(ontents.)474.4 374.4 Q .989
+(The return v)144 391.2 R .989(alue is 0 unless an ille)-.25 F -.05(ga)-.15 G
+3.489(lo).05 G .989(ption is encountered or an error occurs while reading or)
+308.662 391.2 R(writing the history \214le.)144 403.2 Q F1(jobs)108 420 Q F0([)
+2.5 E F1(\255lnp)A F0 2.5(][)C F2(jobspec)A F0(... ])2.5 E F1(jobs \255x)108
+432 Q F2(command)2.5 E F0([)2.5 E F2(ar)2.5 E(gs)-.37 E F0(... ])2.5 E .297
+(The \214rst form lists the acti)144 444 R .598 -.15(ve j)-.25 H 2.798
+(obs. The).15 F F1<ad6c>2.798 E F0 .298
+(option lists process IDs in addition to the normal infor)2.798 F(-)-.2 E .746
+(mation; the)144 456 R F1<ad70>3.246 E F0 .745
+(option lists only the process ID of the job')3.246 F 3.245(sp)-.55 G .745
+(rocess group leader)394.205 456 R 5.745(.T)-.55 G(he)487.25 456 Q F1<ad6e>
+3.245 E F0(option)3.245 E 2.08(displays only jobs that ha)144 468 R 2.38 -.15
+(ve c)-.2 H 2.081(hanged status since last noti\214ed.).15 F(If)7.081 E F2
+(jobspec)4.581 E F0 2.081(is gi)4.581 F -.15(ve)-.25 G 2.081(n, output is).15 F
+.727(restricted to information about that job)144 480 R 5.727(.T)-.4 G .727
+(he return status is 0 unless an ille)316.282 480 R -.05(ga)-.15 G 3.227(lo).05
+G .726(ption is encoun-)474.108 480 R(tered or an ille)144 492 Q -.05(ga)-.15 G
+(l).05 E F2(jobspec)2.5 E F0(is supplied.)2.5 E .607(If the)144 516 R F1<ad78>
+3.107 E F0 .607(option is supplied,)3.107 F F1(jobs)3.107 E F0 .607
+(replaces an)3.107 F(y)-.15 E F2(jobspec)3.107 E F0 .607(found in)3.107 F F2
+(command)3.107 E F0(or)3.107 E F2(ar)3.107 E(gs)-.37 E F0 .607(with the corre-)
+3.107 F(sponding process group ID, and e)144 528 Q -.15(xe)-.15 G(cutes).15 E
+F2(command)2.5 E F0(passing it)2.5 E F2(ar)2.5 E(gs)-.37 E F0 2.5(,r).27 G
+(eturning its e)418.56 528 Q(xit status.)-.15 E F1(kill)108 544.8 Q F0([)2.5 E
+F1(-s sigspec)A F0(|)2.5 E F1(\255sigspec)2.5 E F0 2.5(][)C F2(pid)219.31 544.8
+Q F0(|)2.5 E F2(jobspec)2.5 E F0 2.5(].)C(..)277.97 544.8 Q F1(kill \255l)108
+556.8 Q F0([)2.5 E F2(signum)A F0(])A .943(Send the signal named by)144 568.8 R
+F2(sigspec)3.443 E F0 .942(to the processes named by)3.443 F F2(pid)3.442 E F0
+(or)3.442 E F2(jobspec)3.442 E F0(.).31 E F2(sigspec)5.942 E F0 .942
+(is either a)3.442 F .908(signal name such as)144 580.8 R F3(SIGKILL)3.408 E F0
+.908(or a signal number)3.158 F 5.908(.I)-.55 G(f)359.638 580.8 Q F2(sigspec)
+3.408 E F0 .908(is a signal name, the name is case)3.408 F(insensiti)144 592.8
+Q 2.43 -.15(ve a)-.25 H 2.13(nd may be gi).15 F -.15(ve)-.25 G 4.63(nw).15 G
+2.13(ith or without the)279.67 592.8 R F3(SIG)4.63 E F0 4.629(pre\214x. If)
+4.379 F F2(sigspec)4.629 E F0 2.129(is not present, then)4.629 F F3(SIGTERM)144
+604.8 Q F0 .813(is assumed.)3.063 F .813(An ar)5.813 F .813(gument of)-.18 F F1
+<ad6c>3.313 E F0 .814(lists the signal names.)3.313 F .814(If an)5.814 F 3.314
+(ya)-.15 G -.18(rg)450.232 604.8 S .814(uments are supplied).18 F(when)144
+616.8 Q F1<ad6c>2.827 E F0 .327(is gi)2.827 F -.15(ve)-.25 G .327(n, the names\
+ of the speci\214ed signals are listed, and the return status is 0.).15 F .326
+(An ar)5.326 F(gu-)-.18 E .484(ment of)144 628.8 R F1<adad>2.984 E F0 .484
+(disables option checking for the rest of the ar)2.984 F(guments.)-.18 E F1
+(kill)5.485 E F0 .485(returns true if at least one)2.985 F(signal w)144 640.8 Q
+(as successfully sent, or f)-.1 E(alse if an error occurs or an ille)-.1 E -.05
+(ga)-.15 G 2.5(lo).05 G(ption is encountered.)419.09 640.8 Q F1(let)108 657.6 Q
+F2(ar)2.5 E(g)-.37 E F0([)2.5 E F2(ar)A(g)-.37 E F0(...])2.5 E(Each)144 669.6 Q
+F2(ar)3.677 E(g)-.37 E F0 1.177(is an arithmetic e)3.677 F 1.177
+(xpression to be e)-.15 F -.25(va)-.25 G 1.177(luated \(see).25 F F3 1.176
+(ARITHMETIC EV)3.677 F(ALU)-1.215 E -.855(AT)-.54 G(ION).855 E/F4 9
+/Times-Roman@0 SF(\).)A F0 1.176(If the)5.676 F(last)144 681.6 Q F2(ar)2.5 E(g)
+-.37 E F0 -.25(eva)2.5 G(luates to 0,).25 E F1(let)2.5 E F0
+(returns 1; 0 is returned otherwise.)2.5 E F1(local)108 698.4 Q F0([)2.5 E F2
+(name)A F0([=)A F2(value)A F0 2.5(].)C(..])194.45 698.4 Q -.15(Fo)144 710.4 S
+3.276(re).15 G .776(ach ar)165.456 710.4 R .776(gument, create a local v)-.18 F
+.776(ariable named)-.25 F F2(name)3.276 E F0 3.276(,a).18 G .776(nd assign it)
+380.784 710.4 R F2(value)3.276 E F0 5.777(.W).18 G(hen)470.729 710.4 Q F1
+(local)3.277 E F0 .777(is used)3.277 F .131(within a function, it causes the v)
+144 722.4 R(ariable)-.25 E F2(name)2.631 E F0 .131(to ha)2.631 F .431 -.15
+(ve a v)-.2 H .13(isible scope restricted to that function and).15 F 170.955
+(GNU 1993)72 768 R(September 16)2.5 E(5)535 768 Q EP
+%%Page: 6 6
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S(SH_B).35 E(UIL)-.1 E 290.48
+(TINS\(1\) B)-.92 F(ASH_B)-.35 E(UIL)-.1 E(TINS\(1\))-.92 E .232(its children.)
+144 84 R -.4(Wi)5.232 G .232(th no operands,).4 F/F1 10/Times-Bold@0 SF(local)
+2.733 E F0 .233(writes a list of local v)2.733 F .233
+(ariables to the standard output.)-.25 F .233(It is an)5.233 F .42
+(error to use)144 96 R F1(local)2.92 E F0 .42(when not within a function.)2.92
+F .42(The return status is 0 unless)5.42 F F1(local)2.92 E F0 .42
+(is used outside a)2.92 F(function, or an ille)144 108 Q -.05(ga)-.15 G(l).05 E
+/F2 10/Times-Italic@0 SF(name)2.5 E F0(is supplied.)2.5 E F1(logout)108 124.8 Q
+F0(Exit a login shell.)9.33 E F1(popd)108 141.6 Q F0([)2.5 E F1(+/\255n)A F0(])
+A(Remo)144 153.6 Q -.15(ve)-.15 G 2.799(se).15 G .299
+(ntries from the directory stack.)188.159 153.6 R -.4(Wi)5.299 G .299(th no ar)
+.4 F .299(guments, remo)-.18 F -.15(ve)-.15 G 2.799(st).15 G .3
+(he top directory from the)438.82 153.6 R(stack, and performs a)144 165.6 Q F1
+(cd)2.5 E F0(to the ne)2.5 E 2.5(wt)-.25 G(op directory)291.22 165.6 Q(.)-.65 E
+F1(+n)144 177.6 Q F0(remo)180 177.6 Q -.15(ve)-.15 G 2.849(st).15 G(he)219.209
+177.6 Q F2(n)2.849 E F0 .349(th entry counting from the left of the list sho)B
+.349(wn by)-.25 F F1(dirs)2.848 E F0 2.848(,s)C .348(tarting with zero.)470.704
+177.6 R -.15(Fo)180 189.6 S 2.5(re).15 G(xample: `)200.53 189.6 Q(`popd +0')
+-.74 E 2.5('r)-.74 G(emo)286.06 189.6 Q -.15(ve)-.15 G 2.5(st).15 G
+(he \214rst directory)321.59 189.6 Q 2.5(,`)-.65 G(`popd +1')394.63 189.6 Q 2.5
+('t)-.74 G(he second.)442.3 189.6 Q F1<ad6e>144 201.6 Q F0(remo)180 201.6 Q
+-.15(ve)-.15 G 2.501(st).15 G(he)218.861 201.6 Q F2(n)2.501 E F0 .001
+(th entry counting from the right of the list sho)B .001(wn by)-.25 F F1(dirs)
+2.502 E F0 2.502(,s)C .002(tarting with zero.)471.396 201.6 R -.15(Fo)180 213.6
+S 2.5(re).15 G(xample: `)200.53 213.6 Q(`popd -0')-.74 E 2.5('r)-.74 G(emo)
+283.75 213.6 Q -.15(ve)-.15 G 2.5(st).15 G(he last directory)319.28 213.6 Q 2.5
+(,`)-.65 G(`popd -1')390.65 213.6 Q 2.5('t)-.74 G(he ne)436.01 213.6 Q
+(xt to last.)-.15 E .644(If the)144 230.4 R F1(popd)3.144 E F0 .644
+(command is successful, a)3.144 F F1(dirs)3.143 E F0 .643
+(is performed as well, and the return status is 0.)3.143 F F1(popd)5.643 E F0
+.57(returns f)144 242.4 R .57(alse if an ille)-.1 F -.05(ga)-.15 G 3.07(lo).05
+G .571(ption is encountered, the directory stack is empty)251.25 242.4 R 3.071
+(,an)-.65 G(on-e)469.319 242.4 Q .571(xistent direc-)-.15 F
+(tory stack entry is speci\214ed, or the directory change f)144 254.4 Q(ails.)
+-.1 E F1(pushd)108 271.2 Q F0([)2.5 E F2(dir)A F0(])A F1(pushd +/\255n)108
+283.2 Q F0 .64(Adds a directory to the top of the directory stack, or rotates \
+the stack, making the ne)144 295.2 R 3.139(wt)-.25 G .639(op of the)503.172
+295.2 R 1.315(stack the current w)144 307.2 R 1.315(orking directory)-.1 F
+6.315(.W)-.65 G 1.315(ith no ar)306.885 307.2 R 1.315(guments, e)-.18 F 1.316
+(xchanges the top tw)-.15 F 3.816(od)-.1 G 1.316(irectories and)484.534 307.2 R
+(returns 0, unless the directory stack is empty)144 319.2 Q(.)-.65 E F1(+n)144
+331.2 Q F0 1.268(Rotates the stack so that the)180 331.2 R F2(n)3.768 E F0
+1.267(th directory \(counting from the left of the list sho)B 1.267(wn by)-.25
+F F1(dirs)180 343.2 Q F0 2.5(\)i)C 2.5(sa)205.28 343.2 S 2.5(tt)216.11 343.2 S
+(he top.)224.17 343.2 Q F1<ad6e>144 355.2 Q F0(Rotates the stack so that the)
+180 355.2 Q F2(n)2.5 E F0
+(th directory \(counting from the right\) is at the top.)A F1(dir)144 367.2 Q
+F0(adds)180 367.2 Q F2(dir)2.5 E F0
+(to the directory stack at the top, making it the ne)2.5 E 2.5(wc)-.25 G
+(urrent w)422.5 367.2 Q(orking directory)-.1 E(.)-.65 E .488(If the)144 384 R
+F1(pushd)2.988 E F0 .488(command is successful, a)2.988 F F1(dirs)2.988 E F0
+.488(is performed as well.)2.988 F .489(If the \214rst form is used,)5.488 F F1
+(pushd)2.989 E F0 1.103(returns 0 unless the cd to)144 396 R F2(dir)3.603 E F0
+-.1(fa)3.603 G 3.603(ils. W).1 F 1.103(ith the second form,)-.4 F F1(pushd)
+3.603 E F0 1.103(returns 0 unless the directory)3.603 F .846(stack is empty)144
+408 R 3.346(,an)-.65 G(on-e)220.894 408 Q .847(xistant directory stack element\
+ is speci\214ed, or the directory change to the)-.15 F(speci\214ed ne)144 420 Q
+2.5(wc)-.25 G(urrent directory f)205.4 420 Q(ails.)-.1 E F1(pwd)108 436.8 Q F0
+.725(Print the absolute pathname of the current w)144 436.8 R .724
+(orking directory)-.1 F 5.724(.T)-.65 G .724(he path printed contains no sym-)
+405.56 436.8 R .521(bolic links if the)144 448.8 R F1<ad50>3.021 E F0 .521
+(option to the)3.021 F F1(set)3.021 E F0 -.2(bu)3.021 G .521
+(iltin command is set.).2 F .521(See also the description of)5.521 F F1
+(nolinks)3.022 E F0(under)144 460.8 Q F1 .074(Shell V)2.574 F(ariables)-.92 E
+F0(abo)2.574 E -.15(ve)-.15 G 2.574(\). The).15 F .074
+(return status is 0 unless an error occurs while reading the path-)2.574 F
+(name of the current directory)144 472.8 Q(.)-.65 E F1 -.18(re)108 489.6 S(ad)
+.18 E F0([)2.5 E F1<ad72>A F0 2.5(][)C F2(name)152.39 489.6 Q F0(...])2.5 E
+.036(One line is read from the standard input, and the \214rst w)144 501.6 R
+.037(ord is assigned to the \214rst)-.1 F F2(name)2.537 E F0 2.537(,t).18 G
+.037(he second)500.253 501.6 R -.1(wo)144 513.6 S .109(rd to the second).1 F F2
+(name)2.609 E F0 2.609(,a).18 G .109(nd so on, with lefto)254.045 513.6 R -.15
+(ve)-.15 G 2.609(rw).15 G .109(ords assigned to the last)354.18 513.6 R F2
+(name)2.609 E F0 5.109(.O).18 G .108(nly the char)489.444 513.6 R(-)-.2 E .143
+(acters in)144 525.6 R/F3 9/Times-Bold@0 SF(IFS)2.643 E F0 .143
+(are recognized as w)2.393 F .143(ord delimiters.)-.1 F .143(If no)5.143 F F2
+(names)2.643 E F0 .144(are supplied, the line read is assigned)2.643 F .194
+(to the v)144 537.6 R(ariable)-.25 E F3(REPL)2.694 E(Y)-.828 E/F4 9
+/Times-Roman@0 SF(.)A F0 .194
+(The return code is zero, unless end-of-\214le is encountered.)4.694 F .193
+(If the)5.193 F F1<ad72>2.693 E F0(option)2.693 E .444(is gi)144 549.6 R -.15
+(ve)-.25 G .444(n, a backslash-ne).15 F .444
+(wline pair is not ignored, and the backslash is considered to be part of the)
+-.25 F(line.)144 561.6 Q F1 -.18(re)108 578.4 S(adonly).18 E F0([)2.5 E F1
+<ad66>A F0 2.5(][)C F2(name)169.62 578.4 Q F0(...])2.5 E F1 -.18(re)108 590.4 S
+(adonly -p).18 E F0 .419(The gi)144 602.4 R -.15(ve)-.25 G(n).15 E F2(names)
+2.919 E F0 .419(are mark)2.919 F .419(ed readonly and the v)-.1 F .419
+(alues of these)-.25 F F2(names)2.919 E F0 .418(may not be changed by sub-)
+2.919 F .541(sequent assignment.)144 614.4 R .541(If the)5.541 F F1<ad66>3.041
+E F0 .541(option is supplied, the functions corresponding to the)3.041 F F2
+(names)3.042 E F0 .542(are so)3.042 F(mark)144 626.4 Q 3.037(ed. If)-.1 F .537
+(no ar)3.037 F .537(guments are gi)-.18 F -.15(ve)-.25 G .536(n, or if the).15
+F F1<ad70>3.036 E F0 .536(option is supplied, a list of all readonly names is)
+3.036 F 2.501(printed. An)144 638.4 R(ar)2.501 E .002(gument of)-.18 F F1<adad>
+2.502 E F0 .002(disables option checking for the rest of the ar)2.502 F 2.502
+(guments. The)-.18 F .002(return sta-)2.502 F .192(tus is 0 unless an ille)144
+650.4 R -.05(ga)-.15 G 2.692(lo).05 G .192(ption is encountered, one of the)
+247.732 650.4 R F2(names)2.691 E F0 .191(is not a le)2.691 F -.05(ga)-.15 G
+2.691(ls).05 G .191(hell v)463.498 650.4 R .191(ariable name,)-.25 F(or)144
+662.4 Q F1<ad66>2.5 E F0(is supplied with a)2.5 E F2(name)2.5 E F0
+(that is not a function.)2.5 E F1 -.18(re)108 679.2 S(tur).18 E(n)-.15 E F0([)
+2.5 E F2(n)A F0(])A .618(Causes a function to e)144 691.2 R .618
+(xit with the return v)-.15 F .618(alue speci\214ed by)-.25 F F2(n)3.118 E F0
+5.619(.I).24 G(f)404.557 691.2 Q F2(n)3.119 E F0 .619
+(is omitted, the return status is)3.119 F 1.335(that of the last command e)144
+703.2 R -.15(xe)-.15 G 1.335(cuted in the function body).15 F 6.335(.I)-.65 G
+3.835(fu)387.48 703.2 S 1.335(sed outside a function, b)399.645 703.2 R 1.335
+(ut during)-.2 F -.15(exe)144 715.2 S .794(cution of a script by the).15 F F1
+(.)3.294 E F0(\()5.794 E F1(sour)A(ce)-.18 E F0 3.294(\)c)C .794
+(ommand, it causes the shell to stop e)309.832 715.2 R -.15(xe)-.15 G .795
+(cuting that script).15 F 1.234(and return either)144 727.2 R F2(n)3.734 E F0
+1.234(or the e)3.734 F 1.234(xit status of the last command e)-.15 F -.15(xe)
+-.15 G 1.234(cuted within the script as the e).15 F(xit)-.15 E 170.955
+(GNU 1993)72 768 R(September 16)2.5 E(6)535 768 Q EP
+%%Page: 7 7
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S(SH_B).35 E(UIL)-.1 E 290.48
+(TINS\(1\) B)-.92 F(ASH_B)-.35 E(UIL)-.1 E(TINS\(1\))-.92 E .393
+(status of the script.)144 84 R .393
+(If used outside a function and not during e)5.393 F -.15(xe)-.15 G .393
+(cution of a script by).15 F/F1 10/Times-Bold@0 SF(.)2.893 E F0 2.893(,t).833 G
+.393(he return)503.787 84 R(status is f)144 96 Q(alse.)-.1 E F1(set)108 112.8 Q
+F0([)2.5 E F1(\255\255abefhkmnptuvxldCHP)A F0 2.5(][)C F1(-o)243.29 112.8 Q/F2
+10/Times-Italic@0 SF(option)2.5 E F0 2.5(][)C F2(ar)288.84 112.8 Q(g)-.37 E F0
+(...])2.5 E F1<ad61>144 124.8 Q F0 1.036(Automatically mark v)184 124.8 R 1.036
+(ariables which are modi\214ed or created for e)-.25 F 1.035(xport to the en)
+-.15 F(viron-)-.4 E(ment of subsequent commands.)184 136.8 Q F1<ad62>144 148.8
+Q F0 .721
+(Cause the status of terminated background jobs to be reported immediately)184
+148.8 R 3.221(,r)-.65 G .721(ather than)499.569 148.8 R(before the ne)184 160.8
+Q(xt primary prompt.)-.15 E(\(Also see)5 E F1(notify)2.5 E F0(under)2.5 E F1
+(Shell V)2.5 E(ariables)-.92 E F0(abo)2.5 E -.15(ve)-.15 G(\).).15 E F1<ad65>
+144 172.8 Q F0 1.772(Exit immediately if a)184 172.8 R F2(simple-command)4.272
+E F0(\(see)4.272 E/F3 9/Times-Bold@0 SF 1.772(SHELL GRAMMAR)4.272 F F0(abo)
+4.022 E -.15(ve)-.15 G 4.271(\)e).15 G 1.771(xits with a)494.788 172.8 R .642
+(non\255zero status.)184 184.8 R .642(The shell does not e)5.642 F .642
+(xit if the command that f)-.15 F .643(ails is part of an)-.1 F F2(until)3.143
+E F0(or)3.143 E F2(while)184 196.8 Q F0 .728(loop, part of an)3.228 F F2(if)
+3.228 E F0 .728(statement, part of a)3.228 F F1(&&)3.228 E F0(or)3.228 E/F4 10
+/Symbol SF 1.666<efef>3.228 G F0 .728(list, or if the command')1.562 F 3.228
+(sr)-.55 G(eturn)519.45 196.8 Q -.25(va)184 208.8 S(lue is being in).25 E -.15
+(ve)-.4 G(rted via).15 E F1(!)2.5 E F0(.)A F1<ad66>144 220.8 Q F0
+(Disable pathname e)184 220.8 Q(xpansion.)-.15 E F1<ad68>144 232.8 Q F0 .106
+(Locate and remember function commands as functions are de\214ned.)184 232.8 R
+.106(Function commands)5.106 F(are normally look)184 244.8 Q
+(ed up when the function is e)-.1 E -.15(xe)-.15 G(cuted.).15 E F1<ad6b>144
+256.8 Q F0 .162(All k)184 256.8 R -.15(ey)-.1 G -.1(wo).15 G .162(rd ar).1 F
+.162(guments are placed in the en)-.18 F .161
+(vironment for a command, not just those that)-.4 F(precede the command name.)
+184 268.8 Q F1<ad6d>144 280.8 Q F0 .009(Monitor mode.)184 280.8 R .009
+(Job control is enabled.)5.009 F .009(This \215ag is on by def)5.009 F .01
+(ault for interacti)-.1 F .31 -.15(ve s)-.25 H .01(hells on).15 F .124
+(systems that support it \(see)184 292.8 R F3 .124(JOB CONTR)2.624 F(OL)-.27 E
+F0(abo)2.374 E -.15(ve)-.15 G 2.624(\). Background).15 F .124
+(processes run in a sep-)2.624 F .72
+(arate process group and a line containing their e)184 304.8 R .721
+(xit status is printed upon their comple-)-.15 F(tion.)184 316.8 Q F1<ad6e>144
+328.8 Q F0 .653(Read commands b)184 328.8 R .653(ut do not e)-.2 F -.15(xe)-.15
+G .653(cute them.).15 F .652(This may be used to check a shell script for)5.653
+F(syntax errors.)184 340.8 Q(This is ignored for interacti)5 E .3 -.15(ve s)
+-.25 H(hells.).15 E F1<ad6f>144 352.8 Q F2(option-name)2.5 E F0(The)184 364.8 Q
+F2(option-name)2.5 E F0(can be one of the follo)2.5 E(wing:)-.25 E F1
+(allexport)184 376.8 Q F0(Same as)224 388.8 Q F1<ad61>2.5 E F0(.)A F1
+(braceexpand)184 400.8 Q F0 .312(The shell performs brace e)224 412.8 R .313
+(xpansion \(see)-.15 F F1 .313(Brace Expansion)2.813 F F0(abo)2.813 E -.15(ve)
+-.15 G 2.813(\). This).15 F .313(is on)2.813 F(by def)224 424.8 Q(ault.)-.1 E
+F1(emacs)184 436.8 Q F0 .089(Use an emacs-style command line editing interf)224
+436.8 R 2.589(ace. This)-.1 F .089(is enabled by def)2.589 F(ault)-.1 E .128
+(when the shell is interacti)224 448.8 R -.15(ve)-.25 G 2.628(,u).15 G .128
+(nless the shell is started with the)345.89 448.8 R F1(\255nolineediting)2.629
+E F0(option.)224 460.8 Q F1(err)184 472.8 Q(exit)-.18 E F0(Same as)224 472.8 Q
+F1<ad65>2.5 E F0(.)A F1(histexpand)184 484.8 Q F0(Same as)224 496.8 Q F1<ad48>
+2.5 E F0(.)A F1(ignor)184 508.8 Q(eeof)-.18 E F0 1.024(The ef)224 520.8 R 1.024
+(fect is as if the shell command `IGNOREEOF=10' had been e)-.25 F -.15(xe)-.15
+G(cuted).15 E(\(see)224 532.8 Q F1(Shell V)2.5 E(ariables)-.92 E F0(abo)2.5 E
+-.15(ve)-.15 G(\).).15 E F1(interacti)184 544.8 Q -.1(ve)-.1 G(\255comments).1
+E F0(Allo)224 556.8 Q 2.52(waw)-.25 G .02(ord be)265.35 556.8 R .021
+(ginning with)-.15 F F1(#)2.521 E F0 .021(to cause that w)2.521 F .021
+(ord and all remaining characters)-.1 F
+(on that line to be ignored in an interacti)224 568.8 Q .3 -.15(ve s)-.25 H
+(hell \(see).15 E F3(COMMENTS)2.5 E F0(abo)2.25 E -.15(ve)-.15 G(\).).15 E F1
+(monitor)184 580.8 Q F0(Same as)5.56 E F1<ad6d>2.5 E F0(.)A F1(noclob)184 592.8
+Q(ber)-.1 E F0(Same as)224 604.8 Q F1<ad43>2.5 E F0(.)A F1(noexec)184 616.8 Q
+F0(Same as)224 616.8 Q F1<ad6e>2.5 E F0(.)A F1(noglob)184 628.8 Q F0(Same as)
+224 628.8 Q F1<ad66>2.5 E F0(.)A F1(nohash)184 640.8 Q F0(Same as)9.43 E F1
+<ad64>2.5 E F0(.)A F1(notify)184 652.8 Q F0(Same as)224 652.8 Q F1<ad62>2.5 E
+F0(.)A F1(nounset)184 664.8 Q F0(Same as)6.66 E F1<ad75>2.5 E F0(.)A F1(ph)184
+676.8 Q(ysical)-.15 E F0(Same as)5.14 E F1<ad50>2.5 E F0(.)A F1(posix)184 688.8
+Q F0 2.244(Change the beha)224 688.8 R 2.244(vior of bash where the def)-.2 F
+2.243(ault operation dif)-.1 F 2.243(fers from the)-.25 F
+(Posix 1003.2 standard to match the standard.)224 700.8 Q 170.955(GNU 1993)72
+768 R(September 16)2.5 E(7)535 768 Q EP
+%%Page: 8 8
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S(SH_B).35 E(UIL)-.1 E 290.48
+(TINS\(1\) B)-.92 F(ASH_B)-.35 E(UIL)-.1 E(TINS\(1\))-.92 E/F1 10/Times-Bold@0
+SF(pri)184 84 Q(vileged)-.1 E F0(Same as)224 96 Q F1<ad70>2.5 E F0(.)A F1 -.1
+(ve)184 108 S(rbose).1 E F0(Same as)7.33 E F1<ad76>2.5 E F0(.)A F1(vi)184 120 Q
+F0(Use a vi-style command line editing interf)224 120 Q(ace.)-.1 E F1(xtrace)
+184 132 Q F0(Same as)224 132 Q F1<ad78>2.5 E F0(.)A(If no)184 144 Q/F2 10
+/Times-Italic@0 SF(option-name)2.5 E F0(is supplied, the v)2.5 E
+(alues of the current options are printed.)-.25 E F1<ad70>144 156 Q F0 -.45(Tu)
+184 156 S .521(rn on).45 F F2(privile)3.021 E -.1(ge)-.4 G(d).1 E F0 3.021
+(mode. In)3.021 F .521(this mode, the)3.021 F F1($ENV)3.021 E F0 .522
+(\214le is not processed, and shell func-)3.021 F .26
+(tions are not inherited from the en)184 168 R 2.76(vironment. This)-.4 F .26
+(is enabled automatically on startup if)2.76 F .481(the ef)184 180 R(fecti)-.25
+E .781 -.15(ve u)-.25 H .482
+(ser \(group\) id is not equal to the real user \(group\) id.).15 F -.45(Tu)
+5.482 G .482(rning this option).45 F(of)184 192 Q 2.5(fc)-.25 G(auses the ef)
+202.35 192 Q(fecti)-.25 E .3 -.15(ve u)-.25 H
+(ser and group ids to be set to the real user and group ids.).15 E F1<ad74>144
+204 Q F0(Exit after reading and e)184 204 Q -.15(xe)-.15 G(cuting one command.)
+.15 E F1<ad75>144 216 Q F0 -.35(Tr)184 216 S .445(eat unset v).35 F .444
+(ariables as an error when performing parameter e)-.25 F 2.944(xpansion. If)
+-.15 F -.15(ex)2.944 G .444(pansion is).15 F .519(attempted on an unset v)184
+228 R .519(ariable, the shell prints an error message, and, if not interacti)
+-.25 F -.15(ve)-.25 G(,).15 E -.15(ex)184 240 S(its with a non\255zero status.)
+.15 E F1<ad76>144 252 Q F0(Print shell input lines as the)184 252 Q 2.5(ya)-.15
+G(re read.)306.63 252 Q F1<ad78>144 264 Q F0 1.057(After e)184 264 R 1.056
+(xpanding each)-.15 F F2(simple-command)3.556 E F0(,).77 E F1(bash)3.556 E F0
+1.056(displays the e)3.556 F 1.056(xpanded v)-.15 F 1.056(alue of)-.25 F/F3 9
+/Times-Bold@0 SF(PS4)3.556 E/F4 9/Times-Roman@0 SF(,)A F0(fol-)3.306 E(lo)184
+276 Q(wed by the command and its e)-.25 E(xpanded ar)-.15 E(guments.)-.18 E F1
+<ad6c>144 288 Q F0(Sa)184 288 Q 1.398 -.15(ve a)-.2 H 1.098
+(nd restore the binding of).15 F F2(name)3.598 E F0 1.098(in a)3.598 F F1 -.25
+(fo)3.598 G(r).25 E F2(name)3.598 E F0([in)3.599 E F1 -.1(wo)3.599 G(rd).1 E F0
+3.599(]c)C 1.099(ommand \(see)451.687 288 R F3(SHELL)3.599 E(GRAMMAR)184 300 Q
+F0(abo)2.25 E -.15(ve)-.15 G(\).).15 E F1<ad64>144 312 Q F0 1.68
+(Disable the hashing of commands that are look)184 312 R 1.68(ed up for e)-.1 F
+-.15(xe)-.15 G 4.18(cution. Normally).15 F 4.18(,c)-.65 G(om-)523.89 312 Q
+1.275(mands are remembered in a hash table, and once found, do not ha)184 324 R
+1.576 -.15(ve t)-.2 H 3.776(ob).15 G 3.776(el)490.888 324 S(ook)501.884 324 Q
+1.276(ed up)-.1 F(ag)184 336 Q(ain.)-.05 E F1<ad43>144 348 Q F0 .812(The ef)184
+348 R .812(fect is as if the shell command `noclobber=' had been e)-.25 F -.15
+(xe)-.15 G .811(cuted \(see).15 F F1 .811(Shell V)3.311 F(ari-)-.92 E(ables)184
+360 Q F0(abo)2.5 E -.15(ve)-.15 G(\).).15 E F1<ad48>144 372 Q F0(Enable)184 372
+Q F1(!)3.13 E F0 .63(style history substitution.)5.63 F .63
+(This \215ag is on by def)5.63 F .63(ault when the shell is interac-)-.1 F(ti)
+184 384 Q -.15(ve)-.25 G(.).15 E F1<ad50>144 396 Q F0 2.107
+(If set, do not follo)184 396 R 4.607(ws)-.25 G 2.107
+(ymbolic links when performing commands such as)279.835 396 R F1(cd)4.607 E F0
+(which)4.606 E(change the current directory)184 408 Q 5(.T)-.65 G(he ph)309.42
+408 Q(ysical directory is used instead.)-.05 E F1<adad>144 420 Q F0 .05
+(If no ar)184 420 R .05(guments follo)-.18 F 2.55(wt)-.25 G .05
+(his \215ag, then the positional parameters are unset.)280.98 420 R .05
+(Otherwise, the)5.05 F(positional parameters are set to the)184 432 Q F2(ar)2.5
+E(g)-.37 E F0(s, e)A -.15(ve)-.25 G 2.5(ni).15 G 2.5(fs)371.81 432 S
+(ome of them be)381.53 432 Q(gin with a)-.15 E F1<ad>2.5 E F0(.)A F1<ad>144 444
+Q F0 1.945(Signal the end of options, cause all remaining)184 444 R F2(ar)4.444
+E(g)-.37 E F0 4.444(st)C 4.444(ob)409.45 444 S 4.444(ea)423.894 444 S 1.944
+(ssigned to the positional)437.218 444 R 3.445(parameters. The)184 456 R F1
+<ad78>3.445 E F0(and)3.445 E F1<ad76>3.445 E F0 .945(options are turned of)
+3.445 F 3.445(f. If)-.25 F .946(there are no)3.445 F F2(ar)3.446 E(g)-.37 E F0
+.946(s, the positional)B(parameters remain unchanged.)184 468 Q .317
+(The \215ags are of)144 484.8 R 2.817(fb)-.25 G 2.817(yd)218.328 484.8 S(ef)
+231.145 484.8 Q .317(ault unless otherwise noted.)-.1 F .316
+(Using + rather than \255 causes these \215ags to be)5.317 F .198(turned of)144
+496.8 R 2.698(f. The)-.25 F .199
+(\215ags can also be speci\214ed as options to an in)2.699 F -.2(vo)-.4 G .199
+(cation of the shell.).2 F .199(The current set)5.199 F .643
+(of \215ags may be found in)144 508.8 R F1<24ad>3.143 E F0 5.642(.A)C .642
+(fter the option ar)273.91 508.8 R .642(guments are processed, the remaining)
+-.18 F F2 3.142(na)3.142 G -.37(rg)512.238 508.8 S F0 3.142(sa).37 G(re)532.23
+508.8 Q .775(treated as v)144 520.8 R .775
+(alues for the positional parameters and are assigned, in order)-.25 F 3.275
+(,t)-.4 G(o)448.69 520.8 Q F1($1)3.275 E F0(,)A F1($2)3.275 E F0(,)A F1 3.275
+(... $)3.275 F F2(n)A F0 5.775(.I)C 3.275(fn)523.395 520.8 S(o)535 520.8 Q .309
+(options or)144 532.8 R F2(ar)2.809 E(g)-.37 E F0 2.808(sa)C .308
+(re supplied, all shell v)212.056 532.8 R .308(ariables are printed.)-.25 F
+.308(The return status is al)5.308 F -.1(wa)-.1 G .308(ys true unless).1 F
+(an ille)144 544.8 Q -.05(ga)-.15 G 2.5(lo).05 G(ption is encountered.)188.24
+544.8 Q F1(shift)108 561.6 Q F0([)2.5 E F2(n)A F0(])A .428
+(The positional parameters from)144 573.6 R F2(n)2.928 E F0 .429
+(+1 ... are renamed to)B F1 .429($1 ....)2.929 F F0 -.15(Pa)5.429 G .429
+(rameters represented by the num-).15 F(bers)144 585.6 Q F1($#)3.434 E F0(do)
+3.434 E .934(wn to)-.25 F F1($#)3.434 E F0<ad>A F2(n)A F0 .934(+1 are unset.)B
+(If)5.934 E F2(n)3.433 E F0 .933(is 0, no parameters are changed.)3.433 F(If)
+5.933 E F2(n)3.433 E F0 .933(is not gi)3.433 F -.15(ve)-.25 G .933(n, it is).15
+F .026(assumed to be 1.)144 597.6 R F2(n)5.026 E F0 .026(must be a non-ne)2.526
+F -.05(ga)-.15 G(ti).05 E .326 -.15(ve n)-.25 H .026
+(umber less than or equal to).15 F F1($#)2.526 E F0 5.026(.I)C(f)454.886 597.6
+Q F2(n)2.526 E F0 .027(is greater than)2.527 F F1($#)2.527 E F0(,)A .03
+(the positional parameters are not changed.)144 609.6 R .029
+(The return status is greater than 0 if)5.03 F F2(n)2.529 E F0 .029
+(is greater than)2.529 F F1($#)2.529 E F0(or less than 0; otherwise 0.)144
+621.6 Q F1(suspend)108 638.4 Q F0([)2.5 E F1<ad66>A F0(])A .492(Suspend the e)
+144 650.4 R -.15(xe)-.15 G .492(cution of this shell until it recei).15 F -.15
+(ve)-.25 G 2.992(sa).15 G F3(SIGCONT).001 E F0 2.993(signal. The)2.743 F F1
+<ad66>2.993 E F0 .493(option says not to)2.993 F .759
+(complain if this is a login shell; just suspend an)144 662.4 R(yw)-.15 E(ay)
+-.1 E 5.758(.T)-.65 G .758(he return status is 0 unless the shell is a)375.688
+662.4 R(login shell and)144 674.4 Q F1<ad66>2.5 E F0
+(is not supplied, or if job control is not enabled.)2.5 E F1(test)108 691.2 Q
+F2 -.2(ex)2.5 G(pr).2 E F1([)108 703.2 Q F2 -.2(ex)2.5 G(pr).2 E F1(])2.5 E F0
+.877(Return a status of 0 \(true\) or 1 \(f)6.77 F .878
+(alse\) depending on the e)-.1 F -.25(va)-.25 G .878
+(luation of the conditional e).25 F(xpression)-.15 E F2 -.2(ex)144 715.2 S(pr)
+.2 E F0 5.008(.E).73 G .008(xpressions may be unary or binary)175.918 715.2 R
+5.007(.U)-.65 G .007(nary e)328.064 715.2 R .007
+(xpressions are often used to e)-.15 F .007(xamine the status)-.15 F .203
+(of a \214le.)144 727.2 R .203
+(There are string operators and numeric comparison operators as well.)5.203 F
+.204(Each operator and)5.204 F 170.955(GNU 1993)72 768 R(September 16)2.5 E(8)
+535 768 Q EP
+%%Page: 9 9
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S(SH_B).35 E(UIL)-.1 E 290.48
+(TINS\(1\) B)-.92 F(ASH_B)-.35 E(UIL)-.1 E(TINS\(1\))-.92 E 1.592
+(operand must be a separate ar)144 84 R 4.091(gument. If)-.18 F/F1 10
+/Times-Italic@0 SF(\214le)4.091 E F0 1.591(is of the form /de)4.091 F(v/fd/)
+-.25 E F1(n)A F0 4.091(,t)C 1.591(hen \214le descriptor)444.756 84 R F1(n)4.091
+E F0(is)4.091 E(check)144 96 Q(ed.)-.1 E/F2 10/Times-Bold@0 SF<ad62>144 108 Q
+F1(\214le)2.5 E F0 -.35(Tr)180 108 S(ue if).35 E F1(\214le)2.5 E F0 -.15(ex)2.5
+G(ists and is block special.).15 E F2<ad63>144 120 Q F1(\214le)2.5 E F0 -.35
+(Tr)180 120 S(ue if).35 E F1(\214le)2.5 E F0 -.15(ex)2.5 G
+(ists and is character special.).15 E F2<ad64>144 132 Q F1(\214le)2.5 E F0 -.35
+(Tr)180 132 S(ue if).35 E F1(\214le)2.5 E F0 -.15(ex)2.5 G
+(ists and is a directory).15 E(.)-.65 E F2<ad65>144 144 Q F1(\214le)2.5 E F0
+-.35(Tr)180 144 S(ue if).35 E F1(\214le)2.5 E F0 -.15(ex)2.5 G(ists.).15 E F2
+<ad66>144 156 Q F1(\214le)2.5 E F0 -.35(Tr)180 156 S(ue if).35 E F1(\214le)2.5
+E F0 -.15(ex)2.5 G(ists and is a re).15 E(gular \214le.)-.15 E F2<ad67>144 168
+Q F1(\214le)2.5 E F0 -.35(Tr)180 168 S(ue if).35 E F1(\214le)2.5 E F0 -.15(ex)
+2.5 G(ists and is set-group-id.).15 E F2<ad6b>144 180 Q F1(\214le)2.5 E F0 -.35
+(Tr)180 180 S(ue if).35 E F1(\214le)2.5 E F0(has its `)2.5 E(`stick)-.74 E(y')
+-.15 E 2.5('b)-.74 G(it set.)295.22 180 Q F2<ad4c>144 192 Q F1(\214le)2.5 E F0
+-.35(Tr)8.91 G(ue if).35 E F1(\214le)2.5 E F0 -.15(ex)2.5 G
+(ists and is a symbolic link.).15 E F2<ad70>144 204 Q F1(\214le)2.5 E F0 -.35
+(Tr)180 204 S(ue if).35 E F1(\214le)2.5 E F0 -.15(ex)2.5 G
+(ists and is a named pipe.).15 E F2<ad72>144 216 Q F1(\214le)2.5 E F0 -.35(Tr)
+180 216 S(ue if).35 E F1(\214le)2.5 E F0 -.15(ex)2.5 G(ists and is readable.)
+.15 E F2<ad73>144 228 Q F1(\214le)2.5 E F0 -.35(Tr)180 228 S(ue if).35 E F1
+(\214le)2.5 E F0 -.15(ex)2.5 G(ists and has a size greater than zero.).15 E F2
+<ad53>144 240 Q F1(\214le)2.5 E F0 -.35(Tr)180 240 S(ue if).35 E F1(\214le)2.5
+E F0 -.15(ex)2.5 G(ists and is a sock).15 E(et.)-.1 E F2<ad74>144 252 Q F1(fd)
+2.5 E F0 -.35(Tr)180 252 S(ue if).35 E F1(fd)2.5 E F0(is opened on a terminal.)
+2.5 E F2<ad75>144 264 Q F1(\214le)2.5 E F0 -.35(Tr)180 264 S(ue if).35 E F1
+(\214le)2.5 E F0 -.15(ex)2.5 G(ists and its set-user).15 E(-id bit is set.)-.2
+E F2<ad77>144 276 Q F1(\214le)2.5 E F0 -.35(Tr)8.36 G(ue if).35 E F1(\214le)2.5
+E F0 -.15(ex)2.5 G(ists and is writable.).15 E F2<ad78>144 288 Q F1(\214le)2.5
+E F0 -.35(Tr)180 288 S(ue if).35 E F1(\214le)2.5 E F0 -.15(ex)2.5 G
+(ists and is e).15 E -.15(xe)-.15 G(cutable.).15 E F2<ad4f>144 300 Q F1(\214le)
+2.5 E F0 -.35(Tr)7.8 G(ue if).35 E F1(\214le)2.5 E F0 -.15(ex)2.5 G
+(ists and is o).15 E(wned by the ef)-.25 E(fecti)-.25 E .3 -.15(ve u)-.25 H
+(ser id.).15 E F2<ad47>144 312 Q F1(\214le)2.5 E F0 -.35(Tr)7.8 G(ue if).35 E
+F1(\214le)2.5 E F0 -.15(ex)2.5 G(ists and is o).15 E(wned by the ef)-.25 E
+(fecti)-.25 E .3 -.15(ve g)-.25 H(roup id.).15 E F1(\214le1)144 324 Q F0<ad>2.5
+E F2(nt)A F1(\214le2)2.5 E F0 -.35(Tr)180 336 S(ue if).35 E F1(\214le1)2.5 E F0
+(is ne)2.5 E(wer \(according to modi\214cation date\) than)-.25 E F1(\214le2)
+2.5 E F0(.)A F1(\214le1)144 348 Q F0<ad>2.5 E F2(ot)A F1(\214le2)2.5 E F0 -.35
+(Tr)180 360 S(ue if).35 E F1(\214le1)2.5 E F0(is older than \214le2.)2.5 E F1
+(\214le1)144 372 Q F2(\255ef)2.5 E F1(\214le)2.5 E F0 -.35(Tr)180 384 S(ue if)
+.35 E F1(\214le1)2.5 E F0(and)2.5 E F1(\214le2)2.5 E F0(ha)2.5 E .3 -.15(ve t)
+-.2 H(he same de).15 E(vice and inode numbers.)-.25 E F2<ad7a>144 396 Q F1
+(string)2.5 E F0 -.35(Tr)180 408 S(ue if the length of).35 E F1(string)2.5 E F0
+(is zero.)2.5 E F2<ad6e>144 420 Q F1(string)2.5 E(string)144 432 Q F0 -.35(Tr)
+180 432 S(ue if the length of).35 E F1(string)2.5 E F0(is non\255zero.)2.5 E F1
+(string1)144 444 Q F2(=)2.5 E F1(string2)2.5 E F0 -.35(Tr)180 456 S
+(ue if the strings are equal.).35 E F1(string1)144 468 Q F2(!=)2.5 E F1
+(string2)2.5 E F0 -.35(Tr)180 480 S(ue if the strings are not equal.).35 E F2
+(!)144 492 Q F1 -.2(ex)2.5 G(pr).2 E F0 -.35(Tr)180 492 S(ue if).35 E F1 -.2
+(ex)2.5 G(pr).2 E F0(is f)2.5 E(alse.)-.1 E F1 -.2(ex)144 504 S(pr1).2 E F0<ad>
+2.5 E F2(a)A F1 -.2(ex)2.5 G(pr2).2 E F0 -.35(Tr)180 516 S(ue if both).35 E F1
+-.2(ex)2.5 G(pr1).2 E F0(AND)2.5 E F1 -.2(ex)2.5 G(pr2).2 E F0(are true.)2.5 E
+F1 -.2(ex)144 528 S(pr1).2 E F0<ad>2.5 E F2(o)A F1 -.2(ex)2.5 G(pr2).2 E F0
+-.35(Tr)180 540 S(ue if either).35 E F1 -.2(ex)2.5 G(pr1).2 E F0(OR)2.5 E F1
+-.2(ex)2.5 G(pr2).2 E F0(is true.)2.5 E F1(ar)144 552 Q(g1)-.37 E F2(OP)2.5 E
+F1(ar)2.5 E(g2)-.37 E/F3 9/Times-Bold@0 SF(OP)180 564 Q F0 .035(is one of)2.284
+F F2(\255eq)2.535 E F0(,)A F2(\255ne)2.535 E F0(,)A F2(\255lt)2.535 E F0(,)A F2
+(\255le)2.535 E F0(,)A F2(\255gt)2.535 E F0 2.535(,o)C(r)332.165 564 Q F2
+(\255ge)2.535 E F0 5.035(.T)C .035
+(hese arithmetic binary operators return true)366.815 564 R(if)180 576 Q F1(ar)
+3.32 E(g1)-.37 E F0 .82(is equal, not-equal, less-than, less-than-or)3.32 F .82
+(-equal, greater)-.2 F .82(-than, or greater)-.2 F(-than-or)-.2 E(-)-.2 E .5
+(equal than)180 588 R F1(ar)3 E(g2)-.37 E F0 3.001(,r)C(especti)252.231 588 Q
+-.15(ve)-.25 G(ly).15 E(.)-.65 E F1(Ar)5.501 E(g1)-.37 E F0(and)3.001 E F1(ar)
+3.001 E(g2)-.37 E F0 .501(may be positi)3.001 F .801 -.15(ve i)-.25 H(nte).15 E
+.501(gers, ne)-.15 F -.05(ga)-.15 G(ti).05 E .801 -.15(ve i)-.25 H(nte).15 E
+(gers,)-.15 E(or the special e)180 600 Q(xpression)-.15 E F2<ad6c>2.5 E F1
+(string)2.5 E F0 2.5(,w)C(hich e)327.48 600 Q -.25(va)-.25 G
+(luates to the length of).25 E F1(string)2.5 E F0(.).22 E F2(times)108 616.8 Q
+F0 1.229(Print the accumulated user and system times for the shell and for pro\
+cesses run from the shell.)144 616.8 R(The return status is 0.)144 628.8 Q F2
+(trap)108 645.6 Q F0([)2.5 E F2<ad6c>A F0 2.5(][)C F1(ar)149.8 645.6 Q(g)-.37 E
+F0 2.5(][)C F1(sigspec)172.48 645.6 Q F0(])A .767(The command)144 657.6 R F1
+(ar)3.267 E(g)-.37 E F0 .767(is to be read and e)3.267 F -.15(xe)-.15 G .767
+(cuted when the shell recei).15 F -.15(ve)-.25 G 3.267(ss).15 G(ignal\(s\))
+434.781 657.6 Q F1(sigspec)3.267 E F0 5.767(.I).31 G(f)509.945 657.6 Q F1(ar)
+3.267 E(g)-.37 E F0(is)3.268 E 2.164(absent or)144 669.6 R F2<ad>4.664 E F0
+4.664(,a)C 2.164(ll speci\214ed signals are reset to their original v)204.512
+669.6 R 2.164(alues \(the v)-.25 F 2.163(alues the)-.25 F 4.663(yh)-.15 G 2.163
+(ad upon)505.897 669.6 R .681(entrance to the shell\).)144 681.6 R(If)5.681 E
+F1(ar)3.181 E(g)-.37 E F0 .681
+(is the null string this signal is ignored by the shell and by the com-)3.181 F
+1.174(mands it in)144 693.6 R -.2(vo)-.4 G -.1(ke).2 G(s.).1 E F1(sigspec)6.174
+E F0 1.174(is either a signal name de\214ned in <)3.674 F F1(signal.h)A F0
+1.173(>, or a signal number)B 6.173(.I)-.55 G(f)536.67 693.6 Q F1(sigspec)144
+705.6 Q F0(is)2.769 E F3(EXIT)2.769 E F0 .269(\(0\) the command)2.519 F F1(ar)
+2.769 E(g)-.37 E F0 .269(is e)2.769 F -.15(xe)-.15 G .269(cuted on e).15 F .269
+(xit from the shell.)-.15 F -.4(Wi)5.269 G .269(th no ar).4 F(guments,)-.18 E
+F2(trap)2.77 E F0 .403
+(prints the list of commands associated with each signal number)144 717.6 R
+5.402(.T)-.55 G(he)414.118 717.6 Q F2<ad6c>2.902 E F0 .402
+(option causes the shell to)2.902 F .562
+(print a list of signal names and their corresponding numbers.)144 729.6 R .562
+(An ar)5.562 F .562(gument of)-.18 F F2<adad>3.062 E F0 .562(disables option)
+3.062 F 170.955(GNU 1993)72 768 R(September 16)2.5 E(9)535 768 Q EP
+%%Page: 10 10
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S(SH_B).35 E(UIL)-.1 E 290.48
+(TINS\(1\) B)-.92 F(ASH_B)-.35 E(UIL)-.1 E(TINS\(1\))-.92 E .564
+(checking for the rest of the ar)144 84 R 3.064(guments. Signals)-.18 F .564
+(ignored upon entry to the shell cannot be trapped)3.064 F 1.144(or reset.)144
+96 R -.35(Tr)6.144 G 1.145(apped signals are reset to their original v).35 F
+1.145(alues in a child process when it is created.)-.25 F
+(The return status is f)144 108 Q(alse if either the trap name or number is in)
+-.1 E -.25(va)-.4 G(lid; otherwise).25 E/F1 10/Times-Bold@0 SF(trap)2.5 E F0
+(returns true.)2.5 E F1(type)108 124.8 Q F0([)2.5 E F1(\255all)A F0 2.5(][)C F1
+(\255type)157.58 124.8 Q F0(|)2.5 E F1(\255path)2.5 E F0(])A/F2 10
+/Times-Italic@0 SF(name)2.5 E F0([)2.5 E F2(name)A F0(...])2.5 E -.4(Wi)144
+136.8 S .206(th no options, indicate ho).4 F 2.706(we)-.25 G(ach)272.15 136.8 Q
+F2(name)2.705 E F0 -.1(wo)2.705 G .205
+(uld be interpreted if used as a command name.).1 F .205(If the)5.205 F F1
+(\255type)144 148.8 Q F0 .527(\215ag is used,)3.027 F F1(type)3.027 E F0 .528
+(prints a phrase which is one of)3.028 F F2(alias)3.028 E F0(,).27 E F2 -.1(ke)
+3.028 G(ywor)-.2 E(d)-.37 E F0(,).77 E F2(function)3.028 E F0(,).24 E F2 -.2
+(bu)3.028 G(iltin).2 E F0 3.028(,o).24 G(r)512.284 148.8 Q F2(\214le)3.028 E F0
+(if)3.028 E F2(name)144 160.8 Q F0 .297(is an alias, shell reserv)2.798 F .297
+(ed w)-.15 F .297(ord, function, b)-.1 F .297(uiltin, or disk \214le, respecti)
+-.2 F -.15(ve)-.25 G(ly).15 E 2.797(.I)-.65 G 2.797(ft)472.152 160.8 S .297
+(he name is not)481.059 160.8 R 1.097(found, then nothing is printed, and an e)
+144 172.8 R 1.097(xit status of f)-.15 F 1.097(alse is returned.)-.1 F 1.097
+(If the)6.097 F F1(\255path)3.598 E F0 1.098(\215ag is used,)3.598 F F1(type)
+144 184.8 Q F0 1.009(either returns the name of the disk \214le that w)3.509 F
+1.008(ould be e)-.1 F -.15(xe)-.15 G 1.008(cuted if).15 F F2(name)3.508 E F0
+1.008(were speci\214ed as a)3.508 F .562(command name, or nothing if)144 196.8
+R F1(\255type)3.062 E F0 -.1(wo)3.062 G .562(uld not return).1 F F2(\214le)
+3.063 E F0 5.563(.I).18 G 3.063(fac)389.542 196.8 S .563(ommand is hashed,)
+407.878 196.8 R F1(\255path)3.063 E F0(prints)3.063 E .684(the hashed v)144
+208.8 R .684(alue, not necessarily the \214le that appears \214rst in)-.25 F/F3
+9/Times-Bold@0 SF -.666(PA)3.184 G(TH)-.189 E/F4 9/Times-Roman@0 SF(.)A F0 .684
+(If the)5.184 F F1(\255all)3.184 E F0 .683(\215ag is used,)3.184 F F1(type)
+3.183 E F0 1.135(prints all of the places that contain an e)144 220.8 R -.15
+(xe)-.15 G 1.135(cutable named).15 F F2(name)3.635 E F0 6.136(.T).18 G 1.136
+(his includes aliases and func-)418.256 220.8 R 1.011
+(tions, if and only if the)144 232.8 R F1(\255path)3.511 E F0 1.011
+(\215ag is not also used.)3.511 F 1.011
+(The table of hashed commands is not con-)6.011 F .786(sulted when using)144
+244.8 R F1(\255all)3.286 E F0(.)A F1(type)5.786 E F0(accepts)3.286 E F1<ad61>
+3.286 E F0(,)A F1<ad74>3.286 E F0 3.286(,a)C(nd)335.698 244.8 Q F1<ad70>3.286 E
+F0 .787(in place of)3.287 F F1(\255all)3.287 E F0(,)A F1(\255type)3.287 E F0
+3.287(,a)C(nd)466.906 244.8 Q F1(\255path)3.287 E F0 3.287(,r)C(espec-)514.46
+244.8 Q(ti)144 256.8 Q -.15(ve)-.25 G(ly).15 E 6.127(.A)-.65 G 3.627(na)181.577
+256.8 S -.18(rg)194.644 256.8 S 1.127(ument of).18 F F1<adad>3.627 E F0 1.127
+(disables option checking for the rest of the ar)3.627 F(guments.)-.18 E F1
+(type)6.126 E F0(returns)3.626 E(true if an)144 268.8 Q 2.5(yo)-.15 G 2.5(ft)
+192.45 268.8 S(he ar)201.06 268.8 Q(guments are found, f)-.18 E
+(alse if none are found.)-.1 E F1(ulimit)108 285.6 Q F0([)2.5 E F1
+(\255SHacdfmstpnuv)A F0([)2.5 E F2(limit)A F0(]])A F1(Ulimit)144 297.6 Q F0
+(pro)3.056 E .556(vides control o)-.15 F -.15(ve)-.15 G 3.057(rt).15 G .557
+(he resources a)266.316 297.6 R -.25(va)-.2 G .557
+(ilable to the shell and to processes started by it, on).25 F .765
+(systems that allo)144 309.6 R 3.265(ws)-.25 G .765(uch control.)226.325 309.6
+R .765(The v)5.765 F .765(alue of)-.25 F F2(limit)3.265 E F0 .765
+(can be a number in the unit speci\214ed for the)3.265 F .301
+(resource, or the v)144 321.6 R(alue)-.25 E F1(unlimited)2.801 E F0 5.301(.T)C
+(he)288.565 321.6 Q F1(H)2.801 E F0(and)2.801 E F1(S)2.801 E F0 .302
+(options specify that the hard or soft limit is set for)2.802 F .005(the gi)144
+333.6 R -.15(ve)-.25 G 2.505(nr).15 G 2.505(esource. A)186.38 333.6 R .004(har\
+d limit cannot be increased once it is set; a soft limit may be increased up)
+2.505 F .008(to the v)144 345.6 R .008(alue of the hard limit.)-.25 F .008
+(If neither)5.008 F F1(H)2.508 E F0(nor)2.508 E F1(S)2.508 E F0 .008
+(is speci\214ed, the command applies to the soft limit.)2.508 F(If)144 357.6 Q
+F2(limit)2.758 E F0 .258(is omitted, the current v)2.758 F .257
+(alue of the soft limit of the resource is printed, unless the)-.25 F F1(H)
+2.757 E F0(option)2.757 E .575(is gi)144 369.6 R -.15(ve)-.25 G 3.075(n. When)
+.15 F .576(more than one resource is speci\214ed, the limit name and unit is p\
+rinted before the)3.076 F -.25(va)144 381.6 S 2.5(lue. Other).25 F
+(options are interpreted as follo)2.5 E(ws:)-.25 E F1<ad61>144 393.6 Q F0
+(all current limits are reported)180 393.6 Q F1<ad63>144 405.6 Q F0
+(the maximum size of core \214les created)180 405.6 Q F1<ad64>144 417.6 Q F0
+(the maximum size of a process')180 417.6 Q 2.5(sd)-.55 G(ata se)317.76 417.6 Q
+(gment)-.15 E F1<ad66>144 429.6 Q F0
+(the maximum size of \214les created by the shell)180 429.6 Q F1<ad6d>144 441.6
+Q F0(the maximum resident set size)180 441.6 Q F1<ad73>144 453.6 Q F0
+(the maximum stack size)180 453.6 Q F1<ad74>144 465.6 Q F0
+(the maximum amount of cpu time in seconds)180 465.6 Q F1<ad70>144 477.6 Q F0
+(the pipe size in 512-byte blocks \(this may not be set\))180 477.6 Q F1<ad6e>
+144 489.6 Q F0 .164
+(the maximum number of open \214le descriptors \(most systems do not allo)180
+489.6 R 2.664(wt)-.25 G .164(his v)481.708 489.6 R .164(alue to be)-.25 F
+(set, only displayed\))180 501.6 Q F1<ad75>144 513.6 Q F0
+(the maximum number of processes a)180 513.6 Q -.25(va)-.2 G
+(ilable to a single user).25 E F1<ad76>144 525.6 Q F0
+(The maximum amount of virtual memory a)180 525.6 Q -.25(va)-.2 G
+(ilable to the shell).25 E .778(An ar)144 542.4 R .778(gument of)-.18 F F1
+<adad>3.278 E F0 .778(disables option checking for the rest of the ar)3.278 F
+3.279(guments. If)-.18 F F2(limit)3.279 E F0 .779(is gi)3.279 F -.15(ve)-.25 G
+.779(n, it is).15 F .394(the ne)144 554.4 R 2.894(wv)-.25 G .394
+(alue of the speci\214ed resource \(the)183.168 554.4 R F1<ad61>2.893 E F0 .393
+(option is display only\).)2.893 F .393(If no option is gi)5.393 F -.15(ve)-.25
+G .393(n, then).15 F F1<ad66>144 566.4 Q F0 .43(is assumed.)2.93 F -1.11(Va)
+5.43 G .43(lues are in 1024-byte increments, e)1.11 F .431(xcept for)-.15 F F1
+<ad74>2.931 E F0 2.931(,w)C .431(hich is in seconds,)421.315 566.4 R F1<ad70>
+2.931 E F0 2.931(,w)C(hich)522.78 566.4 Q .828
+(is in units of 512-byte blocks, and)144 578.4 R F1<ad6e>3.327 E F0(and)3.327 E
+F1<ad75>3.327 E F0 3.327(,w)C .827(hich are unscaled v)344.784 578.4 R 3.327
+(alues. The)-.25 F .827(return status is 0)3.327 F .621(unless an ille)144
+590.4 R -.05(ga)-.15 G 3.121(lo).05 G .621
+(ption is encountered, a non-numeric ar)217.603 590.4 R .622(gument other than)
+-.18 F F1(unlimited)3.122 E F0 .622(is supplied)3.122 F(as)144 602.4 Q F2
+(limit)2.5 E F0 2.5(,o)C 2.5(ra)183.17 602.4 S 2.5(ne)193.44 602.4 S
+(rror occurs while setting a ne)205.38 602.4 Q 2.5(wl)-.25 G(imit.)333.99 602.4
+Q F1(umask)108 619.2 Q F0([)2.5 E F1<ad53>A F0 2.5(][)C F2(mode)162.59 619.2 Q
+F0(])A .23(The user \214le-creation mask is set to)144 631.2 R F2(mode)2.73 E
+F0 5.23(.I).18 G(f)323.21 631.2 Q F2(mode)2.73 E F0(be)2.729 E .229
+(gins with a digit, it is interpreted as an octal)-.15 F .066(number; otherwis\
+e it is interpreted as a symbolic mode mask similar to that accepted by)144
+643.2 R F2 -.15(ch)2.566 G(mod).15 E F0(\(1\).).77 E(If)144 655.2 Q F2(mode)
+2.55 E F0 .05(is omitted, or if the)2.55 F F1<ad53>2.55 E F0 .049
+(option is supplied, the current v)2.55 F .049(alue of the mask is printed.)
+-.25 F(The)5.049 E F1<ad53>2.549 E F0 .475
+(option causes the mask to be printed in symbolic form; the def)144 667.2 R
+.475(ault output is an octal number)-.1 F 5.475(.A)-.55 G(n)535 667.2 Q(ar)144
+679.2 Q .125(gument of)-.18 F F1<adad>2.625 E F0 .125
+(disables option checking for the rest of the ar)2.625 F 2.624(guments. The)
+-.18 F .124(return status is 0 if the)2.624 F(mode w)144 691.2 Q
+(as successfully changed or if no)-.1 E F2(mode)2.5 E F0(ar)2.5 E(gument w)-.18
+E(as supplied, and f)-.1 E(alse otherwise.)-.1 E 170.955(GNU 1993)72 768 R
+(September 16)2.5 E(10)530 768 Q EP
+%%Page: 11 11
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF -.35(BA)72 48 S(SH_B).35 E(UIL)-.1 E 290.48
+(TINS\(1\) B)-.92 F(ASH_B)-.35 E(UIL)-.1 E(TINS\(1\))-.92 E/F1 10/Times-Bold@0
+SF(unalias)108 84 Q F0<5bad>2.5 E F1(a)A F0 2.5(][)C/F2 10/Times-Italic@0 SF
+(name)164.2 84 Q F0(...])2.5 E(Remo)144 96 Q -.15(ve)-.15 G F2(name)2.882 E F0
+2.732(sf)C .232(rom the list of de\214ned aliases.)211.374 96 R(If)5.232 E F1
+<ad61>2.733 E F0 .233(is supplied, all alias de\214nitions are remo)2.733 F
+-.15(ve)-.15 G(d.).15 E(The return v)144 108 Q(alue is true unless a supplied)
+-.25 E F2(name)2.5 E F0(is not a de\214ned alias.)2.5 E F1(unset)108 124.8 Q F0
+<5bad>2.5 E F1(fv)A F0 2.5(][)C F2(name)159.74 124.8 Q F0(...])2.5 E -.15(Fo)
+144 136.8 S 2.773(re).15 G(ach)164.953 136.8 Q F2(name)2.773 E F0 2.773(,r).18
+G(emo)212.049 136.8 Q .573 -.15(ve t)-.15 H .273(he corresponding v).15 F .273
+(ariable or)-.25 F 2.773(,g)-.4 G -2.15 -.25(iv e)369.094 136.8 T 2.773(nt).25
+G(he)391.467 136.8 Q F1<ad66>2.773 E F0 .273(option, function.)2.773 F .272
+(An ar)5.272 F(gument)-.18 E(of)144 148.8 Q F1<adad>2.58 E F0 .08
+(disables option checking for the rest of the ar)2.58 F 2.58(guments. Note)-.18
+F(that)2.58 E/F3 9/Times-Bold@0 SF -.666(PA)2.58 G(TH)-.189 E/F4 9
+/Times-Roman@0 SF(,)A F3(IFS)2.33 E F4(,)A F3(PPID)2.33 E F4(,)A F3(PS1)2.331 E
+F4(,)A F3(PS2)2.331 E F4(,)A F3(UID)144 160.8 Q F4(,)A F0(and)4.074 E F3(EUID)
+4.324 E F0 1.824(cannot be unset.)4.074 F 1.824(If an)6.824 F 4.323(yo)-.15 G
+(f)321.938 160.8 Q F3(RANDOM)4.323 E F4(,)A F3(SECONDS)4.073 E F4(,)A F3
+(LINENO)4.073 E F4(,)A F0(or)4.073 E F3(HISTCMD)4.323 E F0(are)4.073 E .328
+(unset, the)144 172.8 R 2.828(yl)-.15 G .328(ose their special properties, e)
+193.116 172.8 R -.15(ve)-.25 G 2.828(ni).15 G 2.828(ft)330.436 172.8 S(he)
+339.374 172.8 Q 2.828(ya)-.15 G .328(re subsequently reset.)360.932 172.8 R
+.328(The e)5.328 F .329(xit status is true)-.15 F(unless a)144 184.8 Q F2(name)
+2.5 E F0(does not e)2.5 E(xist or is non-unsettable.)-.15 E F1(wait)108 201.6 Q
+F0([)2.5 E F2(n)A F0(])A -.8(Wa)144 213.6 S 1.061
+(it for the speci\214ed process and return its termination status.).8 F F2(n)
+6.061 E F0 1.06(may be a process ID or a job)3.56 F .753
+(speci\214cation; if a job spec is gi)144 225.6 R -.15(ve)-.25 G .754
+(n, all processes in that job').15 F 3.254(sp)-.55 G .754(ipeline are w)404.012
+225.6 R .754(aited for)-.1 F 5.754(.I)-.55 G(f)502.458 225.6 Q F2(n)3.254 E F0
+.754(is not)3.254 F(gi)144 237.6 Q -.15(ve)-.25 G .027(n, all currently acti)
+.15 F .327 -.15(ve c)-.25 H .027(hild processes are w).15 F .027(aited for)-.1
+F 2.526(,a)-.4 G .026(nd the return status is zero.)375.932 237.6 R(If)5.026 E
+F2(n)2.526 E F0(speci\214es)2.526 E 2.595(an)144 249.6 S(on-e)156.035 249.6 Q
+.095(xistant process or job, the return status is 127.)-.15 F .096
+(Otherwise, the return status is the e)5.095 F .096(xit status)-.15 F
+(of the last process or job w)144 261.6 Q(aited for)-.1 E(.)-.55 E F3(SEE ALSO)
+72 278.4 Q F0(bash\(1\), sh\(1\))108 290.4 Q 170.955(GNU 1993)72 768 R
+(September 16)2.5 E(11)530 768 Q EP
+%%Trailer
+end
+%%EOF
diff --git a/documentation/builtins.txt b/documentation/builtins.txt
new file mode 100644 (file)
index 0000000..3df6380
--- /dev/null
@@ -0,0 +1,1188 @@
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+NAME
+     bash, :, ., alias, bg, bind, break, builtin, bye, case,  cd,
+     command,  continue, declare, dirs, echo, enable, eval, exec,
+     exit, export, fc, fg, for, getopts, hash, help, history, if,
+     jobs,  kill,  let,  local,  logout,  popd, pushd, pwd, read,
+     readonly, return, set, shift, source, suspend, test,  times,
+     trap,  type,  typeset, ulimit, umask, unalias, unset, until,
+     wait, while - bash built-in commands, see bash(1)
+
+BASH BUILTIN COMMANDS
+     : [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]
+          No effect; the command does  nothing  beyond  expanding
+          _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs and performing any specified redirections.  A
+          zero exit code is returned.
+
+      .  _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]
+     source _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]
+          Read and execute commands from _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be in the  current
+          shell  environment  and  return  the exit status of the
+          last command executed from _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be.  If _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be  does
+          not contain a slash, pathnames in PATH are used to find
+          the directory containing _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be.  The  file  searched
+          for in PATH need not be executable.  The current direc-
+          tory is searched if no file is found in PATH.   If  any
+          _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs  are  supplied,  they  become  the positional
+          parameters when _\bf_\bi_\bl_\be is executed.  Otherwise the  posi-
+          tional  parameters are unchanged.  The return status is
+          the status of the last command exited within the script
+          (0  if no commands are executed), and false if _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be
+          is not found.
+
+     alias [_\bn_\ba_\bm_\be[=_\bv_\ba_\bl_\bu_\be] ...]
+          Alias with no arguments prints the list of  aliases  in
+          the form _\bn_\ba_\bm_\be=_\bv_\ba_\bl_\bu_\be on standard output.  When arguments
+          are supplied, an alias is defined for each  _\bn_\ba_\bm_\be  whose
+          _\bv_\ba_\bl_\bu_\be  is  given.  A trailing space in _\bv_\ba_\bl_\bu_\be causes the
+          next word to be checked for alias substitution when the
+          alias  is expanded.  For each _\bn_\ba_\bm_\be in the argument list
+          for which no _\bv_\ba_\bl_\bu_\be is supplied, the name and  value  of
+          the alias is printed.  Alias returns true unless a _\bn_\ba_\bm_\be
+          is given for which no alias has been defined.
+
+     bg [_\bj_\bo_\bb_\bs_\bp_\be_\bc]
+          Place _\bj_\bo_\bb_\bs_\bp_\be_\bc in the background,  as  if  it  had  been
+          started with &.  If _\bj_\bo_\bb_\bs_\bp_\be_\bc is not present, the shell's
+          notion of the _\bc_\bu_\br_\br_\be_\bn_\bt _\bj_\bo_\bb is used.  bg _\bj_\bo_\bb_\bs_\bp_\be_\bc  returns
+          0  unless run when job control is disabled or, when run
+          with job control enabled, if _\bj_\bo_\bb_\bs_\bp_\be_\bc was not  found  or
+          started without job control.
+
+     bind [-m _\bk_\be_\by_\bm_\ba_\bp] [-lvd] [-q _\bn_\ba_\bm_\be]
+     bind [-m _\bk_\be_\by_\bm_\ba_\bp] -f _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be
+
+
+
+GNU              Last change: 1993 September 16                 1
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+     bind [-m _\bk_\be_\by_\bm_\ba_\bp] _\bk_\be_\by_\bs_\be_\bq:_\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn-_\bn_\ba_\bm_\be
+          Display current readline key and function bindings,  or
+          bind  a  key  sequence to a readline function or macro.
+          The binding syntax accepted is  identical  to  that  of
+          ._\bi_\bn_\bp_\bu_\bt_\br_\bc, but each binding must be passed as a separate
+          argument;   e.g.,   '"\C-x\C-r":    re-read-init-file'.
+          Options, if supplied, have the following meanings:
+          -m _\bk_\be_\by_\bm_\ba_\bp
+               Use _\bk_\be_\by_\bm_\ba_\bp as the keymap to  be  affected  by  the
+               subsequent  bindings.  Acceptable _\bk_\be_\by_\bm_\ba_\bp names are
+               _\be_\bm_\ba_\bc_\bs, _\be_\bm_\ba_\bc_\bs-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd, _\be_\bm_\ba_\bc_\bs-_\bm_\be_\bt_\ba, _\be_\bm_\ba_\bc_\bs-_\bc_\bt_\bl_\bx, _\bv_\bi,
+               _\bv_\bi-_\bm_\bo_\bv_\be,   _\bv_\bi-_\bc_\bo_\bm_\bm_\ba_\bn_\bd,   and   _\bv_\bi-_\bi_\bn_\bs_\be_\br_\bt.   _\bv_\bi  is
+               equivalent to _\bv_\bi-_\bc_\bo_\bm_\bm_\ba_\bn_\bd; _\be_\bm_\ba_\bc_\bs is  equivalent  to
+               _\be_\bm_\ba_\bc_\bs-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd.
+          -l   List the names of all readline functions
+          -v   List current function names and bindings
+          -d   Dump function names and bindings  in  such  a  way
+               that they can be re-read
+          -f _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be
+               Read key bindings from _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be
+          -q _\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn
+               Query about which keys invoke the named _\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn
+
+          The return value is 0 unless an unrecognized option  is
+          given or an error occurred.
+
+     break [_\bn]
+          Exit from within a for, while, or until loop.  If _\bn  is
+          specified,  break  _\bn  levels.   _\bn must be >\b_ 1.  If _\bn is
+          greater than the number of enclosing loops, all enclos-
+          ing loops are exited.  The return value is 0 unless the
+          shell is not executing a loop when break is executed.
+
+     builtin _\bs_\bh_\be_\bl_\bl-_\bb_\bu_\bi_\bl_\bt_\bi_\bn [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]
+          Execute the specified shell builtin, passing  it  _\ba_\br_\bg_\bu_\b-
+          _\bm_\be_\bn_\bt_\bs, and return its exit status.  This is useful when
+          you wish to define a function whose name is the same as
+          a  shell  builtin,  but  need  the functionality of the
+          builtin within the function itself.  The cd builtin  is
+          commonly  redefined  this  way.   The  return status is
+          false if _\bs_\bh_\be_\bl_\bl-_\bb_\bu_\bi_\bl_\bt_\bi_\bn is not a shell builtin command.
+
+     cd [_\bd_\bi_\br]
+          Change the current directory to _\bd_\bi_\br.  The variable HOME
+          is  the  default  _\bd_\bi_\br.  The variable CDPATH defines the
+          search path for the directory containing _\bd_\bi_\br.  Alterna-
+          tive  directory  names are separated by a colon (:).  A
+          null directory name  in  CDPATH  is  the  same  as  the
+          current  directory,  i.e., ``.''.  If _\bd_\bi_\br begins with a
+          slash (/), then CDPATH is not used.  An argument  of  -
+          is  equivalent to $OLDPWD.  The return value is true if
+          the   directory   was   successfully   changed;   false
+
+
+
+GNU              Last change: 1993 September 16                 2
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+          otherwise.
+
+     command [-pVv] _\bc_\bo_\bm_\bm_\ba_\bn_\bd [_\ba_\br_\bg ...]
+          Run _\bc_\bo_\bm_\bm_\ba_\bn_\bd with  _\ba_\br_\bg_\bs  suppressing  the  normal  shell
+          function  lookup.  Only  builtin  commands  or commands
+          found in the PATH are executed.  If the  -p  option  is
+          given,  the  search  for  _\bc_\bo_\bm_\bm_\ba_\bn_\bd  is performed using a
+          default value for PATH that is guaranteed to  find  all
+          of  the  standard  utilities.   If  either the -V or -v
+          option  is  supplied,  a  description  of  _\bc_\bo_\bm_\bm_\ba_\bn_\bd   is
+          printed.  The -v option causes a single word indicating
+          the command or pathname used to invoke  _\bc_\bo_\bm_\bm_\ba_\bn_\bd  to  be
+          printed; the -V option produces a more verbose descrip-
+          tion.  An argument of -- disables option  checking  for
+          the  rest  of the arguments.  If the -V or -v option is
+          supplied, the exit status is 0 if  _\bc_\bo_\bm_\bm_\ba_\bn_\bd  was  found,
+          and  1  if  not.   If neither option is supplied and an
+          error occurred or _\bc_\bo_\bm_\bm_\ba_\bn_\bd cannot  be  found,  the  exit
+          status  is 127.  Otherwise, the exit status of the com-
+          mand builtin is the exit status of _\bc_\bo_\bm_\bm_\ba_\bn_\bd.
+
+     continue [_\bn]
+          Resume the next iteration of the enclosing for,  while,
+          or  until  loop.   If _\bn is specified, resume at the _\bnth
+          enclosing loop.  _\bn must be >\b_ 1.  If _\bn is  greater  than
+          the  number of enclosing loops, the last enclosing loop
+          (the `top-level' loop) is resumed.  The return value is
+          0  unless  the  shell is not executing a loop when con-
+          tinue is executed.
+
+     declare [-frxi] [_\bn_\ba_\bm_\be[=_\bv_\ba_\bl_\bu_\be]]
+     typeset [-frxi] [_\bn_\ba_\bm_\be[=_\bv_\ba_\bl_\bu_\be]]
+          Declare variables and/or give them attributes.   If  no
+          _\bn_\ba_\bm_\bes  are  given, then display the values of variables
+          instead.  The options can be used to restrict output to
+          variables with the specified attribute.
+          -f   Use function names only
+          -r   Make _\bn_\ba_\bm_\bes readonly.  These names cannot  then  be
+               assigned  values  by  subsequent assignment state-
+               ments.
+          -x   Mark _\bn_\ba_\bm_\bes for export to subsequent  commands  via
+               the environment.
+          -i   The variable is treated as an integer;  arithmetic
+               evaluation  (see  ARITHMETIC  EVALUATION ) is per-
+               formed when the variable is assigned a value.
+
+          Using `+'  instead  of  `-'  turns  off  the  attribute
+          instead.   When  used in a function, makes _\bn_\ba_\bm_\bes local,
+          as with the local  command.   The  return  value  is  0
+          unless  an illegal option is encountered, an attempt is
+          made to define a function using "-f  foo=bar",  one  of
+          the  _\bn_\ba_\bm_\be_\bs  is  not  a  legal  shell  variable name, an
+
+
+
+GNU              Last change: 1993 September 16                 3
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+          attempt is made to  turn  off  readonly  status  for  a
+          readonly  variable,  or an attempt is made to display a
+          non-existant function with -f.
+
+     dirs [-l] [+/-n]
+          Display the list of currently  remembered  directories.
+          Directories  are  added to the list with the pushd com-
+          mand; the popd command moves back up through the list.
+          +n   displays the _\bnth entry counting from the  left  of
+               the  list  shown  by  dirs  when  invoked  without
+               options, starting with zero.
+          -n   displays the _\bnth entry counting from the right  of
+               the  list  shown  by  dirs  when  invoked  without
+               options, starting with zero.
+          -l   produces a longer  listing;  the  default  listing
+               format uses a tilde to denote the home directory.
+
+          The return value is 0 unless an illegal option is  sup-
+          plied  or  _\bn  indexes  beyond  the end of the directory
+          stack.
+
+     echo [-neE] [_\ba_\br_\bg ...]
+          Output the  _\ba_\br_\bgs,  separated  by  spaces.   The  return
+          status  is  always 0.  If -n is specified, the trailing
+          newline is suppressed.  If  the  -e  option  is  given,
+          interpretation of the following backslash-escaped char-
+          acters  is  enabled.   The  -E  option   disables   the
+          interpretation of these escape characters, even on sys-
+          tems where they are interpreted by default.
+          \a   alert (bell)
+          \b   backspace
+          \c   suppress trailing newline
+          \f   form feed
+          \n   new line
+          \r   carriage return
+          \t   horizontal tab
+          \v   vertical tab
+          \\   backslash
+          \nnn the character whose ASCII code is _\bn_\bn_\bn (octal)
+
+     enable [-n] [-all] [_\bn_\ba_\bm_\be ...]
+          Enable and disable builtin shell commands.  This allows
+          the execution of a disk command which has the same name
+          as a shell builtin without specifying a full  pathname.
+          If  -n is used, each _\bn_\ba_\bm_\be is disabled; otherwise, _\bn_\ba_\bm_\be_\bs
+          are enabled.  For example, to use the test binary found
+          via the PATH instead of the shell builtin version, type
+          ``enable -n test''.  If no arguments are given, a  list
+          of  all  enabled shell builtins is printed.  If only -n
+          is  supplied,  a  list  of  all  disabled  builtins  is
+          printed.   If  only  -all is supplied, the list printed
+          includes all builtins, with an indication of whether or
+
+
+
+GNU              Last change: 1993 September 16                 4
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+          not  each  is  enabled.  enable accepts -a as a synonym
+          for -all.  The return value is 0 unless a _\bn_\ba_\bm_\be is not a
+          shell builtin.
+
+     eval [_\ba_\br_\bg ...]
+          The _\ba_\br_\bgs are read and concatenated together into a sin-
+          gle command.  This command is then read and executed by
+          the shell, and its exit status is returned as the value
+          of  the  eval  command.   If there are no _\ba_\br_\bg_\bs, or only
+          null arguments, eval returns true.
+
+     exec [[-] _\bc_\bo_\bm_\bm_\ba_\bn_\bd [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]]
+          If _\bc_\bo_\bm_\bm_\ba_\bn_\bd is specified, it replaces the shell.  No new
+          process is created.  The _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs become the arguments
+          to _\bc_\bo_\bm_\bm_\ba_\bn_\bd.  If the first  argument  is  -,  the  shell
+          places  a  dash  in  the  zeroth arg passed to _\bc_\bo_\bm_\bm_\ba_\bn_\bd.
+          This is what login does.  If the file  cannot  be  exe-
+          cuted  for  some reason, a non-interactive shell exits,
+          unless  the   shell   variable   no_exit_on_failed_exec
+          exists,  in which case it returns failure.  An interac-
+          tive shell returns failure if the file cannot  be  exe-
+          cuted.   If  _\bc_\bo_\bm_\bm_\ba_\bn_\bd is not specified, any redirections
+          take effect in the current shell, and the return status
+          is 0.
+
+     exit [_\bn]
+          Cause the shell to exit with a status of _\bn.   If  _\bn  is
+          omitted,  the  exit  status is that of the last command
+          executed.  A trap on EXIT is executed before the  shell
+          terminates.
+
+     export [-nf] [_\bn_\ba_\bm_\be[=_\bw_\bo_\br_\bd]] ...
+     export -p
+          The supplied _\bn_\ba_\bm_\be_\bs are marked for automatic  export  to
+          the  environment of subsequently executed commands.  If
+          the -f option is given, the _\bn_\ba_\bm_\be_\bs refer  to  functions.
+          If no _\bn_\ba_\bm_\be_\bs are given, or if the -p option is supplied,
+          a list of all names that are exported in this shell  is
+          printed.   The  -n option causes the export property to
+          be removed from the named variables.  An argument of --
+          disables option checking for the rest of the arguments.
+          export returns an exit status of 0  unless  an  illegal
+          option  is encountered, one of the _\bn_\ba_\bm_\be_\bs is not a legal
+          shell variable name, or -f is supplied with a _\bn_\ba_\bm_\be that
+          is not a function.
+
+     fc [-e _\be_\bn_\ba_\bm_\be] [-nlr] [_\bf_\bi_\br_\bs_\bt] [_\bl_\ba_\bs_\bt]
+     fc -s [_\bp_\ba_\bt=_\br_\be_\bp] [_\bc_\bm_\bd]
+          Fix Command.  In the first form, a  range  of  commands
+          from  _\bf_\bi_\br_\bs_\bt  to _\bl_\ba_\bs_\bt is selected from the history list.
+          _\bF_\bi_\br_\bs_\bt and _\bl_\ba_\bs_\bt may be specified as a string (to  locate
+          the  last  command  beginning with that string) or as a
+
+
+
+GNU              Last change: 1993 September 16                 5
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+          number (an index into the history list, where  a  nega-
+          tive  number is used as an offset from the current com-
+          mand number).  If _\bl_\ba_\bs_\bt is not specified it  is  set  to
+          the  current  command  for  listing  (so that fc -l -10
+          prints the last 10 commands) and  to  _\bf_\bi_\br_\bs_\bt  otherwise.
+          If  _\bf_\bi_\br_\bs_\bt  is  not  specified it is set to the previous
+          command for editing and -16 for listing.
+
+          The -n flag suppresses the command numbers  when  list-
+          ing.   The  -r flag reverses the order of the commands.
+          If the -l flag is given, the  commands  are  listed  on
+          standard  output.  Otherwise, the editor given by _\be_\bn_\ba_\bm_\be
+          is invoked on a file  containing  those  commands.   If
+          _\be_\bn_\ba_\bm_\be is not given, the value of the FCEDIT variable is
+          used, and the value of EDITOR if FCEDIT is not set.  If
+          neither variable is set, is used.  When editing is com-
+          plete, the edited commands are echoed and executed.
+
+          In the second form, _\bc_\bo_\bm_\bm_\ba_\bn_\bd is re-executed  after  each
+          instance  of _\bp_\ba_\bt is replaced by _\br_\be_\bp.  A useful alias to
+          use with this is ``r=fc -s'', so that typing  ``r  cc''
+          runs  the last command beginning with ``cc'' and typing
+          ``r'' re-executes the last command.
+
+          If the first form is used, the return value is 0 unless
+          an  illegal  option  is  encountered  or  _\bf_\bi_\br_\bs_\bt or _\bl_\ba_\bs_\bt
+          specify history lines out of range.  If the  -e  option
+          is  supplied, the return value is the value of the last
+          command executed or failure if an error occurs with the
+          temporary  file  of  commands.   If  the second form is
+          used, the return status is  that  of  the  command  re-
+          executed,  unless  _\bc_\bm_\bd does not specify a valid history
+          line, in which case fc returns failure.
+
+     fg [_\bj_\bo_\bb_\bs_\bp_\be_\bc]
+          Place _\bj_\bo_\bb_\bs_\bp_\be_\bc  in  the  foreground,  and  make  it  the
+          current  job.   If  _\bj_\bo_\bb_\bs_\bp_\be_\bc is not present, the shell's
+          notion of the _\bc_\bu_\br_\br_\be_\bn_\bt _\bj_\bo_\bb is used.  The return value is
+          that  of  the  command  placed  into the foreground, or
+          failure if run when job control is  disabled  or,  when
+          run  with  job  control  enabled,  if  _\bj_\bo_\bb_\bs_\bp_\be_\bc does not
+          specify a valid job or _\bj_\bo_\bb_\bs_\bp_\be_\bc specifies a job that was
+          started without job control.
+
+     getopts _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg _\bn_\ba_\bm_\be [_\ba_\br_\bg_\bs]
+          getopts is used by shell procedures to parse positional
+          parameters.   _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg  contains the option letters to
+          be recognized; if a letter is followed by a colon,  the
+          option is expected to have an argument, which should be
+          separated from it by white  space.   Each  time  it  is
+          invoked,  getopts  places  the next option in the shell
+          variable _\bn_\ba_\bm_\be, initializing _\bn_\ba_\bm_\be if it does not  exist,
+
+
+
+GNU              Last change: 1993 September 16                 6
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+          and the index of the next argument to be processed into
+          the variable OPTIND.  OPTIND is initialized to  1  each
+          time  the  shell or a shell script is invoked.  When an
+          option requires an argument, getopts places that  argu-
+          ment  into  the  variable  OPTARG.   The shell does not
+          reset OPTIND automatically; it must be  manually  reset
+          between multiple calls to getopts within the same shell
+          invocation if a new set of parameters is to be used.
+
+          getopts can report errors in two ways.   If  the  first
+          character of _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg is a colon, _\bs_\bi_\bl_\be_\bn_\bt error report-
+          ing is used.  In normal operation  diagnostic  messages
+          are  printed  when  illegal  options  or missing option
+          arguments are encountered.  If the variable  OPTERR  is
+          set  to  0, no error message will be displayed, even if
+          the first character of _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg is not a colon.
+
+          If an illegal option is seen,  getopts  places  ?  into
+          _\bn_\ba_\bm_\be  and,  if  not silent, prints an error message and
+          unsets OPTARG.  If getopts is silent, the option  char-
+          acter  found is placed in OPTARG and no diagnostic mes-
+          sage is printed.
+
+          If a required argument is not found, and getopts is not
+          silent,  a  question mark (?) is placed in _\bn_\ba_\bm_\be, OPTARG
+          is unset, and a  diagnostic  message  is  printed.   If
+          getopts  is  silent, then a colon (:) is placed in _\bn_\ba_\bm_\be
+          and OPTARG is set to the option character found.
+
+          getopts normally parses the positional parameters,  but
+          if  more  arguments  are  given in _\ba_\br_\bg_\bs, getopts parses
+          those instead.  getopts  returns  true  if  an  option,
+          specified  or  unspecified, is found.  It returns false
+          if the end  of  options  is  encountered  or  an  error
+          occurs.
+
+     hash [-r] [_\bn_\ba_\bm_\be]
+          For each _\bn_\ba_\bm_\be, the full  pathname  of  the  command  is
+          determined  and  remembered.   The -r option causes the
+          shell to forget all remembered locations.  If no  argu-
+          ments  are given, information about remembered commands
+          is printed.  An argument of -- disables option checking
+          for  the  rest  of the arguments.  The return status is
+          true unless a _\bn_\ba_\bm_\be is not found or an illegal option is
+          supplied.
+
+     help [_\bp_\ba_\bt_\bt_\be_\br_\bn]
+          Display helpful information about builtin commands.  If
+          _\bp_\ba_\bt_\bt_\be_\br_\bn  is  specified, help gives detailed help on all
+          commands matching _\bp_\ba_\bt_\bt_\be_\br_\bn;  otherwise  a  list  of  the
+          builtins  is printed.  The return status is 0 unless no
+          command matches _\bp_\ba_\bt_\bt_\be_\br_\bn.
+
+
+
+GNU              Last change: 1993 September 16                 7
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+     history [_\bn]
+     history -rwan [_\bf_\bi_\bl_\be_\bn_\ba_\bm_\be]
+          With no options, display the command history list  with
+          line  numbers.   Lines  listed with a * have been modi-
+          fied.  An argument of _\bn lists only the  last  _\bn  lines.
+          If a non-option argument is supplied, it is used as the
+          name of the history file; if not, the value of HISTFILE
+          is  used.   Options,  if  supplied,  have the following
+          meanings:
+          -a   Append the ``new'' history  lines  (history  lines
+               entered  since  the  beginning of the current bash
+               session) to the history file
+          -n   Read the history lines not already read  from  the
+               history file into the current history list.  These
+               are lines appended to the history file  since  the
+               beginning of the current bash session.
+          -r   Read the contents of the history file and use them
+               as the current history
+          -w   Write the current history  to  the  history  file,
+               overwriting the history file's contents.
+
+          The return value is  0  unless  an  illegal  option  is
+          encountered or an error occurs while reading or writing
+          the history file.
+
+     jobs [-lnp] [ _\bj_\bo_\bb_\bs_\bp_\be_\bc ... ]
+     jobs -x _\bc_\bo_\bm_\bm_\ba_\bn_\bd [ _\ba_\br_\bg_\bs ... ]
+          The first form lists the active jobs.   The  -l  option
+          lists  process  IDs  in addition to the normal informa-
+          tion; the -p option lists only the process  ID  of  the
+          job's  process  group  leader.   The -n option displays
+          only jobs that have changed status since last notified.
+          If  _\bj_\bo_\bb_\bs_\bp_\be_\bc  is given, output is restricted to informa-
+          tion about that job.  The return status is 0 unless  an
+          illegal  option is encountered or an illegal _\bj_\bo_\bb_\bs_\bp_\be_\bc is
+          supplied.
+
+          If the -x option is supplied, jobs replaces any _\bj_\bo_\bb_\bs_\bp_\be_\bc
+          found in _\bc_\bo_\bm_\bm_\ba_\bn_\bd or _\ba_\br_\bg_\bs with the corresponding process
+          group ID, and executes _\bc_\bo_\bm_\bm_\ba_\bn_\bd passing it _\ba_\br_\bg_\bs, return-
+          ing its exit status.
+
+     kill [-s sigspec | -sigspec] [_\bp_\bi_\bd | _\bj_\bo_\bb_\bs_\bp_\be_\bc] ...
+     kill -l [_\bs_\bi_\bg_\bn_\bu_\bm]
+          Send the signal named by _\bs_\bi_\bg_\bs_\bp_\be_\bc to the processes named
+          by  _\bp_\bi_\bd  or  _\bj_\bo_\bb_\bs_\bp_\be_\bc.   _\bs_\bi_\bg_\bs_\bp_\be_\bc is either a signal name
+          such as SIGKILL or a signal number.  If  _\bs_\bi_\bg_\bs_\bp_\be_\bc  is  a
+          signal  name,  the  name is case insensitive and may be
+          given with or without the SIG prefix.   If  _\bs_\bi_\bg_\bs_\bp_\be_\bc  is
+          not  present,  then SIGTERM is assumed.  An argument of
+          -l lists the signal names.  If any arguments  are  sup-
+          plied  when  -l  is  given,  the names of the specified
+
+
+
+GNU              Last change: 1993 September 16                 8
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+          signals are listed, and the return  status  is  0.   An
+          argument of -- disables option checking for the rest of
+          the arguments.  kill returns true if at least one  sig-
+          nal  was successfully sent, or false if an error occurs
+          or an illegal option is encountered.
+
+     let _\ba_\br_\bg [_\ba_\br_\bg ...]
+          Each _\ba_\br_\bg is an arithmetic expression  to  be  evaluated
+          (see ARITHMETIC EVALUATION).  If the last _\ba_\br_\bg evaluates
+          to 0, let returns 1; 0 is returned otherwise.
+
+     local [_\bn_\ba_\bm_\be[=_\bv_\ba_\bl_\bu_\be] ...]
+          For each argument, create a local variable named  _\bn_\ba_\bm_\be,
+          and assign it _\bv_\ba_\bl_\bu_\be.  When local is used within a func-
+          tion, it causes the variable _\bn_\ba_\bm_\be  to  have  a  visible
+          scope  restricted  to  that  function and its children.
+          With no operands, local writes a list  of  local  vari-
+          ables  to  the  standard output.  It is an error to use
+          local when not within a function.  The return status is
+          0  unless local is used outside a function, or an ille-
+          gal _\bn_\ba_\bm_\be is supplied.
+
+     logout
+          Exit a login shell.
+
+     popd [+/-n]
+          Removes entries from  the  directory  stack.   With  no
+          arguments,  removes  the  top directory from the stack,
+          and performs a cd to the new top directory.
+          +n   removes the _\bnth entry counting from  the  left  of
+               the  list  shown by dirs, starting with zero.  For
+               example: ``popd +0'' removes the first  directory,
+               ``popd +1'' the second.
+          -n   removes the _\bnth entry counting from the  right  of
+               the  list  shown by dirs, starting with zero.  For
+               example: ``popd -0'' removes the  last  directory,
+               ``popd -1'' the next to last.
+
+          If the popd command is successful, a dirs is  performed
+          as  well,  and  the  return  status is 0.  popd returns
+          false if an illegal option is encountered,  the  direc-
+          tory  stack  is  empty,  a non-existent directory stack
+          entry is specified, or the directory change fails.
+
+     pushd [_\bd_\bi_\br]
+     pushd +/-n
+          Adds a directory to the top of the directory stack,  or
+          rotates  the stack, making the new top of the stack the
+          current  working   directory.    With   no   arguments,
+          exchanges the top two directories and returns 0, unless
+          the directory stack is empty.
+          +n   Rotates  the  stack  so  that  the  _\bnth  directory
+
+
+
+GNU              Last change: 1993 September 16                 9
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+               (counting from the left of the list shown by dirs)
+               is at the top.
+          -n   Rotates  the  stack  so  that  the  _\bnth  directory
+               (counting from the right) is at the top.
+          dir  adds _\bd_\bi_\br to the directory stack at the top, making
+               it the new current working directory.
+
+          If the pushd command is successful, a dirs is performed
+          as  well.   If  the first form is used, pushd returns 0
+          unless the cd to _\bd_\bi_\br  fails.   With  the  second  form,
+          pushd  returns 0 unless the directory stack is empty, a
+          non-existant directory stack element is  specified,  or
+          the  directory  change  to  the  specified  new current
+          directory fails.
+
+     pwd  Print the absolute  pathname  of  the  current  working
+          directory.  The path printed contains no symbolic links
+          if the -P option to the set  builtin  command  is  set.
+          See  also  the description of nolinks under Shell Vari-
+          ables above).  The return status is 0 unless  an  error
+          occurs while reading the pathname of the current direc-
+          tory.
+
+     read [-r] [_\bn_\ba_\bm_\be ...]
+          One line is read from the standard input, and the first
+          word  is assigned to the first _\bn_\ba_\bm_\be, the second word to
+          the  second  _\bn_\ba_\bm_\be,  and  so  on,  with  leftover  words
+          assigned  to the last _\bn_\ba_\bm_\be.  Only the characters in IFS
+          are recognized as word delimiters.   If  no  _\bn_\ba_\bm_\be_\bs  are
+          supplied,  the  line  read  is assigned to the variable
+          REPLY.  The return code is zero, unless end-of-file  is
+          encountered.   If  the -r option is given, a backslash-
+          newline pair is not ignored, and the backslash is  con-
+          sidered to be part of the line.
+
+     readonly [-f] [_\bn_\ba_\bm_\be ...]
+     readonly -p
+          The given _\bn_\ba_\bm_\be_\bs are marked readonly and the  values  of
+          these  _\bn_\ba_\bm_\be_\bs  may  not be changed by subsequent assign-
+          ment.  If the -f  option  is  supplied,  the  functions
+          corresponding  to the _\bn_\ba_\bm_\be_\bs are so marked.  If no argu-
+          ments are given, or if the -p  option  is  supplied,  a
+          list  of all readonly names is printed.  An argument of
+          -- disables option checking for the rest of  the  argu-
+          ments.  The return status is 0 unless an illegal option
+          is encountered, one of the _\bn_\ba_\bm_\be_\bs is not a  legal  shell
+          variable  name,  or  -f is supplied with a _\bn_\ba_\bm_\be that is
+          not a function.
+
+     return [_\bn]
+          Causes a function to exit with the return value  speci-
+          fied  by _\bn.  If _\bn is omitted, the return status is that
+
+
+
+GNU              Last change: 1993 September 16                10
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+          of the last command executed in the function body.   If
+          used  outside  a  function,  but  during execution of a
+          script by the . (source) command, it causes  the  shell
+          to  stop  executing  that script and return either _\bn or
+          the exit status of the last command executed within the
+          script  as the exit status of the script.  If used out-
+          side a function and not during execution of a script by
+          ., the return status is false.
+
+     set [--abefhkmnptuvxldCHP] [-o _\bo_\bp_\bt_\bi_\bo_\bn] [_\ba_\br_\bg ...]
+          -a      Automatically mark variables which are modified
+                  or  created  for  export  to the environment of
+                  subsequent commands.
+          -b      Cause the status of terminated background  jobs
+                  to  be reported immediately, rather than before
+                  the next  primary  prompt.   (Also  see  notify
+                  under Shell Variables above).
+          -e      Exit immediately if a _\bs_\bi_\bm_\bp_\bl_\be-_\bc_\bo_\bm_\bm_\ba_\bn_\bd (see SHELL
+                  GRAMMAR  above)  exits  with a non-zero status.
+                  The shell does not exit  if  the  command  that
+                  fails  is  part of an _\bu_\bn_\bt_\bi_\bl or _\bw_\bh_\bi_\bl_\be loop, part
+                  of an _\bi_\bf statement, part of a && or || list, or
+                  if the command's return value is being inverted
+                  via !.
+          -f      Disable pathname expansion.
+          -h      Locate and remember function commands as  func-
+                  tions  are defined.  Function commands are nor-
+                  mally looked up when the function is executed.
+          -k      All  keyword  arguments  are  placed   in   the
+                  environment  for a command, not just those that
+                  precede the command name.
+          -m      Monitor mode.  Job control  is  enabled.   This
+                  flag is on by default for interactive shells on
+                  systems  that  support  it  (see  JOB   CONTROL
+                  above).  Background processes run in a separate
+                  process group and a line containing their  exit
+                  status is printed upon their completion.
+          -n      Read commands but do not  execute  them.   This
+                  may  be used to check a shell script for syntax
+                  errors.   This  is  ignored   for   interactive
+                  shells.
+          -o _\bo_\bp_\bt_\bi_\bo_\bn-_\bn_\ba_\bm_\be
+                  The _\bo_\bp_\bt_\bi_\bo_\bn-_\bn_\ba_\bm_\be can be one of the following:
+                  allexport
+                          Same as -a.
+                  braceexpand
+                          The shell performs brace expansion (see
+                          Brace  Expansion above).  This is on by
+                          default.
+                  emacs   Use an emacs-style command line editing
+                          interface.   This is enabled by default
+                          when the shell is  interactive,  unless
+
+
+
+GNU              Last change: 1993 September 16                11
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+                          the  shell  is  started  with the -nol-
+                          ineediting option.
+                  errexit Same as -e.
+                  histexpand
+                          Same as -H.
+                  ignoreeof
+                          The effect is as if the  shell  command
+                          `IGNOREEOF=10'  had  been executed (see
+                          Shell Variables above).
+                  interactive-comments
+                          Allow a word beginning with # to  cause
+                          that  word and all remaining characters
+                          on  that  line  to  be  ignored  in  an
+                          interactive shell (see COMMENTS above).
+                  monitor Same as -m.
+                  noclobber
+                          Same as -C.
+                  noexec  Same as -n.
+                  noglob  Same as -f.
+                  nohash  Same as -d.
+                  notify  Same as -b.
+                  nounset Same as -u.
+                  physical
+                          Same as -P.
+                  posix   Change the behavior of bash  where  the
+                          default   operation  differs  from  the
+                          Posix  1003.2  standard  to  match  the
+                          standard.
+                  privileged
+                          Same as -p.
+                  verbose Same as -v.
+                  vi      Use a  vi-style  command  line  editing
+                          interface.
+                  xtrace  Same as -x.
+                  If no _\bo_\bp_\bt_\bi_\bo_\bn-_\bn_\ba_\bm_\be is supplied,  the  values  of
+                  the current options are printed.
+          -p      Turn on _\bp_\br_\bi_\bv_\bi_\bl_\be_\bg_\be_\bd mode.   In  this  mode,  the
+                  $ENV file is not processed, and shell functions
+                  are not inherited from the  environment.   This
+                  is  enabled  automatically  on  startup  if the
+                  effective user (group) id is not equal  to  the
+                  real  user (group) id.  Turning this option off
+                  causes the effective user and group ids  to  be
+                  set to the real user and group ids.
+          -t      Exit after reading and executing one command.
+          -u      Treat unset variables as an error when perform-
+                  ing   parameter  expansion.   If  expansion  is
+                  attempted  on  an  unset  variable,  the  shell
+                  prints  an  error message, and, if not interac-
+                  tive, exits with a non-zero status.
+          -v      Print shell input lines as they are read.
+          -x      After  expanding  each   _\bs_\bi_\bm_\bp_\bl_\be-_\bc_\bo_\bm_\bm_\ba_\bn_\bd,   bash
+
+
+
+GNU              Last change: 1993 September 16                12
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+                  displays the expanded value of PS4, followed by
+                  the command and its expanded arguments.
+          -l      Save and restore the binding of _\bn_\ba_\bm_\be in  a  for
+                  _\bn_\ba_\bm_\be  [in  word]  command  (see  SHELL  GRAMMAR
+                  above).
+          -d      Disable the hashing of commands that are looked
+                  up   for  execution.   Normally,  commands  are
+                  remembered in a hash table, and once found,  do
+                  not have to be looked up again.
+          -C      The  effect  is  as  if   the   shell   command
+                  `noclobber=' had been executed (see Shell Vari-
+                  ables above).
+          -H      Enable ! style history substitution.  This flag
+                  is on by default when the shell is interactive.
+          -P      If set, do not follow symbolic links when  per-
+                  forming  commands  such  as cd which change the
+                  current directory.  The physical  directory  is
+                  used instead.
+          --      If no arguments  follow  this  flag,  then  the
+                  positional  parameters  are  unset.  Otherwise,
+                  the positional parameters are set to the  _\ba_\br_\bgs,
+                  even if some of them begin with a -.
+          -       Signal the end of options, cause all  remaining
+                  _\ba_\br_\bgs  to  be assigned to the positional parame-
+                  ters.  The -x and -v options  are  turned  off.
+                  If there are no _\ba_\br_\bgs, the positional parameters
+                  remain unchanged.
+
+          The flags are off by default  unless  otherwise  noted.
+          Using  +  rather than - causes these flags to be turned
+          off.  The flags can also be specified as options to  an
+          invocation  of the shell.  The current set of flags may
+          be found in $-.  After the option  arguments  are  pro-
+          cessed,  the remaining _\bn _\ba_\br_\bgs are treated as values for
+          the positional parameters and are assigned,  in  order,
+          to $1, $2, ... $_\bn.  If no options or _\ba_\br_\bgs are supplied,
+          all shell variables are printed.  The return status  is
+          always true unless an illegal option is encountered.
+
+     shift [_\bn]
+          The positional parameters from _\bn+1 ... are  renamed  to
+          $1  ....  Parameters represented by the numbers $# down
+          to $#-_\bn+1 are unset.  If _\bn  is  0,  no  parameters  are
+          changed.   If _\bn is not given, it is assumed to be 1.  _\bn
+          must be a non-negative number less than or equal to $#.
+          If  _\bn is greater than $#, the positional parameters are
+          not changed.  The return status is greater than 0 if  _\bn
+          is greater than $# or less than 0; otherwise 0.
+
+     suspend [-f]
+          Suspend the execution of this shell until it receives a
+          SIGCONT  signal.  The -f option says not to complain if
+
+
+
+GNU              Last change: 1993 September 16                13
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+          this is a login shell; just suspend anyway.  The return
+          status is 0 unless the shell is a login shell and -f is
+          not supplied, or if job control is not enabled.
+
+     test _\be_\bx_\bp_\br
+     [ _\be_\bx_\bp_\br ]
+          Return a status of 0 (true) or 1 (false)  depending  on
+          the  evaluation  of  the  conditional  expression _\be_\bx_\bp_\br.
+          Expressions may be unary or binary.  Unary  expressions
+          are  often used to examine the status of a file.  There
+          are string operators and numeric  comparison  operators
+          as  well.  Each operator and operand must be a separate
+          argument.  If _\bf_\bi_\bl_\be is of the form /dev/fd/_\bn, then  file
+          descriptor _\bn is checked.
+          -b _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is block special.
+          -c _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is character special.
+          -d _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is a directory.
+          -e _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists.
+          -f _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is a regular file.
+          -g _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is set-group-id.
+          -k _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be has its ``sticky'' bit set.
+          -L _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is a symbolic link.
+          -p _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is a named pipe.
+          -r _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is readable.
+          -s _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and has a  size  greater  than
+               zero.
+          -S _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is a socket.
+          -t _\bf_\bd
+               True if _\bf_\bd is opened on a terminal.
+          -u _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and  its  set-user-id  bit  is
+               set.
+          -w _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is writable.
+          -x _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is executable.
+          -O _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be exists and is owned by the  effective
+               user id.
+          -G _\bf_\bi_\bl_\be
+
+
+
+GNU              Last change: 1993 September 16                14
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+               True if _\bf_\bi_\bl_\be exists and is owned by the  effective
+               group id.
+          _\bf_\bi_\bl_\be_\b1 -nt _\bf_\bi_\bl_\be_\b2
+               True if _\bf_\bi_\bl_\be_\b1 is newer (according to  modification
+               date) than _\bf_\bi_\bl_\be_\b2.
+          _\bf_\bi_\bl_\be_\b1 -ot _\bf_\bi_\bl_\be_\b2
+               True if _\bf_\bi_\bl_\be_\b1 is older than file2.
+          _\bf_\bi_\bl_\be_\b1 -ef _\bf_\bi_\bl_\be
+               True if _\bf_\bi_\bl_\be_\b1 and _\bf_\bi_\bl_\be_\b2 have the same  device  and
+               inode numbers.
+          -z _\bs_\bt_\br_\bi_\bn_\bg
+               True if the length of _\bs_\bt_\br_\bi_\bn_\bg is zero.
+          -n _\bs_\bt_\br_\bi_\bn_\bg
+          _\bs_\bt_\br_\bi_\bn_\bg
+               True if the length of _\bs_\bt_\br_\bi_\bn_\bg is non-zero.
+          _\bs_\bt_\br_\bi_\bn_\bg_\b1 = _\bs_\bt_\br_\bi_\bn_\bg_\b2
+               True if the strings are equal.
+          _\bs_\bt_\br_\bi_\bn_\bg_\b1 != _\bs_\bt_\br_\bi_\bn_\bg_\b2
+               True if the strings are not equal.
+          ! _\be_\bx_\bp_\br
+               True if _\be_\bx_\bp_\br is false.
+          _\be_\bx_\bp_\br_\b1 -a _\be_\bx_\bp_\br_\b2
+               True if both _\be_\bx_\bp_\br_\b1 AND _\be_\bx_\bp_\br_\b2 are true.
+          _\be_\bx_\bp_\br_\b1 -o _\be_\bx_\bp_\br_\b2
+               True if either _\be_\bx_\bp_\br_\b1 OR _\be_\bx_\bp_\br_\b2 is true.
+          _\ba_\br_\bg_\b1 OP _\ba_\br_\bg_\b2
+               OP is one of -eq, -ne,  -lt,  -le,  -gt,  or  -ge.
+               These  arithmetic  binary operators return true if
+               _\ba_\br_\bg_\b1 is equal,  not-equal,  less-than,  less-than-
+               or-equal,  greater-than,  or greater-than-or-equal
+               than _\ba_\br_\bg_\b2, respectively.  _\bA_\br_\bg_\b1  and  _\ba_\br_\bg_\b2  may  be
+               positive  integers, negative integers, or the spe-
+               cial expression -l _\bs_\bt_\br_\bi_\bn_\bg, which evaluates to  the
+               length of _\bs_\bt_\br_\bi_\bn_\bg.
+
+     times
+          Print the accumulated user and  system  times  for  the
+          shell and for processes run from the shell.  The return
+          status is 0.
+
+     trap [-l] [_\ba_\br_\bg] [_\bs_\bi_\bg_\bs_\bp_\be_\bc]
+          The command _\ba_\br_\bg is to be read  and  executed  when  the
+          shell  receives signal(s) _\bs_\bi_\bg_\bs_\bp_\be_\bc.  If _\ba_\br_\bg is absent or
+          -, all specified signals are reset  to  their  original
+          values  (the  values  they  had  upon  entrance  to the
+          shell).  If _\ba_\br_\bg is  the  null  string  this  signal  is
+          ignored  by  the  shell and by the commands it invokes.
+          _\bs_\bi_\bg_\bs_\bp_\be_\bc is either a signal name defined in  <_\bs_\bi_\bg_\bn_\ba_\bl._\bh>,
+          or  a signal number. If _\bs_\bi_\bg_\bs_\bp_\be_\bc is EXIT (0) the command
+          _\ba_\br_\bg is executed on exit from the shell.  With no  argu-
+          ments, trap prints the list of commands associated with
+          each signal number.  The -l option causes the shell  to
+
+
+
+GNU              Last change: 1993 September 16                15
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+          print  a  list  of signal names and their corresponding
+          numbers.  An argument of --  disables  option  checking
+          for  the  rest  of the arguments.  Signals ignored upon
+          entry to the shell cannot be trapped or reset.  Trapped
+          signals  are  reset to their original values in a child
+          process when it is created.  The return status is false
+          if either the trap name or number is invalid; otherwise
+          trap returns true.
+
+     type [-all] [-type | -path] _\bn_\ba_\bm_\be [_\bn_\ba_\bm_\be ...]
+          With no options, indicate how each _\bn_\ba_\bm_\be would be inter-
+          preted if used as a command name.  If the -type flag is
+          used, type prints a phrase which is one of _\ba_\bl_\bi_\ba_\bs,  _\bk_\be_\by_\b-
+          _\bw_\bo_\br_\bd,  _\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn,  _\bb_\bu_\bi_\bl_\bt_\bi_\bn, or _\bf_\bi_\bl_\be if _\bn_\ba_\bm_\be is an alias,
+          shell reserved word, function, builtin, or  disk  file,
+          respectively. If the name is not found, then nothing is
+          printed, and an exit status of false is  returned.   If
+          the -path flag is used, type either returns the name of
+          the disk file that  would  be  executed  if  _\bn_\ba_\bm_\be  were
+          specified  as a command name, or nothing if -type would
+          not return _\bf_\bi_\bl_\be.  If a command is hashed, -path  prints
+          the hashed value, not necessarily the file that appears
+          first in PATH.  If the -all flag is used,  type  prints
+          all  of  the  places  that  contain an executable named
+          _\bn_\ba_\bm_\be.  This includes aliases and functions, if and only
+          if  the  -path  flag  is  not  also used.  The table of
+          hashed commands is not consulted when using -all.  type
+          accepts  -a,  -t,  and  -p in place of -all, -type, and
+          -path, respectively.  An argument of -- disables option
+          checking  for  the rest of the arguments.  type returns
+          true if any of the arguments are found, false  if  none
+          are found.
+
+     ulimit [-SHacdfmstpnuv [_\bl_\bi_\bm_\bi_\bt]]
+          Ulimit provides control over the resources available to
+          the  shell  and  to processes started by it, on systems
+          that allow such control.  The value of _\bl_\bi_\bm_\bi_\bt can  be  a
+          number  in  the unit specified for the resource, or the
+          value unlimited.  The H and S options specify that  the
+          hard  or  soft  limit is set for the given resource.  A
+          hard limit cannot be increased once it is set;  a  soft
+          limit  may  be  increased  up  to the value of the hard
+          limit.  If neither H nor S is  specified,  the  command
+          applies  to  the  soft limit.  If _\bl_\bi_\bm_\bi_\bt is omitted, the
+          current value of the soft  limit  of  the  resource  is
+          printed,  unless the H option is given.  When more than
+          one resource is specified, the limit name and  unit  is
+          printed  before  the  value.   Other options are inter-
+          preted as follows:
+          -a   all current limits are reported
+          -c   the maximum size of core files created
+          -d   the maximum size of a process's data segment
+
+
+
+GNU              Last change: 1993 September 16                16
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+          -f   the maximum size of files created by the shell
+          -m   the maximum resident set size
+          -s   the maximum stack size
+          -t   the maximum amount of cpu time in seconds
+          -p   the pipe size in 512-byte blocks (this may not  be
+               set)
+          -n   the maximum number of open file descriptors  (most
+               systems  do  not  allow this value to be set, only
+               displayed)
+          -u   the maximum number of  processes  available  to  a
+               single user
+          -v   The maximum amount of virtual memory available  to
+               the shell
+
+          An argument of -- disables option checking for the rest
+          of  the  arguments.   If  _\bl_\bi_\bm_\bi_\bt is given, it is the new
+          value of the  specified  resource  (the  -a  option  is
+          display  only).   If  no  option  is  given, then -f is
+          assumed.  Values are in  1024-byte  increments,  except
+          for  -t,  which is in seconds, -p, which is in units of
+          512-byte blocks, and -n  and  -u,  which  are  unscaled
+          values.   The  return  status  is  0  unless an illegal
+          option is encountered,  a  non-numeric  argument  other
+          than unlimited is supplied as _\bl_\bi_\bm_\bi_\bt, or an error occurs
+          while setting a new limit.
+
+     umask [-S] [_\bm_\bo_\bd_\be]
+          The user file-creation mask is set to  _\bm_\bo_\bd_\be.   If  _\bm_\bo_\bd_\be
+          begins  with  a  digit,  it  is interpreted as an octal
+          number; otherwise it is interpreted as a symbolic  mode
+          mask  similar to that accepted by _\bc_\bh_\bm_\bo_\bd(1).  If _\bm_\bo_\bd_\be is
+          omitted, or if the -S option is supplied,  the  current
+          value of the mask is printed.  The -S option causes the
+          mask to be printed in symbolic form; the default output
+          is  an octal number.  An argument of -- disables option
+          checking for the rest of  the  arguments.   The  return
+          status  is 0 if the mode was successfully changed or if
+          no _\bm_\bo_\bd_\be argument was supplied, and false otherwise.
+
+     unalias [-a] [_\bn_\ba_\bm_\be ...]
+          Remove _\bn_\ba_\bm_\bes from the list of defined aliases.   If  -a
+          is  supplied,  all  alias definitions are removed.  The
+          return value is true unless a supplied _\bn_\ba_\bm_\be  is  not  a
+          defined alias.
+
+     unset [-fv] [_\bn_\ba_\bm_\be ...]
+          For each _\bn_\ba_\bm_\be, remove the  corresponding  variable  or,
+          given  the -f option, function.  An argument of -- dis-
+          ables option checking for the rest  of  the  arguments.
+          Note that PATH, IFS, PPID, PS1, PS2, UID, and EUID can-
+          not be unset.  If any of RANDOM,  SECONDS,  LINENO,  or
+          HISTCMD  are unset, they lose their special properties,
+
+
+
+GNU              Last change: 1993 September 16                17
+
+
+
+
+
+
+BASH_BUILTINS(1)         USER COMMANDS           BASH_BUILTINS(1)
+
+
+
+          even if they are subsequently reset.  The  exit  status
+          is  true  unless  a  _\bn_\ba_\bm_\be  does  not  exist  or is non-
+          unsettable.
+
+     wait [_\bn]
+          Wait for the specified process and return its  termina-
+          tion status.  _\bn may be a process ID or a job specifica-
+          tion; if a job spec is given,  all  processes  in  that
+          job's  pipeline are waited for.  If _\bn is not given, all
+          currently active child processes are  waited  for,  and
+          the  return  status  is  zero.   If  _\bn specifies a non-
+          existant process or job,  the  return  status  is  127.
+          Otherwise,  the return status is the exit status of the
+          last process or job waited for.
+
+SEE ALSO
+     bash(1), sh(1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+GNU              Last change: 1993 September 16                18
+
+
+
diff --git a/documentation/features.dvi b/documentation/features.dvi
new file mode 100644 (file)
index 0000000..21e5327
Binary files /dev/null and b/documentation/features.dvi differ
diff --git a/documentation/features.info b/documentation/features.info
new file mode 100644 (file)
index 0000000..6398445
--- /dev/null
@@ -0,0 +1,3011 @@
+This is Info file features.info, produced by Makeinfo-1.55 from the
+input file features.texi.
+
+This text is a brief description of the features that are present in
+the Bash shell.
+
+This is Edition 1.14, last updated 4 August 1994,
+of `The GNU Bash Features Guide',
+for `Bash', Version 1.14.
+
+Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Bash; see the file COPYING.  If not, write to the Free
+Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+\1f
+File: features.info,  Node: Top,  Next: Bourne Shell Features,  Prev: (DIR),  Up: (DIR)
+
+Bash Features
+*************
+
+   Bash contains features that appear in other popular shells, and some
+features that only appear in Bash.  Some of the shells that Bash has
+borrowed concepts from are the Bourne Shell (`sh'), the Korn Shell
+(`ksh'), and the C-shell (`csh' and its successor, `tcsh'). The
+following menu breaks the features up into categories based upon which
+one of these other shells inspired the feature.
+
+   This manual is meant as a brief introduction to features found in
+Bash.  The Bash manual page should be used as the definitive reference
+on shell behavior.
+
+* Menu:
+
+* Bourne Shell Features::      Features originally found in the
+                               Bourne shell.
+
+* Csh Features::               Features originally found in the
+                               Berkeley C-Shell.
+
+* Korn Shell Features::                Features originally found in the Korn
+                               Shell.
+
+* Bash Specific Features::     Features found only in Bash.
+
+* Job Control::                        A chapter describing what job control is
+                               and how bash allows you to use it.
+
+* Using History Interactively::        Chapter dealing with history expansion
+                               rules.
+
+* Command Line Editing::       Chapter describing the command line
+                               editing features.
+
+* Variable Index::             Quick reference helps you find the
+                               variable you want.
+
+* Concept Index::              General index for this manual.
+
+\1f
+File: features.info,  Node: Bourne Shell Features,  Next: Csh Features,  Prev: Top,  Up: Top
+
+Bourne Shell Style Features
+***************************
+
+   Bash is an acronym for Bourne Again SHell.  The Bourne shell is the
+traditional Unix shell originally written by Stephen Bourne.  All of
+the Bourne shell builtin commands are available in Bash, and the rules
+for evaluation and quoting are taken from the Posix 1003.2
+specification for the `standard' Unix shell.
+
+   This section briefly summarizes things which Bash inherits from the
+Bourne shell: shell control structures, builtins, variables, and other
+features.  It also lists the significant differences between Bash and
+the Bourne Shell.
+
+* Menu:
+
+* Looping Constructs::         Shell commands for iterative action.
+* Conditional Constructs::     Shell commands for conditional execution.
+* Shell Functions::            Grouping commands by name.
+* Bourne Shell Builtins::      Builtin commands inherited from the Bourne
+                               Shell.
+* Bourne Shell Variables::     Variables which Bash uses in the same way
+                               as the Bourne Shell.
+* Other Bourne Shell Features::        Addtional aspects of Bash which behave in
+                               the same way as the Bourne Shell.
+
+\1f
+File: features.info,  Node: Looping Constructs,  Next: Conditional Constructs,  Up: Bourne Shell Features
+
+Looping Constructs
+==================
+
+   Note that wherever you see a `;' in the description of a command's
+syntax, it may be replaced indiscriminately with one or more newlines.
+
+   Bash supports the following looping constructs.
+
+`until'
+     The syntax of the `until' command is:
+          until TEST-COMMANDS; do CONSEQUENT-COMMANDS; done
+     Execute CONSEQUENT-COMMANDS as long as the final command in
+     TEST-COMMANDS has an exit status which is not zero.
+
+`while'
+     The syntax of the `while' command is:
+          while TEST-COMMANDS; do CONSEQUENT-COMMANDS; done
+
+     Execute CONSEQUENT-COMMANDS as long as the final command in
+     TEST-COMMANDS has an exit status of zero.
+
+`for'
+     The syntax of the for command is:
+
+          for NAME [in WORDS ...]; do COMMANDS; done
+     Execute COMMANDS for each member in WORDS, with NAME bound to the
+     current member.  If "`in WORDS'" is not present, "`in "$@"'" is
+     assumed.
+
+\1f
+File: features.info,  Node: Conditional Constructs,  Next: Shell Functions,  Prev: Looping Constructs,  Up: Bourne Shell Features
+
+Conditional Constructs
+======================
+
+`if'
+     The syntax of the `if' command is:
+
+          if TEST-COMMANDS; then
+            CONSEQUENT-COMMANDS;
+          [elif MORE-TEST-COMMANDS; then
+            MORE-CONSEQUENTS;]
+          [else ALTERNATE-CONSEQUENTS;]
+          fi
+
+     Execute CONSEQUENT-COMMANDS only if the final command in
+     TEST-COMMANDS has an exit status of zero.  Otherwise, each `elif'
+     list is executed in turn, and if its exit status is zero, the
+     corresponding MORE-CONSEQUENTS is executed and the command
+     completes.  If "`else ALTERNATE-CONSEQUENTS'" is present, and the
+     final command in the final `if' or `elif' clause has a non-zero
+     exit status, then execute ALTERNATE-CONSEQUENTS.
+
+`case'
+     The syntax of the `case' command is:
+
+          `case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac'
+
+     Selectively execute COMMANDS based upon WORD matching PATTERN.
+     The ``|'' is used to separate multiple patterns.
+
+     Here is an example using `case' in a script that could be used to
+     describe an interesting feature of an animal:
+
+          echo -n "Enter the name of an animal: "
+          read ANIMAL
+          echo -n "The $ANIMAL has "
+          case $ANIMAL in
+            horse | dog | cat) echo -n "four";;
+            man | kangaroo ) echo -n "two";;
+            *) echo -n "an unknown number of";;
+          esac
+          echo "legs."
+
+\1f
+File: features.info,  Node: Shell Functions,  Next: Bourne Shell Builtins,  Prev: Conditional Constructs,  Up: Bourne Shell Features
+
+Shell Functions
+===============
+
+   Shell functions are a way to group commands for later execution
+using a single name for the group.  They are executed just like a
+"regular" command.  Shell functions are executed in the current shell
+context; no new process is created to interpret them.
+
+   Functions are declared using this syntax:
+
+     [ `function' ] NAME () { COMMAND-LIST; }
+
+   This defines a function named NAME.  The BODY of the function is the
+COMMAND-LIST between { and }.  This list is executed whenever NAME is
+specified as the name of a command.  The exit status of a function is
+the exit status of the last command executed in the body.
+
+   When a function is executed, the arguments to the function become
+the positional parameters during its execution.  The special parameter
+`#' that gives the number of positional parameters is updated to
+reflect the change.  Positional parameter 0 is unchanged.
+
+   If the builtin command `return' is executed in a function, the
+function completes and execution resumes with the next command after
+the function call.  When a function completes, the values of the
+positional parameters and the special parameter `#' are restored to the
+values they had prior to function execution.
+
+\1f
+File: features.info,  Node: Bourne Shell Builtins,  Next: Bourne Shell Variables,  Prev: Shell Functions,  Up: Bourne Shell Features
+
+Bourne Shell Builtins
+=====================
+
+   The following shell builtin commands are inherited from the Bourne
+shell.  These commands are implemented as specified by the Posix 1003.2
+standard.
+
+`:'
+     Do nothing beyond expanding any arguments and performing
+     redirections.
+
+`.'
+     Read and execute commands from the FILENAME argument in the
+     current shell context.
+
+`break'
+     Exit from a `for', `while', or `until' loop.
+
+`cd'
+     Change the current working directory.
+
+`continue'
+     Resume the next iteration of an enclosing `for', `while', or
+     `until' loop.
+
+`echo'
+     Print the arguments, separated by spaces, to the standard output.
+
+`eval'
+     The arguments are concatenated together into a single command,
+     which is then read and executed.
+
+`exec'
+     If a COMMAND argument is supplied, it replaces the shell.  If no
+     COMMAND is specified, redirections may be used to affect the
+     current shell environment.
+
+`exit'
+     Exit the shell.
+
+`export'
+     Mark the arguments as variables to be passed to child processes in
+     the environment.
+
+`getopts'
+     Parse options to shell scripts or functions.
+
+`hash'
+     Remember the full pathnames of commands specified as arguments, so
+     they need not be searched for on subsequent invocations.
+
+`kill'
+     Send a signal to a process.
+
+`pwd'
+     Print the current working directory.
+
+`read'
+     Read a line from the shell input and use it to set the values of
+     specified variables.
+
+`readonly'
+     Mark variables as unchangable.
+
+`return'
+     Cause a shell function to exit with a specified value.
+
+`shift'
+     Shift positional parameters to the left.
+
+`test'
+`['
+     Evaluate a conditional expression.
+
+`times'
+     Print out the user and system times used by the shell and its
+     children.
+
+`trap'
+     Specify commands to be executed when the shell receives signals.
+
+`umask'
+     Set the shell process's file creation mask.
+
+`unset'
+     Cause shell variables to disappear.
+
+`wait'
+     Wait until child processes exit and report their exit status.
+
+\1f
+File: features.info,  Node: Bourne Shell Variables,  Next: Other Bourne Shell Features,  Prev: Bourne Shell Builtins,  Up: Bourne Shell Features
+
+Bourne Shell Variables
+======================
+
+   Bash uses certain shell variables in the same way as the Bourne
+shell.  In some cases, Bash assigns a default value to the variable.
+
+`IFS'
+     A list of characters that separate fields; used when the shell
+     splits words as part of expansion.
+
+`PATH'
+     A colon-separated list of directories in which the shell looks for
+     commands.
+
+`HOME'
+     The current user's home directory.
+
+`CDPATH'
+     A colon-separated list of directories used as a search path for
+     the `cd' command.
+
+`MAILPATH'
+     A colon-separated list of files which the shell periodically checks
+     for new mail.    You can also specify what message is printed by
+     separating the file name from the message with a `?'.  When used
+     in the text of the message, `$_' stands for the name of the
+     current mailfile.
+
+`PS1'
+     The primary prompt string.
+
+`PS2'
+     The secondary prompt string.
+
+`OPTIND'
+     The index of the last option processed by the `getopts' builtin.
+
+`OPTARG'
+     The value of the last option argument processed by the `getopts'
+     builtin.
+
+\1f
+File: features.info,  Node: Other Bourne Shell Features,  Prev: Bourne Shell Variables,  Up: Bourne Shell Features
+
+Other Bourne Shell Features
+===========================
+
+* Menu:
+
+* Major Differences from the Bourne Shell::    Major differences between
+                                               Bash and the Bourne shell.
+
+   Bash implements essentially the same grammar, parameter and variable
+expansion, redirection, and quoting as the Bourne Shell.  Bash uses the
+Posix 1003.2 standard as the specification of how these features are to
+be implemented.  There are some differences between the traditional
+Bourne shell and the Posix standard; this section quickly details the
+differences of significance.  A number of these differences are
+explained in greater depth in subsequent sections.
+
+\1f
+File: features.info,  Node: Major Differences from the Bourne Shell,  Up: Other Bourne Shell Features
+
+Major Differences from the Bourne Shell
+---------------------------------------
+
+   Bash implements the `!' keyword to negate the return value of a
+pipeline.  Very useful when an `if' statement needs to act only if a
+test fails.
+
+   Bash includes brace expansion (*note Brace Expansion::.).
+
+   Bash includes the Posix and `ksh'-style pattern removal `%%' and
+`##' constructs to remove leading or trailing substrings from variables.
+
+   The Posix and `ksh'-style `$()' form of command substitution is
+implemented, and preferred to the Bourne shell's ```' (which is also
+implemented for backwards compatibility).
+
+   Variables present in the shell's initial environment are
+automatically exported to child processes.  The Bourne shell does not
+normally do this unless the variables are explicitly marked using the
+`export' command.
+
+   The expansion `${#xx}', which returns the length of `$xx', is
+supported.
+
+   The `IFS' variable is used to split only the results of expansion,
+not all words.  This closes a longstanding shell security hole.
+
+   It is possible to have a variable and a function with the same name;
+`sh' does not separate the two name spaces.
+
+   Bash functions are permitted to have local variables, and thus useful
+recursive functions may be written.
+
+   The `noclobber' option is available to avoid overwriting existing
+files with output redirection.
+
+   Bash allows you to write a function to override a builtin, and
+provides access to that builtin's functionality within the function via
+the `builtin' and `command' builtins.
+
+   The `command' builtin allows selective disabling of functions when
+command lookup is performed.
+
+   Individual builtins may be enabled or disabled using the `enable'
+builtin.
+
+   Functions may be exported to children via the environment.
+
+   The Bash `read' builtin will read a line ending in \ with the `-r'
+option, and will use the `$REPLY' variable as a default if no arguments
+are supplied.
+
+   The `return' builtin may be used to abort execution of scripts
+executed with the `.' or `source' builtins.
+
+   The `umask' builtin allows symbolic mode arguments similar to those
+accepted by `chmod'.
+
+   The `test' builtin is slightly different, as it implements the Posix
+1003.2 algorithm, which specifies the behavior based on the number of
+arguments.
+
+\1f
+File: features.info,  Node: Csh Features,  Next: Korn Shell Features,  Prev: Bourne Shell Features,  Up: Top
+
+C-Shell Style Features
+**********************
+
+   The C-Shell ("`csh'") was created by Bill Joy at UC Berkeley.  It is
+generally considered to have better features for interactive use than
+the original Bourne shell.  Some of the `csh' features present in Bash
+include job control, history expansion, `protected' redirection, and
+several variables for controlling the interactive behaviour of the shell
+(e.g. `IGNOREEOF').
+
+   *Note Using History Interactively:: for details on history expansion.
+
+* Menu:
+
+* Tilde Expansion::            Expansion of the ~ character.
+* Brace Expansion::            Expansion of expressions within braces.
+* C Shell Builtins::           Builtin commands adopted from the C Shell.
+* C Shell Variables::          Variables which Bash uses in essentially
+                               the same way as the C Shell.
+
+\1f
+File: features.info,  Node: Tilde Expansion,  Next: Brace Expansion,  Up: Csh Features
+
+Tilde Expansion
+===============
+
+   Bash has tilde (~) expansion, similar, but not identical, to that of
+`csh'.  The following table shows what unquoted words beginning with a
+tilde expand to.
+
+`~'
+     The current value of `$HOME'.
+
+`~/foo'
+     `$HOME/foo'
+
+`~fred/foo'
+     The subdirectory `foo' of the home directory of the user `fred'.
+
+`~+/foo'
+     `$PWD/foo'
+
+`~-'
+     `$OLDPWD/foo'
+
+   Bash will also tilde expand words following redirection operators
+and words following `=' in assignment statements.
+
+\1f
+File: features.info,  Node: Brace Expansion,  Next: C Shell Builtins,  Prev: Tilde Expansion,  Up: Csh Features
+
+Brace Expansion
+===============
+
+   Brace expansion is a mechanism by which arbitrary strings may be
+generated.  This mechanism is similar to PATHNAME EXPANSION (see the
+Bash manual page for details), but the file names generated need not
+exist.  Patterns to be brace expanded take the form of an optional
+PREAMBLE, followed by a series of comma-separated strings between a
+pair of braces, followed by an optional POSTAMBLE.  The preamble is
+prepended to each string contained within the braces, and the postamble
+is then appended to each resulting string, expanding left to right.
+
+   Brace expansions may be nested.  The results of each expanded string
+are not sorted; left to right order is preserved.  For example,
+     a{d,c,b}e
+   expands into ADE ACE ABE.
+
+   Brace expansion is performed before any other expansions, and any
+characters special to other expansions are preserved in the result.  It
+is strictly textual.  Bash does not apply any syntactic interpretation
+to the context of the expansion or the text between the braces.
+
+   A correctly-formed brace expansion must contain unquoted opening and
+closing braces, and at least one unquoted comma.  Any incorrectly
+formed brace expansion is left unchanged.
+
+   This construct is typically used as shorthand when the common prefix
+of the strings to be generated is longer than in the above example:
+     mkdir /usr/local/src/bash/{old,new,dist,bugs}
+   or
+     chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
+
+\1f
+File: features.info,  Node: C Shell Builtins,  Next: C Shell Variables,  Prev: Brace Expansion,  Up: Csh Features
+
+C Shell Builtins
+================
+
+   Bash has several builtin commands whose definition is very similar
+to `csh'.
+
+`pushd'
+          pushd [DIR | +N | -N]
+
+     Save the current directory on a list and then `cd' to DIR.  With no
+     arguments, exchanges the top two directories.
+
+    `+N'
+          Brings the Nth directory (counting from the left of the list
+          printed by `dirs') to the top of the list by rotating the
+          stack.
+
+    `-N'
+          Brings the Nth directory (counting from the right of the list
+          printed by `dirs') to the top of the list by rotating the
+          stack.
+
+    `DIR'
+          Makes the current working directory be the top of the stack,
+          and then CDs to DIR.  You can see the saved directory list
+          with the `dirs' command.
+
+`popd'
+          popd [+N | -N]
+
+     Pops the directory stack, and `cd's to the new top directory.  When
+     no arguments are given, removes the top directory from the stack
+     and `cd's to the new top directory.  The elements are numbered
+     from 0 starting at the first directory listed with `dirs'; i.e.
+     `popd' is equivalent to `popd +0'.
+    `+N'
+          Removes the Nth directory (counting from the left of the list
+          printed by `dirs'), starting with zero.
+
+    `-N'
+          Removes the Nth directory (counting from the right of the
+          list printed by `dirs'), starting with zero.
+
+`dirs'
+          dirs [+N | -N] [-L]
+     Display the list of currently remembered directories.  Directories
+     find their way onto the list with the `pushd' command; you can get
+     back up through the list with the `popd' command.
+    `+N'
+          Displays the Nth directory (counting from the left of the
+          list printed by `dirs' when invoked without options), starting
+          with zero.
+
+    `-N'
+          Displays the Nth directory (counting from the right of the
+          list printed by `dirs' when invoked without options), starting
+          with zero.
+
+    `-L'
+          Produces a longer listing; the default listing format uses a
+          tilde to denote the home directory.
+
+`history'
+          history [N] [ [-w -r -a -n] [FILENAME]]
+
+     Display the history list with line numbers.  Lines prefixed with
+     with a `*' have been modified.  An argument of N says to list only
+     the last N lines.  Option `-w' means write out the current history
+     to the history file; `-r' means to read the current history file
+     and make its contents the history list.  An argument of `-a' means
+     to append the new history lines (history lines entered since the
+     beginning of the current Bash session) to the history file.
+     Finally, the `-n' argument means to read the history lines not
+     already read from the history file into the current history list.
+     These are lines appended to the history file since the beginning
+     of the current Bash session.  If FILENAME is given, then it is used
+     as the history file, else if `$HISTFILE' has a value, that is
+     used, otherwise `~/.bash_history' is used.
+
+`logout'
+     Exit a login shell.
+
+`source'
+     A synonym for `.' (*note Bourne Shell Builtins::.)
+
+\1f
+File: features.info,  Node: C Shell Variables,  Prev: C Shell Builtins,  Up: Csh Features
+
+C Shell Variables
+=================
+
+`IGNOREEOF'
+     If this variable is set, it represents the number of consecutive
+     `EOF's Bash will read before exiting.  By default, Bash will exit
+     upon reading a single `EOF'.
+
+`cdable_vars'
+     If this variable is set, Bash treats arguments to the `cd' command
+     which are not directories as names of variables whose values are
+     the directories to change to.
+
+\1f
+File: features.info,  Node: Korn Shell Features,  Next: Bash Specific Features,  Prev: Csh Features,  Up: Top
+
+Korn Shell Style Features
+*************************
+
+   This section describes features primarily inspired by the Korn Shell
+(`ksh').  In some cases, the Posix 1003.2 standard has adopted these
+commands and variables from the Korn Shell; Bash implements those
+features using the Posix standard as a guide.
+
+* Menu:
+
+* Korn Shell Constructs::      Shell grammar constructs adopted from the
+                               Korn Shell
+* Korn Shell Builtins::                Builtin commands adopted from the Korn Shell.
+* Korn Shell Variables::       Variables which bash uses in essentially
+                               the same way as the Korn Shell.
+* Aliases::                    Substituting one command for another.
+
+\1f
+File: features.info,  Node: Korn Shell Constructs,  Next: Korn Shell Builtins,  Up: Korn Shell Features
+
+Korn Shell Constructs
+=====================
+
+   Bash includes the Korn Shell `select' construct.  This construct
+allows the easy generation of menus.  It has almost the same syntax as
+the `for' command.
+
+   The syntax of the `select' command is:
+     select NAME [in WORDS ...]; do COMMANDS; done
+
+   The list of words following `in' is expanded, generating a list of
+items.  The set of expanded words is printed on the standard error,
+each preceded by a number.  If the "`in WORDS'" is omitted, the
+positional parameters are printed.  The `PS3' prompt is then displayed
+and a line is read from the standard input. If the line consists of the
+number corresponding to one of the displayed words, then the value of
+NAME is set to that word.  If the line is empty, the words and prompt
+are displayed again.  If `EOF' is read, the `select' command completes.
+Any other value read causes NAME to be set to null.  The line read is
+saved in the variable `REPLY'.
+
+   The COMMANDS are executed after each selection until a `break' or
+`return' command is executed, at which point the `select' command
+completes.
+
+\1f
+File: features.info,  Node: Korn Shell Builtins,  Next: Korn Shell Variables,  Prev: Korn Shell Constructs,  Up: Korn Shell Features
+
+Korn Shell Builtins
+===================
+
+   This section describes Bash builtin commands taken from `ksh'.
+
+`fc'
+          `fc [-e ENAME] [-nlr] [FIRST] [LAST]'
+          `fc -s [PAT=REP] [COMMAND]'
+
+     Fix Command.  In the first form, a range of commands from FIRST to
+     LAST is selected from the history list.  Both FIRST and LAST may
+     be specified as a string (to locate the most recent command
+     beginning with that string) or as a number (an index into the
+     history list, where a negative number is used as an offset from the
+     current command number).  If LAST is not specified it is set to
+     FIRST.  If FIRST is not specified it is set to the previous
+     command for editing and -16 for listing.  If the `-l' flag is
+     given, the commands are listed on standard output.  The `-n' flag
+     suppresses the command numbers when listing.  The `-r' flag
+     reverses the order of the listing.  Otherwise, the editor given by
+     ENAME is invoked on a file containing those commands.  If ENAME is
+     not given, the value of the following variable expansion is used:
+     `${FCEDIT:-${EDITOR:-vi}}'.  This says to use the value of the
+     `FCEDIT' variable if set, or the value of the `EDITOR' variable if
+     that is set, or `vi' if neither is set.  When editing is complete,
+     the edited commands are echoed and executed.
+
+     In the second form, COMMAND is re-executed after each instance of
+     PAT in the selected command is replaced by REP.
+
+     A useful alias to use with the `fc' command is `r='fc -s'', so
+     that typing `r cc' runs the last command beginning with `cc' and
+     typing `r' re-executes the last command (*note Aliases::.).
+
+`let'
+     The `let' builtin allows arithmetic to be performed on shell
+     variables.  For details, refer to *Note Arithmetic Builtins::.
+
+`typeset'
+     The `typeset' command is supplied for compatibility with the Korn
+     shell; however, it has been made obsolete by the `declare' command
+     (*note Bash Builtins::.).
+
+\1f
+File: features.info,  Node: Korn Shell Variables,  Next: Aliases,  Prev: Korn Shell Builtins,  Up: Korn Shell Features
+
+Korn Shell Variables
+====================
+
+`REPLY'
+     The default variable for the `read' builtin.
+
+`RANDOM'
+     Each time this parameter is referenced, a random integer is
+     generated.  Assigning a value to this variable seeds the random
+     number generator.
+
+`SECONDS'
+     This variable expands to the number of seconds since the shell was
+     started.  Assignment to this variable resets the count to the
+     value assigned, and the expanded value becomes the value assigned
+     plus the number of seconds since the assignment.
+
+`PS3'
+     The value of this variable is used as the prompt for the `select'
+     command.
+
+`PS4'
+     This is the prompt printed before the command line is echoed when
+     the `-x' option is set (*note The Set Builtin::.).
+
+`PWD'
+     The current working directory as set by the `cd' builtin.
+
+`OLDPWD'
+     The previous working directory as set by the `cd' builtin.
+
+`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.  Bash terminates after that number of seconds if input does
+     not arrive.
+
+\1f
+File: features.info,  Node: Aliases,  Prev: Korn Shell Variables,  Up: Korn Shell Features
+
+Aliases
+=======
+
+* Menu:
+
+* Alias Builtins::             Builtins commands to maniuplate aliases.
+
+   The shell maintains a list of ALIASES that may be set and unset with
+the `alias' and `unalias' builtin commands.
+
+   The first word of each command, if unquoted, is checked to see if it
+has an alias.  If so, that word is replaced by the text of the alias.
+The alias name and the replacement text may contain any valid shell
+input, including shell metacharacters, with the exception that the
+alias name may not contain =.  The first word of the replacement text
+is tested for aliases, but a word that is identical to an alias being
+expanded is not expanded a second time.  This means that one may alias
+`ls' to `"ls -F"', for instance, and Bash does not try to recursively
+expand the replacement text. If the last character of the alias value
+is a space or tab character, then the next command word following the
+alias is also checked for alias expansion.
+
+   Aliases are created and listed with the `alias' command, and removed
+with the `unalias' command.
+
+   There is no mechanism for using arguments in the replacement text,
+as in `csh'.  If arguments are needed, a shell function should be used.
+
+   Aliases are not expanded when the shell is not interactive.
+
+   The rules concerning the definition and use of aliases are somewhat
+confusing.  Bash always reads at least one complete line of input
+before executing any of the commands on that line.  Aliases are
+expanded when a command is read, not when it is executed.  Therefore, an
+alias definition appearing on the same line as another command does not
+take effect until the next line of input is read.  This means that the
+commands following the alias definition on that line are not affected
+by the new alias.  This behavior is also an issue when functions are
+executed.  Aliases are expanded when the function definition is read,
+not when the function is executed, because a function definition is
+itself a compound command.  As a consequence, aliases defined in a
+function are not available until after that function is executed.  To
+be safe, always put alias definitions on a separate line, and do not
+use `alias' in compound commands.
+
+   Note that for almost every purpose, aliases are superseded by shell
+functions.
+
+\1f
+File: features.info,  Node: Alias Builtins,  Up: Aliases
+
+Alias Builtins
+--------------
+
+`alias'
+          alias [NAME[=VALUE] ...]
+
+     Without arguments, print the list of aliases on the standard
+     output.  If arguments are supplied, an alias is defined for each
+     NAME whose VALUE is given.  If no VALUE is given, the name and
+     value of the alias is printed.
+
+`unalias'
+          unalias [-a] [NAME ... ]
+
+     Remove each NAME from the list of aliases.  If `-a' is supplied,
+     all aliases are removed.
+
+\1f
+File: features.info,  Node: Bash Specific Features,  Next: Job Control,  Prev: Korn Shell Features,  Up: Top
+
+Bash Specific Features
+**********************
+
+   This section describes the features unique to Bash.
+
+* Menu:
+
+* Invoking Bash::              Command line options that you can give
+                               to Bash.
+* Bash Startup Files::         When and how Bash executes scripts.
+* Is This Shell Interactive?:: Determining the state of a running Bash.
+* Bash Builtins::              Table of builtins specific to Bash.
+* The Set Builtin::            This builtin is so overloaded it
+                               deserves its own section.
+* Bash Variables::             List of variables that exist in Bash.
+* Shell Arithmetic::           Arithmetic on shell variables.
+* Printing a Prompt::          Controlling the PS1 string.
+
+\1f
+File: features.info,  Node: Invoking Bash,  Next: Bash Startup Files,  Up: Bash Specific Features
+
+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 to be recognized.
+
+`-norc'
+     Don't read the `~/.bashrc' initialization file in an interactive
+     shell.  This is on by default if the shell is invoked as `sh'.
+
+`-rcfile FILENAME'
+     Execute commands from FILENAME (instead of `~/.bashrc') in an
+     interactive shell.
+
+`-noprofile'
+     Don't load the system-wide startup file `/etc/profile' or any of
+     the personal initialization files `~/.bash_profile',
+     `~/.bash_login', or `~/.profile' when bash is invoked as a login
+     shell.
+
+`-version'
+     Display the version number of this shell.
+
+`-login'
+     Make this shell act as if it were directly invoked from login.
+     This is equivalent to `exec - bash' but can be issued from another
+     shell, such as `csh'.  If you wanted to replace your current login
+     shell with a Bash login shell, you would say `exec bash -login'.
+
+`-nobraceexpansion'
+     Do not perform curly brace expansion (*note Brace Expansion::.).
+
+`-nolineediting'
+     Do not use the GNU Readline library (*note Command Line Editing::.)
+     to read interactive command lines.
+
+`-posix'
+     Change the behavior of Bash where the default operation differs
+     from the Posix 1003.2 standard to match the standard.  This is
+     intended to make Bash behave as a strict superset of that standard.
+
+   There are several single-character options you can give which are
+not available with the `set' builtin.
+
+`-c STRING'
+     Read and execute commands from STRING after processing the
+     options, then exit.
+
+`-i'
+     Force the shell to run interactively.
+
+`-s'
+     If this flag is present, or if no arguments remain after option
+     processing, then commands are read from the standard input.  This
+     option allows the positional parameters to be set when invoking an
+     interactive shell.
+
+   An *interactive* shell is one whose input and output are both
+connected to terminals (as determined by `isatty()'), or one started
+with the `-i' option.
+
+\1f
+File: features.info,  Node: Bash Startup Files,  Next: Is This Shell Interactive?,  Prev: Invoking Bash,  Up: Bash Specific Features
+
+Bash Startup Files
+==================
+
+   When and how Bash executes startup files.
+
+     For Login shells (subject to the -noprofile option):
+     
+         On logging in:
+            If `/etc/profile' exists, then source it.
+     
+            If `~/.bash_profile' exists, then source it,
+               else if `~/.bash_login' exists, then source it,
+                  else if `~/.profile' exists, then source it.
+     
+         On logging out:
+            If `~/.bash_logout' exists, source it.
+     
+     For non-login interactive shells (subject to the -norc and -rcfile options):
+         On starting up:
+            If `~/.bashrc' exists, then source it.
+     
+     For non-interactive shells:
+         On starting up:
+            If the environment variable `ENV' is non-null, expand the
+            variable and source the file named by the value.  If Bash is
+            not started in Posix mode, it looks for `BASH_ENV' before
+            `ENV'.
+
+   So, typically, your `~/.bash_profile' contains the line
+     `if [ -f `~/.bashrc' ]; then source `~/.bashrc'; fi'
+
+after (or before) any login specific initializations.
+
+   If Bash is invoked as `sh', it tries to mimic the behavior of `sh'
+as closely as possible.  For a login shell, it attempts to source only
+`/etc/profile' and `~/.profile', in that order.  The `-noprofile'
+option may still be used to disable this behavior.  A shell invoked as
+`sh' does not attempt to source any other startup files.
+
+   When Bash is started in POSIX mode, as with the `-posix' command
+line option, it follows the Posix 1003.2 standard for startup files.
+In this mode, the `ENV' variable is expanded and that file sourced; no
+other startup files are read.
+
+\1f
+File: features.info,  Node: Is This Shell Interactive?,  Next: Bash Builtins,  Prev: Bash Startup Files,  Up: Bash Specific Features
+
+Is This Shell Interactive?
+==========================
+
+   You may wish to determine within a startup script whether Bash is
+running interactively or not.  To do this, examine the variable `$PS1';
+it is unset in non-interactive shells, and set in interactive shells.
+Thus:
+
+     if [ -z "$PS1" ]; then
+       echo This shell is not interactive
+     else
+       echo This shell is interactive
+     fi
+
+   You can ask an interactive Bash to not run your `~/.bashrc' file
+with the `-norc' flag.  You can change the name of the `~/.bashrc' file
+to any other file name with `-rcfile FILENAME'.  You can ask Bash to
+not run your `~/.bash_profile' file with the `-noprofile' flag.
+
+\1f
+File: features.info,  Node: Bash Builtins,  Next: The Set Builtin,  Prev: Is This Shell Interactive?,  Up: Bash Specific Features
+
+Bash Builtin Commands
+=====================
+
+   This section describes builtin commands which are unique to or have
+been extended in Bash.
+
+`builtin'
+          builtin [SHELL-BUILTIN [ARGS]]
+     Run a shell builtin.  This is useful when you wish to rename a
+     shell builtin to be a function, but need the functionality of the
+     builtin within the function itself.
+
+`bind'
+          bind [-m KEYMAP] [-lvd] [-q NAME]
+          bind [-m KEYMAP] -f FILENAME
+          bind [-m KEYMAP] KEYSEQ:FUNCTION-NAME
+
+     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
+     `.inputrc' (*note Readline Init File::.), but each binding must be
+     passed as a separate argument: `"\C-x\C-r":re-read-init-file'.
+     Options, if supplied, have the following meanings:
+
+    `-m keymap'
+          Use KEYMAP as the keymap to be affected by the subsequent
+          bindings.  Acceptable KEYMAP names are `emacs',
+          `emacs-standard', `emacs-meta', `emacs-ctlx', `vi', `vi-move',
+          `vi-command', and `vi-insert'.  `vi' is equivalent to
+          `vi-command'; `emacs' is equivalent to `emacs-standard'.
+
+    `-l'
+          List the names of all readline functions
+
+    `-v'
+          List current function names and bindings
+
+    `-d'
+          Dump function names and bindings in such a way that they can
+          be re-read
+
+    `-f filename'
+          Read key bindings from FILENAME
+
+    `-q'
+          Query about which keys invoke the named FUNCTION
+
+`command'
+          command [-pVv] COMMAND [ARGS ...]
+     Runs COMMAND with ARG ignoring shell functions.  If you have a
+     shell function called `ls', and you wish to call the command `ls',
+     you can say `command ls'.  The `-p' option means to use a default
+     value for `$PATH' that is guaranteed to find all of the standard
+     utilities.
+
+     If either the `-V' or `-v' option is supplied, a description of
+     COMMAND is printed.  The `-v' option causes a single word
+     indicating the command or file name used to invoke COMMAND to be
+     printed; the `-V' option produces a more verbose description.
+
+`declare'
+          declare [-frxi] [NAME[=VALUE]]
+
+     Declare variables and/or give them attributes.  If no NAMEs are
+     given, then display the values of variables instead.  `-f' means
+     to use function names only.  `-r' says to make NAMEs readonly.
+     `-x' says to mark NAMEs for export.  `-i' says that the variable
+     is to be treated as an integer; arithmetic evaluation (*note Shell
+     Arithmetic::.) is performed when the variable is assigned a value.
+     Using `+' instead of `-' turns off the attribute instead.  When
+     used in a function, `declare' makes NAMEs local, as with the
+     `local' command.
+
+`enable'
+          enable [-n] [-a] [NAME ...]
+     Enable and disable builtin shell commands.  This allows you to use
+     a disk command which has the same name as a shell builtin.  If
+     `-n' is used, the NAMEs become disabled.  Otherwise NAMEs are
+     enabled.  For example, to use the `test' binary found via `$PATH'
+     instead of the shell builtin version, type `enable -n test'.  The
+     `-a' option means to list each builtin with an indication of
+     whether or not it is enabled.
+
+`help'
+          help [PATTERN]
+     Display helpful information about builtin commands.  If PATTERN is
+     specified, `help' gives detailed help on all commands matching
+     PATTERN, otherwise a list of the builtins is printed.
+
+`local'
+          local NAME[=VALUE]
+     For each argument, create a local variable called NAME, and give
+     it VALUE.  `local' can only be used within a function; it makes
+     the variable NAME have a visible scope restricted to that function
+     and its children.
+
+`type'
+          type [-all] [-type | -path] [NAME ...]
+     For each NAME, indicate how it would be interpreted if used as a
+     command name.
+
+     If the `-type' flag is used, `type' returns a single word which is
+     one of "alias", "function", "builtin", "file" or "keyword", if
+     NAME is an alias, shell function, shell builtin, disk file, or
+     shell reserved word, respectively.
+
+     If the `-path' flag is used, `type' either returns the name of the
+     disk file that would be executed, or nothing if `-type' would not
+     return "file".
+
+     If the `-all' flag is used, returns all of the places that contain
+     an executable named FILE.  This includes aliases and functions, if
+     and only if the `-path' flag is not also used.
+
+     `Type' accepts `-a', `-t', and `-p' as equivalent to `-all',
+     `-type', and `-path', respectively.
+
+`ulimit'
+          ulimit [-acdmstfpnuvSH] [LIMIT]
+     `Ulimit' provides control over the resources available to processes
+     started by the shell, on systems that allow such control.  If an
+     option is given, it is interpreted as follows:
+    `-S'
+          change and report the soft limit associated with a resource
+          (the default if the `-H' option is not given).
+
+    `-H'
+          change and report the hard limit associated with a resource.
+
+    `-a'
+          all current limits are reported.
+
+    `-c'
+          the maximum size of core files created.
+
+    `-d'
+          the maximum size of a process's data segment.
+
+    `-m'
+          the maximum resident set size.
+
+    `-s'
+          the maximum stack size.
+
+    `-t'
+          the maximum amount of cpu time in seconds.
+
+    `-f'
+          the maximum size of files created by the shell.
+
+    `-p'
+          the pipe buffer size.
+
+    `-n'
+          the maximum number of open file descriptors.
+
+    `-u'
+          the maximum number of processes available to a single user.
+
+    `-v'
+          the maximum amount of virtual memory available to the process.
+
+     If LIMIT is given, it is the new value of the specified resource.
+     Otherwise, the current value of the specified resource is printed.
+     If no option is given, then `-f' is assumed.  Values are in
+     1024-byte increments, except for `-t', which is in seconds, `-p',
+     which is in units of 512-byte blocks, and `-n' and `-u', which are
+     unscaled values.
+
+\1f
+File: features.info,  Node: The Set Builtin,  Next: Bash Variables,  Prev: Bash Builtins,  Up: Bash Specific Features
+
+The Set Builtin
+===============
+
+   This builtin is so overloaded that it deserves its own section.
+
+`set'
+          set [-abefhkmnptuvxldCHP] [-o OPTION] [ARGUMENT ...]
+
+    `-a'
+          Mark variables which are modified or created for export.
+
+    `-b'
+          Cause the status of terminated background jobs to be reported
+          immediately, rather than before printing the next primary
+          prompt.
+
+    `-e'
+          Exit immediately if a command exits with a non-zero status.
+
+    `-f'
+          Disable file name generation (globbing).
+
+    `-h'
+          Locate and remember (hash) commands as functions are defined,
+          rather than when the function is executed.
+
+    `-k'
+          All keyword arguments are placed in the environment for a
+          command, not just those that precede the command name.
+
+    `-m'
+          Job control is enabled (*note Job Control::.).
+
+    `-n'
+          Read commands but do not execute them.
+
+    `-o OPTION-NAME'
+          Set the flag corresponding to OPTION-NAME:
+
+         `allexport'
+               same as `-a'.
+
+         `braceexpand'
+               the shell will perform brace expansion (*note Brace
+               Expansion::.).
+
+         `emacs'
+               use an emacs-style line editing interface (*note Command
+               Line Editing::.).
+
+         `errexit'
+               same as `-e'.
+
+         `histexpand'
+               same as `-H'.
+
+         `ignoreeof'
+               the shell will not exit upon reading EOF.
+
+         `interactive-comments'
+               allow a word beginning with a `#' to cause that word and
+               all remaining characters on that line to be ignored in an
+               interactive shell.
+
+         `monitor'
+               same as `-m'.
+
+         `noclobber'
+               same as `-C'.
+
+         `noexec'
+               same as `-n'.
+
+         `noglob'
+               same as `-f'.
+
+         `nohash'
+               same as `-d'.
+
+         `notify'
+               same as `-b'.
+
+         `nounset'
+               same as `-u'.
+
+         `physical'
+               same as `-P'.
+
+         `posix'
+               change the behavior of Bash where the default operation
+               differs from the Posix 1003.2 standard to match the
+               standard.  This is intended to make Bash behave as a
+               strict superset of that standard.
+
+         `privileged'
+               same as `-p'.
+
+         `verbose'
+               same as `-v'.
+
+         `vi'
+               use a `vi'-style line editing interface.
+
+         `xtrace'
+               same as `-x'.
+
+    `-p'
+          Turn on privileged mode.  In this mode, the `$ENV' file is
+          not processed, and shell functions are not inherited from the
+          environment.  This is enabled automatically on startup if the
+          effective user (group) id is not equal to the real user
+          (group) id.  Turning this option off causes the effective user
+          and group ids to be set to the real user and group ids.
+
+    `-t'
+          Exit after reading and executing one command.
+
+    `-u'
+          Treat unset variables as an error when substituting.
+
+    `-v'
+          Print shell input lines as they are read.
+
+    `-x'
+          Print commands and their arguments as they are executed.
+
+    `-l'
+          Save and restore the binding of the NAME in a `for' command.
+
+    `-d'
+          Disable the hashing of commands that are looked up for
+          execution.  Normally, commands are remembered in a hash
+          table, and once found, do not have to be looked up again.
+
+    `-C'
+          Disallow output redirection to existing files.
+
+    `-H'
+          Enable ! style history substitution.  This flag is on by
+          default.
+
+    `-P'
+          If set, do not follow symbolic links when performing commands
+          such as `cd' which change the current directory.  The
+          physical directory is used instead.
+
+    `--'
+          If no arguments follow this flag, then the positional
+          parameters are unset.  Otherwise, the positional parameters
+          are set to the ARGUMENTS, even if some of them begin with a
+          `-'.
+
+    `-'
+          Signal the end of options, cause all remaining ARGUMENTS to
+          be assigned to the positional parameters.  The `-x' and `-v'
+          options are turned off.  If there are no arguments, the
+          positional parameters remain unchanged.
+
+     Using `+' rather than `-' causes these flags to be turned off.
+     The flags can also be used upon invocation of the shell.  The
+     current set of flags may be found in `$-'.  The remaining N
+     ARGUMENTS are positional parameters and are assigned, in order, to
+     `$1', `$2', ..  `$N'.  If no arguments are given, all shell
+     variables are printed.
+
+\1f
+File: features.info,  Node: Bash Variables,  Next: Shell Arithmetic,  Prev: The Set Builtin,  Up: Bash Specific Features
+
+Bash Variables
+==============
+
+   These variables are set or used by bash, but other shells do not
+normally treat them specially.
+
+`HISTCONTROL'
+`history_control'
+     Set to a value of `ignorespace', it means don't enter lines which
+     begin with a space or tab into the history list.  Set to a value
+     of `ignoredups', it means don't enter lines which match the last
+     entered line.  A value of `ignoreboth' combines the two options.
+     Unset, or set to any other value than those above, means to save
+     all lines on the history list.
+
+`HISTFILE'
+     The name of the file to which the command history is saved.
+
+`HISTSIZE'
+     If set, this is the maximum number of commands to remember in the
+     history.
+
+`histchars'
+     Up to three characters which control history expansion, quick
+     substitution, and tokenization (*note History Interaction::.).
+     The first character is the "history-expansion-char", that is, the
+     character which signifies the start of a history expansion,
+     normally `!'.  The second character is the character which
+     signifies `quick substitution' when seen as the first character on
+     a line, normally `^'.  The optional third character is the
+     character which signifies the remainder of the line is a comment,
+     when found as the first character of a word, usually `#'.  The
+     history comment character causes history substitution to be
+     skipped for the remaining words on the line.  It does not
+     necessarily cause the shell parser to treat the rest of the line
+     as a comment.
+
+`HISTCMD'
+     The history number, or index in the history list, of the current
+     command.  If `HISTCMD' is unset, it loses its special properties,
+     even if it is subsequently reset.
+
+`hostname_completion_file'
+`HOSTFILE'
+     Contains the name of a file in the same format as `/etc/hosts' that
+     should be read when the shell needs to complete a hostname.  You
+     can change the file interactively; the next time you attempt to
+     complete a hostname, Bash will add the contents of the new file to
+     the already existing database.
+
+`MAILCHECK'
+     How often (in seconds) that the shell should check for mail in the
+     files specified in `MAILPATH'.
+
+`PROMPT_COMMAND'
+     If present, this contains a string which is a command to execute
+     before the printing of each primary prompt (`$PS1').
+
+`UID'
+     The numeric real user id of the current user.
+
+`EUID'
+     The numeric effective user id of the current user.
+
+`HOSTTYPE'
+     A string describing the machine Bash is running on.
+
+`OSTYPE'
+     A string describing the operating system Bash is running on.
+
+`FIGNORE'
+     A colon-separated list of suffixes to ignore when performing
+     filename completion A file name whose suffix matches one of the
+     entries in `FIGNORE' is excluded from the list of matched file
+     names.  A sample value is `.o:~'
+
+`INPUTRC'
+     The name of the Readline startup file, overriding the default of
+     `~/.inputrc'.
+
+`BASH_VERSION'
+     The version number of the current instance of Bash.
+
+`IGNOREEOF'
+     Controls the action of the shell on receipt of an `EOF' character
+     as the sole input.  If set, then the value of it is the number of
+     consecutive `EOF' characters that can be read as the first
+     characters on an input line before the shell will exit.  If the
+     variable exists but does not have a numeric value (or has no
+     value) then the default is 10.  If the variable does not exist,
+     then `EOF' signifies the end of input to the shell.  This is only
+     in effect for interactive shells.
+
+`no_exit_on_failed_exec'
+     If this variable exists, the shell will not exit in the case that
+     it couldn't execute the file specified in the `exec' command.
+
+`nolinks'
+     If present, says not to follow symbolic links when doing commands
+     that change the current working directory.  By default, bash
+     follows the logical chain of directories when performing commands
+     such as `cd' which change the current directory.
+
+     For example, if `/usr/sys' is a link to `/usr/local/sys' then:
+          $ cd /usr/sys; echo $PWD
+          /usr/sys
+          $ cd ..; pwd
+          /usr
+
+     If `nolinks' exists, then:
+          $ cd /usr/sys; echo $PWD
+          /usr/local/sys
+          $ cd ..; pwd
+          /usr/local
+
+     See also the description of the `-P' option to the `set' builtin,
+     *Note The Set Builtin::.
+
+\1f
+File: features.info,  Node: Shell Arithmetic,  Next: Printing a Prompt,  Prev: Bash Variables,  Up: Bash Specific Features
+
+Shell Arithmetic
+================
+
+* Menu:
+
+* Arithmetic Evaluation::      How shell arithmetic works.
+* Arithmetic Expansion::       How to use arithmetic in shell expansions.
+* Arithmetic Builtins::                Builtin commands that use shell arithmetic.
+
+\1f
+File: features.info,  Node: Arithmetic Evaluation,  Next: Arithmetic Expansion,  Up: Shell Arithmetic
+
+Arithmetic Evaluation
+---------------------
+
+   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 following
+list of operators is grouped into levels of equal-precedence operators.
+The levels are listed in order of decreasing precedence.
+
+`- +'
+     unary minus and plus
+
+`! ~'
+     logical and bitwise negation
+
+`* / %'
+     multiplication, division, remainder
+
+`+ -'
+     addition, subtraction
+
+`<< >>'
+     left and right bitwise shifts
+
+`<= >= < >'
+     comparison
+
+`== !='
+     equality and inequality
+
+`&'
+     bitwise AND
+
+`^'
+     bitwise exclusive OR
+
+`|'
+     bitwise OR
+
+`&&'
+     logical AND
+
+`||'
+     logical OR
+
+`= *= /= %= += -= <<= >>= &= ^= |='
+     assignment
+
+   Shell variables are allowed as operands; parameter expansion is
+performed before the expression is evaluated.  The value of a parameter
+is coerced to a long integer within an expression.  A shell variable
+need not have its integer attribute turned on to be used in an
+expression.
+
+   Constants with a leading 0 are interpreted as octal numbers.  A
+leading `0x' or `0X' denotes hexadecimal.  Otherwise, numbers take the
+form [BASE#]n, where BASE is a decimal number between 2 and 36
+representing the arithmetic base, and N is a number in that base.  If
+BASE is omitted, then base 10 is used.
+
+   Operators are evaluated in order of precedence.  Sub-expressions in
+parentheses are evaluated first and may override the precedence rules
+above.
+
+\1f
+File: features.info,  Node: Arithmetic Expansion,  Next: Arithmetic Builtins,  Prev: Arithmetic Evaluation,  Up: Shell Arithmetic
+
+Arithmetic Expansion
+--------------------
+
+   Arithmetic expansion allows the evaluation of an arithmetic
+expression and the substitution of the result.  There are two formats
+for arithmetic expansion:
+
+     $[ expression ]
+     $(( expression ))
+
+   The expression is treated as if it were within double quotes, but a
+double quote inside the braces or parentheses is not treated specially.
+All tokens in the expression undergo parameter expansion, command
+substitution, and quote removal.  Arithmetic substitutions may be
+nested.
+
+   The evaluation is performed according to the rules listed above.  If
+the expression is invalid, Bash prints a message indicating failure and
+no substitution occurs.
+
+\1f
+File: features.info,  Node: Arithmetic Builtins,  Prev: Arithmetic Expansion,  Up: Shell Arithmetic
+
+Arithmetic Builtins
+-------------------
+
+`let'
+          let EXPRESSION [EXPRESSION]
+     The `let' builtin allows arithmetic to be performed on shell
+     variables.  Each EXPRESSION is evaluated according to the rules
+     given previously (*note Arithmetic Evaluation::.).  If the last
+     EXPRESSION evaluates to 0, `let' returns 1; otherwise 0 is
+     returned.
+
+\1f
+File: features.info,  Node: Printing a Prompt,  Prev: Shell Arithmetic,  Up: Bash Specific Features
+
+Controlling the Prompt
+======================
+
+   The value of the variable `$PROMPT_COMMAND' is examined just before
+Bash prints each primary prompt.  If it is set and non-null, then the
+value is executed just as if you had typed it on the command line.
+
+   In addition, the following table describes the special characters
+which can appear in the `PS1' variable:
+
+`\t'
+     the time, in HH:MM:SS format.
+
+`\d'
+     the date, in "Weekday Month Date" format (e.g. "Tue May 26").
+
+`\n'
+     newline.
+
+`\s'
+     the name of the shell, the basename of `$0' (the portion following
+     the final slash).
+
+`\w'
+     the current working directory.
+
+`\W'
+     the basename of `$PWD'.
+
+`\u'
+     your username.
+
+`\h'
+     the hostname.
+
+`\#'
+     the command number of this command.
+
+`\!'
+     the history number of this command.
+
+`\nnn'
+     the character corresponding to the octal number `nnn'.
+
+`\$'
+     if the effective uid is 0, `#', otherwise `$'.
+
+`\\'
+     a backslash.
+
+`\['
+     begin a sequence of non-printing characters.  This could be used to
+     embed a terminal control sequence into the prompt.
+
+`\]'
+     end a sequence of non-printing characters.
+
+\1f
+File: features.info,  Node: Job Control,  Next: Using History Interactively,  Prev: Bash Specific Features,  Up: Top
+
+Job Control
+***********
+
+   This chapter disusses what job control is, how it works, and how
+Bash allows you to access its facilities.
+
+* Menu:
+
+* Job Control Basics::         How job control works.
+* Job Control Builtins::       Bash builtin commands used to interact
+                               with job control.
+* Job Control Variables::      Variables Bash uses to customize job
+                               control.
+
+\1f
+File: features.info,  Node: Job Control Basics,  Next: Job Control Builtins,  Up: Job Control
+
+Job Control Basics
+==================
+
+   Job control refers to the ability to selectively stop (suspend) the
+execution of processes and continue (resume) their execution at a later
+point.  A user typically employs this facility via an interactive
+interface supplied jointly by the system's terminal driver and Bash.
+
+   The shell associates a JOB with each pipeline.  It keeps a table of
+currently executing jobs, which may be listed with the `jobs' command.
+When Bash starts a job asynchronously (in the background), it prints a
+line that looks like:
+     [1] 25647
+   indicating that this job is job number 1 and that the process ID of
+the last process in the pipeline associated with this job is 25647.
+All of the processes in a single pipeline are members of the same job.
+Bash uses the JOB abstraction as the basis for job control.
+
+   To facilitate the implementation of the user interface to job
+control, the system maintains the notion of a current terminal process
+group ID.  Members of this process group (processes whose process group
+ID is equal to the current terminal process group ID) receive
+keyboard-generated signals such as `SIGINT'.  These processes are said
+to be in the foreground.  Background processes are those whose process
+group ID differs from the terminal's; such processes are immune to
+keyboard-generated signals.  Only foreground processes are allowed to
+read from or write to the terminal.  Background processes which attempt
+to read from (write to) the terminal are sent a `SIGTTIN' (`SIGTTOU')
+signal by the terminal driver, which, unless caught, suspends the
+process.
+
+   If the operating system on which Bash is running supports job
+control, Bash allows you to use it.  Typing the SUSPEND character
+(typically `^Z', Control-Z) while a process is running causes that
+process to be stopped and returns you to Bash.  Typing the DELAYED
+SUSPEND character (typically `^Y', Control-Y) causes the process to be
+stopped when it attempts to read input from the terminal, and control to
+be returned to Bash.  You may then manipulate the state of this job,
+using the `bg' command to continue it in the background, the `fg'
+command to continue it in the foreground, or the `kill' command to kill
+it.  A `^Z' takes effect immediately, and has the additional side
+effect of causing pending output and typeahead to be discarded.
+
+   There are a number of ways to refer to a job in the shell.  The
+character `%' introduces a job name.  Job number `n' may be referred to
+as `%n'.  A job may also be referred to using a prefix of the name used
+to start it, or using a substring that appears in its command line.
+For example, `%ce' refers to a stopped `ce' job. Using `%?ce', on the
+other hand, refers to any job containing the string `ce' in its command
+line.  If the prefix or substring matches more than one job, Bash
+reports an error.  The symbols `%%' and `%+' refer to the shell's
+notion of the current job, which is the last job stopped while it was
+in the foreground.  The previous job may be referenced using `%-'.  In
+output pertaining to jobs (e.g., the output of the `jobs' command), the
+current job is always flagged with a `+', and the previous job with a
+`-'.
+
+   Simply naming a job can be used to bring it into the foreground:
+`%1' is a synonym for `fg %1' bringing job 1 from the background into
+the foreground.  Similarly, `%1 &' resumes job 1 in the background,
+equivalent to `bg %1'
+
+   The shell learns immediately whenever a job changes state.
+Normally, Bash waits until it is about to print a prompt before
+reporting changes in a job's status so as to not interrupt any other
+output.  If the the `-b' option to the `set' builtin is set, Bash
+reports such changes immediately (*note The Set Builtin::.).  This
+feature is also controlled by the variable `notify'.
+
+   If you attempt to exit bash while jobs are stopped, the shell prints
+a message warning you.  You may then use the `jobs' command to inspect
+their status.  If you do this, or try to exit again immediately, you
+are not warned again, and the stopped jobs are terminated.
+
+\1f
+File: features.info,  Node: Job Control Builtins,  Next: Job Control Variables,  Prev: Job Control Basics,  Up: Job Control
+
+Job Control Builtins
+====================
+
+`bg'
+          bg [JOBSPEC]
+     Place JOBSPEC into the background, as if it had been started with
+     `&'.  If JOBSPEC is not supplied, the current job is used.
+
+`fg'
+          fg [JOBSPEC]
+     Bring JOBSPEC into the foreground and make it the current job.  If
+     JOBSPEC is not supplied, the current job is used.
+
+`jobs'
+          jobs [-lpn] [JOBSPEC]
+          jobs -x COMMAND [JOBSPEC]
+
+     The first form lists the active jobs.  The `-l' option lists
+     process IDs in addition to the normal information; the `-p' option
+     lists only the process ID of the job's process group leader.  The
+     `-n' option displays only jobs that have changed status since last
+     notfied.  If JOBSPEC is given, output is restricted to information
+     about that job.  If JOBSPEC is not supplied, the status of all
+     jobs is listed.
+
+     If the `-x' option is supplied, `jobs' replaces any JOBSPEC found
+     in COMMAND or ARGUMENTS with the corresponding process group ID,
+     and executes COMMAND, passing it ARGUMENTs, returning its exit
+     status.
+
+`suspend'
+          suspend [-f]
+     Suspend the execution of this shell until it receives a `SIGCONT'
+     signal.  The `-f' option means to suspend even if the shell is a
+     login shell.
+
+   When job control is active, the `kill' and `wait' builtins also
+accept JOBSPEC arguments.
+
+\1f
+File: features.info,  Node: Job Control Variables,  Prev: Job Control Builtins,  Up: Job Control
+
+Job Control Variables
+=====================
+
+`auto_resume'
+     This variable controls how the shell interacts with the user and
+     job control.  If this variable exists then single word simple
+     commands without redirects are treated as candidates for resumption
+     of an existing job.  There is no ambiguity allowed; if you have
+     more than one job beginning with the string that you have typed,
+     then the most recently accessed job will be selected.  The name of
+     a stopped job, in this context, is the command line used to start
+     it.  If this variable is set to the value `exact', the string
+     supplied must match the name of a stopped job exactly; if set to
+     `substring', the string supplied needs to match a substring of the
+     name of a stopped job.  The `substring' value provides
+     functionality analogous to the `%?' job id (*note Job Control
+     Basics::.).  If set to any other value, the supplied string must
+     be a prefix of a stopped job's name; this provides functionality
+     analogous to the `%' job id.
+
+`notify'
+     Setting this variable to a value is equivalent to `set -b';
+     unsetting it is equivalent to `set +b' (*note The Set Builtin::.).
+
+\1f
+File: features.info,  Node: Using History Interactively,  Next: Command Line Editing,  Prev: Job Control,  Up: Top
+
+Using History Interactively
+***************************
+
+   This chapter describes how to use the GNU History Library
+interactively, from a user's standpoint.  It should be considered a
+user's guide.  For information on using the GNU History Library in your
+own programs, see the GNU Readline Library Manual.
+
+* Menu:
+
+* History Interaction::                What it feels like using History as a user.
+
+\1f
+File: features.info,  Node: History Interaction,  Up: Using History Interactively
+
+History Interaction
+===================
+
+   The History library provides a history expansion feature that is
+similar to the history expansion provided by `csh'.  The following text
+describes the syntax used to manipulate the history information.
+
+   History expansion takes place in two parts.  The first is to
+determine which line from the previous history should be used during
+substitution.  The second is to select portions of that line for
+inclusion into the current one.  The line selected from the previous
+history is called the "event", and the portions of that line that are
+acted upon are called "words".  The line is broken into words in the
+same fashion that Bash does, so that several English (or Unix) words
+surrounded by quotes are considered as one word.
+
+* Menu:
+
+* Event Designators::  How to specify which history line to use.
+* Word Designators::   Specifying which words are of interest.
+* Modifiers::          Modifying the results of substitution.
+
+\1f
+File: features.info,  Node: Event Designators,  Next: Word Designators,  Up: History Interaction
+
+Event Designators
+-----------------
+
+   An event designator is a reference to a command line entry in the
+history list.
+
+`!'
+     Start a history substitution, except when followed by a space, tab,
+     the end of the line, = or (.
+
+`!!'
+     Refer to the previous command.  This is a synonym for `!-1'.
+
+`!n'
+     Refer to command line N.
+
+`!-n'
+     Refer to the command N lines back.
+
+`!string'
+     Refer to the most recent command starting with STRING.
+
+`!?string'[`?']
+     Refer to the most recent command containing STRING.
+
+`!#'
+     The entire command line typed so far.
+
+`^string1^string2^'
+     Quick Substitution.  Repeat the last command, replacing STRING1
+     with STRING2.  Equivalent to `!!:s/string1/string2/'.
+
+\1f
+File: features.info,  Node: Word Designators,  Next: Modifiers,  Prev: Event Designators,  Up: History Interaction
+
+Word Designators
+----------------
+
+   A : separates the event specification from the word designator.  It
+can be omitted if the word designator begins with a ^, $, * or %.
+Words are numbered from the beginning of the line, with the first word
+being denoted by a 0 (zero).
+
+`0 (zero)'
+     The `0'th word.  For many applications, this is the command word.
+
+`n'
+     The Nth word.
+
+`^'
+     The first argument;  that is, word 1.
+
+`$'
+     The last argument.
+
+`%'
+     The word matched by the most recent `?string?' search.
+
+`x-y'
+     A range of words; `-Y' abbreviates `0-Y'.
+
+`*'
+     All of the words, except the `0'th.  This is a synonym for `1-$'.
+     It is not an error to use * if there is just one word in the event;
+     the empty string is returned in that case.
+
+`x*'
+     Abbreviates `x-$'
+
+`x-'
+     Abbreviates `x-$' like `x*', but omits the last word.
+
+\1f
+File: features.info,  Node: Modifiers,  Prev: Word Designators,  Up: History Interaction
+
+Modifiers
+---------
+
+   After the optional word designator, you can add a sequence of one or
+more of the following modifiers, each preceded by a :.
+
+`h'
+     Remove a trailing pathname component, leaving only the head.
+
+`r'
+     Remove a trailing suffix of the form `.'SUFFIX, leaving the
+     basename.
+
+`e'
+     Remove all but the trailing suffix.
+
+`t'
+     Remove all leading  pathname  components, leaving the tail.
+
+`p'
+     Print the new command but do not execute it.
+
+`q'
+     Quote the substituted words, escaping further substitutions.
+
+`x'
+     Quote the substituted words as with `q', but break into words at
+     spaces, tabs, and newlines.
+
+`s/old/new/'
+     Substitute NEW for the first occurrence of OLD in the event line.
+     Any delimiter may be used in place of /.  The delimiter may be
+     quoted in OLD and NEW with a single backslash.  If & appears in
+     NEW, it is replaced by OLD.  A single backslash will quote the &.
+     The final delimiter is optional if it is the last character on the
+     input line.
+
+`&'
+     Repeat the previous substitution.
+
+`g'
+     Cause changes to be applied over the entire event line.  Used in
+     conjunction with `s', as in `gs/old/new/', or with `&'.
+
+\1f
+File: features.info,  Node: Command Line Editing,  Next: Variable Index,  Prev: Using History Interactively,  Up: Top
+
+Command Line Editing
+********************
+
+   This chapter describes the basic features of the GNU command line
+editing interface.
+
+* Menu:
+
+* Introduction and Notation::  Notation used in this text.
+* Readline Interaction::       The minimum set of commands for editing a line.
+* Readline Init File::         Customizing Readline from a user's view.
+* Bindable Readline Commands:: A description of most of the Readline commands
+                               available for binding
+* Readline vi Mode::           A short description of how to make Readline
+                               behave like the vi editor.
+
+\1f
+File: features.info,  Node: Introduction and Notation,  Next: Readline Interaction,  Up: Command Line Editing
+
+Introduction to Line Editing
+============================
+
+   The following paragraphs describe the notation used to represent
+keystrokes.
+
+   The text C-k is read as `Control-K' and describes the character
+produced when the Control key is depressed and the k key is struck.
+
+   The text M-k is read as `Meta-K' and describes the character
+produced when the meta key (if you have one) is depressed, and the k
+key is struck.  If you do not have a meta key, the identical keystroke
+can be generated by typing ESC first, and then typing k.  Either
+process is known as "metafying" the k key.
+
+   The text M-C-k is read as `Meta-Control-k' and describes the
+character produced by "metafying" C-k.
+
+   In addition, several keys have their own names.  Specifically, DEL,
+ESC, LFD, SPC, RET, and TAB all stand for themselves when seen in this
+text, or in an init file (*note Readline Init File::., for more info).
+
+\1f
+File: features.info,  Node: Readline Interaction,  Next: Readline Init File,  Prev: Introduction and Notation,  Up: Command Line Editing
+
+Readline Interaction
+====================
+
+   Often during an interactive session you type in a long line of text,
+only to notice that the first word on the line is misspelled.  The
+Readline library gives you a set of commands for manipulating the text
+as you type it in, allowing you to just fix your typo, and not forcing
+you to retype the majority of the line.  Using these editing commands,
+you move the cursor to the place that needs correction, and delete or
+insert the text of the corrections.  Then, when you are satisfied with
+the line, you simply press RETURN.  You do not have to be at the end of
+the line to press RETURN; the entire line is accepted regardless of the
+location of the cursor within the line.
+
+* Menu:
+
+* Readline Bare Essentials::   The least you need to know about Readline.
+* Readline Movement Commands:: Moving about the input line.
+* Readline Killing Commands::  How to delete text, and how to get it back!
+* Readline Arguments::         Giving numeric arguments to commands.
+
+\1f
+File: features.info,  Node: Readline Bare Essentials,  Next: Readline Movement Commands,  Up: Readline Interaction
+
+Readline Bare Essentials
+------------------------
+
+   In order to enter characters into the line, simply type them.  The
+typed character appears where the cursor was, and then the cursor moves
+one space to the right.  If you mistype a character, you can use your
+erase character to back up and delete the mistyped character.
+
+   Sometimes you may miss typing a character that you wanted to type,
+and not notice your error until you have typed several other
+characters.  In that case, you can type C-b to move the cursor to the
+left, and then correct your mistake.  Afterwards, you can move the
+cursor to the right with C-f.
+
+   When you add text in the middle of a line, you will notice that
+characters to the right of the cursor are `pushed over' to make room
+for the text that you have inserted.  Likewise, when you delete text
+behind the cursor, characters to the right of the cursor are `pulled
+back' to fill in the blank space created by the removal of the text.  A
+list of the basic bare essentials for editing the text of an input line
+follows.
+
+C-b
+     Move back one character.
+
+C-f
+     Move forward one character.
+
+DEL
+     Delete the character to the left of the cursor.
+
+C-d
+     Delete the character underneath the cursor.
+
+Printing characters
+     Insert the character into the line at the cursor.
+
+C-_
+     Undo the last thing that you did.  You can undo all the way back
+     to an empty line.
+
+\1f
+File: features.info,  Node: Readline Movement Commands,  Next: Readline Killing Commands,  Prev: Readline Bare Essentials,  Up: Readline Interaction
+
+Readline Movement Commands
+--------------------------
+
+   The above table describes the most basic possible keystrokes that
+you need in order to do editing of the input line.  For your
+convenience, many other commands have been added in addition to C-b,
+C-f, C-d, and DEL.  Here are some commands for moving more rapidly
+about the line.
+
+C-a
+     Move to the start of the line.
+
+C-e
+     Move to the end of the line.
+
+M-f
+     Move forward a word.
+
+M-b
+     Move backward a word.
+
+C-l
+     Clear the screen, reprinting the current line at the top.
+
+   Notice how C-f moves forward a character, while M-f moves forward a
+word.  It is a loose convention that control keystrokes operate on
+characters while meta keystrokes operate on words.
+
+\1f
+File: features.info,  Node: Readline Killing Commands,  Next: Readline Arguments,  Prev: Readline Movement Commands,  Up: Readline Interaction
+
+Readline Killing Commands
+-------------------------
+
+   "Killing" text means to delete the text from the line, but to save
+it away for later use, usually by "yanking" (re-inserting) it back into
+the line.  If the description for a command says that it `kills' text,
+then you can be sure that you can get the text back in a different (or
+the same) place later.
+
+   When you use a kill command, the text is saved in a "kill-ring".
+Any number of consecutive kills save all of the killed text together, so
+that when you yank it back, you get it all.  The kill ring is not line
+specific; the text that you killed on a previously typed line is
+available to be yanked back later, when you are typing another line.
+
+   Here is the list of commands for killing text.
+
+C-k
+     Kill the text from the current cursor position to the end of the
+     line.
+
+M-d
+     Kill from the cursor to the end of the current word, or if between
+     words, to the end of the next word.
+
+M-DEL
+     Kill from the cursor the start of the previous word, or if between
+     words, to the start of the previous word.
+
+C-w
+     Kill from the cursor to the previous whitespace.  This is
+     different than M-DEL because the word boundaries differ.
+
+   And, here is how to "yank" the text back into the line.  Yanking
+means to copy the most-recently-killed text from the kill buffer.
+
+C-y
+     Yank the most recently killed text back into the buffer at the
+     cursor.
+
+M-y
+     Rotate the kill-ring, and yank the new top.  You can only do this
+     if the prior command is C-y or M-y.
+
+\1f
+File: features.info,  Node: Readline Arguments,  Prev: Readline Killing Commands,  Up: Readline Interaction
+
+Readline Arguments
+------------------
+
+   You can pass numeric arguments to Readline commands.  Sometimes the
+argument acts as a repeat count, other times it is the sign of the
+argument that is significant.  If you pass a negative argument to a
+command which normally acts in a forward direction, that command will
+act in a backward direction.  For example, to kill text back to the
+start of the line, you might type M- C-k.
+
+   The general way to pass numeric arguments to a command is to type
+meta digits before the command.  If the first `digit' you type is a
+minus sign (-), then the sign of the argument will be negative.  Once
+you have typed one meta digit to get the argument started, you can type
+the remainder of the digits, and then the command.  For example, to give
+the C-d command an argument of 10, you could type M-1 0 C-d.
+
+\1f
+File: features.info,  Node: Readline Init File,  Next: Bindable Readline Commands,  Prev: Readline Interaction,  Up: Command Line Editing
+
+Readline Init File
+==================
+
+   Although the Readline library comes with a set of Emacs-like
+keybindings installed by default, it is possible that you would like to
+use a different set of keybindings.  You can customize programs that
+use Readline by putting commands in an "init" file in your home
+directory.  The name of this file is taken from the value of the shell
+variable `INPUTRC'.  If that variable is unset, the default is
+`~/.inputrc'.
+
+   When a program which uses the Readline library starts up, the init
+file is read, and the key bindings are set.
+
+   In addition, the `C-x C-r' command re-reads this init file, thus
+incorporating any changes that you might have made to it.
+
+* Menu:
+
+* Readline Init Syntax::       Syntax for the commands in the inputrc file.
+* Conditional Init Constructs::        Conditional key bindings in the inputrc file.
+
+\1f
+File: features.info,  Node: Readline Init Syntax,  Next: Conditional Init Constructs,  Up: Readline Init File
+
+Readline Init Syntax
+--------------------
+
+   There are only a few basic constructs allowed in the Readline init
+file.  Blank lines are ignored.  Lines beginning with a # are comments.
+Lines beginning with a $ indicate conditional constructs (*note
+Conditional Init Constructs::.).  Other lines denote variable settings
+and key bindings.
+
+Variable Settings
+     You can change the state of a few variables in Readline by using
+     the `set' command within the init file.  Here is how you would
+     specify that you wish to use `vi' line editing commands:
+
+          set editing-mode vi
+
+     Right now, there are only a few variables which can be set; so
+     few, in fact, that we just list them here:
+
+    `editing-mode'
+          The `editing-mode' variable controls which editing mode you
+          are using.  By default, Readline starts up in Emacs editing
+          mode, where the keystrokes are most similar to Emacs.  This
+          variable can be set to either `emacs' or `vi'.
+
+    `horizontal-scroll-mode'
+          This variable can be set to either `On' or `Off'.  Setting it
+          to `On' means that the text of the lines that you edit will
+          scroll horizontally on a single screen line when they are
+          longer than the width of the screen, instead of wrapping onto
+          a new screen line.  By default, this variable is set to `Off'.
+
+    `mark-modified-lines'
+          This variable, when set to `On', says to display an asterisk
+          (`*') at the start of history lines which have been modified.
+          This variable is `off' by default.
+
+    `bell-style'
+          Controls what happens when Readline wants to ring the
+          terminal bell.  If set to `none', Readline never rings the
+          bell.  If set to `visible', Readline uses a visible bell if
+          one is available.  If set to `audible' (the default),
+          Readline attempts to ring the terminal's bell.
+
+    `comment-begin'
+          The string to insert at the beginning of the line when the
+          `vi-comment' command is executed.  The default value is `"#"'.
+
+    `meta-flag'
+          If set to `on', Readline will enable eight-bit input (it will
+          not strip the eighth bit from the characters it reads),
+          regardless of what the terminal claims it can support.  The
+          default value is `off'.
+
+    `convert-meta'
+          If set to `on', Readline will convert characters with the
+          eigth bit set to an ASCII key sequence by stripping the eigth
+          bit and prepending an ESC character, converting them to a
+          meta-prefixed key sequence.  The default value is `on'.
+
+    `output-meta'
+          If set to `on', Readline will display characters with the
+          eighth bit set directly rather than as a meta-prefixed escape
+          sequence.  The default is `off'.
+
+    `completion-query-items'
+          The number of possible completions that determines when the
+          user is asked whether he wants to see the list of
+          possibilities.  If the number of possible completions is
+          greater than this value, Readline will ask the user whether
+          or not he wishes to view them; otherwise, they are simply
+          listed.  The default limit is `100'.
+
+    `keymap'
+          Sets Readline's idea of the current keymap for key binding
+          commands.  Acceptable `keymap' names are `emacs',
+          `emacs-standard', `emacs-meta', `emacs-ctlx', `vi', `vi-move',
+          `vi-command', and `vi-insert'.  `vi' is equivalent to
+          `vi-command'; `emacs' is equivalent to `emacs-standard'.  The
+          default value is `emacs'.  The value of the `editing-mode'
+          variable also affects the default keymap.
+
+    `show-all-if-ambiguous'
+          This alters the default behavior of the completion functions.
+          If set to `on', words which have more than one possible
+          completion cause the matches to be listed immediately instead
+          of ringing the bell.  The default value is `off'.
+
+    `expand-tilde'
+          If set to `on', tilde expansion is performed when Readline
+          attempts word completion.  The default is `off'.
+
+Key Bindings
+     The syntax for controlling key bindings in the init file is
+     simple.  First you have to know the name of the command that you
+     want to change.  The following pages contain tables of the command
+     name, the default keybinding, and a short description of what the
+     command does.
+
+     Once you know the name of the command, simply place the name of
+     the key you wish to bind the command to, a colon, and then the
+     name of the command on a line in the init file.  The name of the
+     key can be expressed in different ways, depending on which is most
+     comfortable for you.
+
+    KEYNAME: FUNCTION-NAME or MACRO
+          KEYNAME is the name of a key spelled out in English.  For
+          example:
+               Control-u: universal-argument
+               Meta-Rubout: backward-kill-word
+               Control-o: ">&output"
+
+          In the above example, `C-u' is bound to the function
+          `universal-argument', and `C-o' is bound to run the macro
+          expressed on the right hand side (that is, to insert the text
+          `>&output' into the line).
+
+    "KEYSEQ": FUNCTION-NAME or MACRO
+          KEYSEQ differs from KEYNAME above in that strings denoting an
+          entire key sequence can be specified, by placing the key
+          sequence in double quotes.  Some GNU Emacs style key escapes
+          can be used, as in the following example, but the special
+          character names are not recognized.
+
+               "\C-u": universal-argument
+               "\C-x\C-r": re-read-init-file
+               "\e[11~": "Function Key 1"
+
+          In the above example, `C-u' is bound to the function
+          `universal-argument' (just as it was in the first example),
+          `C-x C-r' is bound to the function `re-read-init-file', and
+          `ESC [ 1 1 ~' is bound to insert the text `Function Key 1'.
+          The following escape sequences are available when specifying
+          key sequences:
+
+         ``\C-''
+               control prefix
+
+         ``\M-''
+               meta prefix
+
+         ``\e''
+               an escape character
+
+         ``\\''
+               backslash
+
+         ``\"''
+               "
+
+         ``\'''
+               '
+
+          When entering the text of a macro, single or double quotes
+          should be used to indicate a macro definition.  Unquoted text
+          is assumed to be a function name.  Backslash will quote any
+          character in the macro text, including " and '.  For example,
+          the following binding will make `C-x \' insert a single \
+          into the line:
+               "\C-x\\": "\\"
+
+\1f
+File: features.info,  Node: Conditional Init Constructs,  Prev: Readline Init Syntax,  Up: Readline Init File
+
+Conditional Init Constructs
+---------------------------
+
+   Readline implements a facility similar in spirit to the conditional
+compilation features of the C preprocessor which allows key bindings
+and variable settings to be performed as the result of tests.  There
+are three parser directives used.
+
+`$if'
+     The `$if' construct allows bindings to be made based on the
+     editing mode, the terminal being used, or the application using
+     Readline.  The text of the test extends to the end of the line; no
+     characters are required to isolate it.
+
+    `mode'
+          The `mode=' form of the `$if' directive is used to test
+          whether Readline is in `emacs' or `vi' mode.  This may be
+          used in conjunction with the `set keymap' command, for
+          instance, to set bindings in the `emacs-standard' and
+          `emacs-ctlx' keymaps only if Readline is starting out in
+          `emacs' mode.
+
+    `term'
+          The `term=' form may be used to include terminal-specific key
+          bindings, perhaps to bind the key sequences output by the
+          terminal's function keys.  The word on the right side of the
+          `=' is tested against the full name of the terminal and the
+          portion of the terminal name before the first `-'.  This
+          allows SUN to match both SUN and SUN-CMD, for instance.
+
+    `application'
+          The APPLICATION construct is used to include
+          application-specific settings.  Each program using the
+          Readline library sets the APPLICATION NAME, and you can test
+          for it.  This could be used to bind key sequences to
+          functions useful for a specific program.  For instance, the
+          following command adds a key sequence that quotes the current
+          or previous word in Bash:
+               $if bash
+               # Quote the current or previous word
+               "\C-xq": "\eb\"\ef\""
+               $endif
+
+`$endif'
+     This command, as you saw in the previous example, terminates an
+     `$if' command.
+
+`$else'
+     Commands in this branch of the `$if' directive are executed if the
+     test fails.
+
+\1f
+File: features.info,  Node: Bindable Readline Commands,  Next: Readline vi Mode,  Prev: Readline Init File,  Up: Command Line Editing
+
+Bindable Readline Commands
+==========================
+
+* Menu:
+
+* Commands For Moving::                Moving about the line.
+* Commands For History::       Getting at previous lines.
+* Commands For Text::          Commands for changing text.
+* Commands For Killing::       Commands for killing and yanking.
+* Numeric Arguments::          Specifying numeric arguments, repeat counts.
+* Commands For Completion::    Getting Readline to do the typing for you.
+* Keyboard Macros::            Saving and re-executing typed characters
+* Miscellaneous Commands::     Other miscellaneous commands.
+
+\1f
+File: features.info,  Node: Commands For Moving,  Next: Commands For History,  Up: Bindable Readline Commands
+
+Commands For Moving
+-------------------
+
+`beginning-of-line (C-a)'
+     Move to the start of the current line.
+
+`end-of-line (C-e)'
+     Move to the end of the line.
+
+`forward-char (C-f)'
+     Move forward a character.
+
+`backward-char (C-b)'
+     Move back a character.
+
+`forward-word (M-f)'
+     Move forward to the end of the next word.  Words are composed of
+     letters and digits.
+
+`backward-word (M-b)'
+     Move back to the start of this, or the previous, word.  Words are
+     composed of letters and digits.
+
+`clear-screen (C-l)'
+     Clear the screen and redraw the current line, leaving the current
+     line at the top of the screen.
+
+`redraw-current-line ()'
+     Refresh the current line.  By default, this is unbound.
+
+\1f
+File: features.info,  Node: Commands For History,  Next: Commands For Text,  Prev: Commands For Moving,  Up: Bindable Readline Commands
+
+Commands For Manipulating The History
+-------------------------------------
+
+`accept-line (Newline, Return)'
+     Accept the line regardless of where the cursor is.  If this line is
+     non-empty, add it to the history list according to the setting of
+     the `HISTCONTROL' variable.  If this line was a history line, then
+     restore the history line to its original state.
+
+`previous-history (C-p)'
+     Move `up' through the history list.
+
+`next-history (C-n)'
+     Move `down' through the history list.
+
+`beginning-of-history (M-<)'
+     Move to the first line in the history.
+
+`end-of-history (M->)'
+     Move to the end of the input history, i.e., the line you are
+     entering.
+
+`reverse-search-history (C-r)'
+     Search backward starting at the current line and moving `up'
+     through the history as necessary.  This is an incremental search.
+
+`forward-search-history (C-s)'
+     Search forward starting at the current line and moving `down'
+     through the the history as necessary.  This is an incremental
+     search.
+
+`non-incremental-reverse-search-history (M-p)'
+     Search backward starting at the current line and moving `up'
+     through the history as necessary using a non-incremental search
+     for a string supplied by the user.
+
+`non-incremental-forward-search-history (M-n)'
+     Search forward starting at the current line and moving `down'
+     through the the history as necessary using a non-incremental search
+     for a string supplied by the user.
+
+`history-search-forward ()'
+     Search forward through the history for the string of characters
+     between the start of the current line and the current point.  This
+     is a non-incremental search.  By default, this command is unbound.
+
+`history-search-backward ()'
+     Search backward through the history for the string of characters
+     between the start of the current line and the current point.  This
+     is a non-incremental search.  By default, this command is unbound.
+
+`yank-nth-arg (M-C-y)'
+     Insert the first argument to the previous command (usually the
+     second word on the previous line).  With an argument N, insert the
+     Nth word from the previous command (the words in the previous
+     command begin with word 0).  A negative argument inserts the Nth
+     word from the end of the previous command.
+
+`yank-last-arg (M-., M-_)'
+     Insert last argument to the previous command (the last word on the
+     previous line).  With an argument, behave exactly like
+     `yank-nth-arg'.
+
+\1f
+File: features.info,  Node: Commands For Text,  Next: Commands For Killing,  Prev: Commands For History,  Up: Bindable Readline Commands
+
+Commands For Changing Text
+--------------------------
+
+`delete-char (C-d)'
+     Delete the character under the cursor.  If the cursor is at the
+     beginning of the line, there are no characters in the line, and
+     the last character typed was not C-d, then return EOF.
+
+`backward-delete-char (Rubout)'
+     Delete the character behind the cursor.  A numeric arg says to kill
+     the characters instead of deleting them.
+
+`quoted-insert (C-q, C-v)'
+     Add the next character that you type to the line verbatim.  This is
+     how to insert key sequences like C-q, for example.
+
+`tab-insert (M-TAB)'
+     Insert a tab character.
+
+`self-insert (a, b, A, 1, !, ...)'
+     Insert yourself.
+
+`transpose-chars (C-t)'
+     Drag the character before the cursor forward over the character at
+     the cursor, moving the cursor forward as well.  If the insertion
+     point is at the end of the line, then this transposes the last two
+     characters of the line.  Negative argumentss don't work.
+
+`transpose-words (M-t)'
+     Drag the word behind the cursor past the word in front of the
+     cursor moving the cursor over that word as well.
+
+`upcase-word (M-u)'
+     Uppercase the current (or following) word.  With a negative
+     argument, do the previous word, but do not move the cursor.
+
+`downcase-word (M-l)'
+     Lowercase the current (or following) word.  With a negative
+     argument, do the previous word, but do not move the cursor.
+
+`capitalize-word (M-c)'
+     Capitalize the current (or following) word.  With a negative
+     argument, do the previous word, but do not move the cursor.
+
+\1f
+File: features.info,  Node: Commands For Killing,  Next: Numeric Arguments,  Prev: Commands For Text,  Up: Bindable Readline Commands
+
+Killing And Yanking
+-------------------
+
+`kill-line (C-k)'
+     Kill the text from the current cursor position to the end of the
+     line.
+
+`backward-kill-line (C-x Rubout)'
+     Kill backward to the beginning of the line.
+
+`unix-line-discard (C-u)'
+     Kill backward from the cursor to the beginning of the current line.
+     Save the killed text on the kill-ring.
+
+`kill-whole-line ()'
+     Kill all characters on the current line, no matter where the
+     cursor is.  By default, this is unbound.
+
+`kill-word (M-d)'
+     Kill from the cursor to the end of the current word, or if between
+     words, to the end of the next word.  Word boundaries are the same
+     as `forward-word'.
+
+`backward-kill-word (M-DEL)'
+     Kill the word behind the cursor.  Word boundaries are the same as
+     `backward-word'.
+
+`unix-word-rubout (C-w)'
+     Kill the word behind the cursor, using white space as a word
+     boundary.  The killed text is saved on the kill-ring.
+
+`delete-horizontal-space ()'
+     Delete all spaces and tabs around point.  By default, this is
+     unbound.
+
+`yank (C-y)'
+     Yank the top of the kill ring into the buffer at the current
+     cursor position.
+
+`yank-pop (M-y)'
+     Rotate the kill-ring, and yank the new top.  You can only do this
+     if the prior command is yank or yank-pop.
+
+\1f
+File: features.info,  Node: Numeric Arguments,  Next: Commands For Completion,  Prev: Commands For Killing,  Up: Bindable Readline Commands
+
+Specifying Numeric Arguments
+----------------------------
+
+`digit-argument (M-0, M-1, ... M--)'
+     Add this digit to the argument already accumulating, or start a new
+     argument.  M- starts a negative argument.
+
+`universal-argument ()'
+     Each time this is executed, the argument count is multiplied by
+     four.  The argument count is initially one, so executing this
+     function the first time makes the argument count four.  By
+     default, this is not bound to a key.
+
+\1f
+File: features.info,  Node: Commands For Completion,  Next: Keyboard Macros,  Prev: Numeric Arguments,  Up: Bindable Readline Commands
+
+Letting Readline Type For You
+-----------------------------
+
+`complete (TAB)'
+     Attempt to do completion on the text before the cursor.  This is
+     application-specific.  Generally, if you are typing a filename
+     argument, you can do filename completion; if you are typing a
+     command, you can do command completion, if you are typing in a
+     symbol to GDB, you can do symbol name completion, if you are
+     typing in a variable to Bash, you can do variable name completion,
+     and so on.  See the Bash manual page for a complete list of
+     available completion functions.
+
+`possible-completions (M-?)'
+     List the possible completions of the text before the cursor.
+
+`insert-completions ()'
+     Insert all completions of the text before point that would have
+     been generated by `possible-completions'.  By default, this is not
+     bound to a key.
+
+\1f
+File: features.info,  Node: Keyboard Macros,  Next: Miscellaneous Commands,  Prev: Commands For Completion,  Up: Bindable Readline Commands
+
+Keyboard Macros
+---------------
+
+`start-kbd-macro (C-x ()'
+     Begin saving the characters typed into the current keyboard macro.
+
+`end-kbd-macro (C-x ))'
+     Stop saving the characters typed into the current keyboard macro
+     and save the definition.
+
+`call-last-kbd-macro (C-x e)'
+     Re-execute the last keyboard macro defined, by making the
+     characters in the macro appear as if typed at the keyboard.
+
+\1f
+File: features.info,  Node: Miscellaneous Commands,  Prev: Keyboard Macros,  Up: Bindable Readline Commands
+
+Some Miscellaneous Commands
+---------------------------
+
+`re-read-init-file (C-x C-r)'
+     Read in the contents of your init file, and incorporate any
+     bindings or variable assignments found there.
+
+`abort (C-g)'
+     Abort the current editing command and ring the terminal's bell
+     (subject to the setting of `bell-style').
+
+`do-uppercase-version (M-a, M-b, ...)'
+     Run the command that is bound to the corresoponding uppercase
+     character.
+
+`prefix-meta (ESC)'
+     Make the next character that you type be metafied.  This is for
+     people without a meta key.  Typing `ESC f' is equivalent to typing
+     `M-f'.
+
+`undo (C-_, C-x C-u)'
+     Incremental undo, separately remembered for each line.
+
+`revert-line (M-r)'
+     Undo all changes made to this line.  This is like typing the `undo'
+     command enough times to get back to the beginning.
+
+`tilde-expand (M-~)'
+     Perform tilde expansion on the current word.
+
+`dump-functions ()'
+     Print all of the functions and their key bindings to the readline
+     output stream.  If a numeric argument is supplied, the output is
+     formatted in such a way that it can be made part of an INPUTRC
+     file.
+
+`display-shell-version (C-x C-v)'
+     Display version information about the current instance of Bash.
+
+`shell-expand-line (M-C-e)'
+     Expand the line the way the shell does when it reads it.  This
+     performs alias and history expansion as well as all of the shell
+     word expansions.
+
+`history-expand-line (M-^)'
+     Perform history expansion on the current line.
+
+`insert-last-argument (M-., M-_)'
+     A synonym for `yank-last-arg'.
+
+`operate-and-get-next (C-o)'
+     Accept the current line for execution and fetch the next line
+     relative to the current line from the history for editing.  Any
+     argument is ignored.
+
+`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.
+
+\1f
+File: features.info,  Node: Readline vi Mode,  Prev: Bindable Readline Commands,  Up: Command Line Editing
+
+Readline vi Mode
+================
+
+   While the Readline library does not have a full set of `vi' editing
+functions, it does contain enough to allow simple editing of the line.
+The Readline `vi' mode behaves as specified in the Posix 1003.2
+standard.
+
+   In order to switch interactively between `Emacs' and `Vi' editing
+modes, use the `set -o emacs' and `set -o vi' commands (*note The Set
+Builtin::.).  The Readline default is `emacs' mode.
+
+   When you enter a line in `vi' mode, you are already placed in
+`insertion' mode, as if you had typed an `i'.  Pressing ESC switches
+you into `command' mode, where you can edit the text of the line with
+the standard `vi' movement keys, move to previous history lines with
+`k', and following lines with `j', and so forth.
+
+\1f
+File: features.info,  Node: Variable Index,  Next: Concept Index,  Prev: Command Line Editing,  Up: Top
+
+Variable Index
+**************
+
+* Menu:
+
+* auto_resume:                          Job Control Variables.
+* BASH_VERSION:                         Bash Variables.
+* bell-style:                           Readline Init Syntax.
+* cdable_vars:                          C Shell Variables.
+* CDPATH:                               Bourne Shell Variables.
+* comment-begin:                        Readline Init Syntax.
+* completion-query-items:               Readline Init Syntax.
+* convert-meta:                         Readline Init Syntax.
+* editing-mode:                         Readline Init Syntax.
+* EUID:                                 Bash Variables.
+* expand-tilde:                         Readline Init Syntax.
+* FIGNORE:                              Bash Variables.
+* histchars:                            Bash Variables.
+* HISTCMD:                              Bash Variables.
+* HISTCONTROL:                          Bash Variables.
+* HISTFILE:                             Bash Variables.
+* history_control:                      Bash Variables.
+* HISTSIZE:                             Bash Variables.
+* HOME:                                 Bourne Shell Variables.
+* horizontal-scroll-mode:               Readline Init Syntax.
+* HOSTFILE:                             Bash Variables.
+* hostname_completion_file:             Bash Variables.
+* HOSTTYPE:                             Bash Variables.
+* IFS:                                  Bourne Shell Variables.
+* IGNOREEOF:                            C Shell Variables.
+* IGNOREEOF:                            Bash Variables.
+* INPUTRC:                              Bash Variables.
+* keymap:                               Readline Init Syntax.
+* MAILCHECK:                            Bash Variables.
+* MAILPATH:                             Bourne Shell Variables.
+* mark-modified-lines:                  Readline Init Syntax.
+* meta-flag:                            Readline Init Syntax.
+* nolinks:                              Bash Variables.
+* notify:                               Job Control Variables.
+* no_exit_on_failed_exec:               Bash Variables.
+* OLDPWD:                               Korn Shell Variables.
+* OPTARG:                               Bourne Shell Variables.
+* OPTIND:                               Bourne Shell Variables.
+* OSTYPE:                               Bash Variables.
+* output-meta:                          Readline Init Syntax.
+* PATH:                                 Bourne Shell Variables.
+* PROMPT_COMMAND:                       Bash Variables.
+* PS1:                                  Bourne Shell Variables.
+* PS2:                                  Bourne Shell Variables.
+* PS3:                                  Korn Shell Variables.
+* PS4:                                  Korn Shell Variables.
+* PWD:                                  Korn Shell Variables.
+* RANDOM:                               Korn Shell Variables.
+* REPLY:                                Korn Shell Variables.
+* SECONDS:                              Korn Shell Variables.
+* show-all-if-ambiguous:                Readline Init Syntax.
+* TMOUT:                                Korn Shell Variables.
+* UID:                                  Bash Variables.
+
+\1f
+File: features.info,  Node: Concept Index,  Prev: Variable Index,  Up: Top
+
+Concept Index
+*************
+
+* Menu:
+
+* $else:                                Conditional Init Constructs.
+* $endif:                               Conditional Init Constructs.
+* $if:                                  Conditional Init Constructs.
+* .:                                    Bourne Shell Builtins.
+* ::                                    Bourne Shell Builtins.
+* abort (C-g):                          Miscellaneous Commands.
+* accept-line (Newline, Return):        Commands For History.
+* alias:                                Alias Builtins.
+* backward-char (C-b):                  Commands For Moving.
+* backward-delete-char (Rubout):        Commands For Text.
+* backward-kill-line (C-x Rubout):      Commands For Killing.
+* backward-kill-word (M-DEL):           Commands For Killing.
+* backward-word (M-b):                  Commands For Moving.
+* beginning-of-history (M-<):           Commands For History.
+* beginning-of-line (C-a):              Commands For Moving.
+* bg:                                   Job Control Builtins.
+* bind:                                 Bash Builtins.
+* break:                                Bourne Shell Builtins.
+* builtin:                              Bash Builtins.
+* call-last-kbd-macro (C-x e):          Keyboard Macros.
+* capitalize-word (M-c):                Commands For Text.
+* case:                                 Conditional Constructs.
+* cd:                                   Bourne Shell Builtins.
+* clear-screen (C-l):                   Commands For Moving.
+* command:                              Bash Builtins.
+* complete (TAB):                       Commands For Completion.
+* continue:                             Bourne Shell Builtins.
+* declare:                              Bash Builtins.
+* delete-char (C-d):                    Commands For Text.
+* delete-horizontal-space ():           Commands For Killing.
+* digit-argument (M-0, M-1, ... M-):    Numeric Arguments.
+* dirs:                                 C Shell Builtins.
+* do-uppercase-version (M-a, M-b, ...): Miscellaneous Commands.
+* downcase-word (M-l):                  Commands For Text.
+* dump-functions ():                    Miscellaneous Commands.
+* echo:                                 Bourne Shell Builtins.
+* enable:                               Bash Builtins.
+* end-kbd-macro (C-x )):                Keyboard Macros.
+* end-of-history (M->):                 Commands For History.
+* end-of-line (C-e):                    Commands For Moving.
+* eval:                                 Bourne Shell Builtins.
+* event designators:                    Event Designators.
+* exec:                                 Bourne Shell Builtins.
+* exit:                                 Bourne Shell Builtins.
+* expansion:                            History Interaction.
+* export:                               Bourne Shell Builtins.
+* fc:                                   Korn Shell Builtins.
+* fg:                                   Job Control Builtins.
+* for:                                  Looping Constructs.
+* forward-char (C-f):                   Commands For Moving.
+* forward-search-history (C-s):         Commands For History.
+* forward-word (M-f):                   Commands For Moving.
+* getopts:                              Bourne Shell Builtins.
+* hash:                                 Bourne Shell Builtins.
+* help:                                 Bash Builtins.
+* history:                              C Shell Builtins.
+* history events:                       Event Designators.
+* History, how to use:                  Job Control Variables.
+* history-search-backward ():           Commands For History.
+* history-search-forward ():            Commands For History.
+* if:                                   Conditional Constructs.
+* insert-completions ():                Commands For Completion.
+* interaction, readline:                Readline Interaction.
+* jobs:                                 Job Control Builtins.
+* kill:                                 Bourne Shell Builtins.
+* Kill ring:                            Readline Killing Commands.
+* kill-line (C-k):                      Commands For Killing.
+* kill-whole-line ():                   Commands For Killing.
+* kill-word (M-d):                      Commands For Killing.
+* Killing text:                         Readline Killing Commands.
+* let:                                  Korn Shell Builtins.
+* let:                                  Arithmetic Builtins.
+* local:                                Bash Builtins.
+* logout:                               C Shell Builtins.
+* 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.
+* popd:                                 C Shell Builtins.
+* possible-completions (M-?):           Commands For Completion.
+* prefix-meta (ESC):                    Miscellaneous Commands.
+* previous-history (C-p):               Commands For History.
+* pushd:                                C Shell Builtins.
+* pwd:                                  Bourne Shell Builtins.
+* quoted-insert (C-q, C-v):             Commands For Text.
+* re-read-init-file (C-x C-r):          Miscellaneous Commands.
+* read:                                 Bourne Shell Builtins.
+* Readline, how to use:                 Modifiers.
+* readonly:                             Bourne Shell Builtins.
+* redraw-current-line ():               Commands For Moving.
+* return:                               Bourne Shell Builtins.
+* reverse-search-history (C-r):         Commands For History.
+* revert-line (M-r):                    Miscellaneous Commands.
+* self-insert (a, b, A, 1, !, ...):     Commands For Text.
+* set:                                  The Set Builtin.
+* shift:                                Bourne Shell Builtins.
+* source:                               C Shell Builtins.
+* start-kbd-macro (C-x ():              Keyboard Macros.
+* suspend:                              Job Control Builtins.
+* tab-insert (M-TAB):                   Commands For Text.
+* test:                                 Bourne Shell Builtins.
+* tilde-expand (M-~):                   Miscellaneous Commands.
+* times:                                Bourne Shell Builtins.
+* transpose-chars (C-t):                Commands For Text.
+* transpose-words (M-t):                Commands For Text.
+* trap:                                 Bourne Shell Builtins.
+* type:                                 Bash Builtins.
+* typeset:                              Korn Shell Builtins.
+* ulimit:                               Bash Builtins.
+* umask:                                Bourne Shell Builtins.
+* unalias:                              Alias Builtins.
+* undo (C-_, C-x C-u):                  Miscellaneous Commands.
+* universal-argument ():                Numeric Arguments.
+* unix-line-discard (C-u):              Commands For Killing.
+* unix-word-rubout (C-w):               Commands For Killing.
+* unset:                                Bourne Shell Builtins.
+* until:                                Looping Constructs.
+* upcase-word (M-u):                    Commands For Text.
+* wait:                                 Bourne Shell Builtins.
+* while:                                Looping Constructs.
+* yank (C-y):                           Commands For Killing.
+* yank-last-arg (M-., M-_):             Commands For History.
+* yank-nth-arg (M-C-y):                 Commands For History.
+* yank-pop (M-y):                       Commands For Killing.
+* Yanking text:                         Readline Killing Commands.
+* [:                                    Bourne Shell Builtins.
+
+
+\1f
+Tag Table:
+Node: Top\7f1044
+Node: Bourne Shell Features\7f2405
+Node: Looping Constructs\7f3579
+Node: Conditional Constructs\7f4634
+Node: Shell Functions\7f6194
+Node: Bourne Shell Builtins\7f7567
+Node: Bourne Shell Variables\7f9766
+Node: Other Bourne Shell Features\7f11025
+Node: Major Differences from the Bourne Shell\7f11783
+Node: Csh Features\7f14194
+Node: Tilde Expansion\7f15087
+Node: Brace Expansion\7f15691
+Node: C Shell Builtins\7f17283
+Node: C Shell Variables\7f20578
+Node: Korn Shell Features\7f21088
+Node: Korn Shell Constructs\7f21826
+Node: Korn Shell Builtins\7f23037
+Node: Korn Shell Variables\7f25190
+Node: Aliases\7f26466
+Node: Alias Builtins\7f28833
+Node: Bash Specific Features\7f29356
+Node: Invoking Bash\7f30085
+Node: Bash Startup Files\7f32404
+Node: Is This Shell Interactive?\7f34247
+Node: Bash Builtins\7f35055
+Node: The Set Builtin\7f41437
+Node: Bash Variables\7f46377
+Node: Shell Arithmetic\7f50945
+Node: Arithmetic Evaluation\7f51307
+Node: Arithmetic Expansion\7f53028
+Node: Arithmetic Builtins\7f53862
+Node: Printing a Prompt\7f54334
+Node: Job Control\7f55599
+Node: Job Control Basics\7f56074
+Node: Job Control Builtins\7f60249
+Node: Job Control Variables\7f61768
+Node: Using History Interactively\7f63077
+Node: History Interaction\7f63584
+Node: Event Designators\7f64630
+Node: Word Designators\7f65461
+Node: Modifiers\7f66446
+Node: Command Line Editing\7f67755
+Node: Introduction and Notation\7f68415
+Node: Readline Interaction\7f69435
+Node: Readline Bare Essentials\7f70574
+Node: Readline Movement Commands\7f72104
+Node: Readline Killing Commands\7f72995
+Node: Readline Arguments\7f74698
+Node: Readline Init File\7f75649
+Node: Readline Init Syntax\7f76647
+Node: Conditional Init Constructs\7f83580
+Node: Bindable Readline Commands\7f85826
+Node: Commands For Moving\7f86496
+Node: Commands For History\7f87344
+Node: Commands For Text\7f89988
+Node: Commands For Killing\7f91727
+Node: Numeric Arguments\7f93176
+Node: Commands For Completion\7f93803
+Node: Keyboard Macros\7f94816
+Node: Miscellaneous Commands\7f95375
+Node: Readline vi Mode\7f97466
+Node: Variable Index\7f98343
+Node: Concept Index\7f101671
+\1f
+End Tag Table
diff --git a/documentation/features.ps b/documentation/features.ps
new file mode 100644 (file)
index 0000000..b8b52cc
--- /dev/null
@@ -0,0 +1,3825 @@
+%!PS (but not EPSF; comments have been disabled)
+%DVIPSCommandLine: dvips -D 300 -o features.ps features.dvi
+%DVIPSParameters: dpi=300, compressed, comments removed
+%DVIPSSource:  TeX output 1995.05.08:1603
+/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N
+/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72
+mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1}
+ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale
+isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div
+hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul
+TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if}
+forall round exch round exch]setmatrix}N /@landscape{/isls true N}B
+/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B
+/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{
+/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N
+string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N
+end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{
+/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0]
+N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup
+length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{
+128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub
+get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data
+dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N
+/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup
+/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx
+0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff
+setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff
+.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N
+/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id
+gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp
+add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add
+/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{
+dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1
+adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2
+idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string
+putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval
+adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg}
+{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{
+adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2
+chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{]
+}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup
+length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{
+cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin
+0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul
+add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict
+/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook
+known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X
+/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for
+65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0
+0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V
+{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7
+getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false}
+ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false
+RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1
+false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform
+round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg
+rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail
+{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M}
+B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{
+4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{
+p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p
+a}B /bos{/SS save N}B /eos{SS restore}B end
+TeXDict begin 40258431 52099146 1000 300 300 (features.dvi)
+@start /Fa 1 59 df<127012F8A3127005057C840D>58 D E /Fb
+1 59 df<127812FCA4127806067B8510>58 D E /Fc 35 122 df<126012F0A212701210
+A31220A21240A2040B7D830B>44 D<EA07E0EA1C38EA381CEA300CEA700EEA6006A2EAE0
+07AAEA6006A2EA700EEA300CEA381CEA1C38EA07E010187F9713>48
+D<12035AB4FC1207B3A2EA7FF80D187D9713>I<EA0F80EA1060EA2030EA4038EA803CEA
+C01C12E01240EA003C1338A21370136013C0EA018013001202EA040412081210EA3008EA
+3FF8127F12FF0E187E9713>I<EA07E0EA1838EA201CEA601EEA700EEA201E1200131CA2
+13381370EA07E0EA0038131C130E130FA212E0A212C0EA400EEA601CEA1838EA07E01018
+7F9713>I<1318A21338137813F813B8EA01381202A212041208121812101220124012C0
+B5FCEA0038A6EA03FF10187F9713>I<EA3018EA3FF013E01380EA2000A5EA2FC0EA3060
+EA2030EA00381318131CA2124012E0A2EA8018EA40381330EA30E0EA0F800E187E9713>
+I<EA01F8EA0704EA0C06EA180E123013001270126012E0EAE3E0EAE418EAE80CEAF00EEA
+E0061307A31260A2EA7006EA300EEA180CEA0C38EA07E010187F9713>I<1240EA7FFF13
+FEA2EA4004EA80081310A2EA00201340A21380120113005AA25A1206A2120EA512041019
+7E9813>I<EA07E0EA1818EA300CEA20061260A21270EA780CEA3E18EA1F30EA07C0EA03
+E0EA0CF8EA307CEA601E130FEAC0071303A3EA6002EA2004EA1818EA07E010187F9713>
+I<EA07E0EA1C30EA3018EA700CEA600EEAE006A21307A31260EA700FEA3017EA1827EA07
+C7EA00071306130E130C12701318EA6030EA3060EA0F8010187F9713>I<39FFE1FFC039
+0E001C00AB380FFFFC380E001CAC39FFE1FFC01A1A7F991D>72 D<39FFE01FC0390E000F
+00140C14085C5C5C495A0102C7FC5B130C131C132E1347EB8380EA0F03380E01C06D7EA2
+147080A280141E141F39FFE07FC01A1A7F991E>75 D<B5FC380E01C0EB0070147880A55C
+1470EB01C0D80FFFC7FC380E0380EB00C0801470A31478A31540143CEC1C8039FFE00F00
+1A1A7F991C>82 D<39FF801FE0391E00070014066C13046C130CEB800800035BEA01C06D
+5A00001360EB7040EB78801338011DC7FC131F130EAAEBFFC01B1A7F991D>89
+D<EA1FC0EA38707FEA101C1200A2EA03FCEA1E1C1238127012E01480A2133CEA705F381F
+8F0011107F8F13>97 D<EA07F8EA1C1C1238EA700813005AA612701304EA3808EA1C18EA
+07E00E107F8F11>99 D<133F1307A9EA03E7EA0C17EA180F487E127012E0A6126012706C
+5AEA1C373807C7E0131A7F9915>I<EA07C0EA1C30EA30181270EA600C12E0EAFFFCEAE0
+00A41260EA7004EA3808EA1C18EA07E00E107F8F11>I<EA0FCF3818718038303000EA70
+38A4EA30306C5AEA2FC00060C7FCA21270EA3FF013FC6C7EEA600FEAC003A4EA6006EA38
+1CEA07E011187F8F13>103 D<12FC121CA9137CEA1D87381E0380A2121CAB38FF9FF014
+1A809915>I<1218123CA212181200A612FC121CAE12FF081A80990A>I<12FC121CA9EB1F
+C0EB0F00130C5B13205B13E0121DEA1E70EA1C7813387F131E7F148038FF9FE0131A8099
+14>107 D<12FC121CB3A6EAFF80091A80990A>I<EAFC7CEA1D87381E0380A2121CAB38FF
+9FF01410808F15>110 D<EA07E0EA1C38EA300CEA700EEA6006EAE007A6EA6006EA700E
+EA381CEA1C38EA07E010107F8F13>I<EAFCFCEA1D07381E0380381C01C0A2EB00E0A6EB
+01C01480381E0300EA1D06EA1CF890C7FCA6B47E1317808F15>I<EAFC78EA1D9CEA1E1C
+1308EA1C00ABEAFF800E10808F0F>114 D<EA1F20EA60E0EA402012C0A2EAF000127FEA
+3FC0EA1FE0EA00F0EA8070133012C01320EAF040EA8F800C107F8F0F>I<1208A41218A2
+1238EAFFC0EA3800A81320A41218EA1C40EA07800B177F960F>I<38FC1F80EA1C03AB13
+07120CEA0E0B3803F3F01410808F15>I<38FF0F80383C0700EA1C061304A26C5AA26C5A
+A3EA03A0A2EA01C0A36C5A11107F8F14>I<39FE7F1F8039381C0700003C1306381C0C04
+130E380E16081317A238072310149013A33803C1A014E0380180C0A319107F8F1C>I<38
+FE3F80383C1E00EA1C086C5AEA0F306C5A6C5A12017F1203EA0270487E1208EA181CEA38
+1E38FC3FC012107F8F14>I<38FF0F80383C0700EA1C061304A26C5AA26C5AA3EA03A0A2
+EA01C0A36C5AA248C7FCA212E112E212E4127811177F8F14>I E
+/Fd 1 59 df<126012F0A2126004047D830B>58 D E /Fe 68 127
+df<126012F0AD12601200A4126012F0A212600417789614>33 D<13801201A2EA07E0EA
+1FF0EA39BCEA619CEAC18EA3EAE184EA7180127FEA1FE0EA0FF0EA01F8139C138EEA4186
+12E1A3EA718CEA39B8EA1FF0EA0FC0EA0180A212000F1D7E9914>36
+D<EA01801203EA06005A121C121812385AA35AA91270A37E1218121C120C7EEA03801201
+091D799914>40 D<128012C01260123012381218121C120EA31207A9120EA3121C121812
+381230126012C01280081D7C9914>I<127012F812FCA2127C120C1218123012E012C006
+0A798414>44 D<EAFFFEA30F037E8C14>I<127012F8A312700505798414>I<EA07C0EA0F
+E0EA1C70EA3838EA3018EA701CA2EAE00EA9EA701CA2EA3838A2EA1C70EA0FE0EA07C00F
+177E9614>48 D<1203A25A5A123F12F712471207AEEA7FF0A20C177C9614>I<EA0FC0EA
+1FF0EA3838EA701CEAE00EA312401200131CA213381330137013E0EA01C0EA030012065A
+EA180E1230EA7FFEA20F177E9614>I<EA0FC0EA1FF0EA3838EA701CA212201200131813
+381370EA0FE013F0EA0038131C130EA2124012E0A2EA701CEA7838EA3FF0EA0FC00F177E
+9614>I<137813F8EA01B8A2EA0338A21206120E120C121C12381230127012E0B51280A2
+38003800A548B4FCA211177F9614>I<127012F8A312701200A6127012F8A31270051079
+8F14>58 D<130E133E137C13F0EA03E0EA07C0EA1F00123E12F85A7E123E7EEA07C0EA03
+E0EA00F0137C133E130E0F137E9414>60 D<124012E012F8127C121EEA0F80EA07C0EA01
+F0EA00F8133E131E133E13F8EA01F0EA07C0EA0F80EA1E00127C5A12E012400F157E9514
+>62 D<EA1FE0EA3FF8EA701CEAE00EA21240EA003C137013E0EA01C0EA0380A41300C7FC
+A41203EA0780A2EA03000F177E9614>I<EA01C0487EA21360A2EA0770A4EA0630EA0E38
+A4487EEA1FFCA2EA1C1CA2487EA238FE3F80A211177F9614>65 D<EAFFF013FCEA381E13
+0E1307A4130E131EEA3FFCA2EA381E130E1307A5130E131EEAFFFC13F810177F9614>I<
+3801F180EA07FFEA0E1FEA1C071238EA7003A348C7FCA738700380A338380700121CEA0E
+0EEA07FCEA01F011177F9614>I<EAFFE013F8EA383C7F130E7FA3EB0380A8EB0700A213
+0E131E5BEAFFF813E011177F9614>I<B5FCA2EA3807A490C7FCA21338A2EA3FF8A2EA38
+38A290C7FCA3EB0380A4B5FCA211177F9614>I<B51280A2EA3803A490C7FCA21338A2EA
+3FF8A2EA3838A290C7FCA7B4FCA211177F9614>I<EA03C6EA0FFEEA1C3EEA181E1238EA
+700EA21260EAE000A4137FA2130E12601270A2EA381E1218EA1C3EEA0FFEEA03CE10177F
+9614>I<38FE3F80A238380E00A8EA3FFEA2EA380EA938FE3F80A211177F9614>I<EAFFF8
+A2EA0700B3EAFFF8A20D177D9614>I<EAFE3FA2EA381C5B137813705B12395BEA3B80EA
+3FC07F123EEA3CF01370EA387813387FA27FA238FE1F80A211177F9614>75
+D<B4FCA21238AF1307A4B5FCA210177E9614>I<38FC1F80A2007C1300EA7637A4EA7777
+A2EA7367A313E7EA71C7A2EA7007A638F80F80A211177F9614>I<38FE3F80A2383E0E00
+123BA4138E1239A213CEA31238A213EE136EA4133E12FEA211177F9614>I<EA1FF0EA7F
+FCEA783CEA701CEAE00EAFEA701CEA783CEA7FFCEA1FF00F177E9614>I<EAFFF013FCEA
+381E130E1307A5130E131EEA3FFC13F0EA3800A812FEA210177F9614>I<EAFFE013F8EA
+383C131C7FA45B133CEA3FF85BEA38387FA51480EB1DC0A238FE0F80EB070012177F9614
+>82 D<EA0FCCEA1FFCEA307CEA603CEAE01CA313001270127EEA3FE0EA0FF0EA01F8EA00
+1C131E130E126012E0A2EAF01CEAF838EAFFF0EAC7E00F177E9614>I<387FFF80B5FCEA
+E1C3A43801C000AFEA0FF8A211177F9614>I<38FE0FE0A238380380B0381C0700A2EA0E
+0EEA07FCEA01F01317809614>I<38FC1F80A238380E00A3EA3C1EEA1C1CA46C5AA4EA06
+30EA0770A3EA0360A213E0A26C5A11177F9614>I<38FC1F80A238700700A7EA31C6EA33
+E6EA3BEE136EA5EA1B6CA2EA1A2CEA1E3CA311177F9614>I<38FC1F80A238380E00EA3C
+1EEA1C1CEA1E3CEA0E38A26C5AA2EA036013E0A26C5AA8EA07F0A211177F9614>89
+D<EA7FFE12FFEAE01CA21338A2EA007013E0A2EA01C0A2EA0380EA0700A2120EA25AEA38
+0EA21270A2EAFFFEA20F177E9614>I<EAFFE0A2EAE000B3A7EAFFE0A20B1D799914>I<12
+04121FEA7FC0EAF1E012E00B057C9614>94 D<EA1FC0EA7FF0EA7078EA2018EA001CA2EA
+07FC121FEA3C1C127012E0A3EA707C383FFF80EA0F8F11107E8F14>97
+D<12FCA2121CA513F8EA1DFEEA1F07EA1E03001C1380EB01C0A6EB0380001E1300EA1F0E
+EA1DFCEA0CF81217809614>I<EA03F8EA0FFEEA1C0EEA3804EA7000126012E0A4126012
+70EA380EEA1C1EEA0FFCEA03F00F107E8F14>I<137EA2130EA5EA07CEEA0FFEEA1C3EEA
+301EEA700E12E0A61270EA301EEA383E381FEFC0EA07CF12177F9614>I<EA07E0EA0FF0
+EA1C38EA301CEA700CEAE00EA2EAFFFEA2EAE00012601270EA380EEA1C1EEA0FFCEA03F0
+0F107E8F14>I<13FCEA01FEEA038EEA07041300A3EA7FFE12FFEA0700ACEAFFF8A20F17
+7F9614>I<EA07CF381FFF80EA383B38301800EA701CA3EA3018EA3838EA3FF0EA37C000
+70C7FCA2EA3FF86C7E487EEA700F38E00380A438700700EA3C1EEA1FFCEA07F011197F8F
+14>I<12FCA2121CA51378EA1DFEEA1F86EA1E07121CAA38FF8FE0A21317809614>I<1206
+120FA21206C7FCA4B4FCA21207ACEAFFF8A20D187C9714>I<136013F0A213601300A4EA
+1FF0A2EA0070B2EA40E0EAE0C0EA7F80EA3F000C207E9714>I<12FCA2121CA5EBFF80A2
+EB1C005B5B5BEA1DC0EA1FE0A2EA1E70EA1C38133C131C7F38FF1F80A21117809614>I<
+EAFF80A21203B3EAFFFEA20F177E9614>I<EAFB8EEAFFDF383CF380A2EA38E3AA38FEFB
+E013791310808F14>I<EAFC78EAFDFEEA1F86EA1E07121CAA38FF8FE0A21310808F14>I<
+EA07C0EA1FF0EA3C78EA701CA2EAE00EA6EA701CEA783CEA3C78EA1FF0EA07C00F107E8F
+14>I<EAFCF8EAFDFEEA1F07EA1E03001C1380EB01C0A6EB0380001E1300EA1F0EEA1DFC
+EA1CF890C7FCA6B47EA21218808F14>I<EA03E7EA0FF7EA1C1FEA300F1270487EA6EA70
+0F1230EA1C3FEA0FF7EA07C7EA0007A6EB3FE0A213187F8F14>I<EAFE1FEB7F80EA0EE3
+380F810090C7FCA2120EA8EAFFF0A211107F8F14>I<EA0FD8EA3FF8EA603812C0A2EAF0
+00EA7F80EA3FF0EA07F8EA001CEA600612E012F0EAF81CEAFFF8EACFE00F107E8F14>I<
+1206120EA4EA7FFC12FFEA0E00A8130EA3131CEA07F8EA01F00F157F9414>I<EAFC3FA2
+EA1C07AB131F380FFFE0EA03E71310808F14>I<38FE3F80A2383C1E00EA1C1CA36C5AA3
+EA0630EA0770A36C5AA311107F8F14>I<38FE3F80A238700700EA380EA3EA39CEA3EA1B
+6C121AA3EA1E7CA2EA0E3811107F8F14>I<EA7E3FA2EA1E3CEA0E78EA07705B12036C5A
+12037FEA0770EA0E781338487E38FE3F80A211107F8F14>I<38FE3F80A2381C0E005BA2
+120E5BA212071330A2EA0370A25B1201A25BA3485A12730077C7FC127E123C11187F8F14
+>I<EA3FFF5AEA700E131C1338EA007013E0EA01C0EA0380EA0700120EEA1C0712381270
+B5FCA210107F8F14>I<EA1C10EA3F38EAE7E0EA41C00D047D9614>126
+D E /Ff 51 122 df<903907FC0FE090393FFF3FF89039FC03FC783A03F007F0FC3807E0
+0F15E0D80FC0147802071300A7B71280A23A0FC007E000B3A239FFFC7FFFA226267FA524
+>11 D<EB07FCEB3FFF9038FE0780D803F013C03807E00FA2EA0FC0A3EC030091C7FCA3EC
+7FE0B6FCA2380FC007B3A239FFFC7FFEA21F267FA522>I<123C127E12FFA4127E123C08
+087C8711>46 D<131C133C13FC12FFA21200B3AA387FFFFCA216237CA21F>49
+D<48B4FC000713C0381E07F0383803F8386001FC387C00FE12FE14FF147FA2127C003813
+FFC7FC14FEA2EB01FC14F8EB03F0EB07E01480EB0F00131E5B1370EBE003EA01C0380380
+07380700061206380FFFFE5A5A4813FCB5FCA218237DA21F>I<48B4FC000713E0381E03
+F0383801F8003C13FC387E00FEA3123EEA1C01000013FCA2EB03F8EB07F0EB0FC03801FF
+00A2380007E0EB01F014F8EB00FC14FE14FFA21210127C12FEA214FEA2387C01FC007013
+F8383E07F0380FFFC00001130018237DA21F>I<14381478A214F8130113031307130613
+0C131C13381330136013E0EA01C01380EA03005A120E5A12185A12705AB612C0A2390001
+F800A790387FFFC0A21A237EA21F>I<0018130C001F137CEBFFF814F014E014C01480EB
+FC000018C7FCA513FF001B13E0381F03F0381C00F8000813FCC7127EA3147FA2127812FC
+A3147E5A006013FC1270383801F8381E07E03807FFC03801FE0018237DA21F>I<EB1FC0
+EB7FF03801F0383803E00C3807803E000F137EEA1F005AA2007E133C1400A338FE3FC0EB
+7FF0EB80F800FF13FCEB007C147E5A147FA4127EA4003E137E123F6C137C380F80F83807
+C1F03803FFC038007F0018237DA21F>I<1230123C003FB512C0A215804814005C5C3860
+0018A200E05B485B5CC6485AA249C7FC1306130EA25BA2133CA25BA213F8A41201A66C5A
+13601A257DA41F>I<EBFF80000313E0380F01F8381C007C48133C141E1278A2127C127E
+387F803C13E0383FF878381FFDF0EBFFC07E000313E014F8000F13FCEA1E1F383C07FEEA
+7803EB00FF48133F141F140FA3140E1278141C6C1338381F80F03807FFE0000113001823
+7DA21F>I<141CA2143EA3147FA24A7EA39038019FC0A29038031FE0140F01077FEB0607
+A2010C7F1403011C7FEB1801A2496C7EA2017FB5FCA29039E0007F8049133FA248488015
+1F00038190C7120FA2486E7ED8FFF090B51280A229257EA42E>65
+D<B612E015FC3903F0007FED3F80ED1FC0ED0FE0A216F0A21507150FA216E0151F16C0ED
+7F80913801FE0090B512F815FF9039F0003FC0ED0FE0ED07F016F8150316FCA616F81507
+ED0FF0ED1FE0ED7FC0B7120015F826257EA42C>I<9138FF8008010FEBF01890393FC03C
+789039FE0006F8D801F81303484813014848130048481478121F48481438A2007F151890
+C8FCA2481500A97E16187F123FA26C6C1430120F6C6C14606C6C14C06C6CEB0180D800FE
+EB070090383FC01E90380FFFF8010013C025257DA42C>I<B612E015FC3903F800FFED1F
+C0ED07E06F7E6F7E82150082A2167FA31780AA1700A316FEA24B5A5E4B5A4B5AED1FC0ED
+FF80B648C7FC15E029257EA42F>I<B7FCA23903F8007FED0F8015071503A21501A3ED00
+C01406A21600A2140E141EEBFFFEA2EBF81E140E1406A21660A291C7FC16C0A415011503
+A2ED0F80153FB7FCA223257EA428>I<B612FEA23803F800151F8181A281A3ED01801403
+A292C7FCA25C5C90B5FCA2EBF80F8080A491C8FCAAB512F0A221257EA427>I<B500E0B5
+12E0A23B03F80003F800AF90B6FCA29038F80003B0B500E0B512E0A22B257EA430>72
+D<B512E0A23803F800B3AFB512E0A213257EA417>I<B539E007FF80A2D803F8C7EA7800
+16605E4B5A0307C7FC150E15185D5D5DEC03804AC8FC140E141F4A7E147FECDFC09038FB
+8FE09038FF0FF0EBFC07496C7E816E7E1400157F82153F6F7E6F7E8215076F7E82B539E0
+3FFFC0A22A257EA430>75 D<B512F0A2D803F8C7FCB3A31503A31506A3150EA2151E153E
+157CEC03FCB6FCA220257EA425>I<D8FFF8EDFFF86D5C0003EEFE00017EEC037EA36D14
+06A26D6C130CA26D6C1318A26D6C1330A36D6C1360A26D6C13C0A2903900FC0180A29138
+7E0300A3EC3F06A2EC1F8CA2EC0FD8A2EC07F0A36E5AEA07803CFFFC01C01FFFF8A23525
+7EA43A>I<D8FFF8903807FFE07FD803FE9038003C006D14187F6D7E6D7E806D7E6D7E13
+036D7E6D7E80EC7F80EC3FC0141FEC0FE015F0EC07F8EC03FC1401EC00FE157F1698ED3F
+D8ED1FF8150F15071503A2150115001678486C1438D8FFFC1418A22B257EA430>I<B67E
+15F83903F801FEEC007F6F7E6F7EA282A55EA24B5A4BC7FCEC01FE90B512F815C09038F8
+03F06E7E6E7E157EA2157FA482A31760ED3FC017C0ED1FE1B539E00FFF80923801FE002B
+257EA42E>82 D<01FF1380000713E3380F80F7381E001F48130F481307140312F81401A2
+7E91C7FCB4FCEA7FE013FE383FFFE014F86C13FE00077F6C1480C67E010313C0EB003FEC
+0FE01407A200C01303A315C07E6C13076C14806CEB0F0038FFC03E38E3FFF838803FE01B
+257DA422>I<007FB612F8A2397E00FE010078EC00780070153800601518A200E0151C16
+0C5AA4C71400B3A390B512FEA226247EA32B>I<B53B81FFFE01FFF0A23D07F0001FC000
+0F007013066C6C010F5CA26F7E6C6C5EA26D496C1338000017304B7E017F01195CA29138
+8030FE013F5E829139C0607F01011F5E03E0138190280FE0C03F83C7FCA29139F1801FC3
+010715C617E69139FB000FEE010315EC02FF14FC6D486D5AA24A130301005DA24A130102
+785CA202306D5A3C257FA43F>87 D<B539C001FFE0A2D807F8C7EA1C006C6C141816386C
+6C14306C6C5C16E06D6C5B6D6C485A1503D91FE090C7FC90380FF006150E903807F80C6D
+6C5A15386D6C5A903800FF6015E06E5A6E5AAE90380FFFFCA22B257FA42E>89
+D<EA07FF001F13E0383E03F0383F00F880147E121EC7FCA3EB1FFE3803FE7EEA0FC0EA1F
+00123E127E5AA314BEEA7E01383F073E391FFE1FE03807F00F1B187E971E>97
+D<EAFFC0A2120FACEBC1FCEBCFFF9038FC0FC09038F007E09038C003F0A2EC01F8A215FC
+A815F8A2EC03F013E09038F007E090381C1F80390E0FFF00380C03F81E267FA522>I<EB
+7FE03803FFF83807C07C381F80FC13005A007E1378140012FEA8127E127F6C130CEA1F80
+EBC0183807E0703803FFE038007F0016187E971B>I<ECFFC0A2140FAC137F3803FFCF38
+0FE0FF381F803F383F000FA2127EA212FEA8127EA27E141F381F803F380FC0EF3903FFCF
+FC3800FE0F1E267EA522>I<137F3803FFC03807C1F0380F80F8EA1F0048137C127E147E
+12FEA2B512FEA248C7FCA3127EA214067E6C130C380F80183807E0703803FFE038007F80
+17187E971C>I<EB1FC0EB7FF0EA01F83803E1F8120713C1380FC0F01400A7B5FCA2EA0F
+C0B3A2EAFFFEA215267EA513>I<3901FF07C00007EBDFE0380F83F1EA1F01393E00F800
+007E7FA6003E5B6C485A380F83E0EBFFC0001190C7FC0030C8FCA21238123C383FFFE06C
+13FC806C7F481480383C003F48EB0FC000F81307A4007CEB0F806CEB1F00381F807E3807
+FFF8C613C01B247E971F>I<EAFFC0A2120FAC14FE9038C3FF809038CE0FC013D89038D0
+07E013E0A213C0AF39FFFC7FFEA21F267EA522>I<120FEA1F80EA3FC0A4EA1F80EA0F00
+C7FCA7EA7FC0A2120FB3A2EAFFF8A20D277EA611>I<131E133FEB7F80A4EB3F00131E90
+C7FCA73801FF80A2EA001FB3A8127800FC13005B133EEA787CEA3FF8EA0FE0113283A613
+>I<EAFFC0A2120FACEC1FF0A2EC0780EC0E005C14305CEBC1C0EBC38013C713DFEBFFC0
+EBE7E0EBC3F0138180EB80FC147E80A2EC1F80EC0FC039FFF83FF8A21D267FA520>I<EA
+FFC0A2120FB3B0EAFFFCA20E267EA511>I<26FF80FE137F903A83FF81FFC03B0F8E0FC7
+07E0019813CC903A9007E803F001A013F0A201C013E0AF3BFFFC7FFE3FFFA230187E9733
+>I<38FF80FE903883FF80390F8E0FC0139890389007E013A0A213C0AF39FFFC7FFEA21F
+187E9722>I<EB7F803803FFF03807C0F8381F807E48487EA2007EEB1F80A200FE14C0A8
+007E1480A26CEB3F00A2381F807E6C6C5A3803FFF038007F801A187E971F>I<38FFC1FC
+EBCFFF390FFC1FC09038F007E001C013F0140315F8140115FCA8EC03F8A215F0EBE00790
+38F00FE09038DC1F809038CFFF00EBC3F801C0C7FCA9EAFFFCA21E237F9722>I<38FF83
+E0EB8FF8380F8C7CEB90FC13B013A01478EBE0005BAEEAFFFEA216187F9719>114
+D<3807F8C0EA1FFFEA3C07EA7001EAF000A300FC1300B47EEA7FFC7F383FFF80000F13C0
+120338001FE01303EAC001A212E014C0EAF00338FC078038EFFF00EAC3FC13187E9718>
+I<13C0A41201A312031207120F121FB512C0A2380FC000AC1460A63807E0C013E13801FF
+8038007E0013237FA218>I<39FFC07FE0A2000F1307B0140FA200071317EBE0673903FF
+C7FE38007F071F187E9722>I<39FFF80FF8A2390FC001C015803907E00300A26D5A0003
+1306EBF80E0001130C13FC00005B13FEEB7E30A26D5AA214E06D5AA26D5AA26DC7FCA21D
+187F9720>I<39FFF83FF0A2390FC00F003807E00E6C6C5A6D5A6C6C5A00001360EB7EC0
+6D5AA2131F6D7E497E80EB33F81361EBE0FC3801C07E3803807F3907003F8048131F39FF
+C07FF8A21D187F9720>120 D<39FFF80FF8A2390FC001C015803907E00300A26D5A0003
+1306EBF80E0001130C13FC00005B13FEEB7E30A26D5AA214E06D5AA26D5AA26DC7FCA213
+06A25B1230EA781CEAFC185B1370EA68E0EA7FC0001FC8FC1D237F9720>I
+E /Fg 39 122 df<EB03E0EB1C181338EB703C13E014383801C000A5485A387FFFF03803
+8070A4380700E0A6380E01C0A6381C0380001E13C038FF0FF016207E9F19>12
+D<903803F03F90391E09E0809039380F80C09039701F01E0EBE03E021E13C02601C01CC7
+FCA548485A007FB612803903803803A43A0700700700A6000EEBE00EA64848485A001EEB
+E01E3AFF8FF8FFC023207E9F26>14 D<EC0801EC1803A2EC3006A34A5AA24A5AA349485A
+A349485A001FB612C04815E03A000C018000A24948C7FCA3EB3006A2495AB712806C1500
+26018030C7FCA348485AA200065BA348485AA34848C8FCA2EA100223297D9F26>35
+D<EAFFF0A20C027E8A0F>45 D<13181338EA01F8EA0E701200A513E0A6EA01C0A6EA0380
+A6EA07001380EAFFFC0E1E7B9D17>49 D<EB3F80EBC1E038010070000213785AA2000F13
+7C1380A2EB00781206C712F814F0EB01E014C0EB0380EB0700130E5B5B13605B485A3803
+00201206000813405A383FFFC0481380B5FC161E7E9D17>I<120E121FA2121E120C1200
+AA1230127812F81278127008147C930D>58 D<001FB512FE4814FFC9FCA8B612FC6C14F8
+200C7D9023>61 D<3807FF803800F8001378A25BA6485AA6485AA6485AA648C7FC7FEAFF
+F0111F7E9E10>73 D<3A07FF803FE03A00F8001F000178130C5D4913205D5D4AC7FC1402
+140848485A5C146014F013E1EBE4F83803C878EBD07CEBE03CEBC03E141E141F48487E81
+140781140381380F00016D487E39FFF00FFE231F7E9E23>75 D<EB01FCEB0E0790383801
+C090387000E0484813F048481378485A153C48C7FC5A001E143E123E123C127CA448147C
+A3157815F81278EC01F0007C14E01403003C14C0001CEB0780001EEB0F006C131E380780
+383801C0E038007F801F217C9F23>79 D<0007B5FC3900F803C090387800F015785B157C
+A41578484813F815F0EC01E0EC03C0EC0F00EBFFFCD803C0C7FCA6485AA648C8FC7FEAFF
+F81E1F7E9E1F>I<EB1F82EB7066EBC01E3801800EEA030048130C00061304120EA3000F
+1300A27FEA07F013FF6C13C06C13E038003FF0EB03F813001478143CA200401338A31430
+00601370146000F013C038E8018038C60300EA81FC17217E9F19>83
+D<3A03FFC0FFC03A007F003E00013C1318013E1310011E5B011F5B6D5B0281C7FCEB0783
+14C2EB03C414E8EB01F0A2130080A2EB017CEB023CEB043EEB0C1EEB081F497E13200140
+7FEB8007000180EB0003000780391F8007F039FFC01FFE221F7F9E22>88
+D<EA07F8EA0C0CEA1E061307121C1200A313FFEA07C7EA1E07EA3C0E127800F01310A313
+1EEB2E2038784F40381F878014147D9317>97 D<1207123F120F7EA2120EA65A137CEA1D
+83381E0180001C13C0EB00E05A14F0A5387001E0A214C013031480EB0700EAE80EEACC38
+EA83E014207B9F19>I<13FEEA0383380E0780121C0038130090C7FC12785AA45AA37E5B
+EA70026C5AEA1C18EA07E011147D9314>I<1438EB01F8EB00781438A21470A614E013FC
+EA0382EA0601121CEA3C00383801C0127812F0A438E00380A412F0EA700738380F00381C
+37803807C7E015207D9F19>I<13F8EA070EEA0E07121C383803801278127012F0A2B5FC
+00F0C7FC5AA46C5AEA7002EA3004EA1C18EA07E011147D9314>I<EB07C0EB1C60EB30F0
+1360EBE0E0EBC0001201A5485AEA3FFCEA0380A448C7FCA6120EA65A121EEAFFC014207F
+9F0E>I<140EEB3E11EBE1A33801C1C2380381E0EA07801301120FA3380703C01480EB87
+00EA04FC48C7FCA21218121CEA0FFF14C014E0381800F04813305A5AA3006013606C13C0
+381C0700EA07FC181F809417>I<13E0120712011200A2485AA6485AEB8F80EB90E013A0
+EBC0601380000713E01300A5380E01C0A6381C0380001E13C038FF8FF014207E9F19>I<
+EA01C0EA03E0A213C0EA0180C7FCA6EA0380121F12071203A2EA0700A6120EA65A121EEA
+FF800B1F7F9E0C>I<EB0380EB07C0A21480EB030090C7FCA61307137F130F7FA2130EA6
+5BA65BA65B1260EAF0605BEA6180003FC7FC1228839E0E>I<13E0120712011200A2485A
+A6485AEB81FCEB80F014C0EB81801400EA07045B13181338137C131C120E7FA2130F7F14
+80EA1C03381E07C038FF8FF016207E9F18>I<13E0120712011200A2EA01C0A6EA0380A6
+EA0700A6120EA65A121EEAFF800B207F9F0C>I<390387C07C391F9861863907A0720739
+03C03403EB80380007EB7807EB0070A5000EEBE00EA64848485A001EEBE01E3AFFCFFCFF
+C022147E9326>I<38038F80381F90E0EA07A03803C0601380000713E01300A5380E01C0
+A6381C0380001E13C038FF8FF014147E9319>I<13FCEA0387380E0180381C00C04813E0
+A24813F012F0A438E001E0A214C0130300F0138038700700EA380E6C5AEA07E014147D93
+17>I<EBE3E03807EC383800F01C497E140F48487E1580A53903800F00A2140E141E141C
+5C38074070EB61C0011FC7FC90C8FCA3120EA4121EEAFFC0191D809319>I<EBFC203803
+8260EA0702381E01E0123C003813C0127812F0A438E00380A212F0A21307127038380F00
+EA1C37EA07C7EA0007A3130EA4131EEBFFC0131D7D9318>I<EA038E381FB380EA07C712
+03EB8300EA078090C7FCA5120EA65A121EEAFFC011147E9312>I<EA01F9EA0607EA0803
+12181301EA3802EA3C00121F13F0EA07FCEA01FEEA001FEA40071303A212601306EAF004
+EAC818EA87E010147F9312>I<1380EA0100A35A5A5A121EEAFFF8EA0E00A45AA65A1310
+A41320A2EA1840EA0F800D1C7C9B12>I<381C0380EAFC1FEA3C07EA1C03A238380700A6
+EA700EA4131EA25BEA305E381F9F8011147B9319>I<38FF83F8381E00E0001C13C01480
+121E380E01005B13025B12075BA25BEA039013A013E05B5B120190C7FC15147C9318>I<
+39FF9FE1FC393C078070391C030060148015401580EA0E0790380D81001309EB19C21311
+380F21C4EA0720EB40C814E8EB80F0A26C485A1460000213401E147C9321>I<381FF0FF
+3803C0780001137014403800E0C0EBE180EB73001376133CA2131C132E134E1387EA0107
+380203801204380C01C0383C03E038FE07FC18147F9318>I<390FF83F803901E00E00EB
+C00C140813E000005B143014205C13705CA20171C7FC1339133A133E133C133813181310
+A25BA25BEA70C0EAF08000F1C8FC12E61278191D809318>I E /Fh
+44 122 df<EC3FF8903803FFFE90390FF80F8090393FC001C090397F0007E001FE130F00
+014A7E5B1203A26F5A6F5A0301C7FC92C8FCA5B712F0A33903FC001F150FB3A7267FFFE1
+B51280A329327FB12D>12 D<B512F8A715077F921B>45 D<EB01C01303130F137FEA1FFF
+B5FC13BFEAE03F1200B3B1007FB512F0A31C2E7AAD28>49 D<EB3FE03801FFFE0007EBFF
+80D80F8013C0391E003FE00038EB1FF0007CEB0FF8007EEB07FCB4FC018013FEA21403A2
+EA7F00003E1307C7FC15FCA2EC0FF8A215F0EC1FE015C0EC3F80EC7F00147E14F8495A49
+5A495A49C7FC011E130E5B133849131E49131C485A48C7123C48B512FC5A5A5A4814F8B6
+FCA31F2E7CAD28>I<EB1FF890B5FC000314C03907E01FF0390F0007F8D81F807FEA3FC0
+6E7EA4EA1F80380F0007C75BA25D4A5A4A5AEC3F8002FFC7FCEB3FF8ECFF809038001FE0
+6E7E6E7E6E7E816E7EA21680A3121C123E127FEAFF801600A24A5AEA7F00007E495A003C
+5C391FC01FF06CB512C0000391C7FC38003FF8212E7DAD28>I<157015F0140114031407
+140FA2141F143F147714F714E7EB01C7EB0387EB0707130F130E131C1338137013F013E0
+EA01C0EA0380EA07005A120E5A5A5A5AB712E0A3C7380FF000A9010FB512E0A3232E7EAD
+28>I<000C1430390FC007F090B512E015C0158015005C14F85C1480000EC8FCA8EB1FF0
+EBFFFE390FE03F809038000FC0000EEB07E0000C14F0C713F8140315FCA215FEA2121812
+3E127F5AA215FCA25A0078EB07F815F06CEB0FE06CEB1FC0390FC07F806CB51200000113
+FC38003FE01F2E7CAD28>I<14FF010713E0011F7F90387F80F89038FE003CD801F8137C
+484813FE00071301EA0FE0A2EA1FC0003F6D5A157892C7FC485AA338FF83FC90388FFF80
+90389C0FC09038B003F06E7E01E07F01C07F140081A2491480A4127FA4003F15007F121F
+5D000F495AEA07E06C6C485A3901FC0FE06CB55A013F90C7FCEB0FFC212E7DAD28>I<12
+38123E003FB612C0A316804815005D5D5D0078C7123800705C5D00F0495A48495A4AC7FC
+A2C7120E5C5C1478147014F0495AA213035C1307A2130FA2131F5CA2133FA4137FA86DC8
+FC131E22307CAF28>I<1578A215FCA34A7EA24A7EA24A7FA34A7FEC0E7F021E7FEC1C3F
+A202387F151F02787FEC700FA202E07F1507010180ECC003A249486C7EA201078191C7FC
+498191B6FCA24981011CC7123F013C810138141FA24981160F01F081491407A248488148
+6C1403B549B512FCA336317DB03D>65 D<B712C016FC16FFD801FEC77FEE7FE0707E161F
+707EA2831607A4160FA25FA24C5A4C5A4C5A4B485ADB1FFEC7FC90B65AEEFF8049C7EA3F
+E0EE0FF0EE07FCA2707E83821880A718005E5F16074C5A4C5AEEFFF0B812C094C7FC16F8
+31317DB039>I<913A03FF800180023FEBF00349B5EAFC0701079038003F0FD91FF8EB07
+9FD93FC0EB01FFD9FF807F4848C8127F4848153F0007161F49150F485A001F1607A2485A
+1703127FA24992C7FCA212FFA9127FA27FEF0380123FA26C7E1707000F17006C7E6D150E
+0003161E6C6C151C6C6C6C1478D93FC05CD91FF8EB03E0D907FFEB3F800101D9FFFEC7FC
+D9003F13F80203138031317CB03A>I<B812F0A3C6903880003FEE07F816031600A21778
+A21738A3171C1507A31700A25D5D5D91B5FCA3EC803F818181A21707A392C7120EA4171E
+A2173CA2177C17FC16011607163FB812F8A330317EB035>69 D<B812E0A3C6903880007F
+EE0FF016031601A21600A21770A31738A21507A21700A35D5D5D91B5FCA3EC803F818181
+A592C8FCACB612C0A32D317EB033>I<B6D8807FB512C0A3C60180C7387FC000B391B7FC
+A30280C7127FB3A3B6D8807FB512C0A33A317EB03F>72 D<B61280A3C6EB8000B3B3A7B6
+1280A319317EB01E>I<017FB512C0A39039001FF000B3AF121C123E127FEAFF80A25D14
+3FD87F005B007E5C003C49C7FC381F01FE3807FFF8C613C022317DB02A>I<B6D88003B5
+FCA3C60180C7EA1F80051EC7FC5F5F5FEE01C0EE07804CC8FC161E5E5E16E0ED03C04B5A
+4BC9FC151E153E157F5D02837F02877F91388F7FE0EC9E3F9138BC1FF002F07F4A6C7EEC
+C0074A6C7E826F7F81707E83163F707E707E831607707E83707F8284B6D8801FEBFF80A3
+39317EB03F>I<B67EA3000190C9FCB3A9EE0380A416071700A25EA35E5E5E5E4B5A150F
+B7FCA329317DB030>I<90391FF8018090B51203000314C73907F007EF390F8000FF48C7
+127F003E141F150F5A150712FCA215037EA26C91C7FC13C0EA7FF0EBFF806C13F8ECFF80
+6C14F06C806C806C14FFC6FC013F1480010114C0D9001F13E01401EC003FED1FF0150F15
+07126000E01403A316E07EA26CEC07C07EB4EC0F8001C0EB1F00D8FBFC13FE00F1B512F8
+D8E03F5BD8C003138024317CB02D>83 D<007FB8FCA39039C00FF801D87E00EC003F007C
+82007882A200708200F01780A3481603A5C792C7FCB3AA017FB6FCA331307DAF38>I<B6
+D88003B51280A3C60180C73807C000715AB3AE137F4DC7FC80013F150EA26D6C5C6D6C5C
+6D6C5C6D6C495A903A00FF801FC0023FB55A020F49C8FC020013E039317EB03E>I<B500
+FC91B5FCA3000390C8EA03C06C17806E14076C170080017F150EA26E141E013F151C6E14
+3C011F153880010F5D8001075DA26E130101035D6E13036D5D15806D4AC7FCA26F5A027F
+130EEDE01E023F131CEDF03C021F133815F8020F5BA2EDFCF002075B15FF6E5BA26E5BA2
+6E90C8FCA3157EA2153CA238317EB03D>I<EBFFF0000313FF390F803F809038C00FE048
+6C6C7EA26E7ED80FC07FEA0780C7FCA414FF131FEBFFE33803FC03EA0FF0EA1FC0123FEA
+7F80A2EAFF00A31407A2387F800D393FC01DFE3A1FE078FFF03907FFE07FC6EB803F2420
+7E9F27>97 D<EA01F812FFA3120F1207ADEC3FE0ECFFFC9038FBE07F9039FF001F8049EB
+0FC04914E049EB07F016F8A2ED03FCA316FEA816FCA3ED07F8A216F06DEB0FE06D14C001
+E7EB3F809039C3C0FE00903880FFF89038003FC027327EB12D>I<EB0FFF017F13C03901
+FC01F03803F0033907E007F8120FEA1FC0003FEB03F0EC01E04848C7FCA312FFA8127FA3
+6C6C131CA2001F14386C7E000714703903F001E03901FC07C039007FFF00EB0FF81E207D
+9F24>I<ED0FC0EC07FFA3EC007F153FADEB07F8EB3FFF9038FE07BF3903F801FF3907E0
+007F120F4848133F123FA2485AA312FFA8127FA36C7EA2121F6C6C137F000714FF2603F0
+0313E03A01FC0F3FFE38007FFEEB0FF027327DB12D>I<EB0FFC90387FFF803901FC0FC0
+3903F003E03907E001F0000F14F8391FC000FC003F14FEA24848137E157FA212FFA290B6
+FCA20180C7FCA4127FA36C6C1307121F150E6C7E6C6C131C6C6C13783900FE03E090383F
+FFC0903807FE0020207E9F25>I<EB01FE90380FFF8090381FC3C090387F07E09038FE0F
+F0120113FC1203EC07E0EC018091C7FCA8B512FCA3D803FCC7FCB3A8387FFFF0A31C327E
+B119>I<90391FF007C09039FFFE3FE03A01F83F79F03907E00FC3000F14E19039C007E0
+E0001FECF000A2003F80A5001F5CA2000F5CEBE00F00075C2603F83FC7FC3806FFFE380E
+1FF090C9FC121EA2121F7F90B57E6C14F015FC6C806C801680000F15C0003FC7127F007E
+EC1FE0007C140F00FC1407A4007EEC0FC0003E1580003F141FD80FC0EB7E003907F803FC
+0001B512F0D8001F90C7FC242F7E9F28>I<EA01F812FFA3120F1207ADEC07F8EC3FFEEC
+783F02C013809039F9801FC0EBFB0001FE14E05BA35BB3B500C3B5FCA328327DB12D>I<
+EA03C0487E487E487EA46C5A6C5A6C5AC8FCA9EA01F8127FA31207B3A7B51280A311337D
+B217>I<EA01F812FFA3120F1207B3B3A6B512C0A312327DB117>108
+D<2703F007F8EB1FE000FFD93FFEEBFFF8913A783F01E0FC02C090388300FE280FF1801F
+C6137F2607F30013CC01F602F8148001FC5CA3495CB3B500C3B5380FFFFCA33E207D9F43
+>I<3903F007F800FFEB3FFEEC783F02C013803A0FF1801FC03807F30001F614E013FCA3
+5BB3B500C3B5FCA328207D9F2D>I<EB07FC90387FFFC03901FC07F03903F001F848486C
+7E4848137E001F147F003F158049133F007F15C0A300FF15E0A8007F15C0A36C6CEB7F80
+A2001F15006C6C13FE00075C3903F803F83901FE0FF039007FFFC0D907FCC7FC23207E9F
+28>I<3901F83FE000FFEBFFFC9038FBE07F9039FF003F80D807FEEB1FC049EB0FE04914
+F0ED07F8A216FC1503A216FEA816FC1507A216F8A2ED0FF06D14E06DEB1FC06DEB3F8090
+39FBC0FE009038F8FFF8EC3FC091C8FCABB512C0A3272E7E9F2D>I<3803F03F00FFEB7F
+C09038F1C3E01487390FF30FF0EA07F6A29038FC07E0EC03C091C7FCA25BB2B512E0A31C
+207E9F21>114 D<3801FF86000713FEEA1F00003C133E48131E140E12F8A36C90C7FCB4
+7E13FC387FFFC06C13F0806C7F00077F00017FEA003F01001380143F0060131F00E0130F
+A27E15007E6C131E6C131C38FF807838F3FFF038C07F8019207D9F20>I<131CA5133CA3
+137CA213FC120112031207381FFFFEB5FCA2D803FCC7FCB0EC0380A71201EC0700EA00FE
+EB7F0EEB3FFCEB07F0192E7FAD1F>I<D801F8EB07E000FFEB03FFA3000FEB003F000714
+1FB3153FA20003147FA26C6CEBDFF03A00FE039FFF90387FFF1FEB0FFC28207D9F2D>I<
+B5EB1FFCA3D80FF8EB03C0000715806D1307000315007F0001140E7F6C5CA2EC803C017F
+1338ECC078013F1370ECE0F0011F5B14F1010F5B14F9903807FB80A214FF6D90C7FCA26D
+5AA26D5AA21478A226207E9F2B>I<3A7FFF807FFCA33A03FC000F006C6C131E6C6C5BEC
+803890387FC078013F5B90381FE1E090380FF3C0ECFF806D90C7FC6D5A13016D7E81815B
+903803DFE09038078FF08190380F07FC90381E03FEEB3C01496C7E4914804848EB7FC000
+03EC3FE026FFFC01B5FCA328207F9F2B>120 D<B5EB1FFCA3D80FF8EB03C0000715806D
+1307000315007F0001140E7F6C5CA2EC803C017F1338ECC078013F1370ECE0F0011F5B14
+F1010F5B14F9903807FB80A214FF6D90C7FCA26D5AA26D5AA21478A21470A214F05C1301
+007C5BEAFE035C49C8FC5BEAFC1EEA787CEA3FF0EA0FC0262E7E9F2B>I
+E /Fi 1 14 df<14FF010713E090381F00F80178131E01E01307D80180EB018048C812C0
+00061560481530A248151848150CA2481506A4481503A900601506A46C150CA26C15186C
+1530A26C15606C15C06C6CEB0180D800E0EB07000178131E011F13F8903807FFE0010090
+C7FC282B7EA02D>13 D E /Fj 64 122 df<49B4FC011F13C090387F81E0EBFC013901F8
+07F01203EA07F0A4EC01C091C8FCA3EC3FF8B6FCA33807F003B3A33A7FFF3FFF80A3212A
+7FA925>12 D<131CA3EB7F803803FFE0000F13F8381F9CFC383E1C1E003C7F007C7F0078
+EB0F8000F8131F143FA312FC00FEEB1F0000FF90C7FCEA7FDC13FCEBFFC06C7F6C7F6C13
+FC7E00017F6C6C7E131F131CEC3F800038131F127C00FE130FA312FC00F8140012705C00
+38131E003C5B381F9CF86CB45A00035BC690C7FC131CA319307CAC22>36
+D<123C127FEAFF80A213C0A3127F123E1200A2EA0180A3EA0300A21206120E5A5A12100A
+157B8813>44 D<B51280A611067F9016>I<121C127FA2EAFF80A3EA7F00A2121C09097B
+8813>I<130E131E137EEA07FE12FFA212F81200B3ABB512FEA317277BA622>49
+D<EBFF80000713F04813FC381E03FE393800FF80007C133F00FE14C06C131F15E0140FA2
+127E003C131FC7FC15C0A2EC3F801500147E5C5C495A495AEB078049C7FC131E4913E013
+705B3901C001C0EA0380EA0600000FB5FC5A5A5AB61280A31B277DA622>I<EB7F803803
+FFF04813FC380F81FE381F007FEA3F80EC3F80A3121F1300C7EA7F00A2147E5C495AEB07
+F0EBFFC0A2EB01F8EB007E801580EC1FC0A215E0A2123C127EB4FCA215C0143F48148000
+7CEB7F00383F01FE6CB45A000713F0C613801B277DA622>I<140FA25C5C5C5C5BA2EB03
+BFEB073F130E131C133C1338137013E0EA01C0EA038012071300120E5A5A5A12F0B612F8
+A3C7EA7F00A890381FFFF8A31D277EA622>I<00181303381F801FEBFFFE5C5C5C14C091
+C7FC001CC8FCA7EB7FC0381DFFF8381F80FC381E003F1208C7EA1F8015C0A215E0A21218
+127C12FEA315C05A0078EB3F80A26CEB7F00381F01FE6CB45A000313F0C613801B277DA6
+22>I<EB07F8EB3FFE90B5FC3901FC07803903F00FC03807C01FEA0F80121F130048EB0F
+8091C7FC127EA3EAFE02EB1FF0EB3FFCEB603EEB801F00FF14809038000FC0A24814E0A4
+127EA4123E003F14C07EEC1F80D80F8013003807E07E6CB45A6C5B38003FC01B277DA622
+>I<1238123E003FB512F0A34814E015C0158015003870000EA25C485B5C5CC6485AA249
+5A130791C7FC5B5B131E133EA2137E137CA213FCA41201A76C5A13701C297CA822>I<EB
+3FC03801FFF04813FC3807C07E48C67E001E7FEC0F80123EA2123F138001C01300EBF01F
+381FFC1E6D5A380FFFF86C13E06C7F6C13FC8000077FD80F0F1380D81E0713C0EA3E0139
+7C007FE0141F48130F14071403A315C0127C007EEB07806CEB0F00381FC03F380FFFFC00
+035B38007FC01B277DA622>I<EB7F803801FFF000077F380FC0FC381F803E48487E007E
+1480A2140F00FE14C0A315E0A5007E131FA26C133F6C132F380F80CF3807FF8F0001130F
+EA0008010013C0A3EC1F80123E127FEC3F00143E147E007E5B383E03F8381FFFE06C1380
+D801FEC7FC1B277DA622>I<121C127FA2EAFF80A3EA7F00A2121CC7FCA9121C127FA2EA
+FF80A3EA7F00A2121C091B7B9A13>I<48B4FC000F13E0381E03F0383801F8387800FC00
+FC13FE7EA3127C003813FCEA0001EB03F8EB07E0EB0FC01480EB1E00A25B1338A25BA790
+C7FCA5137013F8487E487EA36C5A6C5A1370172A7CA920>63 D<EC0780A24A7EA34A7EA2
+4A7EA3EC77F8A2ECF7FC14E3A2903801C1FEA201037F1480A249486C7EA24980010E133F
+A2496D7EA2013FB57EA39039700007F8A201F080491303000181491301A2000381D8FFFE
+013F13FCA32E297EA833>65 D<B612F815FF16C03A03F8001FE0ED0FF0ED07F8150316FC
+A21501A3150316F8A2ED07F0150FED1FC0EDFF8090B5EAFE00EDFFC09039F8000FF0ED03
+F8ED01FC16FE1500A216FFA616FE1501ED03FC1507ED1FF8B712E016C0EDFE0028297DA8
+30>I<91387FE003903907FFFC07011FEBFF0F90397FF00F9F9039FF0001FFD801FC7F48
+48147F4848143F4848141F485A160F485A1607127FA290C9FC5AA97E7F1607123FA26C7E
+160E6C7E6C6C141C6C6C143C6C6C14786CB4EB01F090397FF007C0011FB512800107EBFE
+009038007FF028297CA831>I<B612FCEDFF8016E03A03FC001FF8ED03FCED00FE167FEE
+3F80EE1FC0A2EE0FE0A2EE07F0A417F8AA17F0A3EE0FE0A217C0161FEE3F80EE7F005EED
+03FCED1FF8B75A168003FCC7FC2D297EA834>I<B712E0A33903FC001FED07F01501A215
+001670A3913801C0781638A302031300A2140F90B5FCA3EBFC0F1403A20201130EA3161C
+91C7FCA3163C1638167816F815011503151FB712F0A327297EA82C>I<B712C0A33903FC
+003FED0FE015031501A21500A316F0913801C070A316001403A2140F90B5FCA3EBFC0F14
+03A21401A491C8FCA9B512FCA324297EA82A>I<91387FE003903907FFFC07011FEBFF0F
+90397FF00F9F9039FF0001FFD801FC7F484880484880484880485A82485A82127FA290CA
+FC5AA892B512F87E7F03001300123FA26C7EA26C7E6C7E6C7E6C7E6CB45B90387FF00701
+1FB5129F0107EBFE0F9039007FF0032D297CA835>I<B5D8F00FB5FCA3D803FCC7EA3FC0
+AF90B7FCA301FCC7123FB1B5D8F00FB5FCA330297EA835>I<B512F0A33803FC00B3B1B5
+12F0A314297EA819>I<90B512F8A301001300B3A91218127EB4FCA35C387E01FC007C5B
+383E07F0380FFFE0000390C7FC1D297EA823>I<B500F0EBFFFEA3D803FCC7EA0F00161E
+5E5E16E0ED03C04B5A4BC7FC151E5D15F04A5A4A5A1407140F4A7EEC7FF04A7EEBFDE790
+38FFC3FCEC83FE9038FE01FF497E6F7E826F7E151F6F7E8215076F7E6F7E8281EE7F80B5
+39F00FFFFEA32F297EA835>I<B512FCA3D803FCC8FCB3A3ED01C0A415031680A21507A2
+150FA2151F157F913801FF00B7FCA322297EA828>I<D8FFFE92383FFF80A26D5D0003EF
+E000A2D9BF8014EFA2D99FC0EB01CFA2D98FE0EB038FA3D987F0EB070FA2D983F8130EA2
+D981FC131CA3D980FE1338A2027F1370A291383F80E0A391381FC1C0A291380FE380A291
+3807F700A3EC03FEA26E5AA26E5AD8FFFE0203B51280A2157039297DA840>I<D8FFFCEC
+7FFF7F7F00036DEB01C080EBBFE0139F80EB8FF8EB87FCEB83FEEB81FF01801380147F15
+C0EC3FE0EC1FF0EC0FF8EC07FC140315FEEC01FF6E1381ED7FC1ED3FE1ED1FF1150F16F9
+ED07FDED03FF8181167FA2163F161F160F1607D8FFFE14031601A230297EA835>I<ECFF
+C0010F13FC90383F807F9039FE001FC0D801F8EB07E048486D7E48486D7E000F8148486D
+7EA24848147FA2007F168090C8123FA34816C0AA6C16806D147FA2003F1600A26C6C14FE
+A26C6C495A6C6C495A6C6C495A6C6C495A6C6C495A90263FC0FFC7FC90380FFFFC010013
+C02A297CA833>I<B612F815FF16C03A03FC003FE0ED07F0ED03F816FC150116FEA716FC
+150316F8ED07F0ED3FE090B61280EDFE0001FCC8FCB0B512F0A327297EA82E>I<ECFFC0
+010F13FC90383FC0FF9039FE001FC048486D7ED803F0EB03F000078148486D7E48486D7E
+A24848147FA2007F1680A290C8123FA24816C0AA6C16806D147FA2003F1600A26C6C14FE
+143E3A0FE07F81FC00079038C1C1F83A03F18063F0D801F9EB67E0D800FFEB3FC090263F
+C07FC7FC90380FFFFC01004913C0EC003C811601ED1F8316FF6F1380A21700816F5A6F5A
+6F5A2A357CA833>I<B612E015FE6F7E3A03FC003FE0ED0FF06F7E6F7E150182A65E4B5A
+1507ED0FE0ED3FC090B500FEC7FCA29039FC00FF80ED3FC06F7E6F7E6F7EA9170EA21503
+923801FC1CB538F000FEEE7FF8EE0FE02F297EA832>I<9038FF80600003EBF0E0000F13
+F8381F80FD383F001F003E1307481303A200FC1301A214007EA26C140013C0EA7FFCEBFF
+E06C13F86C13FE80000714806C14C0C6FC010F13E0EB007FEC1FF0140F140700E01303A4
+6C14E0A26C13076C14C0B4EB0F80EBE03F39E3FFFE0000E15B38C01FF01C297CA825>I<
+007FB71280A39039807F807FD87C00140F00781507A20070150300F016C0A2481501A5C7
+91C7FCB3A490B612C0A32A287EA72F>I<B500F0EBFFFEA3D803FCC7EA0380B3AA0001ED
+07007F0000150E137F6D143CD91FC05B90390FF003F06DB55A01001480DA1FFCC7FC2F29
+7EA834>I<B500F0EB7FFFA3D803FEC7EA01C00001ED0380A26D14076C16006E5B017F14
+0E80013F5CA26E133C011F14386E1378010F14708001075CA26D6C485AA2ECFE0301015C
+ECFF076D91C7FC1587EC7F8EA215DEEC3FDC15FC6E5AA26E5AA36E5AA26E5AA230297FA8
+33>I<B53CE07FFFE01FFFC0A32803FC0003FCC7EA7000A26D6D7E000160A26D6E13016C
+604B138002801503017F5F4B13C0D93FC0013F49C7FCA2913AE00E1FE00F011F160E17F0
+9126F01C0F131E010F161C033C13F8902707F838075BA2037813FC902703FC70035BA291
+3AFEE001FEF001015E02FF14FF4B7E6D5EA26E486D5AA36EC76CC8FCA2023E80021E141E
+A242297FA845>I<B500F0EB3FFFA3D803FEC7EA03C06C6C15806C6DEB07005E6D6C130E
+6E5B013F143C6D6C13386E5B010F14F06D6C5B6E485A01031303D901FF5B0387C7FC6D13
+8FEC7FCE15FC143F6E5A5D140FAE0103B512C0A330297FA833>89
+D<EAFFE0A4EAF000B3B3B0EAFFE0A40B3C7AAC13>91 D<3803FF80000F13F0381F01FC38
+3F80FE147F801580EA1F00C7FCA4EB3FFF3801FC3FEA0FE0EA1F80EA3F00127E5AA4145F
+007E13DF393F839FFC381FFE0F3803FC031E1B7E9A21>97 D<EAFFE0A3120FACEBE1FE90
+38EFFF809038FE07E09038F803F09038F001F89038E000FCA2157EA2157FA8157EA315FC
+A29038F001F89038F803F090389C0FE090380FFF80390E01FC00202A7EA925>I<EB3FF0
+3801FFFC3803F03E380FC07FEA1F80EA3F00A248133E007E90C7FCA212FEA7127EA2127F
+6CEB03801380001FEB0700380FE00E3803F83C3801FFF838003FC0191B7E9A1E>I<EC7F
+F0A31407ACEB3F873801FFF73807F03F380FC00F381F8007EA3F00A2127EA312FEA8127E
+A27EA2381F800F380FC01F3907E07FFF3801FFE738007F87202A7EA925>I<EB3FC03801
+FFF03803E07C380F803E001F7F130048EB0F80127E15C0A200FE1307A2B6FCA248C8FCA3
+127EA2127F6CEB01C07E390F8003803907C007003803F01E3800FFFCEB3FE01A1B7E9A1F
+>I<EB07F8EB3FFCEB7E3E3801FC7FEA03F813F01207143E1400A7B512C0A33807F000B3
+A3387FFF80A3182A7EA915>I<9038FF80F00003EBE3F8390FC1FE1C391F007C7C48137E
+003EEB3E10007EEB3F00A6003E133E003F137E6C137C380FC1F8380BFFE00018138090C8
+FC1238A2123C383FFFF814FF6C14C06C14E06C14F0121F383C0007007CEB01F8481300A4
+007CEB01F0A2003FEB07E0390FC01F806CB5120038007FF01E287E9A22>I<EAFFE0A312
+0FAC147E9038E1FF809038E30FC001E413E0EBE80701F813F013F0A213E0B039FFFE3FFF
+A3202A7DA925>I<1207EA0F80EA1FC0EA3FE0A3EA1FC0EA0F80EA0700C7FCA7EAFFE0A3
+120FB3A3EAFFFEA30F2B7EAA12>I<EAFFE0A3120FACEC1FFCA3EC0780EC0F00141E5C5C
+14E0EBE3C013E7EBEFE0EBFFF08013F3EBE1FCEBC0FE147FA2EC3F80EC1FC0EC0FE0A2EC
+07F039FFFC1FFFA3202A7FA923>107 D<EAFFE0A3120FB3B2EAFFFEA30F2A7EA912>I<26
+FFC07FEB1FC0903AC1FFC07FF0903AC307E0C1F8D80FC49038F101FC9039C803F20001D8
+01FE7F01D05BA201E05BB03CFFFE3FFF8FFFE0A3331B7D9A38>I<38FFC07E9038C1FF80
+9038C30FC0D80FC413E0EBC80701D813F013D0A213E0B039FFFE3FFFA3201B7D9A25>I<
+EB3FE03801FFFC3803F07E390FC01F80391F800FC0393F0007E0A2007EEB03F0A300FE14
+F8A8007E14F0A26CEB07E0A2391F800FC0390FC01F803907F07F003801FFFC38003FE01D
+1B7E9A22>I<38FFE1FE9038EFFF809038FE0FE0390FF803F09038F001F801E013FC1400
+15FEA2157FA8157E15FEA215FC140101F013F89038F807F09038FC0FE09038EFFF809038
+E1FC0001E0C7FCA9EAFFFEA320277E9A25>I<38FFC1F0EBC7FCEBC63E380FCC7F13D813
+D0A2EBF03EEBE000B0B5FCA3181B7F9A1B>114 D<3803FE30380FFFF0EA3E03EA780012
+7000F01370A27E00FE1300EAFFE06CB4FC14C06C13E06C13F0000713F8C6FCEB07FC1300
+00E0137C143C7E14387E6C137038FF01E038E7FFC000C11300161B7E9A1B>I<13E0A412
+01A31203A21207120F381FFFE0B5FCA2380FE000AD1470A73807F0E0000313C03801FF80
+38007F0014267FA51A>I<39FFE07FF0A3000F1307B2140FA2000713173903F067FF3801
+FFC738007F87201B7D9A25>I<39FFFC03FFA3390FF000F0000714E07F0003EB01C0A2EB
+FC0300011480EBFE070000140013FFEB7F0EA2149EEB3F9C14FC6D5AA26D5AA36D5AA26D
+5AA2201B7F9A23>I<3BFFFC7FFC1FFCA33B0FE00FE001C02607F007EB0380A201F8EBF0
+0700031600EC0FF801FC5C0001150EEC1FFC2600FE1C5B15FE9039FF387E3C017F1438EC
+787F6D486C5A16F0ECE01F011F5CA26D486C5AA2EC800701075CA22E1B7F9A31>I<39FF
+FC1FFEA33907F003803803F8079038FC0F003801FE1E00005BEB7F3814F86D5A6D5A130F
+806D7E130F497EEB3CFEEB38FFEB787F9038F03F803901E01FC0D803C013E0EB800F39FF
+F03FFFA3201B7F9A23>I<39FFFC03FFA3390FF000F0000714E07F0003EB01C0A2EBFC03
+00011480EBFE070000140013FFEB7F0EA2149EEB3F9C14FC6D5AA26D5AA36D5AA26D5AA2
+5CA21307003890C7FCEA7C0FEAFE0E131E131C5BEA74F0EA3FE0EA0F8020277F9A23>I
+E /Fk 91 127 df<127012F8B012701200A5127012F8A31270051C779B18>33
+D<EA4010EAE038EAF078EAE038AAEA60300D0E7B9C18>I<EA0306EA078FA6387FFFC0B5
+12E0A26C13C0380F1E00A6387FFFC0B512E0A26C13C0381E3C00A6EA0C18131C7E9B18>
+I<13C01201A3EA03F0EA0FFCEA3FFEEA7DCFEA71C738E1C38013C7A338F1C0001279123F
+6C7EEA0FF8EA01FC13DE13CF13C73861C38012F1A212E1EBC7001271EA79DEEA3FFEEA1F
+F8EA07E0EA01C0A3120011247D9F18>I<EA3803387C0780A2EAEE0F1400A25B131EA213
+3EEA7C3CA2EA387CEA0078A213F85B12015BA212035BA21207EB8380EB87C0120FEB0EE0
+A2121F121EA2123E383C07C0A23818038013247E9F18>I<EA01C0EA07E0487EEA0E7048
+7EA4EB73F813F313E3380FC1C0EBC38013831303381F0700EA3F87EA7B8EEA71CEEAE1FC
+12E0137CEB7870A2EA70FE387FFFE0EA3FC7380F03C0151C7F9B18>I<1238127CA2127E
+123E120EA3121CA2123812F812F012C0070E789B18>I<137013F0EA01E0EA03C0EA0780
+EA0F00121E121C5AA25AA45AA81270A47EA27E121E7EEA0780EA03C0EA01F0120013700C
+24799F18>I<126012F012787E7E7EEA07801203EA01C0A2EA00E0A41370A813E0A4EA01
+C0A2EA03801207EA0F00121E5A5A5A12600C247C9F18>I<EA01C0A4EA41C138F1C780EA
+FDDF387FFF00EA1FFCEA07F0A2EA1FFCEA7FFF38FDDF80EAF1C73841C100EA01C0A41114
+7D9718>I<136013F0A7387FFFC0B512E0A26C13C03800F000A7136013147E9718>I<121C
+123E127E127F123F121F1207120E121E127C12F81260080C788518>I<387FFFC0B512E0
+A26C13C013047E8F18>I<1230127812FCA2127812300606778518>I<1303EB0780A2130F
+14005B131EA2133E133C137C1378A213F85B12015B12035BA212075B120F90C7FCA25A12
+1E123E123CA2127C127812F85AA2126011247D9F18>I<EA01F0EA07FC487EEA1F1FEA1C
+0738380380007813C0EA7001A238E000E0A9EAF001007013C0A2EA780300381380381C07
+00EA1F1FEA0FFE6C5AEA01F0131C7E9B18>I<EA01801203A21207120F123F12FF12FB12
+431203B0EA7FFCEAFFFEEA7FFC0F1C7B9B18>I<EA03F0EA0FFEEA3FFF387C0F80387003
+C0EAE00138F000E0A21260C7FCA2EB01C0A21303EB0780EB0F00131E5B5B5B485AEA07C0
+485A381E00E05AEA7FFFB5FC7E131C7E9B18>I<EA07F8EA1FFE487E38780780EB03C013
+0112301200EB0380A2EB0F00EA03FF5B7F38000780EB03C01301EB00E0A312F0A2EB01C0
+1303387C0780383FFF006C5AEA03F8131C7E9B18>I<131F5B1377A213E7120113C7EA03
+8712071307120E121E123C1238127812F0B512F8A338000700A6EB7FF0A3151C7F9B18>
+I<383FFF80A30038C7FCA8EA3BF8EA3FFE7F383C0780383003C0EA0001EB00E0A2126012
+F0A238E001C0EA7003387C0F80383FFF00EA1FFCEA03F0131C7E9B18>I<137E48B4FC00
+071380380F83C0EA1E03121C3838018090C7FC5AA2EAE1F8EAE7FEB5FC38FE078038F803
+C0EAF001EB00E05A7E1270A3383801C0EA3C03381E0780380FFF006C5AEA01F8131C7E9B
+18>I<12E0B512E0A214C038E00380EB0700C65A131E131C5BA25B13F05BA2485AA3485A
+A448C7FCA7131D7E9C18>I<1230127812FCA2127812301200A81230127812FCA2127812
+300614779318>58 D<1218123C127EA2123C12181200A81218123C127EA2123E121E120E
+121C123C127812F01260071A789318>I<14C0EB03E01307EB1FC0EB3F80EBFE00485AEA
+07F0485AEA3F8048C7FC12FCA2127F6C7EEA0FE06C7EEA01FC6C7EEB3F80EB1FC0EB07E0
+1303EB00C013187E9918>I<387FFFC0B512E0A3C8FCA4B512E0A36C13C0130C7E9318>I<
+126012F87E127F6C7EEA0FE06C7EEA01FC6C7EEB3F80EB1FC0EB07E0A2EB1FC0EB3F80EB
+FE00485AEA07F0485AEA3F8048C7FC12FC5A126013187E9918>I<EA0FF0EA3FFC48B4FC
+EA700F38F00380A2EA600738000F00133E5BEA01F05B485AA55BC8FCA5EA0380487EA36C
+5A111C7D9B18>I<137CEA01FEEA07FF380F8780381E03C0EA3C1DEA387F3870FFE0EA71
+E313C112E1EAE380A638E1C1C0127113E33870FF8038387F00EA3C1C381E00E0EA0F8338
+07FFC00001138038007E00131C7E9B18>I<137013F8A213D8A2EA01DCA3138CEA038EA4
+EA0707A5380FFF80A3EA0E03381C01C0A3387F07F000FF13F8007F13F0151C7F9B18>I<
+EA7FFCB5FC6C1380381C03C01301EB00E0A4130114C01307381FFF80140014C0EA1C03EB
+00E014F01470A414F014E01303387FFFC0B51280387FFE00141C7F9B18>I<EBF8E0EA03
+FEEA07FFEA0F07EA1E03EA3C01EA38005AA214005AA8127014E0A27E123C381E01C0EA0F
+073807FF803803FE00EA00F8131C7E9B18>I<EA7FF8EAFFFE6C7E381C0F80EB03C0A2EB
+01E01300A214F01470A814F014E0A2130114C01303EB0F80387FFF00485AEA7FF8141C7F
+9B18>I<B512F0A3381C0070A41400A2130EA3EA1FFEA3EA1C0EA390C7FCA21438A5B512
+F8A3151C7F9B18>I<B512F8A3381C0038A41400A21307A3EA1FFFA3EA1C07A390C7FCA7
+EAFFC0A3151C7F9B18>I<3801F1C0EA03FDEA0FFFEA1F0FEA1C03123813011270A290C7
+FC5AA5EB0FF0131F130F387001C0A213031238A2EA1C07EA1F0FEA0FFFEA03FDEA01F114
+1C7E9B18>I<387F07F038FF8FF8387F07F0381C01C0A9EA1FFFA3EA1C01AA387F07F038
+FF8FF8387F07F0151C7F9B18>I<EA7FFFB512806C1300EA01C0B3A4EA7FFFB512806C13
+00111C7D9B18>I<387F07F038FF87F8387F07F0381C03C0EB07801400130E131E5B1338
+5B13F0121DA2EA1FB8A2131C121EEA1C0EA27FA2EB0380A2EB01C0387F03F038FF87F838
+7F03F0151C7F9B18>75 D<EAFFC0A3001CC7FCB114E0A5B5FCA3131C7E9B18>I<38FC01
+F8EAFE03A2383B06E0A4138EA2EA398CA213DCA3EA38D8A213F81370A21300A638FE03F8
+A3151C7F9B18>I<387E07F038FF0FF8387F07F0381D81C0A313C1121CA213E1A3136113
+71A213311339A31319A2131D130DA3EA7F07EAFF87EA7F03151C7F9B18>I<EA0FFE383F
+FF804813C0EA7803EA700100F013E0EAE000B0EAF001007013C0EA7C07EA7FFF6C138038
+0FFE00131C7E9B18>I<EAFFFEEBFF8014C0EA1C03EB01E013001470A514E01301EB03C0
+EA1FFF1480EBFE00001CC7FCA8B47EA3141C7F9B18>I<EA0FFE383FFF804813C0EA7803
+EA700100F013E0EAE000AE1370A2EAF079387039C0EA783FEA7FFF6C1380380FFE00EA00
+0FEB0780A2EB03C01301A213227E9B18>I<EA7FF8EAFFFE6C7E381C0F80130314C01301
+A313031480130F381FFF005BA2EA1C0F7FEB0380A5149CA3387F01F8EAFF81387F00F016
+1C7F9B18>I<3803F1C0EA1FFF5AEA7C0FEA7003EAE001A390C7FC12701278123FEA1FF0
+EA07FEC67EEB0F80EB03C01301EB00E0A2126012E0130100F013C038F80780B5FCEBFE00
+EAE7F8131C7E9B18>I<387FFFF8B5FCA238E07038A400001300B2EA07FFA3151C7F9B18>
+I<38FF83FEA3381C0070B36C13E0EA0F01380783C03803FF806C1300EA007C171C809B18
+>I<38FE03F8EAFF07EAFE03383C01E0001C13C0A3EA1E03000E1380A438070700A4EA03
+8EA4EA018C13DCA3EA00D813F8A21370151C7F9B18>I<38FE03F8A338700070A36C13E0
+A513F8EA39FC13DCA2001913C0A3138CA2EA1D8DA31305000D1380EA0F07A2EA0E03151C
+7F9B18>I<387F0FE0139F130F380E0700120FEA070E138EEA039C13DCEA01F8A212005B
+137013F07F487E13DCEA039E138EEA070F7F000E13801303001E13C0387F07F000FF13F8
+007F13F0151C7F9B18>I<38FE03F8EAFF07EAFE03381C01C0EA1E03000E1380EA0F0700
+071300A2EA038EA2EA01DCA3EA00F8A21370A9EA01FC487E6C5A151C7F9B18>I<383FFF
+E05AA2387001C01303EB07801400C65A131E131C133C5B137013F0485A5B1203485A90C7
+FC5A001E13E0121C123C5A1270B5FCA3131C7E9B18>I<EAFFF8A3EAE000B3ACEAFFF8A3
+0D24779F18>I<126012F0A27E1278127C123CA2123E121E121F7EA27F12077F1203A27F
+12017F12007F1378A2137C133C133E131EA2131F7F14801307A2EB030011247D9F18>I<
+EAFFF8A3EA0038B3ACEAFFF8A30D247F9F18>I<EA0180EA07C0EA1FF0EA7EFCEAF83EEA
+E00E0F067C9B18>I<387FFFC0B512E0A26C13C013047E7F18>I<1206121E123E12381270
+A212E0A312F812FC127CA21238070E789E18>I<EA0FF0EA1FFC487EEA3C0FEA18073800
+0380A213FF1207121FEA7F03127812E0A3EAF007EA780F383FFFF8EA1FFDEA07F015147E
+9318>I<127E12FE127E120EA5133EEBFF80000F13C0EBC1E01380EB0070120E1438A600
+0F1370A2EB80E013C1EBFFC0000E138038063E00151C809B18>I<EA01FEEA07FF001F13
+80EA3E073838030048C7FCA25AA61270EB01C01238EA3E03381FFF8000071300EA01FC12
+147D9318>I<EB1F80133F131F1303A5EA03E3EA0FFBEA1FFFEA3C1FEA380FEA70071303
+12E0A6EA7007A2EA380FEA3C1F381FFFF0380FFBF83803E3F0151C7E9B18>I<EA01F0EA
+07FCEA1FFEEA3E0F38380780EA7003A238E001C0A2B5FCA300E0C7FC1270EB01C01238EA
+3E07381FFF8000071300EA01F812147D9318>I<EB1F80EB7FC0EBFFE013E13801C0C014
+00A3387FFFC0B5FCA23801C000AEEA7FFFA3131C7F9B18>I<3801E1F03807FFF85A381E
+1E30381C0E00487EA5EA1C0EEA1E1EEA1FFC5BEA39E00038C7FC7EEA1FFEEBFFC04813E0
+387801F038700070481338A4007813F0EA7E03381FFFC06C13803801FC00151F7F9318>
+I<127E12FE127E120EA5133EEBFF80000F13C013C1EB80E01300120EAB387FC7FC38FFE7
+FE387FC7FC171C809B18>I<EA0380EA07C0A3EA0380C7FCA4EA7FC012FF127F1201AEB5
+FCA3101D7C9C18>I<1338137CA313381300A4EA0FFCA3EA001CB3A4EA6038EAF078EAFF
+F0EA7FE0EA3F800E277E9C18>I<127E12FE127E120EA5EB3FF0A3EB0780EB0F00131E5B
+5B5BEA0FF87F139C130EEA0E0F7FEB038014C0387FC7F812FF127F151C7F9B18>I<EAFF
+C0A31201B3A4B51280A3111C7D9B18>I<38F9C1C038FFF7F013FF383E3E38EA3C3CA2EA
+3838AB38FE3E3EEB7E7EEB3E3E1714809318>I<EA7E3E38FEFF80007F13C0EA0FC1EB80
+E01300120EAB387FC7FC38FFE7FE387FC7FC1714809318>I<EA01F0EA0FFE487E383E0F
+80EA3803387001C0A238E000E0A5EAF001007013C0EA7803383C0780EA3E0F381FFF006C
+5AEA01F013147E9318>I<EA7E3E38FEFF80007F13C0380FC1E01380EB0070120E1438A6
+000F1370A2EB80E013C1EBFFC0000E1380EB3E0090C7FCA7EA7FC0487E6C5A151E809318
+>I<3801F380EA07FBEA1FFFEA3E1FEA380FEA7007A2EAE003A6EA7007A2EA380FEA3C1F
+EA1FFFEA0FFBEA03E3EA0003A7EB1FF0EB3FF8EB1FF0151E7E9318>I<38FF0FC0EB3FE0
+EB7FF0EA07F0EBE060EBC0005BA290C7FCA9EAFFFC7F5B14147E9318>I<EA07F7EA3FFF
+5AEA780FEAE007A3007CC7FCEA7FE0EA1FFCEA03FEEA001F38600780EAE003A212F038F8
+0F00B5FC13FCEAE7F011147D9318>I<487E1203A4387FFFC0B5FCA238038000A9144014
+E0A33801C1C013FF6C1380EB3E0013197F9818>I<387E07E0EAFE0FEA7E07EA0E00AC13
+01EA0F033807FFFC6C13FE3801FCFC1714809318>I<387F8FF000FF13F8007F13F0381C
+01C0380E0380A338070700A3138FEA038EA3EA01DCA3EA00F8A2137015147F9318>I<38
+FF07F8138F1307383800E0A4381C01C0137113F9A213D9EA1DDD000D1380A3138DEA0F8F
+A23807070015147F9318>I<387F8FF0139F138F380F0700EA078EEA039EEA01DC13F812
+00137013F07FEA01DCEA039E138EEA0707000E1380387F8FF000FF13F8007F13F015147F
+9318>I<387F8FF000FF13F8007F13F0380E01C0EB0380A21207EB0700A2EA0387A2138E
+EA01CEA213CC120013DC1378A31370A313F05B1279EA7BC0EA7F806CC7FC121E151E7F93
+18>I<383FFFF05AA2387001E0EB03C0EB078038000F00131E5B13F8485AEA03C0485A38
+0F0070121E5A5AB512F0A314147F9318>I<EB07E0131F137FEB780013E0AB1201EA7FC0
+485AA26C7EEA01E01200AB1378EB7FE0131F130713247E9F18>I<126012F0B3B0126004
+24769F18>I<127CB4FC13C01203C67EAB7FEB7FC0EB3FE0A2EB7FC0EBF0005BABEA03C0
+12FF90C7FC127C13247E9F18>I<EA060CEA1F1EEA3FBEEAFBF8EAF1F0EA60C00F067C9B
+18>I E /Fl 82 124 df<90381F83E09038F06E303901C07878380380F8903800F03048
+EB7000A7B612803907007000B2383FE3FF1D20809F1B>11 D<133FEBE0C0EA01C0380381
+E0EA0701A290C7FCA6B512E0EA0700B2383FC3FC1620809F19>I<EB3FE013E0EA01C1EA
+0381EA0700A8B5FCEA0700B2383FE7FC1620809F19>I<90381F81F89038F04F043901C0
+7C06390380F80FEB00F05A0270C7FCA6B7FC3907007007B23A3FE3FE3FE02320809F26>
+I<127012F8A71270AA1220A51200A5127012F8A3127005217CA00D>33
+D<EA7038EAF87CEAFC7EA2EA743AEA0402A3EA0804A2EA1008A2EA2010EA40200F0E7F9F
+17>I<127012F812FCA212741204A31208A21210A212201240060E7C9F0D>39
+D<13401380EA01005A12061204120C5AA212381230A212701260A412E0AC1260A4127012
+30A212381218A27E120412067E7EEA008013400A2E7BA112>I<7E12407E12307E120812
+0C7EA212077EA213801201A413C0AC1380A412031300A25A1206A25A120812185A12205A
+5A0A2E7EA112>I<127012F012F8A212781208A31210A31220A21240050E7C840D>44
+D<EAFFF0A20C02808A0F>I<127012F8A3127005057C840D>I<144014C0EB0180A3EB0300
+A31306A25BA35BA35BA25BA35BA3485AA348C7FCA21206A35AA35AA25AA35AA35AA2122D
+7EA117>I<EA03F0EA0E1C487EEA1806EA380738700380A400F013C0AD00701380A3EA78
+0700381300EA1806EA1C0E6C5AEA03F0121F7E9D17>I<13801203120F12F31203B3A6EA
+07C0EAFFFE0F1E7C9D17>I<EA03F0EA0C1CEA100E487E00401380128000F013C0EAF803
+A3EA200712001480A2EB0F00130E5B5B5B13605B485A48C7FC000613405A5A00101380EA
+3FFF5AB5FC121E7E9D17>I<EA03F0EA0C1CEA100EEA200F007813801307A2EA380F1200
+1400A2131E131C1370EA07F0EA003C130E130FEB0780A214C0122012F8A300F013801240
+EB0F00EA200EEA183CEA07F0121F7E9D17>I<1306A2130EA2131E132EA2134E138EA2EA
+010E1202A212041208A212101220A2124012C0B512F038000E00A7EBFFE0141E7F9D17>
+I<EA1803EA1FFE5B5B13E00010C7FCA6EA11F0EA161CEA180EEA10071480EA0003A214C0
+A3127012F0A200E013801240EB0700EA20066C5AEA0838EA07E0121F7E9D17>I<137CEA
+0182EA0701380E0380EA0C0712183838030090C7FC12781270A2EAF1F0EAF21CEAF406EA
+F807EB0380A200F013C0A51270A214801238EB07001218EA0C0E6C5AEA01F0121F7E9D17
+>I<1240387FFFE014C0A23840008038800100A21302485AA25B5BA25BA21360A213E05B
+1201A41203A76C5A131F7E9D17>I<EA03F0EA0C0CEA1006EA3003382001801260A31270
+38780300123EEA3F06EA1FC8EA0FF0EA03F8487EEA0C7EEA103F38300F80EA6007EB01C0
+12C01300A31480EA600100201300EA1002EA0C0CEA03F0121F7E9D17>I<EA03F0EA0E18
+487E487E13071270EB038012F0A214C0A5EA7007A21238EA180BEA0E13EA03E338000380
+A3EB07001230EA7806130EEA700CEA2018EA1070EA0FC0121F7E9D17>I<127012F8A312
+701200AA127012F8A3127005147C930D>I<127012F8A312701200AA127012F012F8A212
+781208A31210A31220A21240051D7C930D>I<EA0FE0EA103CEA601EEA400EEAE00F12F0
+A21260EA001E131C13381370136013C01380A2EA0100A6C7FCA5EA0380EA07C0A3EA0380
+10207E9F15>63 D<5B497EA3497EA3EB09E0A3EB10F0A3EB2078A3497EA2EBC03EEB801E
+A248B5FCEB000FA20002EB0780A348EB03C0A2120C001E14E039FF801FFE1F207F9F22>
+65 D<B512E0380F0078141EA2801580A515005C141E147CEBFFF0EB007C141FEC0F80EC
+07C0140315E0A515C014071580EC0F00143EB512F01B1F7E9E20>I<90380FE010903838
+1C309038E002703803C00139078000F048C71270121E15305A1510127C127800F81400A9
+1278007C1410123CA26C1420A27E6C6C13406C6C13803900E00300EB380CEB0FF01C217E
+9F21>I<B512F83807801EEC0780EC03C0EC01E0EC00F015701578A2153CA3153EA8153C
+A2157C1578A215F0EC01E0EC03C0EC0780EC1E00B512F81F1F7F9E23>I<B61280380F00
+0F14031401140015C01540A314401500A214C0130113FF130113001440A3EC0020A31540
+A315C01401EC0380140FB6FC1B1F7E9E1F>I<B61280380780071401A2140015C01540A4
+EC2000A3146014E013FF138014601420A391C7FCA87FEAFFFE1A1F7F9E1E>I<90380FE0
+109038381C309038E002703803C00139078000F048C71270121E15305A1510127C127800
+F81400A7EC3FFEEC01F000781300127C123CA27EA27E6C7E3903C001703900E002309038
+380C1090380FF0001F217E9F24>I<39FFF07FF8390F000780AD90B5FCEB0007AF39FFF0
+7FF81D1F7E9E22>I<EAFFF0EA0F00B3ABEAFFF00C1F7E9E10>I<3807FFC038003E00131E
+B3A3122012F8A3EAF01CEA403CEA6038EA1070EA0FC012207F9E17>I<39FFF007FC390F
+0003E0EC0180150014025C5C5C5C5C5C49C7FC5B497E130FEB13C0EB21E01341EB80F0EB
+0078A28080A280EC0780A2EC03C015E015F039FFF01FFE1F1F7E9E23>I<EAFFF8EA0F80
+90C7FCB21402A414061404A2140C141C147CB512FC171F7E9E1C>I<B46CEB07FE000715
+C0A2D805C0130BA2D804E01313A301701323A26D1343A36D1383A290380E0103A3EB0702
+A3EB0384A2EB01C8A3EB00F0A21460121FD8FFE0EB7FFE271F7F9E2A>I<B4EB0FF8390F
+8003E0EC0080EA0BC0EA09E0A2EA08F01378A27F7FA27FEB0780A2EB03C0EB01E0A2EB00
+F01478A2143C141EA2140F1407A214031401123E38FF80001D1F7E9E22>I<EB1FE0EB70
+383801C00E48487E39070003804814C0001EEB01E048EB00F0A2007C14F8A20078147800
+F8147CA900781478007C14F8A2003C14F0003E1301001E14E06CEB03C06C148039038007
+003801E01E38007038EB1FE01E217E9F23>I<B512E0380F007C141E80EC0780A215C0A4
+1580A2EC0F00141E147CEBFFE090C8FCAEEAFFF01A1F7E9E1F>I<EB1FE0EB70383801C0
+0E48487E39070003804814C0001EEB01E0003E14F0003C1300007C14F8A20078147800F8
+147CA900781478007C14F8A2003C14F0383E0781391E0841E0390F1023C0000714803903
+9017003801D01E3900783804EB1FF8EB001CEC0C0CEC0E1CEC0FF8A2140715F0EC01E01E
+297E9F23>I<B57E380F00F0143C8080A21580A41500A2141E5C14F0EBFF80EB01C0EB00
+70A280143CA3143EA31504143F141FEC0F0839FFF00788C7EA01F01E207E9E21>I<3803
+F040380C0CC0EA1803EA3001EA6000A212E01440A36C13007E127CEA7F80EA3FF86CB4FC
+00071380C613C0EB1FE013031301EB00F014707EA46C136014E06C13C038F8018038C603
+00EA81FC14217E9F19>I<007FB512E038780F010060EB006000401420A200C014300080
+1410A400001400B3497E3803FFFC1C1F7E9E21>I<39FFF00FF8390F0003E0EC0080B3A4
+6CEB01001380120314026C6C5A6C6C5AEB3830EB0FC01D207E9E22>I<39FFF003FE391F
+8000F86CC7126015206C6C1340A36C6C1380A2EBE00100011400A23800F002A213F8EB78
+04A26D5AA36D5AA2131F6D5AA2EB07C0A36D5AA36DC7FC1F207F9E22>I<3BFFF07FF81F
+F03B1F000FC007C06C903907800180170015C001805C00071502EC09E013C000035DEC19
+F01410D801E05CA2EC2078D800F05CA2EC403C01785CA2EC801E017C1460013C14409038
+3D000F133F6D5CA2011E1307010E91C7FCA2010C7F010413022C207F9E2F>I<39FFF001
+FF391F800078000F146012076D1340000314807F3901F001001200EBF802EB7C06EB3C04
+EB3E08131EEB1F10EB0FB0EB07A014E06D5AACEB3FFC201F7F9E22>89
+D<387FFFFE387E003C127800701378006013F814F0384001E0130314C0EB07801200EB0F
+00131EA25B137C13785B1201EBE002EA03C0A2EA0780000F13061300001E1304003E130C
+123C48133C14FCB5FC171F7E9E1C>I<12FFA212C0B3B3A512FFA2082D7CA10D>I<EA0804
+EA1008EA2010A2EA4020A2EA8040A3EAB85CEAFC7EA2EA7C3EEA381C0F0E7A9F17>I<12
+FFA21203B3B3A512FFA2082D80A10D>I<120812101220A21240A21280A312B812FCA212
+7C1238060E7D9F0D>96 D<EA1FE0EA3030EA7818131CEA300E1200A313FEEA078EEA1E0E
+1238127800F01310A3131E127838386720380F83C014147E9317>I<121C12FC121CAA13
+7CEA1D87381E0180EB00C0001C13E01470A21478A6147014F014E0001E13C0381A018038
+198700EA107C15207E9F19>I<EA01FCEA0706EA1C0F123813060078C7FC127012F0A612
+70127800381380A2381C0100EA0706EA01F811147F9314>I<EB01C0130F1301AAEA01F1
+EA070DEA0C03EA180112381278127012F0A61270A21238EA1803120CEA070D3801F1F815
+207F9F19>I<EA03F0EA0E1C487E487EA21270EB038012F0A2B5FC00F0C7FCA31270A26C
+1380A2381C0100EA0706EA01F811147F9314>I<137CEA01C6EA030F1207EA0E061300A7
+EAFFF0EA0E00B2EA7FE01020809F0E>I<14E03803E330EA0E3CEA1C1C38380E00EA780F
+A5EA380E6C5AEA1E38EA33E00020C7FCA21230A2EA3FFE381FFF8014C0383001E0386000
+70481330A4006013606C13C0381C03803803FC00141F7F9417>I<121C12FC121CAA137C
+1386EA1D03001E1380A2121CAE38FF8FF014207E9F19>I<1238127CA31238C7FCA6121C
+12FC121CB1EAFF80091F7F9E0C>I<13E0EA01F0A3EA00E01300A61370EA07F012001370
+B3A31260EAF06013C0EA6180EA3F000C28829E0E>I<121C12FC121CAAEB1FE0EB0780EB
+060013045B5B5B136013E0EA1DF0EA1E70EA1C38133C131C7F130F7F148014C038FF9FF0
+14207E9F18>I<121C12FC121CB3ABEAFF8009207F9F0C>I<391C3E03E039FCC30C30391D
+039038391E01E01CA2001C13C0AE3AFF8FF8FF8021147E9326>I<EA1C7CEAFC86EA1D03
+001E1380A2121CAE38FF8FF014147E9319>I<EA01F8EA070E381C0380383801C0A23870
+00E0A200F013F0A6007013E0A2383801C0A2381C038038070E00EA01F814147F9317>I<
+EA1C7CEAFD87381E018014C0381C00E014F014701478A6147014F014E0381E01C0EB0380
+381D8700EA1C7C90C7FCA8B47E151D7E9319>I<3801F04038070CC0EA0E02EA1C03EA38
+011278127012F0A6127012781238EA1C03EA0C05EA0709EA01F1EA0001A8EB0FF8151D7F
+9318>I<EA1CF0EAFD18EA1E3CA21318EA1C00AEEAFFC00E147E9312>I<EA0FC8EA3038EA
+6018EAC008A3EAE000127CEA3FE0EA1FF0EA07F8EA003CEA800E130612C0A21304EAE00C
+EAD818EA87E00F147F9312>I<1202A31206A2120EA2123EEAFFF8EA0E00AB1304A5EA07
+081203EA01F00E1C7F9B12>I<381C0380EAFC1FEA1C03AE1307120CEA061B3803E3F014
+147E9319>I<38FF83F8383E00E0001C13C06C1380A338070100A21383EA0382A2EA01C4
+A213E4EA00E8A21370A3132015147F9318>I<39FF9FE1FC393C078070391C030060EC80
+20000E1440A214C0D80704138014E0A239038861001471A23801D032143A143E3800E01C
+A2EB6018EB40081E147F9321>I<38FF87F8381E03C0380E0180EB0300EA0702EA0384EA
+01C813D8EA00F01370137813F8139CEA010E1202EA060738040380000C13C0003C13E038
+FE07FC16147F9318>I<38FF83F8383E00E0001C13C06C1380A338070100A21383EA0382
+A2EA01C4A213E4EA00E8A21370A31320A25BA3EAF080A200F1C7FC1262123C151D7F9318
+>I<EA7FFFEA700E1260EA401C133813781370EA00E0120113C0EA038012071301120E12
+1EEA1C03EA3802EA7006130EEAFFFE10147F9314>I<B512FC1601808C17>I
+E /Fm 9 118 df<B87E17F817FF8428007FE0000313E004007FEF3FF8717EA2717EA284
+83A64D5AA34D5A4D5A60EFFFE04C5B040F90C7FC91B612FCA2EFFF8002E0C713E0EF3FF8
+EF0FFC84717E711380A27113C0A219E0A819C05F19805F4D13004D5A4D5A4CB45AB95A18
+C095C7FC17F03B3B7CBA45>66 D<B912C0A43A007FF000079338007FE0173F170F1707A2
+1703A21701A418F0EE7800A41800A216F8A21501150791B5FCA4ECF00715011500A21678
+A693C8FCAEB612FEA4343B7CBA3D>70 D<EB3FFE48B512E0000714F8390FE007FC9038F0
+01FE486C6C7E6F7E82153F6C48806C5A6C5AC8FCA491B5FC131F90387FF83F3803FF8038
+07FC00EA0FF0485A123F485AA2485AA4157F6C7E15DF3A3FE0039FF03B1FF80F0FFFE038
+07FFFE0001497E39003FE0002B267DA52F>97 D<49B47E010F13F0017F13FC9038FF81FE
+3A03FE007F80D807F8133F4848EB1FC0ED0FE0485A003F15F01507485A16F8A212FFA290
+B6FCA301C0C8FCA4127FA36C7E1678121F7F000F15F06C6C13016C6CEB03E06C6CEB0FC0
+3A00FFC07F8090393FFFFE00010F13F8010013C025267DA52C>101
+D<13FE12FFA412071203B0EDFF80020313F0020F7F91381E03FC91383801FE02607F4A7E
+01FF15805C91C7FCA35BB3A4B5D8F83F13FEA42F3C7CBB36>104
+D<3901FC03F000FFEB0FFC4AB4FC91383C3F80EC707F00079038E0FFC000035BEBFD80A2
+01FFEB7F809138003F00151E92C7FC5BB3A3B512FCA422267DA528>114
+D<90383FF0383903FFFE7848EBFFF8381FC00F383F0003003E13005A157812FCA27E6C14
+0013C013FC387FFFF06C13FEECFF806C14C06C14E0000314F0C614F8011F13FCEB007FEC
+07FE0070130100F01300157E7EA27E157C6C14FC6C14F890388001F09038F00FE000F9B5
+12C0D8F07F130038C01FF81F267DA526>I<130FA55BA45BA25BA25B5A5A5A001FEBFFF0
+B6FCA3000190C7FCB3153CA86C14781480017F13F090383FC1E090381FFFC06D13809038
+01FE001E377EB626>I<01FEEC3F8000FFEC3FFFA400071401000380B3A45DA25D120115
+066C6C4913C090267F807813FE6DB45A6D5B010313802F267CA536>I
+E end
+TeXDict begin
+
+1 0 bop 0 1176 a Fm(Bash)32 b(F)-8 b(eatures)p 0 1210
+1950 17 v 1261 1258 a Fl(Ov)o(erview)16 b(Do)q(cumen)o(tation)f(for)g
+(Bash)1244 1312 y(Edition)h(1.14,)d(for)i Fk(bash)g Fl(V)l(ersion)h
+(1.14.)1701 1366 y(August)f(1994)0 2467 y Fj(Brian)23
+b(F)-6 b(o)n(x,)23 b(F)-6 b(ree)23 b(Soft)n(w)n(are)f(F)-6
+b(oundation)0 2534 y(Chet)22 b(Ramey)-6 b(,)23 b(Case)e(W)-6
+b(estern)23 b(Reserv)n(e)f(Univ)n(ersit)n(y)p 0 2570
+1950 9 v eop
+2 1 bop 0 2661 a Fl(Cop)o(yrigh)o(t)226 2660 y(c)214
+2661 y Fi(\015)15 b Fl(1991,)f(1993)g(F)l(ree)h(Soft)o(w)o(are)f(F)l
+(oundation,)h(Inc.)p eop
+1 2 bop 0 -58 a Fl(Chapter)15 b(1:)k(Bourne)d(Shell)h(St)o(yle)f(F)l
+(eatures)1143 b(1)0 183 y Fh(1)41 b(Bourne)15 b(Shell)e(St)n(yle)h(F)-7
+b(eatures)62 369 y Fl(Bash)20 b(is)g(an)g(acron)o(ym)f(for)g(Bourne)i
+(Again)f(SHell.)35 b(The)20 b(Bourne)h(shell)g(is)f(the)g(traditional)h
+(Unix)f(shell)0 432 y(originally)f(written)f(b)o(y)f(Stephen)i(Bourne.)
+27 b(All)19 b(of)e(the)h(Bourne)f(shell)j(builtin)f(commands)f(are)f(a)
+o(v)m(ailable)i(in)0 494 y(Bash,)g(and)f(the)g(rules)h(for)e(ev)m
+(aluation)j(and)e(quoting)g(are)g(tak)o(en)g(from)f(the)h(P)o(osix)g
+(1003.2)f(sp)q(eci\014cation)j(for)0 556 y(the)15 b(`standard')f(Unix)i
+(shell.)62 693 y(This)g(section)f(brie\015y)h(summarizes)f(things)g
+(whic)o(h)h(Bash)f(inherits)h(from)e(the)g(Bourne)i(shell:)21
+b(shell)16 b(con)o(trol)0 755 y(structures,)i(builtins,)i(v)m
+(ariables,)g(and)e(other)g(features.)27 b(It)18 b(also)g(lists)h(the)f
+(signi\014can)o(t)h(di\013erences)g(b)q(et)o(w)o(een)0
+818 y(Bash)c(and)h(the)f(Bourne)h(Shell.)0 1041 y Fj(1.1)33
+b(Lo)r(oping)15 b(Constructs)62 1178 y Fl(Note)g(that)g(wherev)o(er)h
+(y)o(ou)f(see)h(a)f(`)p Fk(;)p Fl(')g(in)h(the)g(description)h(of)e(a)g
+(command's)g(syn)o(tax,)g(it)h(ma)o(y)e(b)q(e)j(replaced)0
+1240 y(indiscriminately)h(with)e(one)f(or)g(more)g(newlines.)62
+1377 y(Bash)h(supp)q(orts)f(the)g(follo)o(wing)h(lo)q(oping)g
+(constructs.)0 1527 y Fk(until)120 b Fl(The)15 b(syn)o(tax)g(of)g(the)g
+Fk(until)f Fl(command)h(is:)360 1589 y Fk(until)23 b
+Fg(test-commands)r Fk(;)g(do)h Fg(consequen)o(t-commands)r
+Fk(;)g(done)240 1663 y Fl(Execute)14 b Fg(consequen)o(t-commands)i
+Fl(as)d(long)h(as)f(the)h(\014nal)h(command)e(in)i Fg(test-commands)g
+Fl(has)e(an)240 1726 y(exit)j(status)e(whic)o(h)i(is)g(not)f(zero.)0
+1813 y Fk(while)120 b Fl(The)15 b(syn)o(tax)g(of)g(the)g
+Fk(while)f Fl(command)h(is:)360 1875 y Fk(while)23 b
+Fg(test-commands)r Fk(;)g(do)h Fg(consequen)o(t-commands)r
+Fk(;)g(done)240 1949 y Fl(Execute)14 b Fg(consequen)o(t-commands)i
+Fl(as)d(long)h(as)f(the)h(\014nal)h(command)e(in)i Fg(test-commands)g
+Fl(has)e(an)240 2011 y(exit)j(status)e(of)h(zero.)0 2098
+y Fk(for)168 b Fl(The)15 b(syn)o(tax)g(of)g(the)g(for)g(command)g(is:)
+360 2160 y Fk(for)23 b Fg(name)k Fk([in)c Fg(w)o(ords)i
+Fk(...];)f(do)f Fg(commands)r Fk(;)h(done)240 2235 y
+Fl(Execute)11 b Fg(commands)g Fl(for)f(eac)o(h)g(mem)o(b)q(er)h(in)g
+Fg(w)o(ords)p Fl(,)f(with)g Fg(name)j Fl(b)q(ound)e(to)f(the)g(curren)o
+(t)g(mem)o(b)q(er.)240 2297 y(If)15 b(\\)p Fk(in)g Fg(w)o(ords)r
+Fl(")f(is)i(not)f(presen)o(t,)f(\\)p Fk(in)h("$@")p Fl(")f(is)i
+(assumed.)0 2521 y Fj(1.2)33 b(Conditional)16 b(Constructs)0
+2670 y Fk(if)192 b Fl(The)15 b(syn)o(tax)g(of)g(the)g
+Fk(if)g Fl(command)g(is:)p eop
+2 3 bop 0 -58 a Fl(2)1646 b(Bash)15 b(F)l(eatures)360
+183 y Fk(if)24 b Fg(test-commands)r Fk(;)f(then)408 233
+y Fg(consequen)o(t-commands)r Fk(;)360 283 y([elif)g
+Fg(more-test-commands)r Fk(;)g(then)408 333 y Fg(more-consequen)o(ts)r
+Fk(;])360 382 y([else)g Fg(alternate-consequen)o(ts)r
+Fk(;])360 432 y(fi)240 508 y Fl(Execute)e Fg(consequen)o(t-commands)h
+Fl(only)f(if)g(the)g(\014nal)g(command)f(in)h Fg(test-commands)h
+Fl(has)e(an)240 570 y(exit)c(status)e(of)h(zero.)20 b(Otherwise,)c(eac)
+o(h)f Fk(elif)g Fl(list)h(is)f(executed)i(in)f(turn,)f(and)g(if)h(its)f
+(exit)h(status)240 633 y(is)g(zero,)f(the)h(corresp)q(onding)h
+Fg(more-consequen)o(ts)g Fl(is)f(executed)h(and)f(the)f(command)h
+(completes.)240 695 y(If)i(\\)p Fk(else)d Fg(alternate-consequen)o(ts)r
+Fl(")j(is)h(presen)o(t,)f(and)h(the)f(\014nal)h(command)f(in)h(the)g
+(\014nal)g Fk(if)e Fl(or)240 757 y Fk(elif)e Fl(clause)h(has)f(a)g
+(non-zero)g(exit)h(status,)e(then)h(execute)h Fg(alternate-consequen)o
+(ts)p Fl(.)0 846 y Fk(case)144 b Fl(The)15 b(syn)o(tax)g(of)g(the)g
+Fk(case)g Fl(command)g(is:)360 910 y Fk(case)23 b Fg(w)o(ord)i
+Fk(in)f([)p Fg(pattern)f Fk([|)h Fg(pattern)p Fk(]...\))f
+Fg(commands)i Fk(;;]...)e(esac)240 986 y Fl(Selectiv)o(ely)c(execute)e
+Fg(commands)h Fl(based)e(up)q(on)h Fg(w)o(ord)h Fl(matc)o(hing)e
+Fg(pattern)p Fl(.)23 b(The)16 b(`)p Fk(|)p Fl(')g(is)h(used)g(to)240
+1048 y(separate)e(m)o(ultiple)i(patterns.)240 1124 y(Here)d(is)h(an)f
+(example)g(using)h Fk(case)e Fl(in)i(a)f(script)g(that)f(could)i(b)q(e)
+g(used)f(to)g(describ)q(e)h(an)f(in)o(teresting)240 1186
+y(feature)h(of)g(an)g(animal:)360 1249 y Fk(echo)23 b(-n)h("Enter)f
+(the)g(name)h(of)f(an)h(animal:)f(")360 1299 y(read)g(ANIMAL)360
+1349 y(echo)g(-n)h("The)f($ANIMAL)g(has)h(")360 1399
+y(case)f($ANIMAL)g(in)408 1448 y(horse)g(|)h(dog)f(|)h(cat\))f(echo)g
+(-n)h("four";;)408 1498 y(man)f(|)h(kangaroo)f(\))g(echo)h(-n)f
+("two";;)408 1548 y(*\))g(echo)h(-n)f("an)h(unknown)f(number)g(of";;)
+360 1598 y(esac)360 1648 y(echo)g("legs.")0 1881 y Fj(1.3)33
+b(Shell)16 b(F)-6 b(unctions)62 2019 y Fl(Shell)20 b(functions)f(are)f
+(a)g(w)o(a)o(y)g(to)f(group)h(commands)g(for)g(later)g(execution)h
+(using)g(a)f(single)i(name)e(for)g(the)0 2082 y(group.)36
+b(They)21 b(are)f(executed)h(just)g(lik)o(e)g(a)g Fk(")p
+Fl(regular)p Fk(")f Fl(command.)36 b(Shell)22 b(functions)g(are)e
+(executed)h(in)h(the)0 2144 y(curren)o(t)15 b(shell)i(con)o(text;)d(no)
+h(new)h(pro)q(cess)f(is)h(created)f(to)g(in)o(terpret)g(them.)62
+2282 y(F)l(unctions)h(are)f(declared)i(using)e(this)h(syn)o(tax:)120
+2407 y Fk([)24 b(function)e(])i Fg(name)j Fk(\(\))c({)h
+Fg(command-list)q Fk(;)h(})62 2545 y Fl(This)16 b(de\014nes)h(a)e
+(function)i(named)e Fg(name)p Fl(.)21 b(The)16 b Fg(b)q(o)q(dy)k
+Fl(of)15 b(the)h(function)g(is)g(the)g Fg(command-list)h
+Fl(b)q(et)o(w)o(een)f Fk({)0 2608 y Fl(and)d Fk(})p Fl(.)19
+b(This)14 b(list)g(is)g(executed)g(whenev)o(er)g Fg(name)i
+Fl(is)d(sp)q(eci\014ed)j(as)c(the)i(name)f(of)g(a)g(command.)19
+b(The)13 b(exit)h(status)0 2670 y(of)h(a)g(function)h(is)f(the)h(exit)f
+(status)g(of)f(the)i(last)f(command)g(executed)h(in)g(the)f(b)q(o)q(dy)
+l(.)p eop
+3 4 bop 0 -58 a Fl(Chapter)15 b(1:)k(Bourne)d(Shell)h(St)o(yle)f(F)l
+(eatures)1143 b(3)62 183 y(When)17 b(a)e(function)i(is)g(executed,)g
+(the)f(argumen)o(ts)f(to)g(the)i(function)f(b)q(ecome)h(the)f(p)q
+(ositional)i(parameters)0 246 y(during)h(its)f(execution.)29
+b(The)18 b(sp)q(ecial)i(parameter)d Fk(#)h Fl(that)f(giv)o(es)h(the)g
+(n)o(um)o(b)q(er)h(of)e(p)q(ositional)i(parameters)e(is)0
+308 y(up)q(dated)f(to)f(re\015ect)g(the)g(c)o(hange.)20
+b(P)o(ositional)c(parameter)e(0)h(is)h(unc)o(hanged.)62
+445 y(If)f(the)g(builtin)i(command)e Fk(return)f Fl(is)h(executed)h(in)
+f(a)g(function,)g(the)g(function)g(completes)h(and)f(execution)0
+507 y(resumes)g(with)h(the)f(next)h(command)f(after)f(the)h(function)i
+(call.)k(When)15 b(a)g(function)h(completes,)g(the)f(v)m(alues)h(of)0
+569 y(the)f(p)q(ositional)h(parameters)e(and)h(the)g(sp)q(ecial)i
+(parameter)d Fk(#)h Fl(are)f(restored)g(to)h(the)g(v)m(alues)h(they)f
+(had)g(prior)g(to)0 632 y(function)h(execution.)0 852
+y Fj(1.4)33 b(Bourne)15 b(Shell)i(Builtins)62 989 y Fl(The)d(follo)o
+(wing)g(shell)h(builtin)g(commands)e(are)g(inherited)i(from)e(the)g
+(Bourne)h(shell.)21 b(These)13 b(commands)g(are)0 1052
+y(implemen)o(ted)k(as)e(sp)q(eci\014ed)i(b)o(y)e(the)g(P)o(osix)h
+(1003.2)d(standard.)0 1200 y Fk(:)216 b Fl(Do)15 b(nothing)g(b)q(ey)o
+(ond)h(expanding)h(an)o(y)d(argumen)o(ts)h(and)g(p)q(erforming)h
+(redirections.)0 1286 y Fk(.)216 b Fl(Read)15 b(and)g(execute)g
+(commands)g(from)f(the)h Fg(\014lename)j Fl(argumen)o(t)c(in)h(the)g
+(curren)o(t)g(shell)h(con)o(text.)0 1371 y Fk(break)120
+b Fl(Exit)15 b(from)g(a)g Fk(for)p Fl(,)f Fk(while)p
+Fl(,)g(or)h Fk(until)f Fl(lo)q(op.)0 1457 y Fk(cd)192
+b Fl(Change)15 b(the)g(curren)o(t)h(w)o(orking)e(directory)l(.)0
+1542 y Fk(continue)48 b Fl(Resume)16 b(the)f(next)h(iteration)f(of)g
+(an)g(enclosing)i Fk(for)p Fl(,)d Fk(while)p Fl(,)g(or)h
+Fk(until)f Fl(lo)q(op.)0 1628 y Fk(echo)144 b Fl(Prin)o(t)15
+b(the)g(argumen)o(ts,)f(separated)h(b)o(y)g(spaces,)h(to)e(the)h
+(standard)g(output.)0 1713 y Fk(eval)144 b Fl(The)17
+b(argumen)o(ts)g(are)f(concatenated)h(together)g(in)o(to)g(a)g(single)h
+(command,)f(whic)o(h)h(is)g(then)f(read)240 1776 y(and)e(executed.)0
+1861 y Fk(exec)144 b Fl(If)16 b(a)g Fg(command)i Fl(argumen)o(t)d(is)i
+(supplied,)h(it)f(replaces)g(the)f(shell.)24 b(If)17
+b(no)f Fg(command)i Fl(is)e(sp)q(eci\014ed,)240 1924
+y(redirections)g(ma)o(y)f(b)q(e)h(used)g(to)e(a\013ect)h(the)g(curren)o
+(t)g(shell)i(en)o(vironmen)o(t.)0 2009 y Fk(exit)144
+b Fl(Exit)15 b(the)h(shell.)0 2095 y Fk(export)96 b Fl(Mark)14
+b(the)i(argumen)o(ts)e(as)h(v)m(ariables)h(to)f(b)q(e)h(passed)f(to)g
+(c)o(hild)i(pro)q(cesses)e(in)h(the)f(en)o(vironmen)o(t.)0
+2180 y Fk(getopts)72 b Fl(P)o(arse)14 b(options)i(to)e(shell)j(scripts)
+f(or)e(functions.)0 2266 y Fk(hash)144 b Fl(Remem)o(b)q(er)17
+b(the)g(full)g(pathnames)g(of)f(commands)g(sp)q(eci\014ed)i(as)e
+(argumen)o(ts,)g(so)g(they)g(need)h(not)240 2328 y(b)q(e)f(searc)o(hed)
+f(for)g(on)g(subsequen)o(t)h(in)o(v)o(o)q(cations.)0
+2413 y Fk(kill)144 b Fl(Send)16 b(a)f(signal)h(to)f(a)f(pro)q(cess.)0
+2499 y Fk(pwd)168 b Fl(Prin)o(t)15 b(the)g(curren)o(t)h(w)o(orking)e
+(directory)l(.)0 2584 y Fk(read)144 b Fl(Read)16 b(a)f(line)i(from)d
+(the)h(shell)i(input)f(and)g(use)f(it)h(to)e(set)h(the)g(v)m(alues)i
+(of)e(sp)q(eci\014ed)i(v)m(ariables.)0 2670 y Fk(readonly)48
+b Fl(Mark)14 b(v)m(ariables)j(as)e(unc)o(hangable.)p
+eop
+4 5 bop 0 -58 a Fl(4)1646 b(Bash)15 b(F)l(eatures)0 183
+y Fk(return)96 b Fl(Cause)15 b(a)g(shell)i(function)f(to)e(exit)i(with)
+g(a)e(sp)q(eci\014ed)k(v)m(alue.)0 283 y Fk(shift)120
+b Fl(Shift)16 b(p)q(ositional)g(parameters)f(to)f(the)i(left.)0
+383 y Fk(test)0 464 y([)216 b Fl(Ev)m(aluate)16 b(a)f(conditional)h
+(expression.)0 564 y Fk(times)120 b Fl(Prin)o(t)15 b(out)g(the)g(user)h
+(and)f(system)g(times)g(used)h(b)o(y)f(the)g(shell)i(and)f(its)f(c)o
+(hildren.)0 664 y Fk(trap)144 b Fl(Sp)q(ecify)17 b(commands)e(to)f(b)q
+(e)i(executed)g(when)g(the)f(shell)i(receiv)o(es)f(signals.)0
+764 y Fk(umask)120 b Fl(Set)15 b(the)h(shell)g(pro)q(cess's)f(\014le)i
+(creation)e(mask.)0 863 y Fk(unset)120 b Fl(Cause)15
+b(shell)i(v)m(ariables)f(to)f(disapp)q(ear.)0 963 y Fk(wait)144
+b Fl(W)l(ait)15 b(un)o(til)h(c)o(hild)h(pro)q(cesses)f(exit)g(and)f
+(rep)q(ort)g(their)g(exit)h(status.)0 1244 y Fj(1.5)33
+b(Bourne)15 b(Shell)i(V)-6 b(ariables)62 1388 y Fl(Bash)20
+b(uses)h(certain)f(shell)h(v)m(ariables)h(in)f(the)f(same)f(w)o(a)o(y)g
+(as)h(the)g(Bourne)g(shell.)36 b(In)21 b(some)e(cases,)i(Bash)0
+1450 y(assigns)15 b(a)g(default)h(v)m(alue)g(to)f(the)g(v)m(ariable.)0
+1612 y Fk(IFS)168 b Fl(A)19 b(list)i(of)d(c)o(haracters)h(that)g
+(separate)f(\014elds;)23 b(used)d(when)f(the)h(shell)h(splits)f(w)o
+(ords)f(as)g(part)f(of)240 1674 y(expansion.)0 1774 y
+Fk(PATH)144 b Fl(A)15 b(colon-separated)h(list)g(of)f(directories)h(in)
+g(whic)o(h)g(the)f(shell)i(lo)q(oks)e(for)g(commands.)0
+1874 y Fk(HOME)144 b Fl(The)15 b(curren)o(t)h(user's)e(home)i
+(directory)l(.)0 1974 y Fk(CDPATH)96 b Fl(A)15 b(colon-separated)h
+(list)g(of)f(directories)h(used)g(as)e(a)h(searc)o(h)g(path)g(for)g
+(the)g Fk(cd)g Fl(command.)0 2074 y Fk(MAILPATH)48 b
+Fl(A)13 b(colon-separated)h(list)g(of)f(\014les)i(whic)o(h)f(the)g
+(shell)h(p)q(erio)q(dically)h(c)o(hec)o(ks)e(for)e(new)i(mail.)20
+b(Y)l(ou)14 b(can)240 2136 y(also)f(sp)q(ecify)i(what)d(message)h(is)h
+(prin)o(ted)f(b)o(y)h(separating)f(the)g(\014le)h(name)f(from)g(the)g
+(message)g(with)240 2198 y(a)18 b(`)p Fk(?)p Fl('.)29
+b(When)19 b(used)g(in)g(the)g(text)f(of)g(the)h(message,)f
+Fk($_)g Fl(stands)g(for)g(the)h(name)f(of)g(the)h(curren)o(t)240
+2261 y(mail\014le.)0 2360 y Fk(PS1)168 b Fl(The)15 b(primary)h(prompt)e
+(string.)0 2460 y Fk(PS2)168 b Fl(The)15 b(secondary)h(prompt)e
+(string.)0 2560 y Fk(OPTIND)96 b Fl(The)15 b(index)i(of)e(the)g(last)g
+(option)g(pro)q(cessed)h(b)o(y)g(the)f Fk(getopts)f Fl(builtin.)0
+2660 y Fk(OPTARG)96 b Fl(The)15 b(v)m(alue)i(of)e(the)g(last)g(option)g
+(argumen)o(t)g(pro)q(cessed)h(b)o(y)f(the)g Fk(getopts)f
+Fl(builtin.)p eop
+5 6 bop 0 -58 a Fl(Chapter)15 b(1:)k(Bourne)d(Shell)h(St)o(yle)f(F)l
+(eatures)1143 b(5)0 183 y Fj(1.6)33 b(Other)15 b(Bourne)g(Shell)i(F)-6
+b(eatures)62 321 y Fl(Bash)15 b(implemen)o(ts)g(essen)o(tially)h(the)e
+(same)g(grammar,)f(parameter)g(and)h(v)m(ariable)i(expansion,)f
+(redirection,)0 384 y(and)h(quoting)g(as)f(the)h(Bourne)g(Shell.)23
+b(Bash)16 b(uses)g(the)g(P)o(osix)f(1003.2)f(standard)i(as)f(the)h(sp)q
+(eci\014cation)h(of)e(ho)o(w)0 446 y(these)i(features)f(are)g(to)g(b)q
+(e)h(implemen)o(ted.)25 b(There)17 b(are)f(some)g(di\013erences)h(b)q
+(et)o(w)o(een)g(the)f(traditional)i(Bourne)0 508 y(shell)f(and)f(the)f
+(P)o(osix)h(standard;)f(this)h(section)g(quic)o(kly)h(details)f(the)g
+(di\013erences)g(of)f(signi\014cance.)23 b(A)16 b(n)o(um)o(b)q(er)0
+571 y(of)f(these)g(di\013erences)i(are)d(explained)k(in)e(greater)e
+(depth)i(in)g(subsequen)o(t)g(sections.)0 789 y Ff(1.6.1)30
+b(Ma)s(jor)15 b(Di\013erences)h(from)e(the)h(Bourne)g(Shell)62
+928 y Fl(Bash)i(implemen)o(ts)g(the)g Fk(!)f Fl(k)o(eyw)o(ord)f(to)h
+(negate)g(the)g(return)g(v)m(alue)i(of)e(a)g(pip)q(eline.)26
+b(V)l(ery)17 b(useful)g(when)g(an)0 990 y Fk(if)e Fl(statemen)o(t)f
+(needs)i(to)f(act)f(only)i(if)g(a)f(test)f(fails.)62
+1128 y(Bash)i(includes)h(brace)e(expansion)h(\(see)g(Section)g(2.2)e
+([Brace)h(Expansion],)g(page)g(7\).)62 1266 y(Bash)h(includes)h(the)f
+(P)o(osix)f(and)h Fk(ksh)p Fl(-st)o(yle)f(pattern)g(remo)o(v)m(al)g
+Fk(\045\045)h Fl(and)f Fk(##)g Fl(constructs)g(to)g(remo)o(v)o(e)g
+(leading)0 1329 y(or)g(trailing)h(substrings)f(from)g(v)m(ariables.)62
+1467 y(The)j(P)o(osix)g(and)g Fk(ksh)p Fl(-st)o(yle)g
+Fk($\(\))f Fl(form)g(of)h(command)f(substitution)i(is)f(implemen)o
+(ted,)i(and)e(preferred)h(to)0 1529 y(the)c(Bourne)h(shell's)g
+Fk(``)f Fl(\(whic)o(h)h(is)g(also)f(implemen)o(ted)i(for)d(bac)o(kw)o
+(ards)h(compatibilit)o(y\).)62 1667 y(V)l(ariables)e(presen)o(t)g(in)f
+(the)h(shell's)g(initial)h(en)o(vironmen)o(t)e(are)g(automatically)g
+(exp)q(orted)h(to)e(c)o(hild)j(pro)q(cesses.)0 1730 y(The)19
+b(Bourne)g(shell)h(do)q(es)f(not)f(normally)h(do)g(this)g(unless)g(the)
+g(v)m(ariables)h(are)e(explicitly)j(mark)o(ed)e(using)g(the)0
+1792 y Fk(export)14 b Fl(command.)62 1930 y(The)i(expansion)g
+Fk(${#xx})p Fl(,)e(whic)o(h)i(returns)f(the)g(length)h(of)f
+Fk($xx)p Fl(,)f(is)i(supp)q(orted.)62 2068 y(The)k Fk(IFS)g
+Fl(v)m(ariable)h(is)f(used)g(to)f(split)i(only)f(the)g(results)g(of)g
+(expansion,)h(not)e(all)i(w)o(ords.)33 b(This)20 b(closes)g(a)0
+2131 y(longstanding)c(shell)h(securit)o(y)e(hole.)62
+2269 y(It)i(is)g(p)q(ossible)i(to)d(ha)o(v)o(e)h(a)f(v)m(ariable)i(and)
+f(a)g(function)h(with)f(the)g(same)f(name;)h Fk(sh)g
+Fl(do)q(es)g(not)g(separate)f(the)0 2331 y(t)o(w)o(o)e(name)h(spaces.)
+62 2469 y(Bash)j(functions)h(are)e(p)q(ermitted)i(to)e(ha)o(v)o(e)h(lo)
+q(cal)g(v)m(ariables,)i(and)e(th)o(us)g(useful)h(recursiv)o(e)f
+(functions)h(ma)o(y)0 2532 y(b)q(e)d(written.)62 2670
+y(The)g Fk(noclobber)e Fl(option)h(is)h(a)o(v)m(ailable)h(to)d(a)o(v)o
+(oid)h(o)o(v)o(erwriting)g(existing)h(\014les)g(with)g(output)f
+(redirection.)p eop
+6 7 bop 0 -58 a Fl(6)1646 b(Bash)15 b(F)l(eatures)62
+183 y(Bash)i(allo)o(ws)g(y)o(ou)f(to)g(write)g(a)g(function)i(to)e(o)o
+(v)o(erride)g(a)g(builtin,)j(and)e(pro)o(vides)g(access)f(to)g(that)g
+(builtin's)0 246 y(functionalit)o(y)g(within)h(the)e(function)h(via)g
+(the)f Fk(builtin)f Fl(and)h Fk(command)g Fl(builtins.)62
+382 y(The)f Fk(command)e Fl(builtin)j(allo)o(ws)f(selectiv)o(e)g
+(disabling)h(of)e(functions)h(when)f(command)g(lo)q(okup)h(is)g(p)q
+(erformed.)62 519 y(Individual)k(builtins)g(ma)o(y)c(b)q(e)i(enabled)h
+(or)e(disabled)i(using)e(the)h Fk(enable)e Fl(builtin.)62
+656 y(F)l(unctions)i(ma)o(y)f(b)q(e)h(exp)q(orted)f(to)g(c)o(hildren)i
+(via)e(the)h(en)o(vironmen)o(t.)62 793 y(The)g(Bash)f
+Fk(read)g Fl(builtin)i(will)g(read)f(a)f(line)h(ending)h(in)f
+Fk(\\)f Fl(with)h(the)f Fk(-r)g Fl(option,)g(and)h(will)h(use)e(the)h
+Fk($REPLY)0 856 y Fl(v)m(ariable)h(as)d(a)h(default)h(if)g(no)f
+(argumen)o(ts)f(are)h(supplied.)62 993 y(The)j Fk(return)f
+Fl(builtin)j(ma)o(y)d(b)q(e)h(used)h(to)e(ab)q(ort)g(execution)h(of)g
+(scripts)g(executed)g(with)g(the)g Fk(.)g Fl(or)f Fk(source)0
+1055 y Fl(builtins.)62 1192 y(The)f Fk(umask)e Fl(builtin)k(allo)o(ws)d
+(sym)o(b)q(olic)h(mo)q(de)g(argumen)o(ts)e(similar)j(to)d(those)h
+(accepted)h(b)o(y)f Fk(chmod)p Fl(.)62 1329 y(The)d Fk(test)e
+Fl(builtin)k(is)d(sligh)o(tly)i(di\013eren)o(t,)e(as)g(it)h(implemen)o
+(ts)g(the)f(P)o(osix)g(1003.2)f(algorithm,)h(whic)o(h)h(sp)q(eci\014es)
+0 1391 y(the)j(b)q(eha)o(vior)h(based)g(on)f(the)g(n)o(um)o(b)q(er)g
+(of)g(argumen)o(ts.)p eop
+7 8 bop 0 -58 a Fl(Chapter)15 b(2:)k(C-Shell)f(St)o(yle)d(F)l(eatures)
+1254 b(7)0 183 y Fh(2)41 b(C-Shell)13 b(St)n(yle)h(F)-7
+b(eatures)62 355 y Fl(The)18 b(C-Shell)h(\()p Fk(csh)p
+Fl(\))e(w)o(as)f(created)i(b)o(y)f(Bill)j(Jo)o(y)d(at)g(UC)g(Berk)o
+(eley)l(.)28 b(It)18 b(is)g(generally)h(considered)f(to)f(ha)o(v)o(e)0
+417 y(b)q(etter)e(features)f(for)g(in)o(teractiv)o(e)h(use)g(than)f
+(the)h(original)h(Bourne)f(shell.)21 b(Some)15 b(of)f(the)h
+Fk(csh)f Fl(features)g(presen)o(t)0 480 y(in)21 b(Bash)f(include)i(job)
+e(con)o(trol,)g(history)g(expansion,)h(`protected')e(redirection,)j
+(and)e(sev)o(eral)g(v)m(ariables)i(for)0 542 y(con)o(trolling)16
+b(the)f(in)o(teractiv)o(e)h(b)q(eha)o(viour)g(of)f(the)g(shell)i
+(\(e.g.)i Fk(IGNOREEOF)p Fl(\).)62 679 y(See)d(Chapter)f(6)g([Using)g
+(History)g(In)o(teractiv)o(ely],)h(page)f(33)f(for)h(details)h(on)f
+(history)g(expansion.)0 888 y Fj(2.1)33 b(Tilde)16 b(Expansion)62
+1025 y Fl(Bash)k(has)f(tilde)i(\()p Fk(~)p Fl(\))e(expansion,)i
+(similar,)g(but)f(not)f(iden)o(tical,)j(to)d(that)f(of)h
+Fk(csh)p Fl(.)33 b(The)19 b(follo)o(wing)i(table)0 1087
+y(sho)o(ws)15 b(what)f(unquoted)i(w)o(ords)e(b)q(eginning)k(with)d(a)g
+(tilde)i(expand)e(to.)0 1233 y Fk(~)216 b Fl(The)15 b(curren)o(t)h(v)m
+(alue)g(of)f Fk($HOME)p Fl(.)0 1313 y Fk(~/foo)120 b
+Fl(`)p Fk($HOME/foo)p Fl(')0 1384 y Fk(~fred/foo)240
+1446 y Fl(The)15 b(sub)q(directory)i Fk(foo)d Fl(of)h(the)g(home)h
+(directory)f(of)g(the)g(user)g Fk(fred)p Fl(.)0 1526
+y Fk(~+/foo)96 b Fl(`)p Fk($PWD/foo)p Fl(')0 1605 y Fk(~-)192
+b Fl(`)p Fk($OLDPWD/foo)p Fl(')62 1751 y(Bash)21 b(will)h(also)f(tilde)
+h(expand)g(w)o(ords)e(follo)o(wing)h(redirection)h(op)q(erators)e(and)h
+(w)o(ords)f(follo)o(wing)h(`)p Fk(=)p Fl(')f(in)0 1813
+y(assignmen)o(t)15 b(statemen)o(ts.)0 2022 y Fj(2.2)33
+b(Brace)14 b(Expansion)62 2159 y Fl(Brace)d(expansion)h(is)g(a)e(mec)o
+(hanism)i(b)o(y)f(whic)o(h)h(arbitrary)e(strings)h(ma)o(y)f(b)q(e)i
+(generated.)18 b(This)12 b(mec)o(hanism)f(is)0 2222 y(similar)j(to)e
+Fg(pathname)g(expansion)i Fl(\(see)f(the)f(Bash)h(man)o(ual)g(page)g
+(for)f(details\),)h(but)g(the)g(\014le)g(names)g(generated)0
+2284 y(need)j(not)f(exist.)21 b(P)o(atterns)14 b(to)h(b)q(e)h(brace)g
+(expanded)g(tak)o(e)f(the)h(form)e(of)h(an)h(optional)g
+Fg(pream)o(ble)p Fl(,)f(follo)o(w)o(ed)h(b)o(y)0 2346
+y(a)h(series)g(of)g(comma-separated)f(strings)h(b)q(et)o(w)o(een)g(a)g
+(pair)h(of)e(braces,)h(follo)o(w)o(ed)h(b)o(y)f(an)g(optional)g
+Fg(p)q(ostam)o(ble)p Fl(.)0 2408 y(The)f(pream)o(ble)h(is)f(prep)q
+(ended)i(to)d(eac)o(h)h(string)g(con)o(tained)h(within)g(the)f(braces,)
+g(and)g(the)g(p)q(ostam)o(ble)g(is)h(then)0 2471 y(app)q(ended)g(to)d
+(eac)o(h)i(resulting)g(string,)f(expanding)h(left)g(to)e(righ)o(t.)62
+2608 y(Brace)19 b(expansions)g(ma)o(y)f(b)q(e)i(nested.)30
+b(The)19 b(results)g(of)f(eac)o(h)h(expanded)h(string)f(are)f(not)g
+(sorted;)i(left)f(to)0 2670 y(righ)o(t)c(order)g(is)h(preserv)o(ed.)k
+(F)l(or)14 b(example,)p eop
+8 9 bop 0 -58 a Fl(8)1646 b(Bash)15 b(F)l(eatures)120
+183 y Fk(a{d,c,b}e)62 322 y Fl(expands)h(in)o(to)f Fg(ade)h(ace)f(ab)q
+(e)p Fl(.)62 461 y(Brace)h(expansion)g(is)g(p)q(erformed)g(b)q(efore)g
+(an)o(y)f(other)g(expansions,)h(and)g(an)o(y)f(c)o(haracters)g(sp)q
+(ecial)i(to)e(other)0 524 y(expansions)k(are)f(preserv)o(ed)h(in)g(the)
+f(result.)30 b(It)18 b(is)h(strictly)g(textual.)29 b(Bash)18
+b(do)q(es)h(not)f(apply)h(an)o(y)f(syn)o(tactic)0 586
+y(in)o(terpretation)d(to)g(the)g(con)o(text)g(of)g(the)g(expansion)h
+(or)f(the)g(text)g(b)q(et)o(w)o(een)g(the)g(braces.)62
+725 y(A)h(correctly-formed)f(brace)h(expansion)g(m)o(ust)f(con)o(tain)g
+(unquoted)h(op)q(ening)h(and)e(closing)i(braces,)e(and)h(at)0
+787 y(least)f(one)h(unquoted)f(comma.)20 b(An)o(y)15
+b(incorrectly)h(formed)f(brace)g(expansion)h(is)g(left)g(unc)o(hanged.)
+62 926 y(This)22 b(construct)f(is)h(t)o(ypically)h(used)f(as)f
+(shorthand)g(when)h(the)f(common)g(pre\014x)h(of)f(the)g(strings)h(to)e
+(b)q(e)0 988 y(generated)15 b(is)h(longer)f(than)g(in)h(the)g(ab)q(o)o
+(v)o(e)f(example:)120 1115 y Fk(mkdir)23 b(/usr/local/src/bash/{old,ne)
+o(w,dist,b)o(ugs})62 1254 y Fl(or)120 1380 y Fk(chown)g(root)g
+(/usr/{ucb/{ex,edit},lib/{ex?.?)o(*,how_e)o(x}})0 1623
+y Fj(2.3)33 b(C)14 b(Shell)j(Builtins)62 1762 y Fl(Bash)f(has)f(sev)o
+(eral)g(builtin)i(commands)e(whose)h(de\014nition)h(is)e(v)o(ery)g
+(similar)h(to)f Fk(csh)p Fl(.)0 1915 y Fk(pushd)360 1979
+y(pushd)23 b([)p Fg(dir)28 b Fk(|)c(+)p Fg(n)g Fk(|)f
+Fg(-n)p Fk(])240 2056 y Fl(Sa)o(v)o(e)14 b(the)g(curren)o(t)h
+(directory)f(on)g(a)g(list)i(and)e(then)h Fk(cd)f Fl(to)f
+Fg(dir)p Fl(.)21 b(With)14 b(no)h(argumen)o(ts,)e(exc)o(hanges)240
+2118 y(the)i(top)g(t)o(w)o(o)f(directories.)240 2210
+y Fk(+)p Fg(n)191 b Fl(Brings)13 b(the)f Fg(n)p Fl(th)h(directory)f
+(\(coun)o(ting)h(from)e(the)i(left)f(of)g(the)g(list)i(prin)o(ted)f(b)o
+(y)f Fk(dirs)p Fl(\))480 2272 y(to)j(the)g(top)g(of)f(the)i(list)g(b)o
+(y)f(rotating)f(the)h(stac)o(k.)240 2363 y Fk(-)p Fg(n)191
+b Fl(Brings)21 b(the)f Fg(n)p Fl(th)g(directory)h(\(coun)o(ting)f(from)
+g(the)g(righ)o(t)g(of)g(the)g(list)h(prin)o(ted)g(b)o(y)480
+2425 y Fk(dirs)p Fl(\))14 b(to)h(the)g(top)g(of)g(the)g(list)h(b)o(y)f
+(rotating)f(the)i(stac)o(k.)240 2517 y Fg(dir)185 b Fl(Mak)o(es)14
+b(the)g(curren)o(t)h(w)o(orking)f(directory)g(b)q(e)i(the)e(top)g(of)g
+(the)h(stac)o(k,)e(and)i(then)g Fg(cd)r Fl(s)480 2579
+y(to)g Fg(dir)p Fl(.)20 b(Y)l(ou)c(can)f(see)g(the)h(sa)o(v)o(ed)e
+(directory)i(list)g(with)f(the)h Fk(dirs)e Fl(command.)0
+2670 y Fk(popd)p eop
+9 10 bop 0 -58 a Fl(Chapter)15 b(2:)k(C-Shell)f(St)o(yle)d(F)l(eatures)
+1254 b(9)360 183 y Fk(popd)23 b([+)p Fg(n)h Fk(|)g(-)p
+Fg(n)p Fk(])240 265 y Fl(P)o(ops)17 b(the)g(directory)h(stac)o(k,)f
+(and)h Fk(cd)p Fl(s)f(to)f(the)i(new)g(top)f(directory)l(.)27
+b(When)17 b(no)h(argumen)o(ts)e(are)240 327 y(giv)o(en,)f(remo)o(v)o
+(es)e(the)i(top)e(directory)i(from)f(the)g(stac)o(k)g(and)g
+Fk(cd)p Fl(s)g(to)g(the)g(new)h(top)f(directory)l(.)20
+b(The)240 389 y(elemen)o(ts)14 b(are)g(n)o(um)o(b)q(ered)g(from)f(0)g
+(starting)g(at)g(the)h(\014rst)f(directory)h(listed)h(with)f
+Fk(dirs)p Fl(;)f(i.e.)20 b Fk(popd)240 452 y Fl(is)c(equiv)m(alen)o(t)h
+(to)d Fk(popd)h(+0)p Fl(.)240 553 y Fk(+)p Fg(n)191 b
+Fl(Remo)o(v)o(es)19 b(the)g Fg(n)p Fl(th)g(directory)g(\(coun)o(ting)g
+(from)f(the)i(left)f(of)f(the)h(list)h(prin)o(ted)g(b)o(y)480
+615 y Fk(dirs)p Fl(\),)14 b(starting)g(with)i(zero.)240
+716 y Fk(-)p Fg(n)191 b Fl(Remo)o(v)o(es)16 b(the)h Fg(n)p
+Fl(th)f(directory)h(\(coun)o(ting)g(from)e(the)i(righ)o(t)f(of)g(the)h
+(list)g(prin)o(ted)g(b)o(y)480 778 y Fk(dirs)p Fl(\),)d(starting)g
+(with)i(zero.)0 879 y Fk(dirs)360 948 y(dirs)23 b([+)p
+Fg(n)h Fk(|)g(-)p Fg(n)p Fk(])g([-)p Fg(l)r Fk(])240
+1030 y Fl(Displa)o(y)19 b(the)f(list)i(of)d(curren)o(tly)i(remem)o(b)q
+(ered)g(directories.)31 b(Directories)19 b(\014nd)g(their)g(w)o(a)o(y)e
+(on)o(to)240 1092 y(the)e(list)h(with)g(the)f Fk(pushd)f
+Fl(command;)h(y)o(ou)g(can)g(get)g(bac)o(k)g(up)h(through)f(the)g(list)
+h(with)f(the)h Fk(popd)240 1155 y Fl(command.)240 1256
+y Fk(+)p Fg(n)191 b Fl(Displa)o(ys)20 b(the)g Fg(n)p
+Fl(th)f(directory)h(\(coun)o(ting)g(from)f(the)h(left)f(of)h(the)f
+(list)i(prin)o(ted)f(b)o(y)480 1318 y Fk(dirs)15 b Fl(when)g(in)o(v)o
+(ok)o(ed)h(without)f(options\),)g(starting)f(with)i(zero.)240
+1419 y Fk(-)p Fg(n)191 b Fl(Displa)o(ys)18 b(the)f Fg(n)p
+Fl(th)g(directory)g(\(coun)o(ting)g(from)g(the)g(righ)o(t)g(of)f(the)h
+(list)h(prin)o(ted)g(b)o(y)480 1481 y Fk(dirs)d Fl(when)g(in)o(v)o(ok)o
+(ed)h(without)f(options\),)g(starting)f(with)i(zero.)240
+1582 y Fk(-)p Fg(l)204 b Fl(Pro)q(duces)16 b(a)g(longer)g(listing;)i
+(the)e(default)g(listing)i(format)c(uses)i(a)g(tilde)h(to)f(denote)480
+1644 y(the)f(home)g(directory)l(.)0 1745 y Fk(history)360
+1815 y(history)23 b([)p Fg(n)p Fk(])h([)f([-w)h(-r)g(-a)f(-n])h([)p
+Fg(\014lename)s Fk(]])240 1896 y Fl(Displa)o(y)c(the)g(history)g(list)h
+(with)f(line)i(n)o(um)o(b)q(ers.)34 b(Lines)21 b(pre\014xed)g(with)f
+(with)g(a)g Fk(*)f Fl(ha)o(v)o(e)h(b)q(een)240 1958 y(mo)q(di\014ed.)25
+b(An)17 b(argumen)o(t)f(of)g Fg(n)g Fl(sa)o(ys)g(to)g(list)h(only)g
+(the)g(last)f Fg(n)h Fl(lines.)25 b(Option)17 b Fk(-w)f
+Fl(means)h(write)240 2021 y(out)i(the)g(curren)o(t)g(history)g(to)f
+(the)i(history)f(\014le;)i Fk(-r)e Fl(means)g(to)g(read)g(the)g(curren)
+o(t)g(history)g(\014le)240 2083 y(and)e(mak)o(e)g(its)g(con)o(ten)o(ts)
+f(the)h(history)g(list.)26 b(An)18 b(argumen)o(t)e(of)g
+Fk(-a)h Fl(means)g(to)f(app)q(end)j(the)e(new)240 2145
+y(history)f(lines)i(\(history)d(lines)j(en)o(tered)e(since)h(the)f(b)q
+(eginning)j(of)c(the)h(curren)o(t)g(Bash)g(session\))h(to)240
+2208 y(the)g(history)f(\014le.)25 b(Finally)l(,)18 b(the)f
+Fk(-n)f Fl(argumen)o(t)g(means)h(to)f(read)g(the)h(history)f(lines)i
+(not)f(already)240 2270 y(read)i(from)g(the)g(history)g(\014le)h(in)o
+(to)f(the)h(curren)o(t)f(history)g(list.)33 b(These)19
+b(are)g(lines)i(app)q(ended)g(to)240 2332 y(the)d(history)h(\014le)g
+(since)g(the)g(b)q(eginning)h(of)e(the)g(curren)o(t)h(Bash)f(session.)
+30 b(If)18 b Fg(\014lename)k Fl(is)d(giv)o(en,)240 2394
+y(then)c(it)f(is)h(used)g(as)e(the)i(history)f(\014le,)h(else)g(if)g
+Fk($HISTFILE)e Fl(has)h(a)g(v)m(alue,)h(that)e(is)i(used,)g(otherwise)
+240 2457 y(`)p Fk(~/.bash_history)p Fl(')d(is)k(used.)0
+2558 y Fk(logout)96 b Fl(Exit)15 b(a)g(login)h(shell.)0
+2659 y Fk(source)96 b Fl(A)15 b(synon)o(ym)g(for)g Fk(.)g
+Fl(\(see)g(Section)h(1.4)e([Bourne)h(Shell)j(Builtins],)e(page)f(3\))p
+eop
+10 11 bop 0 -58 a Fl(10)1623 b(Bash)15 b(F)l(eatures)0
+183 y Fj(2.4)33 b(C)14 b(Shell)j(V)-6 b(ariables)0 320
+y Fk(IGNOREEOF)240 382 y Fl(If)12 b(this)h(v)m(ariable)g(is)g(set,)f
+(it)h(represen)o(ts)f(the)g(n)o(um)o(b)q(er)g(of)g(consecutiv)o(e)h
+Fk(EOF)p Fl(s)f(Bash)g(will)i(read)e(b)q(efore)240 445
+y(exiting.)21 b(By)15 b(default,)h(Bash)f(will)i(exit)e(up)q(on)h
+(reading)g(a)f(single)h Fk(EOF)p Fl(.)0 519 y Fk(cdable_vars)240
+582 y Fl(If)g(this)g(v)m(ariable)i(is)e(set,)g(Bash)g(treats)e(argumen)
+o(ts)h(to)h(the)g Fk(cd)f Fl(command)h(whic)o(h)h(are)e(not)h(direc-)
+240 644 y(tories)f(as)g(names)g(of)g(v)m(ariables)h(whose)f(v)m(alues)i
+(are)e(the)g(directories)h(to)f(c)o(hange)g(to.)p eop
+11 12 bop 0 -58 a Fl(Chapter)15 b(3:)k(Korn)d(Shell)h(St)o(yle)e(F)l
+(eatures)1164 b(11)0 183 y Fh(3)41 b(Korn)15 b(Shell)f(St)n(yle)g(F)-7
+b(eatures)62 373 y Fl(This)23 b(section)g(describ)q(es)h(features)e
+(primarily)h(inspired)h(b)o(y)f(the)f(Korn)g(Shell)j(\()p
+Fk(ksh)p Fl(\).)40 b(In)22 b(some)g(cases,)0 435 y(the)17
+b(P)o(osix)f(1003.2)f(standard)h(has)h(adopted)g(these)f(commands)h
+(and)g(v)m(ariables)h(from)e(the)g(Korn)h(Shell;)i(Bash)0
+498 y(implemen)o(ts)d(those)f(features)g(using)h(the)f(P)o(osix)h
+(standard)e(as)h(a)g(guide.)0 728 y Fj(3.1)33 b(Korn)15
+b(Shell)i(Constructs)62 865 y Fl(Bash)h(includes)j(the)d(Korn)g(Shell)i
+Fk(select)d Fl(construct.)28 b(This)18 b(construct)g(allo)o(ws)g(the)g
+(easy)g(generation)g(of)0 928 y(men)o(us.)i(It)15 b(has)g(almost)g(the)
+g(same)g(syn)o(tax)g(as)g(the)g Fk(for)g Fl(command.)62
+1065 y(The)h(syn)o(tax)e(of)h(the)g Fk(select)g Fl(command)g(is:)120
+1190 y Fk(select)23 b Fg(name)k Fk([in)c Fg(w)o(ords)i
+Fk(...];)e(do)h Fg(commands)r Fk(;)f(done)62 1328 y Fl(The)13
+b(list)g(of)g(w)o(ords)e(follo)o(wing)j Fk(in)e Fl(is)h(expanded,)h
+(generating)f(a)f(list)h(of)f(items.)20 b(The)13 b(set)f(of)g(expanded)
+i(w)o(ords)0 1390 y(is)19 b(prin)o(ted)g(on)g(the)f(standard)g(error,)g
+(eac)o(h)h(preceded)h(b)o(y)e(a)g(n)o(um)o(b)q(er.)30
+b(If)19 b(the)f(\\)p Fk(in)d Fg(w)o(ords)r Fl(")i(is)i(omitted,)g(the)0
+1452 y(p)q(ositional)g(parameters)d(are)h(prin)o(ted.)26
+b(The)18 b Fk(PS3)e Fl(prompt)h(is)h(then)f(displa)o(y)o(ed)i(and)e(a)g
+(line)i(is)e(read)g(from)g(the)0 1515 y(standard)h(input.)32
+b(If)19 b(the)g(line)h(consists)f(of)g(the)g(n)o(um)o(b)q(er)g(corresp)
+q(onding)h(to)e(one)h(of)f(the)h(displa)o(y)o(ed)h(w)o(ords,)0
+1577 y(then)13 b(the)g(v)m(alue)h(of)e Fg(name)k Fl(is)d(set)f(to)g
+(that)g(w)o(ord.)19 b(If)13 b(the)g(line)h(is)f(empt)o(y)l(,)g(the)g(w)
+o(ords)f(and)h(prompt)f(are)h(displa)o(y)o(ed)0 1639
+y(again.)19 b(If)14 b Fk(EOF)g Fl(is)g(read,)f(the)h
+Fk(select)f Fl(command)h(completes.)20 b(An)o(y)14 b(other)f(v)m(alue)i
+(read)e(causes)h Fg(name)j Fl(to)c(b)q(e)h(set)0 1702
+y(to)h(n)o(ull.)21 b(The)15 b(line)i(read)e(is)h(sa)o(v)o(ed)f(in)h
+(the)f(v)m(ariable)i Fk(REPLY)p Fl(.)62 1839 y(The)d
+Fg(commands)h Fl(are)f(executed)g(after)f(eac)o(h)g(selection)i(un)o
+(til)g(a)e Fk(break)g Fl(or)g Fk(return)g Fl(command)g(is)h(executed,)0
+1901 y(at)h(whic)o(h)h(p)q(oin)o(t)f(the)h Fk(select)e
+Fl(command)h(completes.)0 2131 y Fj(3.2)33 b(Korn)15
+b(Shell)i(Builtins)62 2269 y Fl(This)f(section)g(describ)q(es)h(Bash)e
+(builtin)i(commands)e(tak)o(en)g(from)g Fk(ksh)p Fl(.)0
+2420 y Fk(fc)360 2483 y(fc)24 b([-e)f Fg(ename)s Fk(])h([-nlr])f([)p
+Fg(\014rst)q Fk(])g([)p Fg(last)q Fk(])360 2532 y(fc)h(-s)f([)p
+Fg(pat=rep)q Fk(])h([)p Fg(command)r Fk(])240 2608 y
+Fl(Fix)19 b(Command.)29 b(In)20 b(the)e(\014rst)h(form,)f(a)g(range)g
+(of)h(commands)f(from)g Fg(\014rst)h Fl(to)f Fg(last)i
+Fl(is)f(selected)240 2670 y(from)f(the)g(history)h(list.)30
+b(Both)18 b Fg(\014rst)h Fl(and)g Fg(last)g Fl(ma)o(y)f(b)q(e)h(sp)q
+(eci\014ed)i(as)d(a)g(string)h(\(to)e(lo)q(cate)i(the)p
+eop
+12 13 bop 0 -58 a Fl(12)1623 b(Bash)15 b(F)l(eatures)240
+183 y(most)h(recen)o(t)h(command)g(b)q(eginning)i(with)f(that)e
+(string\))h(or)f(as)h(a)g(n)o(um)o(b)q(er)g(\(an)g(index)h(in)o(to)f
+(the)240 246 y(history)g(list,)h(where)g(a)f(negativ)o(e)g(n)o(um)o(b)q
+(er)h(is)g(used)g(as)f(an)g(o\013set)f(from)h(the)g(curren)o(t)g
+(command)240 308 y(n)o(um)o(b)q(er\).)k(If)15 b Fg(last)i
+Fl(is)f(not)f(sp)q(eci\014ed)i(it)f(is)g(set)f(to)g Fg(\014rst)p
+Fl(.)21 b(If)15 b Fg(\014rst)h Fl(is)g(not)f(sp)q(eci\014ed)j(it)e(is)g
+(set)f(to)g(the)240 370 y(previous)f(command)g(for)e(editing)j(and)f
+(-16)f(for)g(listing.)20 b(If)14 b(the)g Fk(-l)f Fl(\015ag)g(is)h(giv)o
+(en,)g(the)f(commands)240 432 y(are)19 b(listed)i(on)e(standard)g
+(output.)32 b(The)19 b Fk(-n)g Fl(\015ag)g(suppresses)h(the)g(command)f
+(n)o(um)o(b)q(ers)g(when)240 495 y(listing.)31 b(The)18
+b Fk(-r)g Fl(\015ag)h(rev)o(erses)f(the)g(order)g(of)g(the)h(listing.)
+30 b(Otherwise,)20 b(the)f(editor)f(giv)o(en)h(b)o(y)240
+557 y Fg(ename)d Fl(is)d(in)o(v)o(ok)o(ed)h(on)f(a)g(\014le)h(con)o
+(taining)g(those)e(commands.)19 b(If)14 b Fg(ename)i
+Fl(is)d(not)g(giv)o(en,)h(the)f(v)m(alue)240 619 y(of)h(the)g(follo)o
+(wing)i(v)m(ariable)f(expansion)h(is)f(used:)20 b Fk
+(${FCEDIT:-${EDITOR:-vi}})o Fl(.)d(This)e(sa)o(ys)f(to)240
+681 y(use)g(the)g(v)m(alue)g(of)f(the)h Fk(FCEDIT)f Fl(v)m(ariable)i
+(if)f(set,)f(or)g(the)h(v)m(alue)g(of)f(the)h Fk(EDITOR)f
+Fl(v)m(ariable)i(if)f(that)e(is)240 744 y(set,)i(or)g
+Fk(vi)h Fl(if)g(neither)h(is)f(set.)20 b(When)15 b(editing)h(is)f
+(complete,)g(the)g(edited)h(commands)f(are)f(ec)o(ho)q(ed)240
+806 y(and)h(executed.)240 881 y(In)h(the)g(second)g(form,)f
+Fg(command)i Fl(is)f(re-executed)h(after)e(eac)o(h)h(instance)g(of)f
+Fg(pat)i Fl(in)f(the)g(selected)240 944 y(command)f(is)h(replaced)g(b)o
+(y)f Fg(rep)p Fl(.)240 1019 y(A)20 b(useful)i(alias)f(to)e(use)i(with)f
+(the)h Fk(fc)f Fl(command)g(is)h Fk(r='fc)14 b(-s')p
+Fl(,)21 b(so)f(that)f(t)o(yping)i Fk(r)15 b(cc)20 b Fl(runs)240
+1081 y(the)c(last)g(command)h(b)q(eginning)h(with)f Fk(cc)e
+Fl(and)i(t)o(yping)f Fk(r)g Fl(re-executes)h(the)g(last)f(command)g
+(\(see)240 1144 y(Section)g(3.4)e([Aliases],)h(page)h(13\).)0
+1232 y Fk(let)168 b Fl(The)15 b Fk(let)f Fl(builtin)j(allo)o(ws)d
+(arithmetic)h(to)f(b)q(e)i(p)q(erformed)e(on)h(shell)h(v)m(ariables.)21
+b(F)l(or)14 b(details,)h(refer)240 1294 y(to)g(Section)h(4.7.3)d
+([Arithmetic)j(Builtins],)h(page)e(26.)0 1383 y Fk(typeset)72
+b Fl(The)17 b Fk(typeset)f Fl(command)h(is)h(supplied)h(for)d
+(compatibilit)o(y)j(with)e(the)g(Korn)g(shell;)i(ho)o(w)o(ev)o(er,)e
+(it)240 1445 y(has)j(b)q(een)i(made)f(obsolete)g(b)o(y)f(the)h
+Fk(declare)e Fl(command)i(\(see)f(Section)i(4.4)d([Bash)i(Builtins],)
+240 1508 y(page)15 b(17\).)0 1738 y Fj(3.3)33 b(Korn)15
+b(Shell)i(V)-6 b(ariables)0 1889 y Fk(REPLY)120 b Fl(The)15
+b(default)h(v)m(ariable)h(for)d(the)i Fk(read)e Fl(builtin.)0
+1978 y Fk(RANDOM)96 b Fl(Eac)o(h)19 b(time)h(this)f(parameter)g(is)h
+(referenced,)h(a)e(random)f(in)o(teger)i(is)g(generated.)32
+b(Assigning)20 b(a)240 2040 y(v)m(alue)c(to)f(this)h(v)m(ariable)g
+(seeds)g(the)f(random)g(n)o(um)o(b)q(er)g(generator.)0
+2129 y Fk(SECONDS)72 b Fl(This)13 b(v)m(ariable)g(expands)g(to)e(the)h
+(n)o(um)o(b)q(er)g(of)g(seconds)h(since)g(the)f(shell)h(w)o(as)f
+(started.)18 b(Assignmen)o(t)240 2191 y(to)12 b(this)i(v)m(ariable)g
+(resets)e(the)h(coun)o(t)g(to)f(the)h(v)m(alue)i(assigned,)e(and)g(the)
+g(expanded)h(v)m(alue)g(b)q(ecomes)240 2253 y(the)h(v)m(alue)i
+(assigned)f(plus)g(the)f(n)o(um)o(b)q(er)h(of)e(seconds)i(since)g(the)g
+(assignmen)o(t.)0 2342 y Fk(PS3)168 b Fl(The)15 b(v)m(alue)i(of)e(this)
+g(v)m(ariable)i(is)f(used)f(as)g(the)g(prompt)g(for)g(the)g
+Fk(select)f Fl(command.)0 2430 y Fk(PS4)168 b Fl(This)18
+b(is)f(the)g(prompt)g(prin)o(ted)h(b)q(efore)f(the)g(command)g(line)i
+(is)f(ec)o(ho)q(ed)g(when)f(the)g Fk(-x)g Fl(option)g(is)240
+2493 y(set)e(\(see)g(Section)h(4.5)e([The)i(Set)f(Builtin],)h(page)g
+(20\).)0 2581 y Fk(PWD)168 b Fl(The)15 b(curren)o(t)h(w)o(orking)e
+(directory)i(as)f(set)g(b)o(y)g(the)g Fk(cd)g Fl(builtin.)0
+2670 y Fk(OLDPWD)96 b Fl(The)15 b(previous)h(w)o(orking)f(directory)h
+(as)e(set)h(b)o(y)h(the)f Fk(cd)g Fl(builtin.)p eop
+13 14 bop 0 -58 a Fl(Chapter)15 b(3:)k(Korn)d(Shell)h(St)o(yle)e(F)l
+(eatures)1164 b(13)0 183 y Fk(TMOUT)120 b Fl(If)14 b(set)g(to)g(a)g(v)m
+(alue)h(greater)e(than)h(zero,)g(the)g(v)m(alue)i(is)e(in)o(terpreted)h
+(as)f(the)g(n)o(um)o(b)q(er)g(of)g(seconds)h(to)240 246
+y(w)o(ait)f(for)f(input)i(after)e(issuing)i(the)g(primary)f(prompt.)19
+b(Bash)14 b(terminates)g(after)f(that)g(n)o(um)o(b)q(er)h(of)240
+308 y(seconds)i(if)f(input)i(do)q(es)e(not)g(arriv)o(e.)0
+528 y Fj(3.4)33 b(Aliases)62 665 y Fl(The)19 b(shell)i(main)o(tains)e
+(a)f(list)i(of)e Fg(aliases)k Fl(that)c(ma)o(y)g(b)q(e)h(set)g(and)g
+(unset)g(with)g(the)g Fk(alias)f Fl(and)h Fk(unalias)0
+727 y Fl(builtin)e(commands.)62 864 y(The)i(\014rst)f(w)o(ord)f(of)h
+(eac)o(h)h(command,)f(if)h(unquoted,)g(is)g(c)o(hec)o(k)o(ed)g(to)f
+(see)g(if)h(it)g(has)f(an)g(alias.)30 b(If)18 b(so,)h(that)0
+927 y(w)o(ord)12 b(is)i(replaced)g(b)o(y)f(the)g(text)f(of)h(the)g
+(alias.)20 b(The)13 b(alias)h(name)f(and)g(the)g(replacemen)o(t)g(text)
+g(ma)o(y)f(con)o(tain)h(an)o(y)0 989 y(v)m(alid)18 b(shell)h(input,)f
+(including)h(shell)g(metac)o(haracters,)c(with)i(the)g(exception)h
+(that)e(the)h(alias)g(name)g(ma)o(y)f(not)0 1051 y(con)o(tain)g
+Fk(=)p Fl(.)k(The)c(\014rst)f(w)o(ord)f(of)h(the)h(replacemen)o(t)g
+(text)f(is)h(tested)f(for)g(aliases,)h(but)g(a)f(w)o(ord)f(that)h(is)h
+(iden)o(tical)0 1113 y(to)g(an)h(alias)h(b)q(eing)g(expanded)g(is)g
+(not)e(expanded)i(a)f(second)h(time.)25 b(This)18 b(means)f(that)f(one)
+h(ma)o(y)f(alias)i Fk(ls)f Fl(to)0 1176 y Fk("ls)e(-F")p
+Fl(,)j(for)f(instance,)j(and)e(Bash)g(do)q(es)h(not)f(try)f(to)h
+(recursiv)o(ely)h(expand)g(the)f(replacemen)o(t)h(text.)28
+b(If)19 b(the)0 1238 y(last)14 b(c)o(haracter)f(of)h(the)g(alias)h(v)m
+(alue)g(is)g(a)e(space)i(or)e(tab)h(c)o(haracter,)f(then)i(the)f(next)g
+(command)g(w)o(ord)f(follo)o(wing)0 1300 y(the)i(alias)h(is)g(also)f(c)
+o(hec)o(k)o(ed)h(for)e(alias)i(expansion.)62 1437 y(Aliases)i(are)f
+(created)g(and)g(listed)h(with)f(the)g Fk(alias)g Fl(command,)f(and)h
+(remo)o(v)o(ed)g(with)g(the)g Fk(unalias)f Fl(com-)0
+1499 y(mand.)62 1636 y(There)i(is)h(no)f(mec)o(hanism)g(for)f(using)i
+(argumen)o(ts)e(in)i(the)f(replacemen)o(t)g(text,)g(as)f(in)i
+Fk(csh)p Fl(.)28 b(If)18 b(argumen)o(ts)0 1699 y(are)d(needed,)h(a)f
+(shell)i(function)f(should)g(b)q(e)g(used.)62 1836 y(Aliases)h(are)d
+(not)h(expanded)i(when)e(the)g(shell)i(is)f(not)f(in)o(teractiv)o(e.)62
+1973 y(The)d(rules)g(concerning)g(the)g(de\014nition)h(and)e(use)h(of)f
+(aliases)h(are)e(somewhat)h(confusing.)19 b(Bash)12 b(alw)o(a)o(ys)e
+(reads)0 2035 y(at)k(least)h(one)g(complete)h(line)g(of)f(input)g(b)q
+(efore)h(executing)g(an)o(y)e(of)g(the)h(commands)g(on)g(that)f(line.)
+21 b(Aliases)16 b(are)0 2097 y(expanded)c(when)g(a)f(command)g(is)g
+(read,)h(not)f(when)g(it)h(is)f(executed.)20 b(Therefore,)11
+b(an)g(alias)h(de\014nition)h(app)q(earing)0 2159 y(on)h(the)g(same)g
+(line)h(as)f(another)f(command)h(do)q(es)h(not)e(tak)o(e)g(e\013ect)h
+(un)o(til)h(the)f(next)g(line)i(of)d(input)i(is)g(read.)k(This)0
+2222 y(means)f(that)f(the)h(commands)f(follo)o(wing)i(the)f(alias)g
+(de\014nition)i(on)d(that)g(line)j(are)d(not)h(a\013ected)f(b)o(y)h
+(the)g(new)0 2284 y(alias.)24 b(This)16 b(b)q(eha)o(vior)h(is)g(also)f
+(an)g(issue)h(when)g(functions)g(are)f(executed.)24 b(Aliases)17
+b(are)f(expanded)h(when)g(the)0 2346 y(function)e(de\014nition)h(is)e
+(read,)g(not)f(when)i(the)f(function)g(is)h(executed,)g(b)q(ecause)f(a)
+g(function)h(de\014nition)h(is)e(itself)0 2408 y(a)g(comp)q(ound)g
+(command.)20 b(As)13 b(a)h(consequence,)h(aliases)g(de\014ned)g(in)g(a)
+e(function)i(are)f(not)f(a)o(v)m(ailable)j(un)o(til)f(after)0
+2471 y(that)i(function)h(is)g(executed.)27 b(T)l(o)17
+b(b)q(e)h(safe,)f(alw)o(a)o(ys)g(put)g(alias)h(de\014nitions)h(on)f(a)f
+(separate)f(line,)k(and)d(do)g(not)0 2533 y(use)f Fk(alias)e
+Fl(in)i(comp)q(ound)g(commands.)62 2670 y(Note)f(that)g(for)f(almost)h
+(ev)o(ery)g(purp)q(ose,)g(aliases)h(are)f(sup)q(erseded)i(b)o(y)e
+(shell)i(functions.)p eop
+14 15 bop 0 -58 a Fl(14)1623 b(Bash)15 b(F)l(eatures)0
+183 y Ff(3.4.1)30 b(Alias)15 b(Builtins)0 333 y Fk(alias)360
+395 y(alias)23 b([)p Fg(name)s Fk([=)p Fg(v)m(alue)s
+Fk(])h(...])240 470 y Fl(Without)16 b(argumen)o(ts,)e(prin)o(t)i(the)g
+(list)g(of)g(aliases)g(on)f(the)h(standard)f(output.)22
+b(If)15 b(argumen)o(ts)g(are)240 532 y(supplied,)k(an)e(alias)g(is)g
+(de\014ned)h(for)e(eac)o(h)h Fg(name)i Fl(whose)d Fg(v)m(alue)21
+b Fl(is)c(giv)o(en.)25 b(If)17 b(no)f Fg(v)m(alue)21
+b Fl(is)c(giv)o(en,)240 594 y(the)e(name)g(and)h(v)m(alue)g(of)f(the)g
+(alias)h(is)g(prin)o(ted.)0 681 y Fk(unalias)360 744
+y(unalias)23 b([-a])g([)p Fg(name)k Fk(...)c(])240 818
+y Fl(Remo)o(v)o(e)15 b(eac)o(h)g Fg(name)j Fl(from)d(the)g(list)h(of)f
+(aliases.)20 b(If)c Fk(-a)f Fl(is)g(supplied,)i(all)g(aliases)e(are)g
+(remo)o(v)o(ed.)p eop
+15 16 bop 0 -58 a Fl(Chapter)15 b(4:)k(Bash)d(Sp)q(eci\014c)h(F)l
+(eatures)1226 b(15)0 183 y Fh(4)41 b(Bash)15 b(Sp)r(eci\014c)f(F)-7
+b(eatures)62 369 y Fl(This)16 b(section)g(describ)q(es)h(the)e
+(features)g(unique)h(to)f(Bash.)0 593 y Fj(4.1)33 b(In)n(v)n(oking)17
+b(Bash)62 730 y Fl(In)c(addition)h(to)e(the)h(single-c)o(haracter)g
+(shell)h(command-line)g(options)f(\(see)f(Section)i(4.5)d([The)i(Set)f
+(Builtin],)0 792 y(page)17 b(20\),)f(there)h(are)g(sev)o(eral)h(m)o
+(ulti-c)o(haracter)f(options)g(that)g(y)o(ou)f(can)i(use.)26
+b(These)17 b(options)g(m)o(ust)g(app)q(ear)0 854 y(on)e(the)g(command)g
+(line)i(b)q(efore)f(the)f(single-c)o(haracter)h(options)f(to)g(b)q(e)h
+(recognized.)0 1003 y Fk(-norc)120 b Fl(Don't)20 b(read)h(the)g(`)p
+Fk(~/.bashrc)p Fl(')e(initialization)24 b(\014le)e(in)g(an)f(in)o
+(teractiv)o(e)g(shell.)39 b(This)22 b(is)f(on)g(b)o(y)240
+1066 y(default)16 b(if)f(the)h(shell)h(is)e(in)o(v)o(ok)o(ed)h(as)e
+Fk(sh)p Fl(.)0 1140 y Fk(-rcfile)g Fg(\014lename)240
+1203 y Fl(Execute)i(commands)f(from)f Fg(\014lename)19
+b Fl(\(instead)c(of)g(`)p Fk(~/.bashrc)p Fl('\))e(in)j(an)f(in)o
+(teractiv)o(e)h(shell.)0 1277 y Fk(-noprofile)240 1339
+y Fl(Don't)k(load)h(the)h(system-wide)f(startup)g(\014le)h(`)p
+Fk(/etc/profile)p Fl(')c(or)j(an)o(y)g(of)f(the)i(p)q(ersonal)f(ini-)
+240 1402 y(tialization)g(\014les)g(`)p Fk(~/.bash_profile)p
+Fl(',)d(`)p Fk(~/.bash_login)p Fl(',)g(or)h(`)p Fk(~/.profile)p
+Fl(')f(when)i(bash)g(is)240 1464 y(in)o(v)o(ok)o(ed)15
+b(as)g(a)g(login)h(shell.)0 1551 y Fk(-version)48 b Fl(Displa)o(y)16
+b(the)f(v)o(ersion)g(n)o(um)o(b)q(er)h(of)f(this)g(shell.)0
+1637 y Fk(-login)96 b Fl(Mak)o(e)13 b(this)h(shell)h(act)e(as)g(if)h
+(it)g(w)o(ere)g(directly)h(in)o(v)o(ok)o(ed)e(from)g(login.)20
+b(This)15 b(is)f(equiv)m(alen)o(t)h(to)e(`)p Fk(exec)240
+1700 y(-)i(bash)p Fl(')i(but)h(can)g(b)q(e)h(issued)g(from)f(another)f
+(shell,)j(suc)o(h)f(as)e Fk(csh)p Fl(.)28 b(If)18 b(y)o(ou)g(w)o(an)o
+(ted)g(to)f(replace)240 1762 y(y)o(our)e(curren)o(t)g(login)h(shell)h
+(with)e(a)g(Bash)g(login)h(shell,)h(y)o(ou)e(w)o(ould)g(sa)o(y)g(`)p
+Fk(exec)f(bash)h(-login)p Fl('.)0 1837 y Fk(-nobraceexpansion)240
+1899 y Fl(Do)g(not)f(p)q(erform)h(curly)h(brace)g(expansion)g(\(see)f
+(Section)h(2.2)e([Brace)h(Expansion],)g(page)g(7\).)0
+1973 y Fk(-nolineediting)240 2036 y Fl(Do)c(not)g(use)h(the)f(GNU)h
+(Readline)h(library)g(\(see)e(Chapter)g(7)g([Command)g(Line)i
+(Editing],)g(page)e(37\))240 2098 y(to)k(read)g(in)o(teractiv)o(e)g
+(command)g(lines.)0 2185 y Fk(-posix)96 b Fl(Change)14
+b(the)g(b)q(eha)o(vior)g(of)f(Bash)h(where)g(the)g(default)g(op)q
+(eration)g(di\013ers)g(from)f(the)h(P)o(osix)g(1003.2)240
+2247 y(standard)19 b(to)g(matc)o(h)g(the)h(standard.)32
+b(This)20 b(is)g(in)o(tended)h(to)e(mak)o(e)g(Bash)h(b)q(eha)o(v)o(e)g
+(as)f(a)g(strict)240 2309 y(sup)q(erset)d(of)e(that)h(standard.)62
+2458 y(There)20 b(are)f(sev)o(eral)g(single-c)o(haracter)h(options)g(y)
+o(ou)f(can)g(giv)o(e)h(whic)o(h)g(are)f(not)f(a)o(v)m(ailable)j(with)f
+(the)f Fk(set)0 2521 y Fl(builtin.)0 2670 y Fk(-c)c Fg(string)63
+b Fl(Read)16 b(and)f(execute)h(commands)f(from)g Fg(string)k
+Fl(after)14 b(pro)q(cessing)i(the)f(options,)g(then)h(exit.)p
+eop
+16 17 bop 0 -58 a Fl(16)1623 b(Bash)15 b(F)l(eatures)0
+183 y Fk(-i)192 b Fl(F)l(orce)15 b(the)g(shell)i(to)e(run)g(in)o
+(teractiv)o(ely)l(.)0 285 y Fk(-s)192 b Fl(If)11 b(this)h(\015ag)f(is)h
+(presen)o(t,)f(or)g(if)h(no)f(argumen)o(ts)f(remain)i(after)f(option)g
+(pro)q(cessing,)i(then)e(commands)240 347 y(are)16 b(read)g(from)f(the)
+h(standard)g(input.)24 b(This)16 b(option)h(allo)o(ws)f(the)g(p)q
+(ositional)i(parameters)d(to)g(b)q(e)240 410 y(set)g(when)h(in)o(v)o
+(oking)f(an)h(in)o(teractiv)o(e)f(shell.)62 574 y(An)i
+Fg(in)o(teractiv)o(e)j Fl(shell)e(is)f(one)g(whose)f(input)i(and)f
+(output)f(are)g(b)q(oth)h(connected)h(to)e(terminals)h(\(as)f(deter-)0
+636 y(mined)g(b)o(y)f Fk(isatty\(\))p Fl(\),)f(or)h(one)g(started)f
+(with)i(the)f Fk(-i)g Fl(option.)0 927 y Fj(4.2)33 b(Bash)14
+b(Startup)j(Files)62 1071 y Fl(When)f(and)f(ho)o(w)g(Bash)g(executes)h
+(startup)e(\014les.)120 1203 y Fk(For)23 b(Login)h(shells)f(\(subject)f
+(to)i(the)f(-noprofile)g(option\):)215 1303 y(On)h(logging)f(in:)287
+1353 y(If)h(`/etc/profile')e(exists,)g(then)i(source)f(it.)287
+1452 y(If)h(`~/.bash_profile')d(exists,)i(then)g(source)g(it,)359
+1502 y(else)g(if)h(`~/.bash_login')d(exists,)i(then)h(source)f(it,)430
+1552 y(else)h(if)f(`~/.profile')f(exists,)h(then)h(source)f(it.)215
+1652 y(On)h(logging)f(out:)287 1701 y(If)h(`~/.bash_logout')d(exists,)i
+(source)g(it.)120 1801 y(For)g(non-login)g(interactive)f(shells)h
+(\(subject)g(to)h(the)f(-norc)g(and)h(-rcfile)f(options\):)215
+1851 y(On)h(starting)f(up:)287 1901 y(If)h(`~/.bashrc')e(exists,)h
+(then)g(source)g(it.)120 2000 y(For)g(non-interactive)f(shells:)215
+2050 y(On)i(starting)f(up:)287 2100 y(If)h(the)f(environment)f
+(variable)h(ENV)h(is)f(non-null,)g(expand)g(the)287 2150
+y(variable)g(and)g(source)g(the)h(file)f(named)g(by)h(the)f(value.)47
+b(If)24 b(Bash)f(is)287 2199 y(not)g(started)g(in)h(Posix)f(mode,)g(it)
+h(looks)f(for)h(BASH_ENV)e(before)287 2249 y(ENV.)62
+2394 y Fl(So,)15 b(t)o(ypically)l(,)h(y)o(our)f Fk(~/.bash_profile)e
+Fl(con)o(tains)j(the)f(line)120 2526 y Fk(if)24 b([)f(-f)h(~/.bashrc)f
+(];)g(then)g(source)g(~/.bashrc;)g(fi)0 2670 y Fl(after)14
+b(\(or)h(b)q(efore\))g(an)o(y)g(login)h(sp)q(eci\014c)h
+(initializations.)p eop
+17 18 bop 0 -58 a Fl(Chapter)15 b(4:)k(Bash)d(Sp)q(eci\014c)h(F)l
+(eatures)1226 b(17)62 183 y(If)16 b(Bash)g(is)g(in)o(v)o(ok)o(ed)g(as)f
+Fk(sh)p Fl(,)g(it)g(tries)h(to)f(mimic)i(the)f(b)q(eha)o(vior)g(of)f
+Fk(sh)g Fl(as)g(closely)i(as)e(p)q(ossible.)23 b(F)l(or)15
+b(a)g(login)0 246 y(shell,)g(it)e(attempts)f(to)g(source)i(only)f(`)p
+Fk(/etc/profile)p Fl(')e(and)i(`)p Fk(~/.profile)p Fl(',)e(in)j(that)e
+(order.)19 b(The)13 b Fk(-noprofile)0 308 y Fl(option)h(ma)o(y)g(still)
+h(b)q(e)g(used)g(to)f(disable)h(this)g(b)q(eha)o(vior.)20
+b(A)14 b(shell)i(in)o(v)o(ok)o(ed)e(as)g Fk(sh)g Fl(do)q(es)g(not)g
+(attempt)f(to)h(source)0 370 y(an)o(y)h(other)g(startup)f(\014les.)62
+507 y(When)h(Bash)g(is)g(started)f(in)h Fg(POSIX)21 b
+Fl(mo)q(de,)14 b(as)g(with)h(the)g Fk(-posix)f Fl(command)g(line)j
+(option,)d(it)h(follo)o(ws)g(the)0 570 y(P)o(osix)j(1003.2)e(standard)h
+(for)h(startup)f(\014les.)29 b(In)18 b(this)g(mo)q(de,)h(the)f
+Fk(ENV)f Fl(v)m(ariable)i(is)g(expanded)g(and)f(that)f(\014le)0
+632 y(sourced;)e(no)g(other)g(startup)g(\014les)h(are)f(read.)0
+859 y Fj(4.3)33 b(Is)14 b(This)i(Shell)h(In)n(teractiv)n(e?)62
+996 y Fl(Y)l(ou)c(ma)o(y)f(wish)h(to)f(determine)i(within)g(a)e
+(startup)g(script)h(whether)g(Bash)g(is)g(running)h(in)o(teractiv)o
+(ely)g(or)e(not.)0 1058 y(T)l(o)17 b(do)g(this,)h(examine)g(the)g(v)m
+(ariable)g Fk($PS1)p Fl(;)g(it)f(is)h(unset)g(in)g(non-in)o(teractiv)o
+(e)g(shells,)h(and)e(set)g(in)i(in)o(teractiv)o(e)0 1120
+y(shells.)i(Th)o(us:)120 1245 y Fk(if)j([)f(-z)h("$PS1")f(];)h(then)120
+1295 y(echo)f(This)h(shell)f(is)g(not)h(interactive)120
+1345 y(else)120 1395 y(echo)f(This)h(shell)f(is)g(interactive)120
+1444 y(fi)62 1582 y Fl(Y)l(ou)16 b(can)f(ask)f(an)h(in)o(teractiv)o(e)h
+(Bash)f(to)f(not)h(run)g(y)o(our)g(`)p Fk(~/.bashrc)p
+Fl(')e(\014le)j(with)g(the)f Fk(-norc)f Fl(\015ag.)20
+b(Y)l(ou)15 b(can)0 1644 y(c)o(hange)j(the)f(name)h(of)f(the)h(`)p
+Fk(~/.bashrc)p Fl(')d(\014le)k(to)e(an)o(y)g(other)g(\014le)i(name)e
+(with)h Fk(-rcfile)c Fg(\014lename)s Fl(.)28 b(Y)l(ou)18
+b(can)0 1706 y(ask)d(Bash)g(to)g(not)f(run)i(y)o(our)f(`)p
+Fk(~/.bash_profile)p Fl(')d(\014le)k(with)g(the)f Fk(-noprofile)f
+Fl(\015ag.)0 1933 y Fj(4.4)33 b(Bash)14 b(Builtin)k(Commands)62
+2070 y Fl(This)e(section)g(describ)q(es)h(builtin)g(commands)e(whic)o
+(h)h(are)f(unique)i(to)d(or)h(ha)o(v)o(e)g(b)q(een)h(extended)g(in)g
+(Bash.)0 2220 y Fk(builtin)360 2283 y(builtin)23 b([)p
+Fg(shell-builti)q(n)k Fk([)p Fg(args)r Fk(]])240 2358
+y Fl(Run)20 b(a)f(shell)h(builtin.)34 b(This)20 b(is)g(useful)g(when)f
+(y)o(ou)g(wish)h(to)e(rename)h(a)g(shell)i(builtin)g(to)e(b)q(e)g(a)240
+2420 y(function,)d(but)f(need)h(the)f(functionalit)o(y)i(of)e(the)g
+(builtin)i(within)g(the)e(function)h(itself.)0 2508 y
+Fk(bind)360 2570 y(bind)23 b([-m)h Fg(k)o(eymap)q Fk(])g([-lvd])f([-q)g
+Fg(name)s Fk(])360 2620 y(bind)g([-m)h Fg(k)o(eymap)q
+Fk(])g(-f)f Fg(\014lename)360 2670 y Fk(bind)g([-m)h
+Fg(k)o(eymap)q Fk(])g Fg(k)o(eyseq:function-name)p eop
+18 19 bop 0 -58 a Fl(18)1623 b(Bash)15 b(F)l(eatures)240
+183 y(Displa)o(y)k(curren)o(t)e(Readline)k(\(see)c(Chapter)h(7)g
+([Command)f(Line)i(Editing],)g(page)f(37\))f(k)o(ey)h(and)240
+246 y(function)24 b(bindings,)j(or)c(bind)h(a)f(k)o(ey)g(sequence)i(to)
+d(a)h(Readline)j(function)e(or)e(macro.)44 b(The)240
+308 y(binding)25 b(syn)o(tax)d(accepted)i(is)g(iden)o(tical)h(to)d
+(that)h(of)f(`)p Fk(.inputrc)p Fl(')f(\(see)i(Section)h(7.3)f([Read-)
+240 370 y(line)f(Init)g(File],)h(page)d(40\),)h(but)g(eac)o(h)g
+(binding)i(m)o(ust)d(b)q(e)i(passed)f(as)f(a)h(separate)f(argumen)o(t:)
+240 432 y(`)p Fk("\\C-x\\C-r":re-read-init)o(-file)p
+Fl(')o(.)d(Options,)e(if)f(supplied,)i(ha)o(v)o(e)e(the)g(follo)o(wing)
+h(meanings:)240 518 y Fk(-m)g(keymap)33 b Fl(Use)14 b
+Fg(k)o(eymap)h Fl(as)e(the)h(k)o(eymap)f(to)g(b)q(e)h(a\013ected)g(b)o
+(y)f(the)h(subsequen)o(t)g(bindings.)22 b(Ac-)480 580
+y(ceptable)14 b Fg(k)o(eymap)h Fl(names)e(are)g Fk(emacs)p
+Fl(,)g Fk(emacs-standard)p Fl(,)e Fk(emacs-meta)p Fl(,)h
+Fk(emacs-)480 643 y(ctlx)p Fl(,)k Fk(vi)p Fl(,)h Fk(vi-move)p
+Fl(,)f Fk(vi-command)p Fl(,)g(and)h Fk(vi-insert)p Fl(.)23
+b Fk(vi)17 b Fl(is)g(equiv)m(alen)o(t)i(to)d Fk(vi-)480
+705 y(command)p Fl(;)e Fk(emacs)g Fl(is)i(equiv)m(alen)o(t)h(to)d
+Fk(emacs-standard)p Fl(.)240 791 y Fk(-l)192 b Fl(List)16
+b(the)f(names)g(of)g(all)h(readline)h(functions)240 877
+y Fk(-v)192 b Fl(List)16 b(curren)o(t)f(function)h(names)f(and)g
+(bindings)240 962 y Fk(-d)192 b Fl(Dump)13 b(function)h(names)f(and)h
+(bindings)h(in)f(suc)o(h)f(a)g(w)o(a)o(y)f(that)h(they)g(can)g(b)q(e)h
+(re-read)240 1036 y Fk(-f)h(filename)480 1099 y Fl(Read)h(k)o(ey)f
+(bindings)i(from)d Fg(\014lename)240 1184 y Fk(-q)192
+b Fl(Query)16 b(ab)q(out)f(whic)o(h)h(k)o(eys)f(in)o(v)o(ok)o(e)g(the)g
+(named)h Fg(function)0 1270 y Fk(command)360 1332 y(command)23
+b([-pVv])g Fg(command)j Fk([)p Fg(args)e Fk(...])240
+1406 y Fl(Runs)18 b Fg(command)i Fl(with)d Fg(arg)k Fl(ignoring)d
+(shell)h(functions.)28 b(If)18 b(y)o(ou)f(ha)o(v)o(e)g(a)g(shell)i
+(function)f(called)240 1468 y Fk(ls)p Fl(,)f(and)h(y)o(ou)f(wish)h(to)f
+(call)h(the)g(command)f Fk(ls)p Fl(,)g(y)o(ou)g(can)h(sa)o(y)e(`)p
+Fk(command)e(ls)p Fl('.)26 b(The)18 b Fk(-p)f Fl(option)240
+1530 y(means)g(to)g(use)g(a)g(default)h(v)m(alue)g(for)f
+Fk($PATH)g Fl(that)f(is)i(guaran)o(teed)f(to)f(\014nd)i(all)g(of)f(the)
+g(standard)240 1593 y(utilities.)240 1667 y(If)i(either)h(the)f
+Fk(-V)g Fl(or)f Fk(-v)h Fl(option)g(is)h(supplied,)i(a)c(description)j
+(of)d Fg(command)j Fl(is)f(prin)o(ted.)32 b(The)240 1729
+y Fk(-v)19 b Fl(option)h(causes)f(a)g(single)i(w)o(ord)d(indicating)j
+(the)f(command)f(or)g(\014le)h(name)f(used)h(to)f(in)o(v)o(ok)o(e)240
+1791 y Fg(command)e Fl(to)d(b)q(e)i(prin)o(ted;)g(the)f
+Fk(-V)g Fl(option)g(pro)q(duces)h(a)f(more)g(v)o(erb)q(ose)g
+(description.)0 1877 y Fk(declare)360 1939 y(declare)23
+b([-frxi])g([)p Fg(name)s Fk([=)p Fg(v)m(alue)s Fk(]])240
+2013 y Fl(Declare)15 b(v)m(ariables)h(and/or)d(giv)o(e)i(them)f
+(attributes.)20 b(If)15 b(no)f Fg(name)s Fl(s)g(are)g(giv)o(en,)h(then)
+f(displa)o(y)i(the)240 2075 y(v)m(alues)k(of)f(v)m(ariables)i(instead.)
+33 b Fk(-f)19 b Fl(means)g(to)g(use)h(function)g(names)f(only)l(.)33
+b Fk(-r)19 b Fl(sa)o(ys)g(to)f(mak)o(e)240 2137 y Fg(name)s
+Fl(s)d(readonly)l(.)22 b Fk(-x)15 b Fl(sa)o(ys)g(to)g(mark)g
+Fg(name)s Fl(s)g(for)g(exp)q(ort.)21 b Fk(-i)16 b Fl(sa)o(ys)f(that)f
+(the)i(v)m(ariable)h(is)f(to)f(b)q(e)240 2199 y(treated)c(as)h(an)f(in)
+o(teger;)i(arithmetic)f(ev)m(aluation)h(\(see)f(Section)h(4.7)d([Shell)
+k(Arithmetic],)e(page)g(24\))240 2262 y(is)17 b(p)q(erformed)f(when)h
+(the)g(v)m(ariable)g(is)g(assigned)g(a)f(v)m(alue.)24
+b(Using)17 b Fk(+)f Fl(instead)h(of)f Fk(-)g Fl(turns)g(o\013)g(the)240
+2324 y(attribute)h(instead.)24 b(When)17 b(used)h(in)f(a)f(function,)i
+Fk(declare)e Fl(mak)o(es)g Fg(name)s Fl(s)g(lo)q(cal,)i(as)e(with)h
+(the)240 2386 y Fk(local)d Fl(command.)0 2472 y Fk(enable)360
+2534 y(enable)23 b([-n])g([-a])h([)p Fg(name)i Fk(...])240
+2608 y Fl(Enable)19 b(and)f(disable)h(builtin)i(shell)e(commands.)28
+b(This)19 b(allo)o(ws)f(y)o(ou)f(to)h(use)g(a)f(disk)i(command)240
+2670 y(whic)o(h)d(has)f(the)g(same)f(name)h(as)g(a)f(shell)j(builtin.)
+22 b(If)15 b Fk(-n)g Fl(is)g(used,)g(the)g Fg(name)s
+Fl(s)g(b)q(ecome)h(disabled.)p eop
+19 20 bop 0 -58 a Fl(Chapter)15 b(4:)k(Bash)d(Sp)q(eci\014c)h(F)l
+(eatures)1226 b(19)240 183 y(Otherwise)18 b Fg(name)s
+Fl(s)f(are)g(enabled.)28 b(F)l(or)17 b(example,)h(to)f(use)h(the)f
+Fk(test)g Fl(binary)h(found)g(via)g Fk($PATH)240 246
+y Fl(instead)c(of)f(the)g(shell)i(builtin)g(v)o(ersion,)e(t)o(yp)q(e)h
+(`)p Fk(enable)g(-n)h(test)p Fl('.)j(The)13 b Fk(-a)g
+Fl(option)g(means)h(to)e(list)240 308 y(eac)o(h)j(builtin)j(with)d(an)g
+(indication)j(of)c(whether)i(or)e(not)h(it)h(is)f(enabled.)0
+396 y Fk(help)360 459 y(help)23 b([)p Fg(pattern)p Fk(])240
+535 y Fl(Displa)o(y)13 b(helpful)i(information)e(ab)q(out)f(builtin)j
+(commands.)k(If)13 b Fg(pattern)f Fl(is)i(sp)q(eci\014ed,)h
+Fk(help)d Fl(giv)o(es)240 597 y(detailed)22 b(help)g(on)f(all)h
+(commands)f(matc)o(hing)f Fg(pattern)p Fl(,)i(otherwise)f(a)f(list)i
+(of)f(the)f(builtins)j(is)240 659 y(prin)o(ted.)0 748
+y Fk(local)360 811 y(local)g Fg(name)s Fk([=)p Fg(v)m(alue)s
+Fk(])240 886 y Fl(F)l(or)10 b(eac)o(h)g(argumen)o(t,)g(create)h(a)f(lo)
+q(cal)h(v)m(ariable)h(called)g Fg(name)p Fl(,)f(and)f(giv)o(e)h(it)g
+Fg(v)m(alue)p Fl(.)19 b Fk(local)10 b Fl(can)g(only)240
+948 y(b)q(e)18 b(used)f(within)i(a)d(function;)j(it)e(mak)o(es)f(the)i
+(v)m(ariable)g Fg(name)i Fl(ha)o(v)o(e)c(a)h(visible)i(scop)q(e)f
+(restricted)240 1010 y(to)d(that)f(function)i(and)f(its)h(c)o(hildren.)
+0 1099 y Fk(type)360 1162 y(type)23 b([-all])g([-type)g(|)h(-path])f([)
+p Fg(name)k Fk(...])240 1237 y Fl(F)l(or)15 b(eac)o(h)g
+Fg(name)p Fl(,)g(indicate)h(ho)o(w)f(it)h(w)o(ould)f(b)q(e)h(in)o
+(terpreted)g(if)f(used)h(as)f(a)g(command)g(name.)240
+1313 y(If)e(the)g Fk(-type)g Fl(\015ag)f(is)i(used,)f
+Fk(type)g Fl(returns)g(a)f(single)j(w)o(ord)d(whic)o(h)i(is)f(one)g(of)
+g(\\alias",)g(\\function",)240 1375 y(\\builtin",)i(\\\014le")f(or)g
+(\\k)o(eyw)o(ord",)e(if)i Fg(name)i Fl(is)e(an)g(alias,)g(shell)h
+(function,)g(shell)g(builtin,)h(disk)e(\014le,)240 1437
+y(or)h(shell)h(reserv)o(ed)g(w)o(ord,)e(resp)q(ectiv)o(ely)l(.)240
+1512 y(If)j(the)g Fk(-path)g Fl(\015ag)f(is)i(used,)g
+Fk(type)e Fl(either)i(returns)f(the)g(name)g(of)g(the)g(disk)g(\014le)i
+(that)d(w)o(ould)h(b)q(e)240 1575 y(executed,)f(or)e(nothing)i(if)g
+Fk(-type)e Fl(w)o(ould)i(not)f(return)g(\\\014le".)240
+1650 y(If)f(the)g Fk(-all)g Fl(\015ag)f(is)i(used,)f(returns)g(all)h
+(of)f(the)g(places)g(that)g(con)o(tain)g(an)g(executable)h(named)f
+Fg(\014le)p Fl(.)240 1712 y(This)i(includes)h(aliases)f(and)g
+(functions,)f(if)h(and)f(only)h(if)g(the)f Fk(-path)f
+Fl(\015ag)h(is)h(not)f(also)g(used.)240 1788 y Fk(Type)g
+Fl(accepts)g Fk(-a)p Fl(,)f Fk(-t)p Fl(,)h(and)g Fk(-p)g
+Fl(as)g(equiv)m(alen)o(t)i(to)d Fk(-all)p Fl(,)h Fk(-type)p
+Fl(,)f(and)h Fk(-path)p Fl(,)f(resp)q(ectiv)o(ely)l(.)0
+1876 y Fk(ulimit)360 1939 y(ulimit)23 b([-acdmstfpnuvSH])f([)p
+Fg(limit)q Fk(])240 2015 y(Ulimit)15 b Fl(pro)o(vides)i(con)o(trol)f(o)
+o(v)o(er)f(the)i(resources)f(a)o(v)m(ailable)i(to)d(pro)q(cesses)i
+(started)e(b)o(y)h(the)h(shell,)240 2077 y(on)e(systems)g(that)f(allo)o
+(w)i(suc)o(h)f(con)o(trol.)20 b(If)15 b(an)g(option)h(is)g(giv)o(en,)f
+(it)g(is)h(in)o(terpreted)g(as)f(follo)o(ws:)240 2165
+y Fk(-S)192 b Fl(c)o(hange)16 b(and)g(rep)q(ort)g(the)g(soft)f(limit)i
+(asso)q(ciated)f(with)h(a)e(resource)h(\(the)g(default)g(if)480
+2228 y(the)f Fk(-H)g Fl(option)h(is)f(not)g(giv)o(en\).)240
+2316 y Fk(-H)192 b Fl(c)o(hange)15 b(and)h(rep)q(ort)f(the)g(hard)g
+(limit)i(asso)q(ciated)e(with)h(a)e(resource.)240 2405
+y Fk(-a)192 b Fl(all)16 b(curren)o(t)f(limits)i(are)e(rep)q(orted.)240
+2493 y Fk(-c)192 b Fl(the)15 b(maxim)o(um)g(size)i(of)d(core)h(\014les)
+i(created.)240 2582 y Fk(-d)192 b Fl(the)15 b(maxim)o(um)g(size)i(of)d
+(a)h(pro)q(cess's)g(data)g(segmen)o(t.)240 2670 y Fk(-m)192
+b Fl(the)15 b(maxim)o(um)g(residen)o(t)h(set)f(size.)p
+eop
+20 21 bop 0 -58 a Fl(20)1623 b(Bash)15 b(F)l(eatures)240
+183 y Fk(-s)192 b Fl(the)15 b(maxim)o(um)g(stac)o(k)g(size.)240
+268 y Fk(-t)192 b Fl(the)15 b(maxim)o(um)g(amoun)o(t)g(of)g(cpu)g(time)
+h(in)g(seconds.)240 353 y Fk(-f)192 b Fl(the)15 b(maxim)o(um)g(size)i
+(of)d(\014les)i(created)g(b)o(y)f(the)g(shell.)240 438
+y Fk(-p)192 b Fl(the)15 b(pip)q(e)i(bu\013er)e(size.)240
+523 y Fk(-n)192 b Fl(the)15 b(maxim)o(um)g(n)o(um)o(b)q(er)h(of)f(op)q
+(en)h(\014le)g(descriptors.)240 608 y Fk(-u)192 b Fl(the)15
+b(maxim)o(um)g(n)o(um)o(b)q(er)h(of)f(pro)q(cesses)g(a)o(v)m(ailable)i
+(to)e(a)g(single)h(user.)240 693 y Fk(-v)192 b Fl(the)15
+b(maxim)o(um)g(amoun)o(t)g(of)g(virtual)g(memory)g(a)o(v)m(ailable)i
+(to)d(the)i(pro)q(cess.)240 778 y(If)i Fg(limit)i Fl(is)e(giv)o(en,)g
+(it)g(is)g(the)f(new)h(v)m(alue)h(of)e(the)g(sp)q(eci\014ed)j
+(resource.)27 b(Otherwise,)18 b(the)g(curren)o(t)240
+841 y(v)m(alue)h(of)d(the)i(sp)q(eci\014ed)h(resource)f(is)f(prin)o
+(ted.)27 b(If)18 b(no)f(option)h(is)g(giv)o(en,)f(then)h(`)p
+Fk(-f)p Fl(')e(is)i(assumed.)240 903 y(V)l(alues)f(are)e(in)i(1024-b)o
+(yte)d(incremen)o(ts,)i(except)h(for)e(`)p Fk(-t)p Fl(',)f(whic)o(h)j
+(is)f(in)h(seconds,)e(`)p Fk(-p)p Fl(',)g(whic)o(h)h(is)240
+965 y(in)g(units)g(of)f(512-b)o(yte)f(blo)q(c)o(ks,)i(and)f(`)p
+Fk(-n)p Fl(')f(and)h(`)p Fk(-u)p Fl(',)f(whic)o(h)i(are)f(unscaled)i(v)
+m(alues.)0 1185 y Fj(4.5)33 b(The)15 b(Set)g(Builtin)62
+1322 y Fl(This)h(builtin)i(is)d(so)g(o)o(v)o(erloaded)g(that)g(it)g
+(deserv)o(es)h(its)f(o)o(wn)g(section.)0 1470 y Fk(set)360
+1531 y(set)23 b([-abefhkmnptuvxldCHP])e([-o)j Fg(option)p
+Fk(])g([)p Fg(argumen)o(t)g Fk(...])240 1616 y(-a)192
+b Fl(Mark)14 b(v)m(ariables)j(whic)o(h)f(are)f(mo)q(di\014ed)h(or)f
+(created)g(for)g(exp)q(ort.)240 1701 y Fk(-b)192 b Fl(Cause)19
+b(the)g(status)f(of)g(terminated)h(bac)o(kground)g(jobs)g(to)f(b)q(e)h
+(rep)q(orted)g(immedi-)480 1764 y(ately)l(,)c(rather)g(than)g(b)q
+(efore)g(prin)o(ting)h(the)g(next)f(primary)g(prompt.)240
+1849 y Fk(-e)192 b Fl(Exit)15 b(immediately)i(if)f(a)f(command)g(exits)
+g(with)h(a)f(non-zero)g(status.)240 1934 y Fk(-f)192
+b Fl(Disable)16 b(\014le)g(name)g(generation)f(\(globbing\).)240
+2019 y Fk(-h)192 b Fl(Lo)q(cate)19 b(and)h(remem)o(b)q(er)f(\(hash\))f
+(commands)h(as)g(functions)h(are)e(de\014ned,)k(rather)480
+2081 y(than)15 b(when)h(the)f(function)h(is)g(executed.)240
+2166 y Fk(-k)192 b Fl(All)16 b(k)o(eyw)o(ord)d(argumen)o(ts)h(are)g
+(placed)i(in)f(the)g(en)o(vironmen)o(t)f(for)g(a)g(command,)g(not)480
+2228 y(just)h(those)g(that)f(precede)j(the)e(command)g(name.)240
+2313 y Fk(-m)192 b Fl(Job)15 b(con)o(trol)g(is)h(enabled)h(\(see)e
+(Chapter)g(5)g([Job)g(Con)o(trol],)f(page)h(29\).)240
+2398 y Fk(-n)192 b Fl(Read)16 b(commands)f(but)g(do)g(not)g(execute)h
+(them.)240 2472 y Fk(-o)f Fg(option-name)480 2534 y Fl(Set)g(the)h
+(\015ag)e(corresp)q(onding)j(to)d Fg(option-name)s Fl(:)480
+2608 y Fk(allexport)720 2670 y Fl(same)h(as)g Fk(-a)p
+Fl(.)p eop
+21 22 bop 0 -58 a Fl(Chapter)15 b(4:)k(Bash)d(Sp)q(eci\014c)h(F)l
+(eatures)1226 b(21)480 183 y Fk(braceexpand)720 246 y
+Fl(the)16 b(shell)i(will)g(p)q(erform)e(brace)g(expansion)h(\(see)f
+(Section)h(2.2)e([Brace)720 308 y(Expansion],)g(page)g(7\).)480
+396 y Fk(emacs)120 b Fl(use)15 b(an)g(emacs-st)o(yle)h(line)g(editing)h
+(in)o(terface)e(\(see)g(Chapter)g(7)g([Com-)720 458 y(mand)g(Line)i
+(Editing],)e(page)g(37\).)480 547 y Fk(errexit)72 b Fl(same)15
+b(as)g Fk(-e)p Fl(.)480 622 y Fk(histexpand)720 685 y
+Fl(same)g(as)g Fk(-H)p Fl(.)480 760 y Fk(ignoreeof)720
+822 y Fl(the)g(shell)i(will)g(not)e(exit)g(up)q(on)h(reading)g(EOF.)480
+898 y Fk(interactive-comments)720 960 y Fl(allo)o(w)h(a)g(w)o(ord)g(b)q
+(eginning)i(with)f(a)e(`)p Fk(#)p Fl(')h(to)f(cause)i(that)e(w)o(ord)h
+(and)g(all)720 1022 y(remaining)11 b(c)o(haracters)f(on)g(that)f(line)j
+(to)e(b)q(e)h(ignored)f(in)h(an)g(in)o(teractiv)o(e)720
+1084 y(shell.)480 1173 y Fk(monitor)72 b Fl(same)15 b(as)g
+Fk(-m)p Fl(.)480 1248 y Fk(noclobber)720 1310 y Fl(same)g(as)g
+Fk(-C)p Fl(.)480 1399 y Fk(noexec)96 b Fl(same)15 b(as)g
+Fk(-n)p Fl(.)480 1487 y Fk(noglob)96 b Fl(same)15 b(as)g
+Fk(-f)p Fl(.)480 1576 y Fk(nohash)96 b Fl(same)15 b(as)g
+Fk(-d)p Fl(.)480 1664 y Fk(notify)96 b Fl(same)15 b(as)g
+Fk(-b)p Fl(.)480 1753 y Fk(nounset)72 b Fl(same)15 b(as)g
+Fk(-u)p Fl(.)480 1841 y Fk(physical)48 b Fl(same)15 b(as)g
+Fk(-P)p Fl(.)480 1930 y Fk(posix)120 b Fl(c)o(hange)11
+b(the)h(b)q(eha)o(vior)f(of)g(Bash)h(where)f(the)g(default)h(op)q
+(eration)g(di\013ers)720 1992 y(from)17 b(the)g(P)o(osix)g(1003.2)f
+(standard)h(to)f(matc)o(h)h(the)h(standard.)25 b(This)720
+2054 y(is)19 b(in)o(tended)g(to)f(mak)o(e)g(Bash)g(b)q(eha)o(v)o(e)g
+(as)g(a)g(strict)g(sup)q(erset)h(of)f(that)720 2116 y(standard.)480
+2192 y Fk(privileged)720 2254 y Fl(same)d(as)g Fk(-p)p
+Fl(.)480 2342 y Fk(verbose)72 b Fl(same)15 b(as)g Fk(-v)p
+Fl(.)480 2431 y Fk(vi)192 b Fl(use)16 b(a)e Fk(vi)p Fl(-st)o(yle)i
+(line)g(editing)h(in)o(terface.)480 2519 y Fk(xtrace)96
+b Fl(same)15 b(as)g Fk(-x)p Fl(.)240 2608 y Fk(-p)192
+b Fl(T)l(urn)14 b(on)g(privileged)j(mo)q(de.)j(In)14
+b(this)h(mo)q(de,)f(the)g Fk($ENV)g Fl(\014le)h(is)f(not)g(pro)q
+(cessed,)h(and)480 2670 y(shell)21 b(functions)g(are)f(not)f(inherited)
+j(from)d(the)h(en)o(vironmen)o(t.)34 b(This)20 b(is)g(enabled)p
+eop
+22 23 bop 0 -58 a Fl(22)1623 b(Bash)15 b(F)l(eatures)480
+183 y(automatically)g(on)f(startup)f(if)i(the)f(e\013ectiv)o(e)g(user)h
+(\(group\))e(id)i(is)g(not)e(equal)i(to)f(the)480 246
+y(real)j(user)g(\(group\))e(id.)25 b(T)l(urning)18 b(this)f(option)g
+(o\013)f(causes)g(the)h(e\013ectiv)o(e)g(user)g(and)480
+308 y(group)e(ids)h(to)e(b)q(e)i(set)f(to)g(the)g(real)h(user)f(and)g
+(group)g(ids.)240 396 y Fk(-t)192 b Fl(Exit)15 b(after)g(reading)h(and)
+f(executing)h(one)g(command.)240 485 y Fk(-u)192 b Fl(T)l(reat)15
+b(unset)g(v)m(ariables)i(as)d(an)i(error)e(when)i(substituting.)240
+573 y Fk(-v)192 b Fl(Prin)o(t)15 b(shell)i(input)f(lines)h(as)e(they)g
+(are)g(read.)240 661 y Fk(-x)192 b Fl(Prin)o(t)15 b(commands)g(and)h
+(their)f(argumen)o(ts)g(as)f(they)i(are)f(executed.)240
+750 y Fk(-l)192 b Fl(Sa)o(v)o(e)15 b(and)g(restore)g(the)g(binding)i
+(of)e(the)g Fg(name)j Fl(in)e(a)f Fk(for)g Fl(command.)240
+838 y Fk(-d)192 b Fl(Disable)18 b(the)f(hashing)h(of)f(commands)f(that)
+h(are)f(lo)q(ok)o(ed)i(up)f(for)g(execution.)26 b(Nor-)480
+900 y(mally)l(,)15 b(commands)g(are)f(remem)o(b)q(ered)h(in)h(a)e(hash)
+h(table,)f(and)h(once)g(found,)g(do)f(not)480 963 y(ha)o(v)o(e)h(to)f
+(b)q(e)i(lo)q(ok)o(ed)g(up)g(again.)240 1051 y Fk(-C)192
+b Fl(Disallo)o(w)16 b(output)f(redirection)h(to)f(existing)h(\014les.)
+240 1140 y Fk(-H)192 b Fl(Enable)16 b(!)k(st)o(yle)15
+b(history)g(substitution.)21 b(This)16 b(\015ag)f(is)h(on)f(b)o(y)g
+(default.)240 1228 y Fk(-P)192 b Fl(If)14 b(set,)g(do)g(not)g(follo)o
+(w)g(sym)o(b)q(olic)h(links)h(when)f(p)q(erforming)f(commands)g(suc)o
+(h)h(as)e Fk(cd)480 1290 y Fl(whic)o(h)h(c)o(hange)f(the)g(curren)o(t)g
+(directory)l(.)20 b(The)13 b(ph)o(ysical)i(directory)e(is)h(used)g
+(instead.)240 1379 y Fk(--)192 b Fl(If)16 b(no)f(argumen)o(ts)f(follo)o
+(w)i(this)f(\015ag,)g(then)h(the)f(p)q(ositional)i(parameters)d(are)h
+(unset.)480 1441 y(Otherwise,)e(the)e(p)q(ositional)i(parameters)e(are)
+g(set)h(to)f(the)g Fg(argumen)o(ts)p Fl(,)g(ev)o(en)h(if)g(some)480
+1503 y(of)j(them)g(b)q(egin)h(with)g(a)f Fk(-)p Fl(.)240
+1592 y Fk(-)216 b Fl(Signal)15 b(the)g(end)f(of)g(options,)g(cause)h
+(all)g(remaining)g Fg(argumen)o(ts)g Fl(to)f(b)q(e)h(assigned)g(to)480
+1654 y(the)h(p)q(ositional)h(parameters.)22 b(The)16
+b Fk(-x)f Fl(and)i Fk(-v)e Fl(options)h(are)g(turned)g(o\013.)22
+b(If)16 b(there)480 1716 y(are)f(no)g(argumen)o(ts,)f(the)h(p)q
+(ositional)i(parameters)d(remain)i(unc)o(hanged.)240
+1805 y(Using)21 b(`)p Fk(+)p Fl(')e(rather)g(than)h(`)p
+Fk(-)p Fl(')f(causes)h(these)h(\015ags)e(to)h(b)q(e)g(turned)h(o\013.)
+33 b(The)21 b(\015ags)e(can)h(also)g(b)q(e)240 1867 y(used)e(up)q(on)g
+(in)o(v)o(o)q(cation)g(of)f(the)g(shell.)28 b(The)17
+b(curren)o(t)h(set)f(of)g(\015ags)f(ma)o(y)h(b)q(e)h(found)g(in)g
+Fk($-)p Fl(.)26 b(The)240 1929 y(remaining)14 b(N)f Fg(argumen)o(ts)h
+Fl(are)f(p)q(ositional)h(parameters)e(and)i(are)e(assigned,)i(in)g
+(order,)f(to)f Fk($1)p Fl(,)h Fk($2)p Fl(,)240 1991 y(..)19
+b Fk($N)p Fl(.)h(If)15 b(no)h(argumen)o(ts)e(are)h(giv)o(en,)g(all)h
+(shell)h(v)m(ariables)g(are)d(prin)o(ted.)0 2221 y Fj(4.6)33
+b(Bash)14 b(V)-6 b(ariables)62 2359 y Fl(These)16 b(v)m(ariables)g(are)
+f(set)g(or)g(used)h(b)o(y)f(bash,)g(but)g(other)g(shells)i(do)e(not)g
+(normally)g(treat)g(them)g(sp)q(ecially)l(.)0 2496 y
+Fk(HISTCONTROL)0 2545 y(history_control)240 2608 y Fl(Set)i(to)g(a)g(v)
+m(alue)h(of)f(`)p Fk(ignorespace)p Fl(',)e(it)j(means)f(don't)g(en)o
+(ter)g(lines)i(whic)o(h)f(b)q(egin)g(with)g(a)f(space)240
+2670 y(or)f(tab)f(in)o(to)h(the)h(history)f(list.)23
+b(Set)16 b(to)g(a)g(v)m(alue)h(of)f(`)p Fk(ignoredups)p
+Fl(',)d(it)k(means)f(don't)f(en)o(ter)h(lines)p eop
+23 24 bop 0 -58 a Fl(Chapter)15 b(4:)k(Bash)d(Sp)q(eci\014c)h(F)l
+(eatures)1226 b(23)240 183 y(whic)o(h)16 b(matc)o(h)f(the)g(last)g(en)o
+(tered)g(line.)22 b(A)15 b(v)m(alue)h(of)f(`)p Fk(ignoreboth)p
+Fl(')e(com)o(bines)j(the)f(t)o(w)o(o)f(options.)240 246
+y(Unset,)f(or)f(set)g(to)g(an)o(y)h(other)f(v)m(alue)i(than)e(those)h
+(ab)q(o)o(v)o(e,)f(means)h(to)f(sa)o(v)o(e)g(all)h(lines)i(on)d(the)h
+(history)240 308 y(list.)0 398 y Fk(HISTFILE)48 b Fl(The)15
+b(name)h(of)e(the)i(\014le)g(to)e(whic)o(h)j(the)e(command)g(history)g
+(is)h(sa)o(v)o(ed.)0 488 y Fk(HISTSIZE)48 b Fl(If)15
+b(set,)g(this)h(is)f(the)h(maxim)o(um)f(n)o(um)o(b)q(er)g(of)g
+(commands)g(to)g(remem)o(b)q(er)g(in)h(the)f(history)l(.)0
+564 y Fk(histchars)240 627 y Fl(Up)j(to)g(three)g(c)o(haracters)g(whic)
+o(h)h(con)o(trol)e(history)h(expansion,)i(quic)o(k)f(substitution,)g
+(and)f(tok-)240 689 y(enization)j(\(see)e(Section)i(6.1)e([History)g
+(In)o(teraction],)h(page)f(33\).)33 b(The)20 b(\014rst)f(c)o(haracter)g
+(is)h(the)240 751 y Fg(history-expansion-c)o(har)p Fl(,)d(that)e(is,)i
+(the)f(c)o(haracter)f(whic)o(h)i(signi\014es)g(the)g(start)d(of)i(a)g
+(history)g(ex-)240 814 y(pansion,)23 b(normally)f(`)p
+Fk(!)p Fl('.)37 b(The)21 b(second)h(c)o(haracter)e(is)i(the)f(c)o
+(haracter)g(whic)o(h)h(signi\014es)h(`quic)o(k)240 876
+y(substitution')d(when)h(seen)f(as)g(the)g(\014rst)g(c)o(haracter)f(on)
+h(a)g(line,)i(normally)f(`)p Fk(^)p Fl('.)33 b(The)20
+b(optional)240 938 y(third)15 b(c)o(haracter)f(is)h(the)f(c)o(haracter)
+g(whic)o(h)h(signi\014es)h(the)f(remainder)g(of)f(the)h(line)h(is)f(a)f
+(commen)o(t,)240 1000 y(when)f(found)f(as)g(the)g(\014rst)g(c)o
+(haracter)f(of)h(a)g(w)o(ord,)f(usually)j(`)p Fk(#)p
+Fl('.)k(The)12 b(history)g(commen)o(t)g(c)o(haracter)240
+1063 y(causes)k(history)g(substitution)g(to)f(b)q(e)h(skipp)q(ed)i(for)
+d(the)h(remaining)h(w)o(ords)d(on)i(the)g(line.)23 b(It)16
+b(do)q(es)240 1125 y(not)f(necessarily)h(cause)g(the)f(shell)i(parser)e
+(to)f(treat)h(the)g(rest)g(of)f(the)i(line)h(as)d(a)h(commen)o(t.)0
+1215 y Fk(HISTCMD)72 b Fl(The)16 b(history)g(n)o(um)o(b)q(er,)f(or)h
+(index)h(in)f(the)g(history)g(list,)g(of)f(the)h(curren)o(t)g(command.)
+21 b(If)16 b Fk(HISTCMD)240 1277 y Fl(is)g(unset,)f(it)g(loses)h(its)f
+(sp)q(ecial)i(prop)q(erties,)f(ev)o(en)f(if)h(it)f(is)h(subsequen)o
+(tly)h(reset.)0 1354 y Fk(hostname_completion_file)0
+1416 y(HOSTFILE)48 b Fl(Con)o(tains)17 b(the)h(name)g(of)f(a)h(\014le)h
+(in)f(the)g(same)f(format)g(as)g(`)p Fk(/etc/hosts)p
+Fl(')f(that)h(should)i(b)q(e)f(read)240 1478 y(when)g(the)g(shell)i
+(needs)f(to)e(complete)i(a)e(hostname.)28 b(Y)l(ou)18
+b(can)g(c)o(hange)g(the)g(\014le)h(in)o(teractiv)o(ely;)240
+1540 y(the)c(next)h(time)g(y)o(ou)f(attempt)f(to)h(complete)h(a)f
+(hostname,)g(Bash)g(will)i(add)f(the)f(con)o(ten)o(ts)g(of)g(the)240
+1603 y(new)g(\014le)i(to)d(the)i(already)f(existing)h(database.)0
+1679 y Fk(MAILCHECK)240 1741 y Fl(Ho)o(w)k(often)g(\(in)h(seconds\))f
+(that)g(the)g(shell)i(should)f(c)o(hec)o(k)g(for)f(mail)h(in)g(the)f
+(\014les)i(sp)q(eci\014ed)g(in)240 1803 y Fk(MAILPATH)p
+Fl(.)0 1880 y Fk(PROMPT_COMMAND)240 1942 y Fl(If)15 b(presen)o(t,)g
+(this)g(con)o(tains)g(a)g(string)g(whic)o(h)h(is)f(a)g(command)f(to)h
+(execute)g(b)q(efore)h(the)f(prin)o(ting)g(of)240 2004
+y(eac)o(h)g(primary)h(prompt)e(\()p Fk($PS1)p Fl(\).)0
+2094 y Fk(UID)168 b Fl(The)15 b(n)o(umeric)i(real)e(user)g(id)h(of)f
+(the)g(curren)o(t)h(user.)0 2185 y Fk(EUID)144 b Fl(The)15
+b(n)o(umeric)i(e\013ectiv)o(e)e(user)g(id)h(of)f(the)g(curren)o(t)h
+(user.)0 2275 y Fk(HOSTTYPE)48 b Fl(A)15 b(string)g(describing)i(the)f
+(mac)o(hine)g(Bash)f(is)h(running)g(on.)0 2365 y Fk(OSTYPE)96
+b Fl(A)15 b(string)g(describing)i(the)f(op)q(erating)f(system)g(Bash)g
+(is)h(running)g(on.)0 2455 y Fk(FIGNORE)72 b Fl(A)14
+b(colon-separated)h(list)g(of)f(su\016xes)g(to)g(ignore)g(when)h(p)q
+(erforming)g(\014lename)g(completion)h(A)e(\014le)240
+2518 y(name)j(whose)h(su\016x)f(matc)o(hes)g(one)g(of)g(the)h(en)o
+(tries)f(in)i Fk(FIGNORE)d Fl(is)i(excluded)h(from)e(the)g(list)h(of)
+240 2580 y(matc)o(hed)d(\014le)h(names.)k(A)15 b(sample)h(v)m(alue)h
+(is)e(`)p Fk(.o:~)p Fl(')0 2670 y Fk(INPUTRC)72 b Fl(The)15
+b(name)h(of)e(the)i(Readline)h(startup)e(\014le,)h(o)o(v)o(erriding)f
+(the)g(default)h(of)f(`)p Fk(~/.inputrc)p Fl('.)p eop
+24 25 bop 0 -58 a Fl(24)1623 b(Bash)15 b(F)l(eatures)0
+183 y Fk(BASH_VERSION)240 246 y Fl(The)g(v)o(ersion)h(n)o(um)o(b)q(er)f
+(of)g(the)g(curren)o(t)h(instance)g(of)e(Bash.)0 318
+y Fk(IGNOREEOF)240 380 y Fl(Con)o(trols)g(the)h(action)f(of)g(the)h
+(shell)h(on)f(receipt)g(of)g(an)f Fk(EOF)g Fl(c)o(haracter)g(as)g(the)h
+(sole)g(input.)21 b(If)15 b(set,)240 443 y(then)j(the)g(v)m(alue)h(of)f
+(it)g(is)g(the)g(n)o(um)o(b)q(er)h(of)e(consecutiv)o(e)i
+Fk(EOF)f Fl(c)o(haracters)f(that)g(can)h(b)q(e)g(read)g(as)240
+505 y(the)d(\014rst)f(c)o(haracters)f(on)i(an)f(input)h(line)i(b)q
+(efore)d(the)h(shell)h(will)g(exit.)k(If)15 b(the)f(v)m(ariable)i
+(exists)f(but)240 567 y(do)q(es)h(not)f(ha)o(v)o(e)g(a)g(n)o(umeric)h
+(v)m(alue)h(\(or)d(has)h(no)h(v)m(alue\))g(then)f(the)h(default)g(is)g
+(10.)k(If)15 b(the)h(v)m(ariable)240 629 y(do)q(es)e(not)g(exist,)g
+(then)g Fk(EOF)f Fl(signi\014es)j(the)e(end)g(of)g(input)h(to)e(the)h
+(shell.)21 b(This)14 b(is)h(only)f(in)h(e\013ect)f(for)240
+692 y(in)o(teractiv)o(e)i(shells.)0 764 y Fk(no_exit_on_failed_exec)240
+826 y Fl(If)e(this)h(v)m(ariable)g(exists,)g(the)f(shell)h(will)h(not)e
+(exit)g(in)h(the)g(case)f(that)f(it)h(couldn't)h(execute)g(the)f
+(\014le)240 889 y(sp)q(eci\014ed)j(in)f(the)g Fk(exec)e
+Fl(command.)0 972 y Fk(nolinks)72 b Fl(If)20 b(presen)o(t,)g(sa)o(ys)e
+(not)h(to)g(follo)o(w)g(sym)o(b)q(olic)i(links)f(when)g(doing)g
+(commands)f(that)g(c)o(hange)g(the)240 1034 y(curren)o(t)i(w)o(orking)h
+(directory)l(.)39 b(By)22 b(default,)h(bash)f(follo)o(ws)f(the)h
+(logical)h(c)o(hain)f(of)f(directories)240 1096 y(when)16
+b(p)q(erforming)f(commands)g(suc)o(h)h(as)f Fk(cd)f Fl(whic)o(h)j(c)o
+(hange)e(the)g(curren)o(t)g(directory)l(.)240 1169 y(F)l(or)g(example,)
+g(if)h(`)p Fk(/usr/sys)p Fl(')d(is)j(a)f(link)h(to)f(`)p
+Fk(/usr/local/sys)p Fl(')d(then:)360 1229 y Fk($)24 b(cd)f(/usr/sys;)g
+(echo)g($PWD)360 1278 y(/usr/sys)360 1328 y($)h(cd)f(..;)h(pwd)360
+1378 y(/usr)240 1451 y Fl(If)15 b Fk(nolinks)g Fl(exists,)g(then:)360
+1511 y Fk($)24 b(cd)f(/usr/sys;)g(echo)g($PWD)360 1561
+y(/usr/local/sys)360 1610 y($)h(cd)f(..;)h(pwd)360 1660
+y(/usr/local)240 1733 y Fl(See)12 b(also)e(the)i(description)g(of)e
+(the)i Fk(-P)e Fl(option)h(to)g(the)g Fk(set)f Fl(builtin,)k(Section)e
+(4.5)e([The)g(Set)h(Builtin],)240 1795 y(page)k(20.)0
+2010 y Fj(4.7)33 b(Shell)16 b(Arithmetic)0 2209 y Ff(4.7.1)30
+b(Arithmetic)16 b(Ev)m(aluation)62 2346 y Fl(The)f(shell)g(allo)o(ws)f
+(arithmetic)h(expressions)g(to)e(b)q(e)i(ev)m(aluated,)g(as)e(one)h(of)
+g(the)g(shell)i(expansions)e(or)g(b)o(y)g(the)0 2408
+y Fk(let)h Fl(builtin.)62 2545 y(Ev)m(aluation)i(is)g(done)f(in)h(long)
+f(in)o(tegers)g(with)g(no)g(c)o(hec)o(k)g(for)g(o)o(v)o(er\015o)o(w,)e
+(though)i(division)i(b)o(y)e(0)f(is)i(trapp)q(ed)0 2608
+y(and)g(\015agged)f(as)g(an)h(error.)23 b(The)17 b(follo)o(wing)g(list)
+h(of)e(op)q(erators)g(is)h(group)q(ed)g(in)o(to)f(lev)o(els)i(of)e
+(equal-precedence)0 2670 y(op)q(erators.)j(The)c(lev)o(els)i(are)e
+(listed)h(in)g(order)f(of)g(decreasing)h(precedence.)p
+eop
+25 26 bop 0 -58 a Fl(Chapter)15 b(4:)k(Bash)d(Sp)q(eci\014c)h(F)l
+(eatures)1226 b(25)0 183 y Fk(-)15 b(+)177 b Fl(unary)15
+b(min)o(us)h(and)f(plus)0 271 y Fk(!)g(~)177 b Fl(logical)16
+b(and)g(bit)o(wise)g(negation)0 359 y Fk(*)f(/)g(\045)138
+b Fl(m)o(ultiplication,)17 b(division,)g(remainder)0
+447 y Fk(+)e(-)177 b Fl(addition,)16 b(subtraction)0
+535 y Fk(<<)f(>>)129 b Fl(left)16 b(and)f(righ)o(t)g(bit)o(wise)h
+(shifts)0 622 y Fk(<=)f(>=)g(<)g(>)51 b Fl(comparison)0
+710 y Fk(==)15 b(!=)129 b Fl(equalit)o(y)16 b(and)f(inequalit)o(y)0
+798 y Fk(&)216 b Fl(bit)o(wise)16 b(AND)0 886 y Fk(^)216
+b Fl(bit)o(wise)16 b(exclusiv)o(e)h(OR)0 974 y Fk(|)216
+b Fl(bit)o(wise)16 b(OR)0 1062 y Fk(&&)192 b Fl(logical)16
+b(AND)0 1149 y Fk(||)192 b Fl(logical)16 b(OR)0 1225
+y Fk(=)f(*=)g(/=)g(\045=)g(+=)g(-=)f(<<=)h(>>=)g(&=)g(^=)g(|=)240
+1287 y Fl(assignmen)o(t)62 1437 y(Shell)h(v)m(ariables)e(are)f(allo)o
+(w)o(ed)h(as)f(op)q(erands;)h(parameter)e(expansion)j(is)e(p)q
+(erformed)h(b)q(efore)g(the)f(expression)0 1499 y(is)k(ev)m(aluated.)26
+b(The)17 b(v)m(alue)i(of)d(a)h(parameter)f(is)h(co)q(erced)h(to)e(a)h
+(long)g(in)o(teger)g(within)h(an)f(expression.)25 b(A)17
+b(shell)0 1561 y(v)m(ariable)g(need)f(not)e(ha)o(v)o(e)h(its)h(in)o
+(teger)f(attribute)g(turned)h(on)f(to)f(b)q(e)i(used)g(in)g(an)f
+(expression.)62 1699 y(Constan)o(ts)21 b(with)i(a)f(leading)i(0)e(are)g
+(in)o(terpreted)h(as)f(o)q(ctal)h(n)o(um)o(b)q(ers.)41
+b(A)23 b(leading)h Fk(0x)e Fl(or)g Fk(0X)g Fl(denotes)0
+1761 y(hexadecimal.)e(Otherwise,)14 b(n)o(um)o(b)q(ers)e(tak)o(e)f(the)
+i(form)e([)p Fg(base#)r Fl(]n,)g(where)i Fg(base)h Fl(is)f(a)f(decimal)
+h(n)o(um)o(b)q(er)g(b)q(et)o(w)o(een)0 1823 y(2)h(and)g(36)g(represen)o
+(ting)g(the)h(arithmetic)f(base,)g(and)h Fg(n)f Fl(is)h(a)e(n)o(um)o(b)
+q(er)i(in)g(that)e(base.)20 b(If)14 b Fg(base)j Fl(is)e(omitted,)f
+(then)0 1886 y(base)h(10)g(is)h(used.)62 2023 y(Op)q(erators)i(are)f
+(ev)m(aluated)i(in)g(order)e(of)h(precedence.)29 b(Sub-expressions)20
+b(in)e(paren)o(theses)g(are)g(ev)m(aluated)0 2085 y(\014rst)d(and)g(ma)
+o(y)g(o)o(v)o(erride)g(the)g(precedence)i(rules)f(ab)q(o)o(v)o(e.)0
+2296 y Ff(4.7.2)30 b(Arithmetic)16 b(Expansion)62 2433
+y Fl(Arithmetic)h(expansion)f(allo)o(ws)g(the)f(ev)m(aluation)i(of)e
+(an)g(arithmetic)i(expression)f(and)g(the)f(substitution)h(of)0
+2495 y(the)f(result.)21 b(There)15 b(are)g(t)o(w)o(o)f(formats)g(for)g
+(arithmetic)i(expansion:)120 2620 y Fk($[)24 b(expression)e(])120
+2670 y($\(\()h(expression)g(\)\))p eop
+26 27 bop 0 -58 a Fl(26)1623 b(Bash)15 b(F)l(eatures)62
+183 y(The)e(expression)h(is)f(treated)f(as)g(if)h(it)g(w)o(ere)g
+(within)h(double)g(quotes,)e(but)h(a)f(double)i(quote)f(inside)h(the)f
+(braces)0 246 y(or)i(paren)o(theses)g(is)h(not)f(treated)g(sp)q
+(ecially)l(.)22 b(All)17 b(tok)o(ens)e(in)h(the)f(expression)h(undergo)
+g(parameter)e(expansion,)0 308 y(command)h(substitution,)h(and)f(quote)
+g(remo)o(v)m(al.)20 b(Arithmetic)c(substitutions)g(ma)o(y)f(b)q(e)h
+(nested.)62 446 y(The)k(ev)m(aluation)g(is)g(p)q(erformed)f(according)h
+(to)f(the)g(rules)h(listed)h(ab)q(o)o(v)o(e.)31 b(If)20
+b(the)f(expression)h(is)g(in)o(v)m(alid,)0 508 y(Bash)15
+b(prin)o(ts)h(a)f(message)f(indicating)j(failure)g(and)e(no)g
+(substitution)h(o)q(ccurs.)0 724 y Ff(4.7.3)30 b(Arithmetic)16
+b(Builtins)0 875 y Fk(let)360 938 y(let)23 b Fg(expression)i
+Fk([)p Fg(expression)p Fk(])240 1014 y Fl(The)16 b Fk(let)f
+Fl(builtin)i(allo)o(ws)f(arithmetic)g(to)f(b)q(e)h(p)q(erformed)g(on)f
+(shell)i(v)m(ariables.)22 b(Eac)o(h)15 b Fg(expression)240
+1076 y Fl(is)e(ev)m(aluated)h(according)g(to)e(the)h(rules)g(giv)o(en)h
+(previously)g(\(see)f(Section)g(4.7.1)f([Arithmetic)h(Ev)m(al-)240
+1138 y(uation],)18 b(page)f(24\).)27 b(If)18 b(the)g(last)f
+Fg(expression)i Fl(ev)m(aluates)f(to)f(0,)h Fk(let)f
+Fl(returns)h(1;)g(otherwise)g(0)f(is)240 1201 y(returned.)0
+1433 y Fj(4.8)33 b(Con)n(trolling)17 b(the)e(Prompt)62
+1571 y Fl(The)j(v)m(alue)g(of)e(the)h(v)m(ariable)i Fk($PROMPT_COMMAND)
+c Fl(is)i(examined)h(just)f(b)q(efore)g(Bash)h(prin)o(ts)f(eac)o(h)g
+(primary)0 1633 y(prompt.)32 b(If)19 b(it)h(is)f(set)g(and)h(non-n)o
+(ull,)h(then)f(the)f(v)m(alue)i(is)f(executed)g(just)f(as)g(if)g(y)o
+(ou)g(had)h(t)o(yp)q(ed)f(it)h(on)f(the)0 1696 y(command)c(line.)62
+1833 y(In)20 b(addition,)g(the)f(follo)o(wing)h(table)f(describ)q(es)h
+(the)f(sp)q(ecial)i(c)o(haracters)d(whic)o(h)i(can)f(app)q(ear)g(in)g
+(the)g Fk(PS1)0 1896 y Fl(v)m(ariable:)0 2047 y Fk(\\t)192
+b Fl(the)15 b(time,)g(in)h(HH:MM:SS)f(format.)0 2136
+y Fk(\\d)192 b Fl(the)15 b(date,)g(in)h Fk(")p Fl(W)l(eekda)o(y)f(Mon)o
+(th)f(Date)p Fk(")h Fl(format)f(\(e.g.)19 b Fk(")p Fl(T)l(ue)c(Ma)o(y)g
+(26)p Fk(")p Fl(\).)0 2225 y Fk(\\n)192 b Fl(newline.)0
+2314 y Fk(\\s)g Fl(the)15 b(name)g(of)g(the)h(shell,)g(the)f(basename)h
+(of)e Fk($0)h Fl(\(the)g(p)q(ortion)h(follo)o(wing)g(the)f(\014nal)h
+(slash\).)0 2403 y Fk(\\w)192 b Fl(the)15 b(curren)o(t)g(w)o(orking)g
+(directory)l(.)0 2492 y Fk(\\W)192 b Fl(the)15 b(basename)h(of)e
+Fk($PWD)p Fl(.)0 2581 y Fk(\\u)192 b Fl(y)o(our)15 b(username.)0
+2670 y Fk(\\h)192 b Fl(the)15 b(hostname.)p eop
+27 28 bop 0 -58 a Fl(Chapter)15 b(4:)k(Bash)d(Sp)q(eci\014c)h(F)l
+(eatures)1226 b(27)0 183 y Fk(\\#)192 b Fl(the)15 b(command)g(n)o(um)o
+(b)q(er)h(of)f(this)g(command.)0 270 y Fk(\\!)192 b Fl(the)15
+b(history)g(n)o(um)o(b)q(er)h(of)f(this)g(command.)0
+358 y Fk(\\nnn)144 b Fl(the)15 b(c)o(haracter)g(corresp)q(onding)h(to)e
+(the)i(o)q(ctal)f(n)o(um)o(b)q(er)h Fk(nnn)p Fl(.)0 445
+y Fk(\\$)192 b Fl(if)16 b(the)f(e\013ectiv)o(e)g(uid)i(is)e(0,)g
+Fk(#)p Fl(,)g(otherwise)g Fk($)p Fl(.)0 532 y Fk(\\\\)192
+b Fl(a)15 b(bac)o(kslash.)0 619 y Fk(\\[)192 b Fl(b)q(egin)18
+b(a)e(sequence)i(of)e(non-prin)o(ting)h(c)o(haracters.)23
+b(This)17 b(could)h(b)q(e)f(used)g(to)f(em)o(b)q(ed)h(a)f(terminal)240
+681 y(con)o(trol)f(sequence)h(in)o(to)f(the)h(prompt.)0
+769 y Fk(\\])192 b Fl(end)16 b(a)f(sequence)h(of)f(non-prin)o(ting)h(c)
+o(haracters.)p eop
+28 29 bop 0 -58 a Fl(28)1623 b(Bash)15 b(F)l(eatures)p
+eop
+29 30 bop 0 -58 a Fl(Chapter)15 b(5:)k(Job)d(Con)o(trol)1435
+b(29)0 183 y Fh(5)41 b(Job)15 b(Con)n(trol)62 391 y Fl(This)i(c)o
+(hapter)e(disusses)i(what)e(job)h(con)o(trol)g(is,)g(ho)o(w)f(it)h(w)o
+(orks,)f(and)h(ho)o(w)f(Bash)h(allo)o(ws)g(y)o(ou)g(to)f(access)h(its)0
+453 y(facilities.)0 715 y Fj(5.1)33 b(Job)14 b(Con)n(trol)i(Basics)62
+856 y Fl(Job)21 b(con)o(trol)e(refers)h(to)g(the)g(abilit)o(y)h(to)e
+(selectiv)o(ely)j(stop)e(\(susp)q(end\))h(the)f(execution)h(of)e(pro)q
+(cesses)i(and)0 918 y(con)o(tin)o(ue)f(\(resume\))e(their)h(execution)i
+(at)d(a)g(later)h(p)q(oin)o(t.)32 b(A)19 b(user)g(t)o(ypically)h(emplo)
+o(ys)f(this)h(facilit)o(y)g(via)f(an)0 980 y(in)o(teractiv)o(e)d(in)o
+(terface)f(supplied)j(join)o(tly)d(b)o(y)g(the)h(system's)e(terminal)i
+(driv)o(er)g(and)f(Bash.)62 1122 y(The)22 b(shell)h(asso)q(ciates)e(a)h
+Fg(job)g Fl(with)g(eac)o(h)f(pip)q(elin)q(e.)41 b(It)22
+b(k)o(eeps)g(a)f(table)h(of)f(curren)o(tly)h(executing)h(jobs,)0
+1184 y(whic)o(h)e(ma)o(y)e(b)q(e)i(listed)g(with)g(the)f
+Fk(jobs)f Fl(command.)34 b(When)21 b(Bash)f(starts)e(a)i(job)g(async)o
+(hronously)g(\(in)h(the)0 1246 y(bac)o(kground\),)14
+b(it)i(prin)o(ts)f(a)g(line)i(that)d(lo)q(oks)i(lik)o(e:)120
+1375 y Fk([1])23 b(25647)62 1516 y Fl(indicating)14 b(that)d(this)h
+(job)g(is)g(job)f(n)o(um)o(b)q(er)i(1)e(and)h(that)f(the)h(pro)q(cess)g
+(ID)g(of)f(the)h(last)f(pro)q(cess)h(in)h(the)f(pip)q(eline)0
+1578 y(asso)q(ciated)j(with)f(this)h(job)f(is)h(25647.)k(All)c(of)f
+(the)h(pro)q(cesses)g(in)g(a)f(single)i(pip)q(eline)h(are)d(mem)o(b)q
+(ers)h(of)f(the)g(same)0 1641 y(job.)20 b(Bash)15 b(uses)g(the)h
+Fg(job)g Fl(abstraction)e(as)h(the)h(basis)f(for)g(job)g(con)o(trol.)62
+1782 y(T)l(o)i(facilitate)g(the)g(implemen)o(tation)h(of)e(the)h(user)f
+(in)o(terface)h(to)f(job)h(con)o(trol,)f(the)h(system)f(main)o(tains)h
+(the)0 1844 y(notion)i(of)g(a)g(curren)o(t)g(terminal)h(pro)q(cess)f
+(group)g(ID.)g(Mem)o(b)q(ers)g(of)g(this)h(pro)q(cess)f(group)g(\(pro)q
+(cesses)g(whose)0 1906 y(pro)q(cess)g(group)g(ID)g(is)g(equal)g(to)g
+(the)g(curren)o(t)f(terminal)i(pro)q(cess)f(group)g(ID\))f(receiv)o(e)i
+(k)o(eyb)q(oard-generated)0 1968 y(signals)14 b(suc)o(h)f(as)f
+Fk(SIGINT)p Fl(.)18 b(These)13 b(pro)q(cesses)g(are)g(said)g(to)f(b)q
+(e)i(in)f(the)g(foreground.)19 b(Bac)o(kground)12 b(pro)q(cesses)h(are)
+0 2031 y(those)i(whose)f(pro)q(cess)i(group)e(ID)h(di\013ers)h(from)e
+(the)h(terminal's;)g(suc)o(h)g(pro)q(cesses)g(are)g(imm)o(une)h(to)e(k)
+o(eyb)q(oard-)0 2093 y(generated)19 b(signals.)30 b(Only)20
+b(foreground)e(pro)q(cesses)h(are)f(allo)o(w)o(ed)h(to)f(read)h(from)e
+(or)h(write)h(to)f(the)h(terminal.)0 2155 y(Bac)o(kground)i(pro)q
+(cesses)h(whic)o(h)h(attempt)e(to)g(read)g(from)g(\(write)g(to\))g(the)
+h(terminal)g(are)f(sen)o(t)h(a)f Fk(SIGTTIN)0 2218 y
+Fl(\()p Fk(SIGTTOU)p Fl(\))14 b(signal)i(b)o(y)f(the)g(terminal)h(driv)
+o(er,)f(whic)o(h,)h(unless)g(caugh)o(t,)f(susp)q(ends)h(the)f(pro)q
+(cess.)62 2359 y(If)h(the)g(op)q(erating)g(system)f(on)g(whic)o(h)i
+(Bash)e(is)h(running)h(supp)q(orts)f(job)f(con)o(trol,)g(Bash)h(allo)o
+(ws)f(y)o(ou)h(to)f(use)0 2421 y(it.)20 b(T)o(yping)15
+b(the)g Fg(susp)q(end)j Fl(c)o(haracter)c(\(t)o(ypically)i(`)p
+Fk(^Z)p Fl(',)e(Con)o(trol-Z\))f(while)k(a)d(pro)q(cess)h(is)h(running)
+g(causes)f(that)0 2483 y(pro)q(cess)i(to)f(b)q(e)i(stopp)q(ed)f(and)g
+(returns)g(y)o(ou)f(to)g(Bash.)25 b(T)o(yping)17 b(the)g
+Fg(dela)o(y)o(ed)h(susp)q(end)i Fl(c)o(haracter)c(\(t)o(ypically)0
+2545 y(`)p Fk(^Y)p Fl(',)11 b(Con)o(trol-Y\))h(causes)g(the)h(pro)q
+(cess)f(to)g(b)q(e)h(stopp)q(ed)f(when)h(it)g(attempts)e(to)g(read)i
+(input)g(from)e(the)i(terminal,)0 2608 y(and)k(con)o(trol)f(to)f(b)q(e)
+i(returned)g(to)f(Bash.)23 b(Y)l(ou)16 b(ma)o(y)g(then)h(manipulate)g
+(the)g(state)e(of)h(this)h(job,)f(using)h(the)f Fk(bg)0
+2670 y Fl(command)h(to)f(con)o(tin)o(ue)h(it)g(in)h(the)f(bac)o
+(kground,)g(the)g Fk(fg)f Fl(command)h(to)f(con)o(tin)o(ue)h(it)g(in)h
+(the)f(foreground,)f(or)p eop
+30 31 bop 0 -58 a Fl(30)1623 b(Bash)15 b(F)l(eatures)0
+183 y(the)h Fk(kill)f Fl(command)g(to)g(kill)i(it.)k(A)16
+b(`)p Fk(^Z)p Fl(')f(tak)o(es)f(e\013ect)i(immediately)l(,)h(and)f(has)
+f(the)h(additional)h(side)f(e\013ect)f(of)0 246 y(causing)h(p)q(ending)
+h(output)e(and)g(t)o(yp)q(eahead)h(to)e(b)q(e)i(discarded.)62
+382 y(There)i(are)g(a)f(n)o(um)o(b)q(er)i(of)e(w)o(a)o(ys)g(to)g(refer)
+h(to)f(a)g(job)h(in)h(the)e(shell.)30 b(The)18 b(c)o(haracter)f(`)p
+Fk(\045)p Fl(')g(in)o(tro)q(duces)i(a)e(job)0 445 y(name.)i(Job)c(n)o
+(um)o(b)q(er)f Fk(n)f Fl(ma)o(y)h(b)q(e)g(referred)g(to)f(as)h(`)p
+Fk(\045n)p Fl('.)k(A)c(job)g(ma)o(y)f(also)g(b)q(e)i(referred)f(to)f
+(using)i(a)e(pre\014x)h(of)g(the)0 507 y(name)j(used)g(to)f(start)g
+(it,)h(or)f(using)h(a)g(substring)g(that)f(app)q(ears)g(in)i(its)f
+(command)f(line.)27 b(F)l(or)16 b(example,)h(`)p Fk(\045ce)p
+Fl(')0 569 y(refers)d(to)g(a)g(stopp)q(ed)h Fk(ce)f Fl(job.)20
+b(Using)15 b(`)p Fk(\045?ce)p Fl(',)e(on)h(the)h(other)f(hand,)h
+(refers)f(to)g(an)o(y)g(job)g(con)o(taining)h(the)g(string)0
+632 y(`)p Fk(ce)p Fl(')h(in)j(its)e(command)h(line.)28
+b(If)18 b(the)g(pre\014x)g(or)f(substring)h(matc)o(hes)f(more)g(than)g
+(one)h(job,)f(Bash)h(rep)q(orts)f(an)0 694 y(error.)i(The)c(sym)o(b)q
+(ols)g(`)p Fk(\045\045)p Fl(')f(and)h(`)p Fk(\045+)p
+Fl(')f(refer)h(to)f(the)h(shell's)h(notion)f(of)g(the)g(curren)o(t)g
+(job,)f(whic)o(h)i(is)f(the)g(last)g(job)0 756 y(stopp)q(ed)h(while)h
+(it)f(w)o(as)f(in)h(the)g(foreground.)k(The)c(previous)g(job)f(ma)o(y)g
+(b)q(e)h(referenced)h(using)f(`)p Fk(\045-)p Fl('.)k(In)c(output)0
+818 y(p)q(ertaining)h(to)f(jobs)g(\(e.g.,)f(the)h(output)g(of)f(the)i
+Fk(jobs)e Fl(command\),)h(the)g(curren)o(t)g(job)g(is)g(alw)o(a)o(ys)g
+(\015agged)g(with)0 881 y(a)f(`)p Fk(+)p Fl(',)f(and)h(the)g(previous)h
+(job)f(with)h(a)f(`)p Fk(-)p Fl('.)62 1018 y(Simply)21
+b(naming)f(a)f(job)g(can)h(b)q(e)g(used)g(to)f(bring)h(it)g(in)o(to)f
+(the)g(foreground:)28 b(`)p Fk(\0451)p Fl(')19 b(is)h(a)f(synon)o(ym)g
+(for)g(`)p Fk(fg)0 1080 y(\0451)p Fl(')14 b(bringing)j(job)e(1)g(from)f
+(the)h(bac)o(kground)h(in)o(to)f(the)g(foreground.)k(Similarly)l(,)f(`)
+p Fk(\0451)c(&)p Fl(')h(resumes)g(job)g(1)g(in)h(the)0
+1142 y(bac)o(kground,)f(equiv)m(alen)o(t)i(to)d(`)p Fk(bg)h(\0451)p
+Fl(')62 1279 y(The)20 b(shell)h(learns)e(immediately)i(whenev)o(er)f(a)
+f(job)g(c)o(hanges)g(state.)31 b(Normally)l(,)21 b(Bash)e(w)o(aits)g
+(un)o(til)h(it)f(is)0 1341 y(ab)q(out)14 b(to)g(prin)o(t)h(a)f(prompt)g
+(b)q(efore)g(rep)q(orting)h(c)o(hanges)f(in)i(a)e(job's)f(status)h(so)g
+(as)g(to)g(not)g(in)o(terrupt)g(an)o(y)g(other)0 1404
+y(output.)21 b(If)15 b(the)h(the)g Fk(-b)f Fl(option)g(to)g(the)h
+Fk(set)f Fl(builtin)j(is)e(set,)f(Bash)g(rep)q(orts)g(suc)o(h)h(c)o
+(hanges)g(immediately)h(\(see)0 1466 y(Section)f(4.5)e([The)h(Set)h
+(Builtin],)g(page)f(20\).)k(This)d(feature)f(is)h(also)f(con)o(trolled)
+h(b)o(y)f(the)g(v)m(ariable)i Fk(notify)p Fl(.)62 1603
+y(If)j(y)o(ou)g(attempt)f(to)g(exit)h(bash)g(while)i(jobs)e(are)f
+(stopp)q(ed,)i(the)f(shell)i(prin)o(ts)e(a)f(message)h(w)o(arning)g(y)o
+(ou.)0 1665 y(Y)l(ou)d(ma)o(y)f(then)h(use)g(the)g Fk(jobs)f
+Fl(command)g(to)g(insp)q(ect)i(their)f(status.)24 b(If)17
+b(y)o(ou)f(do)h(this,)g(or)f(try)g(to)g(exit)h(again)0
+1727 y(immediately)l(,)g(y)o(ou)e(are)f(not)h(w)o(arned)g(again,)g(and)
+g(the)h(stopp)q(ed)f(jobs)g(are)g(terminated.)0 1950
+y Fj(5.2)33 b(Job)14 b(Con)n(trol)i(Builtins)0 2100 y
+Fk(bg)360 2162 y(bg)24 b([)p Fg(jobsp)q(ec)s Fk(])240
+2236 y Fl(Place)16 b Fg(jobsp)q(ec)i Fl(in)o(to)d(the)g(bac)o(kground,)
+f(as)h(if)g(it)g(had)g(b)q(een)h(started)e(with)i(`)p
+Fk(&)p Fl('.)i(If)e Fg(jobsp)q(ec)i Fl(is)d(not)240 2298
+y(supplied,)i(the)e(curren)o(t)h(job)f(is)g(used.)0 2385
+y Fk(fg)360 2447 y(fg)24 b([)p Fg(jobsp)q(ec)s Fk(])240
+2521 y Fl(Bring)f Fg(jobsp)q(ec)j Fl(in)o(to)c(the)h(foreground)f(and)g
+(mak)o(e)g(it)h(the)f(curren)o(t)h(job.)41 b(If)23 b
+Fg(jobsp)q(ec)i Fl(is)e(not)240 2583 y(supplied,)17 b(the)e(curren)o(t)
+h(job)f(is)g(used.)0 2670 y Fk(jobs)p eop
+31 32 bop 0 -58 a Fl(Chapter)15 b(5:)k(Job)d(Con)o(trol)1435
+b(31)360 183 y Fk(jobs)23 b([-lpn])g([)p Fg(jobsp)q(ec)s
+Fk(])360 233 y(jobs)g(-x)h Fg(command)h Fk([)p Fg(jobsp)q(ec)s
+Fk(])240 308 y Fl(The)16 b(\014rst)g(form)f(lists)i(the)f(activ)o(e)g
+(jobs.)22 b(The)16 b Fk(-l)g Fl(option)g(lists)g(pro)q(cess)h(IDs)f(in)
+g(addition)i(to)d(the)240 370 y(normal)h(information;)f(the)h
+Fk(-p)g Fl(option)g(lists)g(only)g(the)g(pro)q(cess)g(ID)g(of)f(the)h
+(job's)f(pro)q(cess)h(group)240 432 y(leader.)k(The)14
+b Fk(-n)g Fl(option)g(displa)o(ys)h(only)f(jobs)g(that)f(ha)o(v)o(e)h
+(c)o(hanged)g(status)f(since)i(last)f(not\014ed.)20 b(If)240
+495 y Fg(jobsp)q(ec)g Fl(is)d(giv)o(en,)h(output)e(is)h(restricted)g
+(to)f(information)h(ab)q(out)g(that)f(job.)24 b(If)17
+b Fg(jobsp)q(ec)j Fl(is)d(not)240 557 y(supplied,)g(the)e(status)g(of)g
+(all)h(jobs)f(is)g(listed.)240 632 y(If)e(the)f Fk(-x)g
+Fl(option)g(is)h(supplied,)i Fk(jobs)d Fl(replaces)h(an)o(y)f
+Fg(jobsp)q(ec)j Fl(found)e(in)g Fg(command)h Fl(or)e
+Fg(argumen)o(ts)240 694 y Fl(with)f(the)h(corresp)q(onding)g(pro)q
+(cess)f(group)g(ID,)g(and)g(executes)h Fg(command)p Fl(,)f(passing)h
+(it)f Fg(argumen)o(t)q Fl(s,)240 756 y(returning)16 b(its)f(exit)h
+(status.)0 843 y Fk(suspend)360 906 y(suspend)23 b([-f])240
+980 y Fl(Susp)q(end)c(the)e(execution)i(of)e(this)g(shell)i(un)o(til)g
+(it)e(receiv)o(es)i(a)e Fk(SIGCONT)f Fl(signal.)27 b(The)18
+b Fk(-f)f Fl(option)240 1043 y(means)e(to)g(susp)q(end)h(ev)o(en)g(if)f
+(the)h(shell)g(is)g(a)f(login)h(shell.)62 1192 y(When)g(job)f(con)o
+(trol)g(is)g(activ)o(e,)g(the)h Fk(kill)e Fl(and)i Fk(wait)e
+Fl(builtins)k(also)d(accept)g Fg(jobsp)q(ec)k Fl(argumen)o(ts.)0
+1416 y Fj(5.3)33 b(Job)14 b(Con)n(trol)i(V)-6 b(ariables)0
+1553 y Fk(auto_resume)240 1615 y Fl(This)20 b(v)m(ariable)h(con)o
+(trols)e(ho)o(w)g(the)h(shell)h(in)o(teracts)e(with)h(the)g(user)f(and)
+h(job)f(con)o(trol.)33 b(If)20 b(this)240 1678 y(v)m(ariable)k(exists)e
+(then)h(single)g(w)o(ord)f(simple)i(commands)e(without)g(redirects)h
+(are)f(treated)f(as)240 1740 y(candidates)f(for)e(resumption)i(of)e(an)
+h(existing)h(job.)32 b(There)19 b(is)h(no)f(am)o(biguit)o(y)g(allo)o(w)
+o(ed;)i(if)e(y)o(ou)240 1802 y(ha)o(v)o(e)c(more)f(than)h(one)h(job)e
+(b)q(eginning)k(with)d(the)g(string)g(that)g(y)o(ou)f(ha)o(v)o(e)h(t)o
+(yp)q(ed,)g(then)h(the)f(most)240 1864 y(recen)o(tly)j(accessed)g(job)f
+(will)i(b)q(e)e(selected.)28 b(The)17 b(name)g(of)g(a)g(stopp)q(ed)h
+(job,)f(in)h(this)g(con)o(text,)e(is)240 1927 y(the)f(command)g(line)h
+(used)g(to)e(start)g(it.)20 b(If)15 b(this)g(v)m(ariable)i(is)e(set)g
+(to)f(the)h(v)m(alue)h Fk(exact)p Fl(,)e(the)h(string)240
+1989 y(supplied)h(m)o(ust)c(matc)o(h)h(the)g(name)g(of)g(a)g(stopp)q
+(ed)h(job)f(exactly;)h(if)f(set)g(to)g Fk(substring)p
+Fl(,)f(the)h(string)240 2051 y(supplied)22 b(needs)d(to)g(matc)o(h)g(a)
+f(substring)i(of)f(the)g(name)g(of)g(a)g(stopp)q(ed)g(job.)32
+b(The)19 b Fk(substring)240 2114 y Fl(v)m(alue)g(pro)o(vides)g
+(functionalit)o(y)g(analogous)f(to)f(the)h Fk(\045?)g
+Fl(job)g(id)h(\(see)f(Section)h(5.1)e([Job)h(Con)o(trol)240
+2176 y(Basics],)f(page)g(29\).)25 b(If)17 b(set)g(to)f(an)o(y)h(other)f
+(v)m(alue,)j(the)e(supplied)i(string)e(m)o(ust)g(b)q(e)g(a)g(pre\014x)h
+(of)e(a)240 2238 y(stopp)q(ed)g(job's)e(name;)h(this)h(pro)o(vides)f
+(functionalit)o(y)i(analogous)e(to)f(the)i Fk(\045)f
+Fl(job)g(id.)0 2325 y Fk(notify)96 b Fl(Setting)18 b(this)g(v)m
+(ariable)g(to)f(a)g(v)m(alue)i(is)f(equiv)m(alen)o(t)h(to)d(`)p
+Fk(set)f(-b)p Fl(';)i(unsetting)h(it)g(is)g(equiv)m(alen)o(t)h(to)240
+2387 y(`)p Fk(set)14 b(+b)p Fl(')h(\(see)g(Section)h(4.5)e([The)h(Set)h
+(Builtin],)g(page)f(20\).)p eop
+32 33 bop 0 -58 a Fl(32)1623 b(Bash)15 b(F)l(eatures)p
+eop
+33 34 bop 0 -58 a Fl(Chapter)15 b(6:)k(Using)d(History)f(In)o(teractiv)
+o(ely)1135 b(33)0 183 y Fh(6)41 b(Using)14 b(History)h(In)n(teractiv)n
+(ely)62 355 y Fl(This)i(c)o(hapter)e(describ)q(es)j(ho)o(w)d(to)h(use)g
+(the)g(GNU)g(History)f(Library)i(in)o(teractiv)o(ely)l(,)g(from)e(a)g
+(user's)h(stand-)0 417 y(p)q(oin)o(t.)23 b(It)16 b(should)h(b)q(e)f
+(considered)i(a)d(user's)h(guide.)23 b(F)l(or)15 b(information)h(on)g
+(using)h(the)f(GNU)g(History)f(Library)0 479 y(in)h(y)o(our)f(o)o(wn)f
+(programs,)g(see)i(the)f(GNU)g(Readline)i(Library)f(Man)o(ual.)0
+688 y Fj(6.1)33 b(History)15 b(In)n(teraction)62 825
+y Fl(The)j(History)g(library)g(pro)o(vides)h(a)e(history)h(expansion)h
+(feature)e(that)g(is)i(similar)g(to)e(the)h(history)f(expan-)0
+887 y(sion)k(pro)o(vided)h(b)o(y)f Fk(csh)p Fl(.)36 b(The)22
+b(follo)o(wing)f(text)g(describ)q(es)h(the)f(syn)o(tax)f(used)i(to)e
+(manipulate)i(the)f(history)0 949 y(information.)62 1086
+y(History)11 b(expansion)i(tak)o(es)d(place)i(in)h(t)o(w)o(o)d(parts.)
+18 b(The)11 b(\014rst)g(is)h(to)f(determine)h(whic)o(h)g(line)h(from)e
+(the)g(previous)0 1148 y(history)h(should)h(b)q(e)f(used)h(during)f
+(substitution.)20 b(The)12 b(second)g(is)h(to)e(select)h(p)q(ortions)g
+(of)g(that)f(line)i(for)f(inclusion)0 1211 y(in)o(to)f(the)h(curren)o
+(t)f(one.)18 b(The)12 b(line)h(selected)f(from)f(the)g(previous)h
+(history)g(is)f(called)i(the)e Fg(ev)o(en)o(t)p Fl(,)h(and)f(the)h(p)q
+(ortions)0 1273 y(of)h(that)g(line)i(that)e(are)g(acted)g(up)q(on)h
+(are)g(called)h Fg(w)o(ords)p Fl(.)j(The)c(line)h(is)f(brok)o(en)f(in)o
+(to)h(w)o(ords)f(in)h(the)f(same)h(fashion)0 1335 y(that)j(Bash)h(do)q
+(es,)h(so)e(that)g(sev)o(eral)h(English)i(\(or)d(Unix\))h(w)o(ords)f
+(surrounded)i(b)o(y)f(quotes)f(are)h(considered)h(as)0
+1398 y(one)c(w)o(ord.)0 1590 y Ff(6.1.1)30 b(Ev)n(en)n(t)16
+b(Designators)62 1727 y Fl(An)g(ev)o(en)o(t)f(designator)g(is)g(a)g
+(reference)h(to)f(a)g(command)g(line)i(en)o(try)d(in)i(the)g(history)f
+(list.)0 1872 y Fk(!)216 b Fl(Start)14 b(a)g(history)h(substitution,)g
+(except)h(when)f(follo)o(w)o(ed)g(b)o(y)g(a)f(space,)h(tab,)f(the)h
+(end)g(of)g(the)g(line,)240 1934 y Fk(=)g Fl(or)g Fk(\()p
+Fl(.)0 2014 y Fk(!!)192 b Fl(Refer)16 b(to)e(the)i(previous)f(command.)
+20 b(This)c(is)g(a)f(synon)o(ym)g(for)f Fk(!-1)p Fl(.)0
+2093 y Fk(!n)192 b Fl(Refer)16 b(to)e(command)h(line)i
+Fg(n)p Fl(.)0 2173 y Fk(!-n)168 b Fl(Refer)16 b(to)e(the)i(command)f
+Fg(n)g Fl(lines)i(bac)o(k.)0 2252 y Fk(!string)72 b Fl(Refer)16
+b(to)e(the)i(most)e(recen)o(t)h(command)g(starting)g(with)g
+Fg(string)p Fl(.)0 2323 y Fk(!?string)p Fl([)p Fk(?)p
+Fl(])240 2385 y(Refer)h(to)e(the)i(most)e(recen)o(t)h(command)g(con)o
+(taining)h Fg(string)p Fl(.)0 2465 y Fk(!#)192 b Fl(The)15
+b(en)o(tire)h(command)f(line)i(t)o(yp)q(ed)f(so)e(far.)0
+2535 y Fk(^string1^string2^)240 2598 y Fl(Quic)o(k)j(Substitution.)22
+b(Rep)q(eat)16 b(the)g(last)f(command,)h(replacing)h
+Fg(string1)h Fl(with)e Fg(string2)p Fl(.)21 b(Equiv-)240
+2660 y(alen)o(t)15 b(to)g Fk(!!:s/string1/string2/)p
+Fl(.)p eop
+34 35 bop 0 -58 a Fl(34)1623 b(Bash)15 b(F)l(eatures)0
+183 y Ff(6.1.2)30 b(W)-5 b(ord)15 b(Designators)62 320
+y Fl(A)i Fk(:)g Fl(separates)f(the)h(ev)o(en)o(t)f(sp)q(eci\014cation)j
+(from)d(the)g(w)o(ord)g(designator.)25 b(It)17 b(can)g(b)q(e)g(omitted)
+g(if)g(the)g(w)o(ord)0 382 y(designator)d(b)q(egins)h(with)f(a)f
+Fk(^)p Fl(,)h Fk($)p Fl(,)f Fk(*)h Fl(or)f Fk(\045)p
+Fl(.)20 b(W)l(ords)13 b(are)h(n)o(um)o(b)q(ered)g(from)f(the)h(b)q
+(eginning)i(of)d(the)h(line,)i(with)e(the)0 445 y(\014rst)h(w)o(ord)f
+(b)q(eing)j(denoted)f(b)o(y)f(a)g(0)f(\(zero\).)0 593
+y Fk(0)h(\(zero\))57 b Fl(The)15 b Fk(0)p Fl(th)g(w)o(ord.)20
+b(F)l(or)14 b(man)o(y)h(applications,)h(this)g(is)g(the)f(command)g(w)o
+(ord.)0 679 y Fk(n)216 b Fl(The)15 b Fg(n)p Fl(th)h(w)o(ord.)0
+765 y Fk(^)216 b Fl(The)15 b(\014rst)g(argumen)o(t;)f(that)h(is,)g(w)o
+(ord)g(1.)0 851 y Fk($)216 b Fl(The)15 b(last)h(argumen)o(t.)0
+937 y Fk(\045)216 b Fl(The)15 b(w)o(ord)g(matc)o(hed)g(b)o(y)g(the)g
+(most)g(recen)o(t)g Fk(?string?)f Fl(searc)o(h.)0 1022
+y Fk(x-y)168 b Fl(A)15 b(range)g(of)g(w)o(ords;)f Fk(-)p
+Fg(y)19 b Fl(abbreviates)c Fk(0-)p Fg(y)t Fl(.)0 1108
+y Fk(*)216 b Fl(All)17 b(of)f(the)g(w)o(ords,)f(except)i(the)f
+Fk(0)p Fl(th.)22 b(This)17 b(is)f(a)g(synon)o(ym)g(for)f
+Fk(1-$)p Fl(.)22 b(It)17 b(is)f(not)g(an)g(error)f(to)h(use)240
+1170 y Fk(*)f Fl(if)h(there)f(is)h(just)f(one)g(w)o(ord)f(in)i(the)g
+(ev)o(en)o(t;)e(the)i(empt)o(y)e(string)i(is)f(returned)h(in)g(that)e
+(case.)0 1256 y Fk(x*)192 b Fl(Abbreviates)16 b Fk(x-$)0
+1342 y(x-)192 b Fl(Abbreviates)16 b Fk(x-$)f Fl(lik)o(e)h
+Fk(x*)p Fl(,)e(but)i(omits)f(the)g(last)g(w)o(ord.)0
+1547 y Ff(6.1.3)30 b(Mo)r(di\014ers)62 1684 y Fl(After)20
+b(the)f(optional)i(w)o(ord)e(designator,)h(y)o(ou)f(can)h(add)g(a)g
+(sequence)h(of)e(one)h(or)f(more)g(of)g(the)h(follo)o(wing)0
+1746 y(mo)q(di\014ers,)c(eac)o(h)f(preceded)i(b)o(y)e(a)g
+Fk(:)p Fl(.)0 1895 y Fk(h)216 b Fl(Remo)o(v)o(e)15 b(a)g(trailing)h
+(pathname)f(comp)q(onen)o(t,)g(lea)o(ving)h(only)g(the)f(head.)0
+1980 y Fk(r)216 b Fl(Remo)o(v)o(e)15 b(a)g(trailing)h(su\016x)f(of)g
+(the)g(form)g(`)p Fk(.)p Fl(')p Fg(su\016x)p Fl(,)f(lea)o(ving)i(the)f
+(basename.)0 2066 y Fk(e)216 b Fl(Remo)o(v)o(e)15 b(all)h(but)g(the)f
+(trailing)h(su\016x.)0 2152 y Fk(t)216 b Fl(Remo)o(v)o(e)15
+b(all)h(leading)h(pathname)e(comp)q(onen)o(ts,)g(lea)o(ving)h(the)f
+(tail.)0 2238 y Fk(p)216 b Fl(Prin)o(t)15 b(the)g(new)h(command)f(but)g
+(do)g(not)g(execute)h(it.)0 2323 y Fk(q)216 b Fl(Quote)15
+b(the)h(substituted)g(w)o(ords,)e(escaping)i(further)f(substitutions.)0
+2409 y Fk(x)216 b Fl(Quote)22 b(the)f(substituted)h(w)o(ords)f(as)g
+(with)h Fk(q)p Fl(,)h(but)e(break)h(in)o(to)f(w)o(ords)g(at)g(spaces,)i
+(tabs,)f(and)240 2471 y(newlines.)0 2545 y Fk(s/old/new/)240
+2608 y Fl(Substitute)16 b Fg(new)k Fl(for)15 b(the)h(\014rst)f(o)q
+(ccurrence)h(of)g Fg(old)h Fl(in)g(the)e(ev)o(en)o(t)h(line.)22
+b(An)o(y)16 b(delimiter)h(ma)o(y)e(b)q(e)240 2670 y(used)e(in)f(place)h
+(of)f Fk(/)p Fl(.)19 b(The)12 b(delimiter)i(ma)o(y)d(b)q(e)i(quoted)f
+(in)h Fg(old)h Fl(and)e Fg(new)17 b Fl(with)12 b(a)g(single)h(bac)o
+(kslash.)p eop
+35 36 bop 0 -58 a Fl(Chapter)15 b(6:)k(Using)d(History)f(In)o(teractiv)
+o(ely)1135 b(35)240 183 y(If)13 b Fk(&)h Fl(app)q(ears)f(in)h
+Fg(new)p Fl(,)f(it)h(is)g(replaced)g(b)o(y)f Fg(old)p
+Fl(.)20 b(A)13 b(single)i(bac)o(kslash)e(will)i(quote)e(the)h
+Fk(&)p Fl(.)19 b(The)13 b(\014nal)240 246 y(delimiter)k(is)f(optional)g
+(if)f(it)h(is)f(the)h(last)f(c)o(haracter)f(on)h(the)h(input)g(line.)0
+333 y Fk(&)216 b Fl(Rep)q(eat)16 b(the)f(previous)h(substitution.)0
+420 y Fk(g)216 b Fl(Cause)15 b(c)o(hanges)g(to)f(b)q(e)i(applied)h(o)o
+(v)o(er)d(the)h(en)o(tire)g(ev)o(en)o(t)g(line.)21 b(Used)16
+b(in)g(conjunction)g(with)f Fk(s)p Fl(,)f(as)240 482
+y(in)i Fk(gs/old/new/)p Fl(,)d(or)i(with)h Fk(&)p Fl(.)p
+eop
+36 37 bop 0 -58 a Fl(36)1623 b(Bash)15 b(F)l(eatures)p
+eop
+37 38 bop 0 -58 a Fl(Chapter)15 b(7:)k(Command)c(Line)i(Editing)1205
+b(37)0 183 y Fh(7)41 b(Command)16 b(Line)f(Editing)62
+408 y Fl(This)h(c)o(hapter)f(describ)q(es)i(the)e(basic)h(features)f
+(of)g(the)g(GNU)g(command)g(line)i(editing)f(in)o(terface.)0
+701 y Fj(7.1)33 b(In)n(tro)r(duction)17 b(to)e(Line)h(Editing)62
+845 y Fl(The)g(follo)o(wing)g(paragraphs)e(describ)q(e)j(the)e
+(notation)g(used)h(to)e(represen)o(t)i(k)o(eystrok)o(es.)62
+990 y(The)f(text)e Fk(C-K)h Fl(is)g(read)g(as)g(`Con)o(trol-K')f(and)h
+(describ)q(es)i(the)e(c)o(haracter)f(pro)q(duced)i(when)g(the)f(Con)o
+(trol)f(k)o(ey)0 1052 y(is)j(depressed)g(and)f(the)h
+Fk(K)f Fl(k)o(ey)g(is)g(struc)o(k.)62 1197 y(The)i(text)f
+Fk(M-K)g Fl(is)i(read)e(as)g(`Meta-K')g(and)h(describ)q(es)h(the)f(c)o
+(haracter)f(pro)q(duced)h(when)h(the)e(meta)g(k)o(ey)h(\(if)0
+1259 y(y)o(ou)g(ha)o(v)o(e)f(one\))h(is)g(depressed,)h(and)f(the)g
+Fk(K)g Fl(k)o(ey)g(is)g(struc)o(k.)25 b(If)17 b(y)o(ou)f(do)h(not)g(ha)
+o(v)o(e)f(a)h(meta)f(k)o(ey)l(,)h(the)g(iden)o(tical)0
+1321 y(k)o(eystrok)o(e)i(can)g(b)q(e)i(generated)e(b)o(y)h(t)o(yping)f
+Fk(ESC)h Fg(\014rst)p Fl(,)g(and)f(then)h(t)o(yping)g
+Fk(K)p Fl(.)33 b(Either)20 b(pro)q(cess)g(is)g(kno)o(wn)f(as)0
+1383 y Fg(metafying)g Fl(the)c Fk(K)g Fl(k)o(ey)l(.)62
+1528 y(The)h(text)e Fk(M-C-K)g Fl(is)i(read)f(as)f(`Meta-Con)o(trol-k')
+g(and)h(describ)q(es)h(the)g(c)o(haracter)e(pro)q(duced)i(b)o(y)f
+Fg(metafying)0 1590 y Fk(C-K)p Fl(.)62 1735 y(In)i(addition,)h(sev)o
+(eral)e(k)o(eys)g(ha)o(v)o(e)g(their)h(o)o(wn)f(names.)23
+b(Sp)q(eci\014cally)m(,)c Fk(DEL)p Fl(,)d Fk(ESC)p Fl(,)f
+Fk(LFD)p Fl(,)h Fk(SPC)p Fl(,)g Fk(RET)p Fl(,)g(and)g
+Fk(TAB)0 1797 y Fl(all)e(stand)f(for)f(themselv)o(es)i(when)f(seen)h
+(in)g(this)f(text,)g(or)g(in)g(an)g(init)i(\014le)f(\(see)f(Section)h
+(7.3)e([Readline)j(Init)f(File],)0 1859 y(page)h(40,)f(for)h(more)g
+(info\).)0 2152 y Fj(7.2)33 b(Readline)16 b(In)n(teraction)62
+2296 y Fl(Often)g(during)h(an)f(in)o(teractiv)o(e)g(session)h(y)o(ou)e
+(t)o(yp)q(e)h(in)h(a)f(long)g(line)h(of)f(text,)f(only)h(to)g(notice)g
+(that)f(the)h(\014rst)0 2359 y(w)o(ord)d(on)i(the)f(line)i(is)e(missp)q
+(elled.)23 b(The)14 b(Readline)i(library)f(giv)o(es)g(y)o(ou)e(a)h(set)
+g(of)g(commands)g(for)f(manipulating)0 2421 y(the)18
+b(text)g(as)g(y)o(ou)g(t)o(yp)q(e)g(it)h(in,)g(allo)o(wing)g(y)o(ou)f
+(to)g(just)g(\014x)g(y)o(our)g(t)o(yp)q(o,)g(and)h(not)f(forcing)g(y)o
+(ou)g(to)g(ret)o(yp)q(e)g(the)0 2483 y(ma)s(jorit)o(y)d(of)h(the)g
+(line.)25 b(Using)17 b(these)g(editing)h(commands,)e(y)o(ou)g(mo)o(v)o
+(e)f(the)i(cursor)f(to)g(the)g(place)h(that)f(needs)0
+2545 y(correction,)g(and)h(delete)g(or)f(insert)g(the)h(text)e(of)h
+(the)g(corrections.)23 b(Then,)17 b(when)g(y)o(ou)f(are)g(satis\014ed)g
+(with)h(the)0 2608 y(line,)h(y)o(ou)e(simply)i(press)f
+Fk(RETURN)p Fl(.)23 b(Y)l(ou)17 b(do)f(not)g(ha)o(v)o(e)g(to)g(b)q(e)i
+(at)e(the)g(end)h(of)f(the)h(line)h(to)e(press)h Fk(RETURN)p
+Fl(;)f(the)0 2670 y(en)o(tire)g(line)h(is)e(accepted)h(regardless)f(of)
+g(the)g(lo)q(cation)h(of)f(the)h(cursor)e(within)j(the)e(line.)p
+eop
+38 39 bop 0 -58 a Fl(38)1623 b(Bash)15 b(F)l(eatures)0
+183 y Ff(7.2.1)30 b(Readline)15 b(Bare)g(Essen)n(tials)62
+320 y Fl(In)f(order)f(to)f(en)o(ter)h(c)o(haracters)g(in)o(to)g(the)g
+(line,)i(simply)f(t)o(yp)q(e)f(them.)19 b(The)14 b(t)o(yp)q(ed)f(c)o
+(haracter)f(app)q(ears)i(where)0 383 y(the)h(cursor)h(w)o(as,)e(and)h
+(then)h(the)g(cursor)f(mo)o(v)o(es)f(one)i(space)g(to)e(the)i(righ)o
+(t.)k(If)c(y)o(ou)f(mist)o(yp)q(e)h(a)f(c)o(haracter,)f(y)o(ou)0
+445 y(can)h(use)h(y)o(our)f(erase)g(c)o(haracter)f(to)h(bac)o(k)g(up)g
+(and)h(delete)g(the)f(mist)o(yp)q(ed)h(c)o(haracter.)62
+582 y(Sometimes)f(y)o(ou)e(ma)o(y)h(miss)g(t)o(yping)g(a)g(c)o
+(haracter)g(that)f(y)o(ou)h(w)o(an)o(ted)f(to)g(t)o(yp)q(e,)h(and)h
+(not)e(notice)i(y)o(our)f(error)0 644 y(un)o(til)k(y)o(ou)e(ha)o(v)o(e)
+g(t)o(yp)q(ed)h(sev)o(eral)g(other)f(c)o(haracters.)23
+b(In)18 b(that)d(case,)i(y)o(ou)f(can)h(t)o(yp)q(e)g
+Fk(C-B)f Fl(to)g(mo)o(v)o(e)g(the)g(cursor)0 706 y(to)f(the)h(left,)g
+(and)g(then)g(correct)f(y)o(our)h(mistak)o(e.)21 b(Afterw)o(ards,)14
+b(y)o(ou)i(can)g(mo)o(v)o(e)f(the)h(cursor)f(to)g(the)h(righ)o(t)g
+(with)0 769 y Fk(C-F)p Fl(.)62 906 y(When)i(y)o(ou)f(add)g(text)g(in)h
+(the)f(middle)i(of)e(a)g(line,)i(y)o(ou)e(will)i(notice)e(that)g(c)o
+(haracters)f(to)h(the)g(righ)o(t)g(of)g(the)0 968 y(cursor)h(are)h
+(`pushed)g(o)o(v)o(er')e(to)h(mak)o(e)g(ro)q(om)g(for)g(the)h(text)f
+(that)g(y)o(ou)g(ha)o(v)o(e)h(inserted.)31 b(Lik)o(ewise,)20
+b(when)f(y)o(ou)0 1030 y(delete)f(text)f(b)q(ehind)i(the)f(cursor,)f(c)
+o(haracters)f(to)h(the)g(righ)o(t)g(of)g(the)h(cursor)f(are)g(`pulled)i
+(bac)o(k')d(to)h(\014ll)i(in)f(the)0 1092 y(blank)g(space)f(created)g
+(b)o(y)g(the)h(remo)o(v)m(al)f(of)f(the)i(text.)25 b(A)17
+b(list)h(of)e(the)h(basic)h(bare)f(essen)o(tials)h(for)e(editing)j(the)
+0 1155 y(text)c(of)f(an)i(input)g(line)h(follo)o(ws.)0
+1304 y Fk(C-B)168 b Fl(Mo)o(v)o(e)14 b(bac)o(k)h(one)h(c)o(haracter.)0
+1391 y Fk(C-F)168 b Fl(Mo)o(v)o(e)14 b(forw)o(ard)g(one)h(c)o
+(haracter.)0 1478 y Fk(DEL)168 b Fl(Delete)16 b(the)f(c)o(haracter)g
+(to)f(the)h(left)h(of)f(the)g(cursor.)0 1566 y Fk(C-D)168
+b Fl(Delete)16 b(the)f(c)o(haracter)g(underneath)h(the)f(cursor.)0
+1640 y(Prin)o(ting)h(c)o(haracters)240 1703 y(Insert)f(the)h(c)o
+(haracter)e(in)o(to)h(the)h(line)h(at)d(the)h(cursor.)0
+1790 y Fk(C-_)168 b Fl(Undo)15 b(the)h(last)f(thing)h(that)e(y)o(ou)h
+(did.)21 b(Y)l(ou)15 b(can)h(undo)f(all)h(the)g(w)o(a)o(y)e(bac)o(k)h
+(to)f(an)i(empt)o(y)e(line.)0 1997 y Ff(7.2.2)30 b(Readline)15
+b(Mo)n(v)n(emen)n(t)h(Commands)62 2134 y Fl(The)c(ab)q(o)o(v)o(e)g
+(table)g(describ)q(es)i(the)e(most)f(basic)h(p)q(ossible)i(k)o(eystrok)
+o(es)d(that)g(y)o(ou)g(need)i(in)g(order)f(to)f(do)h(editing)0
+2197 y(of)g(the)h(input)h(line.)21 b(F)l(or)12 b(y)o(our)g(con)o(v)o
+(enience,)i(man)o(y)f(other)f(commands)h(ha)o(v)o(e)f(b)q(een)i(added)f
+(in)h(addition)g(to)e Fk(C-B)p Fl(,)0 2259 y Fk(C-F)p
+Fl(,)i Fk(C-D)p Fl(,)h(and)g Fk(DEL)p Fl(.)20 b(Here)15
+b(are)g(some)g(commands)g(for)f(mo)o(ving)h(more)g(rapidly)i(ab)q(out)e
+(the)g(line.)0 2408 y Fk(C-A)168 b Fl(Mo)o(v)o(e)14 b(to)h(the)g(start)
+f(of)h(the)g(line.)0 2496 y Fk(C-E)168 b Fl(Mo)o(v)o(e)14
+b(to)h(the)g(end)h(of)f(the)g(line.)0 2583 y Fk(M-F)168
+b Fl(Mo)o(v)o(e)14 b(forw)o(ard)g(a)h(w)o(ord.)0 2670
+y Fk(M-B)168 b Fl(Mo)o(v)o(e)14 b(bac)o(kw)o(ard)h(a)g(w)o(ord.)p
+eop
+39 40 bop 0 -58 a Fl(Chapter)15 b(7:)k(Command)c(Line)i(Editing)1205
+b(39)0 183 y Fk(C-L)168 b Fl(Clear)15 b(the)h(screen,)f(reprin)o(ting)h
+(the)f(curren)o(t)g(line)i(at)e(the)g(top.)62 350 y(Notice)22
+b(ho)o(w)e Fk(C-F)h Fl(mo)o(v)o(es)f(forw)o(ard)g(a)g(c)o(haracter,)i
+(while)g Fk(M-F)f Fl(mo)o(v)o(es)f(forw)o(ard)g(a)h(w)o(ord.)36
+b(It)21 b(is)h(a)f(lo)q(ose)0 412 y(con)o(v)o(en)o(tion)15
+b(that)g(con)o(trol)g(k)o(eystrok)o(es)f(op)q(erate)h(on)g(c)o
+(haracters)f(while)j(meta)e(k)o(eystrok)o(es)f(op)q(erate)h(on)g(w)o
+(ords.)0 696 y Ff(7.2.3)30 b(Readline)15 b(Killing)g(Commands)62
+841 y Fg(Killing)25 b Fl(text)18 b(means)g(to)f(delete)i(the)g(text)e
+(from)h(the)g(line,)i(but)e(to)g(sa)o(v)o(e)f(it)i(a)o(w)o(a)o(y)d(for)
+i(later)g(use,)h(usually)0 903 y(b)o(y)c Fg(y)o(anking)k
+Fl(\(re-inserting\))c(it)g(bac)o(k)g(in)o(to)g(the)g(line.)21
+b(If)16 b(the)f(description)h(for)e(a)h(command)f(sa)o(ys)h(that)f(it)h
+(`kills')0 966 y(text,)f(then)i(y)o(ou)f(can)g(b)q(e)h(sure)f(that)g(y)
+o(ou)g(can)g(get)g(the)g(text)g(bac)o(k)g(in)h(a)f(di\013eren)o(t)g
+(\(or)f(the)i(same\))e(place)i(later.)62 1111 y(When)g(y)o(ou)f(use)g
+(a)g(kill)i(command,)e(the)h(text)e(is)i(sa)o(v)o(ed)f(in)h(a)f
+Fg(kill-ring)p Fl(.)22 b(An)o(y)16 b(n)o(um)o(b)q(er)f(of)g(consecutiv)
+o(e)h(kills)0 1173 y(sa)o(v)o(e)g(all)i(of)e(the)h(killed)i(text)d
+(together,)g(so)g(that)g(when)h(y)o(ou)f(y)o(ank)h(it)g(bac)o(k,)f(y)o
+(ou)h(get)f(it)h(all.)25 b(The)17 b(kill)h(ring)f(is)0
+1236 y(not)e(line)i(sp)q(eci\014c;)g(the)f(text)f(that)g(y)o(ou)g
+(killed)j(on)d(a)h(previously)g(t)o(yp)q(ed)g(line)h(is)f(a)o(v)m
+(ailable)i(to)d(b)q(e)h(y)o(ank)o(ed)f(bac)o(k)0 1298
+y(later,)g(when)h(y)o(ou)e(are)h(t)o(yping)h(another)e(line.)62
+1443 y(Here)i(is)f(the)h(list)g(of)e(commands)h(for)g(killing)j(text.)0
+1610 y Fk(C-K)168 b Fl(Kill)17 b(the)f(text)e(from)h(the)g(curren)o(t)g
+(cursor)g(p)q(osition)h(to)f(the)g(end)h(of)f(the)g(line.)0
+1714 y Fk(M-D)168 b Fl(Kill)17 b(from)d(the)h(cursor)g(to)f(the)h(end)g
+(of)g(the)g(curren)o(t)f(w)o(ord,)g(or)g(if)i(b)q(et)o(w)o(een)f(w)o
+(ords,)f(to)g(the)h(end)g(of)240 1776 y(the)g(next)h(w)o(ord.)0
+1880 y Fk(M-DEL)120 b Fl(Kill)16 b(from)d(the)i(cursor)e(the)h(start)f
+(of)h(the)g(previous)h(w)o(ord,)e(or)g(if)i(b)q(et)o(w)o(een)f(w)o
+(ords,)f(to)h(the)g(start)e(of)240 1942 y(the)j(previous)h(w)o(ord.)0
+2046 y Fk(C-W)168 b Fl(Kill)18 b(from)e(the)g(cursor)g(to)f(the)h
+(previous)h(whitespace.)24 b(This)17 b(is)f(di\013eren)o(t)h(than)f
+Fk(M-DEL)f Fl(b)q(ecause)240 2109 y(the)g(w)o(ord)g(b)q(oundaries)h
+(di\013er.)62 2275 y(And,)e(here)g(is)h(ho)o(w)e(to)g
+Fg(y)o(ank)j Fl(the)e(text)f(bac)o(k)g(in)o(to)h(the)f(line.)22
+b(Y)l(anking)14 b(means)g(to)f(cop)o(y)g(the)h(most-recen)o(tly-)0
+2337 y(killed)j(text)e(from)g(the)g(kill)i(bu\013er.)0
+2504 y Fk(C-Y)168 b Fl(Y)l(ank)15 b(the)h(most)e(recen)o(tly)i(killed)h
+(text)e(bac)o(k)g(in)o(to)g(the)h(bu\013er)f(at)f(the)i(cursor.)0
+2608 y Fk(M-Y)168 b Fl(Rotate)13 b(the)h(kill-ring,)i(and)e(y)o(ank)g
+(the)g(new)g(top.)19 b(Y)l(ou)14 b(can)g(only)g(do)g(this)g(if)g(the)g
+(prior)g(command)240 2670 y(is)i Fk(C-Y)e Fl(or)h Fk(M-Y)p
+Fl(.)p eop
+40 41 bop 0 -58 a Fl(40)1623 b(Bash)15 b(F)l(eatures)0
+183 y Ff(7.2.4)30 b(Readline)15 b(Argumen)n(ts)62 330
+y Fl(Y)l(ou)k(can)g(pass)f(n)o(umeric)i(argumen)o(ts)d(to)h(Readline)j
+(commands.)30 b(Sometimes)19 b(the)f(argumen)o(t)g(acts)g(as)g(a)0
+392 y(rep)q(eat)f(coun)o(t,)f(other)g(times)g(it)h(is)g(the)g
+Fg(sign)f Fl(of)g(the)h(argumen)o(t)f(that)f(is)i(signi\014can)o(t.)25
+b(If)16 b(y)o(ou)h(pass)f(a)g(negativ)o(e)0 455 y(argumen)o(t)g(to)g(a)
+h(command)g(whic)o(h)h(normally)f(acts)g(in)h(a)e(forw)o(ard)g
+(direction,)i(that)f(command)f(will)j(act)d(in)i(a)0
+517 y(bac)o(kw)o(ard)13 b(direction.)21 b(F)l(or)13 b(example,)h(to)f
+(kill)i(text)e(bac)o(k)h(to)f(the)h(start)e(of)h(the)h(line,)h(y)o(ou)e
+(migh)o(t)h(t)o(yp)q(e)g Fk(M--)f(C-K)p Fl(.)62 664 y(The)19
+b(general)g(w)o(a)o(y)f(to)g(pass)g(n)o(umeric)i(argumen)o(ts)e(to)g(a)
+g(command)h(is)g(to)f(t)o(yp)q(e)g(meta)g(digits)i(b)q(efore)f(the)0
+726 y(command.)36 b(If)21 b(the)g(\014rst)f(`digit')h(y)o(ou)g(t)o(yp)q
+(e)f(is)i(a)e(min)o(us)h(sign)g(\()p Fk(-)p Fl(\),)g(then)g(the)g(sign)
+g(of)g(the)f(argumen)o(t)g(will)0 788 y(b)q(e)i(negativ)o(e.)40
+b(Once)22 b(y)o(ou)f(ha)o(v)o(e)h(t)o(yp)q(ed)g(one)f(meta)g(digit)i
+(to)e(get)g(the)h(argumen)o(t)f(started,)h(y)o(ou)f(can)h(t)o(yp)q(e)0
+851 y(the)c(remainder)h(of)f(the)g(digits,)h(and)f(then)h(the)f
+(command.)29 b(F)l(or)17 b(example,)i(to)f(giv)o(e)g(the)g
+Fk(C-D)g Fl(command)g(an)0 913 y(argumen)o(t)c(of)h(10,)f(y)o(ou)h
+(could)h(t)o(yp)q(e)g Fk(M-1)23 b(0)h(C-D)p Fl(.)0 1226
+y Fj(7.3)33 b(Readline)16 b(Init)g(File)62 1373 y Fl(Although)g(the)g
+(Readline)h(library)g(comes)e(with)h(a)f(set)g(of)g(Emacs-lik)o(e)h(k)o
+(eybindings)h(installed)g(b)o(y)f(default,)0 1435 y(it)e(is)g(p)q
+(ossible)i(that)d(y)o(ou)g(w)o(ould)h(lik)o(e)h(to)e(use)h(a)f
+(di\013eren)o(t)h(set)g(of)f(k)o(eybindings.)21 b(Y)l(ou)14
+b(can)g(customize)g(programs)0 1497 y(that)i(use)i(Readline)h(b)o(y)e
+(putting)h(commands)f(in)h(an)f Fg(init)i Fl(\014le)f(in)g(y)o(our)f
+(home)g(directory)l(.)26 b(The)18 b(name)f(of)g(this)0
+1559 y(\014le)h(is)g(tak)o(en)f(from)g(the)g(v)m(alue)i(of)e(the)g
+(shell)i(v)m(ariable)g Fk(INPUTRC)p Fl(.)25 b(If)18 b(that)f(v)m
+(ariable)h(is)g(unset,)g(the)f(default)h(is)0 1622 y(`)p
+Fk(~/.inputrc)p Fl('.)62 1769 y(When)h(a)g(program)e(whic)o(h)j(uses)f
+(the)g(Readline)i(library)e(starts)f(up,)h(the)g(init)h(\014le)g(is)f
+(read,)g(and)g(the)g(k)o(ey)0 1831 y(bindings)e(are)e(set.)62
+1978 y(In)j(addition,)h(the)f Fk(C-x)c(C-r)k Fl(command)f(re-reads)g
+(this)h(init)h(\014le,)g(th)o(us)e(incorp)q(orating)h(an)o(y)f(c)o
+(hanges)h(that)0 2040 y(y)o(ou)d(migh)o(t)g(ha)o(v)o(e)g(made)g(to)f
+(it.)0 2336 y Ff(7.3.1)30 b(Readline)15 b(Init)g(Syn)n(tax)62
+2483 y Fl(There)h(are)f(only)h(a)f(few)g(basic)h(constructs)f(allo)o(w)
+o(ed)h(in)g(the)g(Readline)i(init)e(\014le.)22 b(Blank)16
+b(lines)h(are)e(ignored.)0 2545 y(Lines)j(b)q(eginning)g(with)f(a)f
+Fk(#)g Fl(are)g(commen)o(ts.)22 b(Lines)c(b)q(eginning)g(with)f(a)f
+Fk($)g Fl(indicate)h(conditional)h(constructs)0 2608
+y(\(see)d(Section)g(7.3.2)e([Conditional)j(Init)f(Constructs],)f(page)g
+(43\).)19 b(Other)c(lines)h(denote)f(v)m(ariable)h(settings)f(and)0
+2670 y(k)o(ey)g(bindings.)p eop
+41 42 bop 0 -58 a Fl(Chapter)15 b(7:)k(Command)c(Line)i(Editing)1205
+b(41)0 183 y(V)l(ariable)16 b(Settings)240 246 y(Y)l(ou)j(can)g(c)o
+(hange)g(the)g(state)f(of)g(a)g(few)h(v)m(ariables)h(in)g(Readline)h(b)
+o(y)d(using)i(the)f Fk(set)f Fl(command)240 308 y(within)e(the)f(init)h
+(\014le.)k(Here)15 b(is)g(ho)o(w)g(y)o(ou)f(w)o(ould)h(sp)q(ecify)h
+(that)e(y)o(ou)g(wish)i(to)e(use)h Fk(vi)f Fl(line)j(editing)240
+370 y(commands:)360 433 y Fk(set)23 b(editing-mode)g(vi)240
+509 y Fl(Righ)o(t)14 b(no)o(w,)f(there)h(are)f(only)h(a)f(few)h(v)m
+(ariables)g(whic)o(h)h(can)f(b)q(e)g(set;)f(so)g(few,)h(in)g(fact,)f
+(that)g(w)o(e)g(just)240 571 y(list)j(them)f(here:)240
+647 y Fk(editing-mode)480 709 y Fl(The)e Fk(editing-mode)e
+Fl(v)m(ariable)j(con)o(trols)e(whic)o(h)h(editing)h(mo)q(de)f(y)o(ou)f
+(are)g(using.)20 b(By)480 771 y(default,)f(Readline)h(starts)c(up)i(in)
+h(Emacs)e(editing)i(mo)q(de,)f(where)g(the)g(k)o(eystrok)o(es)480
+833 y(are)c(most)g(similar)h(to)f(Emacs.)19 b(This)c(v)m(ariable)h(can)
+f(b)q(e)g(set)f(to)g(either)h Fk(emacs)f Fl(or)g Fk(vi)p
+Fl(.)240 909 y Fk(horizontal-scroll-mode)480 971 y Fl(This)k(v)m
+(ariable)g(can)f(b)q(e)g(set)g(to)f(either)i Fk(On)f
+Fl(or)f Fk(Off)p Fl(.)25 b(Setting)17 b(it)g(to)f Fk(On)h
+Fl(means)g(that)480 1033 y(the)d(text)g(of)f(the)h(lines)i(that)d(y)o
+(ou)h(edit)h(will)g(scroll)g(horizon)o(tally)g(on)f(a)g(single)h
+(screen)480 1096 y(line)f(when)f(they)g(are)f(longer)h(than)f(the)h
+(width)g(of)f(the)g(screen,)h(instead)g(of)g(wrapping)480
+1158 y(on)o(to)h(a)h(new)h(screen)f(line.)22 b(By)15
+b(default,)h(this)f(v)m(ariable)i(is)f(set)e(to)h Fk(Off)p
+Fl(.)240 1234 y Fk(mark-modified-lines)480 1296 y Fl(This)h(v)m
+(ariable,)g(when)g(set)f(to)f Fk(On)p Fl(,)h(sa)o(ys)f(to)g(displa)o(y)
+j(an)e(asterisk)g(\(`)p Fk(*)p Fl('\))e(at)i(the)g(start)480
+1358 y(of)f(history)h(lines)i(whic)o(h)e(ha)o(v)o(e)g(b)q(een)h(mo)q
+(di\014ed.)21 b(This)15 b(v)m(ariable)h(is)g Fk(off)e
+Fl(b)o(y)h(default.)240 1434 y Fk(bell-style)480 1496
+y Fl(Con)o(trols)h(what)f(happ)q(ens)j(when)f(Readline)h(w)o(an)o(ts)e
+(to)f(ring)i(the)f(terminal)h(b)q(ell.)26 b(If)480 1558
+y(set)13 b(to)g Fk(none)p Fl(,)g(Readline)j(nev)o(er)e(rings)g(the)g(b)
+q(ell.)21 b(If)14 b(set)f(to)g Fk(visible)p Fl(,)g(Readline)j(uses)480
+1621 y(a)g(visible)j(b)q(ell)g(if)e(one)g(is)g(a)o(v)m(ailable.)27
+b(If)17 b(set)f(to)g Fk(audible)g Fl(\(the)h(default\),)g(Readline)480
+1683 y(attempts)d(to)h(ring)g(the)h(terminal's)f(b)q(ell.)240
+1758 y Fk(comment-begin)480 1821 y Fl(The)21 b(string)h(to)e(insert)i
+(at)e(the)h(b)q(eginning)j(of)c(the)i(line)g(when)g(the)f
+Fk(vi-comment)480 1883 y Fl(command)15 b(is)h(executed.)21
+b(The)15 b(default)h(v)m(alue)g(is)g Fk("#")p Fl(.)240
+1958 y Fk(meta-flag)480 2021 y Fl(If)d(set)g(to)f Fk(on)p
+Fl(,)g(Readline)j(will)g(enable)f(eigh)o(t-bit)f(input)h(\(it)f(will)h
+(not)f(strip)g(the)g(eigh)o(th)480 2083 y(bit)i(from)g(the)g(c)o
+(haracters)f(it)h(reads\),)f(regardless)h(of)g(what)f(the)h(terminal)h
+(claims)g(it)480 2145 y(can)f(supp)q(ort.)20 b(The)c(default)g(v)m
+(alue)g(is)g Fk(off)p Fl(.)240 2221 y Fk(convert-meta)480
+2283 y Fl(If)23 b(set)f(to)f Fk(on)p Fl(,)j(Readline)h(will)f(con)o(v)o
+(ert)d(c)o(haracters)h(with)g(the)h(eigth)g(bit)f(set)h(to)480
+2345 y(an)17 b(ASCI)q(I)g(k)o(ey)g(sequence)h(b)o(y)e(stripping)i(the)f
+(eigth)g(bit)g(and)g(prep)q(ending)i(an)d Fk(ESC)480
+2408 y Fl(c)o(haracter,)h(con)o(v)o(erting)g(them)g(to)f(a)h
+(meta-pre\014xed)h(k)o(ey)f(sequence.)27 b(The)17 b(default)480
+2470 y(v)m(alue)f(is)g Fk(on)p Fl(.)240 2545 y Fk(output-meta)480
+2608 y Fl(If)d(set)f(to)g Fk(on)p Fl(,)h(Readline)i(will)f(displa)o(y)g
+(c)o(haracters)d(with)i(the)g(eigh)o(th)g(bit)g(set)g(directly)480
+2670 y(rather)i(than)g(as)f(a)h(meta-pre\014xed)h(escap)q(e)g
+(sequence.)21 b(The)16 b(default)f(is)h Fk(off)p Fl(.)p
+eop
+42 43 bop 0 -58 a Fl(42)1623 b(Bash)15 b(F)l(eatures)240
+183 y Fk(completion-query-items)480 246 y Fl(The)d(n)o(um)o(b)q(er)g
+(of)f(p)q(ossible)j(completions)e(that)f(determines)i(when)f(the)g
+(user)g(is)g(ask)o(ed)480 308 y(whether)k(he)h(w)o(an)o(ts)d(to)i(see)g
+(the)g(list)h(of)e(p)q(ossibiliti)q(es.)25 b(If)16 b(the)g(n)o(um)o(b)q
+(er)h(of)e(p)q(ossible)480 370 y(completions)i(is)f(greater)f(than)h
+(this)h(v)m(alue,)f(Readline)j(will)e(ask)f(the)g(user)g(whether)480
+432 y(or)k(not)h(he)h(wishes)f(to)g(view)g(them;)j(otherwise,)e(they)f
+(are)g(simply)h(listed.)39 b(The)480 495 y(default)16
+b(limit)g(is)g Fk(100)p Fl(.)240 588 y Fk(keymap)96 b
+Fl(Sets)13 b(Readline's)i(idea)e(of)g(the)g(curren)o(t)f(k)o(eymap)h
+(for)f(k)o(ey)h(binding)i(commands.)k(Ac-)480 651 y(ceptable)d
+Fk(keymap)e Fl(names)h(are)g Fk(emacs)p Fl(,)f Fk(emacs-standard)p
+Fl(,)f Fk(emacs-meta)p Fl(,)g Fk(emacs-)480 713 y(ctlx)p
+Fl(,)j Fk(vi)p Fl(,)h Fk(vi-move)p Fl(,)f Fk(vi-command)p
+Fl(,)g(and)h Fk(vi-insert)p Fl(.)23 b Fk(vi)17 b Fl(is)g(equiv)m(alen)o
+(t)i(to)d Fk(vi-)480 775 y(command)p Fl(;)22 b Fk(emacs)e
+Fl(is)h(equiv)m(alen)o(t)h(to)e Fk(emacs-standard)p Fl(.)35
+b(The)20 b(default)i(v)m(alue)f(is)480 838 y Fk(emacs)p
+Fl(.)33 b(The)21 b(v)m(alue)g(of)e(the)i Fk(editing-mode)d
+Fl(v)m(ariable)j(also)f(a\013ects)f(the)h(default)480
+900 y(k)o(eymap.)240 978 y Fk(show-all-if-ambiguous)480
+1040 y Fl(This)d(alters)f(the)h(default)g(b)q(eha)o(vior)g(of)f(the)g
+(completion)i(functions.)24 b(If)17 b(set)f(to)g Fk(on)p
+Fl(,)480 1102 y(w)o(ords)d(whic)o(h)h(ha)o(v)o(e)f(more)h(than)f(one)h
+(p)q(ossible)h(completion)g(cause)f(the)f(matc)o(hes)h(to)480
+1165 y(b)q(e)h(listed)g(immediately)h(instead)f(of)f(ringing)h(the)f(b)
+q(ell.)22 b(The)14 b(default)h(v)m(alue)g(is)g Fk(off)p
+Fl(.)240 1243 y Fk(expand-tilde)480 1305 y Fl(If)20 b(set)f(to)g
+Fk(on)p Fl(,)h(tilde)h(expansion)f(is)g(p)q(erformed)g(when)g(Readline)
+i(attempts)d(w)o(ord)480 1367 y(completion.)i(The)15
+b(default)h(is)g Fk(off)p Fl(.)0 1445 y(Key)g(Bindings)240
+1508 y(The)k(syn)o(tax)f(for)g(con)o(trolling)i(k)o(ey)e(bindings)j(in)
+e(the)g(init)h(\014le)g(is)f(simple.)35 b(First)19 b(y)o(ou)g(ha)o(v)o
+(e)h(to)240 1570 y(kno)o(w)13 b(the)h(name)g(of)f(the)h(command)g(that)
+f(y)o(ou)g(w)o(an)o(t)g(to)g(c)o(hange.)20 b(The)14 b(follo)o(wing)g
+(pages)g(con)o(tain)240 1632 y(tables)i(of)f(the)h(command)g(name,)f
+(the)h(default)g(k)o(eybinding,)i(and)e(a)f(short)g(description)i(of)f
+(what)240 1694 y(the)f(command)g(do)q(es.)240 1772 y(Once)h(y)o(ou)e
+(kno)o(w)g(the)h(name)g(of)f(the)h(command,)f(simply)i(place)g(the)f
+(name)f(of)h(the)f(k)o(ey)h(y)o(ou)f(wish)240 1835 y(to)g(bind)j(the)e
+(command)g(to,)f(a)g(colon,)i(and)f(then)g(the)g(name)g(of)g(the)g
+(command)g(on)g(a)f(line)j(in)f(the)240 1897 y(init)h(\014le.)22
+b(The)16 b(name)g(of)f(the)h(k)o(ey)f(can)h(b)q(e)g(expressed)h(in)f
+(di\013eren)o(t)g(w)o(a)o(ys,)f(dep)q(ending)i(on)f(whic)o(h)240
+1959 y(is)g(most)e(comfortable)h(for)g(y)o(ou.)240 2037
+y Fg(k)o(eyname)s Fl(:)k Fg(function-name)g Fl(or)c Fg(macro)480
+2100 y(k)o(eyname)j Fl(is)d(the)h(name)f(of)g(a)g(k)o(ey)g(sp)q(elled)i
+(out)e(in)h(English.)21 b(F)l(or)15 b(example:)600 2165
+y Fk(Control-u:)22 b(universal-argument)600 2215 y(Meta-Rubout:)g
+(backward-kill-word)600 2265 y(Control-o:)g(">&output")480
+2343 y Fl(In)12 b(the)g(ab)q(o)o(v)o(e)f(example,)h(`)p
+Fk(C-u)p Fl(')f(is)h(b)q(ound)g(to)f(the)h(function)g
+Fk(universal-argument)p Fl(,)480 2405 y(and)h(`)p Fk(C-o)p
+Fl(')f(is)h(b)q(ound)h(to)f(run)g(the)g(macro)f(expressed)i(on)f(the)g
+(righ)o(t)g(hand)g(side)h(\(that)480 2467 y(is,)h(to)g(insert)h(the)f
+(text)g(`)p Fk(>&output)p Fl(')e(in)o(to)i(the)g(line\).)240
+2545 y Fk(")p Fg(k)o(eyseq)q Fk(")p Fl(:)20 b Fg(function-name)e
+Fl(or)d Fg(macro)480 2608 y(k)o(eyseq)j Fl(di\013ers)f(from)f
+Fg(k)o(eyname)k Fl(ab)q(o)o(v)o(e)c(in)i(that)e(strings)h(denoting)h
+(an)f(en)o(tire)g(k)o(ey)480 2670 y(sequence)i(can)f(b)q(e)h(sp)q
+(eci\014ed,)i(b)o(y)d(placing)h(the)f(k)o(ey)g(sequence)h(in)g(double)h
+(quotes.)p eop
+43 44 bop 0 -58 a Fl(Chapter)15 b(7:)k(Command)c(Line)i(Editing)1205
+b(43)480 183 y(Some)18 b(GNU)g(Emacs)f(st)o(yle)h(k)o(ey)g(escap)q(es)g
+(can)g(b)q(e)h(used,)g(as)e(in)i(the)f(follo)o(wing)h(ex-)480
+246 y(ample,)c(but)h(the)f(sp)q(ecial)i(c)o(haracter)e(names)g(are)g
+(not)f(recognized.)600 308 y Fk("\\C-u":)23 b(universal-argument)600
+358 y("\\C-x\\C-r":)f(re-read-init-file)600 407 y("\\e[11~":)h
+("Function)f(Key)i(1")480 482 y Fl(In)13 b(the)g(ab)q(o)o(v)o(e)g
+(example,)g(`)p Fk(C-u)p Fl(')f(is)h(b)q(ound)h(to)e(the)h(function)g
+Fk(universal-argument)480 544 y Fl(\(just)g(as)f(it)i(w)o(as)e(in)i
+(the)f(\014rst)g(example\),)h(`)p Fk(C-x)g(C-r)p Fl(')f(is)g(b)q(ound)i
+(to)d(the)h(function)h Fk(re-)480 607 y(read-init-file)p
+Fl(,)g(and)i(`)p Fk(ESC)e([)h(1)g(1)g(~)p Fl(')h(is)g(b)q(ound)h(to)f
+(insert)g(the)g(text)f(`)p Fk(Function)480 669 y(Key)g(1)p
+Fl('.)24 b(The)18 b(follo)o(wing)f(escap)q(e)h(sequences)g(are)f(a)o(v)
+m(ailable)i(when)e(sp)q(ecifying)i(k)o(ey)480 731 y(sequences:)480
+818 y Fk(\\C-)168 b Fl(con)o(trol)15 b(pre\014x)480 906
+y Fk(\\M-)168 b Fl(meta)15 b(pre\014x)480 993 y Fk(\\e)192
+b Fl(an)15 b(escap)q(e)h(c)o(haracter)480 1080 y Fk(\\\\)192
+b Fl(bac)o(kslash)480 1167 y Fk(\\")g(")480 1254 y(\\')g(')480
+1342 y Fl(When)14 b(en)o(tering)h(the)f(text)f(of)h(a)f(macro,)g
+(single)j(or)d(double)i(quotes)f(should)h(b)q(e)f(used)480
+1404 y(to)g(indicate)j(a)e(macro)f(de\014nition.)22 b(Unquoted)15
+b(text)g(is)g(assumed)g(to)g(b)q(e)g(a)g(function)480
+1466 y(name.)27 b(Bac)o(kslash)18 b(will)h(quote)e(an)o(y)g(c)o
+(haracter)g(in)h(the)g(macro)f(text,)g(including)j Fk(")480
+1528 y Fl(and)c Fk(')p Fl(.)22 b(F)l(or)16 b(example,)h(the)f(follo)o
+(wing)h(binding)h(will)f(mak)o(e)f Fk(C-x)f(\\)g Fl(insert)i(a)f
+(single)480 1591 y Fk(\\)f Fl(in)o(to)g(the)g(line:)600
+1653 y Fk("\\C-x\\\\":)23 b("\\\\")0 1860 y Ff(7.3.2)30
+b(Conditional)15 b(Init)g(Constructs)62 1997 y Fl(Readline)j(implemen)o
+(ts)e(a)f(facilit)o(y)h(similar)g(in)g(spirit)g(to)f(the)g(conditional)
+i(compilation)f(features)f(of)g(the)g(C)0 2060 y(prepro)q(cessor)f
+(whic)o(h)h(allo)o(ws)f(k)o(ey)g(bindings)h(and)f(v)m(ariable)i
+(settings)e(to)f(b)q(e)h(p)q(erformed)h(as)e(the)h(result)g(of)g
+(tests.)0 2122 y(There)h(are)g(three)h(parser)e(directiv)o(es)j(used.)0
+2271 y Fk($if)168 b Fl(The)14 b Fk($if)e Fl(construct)h(allo)o(ws)h
+(bindings)h(to)e(b)q(e)h(made)f(based)h(on)f(the)h(editing)g(mo)q(de,)g
+(the)f(terminal)240 2334 y(b)q(eing)k(used,)e(or)g(the)g(application)i
+(using)f(Readline.)22 b(The)16 b(text)f(of)g(the)g(test)g(extends)g(to)
+g(the)g(end)240 2396 y(of)g(the)g(line;)i(no)e(c)o(haracters)f(are)h
+(required)h(to)f(isolate)g(it.)240 2483 y Fk(mode)144
+b Fl(The)19 b Fk(mode=)f Fl(form)g(of)h(the)g Fk($if)f
+Fl(directiv)o(e)i(is)f(used)h(to)e(test)g(whether)h(Readline)i(is)480
+2545 y(in)h Fk(emacs)f Fl(or)f Fk(vi)h Fl(mo)q(de.)38
+b(This)22 b(ma)o(y)f(b)q(e)h(used)g(in)g(conjunction)g(with)f(the)h(`)p
+Fk(set)480 2608 y(keymap)p Fl(')d(command,)i(for)e(instance,)j(to)d
+(set)h(bindings)i(in)f(the)f Fk(emacs-standard)480 2670
+y Fl(and)15 b Fk(emacs-ctlx)f Fl(k)o(eymaps)h(only)h(if)f(Readline)j
+(is)e(starting)e(out)h(in)h Fk(emacs)f Fl(mo)q(de.)p
+eop
+44 45 bop 0 -58 a Fl(44)1623 b(Bash)15 b(F)l(eatures)240
+183 y Fk(term)144 b Fl(The)21 b Fk(term=)f Fl(form)g(ma)o(y)h(b)q(e)g
+(used)h(to)e(include)j(terminal-sp)q(eci\014c)h(k)o(ey)c(bindings,)480
+246 y(p)q(erhaps)15 b(to)f(bind)j(the)d(k)o(ey)h(sequences)h(output)e
+(b)o(y)h(the)g(terminal's)g(function)h(k)o(eys.)480 308
+y(The)f(w)o(ord)g(on)f(the)i(righ)o(t)e(side)i(of)f(the)g(`)p
+Fk(=)p Fl(')f(is)h(tested)g(against)g(the)g(full)h(name)f(of)g(the)480
+370 y(terminal)k(and)g(the)g(p)q(ortion)g(of)f(the)h(terminal)g(name)g
+(b)q(efore)g(the)g(\014rst)f(`)p Fk(-)p Fl('.)29 b(This)480
+432 y(allo)o(ws)15 b Fg(sun)h Fl(to)e(matc)o(h)h(b)q(oth)g
+Fg(sun)h Fl(and)f Fg(sun-cmd)p Fl(,)h(for)f(instance.)240
+510 y Fk(application)480 572 y Fl(The)j Fg(application)i
+Fl(construct)e(is)g(used)h(to)e(include)k(application-sp)q(eci\014c)g
+(settings.)480 634 y(Eac)o(h)d(program)g(using)h(the)f(Readline)j
+(library)e(sets)f(the)h Fg(application)h(name)p Fl(,)f(and)480
+697 y(y)o(ou)c(can)h(test)f(for)g(it.)21 b(This)16 b(could)g(b)q(e)h
+(used)f(to)e(bind)j(k)o(ey)f(sequences)g(to)f(functions)480
+759 y(useful)h(for)e(a)h(sp)q(eci\014c)i(program.)h(F)l(or)d(instance,)
+g(the)g(follo)o(wing)h(command)e(adds)h(a)480 821 y(k)o(ey)g(sequence)h
+(that)f(quotes)g(the)g(curren)o(t)g(or)g(previous)h(w)o(ord)e(in)i
+(Bash:)600 886 y Fk($if)23 b(bash)600 936 y(#)h(Quote)f(the)g(current)g
+(or)h(previous)f(word)600 986 y("\\C-xq":)g("\\eb\\"\\ef\\"")600
+1036 y($endif)0 1129 y($endif)96 b Fl(This)16 b(command,)e(as)h(y)o(ou)
+g(sa)o(w)g(in)h(the)f(previous)h(example,)f(terminates)h(an)f
+Fk($if)f Fl(command.)0 1222 y Fk($else)120 b Fl(Commands)15
+b(in)h(this)f(branc)o(h)h(of)e(the)i Fk($if)e Fl(directiv)o(e)j(are)e
+(executed)h(if)g(the)f(test)g(fails.)0 1472 y Fj(7.4)33
+b(Bindable)16 b(Readline)h(Commands)0 1706 y Ff(7.4.1)30
+b(Commands)15 b(F)-5 b(or)15 b(Mo)n(ving)0 1846 y Fk(beginning-of-line)
+e(\(C-a\))240 1908 y Fl(Mo)o(v)o(e)h(to)h(the)g(start)f(of)h(the)g
+(curren)o(t)g(line.)0 1986 y Fk(end-of-line)f(\(C-e\))240
+2048 y Fl(Mo)o(v)o(e)g(to)h(the)g(end)h(of)f(the)g(line.)0
+2126 y Fk(forward-char)f(\(C-f\))240 2188 y Fl(Mo)o(v)o(e)g(forw)o(ard)
+g(a)h(c)o(haracter.)0 2266 y Fk(backward-char)e(\(C-b\))240
+2328 y Fl(Mo)o(v)o(e)h(bac)o(k)h(a)g(c)o(haracter.)0
+2406 y Fk(forward-word)f(\(M-f\))240 2468 y Fl(Mo)o(v)o(e)g(forw)o(ard)
+g(to)h(the)g(end)h(of)f(the)g(next)g(w)o(ord.)k(W)l(ords)c(are)g(comp)q
+(osed)h(of)e(letters)i(and)f(digits.)0 2545 y Fk(backward-word)e
+(\(M-b\))240 2608 y Fl(Mo)o(v)o(e)j(bac)o(k)g(to)g(the)h(start)f(of)g
+(this,)h(or)g(the)f(previous,)i(w)o(ord.)24 b(W)l(ords)16
+b(are)g(comp)q(osed)i(of)e(letters)240 2670 y(and)f(digits.)p
+eop
+45 46 bop 0 -58 a Fl(Chapter)15 b(7:)k(Command)c(Line)i(Editing)1205
+b(45)0 183 y Fk(clear-screen)14 b(\(C-l\))240 246 y Fl(Clear)h(the)g
+(screen)g(and)g(redra)o(w)f(the)h(curren)o(t)g(line,)h(lea)o(ving)g
+(the)f(curren)o(t)f(line)j(at)d(the)h(top)f(of)h(the)240
+308 y(screen.)0 386 y Fk(redraw-current-line)e(\(\))240
+448 y Fl(Refresh)j(the)f(curren)o(t)g(line.)22 b(By)15
+b(default,)h(this)f(is)h(un)o(b)q(ound.)0 688 y Ff(7.4.2)30
+b(Commands)15 b(F)-5 b(or)15 b(Manipulating)g(The)g(History)0
+829 y Fk(accept-line)f(\(Newline,)g(Return\))240 891
+y Fl(Accept)k(the)g(line)h(regardless)f(of)f(where)h(the)g(cursor)f
+(is.)28 b(If)18 b(this)g(line)h(is)g(non-empt)o(y)l(,)f(add)g(it)g(to)
+240 953 y(the)d(history)f(list)h(according)g(to)f(the)g(setting)h(of)f
+(the)g Fk(HISTCONTROL)f Fl(v)m(ariable.)21 b(If)15 b(this)g(line)h(w)o
+(as)d(a)240 1015 y(history)i(line,)i(then)e(restore)g(the)g(history)g
+(line)i(to)e(its)g(original)h(state.)0 1094 y Fk(previous-history)d
+(\(C-p\))240 1156 y Fl(Mo)o(v)o(e)h(`up')h(through)g(the)g(history)g
+(list.)0 1234 y Fk(next-history)f(\(C-n\))240 1296 y
+Fl(Mo)o(v)o(e)g(`do)o(wn')g(through)h(the)h(history)f(list.)0
+1375 y Fk(beginning-of-history)d(\(M-<\))240 1437 y Fl(Mo)o(v)o(e)i(to)
+h(the)g(\014rst)g(line)i(in)f(the)f(history)l(.)0 1515
+y Fk(end-of-history)e(\(M->\))240 1578 y Fl(Mo)o(v)o(e)h(to)h(the)g
+(end)h(of)f(the)g(input)h(history)l(,)f(i.e.,)g(the)g(line)i(y)o(ou)e
+(are)g(en)o(tering.)0 1656 y Fk(reverse-search-history)d(\(C-r\))240
+1718 y Fl(Searc)o(h)18 b(bac)o(kw)o(ard)f(starting)g(at)g(the)g(curren)
+o(t)h(line)h(and)f(mo)o(ving)f(`up')h(through)f(the)h(history)f(as)240
+1780 y(necessary)l(.)j(This)c(is)g(an)f(incremen)o(tal)h(searc)o(h.)0
+1859 y Fk(forward-search-history)c(\(C-s\))240 1921 y
+Fl(Searc)o(h)j(forw)o(ard)e(starting)h(at)g(the)g(curren)o(t)h(line)h
+(and)f(mo)o(ving)f(`do)o(wn')g(through)g(the)g(the)h(history)240
+1983 y(as)g(necessary)l(.)20 b(This)c(is)g(an)f(incremen)o(tal)h(searc)
+o(h.)0 2062 y Fk(non-incremental-reverse-se)o(arch-hi)o(story)c
+(\(M-p\))240 2124 y Fl(Searc)o(h)18 b(bac)o(kw)o(ard)f(starting)g(at)g
+(the)g(curren)o(t)h(line)h(and)f(mo)o(ving)f(`up')h(through)f(the)h
+(history)f(as)240 2186 y(necessary)e(using)h(a)f(non-incremen)o(tal)i
+(searc)o(h)e(for)g(a)f(string)i(supplied)h(b)o(y)e(the)h(user.)0
+2264 y Fk(non-incremental-forward-se)o(arch-hi)o(story)c(\(M-n\))240
+2327 y Fl(Searc)o(h)j(forw)o(ard)e(starting)h(at)g(the)g(curren)o(t)h
+(line)h(and)f(mo)o(ving)f(`do)o(wn')g(through)g(the)g(the)h(history)240
+2389 y(as)g(necessary)g(using)h(a)f(non-incremen)o(tal)i(searc)o(h)e
+(for)f(a)h(string)g(supplied)j(b)o(y)d(the)g(user.)0
+2467 y Fk(history-search-forward)d(\(\))240 2529 y Fl(Searc)o(h)h(forw)
+o(ard)f(through)h(the)g(history)g(for)g(the)g(string)g(of)g(c)o
+(haracters)f(b)q(et)o(w)o(een)i(the)f(start)f(of)h(the)240
+2592 y(curren)o(t)j(line)i(and)e(the)h(curren)o(t)f(p)q(oin)o(t.)23
+b(This)17 b(is)f(a)g(non-incremen)o(tal)i(searc)o(h.)23
+b(By)16 b(default,)h(this)240 2654 y(command)e(is)h(un)o(b)q(ound.)p
+eop
+46 47 bop 0 -58 a Fl(46)1623 b(Bash)15 b(F)l(eatures)0
+183 y Fk(history-search-backward)d(\(\))240 246 y Fl(Searc)o(h)k(bac)o
+(kw)o(ard)g(through)g(the)g(history)g(for)g(the)g(string)g(of)g(c)o
+(haracters)g(b)q(et)o(w)o(een)g(the)g(start)f(of)240
+308 y(the)i(curren)o(t)g(line)h(and)f(the)g(curren)o(t)g(p)q(oin)o(t.)
+25 b(This)17 b(is)g(a)g(non-incremen)o(tal)h(searc)o(h.)25
+b(By)17 b(default,)240 370 y(this)f(command)f(is)g(un)o(b)q(ound.)0
+450 y Fk(yank-nth-arg)f(\(M-C-y\))240 512 y Fl(Insert)19
+b(the)g(\014rst)f(argumen)o(t)g(to)g(the)h(previous)g(command)g
+(\(usually)g(the)g(second)g(w)o(ord)f(on)h(the)240 575
+y(previous)e(line\).)23 b(With)16 b(an)g(argumen)o(t)f
+Fg(n)p Fl(,)h(insert)h(the)f Fg(n)p Fl(th)g(w)o(ord)f(from)g(the)h
+(previous)h(command)240 637 y(\(the)d(w)o(ords)g(in)h(the)g(previous)g
+(command)f(b)q(egin)i(with)f(w)o(ord)f(0\).)19 b(A)14
+b(negativ)o(e)h(argumen)o(t)f(inserts)240 699 y(the)h
+Fg(n)p Fl(th)h(w)o(ord)e(from)h(the)g(end)h(of)e(the)i(previous)g
+(command.)0 779 y Fk(yank-last-arg)d(\(M-.,)i(M-_\))240
+841 y Fl(Insert)k(last)g(argumen)o(t)g(to)f(the)h(previous)h(command)f
+(\(the)g(last)g(w)o(ord)f(on)h(the)g(previous)h(line\).)240
+904 y(With)15 b(an)h(argumen)o(t,)e(b)q(eha)o(v)o(e)h(exactly)h(lik)o
+(e)g Fk(yank-nth-arg)p Fl(.)0 1158 y Ff(7.4.3)30 b(Commands)15
+b(F)-5 b(or)15 b(Changing)g(T)-5 b(ext)0 1301 y Fk(delete-char)14
+b(\(C-d\))240 1363 y Fl(Delete)f(the)f(c)o(haracter)f(under)i(the)f
+(cursor.)19 b(If)12 b(the)g(cursor)g(is)g(at)g(the)g(b)q(eginning)i(of)
+e(the)g(line,)i(there)240 1425 y(are)k(no)g(c)o(haracters)g(in)h(the)g
+(line,)h(and)f(the)f(last)g(c)o(haracter)g(t)o(yp)q(ed)h(w)o(as)e(not)h
+(C-d,)h(then)g(return)240 1487 y(EOF.)0 1567 y Fk(backward-delete-char)
+12 b(\(Rubout\))240 1630 y Fl(Delete)g(the)f(c)o(haracter)f(b)q(ehind)j
+(the)e(cursor.)18 b(A)11 b(n)o(umeric)h(arg)e(sa)o(ys)g(to)g(kill)j
+(the)e(c)o(haracters)f(instead)240 1692 y(of)15 b(deleting)h(them.)0
+1772 y Fk(quoted-insert)d(\(C-q,)i(C-v\))240 1834 y Fl(Add)i(the)f
+(next)h(c)o(haracter)f(that)f(y)o(ou)h(t)o(yp)q(e)h(to)f(the)g(line)i
+(v)o(erbatim.)24 b(This)17 b(is)g(ho)o(w)e(to)h(insert)h(k)o(ey)240
+1897 y(sequences)f(lik)o(e)h Fk(C-Q)p Fl(,)d(for)h(example.)0
+1976 y Fk(tab-insert)f(\(M-TAB\))240 2039 y Fl(Insert)h(a)g(tab)g(c)o
+(haracter.)0 2119 y Fk(self-insert)f(\(a,)g(b,)h(A,)g(1,)g(!,)g(...\))
+240 2181 y Fl(Insert)g(y)o(ourself.)0 2261 y Fk(transpose-chars)e
+(\(C-t\))240 2323 y Fl(Drag)h(the)h(c)o(haracter)g(b)q(efore)g(the)h
+(cursor)f(forw)o(ard)f(o)o(v)o(er)g(the)h(c)o(haracter)g(at)f(the)i
+(cursor,)e(mo)o(ving)240 2386 y(the)k(cursor)h(forw)o(ard)e(as)h(w)o
+(ell.)30 b(If)19 b(the)f(insertion)i(p)q(oin)o(t)f(is)g(at)e(the)i(end)
+g(of)f(the)g(line,)j(then)e(this)240 2448 y(transp)q(oses)c(the)g(last)
+g(t)o(w)o(o)f(c)o(haracters)h(of)f(the)i(line.)21 b(Negativ)o(e)15
+b(argumen)o(tss)f(don't)h(w)o(ork.)0 2528 y Fk(transpose-words)e
+(\(M-t\))240 2590 y Fl(Drag)f(the)h(w)o(ord)f(b)q(ehind)i(the)f(cursor)
+g(past)f(the)h(w)o(ord)f(in)h(fron)o(t)f(of)h(the)f(cursor)h(mo)o(ving)
+f(the)h(cursor)240 2652 y(o)o(v)o(er)h(that)h(w)o(ord)f(as)h(w)o(ell.)p
+eop
+47 48 bop 0 -58 a Fl(Chapter)15 b(7:)k(Command)c(Line)i(Editing)1205
+b(47)0 183 y Fk(upcase-word)14 b(\(M-u\))240 246 y Fl(Upp)q(ercase)h
+(the)e(curren)o(t)h(\(or)f(follo)o(wing\))h(w)o(ord.)k(With)c(a)f
+(negativ)o(e)h(argumen)o(t,)f(do)g(the)h(previous)240
+308 y(w)o(ord,)g(but)h(do)h(not)e(mo)o(v)o(e)h(the)g(cursor.)0
+383 y Fk(downcase-word)e(\(M-l\))240 445 y Fl(Lo)o(w)o(ercase)g(the)i
+(curren)o(t)f(\(or)f(follo)o(wing\))h(w)o(ord.)19 b(With)14
+b(a)g(negativ)o(e)g(argumen)o(t,)f(do)h(the)g(previous)240
+507 y(w)o(ord,)g(but)h(do)h(not)e(mo)o(v)o(e)h(the)g(cursor.)0
+582 y Fk(capitalize-word)e(\(M-c\))240 644 y Fl(Capitalize)j(the)e
+(curren)o(t)g(\(or)f(follo)o(wing\))i(w)o(ord.)j(With)d(a)f(negativ)o
+(e)g(argumen)o(t,)f(do)h(the)g(previous)240 707 y(w)o(ord,)g(but)h(do)h
+(not)e(mo)o(v)o(e)h(the)g(cursor.)0 916 y Ff(7.4.4)30
+b(Killing)15 b(And)h(Y)-5 b(anking)0 1053 y Fk(kill-line)14
+b(\(C-k\))240 1115 y Fl(Kill)j(the)f(text)e(from)h(the)g(curren)o(t)g
+(cursor)g(p)q(osition)h(to)f(the)g(end)h(of)f(the)g(line.)0
+1190 y Fk(backward-kill-line)e(\(C-x)h(Rubout\))240 1252
+y Fl(Kill)j(bac)o(kw)o(ard)e(to)f(the)i(b)q(eginning)h(of)e(the)g
+(line.)0 1327 y Fk(unix-line-discard)e(\(C-u\))240 1390
+y Fl(Kill)j(bac)o(kw)o(ard)d(from)f(the)i(cursor)f(to)g(the)h(b)q
+(eginning)i(of)d(the)g(curren)o(t)h(line.)21 b(Sa)o(v)o(e)13
+b(the)h(killed)h(text)240 1452 y(on)g(the)g(kill-ring.)0
+1527 y Fk(kill-whole-line)e(\(\))240 1589 y Fl(Kill)18
+b(all)f(c)o(haracters)e(on)h(the)g(curren)o(t)f(line,)j(no)e(matter)e
+(where)i(the)g(cursor)g(is.)22 b(By)16 b(default,)h(this)240
+1651 y(is)f(un)o(b)q(ound.)0 1726 y Fk(kill-word)e(\(M-d\))240
+1789 y Fl(Kill)j(from)d(the)h(cursor)g(to)f(the)h(end)g(of)g(the)g
+(curren)o(t)f(w)o(ord,)g(or)g(if)i(b)q(et)o(w)o(een)f(w)o(ords,)f(to)g
+(the)h(end)g(of)240 1851 y(the)g(next)h(w)o(ord.)j(W)l(ord)c(b)q
+(oundaries)h(are)f(the)g(same)g(as)g Fk(forward-word)p
+Fl(.)0 1926 y Fk(backward-kill-word)e(\(M-DEL\))240 1988
+y Fl(Kill)k(the)f(w)o(ord)e(b)q(ehind)j(the)f(cursor.)j(W)l(ord)c(b)q
+(oundaries)i(are)d(the)i(same)f(as)f Fk(backward-word)p
+Fl(.)0 2063 y Fk(unix-word-rubout)f(\(C-w\))240 2125
+y Fl(Kill)i(the)e(w)o(ord)f(b)q(ehind)j(the)f(cursor,)e(using)i(white)f
+(space)h(as)e(a)h(w)o(ord)f(b)q(oundary)l(.)20 b(The)13
+b(killed)i(text)240 2187 y(is)h(sa)o(v)o(ed)e(on)i(the)f(kill-ring.)0
+2262 y Fk(delete-horizontal-space)d(\(\))240 2325 y Fl(Delete)k(all)g
+(spaces)f(and)h(tabs)e(around)i(p)q(oin)o(t.)k(By)15
+b(default,)h(this)f(is)h(un)o(b)q(ound.)0 2399 y Fk(yank)f(\(C-y\))240
+2462 y Fl(Y)l(ank)g(the)h(top)f(of)f(the)i(kill)h(ring)e(in)o(to)g(the)
+h(bu\013er)f(at)f(the)i(curren)o(t)f(cursor)g(p)q(osition.)0
+2537 y Fk(yank-pop)f(\(M-y\))240 2599 y Fl(Rotate)f(the)h(kill-ring,)i
+(and)e(y)o(ank)g(the)g(new)g(top.)19 b(Y)l(ou)14 b(can)g(only)g(do)g
+(this)g(if)g(the)g(prior)g(command)240 2661 y(is)i(y)o(ank)f(or)f(y)o
+(ank-p)q(op.)p eop
+48 49 bop 0 -58 a Fl(48)1623 b(Bash)15 b(F)l(eatures)0
+183 y Ff(7.4.5)30 b(Sp)r(ecifying)15 b(Numeric)h(Argumen)n(ts)0
+324 y Fk(digit-argument)d(\(M-0,)i(M-1,)f(...)h(M--\))240
+386 y Fl(Add)k(this)f(digit)h(to)f(the)g(argumen)o(t)f(already)i(accum)
+o(ulating,)g(or)f(start)f(a)g(new)i(argumen)o(t.)28 b(M{)240
+448 y(starts)14 b(a)h(negativ)o(e)g(argumen)o(t.)0 527
+y Fk(universal-argument)e(\(\))240 589 y Fl(Eac)o(h)k(time)h(this)g(is)
+f(executed,)i(the)e(argumen)o(t)g(coun)o(t)g(is)h(m)o(ultiplied)i(b)o
+(y)d(four.)26 b(The)18 b(argumen)o(t)240 651 y(coun)o(t)i(is)h
+(initially)j(one,)d(so)f(executing)i(this)f(function)g(the)g(\014rst)f
+(time)h(mak)o(es)f(the)h(argumen)o(t)240 714 y(coun)o(t)15
+b(four.)20 b(By)15 b(default,)g(this)h(is)g(not)e(b)q(ound)j(to)d(a)h
+(k)o(ey)l(.)0 954 y Ff(7.4.6)30 b(Letting)14 b(Readline)h(T)n(yp)r(e)h
+(F)-5 b(or)14 b(Y)-5 b(ou)0 1095 y Fk(complete)14 b(\(TAB\))240
+1157 y Fl(A)o(ttempt)i(to)h(do)g(completion)i(on)e(the)g(text)g(b)q
+(efore)h(the)f(cursor.)26 b(This)18 b(is)g(application-sp)q(eci\014c.)
+240 1219 y(Generally)l(,)h(if)f(y)o(ou)f(are)h(t)o(yping)g(a)f
+(\014lename)i(argumen)o(t,)e(y)o(ou)g(can)h(do)f(\014lename)i
+(completion;)g(if)240 1282 y(y)o(ou)f(are)f(t)o(yping)i(a)e(command,)i
+(y)o(ou)e(can)i(do)f(command)g(completion,)h(if)g(y)o(ou)e(are)h(t)o
+(yping)g(in)h(a)240 1344 y(sym)o(b)q(ol)e(to)f(GDB,)g(y)o(ou)g(can)h
+(do)g(sym)o(b)q(ol)g(name)g(completion,)h(if)f(y)o(ou)f(are)h(t)o
+(yping)g(in)g(a)g(v)m(ariable)240 1406 y(to)e(Bash,)h(y)o(ou)f(can)h
+(do)g(v)m(ariable)h(name)f(completion,)h(and)f(so)f(on.)22
+b(See)16 b(the)g(Bash)g(man)o(ual)g(page)240 1468 y(for)f(a)f(complete)
+i(list)g(of)f(a)o(v)m(ailable)i(completion)f(functions.)0
+1547 y Fk(possible-completions)c(\(M-?\))240 1609 y Fl(List)k(the)f(p)q
+(ossible)i(completions)f(of)f(the)g(text)g(b)q(efore)h(the)f(cursor.)0
+1687 y Fk(insert-completions)e(\(\))240 1750 y Fl(Insert)22
+b(all)h(completions)g(of)f(the)g(text)f(b)q(efore)h(p)q(oin)o(t)h(that)
+e(w)o(ould)h(ha)o(v)o(e)g(b)q(een)h(generated)f(b)o(y)240
+1812 y Fk(possible-completions)p Fl(.)17 b(By)e(default,)h(this)f(is)h
+(not)f(b)q(ound)h(to)f(a)g(k)o(ey)l(.)0 2052 y Ff(7.4.7)30
+b(Keyb)r(oard)15 b(Macros)0 2193 y Fk(start-kbd-macro)e(\(C-x)i(\(\))
+240 2255 y Fl(Begin)h(sa)o(ving)f(the)h(c)o(haracters)e(t)o(yp)q(ed)i
+(in)o(to)f(the)g(curren)o(t)g(k)o(eyb)q(oard)g(macro.)0
+2334 y Fk(end-kbd-macro)e(\(C-x)i(\)\))240 2396 y Fl(Stop)f(sa)o(ving)h
+(the)g(c)o(haracters)f(t)o(yp)q(ed)h(in)o(to)f(the)h(curren)o(t)f(k)o
+(eyb)q(oard)h(macro)f(and)h(sa)o(v)o(e)f(the)g(de\014ni-)240
+2458 y(tion.)0 2537 y Fk(call-last-kbd-macro)f(\(C-x)h(e\))240
+2599 y Fl(Re-execute)20 b(the)f(last)f(k)o(eyb)q(oard)g(macro)g
+(de\014ned,)i(b)o(y)f(making)f(the)h(c)o(haracters)f(in)h(the)g(macro)
+240 2661 y(app)q(ear)c(as)g(if)h(t)o(yp)q(ed)f(at)g(the)g(k)o(eyb)q
+(oard.)p eop
+49 50 bop 0 -58 a Fl(Chapter)15 b(7:)k(Command)c(Line)i(Editing)1205
+b(49)0 183 y Ff(7.4.8)30 b(Some)15 b(Miscellaneous)h(Commands)0
+320 y Fk(re-read-init-file)d(\(C-x)h(C-r\))240 382 y
+Fl(Read)i(in)g(the)f(con)o(ten)o(ts)f(of)h(y)o(our)g(init)h(\014le,)g
+(and)f(incorp)q(orate)h(an)o(y)e(bindings)j(or)e(v)m(ariable)i(assign-)
+240 445 y(men)o(ts)e(found)g(there.)0 515 y Fk(abort)f(\(C-g\))240
+578 y Fl(Ab)q(ort)f(the)h(curren)o(t)f(editing)i(command)e(and)h(ring)g
+(the)f(terminal's)h(b)q(ell)h(\(sub)s(ject)f(to)e(the)i(setting)240
+640 y(of)h Fk(bell-style)p Fl(\).)0 710 y Fk(do-uppercase-version)d
+(\(M-a,)j(M-b,)f(...\))240 773 y Fl(Run)i(the)f(command)g(that)g(is)h
+(b)q(ound)g(to)e(the)i(corresop)q(onding)g(upp)q(ercase)g(c)o
+(haracter.)0 843 y Fk(prefix-meta)e(\(ESC\))240 906 y
+Fl(Mak)o(e)g(the)g(next)h(c)o(haracter)f(that)g(y)o(ou)g(t)o(yp)q(e)h
+(b)q(e)g(meta\014ed.)20 b(This)15 b(is)g(for)f(p)q(eople)i(without)e(a)
+h(meta)240 968 y(k)o(ey)l(.)20 b(T)o(yping)c(`)p Fk(ESC)e(f)p
+Fl(')h(is)g(equiv)m(alen)o(t)i(to)e(t)o(yping)g(`)p Fk(M-f)p
+Fl('.)0 1038 y Fk(undo)g(\(C-_,)f(C-x)h(C-u\))240 1101
+y Fl(Incremen)o(tal)h(undo,)f(separately)h(remem)o(b)q(ered)g(for)e
+(eac)o(h)h(line.)0 1171 y Fk(revert-line)f(\(M-r\))240
+1234 y Fl(Undo)20 b(all)h(c)o(hanges)f(made)g(to)f(this)i(line.)35
+b(This)21 b(is)f(lik)o(e)h(t)o(yping)f(the)g Fk(undo)g
+Fl(command)g(enough)240 1296 y(times)15 b(to)g(get)g(bac)o(k)g(to)f
+(the)i(b)q(eginning.)0 1366 y Fk(tilde-expand)e(\(M-~\))240
+1429 y Fl(P)o(erform)g(tilde)j(expansion)f(on)f(the)g(curren)o(t)g(w)o
+(ord.)0 1499 y Fk(dump-functions)e(\(\))240 1562 y Fl(Prin)o(t)18
+b(all)h(of)f(the)g(functions)h(and)g(their)g(k)o(ey)f(bindings)i(to)d
+(the)i(readline)h(output)e(stream.)28 b(If)18 b(a)240
+1624 y(n)o(umeric)i(argumen)o(t)d(is)i(supplied,)j(the)d(output)f(is)h
+(formatted)f(in)h(suc)o(h)g(a)f(w)o(a)o(y)g(that)g(it)h(can)f(b)q(e)240
+1686 y(made)d(part)g(of)g(an)g Fg(inputrc)k Fl(\014le.)0
+1757 y Fk(display-shell-version)12 b(\(C-x)j(C-v\))240
+1819 y Fl(Displa)o(y)h(v)o(ersion)f(information)h(ab)q(out)f(the)g
+(curren)o(t)g(instance)h(of)f(Bash.)0 1890 y Fk(shell-expand-line)e
+(\(M-C-e\))240 1952 y Fl(Expand)f(the)h(line)g(the)f(w)o(a)o(y)g(the)g
+(shell)h(do)q(es)g(when)f(it)h(reads)f(it.)19 b(This)12
+b(p)q(erforms)g(alias)h(and)f(history)240 2014 y(expansion)k(as)f(w)o
+(ell)h(as)f(all)h(of)f(the)g(shell)i(w)o(ord)d(expansions.)0
+2085 y Fk(history-expand-line)f(\(M-^\))240 2147 y Fl(P)o(erform)h
+(history)h(expansion)h(on)g(the)f(curren)o(t)g(line.)0
+2217 y Fk(insert-last-argument)d(\(M-.,)j(M-_\))240 2280
+y Fl(A)g(synon)o(ym)g(for)g Fk(yank-last-arg)p Fl(.)0
+2350 y Fk(operate-and-get-next)d(\(C-o\))240 2413 y Fl(Accept)i(the)f
+(curren)o(t)h(line)g(for)f(execution)i(and)e(fetc)o(h)g(the)h(next)f
+(line)i(relativ)o(e)f(to)f(the)g(curren)o(t)g(line)240
+2475 y(from)h(the)i(history)f(for)f(editing.)22 b(An)o(y)15
+b(argumen)o(t)f(is)i(ignored.)0 2545 y Fk(emacs-editing-mode)d(\(C-e\))
+240 2608 y Fl(When)k(in)h Fk(vi)e Fl(editing)i(mo)q(de,)f(this)g
+(causes)g(a)g(switc)o(h)g(bac)o(k)f(to)h(emacs)f(editing)i(mo)q(de,)f
+(as)g(if)g(the)240 2670 y(command)e Fk(set)g(-o)g(emacs)f
+Fl(had)i(b)q(een)g(executed.)p eop
+50 51 bop 0 -58 a Fl(50)1623 b(Bash)15 b(F)l(eatures)0
+183 y Fj(7.5)33 b(Readline)16 b(vi)g(Mo)r(de)62 320 y
+Fl(While)d(the)f(Readline)i(library)e(do)q(es)g(not)g(ha)o(v)o(e)f(a)g
+(full)i(set)f(of)f Fk(vi)g Fl(editing)i(functions,)g(it)f(do)q(es)g
+(con)o(tain)g(enough)0 382 y(to)i(allo)o(w)h(simple)i(editing)f(of)f
+(the)g(line.)21 b(The)15 b(Readline)i Fk(vi)e Fl(mo)q(de)g(b)q(eha)o(v)
+o(es)h(as)e(sp)q(eci\014ed)j(in)f(the)f(P)o(osix)g(1003.2)0
+445 y(standard.)62 582 y(In)f(order)g(to)e(switc)o(h)i(in)o(teractiv)o
+(ely)g(b)q(et)o(w)o(een)g Fk(Emacs)f Fl(and)h Fk(Vi)f
+Fl(editing)h(mo)q(des,)g(use)g(the)f Fk(set)i(-o)g(emacs)e
+Fl(and)0 644 y Fk(set)i(-o)g(vi)h Fl(commands)h(\(see)f(Section)i(4.5)e
+([The)g(Set)h(Builtin],)i(page)d(20\).)24 b(The)17 b(Readline)i
+(default)e(is)h Fk(emacs)0 706 y Fl(mo)q(de.)62 843 y(When)h(y)o(ou)f
+(en)o(ter)g(a)g(line)i(in)g Fk(vi)e Fl(mo)q(de,)h(y)o(ou)f(are)g
+(already)g(placed)i(in)f(`insertion')g(mo)q(de,)g(as)f(if)h(y)o(ou)f
+(had)0 906 y(t)o(yp)q(ed)e(an)f(`)p Fk(i)p Fl('.)20 b(Pressing)c
+Fk(ESC)f Fl(switc)o(hes)h(y)o(ou)f(in)o(to)h(`command')f(mo)q(de,)g
+(where)h(y)o(ou)f(can)h(edit)g(the)g(text)f(of)g(the)0
+968 y(line)20 b(with)e(the)g(standard)g Fk(vi)f Fl(mo)o(v)o(emen)o(t)g
+(k)o(eys,)h(mo)o(v)o(e)g(to)f(previous)i(history)f(lines)h(with)g(`)p
+Fk(k)p Fl(',)e(and)h(follo)o(wing)0 1030 y(lines)f(with)e(`)p
+Fk(j)p Fl(',)f(and)i(so)e(forth.)p eop
+51 52 bop 0 -58 a Fl(App)q(endix)17 b(A:)e(V)l(ariable)i(Index)1345
+b(51)0 183 y Fh(App)r(endix)13 b(A)41 b(V)-7 b(ariable)14
+b(Index)0 438 y Fj(A)0 504 y Fe(auto)p 82 504 12 2 v
+13 w(resume)7 b Fd(:)s(:)f(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(31)0 616 y Fj(B)0
+683 y Fe(BASH)p 82 683 V 13 w(VERSION)5 b Fd(:)s(:)h(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)18
+b Fc(24)0 741 y Fe(bell-style)t Fd(:)s(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)18
+b Fc(41)0 853 y Fj(C)0 919 y Fe(cdable)p 122 919 V 12
+w(vars)7 b Fd(:)t(:)f(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(10)0 977 y Fe(CDPATH)9
+b Fd(:)d(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(4)0
+1035 y Fe(comment-be)o(gi)o(n)7 b Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b Fc(41)0 1093
+y Fe(completion)o(-q)o(uer)o(y-)o(ite)o(ms)7 b Fd(:)s(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)20 b Fc(42)0 1152 y Fe(convert-me)o(ta)8
+b Fd(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)24 b Fc(41)0 1263 y Fj(E)0 1330 y Fe(editing-mo)o(de)8
+b Fd(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)24 b Fc(41)0 1388 y Fe(EUID)t Fd(:)5 b(:)h(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)17 b Fc(23)0 1446 y Fe(expand-til)o(de)8
+b Fd(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)24 b Fc(42)0 1558 y Fj(F)0 1624 y Fe(FIGNORE)9
+b Fd(:)s(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(23)0 1736
+y Fj(H)0 1803 y Fe(histchars)6 b Fd(:)s(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)19
+b Fc(23)0 1861 y Fe(HISTCMD)9 b Fd(:)s(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22
+b Fc(23)0 1919 y Fe(HISTCONTRO)o(L)t Fd(:)s(:)6 b(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17
+b Fc(22)0 1977 y Fe(HISTFILE)8 b Fd(:)s(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21
+b Fc(23)0 2035 y Fe(history)p 142 2035 V 11 w(control)8
+b Fd(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23
+b Fc(22)0 2093 y Fe(HISTSIZE)8 b Fd(:)s(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21
+b Fc(23)0 2151 y Fe(HOME)5 b Fd(:)g(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)18 b Fc(4)0 2209 y Fe(horizontal)o(-s)o(cro)o(ll)o(-mo)o(de)
+7 b Fd(:)s(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(41)0 2268
+y Fe(HOSTFILE)8 b Fd(:)s(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b Fc(23)0
+2326 y Fe(hostname)p 162 2326 V 11 w(completion)p 372
+2326 V 10 w(file)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b Fc(23)0
+2384 y Fe(HOSTTYPE)8 b Fd(:)s(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21
+b Fc(23)0 2496 y Fj(I)0 2562 y Fe(IFS)7 b Fd(:)e(:)h(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)19 b Fc(4)0 2620 y Fe(IGNOREEOF)6
+b Fd(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)22 b Fc(10,)13 b(24)0 2678 y Fe(INPUTRC)c
+Fd(:)s(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(23)1015 438 y
+Fj(K)1015 504 y Fe(keymap)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)24
+b Fc(42)1015 636 y Fj(M)1015 702 y Fe(MAILCHECK)7 b Fd(:)s(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)20 b Fc(23)1015 760 y Fe(MAILPATH)9 b Fd(:)s(:)d(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)22 b Fc(4)1015 818 y Fe(mark-modifi)o(ed)o(-li)o(nes)7
+b Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)24 b
+Fc(41)1015 876 y Fe(meta-flag)7 b Fd(:)s(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20
+b Fc(41)1015 1008 y Fj(N)1015 1074 y Fe(no)p 1057 1074
+V 14 w(exit)p 1151 1074 V 12 w(on)p 1203 1074 V 14 w(failed)p
+1337 1074 V 12 w(exec)8 b Fd(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23
+b Fc(24)1015 1132 y Fe(nolinks)9 b Fd(:)t(:)d(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)22
+b Fc(24)1015 1190 y Fe(notify)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+24 b Fc(31)1015 1322 y Fj(O)1015 1388 y Fe(OLDPWD)9 b
+Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(12)1015 1446
+y Fe(OPTARG)10 b Fd(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)25
+b Fc(4)1015 1504 y Fe(OPTIND)10 b Fd(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)25 b Fc(4)1015 1562 y Fe(OSTYPE)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)24 b Fc(23)1015 1620 y Fe(output-meta)s Fd(:)s(:)6
+b(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)17 b Fc(41)1015 1752 y Fj(P)1015 1818 y Fe(PATH)5
+b Fd(:)g(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(4)1015 1876 y Fe(PROMPT)p 1137 1876 V 12 w(COMMAND)9
+b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)25 b Fc(23)1015 1934 y Fe(PS1)7 b Fd(:)e(:)h(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(4)1015 1992 y Fe(PS2)7
+b Fd(:)e(:)h(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20
+b Fc(4)1015 2051 y Fe(PS3)6 b Fd(:)f(:)h(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)19 b Fc(12)1015 2109 y Fe(PS4)6 b Fd(:)f(:)h(:)g(:)g(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(12)1015 2167 y Fe(PWD)6
+b Fd(:)f(:)h(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(12)1015 2298 y Fj(R)1015 2364 y Fe(RANDOM)9 b Fd(:)d(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)24 b Fc(12)1015 2423 y Fe(REPLY)s
+Fd(:)5 b(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)16 b Fc(12)1015
+2554 y Fj(S)1015 2620 y Fe(SECONDS)9 b Fd(:)t(:)d(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)22 b Fc(12)1015 2678 y Fe(show-all-if)o(-a)o(mbi)o(guo)o(us)7
+b Fd(:)t(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(42)p
+eop
+52 53 bop 0 -58 a Fl(52)1623 b(Bash)15 b(F)l(eatures)0
+183 y Fj(T)0 250 y Fe(TMOUT)s Fd(:)t(:)6 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)16 b Fc(13)1015 183 y Fj(U)1015 250 y Fe(UID)6
+b Fd(:)f(:)h(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(23)p eop
+53 54 bop 0 -58 a Fl(App)q(endix)17 b(B:)e(Concept)h(Index)1347
+b(53)0 183 y Fh(App)r(endix)13 b(B)41 b(Concept)16 b(Index)0
+438 y Fj($)0 504 y Fe($else)s Fd(:)t(:)6 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)16 b Fc(44)0 562 y Fe($endif)8 b Fd(:)e(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)23 b Fc(44)0 621 y Fe($if)6 b Fd(:)f(:)h(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)18 b Fc(43)0 732 y Fj(.)0 799 y Fe(.)9
+b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22
+b Fc(3)0 911 y Fj(:)0 977 y Fe(:)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(3)0 1089 y Fj([)0
+1155 y Fe([)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)22 b Fc(4)0 1267 y Fj(A)0 1334 y Fe(abort)11
+b(\(C-g\))c Fd(:)t(:)f(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)g(:)20 b Fc(49)0 1392 y Fe(accept-lin)o(e)10
+b(\(Newline)o(,)g(Return\))5 b Fd(:)s(:)h(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(45)0 1450
+y Fe(alias)s Fd(:)t(:)6 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)16
+b Fc(14)0 1562 y Fj(B)0 1628 y Fe(backward-c)o(ha)o(r)10
+b(\(C-b\))c Fd(:)t(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(44)0 1686 y Fe(backward-d)o(el)o(ete)o(-c)o(har)9
+b(\(Rubout\))e Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)23 b Fc(46)0 1745 y Fe(backward-k)o(il)o(l-l)o(in)o
+(e)10 b(\(C-x)h(Rubout\))d Fd(:)e(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(47)0 1803 y Fe(backward-k)o(il)o(l-w)o
+(or)o(d)10 b(\(M-DEL\))5 b Fd(:)t(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)18 b Fc(47)0
+1861 y Fe(backward-w)o(or)o(d)10 b(\(M-b\))c Fd(:)t(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(44)0 1919 y Fe(beginning-)o(of)o(-hi)o
+(st)o(ory)9 b(\(M-<\))c Fd(:)g(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)18 b Fc(45)0
+1977 y Fe(beginning-)o(of)o(-li)o(ne)9 b(\(C-a\))g Fd(:)c(:)h(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)22 b Fc(44)0 2035 y Fe(bg)7 b Fd(:)e(:)h(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(30)0 2093 y Fe(bind)t
+Fd(:)5 b(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)17
+b Fc(17)0 2151 y Fe(break)t Fd(:)t(:)6 b(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)17 b Fc(3)0 2209 y Fe(builtin)9 b Fd(:)s(:)e(:)f(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)22 b Fc(17)0 2321 y Fj(C)0 2388 y Fe(call-last-)o(kb)o(d-m)o(ac)o
+(ro)9 b(\(C-x)j(e\))7 b Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)20 b Fc(48)0 2446
+y Fe(capitalize)o(-w)o(ord)9 b(\(M-c\))s Fd(:)t(:)d(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)16 b Fc(47)0 2504 y Fe(case)5 b Fd(:)g(:)h(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(2)0 2562 y Fe(cd)8
+b Fd(:)d(:)h(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21
+b Fc(3)0 2620 y Fe(clear-scre)o(en)9 b(\(C-l\))e Fd(:)t(:)f(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(45)0 2678 y Fe(command)9
+b Fd(:)s(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(18)1015 438
+y Fe(complete)10 b(\(TAB\))t Fd(:)t(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(48)1015 496 y
+Fe(continue)9 b Fd(:)s(:)d(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b
+Fc(3)1015 627 y Fj(D)1015 693 y Fe(declare)9 b Fd(:)t(:)d(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)22 b Fc(18)1015 751 y Fe(delete-char)9 b(\(C-d\))f
+Fd(:)t(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22
+b Fc(46)1015 809 y Fe(delete-hori)o(zo)o(nta)o(l-s)o(pa)o(ce)9
+b(\(\))c Fd(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(47)1015 867 y Fe(digit-argum)o(en)o
+(t)10 b(\(M-0,)h(M-1,)g(...)h(M--\))5 b Fd(:)g(:)h(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(48)1015 925 y Fe(dirs)5
+b Fd(:)g(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(9)1015 984 y Fe(display-she)o(ll)o(-ve)o(rsi)o(on)9
+b(\(C-x)i(C-v\))f Fd(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)24 b Fc(49)1015 1042 y Fe(do-uppercas)o(e-)o(ver)o(sio)o(n)
+10 b(\(M-a,)g(M-b,)i(...\))c Fd(:)t(:)e(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)21 b Fc(49)1015 1100 y Fe(downcase-wo)o(rd)9 b(\(M-l\))d
+Fd(:)t(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(47)1015 1158 y Fe(dump-functi)o(on)o(s)10 b(\(\))e
+Fd(:)d(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22
+b Fc(49)1015 1288 y Fj(E)1015 1355 y Fe(echo)5 b Fd(:)g(:)i(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(3)1015 1413 y
+Fe(emacs-editi)o(ng)o(-mo)o(de)9 b(\(C-e\))f Fd(:)t(:)e(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+21 b Fc(49)1015 1471 y Fe(enable)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)24 b Fc(18)1015 1529 y Fe(end-kbd-mac)o(ro)9 b(\(C-x)j(\)\))7
+b Fd(:)t(:)f(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(48)1015
+1587 y Fe(end-of-hist)o(or)o(y)10 b(\(M->\))t Fd(:)t(:)d(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(45)1015 1645 y Fe(end-of-line)9
+b(\(C-e\))f Fd(:)t(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+22 b Fc(44)1015 1703 y Fe(eval)5 b Fd(:)g(:)i(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)19 b Fc(3)1015 1762 y(ev)o(en)o(t)14
+b(designators)e Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)23 b Fc(33)1015 1820 y Fe(exec)5 b Fd(:)g(:)i(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(3)1015 1878 y
+Fe(exit)5 b Fd(:)g(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(3)1015 1936 y(expansion)t Fd(:)9 b(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17
+b Fc(33)1015 1994 y Fe(export)10 b Fd(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)25 b Fc(3)1015 2124 y Fj(F)1015 2191 y Fe(fc)7
+b Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)20
+b Fc(11)1015 2249 y Fe(fg)7 b Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)20 b Fc(30)1015 2307 y Fe(for)7 b Fd(:)e(:)h(:)g(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(1)1015 2365
+y Fe(forward-cha)o(r)10 b(\(C-f\))d Fd(:)t(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)20 b Fc(44)1015 2423 y Fe(forward-sea)o(rc)o(h-h)o
+(ist)o(or)o(y)10 b(\(C-s\))f Fd(:)d(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)25 b Fc(45)1015 2481
+y Fe(forward-wor)o(d)10 b(\(M-f\))d Fd(:)t(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)20 b Fc(44)1015 2612 y Fj(G)1015
+2678 y Fe(getopts)8 b Fd(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)23
+b Fc(3)p eop
+54 55 bop 0 -58 a Fl(54)1623 b(Bash)15 b(F)l(eatures)0
+183 y Fj(H)0 250 y Fe(hash)5 b Fd(:)g(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)18 b Fc(3)0 308 y Fe(help)t Fd(:)5 b(:)h(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)17 b Fc(19)0 366 y Fe(history)7
+b Fd(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b Fc(9)0 424
+y(history)14 b(ev)o(en)o(ts)t Fd(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(33)0
+482 y(History)m(,)c(ho)o(w)g(to)g(use)c Fd(:)e(:)f(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(31)0 540 y Fe(history-ex)o(pa)o
+(nd-)o(li)o(ne)9 b(\(M-^\))e Fd(:)t(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)19
+b Fc(49)0 598 y Fe(history-se)o(ar)o(ch-)o(ba)o(ckw)o(ard)9
+b(\(\))c Fd(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)18 b Fc(45)0 656 y Fe(history-se)o(ar)o(ch-)
+o(fo)o(rwa)o(rd)9 b(\(\))e Fd(:)e(:)h(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)19
+b Fc(45)0 790 y Fj(I)0 856 y Fe(if)8 b Fd(:)d(:)h(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b Fc(1)0 915 y Fe(insert-com)o(pl)o
+(eti)o(on)o(s)10 b(\(\))s Fd(:)5 b(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+16 b Fc(48)0 973 y Fe(insert-las)o(t-)o(arg)o(um)o(ent)9
+b(\(M-.,)i(M-)p 558 973 12 2 v 13 w(\))5 b Fd(:)h(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(49)0
+1031 y(in)o(teraction,)d(readline)t Fd(:)8 b(:)e(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)16 b Fc(37)0 1164 y Fj(J)0
+1231 y Fe(jobs)t Fd(:)5 b(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)17
+b Fc(31)0 1364 y Fj(K)0 1431 y Fe(kill)5 b Fd(:)g(:)h(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(3)0 1489 y(Kill)d(ring)7
+b Fd(:)g(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(39)0 1547
+y Fe(kill-line)9 b(\(C-k\))g Fd(:)d(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(47)0 1605 y Fe(kill-whole)o(-l)o(ine)9
+b(\(\))e Fd(:)e(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20
+b Fc(47)0 1663 y Fe(kill-word)9 b(\(M-d\))g Fd(:)d(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(47)0
+1721 y(Killing)16 b(text)7 b Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b
+Fc(39)0 1855 y Fj(L)0 1921 y Fe(let)9 b Fd(:)c(:)h(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)21 b Fc(12,)13 b(26)0 1979 y Fe(local)s Fd(:)t(:)6
+b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)16 b Fc(19)0 2038
+y Fe(logout)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)24
+b Fc(9)0 2171 y Fj(N)0 2238 y Fe(next-histo)o(ry)9 b(\(C-n\))e
+Fd(:)t(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20
+b Fc(45)0 2296 y Fe(non-increm)o(en)o(tal)o(-f)o(orw)o(ard)o(-s)o(ear)o
+(ch)o(-hi)o(st)o(ory)9 b(\(M-n\))82 2354 y Fd(:)d(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(45)0 2412 y Fe(non-increm)o(en)o(tal)o
+(-r)o(eve)o(rse)o(-s)o(ear)o(ch)o(-hi)o(st)o(ory)9 b(\(M-p\))82
+2470 y Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18
+b Fc(45)0 2604 y Fj(O)0 2670 y Fe(operate-an)o(d-)o(get)o(-n)o(ext)9
+b(\(C-o\))c Fd(:)g(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)18 b Fc(49)1015 183 y
+Fj(P)1015 250 y Fe(popd)5 b Fd(:)g(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)19 b Fc(8)1015 308 y Fe(possible-co)o(mp)o(let)o(ion)o(s)10
+b(\(M-?\))5 b Fd(:)t(:)h(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(48)1015 366 y
+Fe(prefix-meta)9 b(\(ESC\))f Fd(:)t(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)22 b Fc(49)1015 424 y Fe(previous-hi)o(st)o(ory)9
+b(\(C-p\))g Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(45)1015
+482 y Fe(pushd)t Fd(:)5 b(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)17
+b Fc(8)1015 540 y Fe(pwd)7 b Fd(:)e(:)h(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)20 b Fc(3)1015 656 y Fj(Q)1015 722 y Fe(quoted-inse)o
+(rt)9 b(\(C-q,)i(C-v\))f Fd(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)25
+b Fc(46)1015 838 y Fj(R)1015 904 y Fe(re-read-ini)o(t-)o(fil)o(e)10
+b(\(C-x)h(C-r\))c Fd(:)e(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b Fc(49)1015 962 y
+Fe(read)5 b Fd(:)g(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(3)1015 1020 y(Readline,)d(ho)o(w)d(to)g(use)5 b
+Fd(:)h(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fc(35)1015 1078 y Fe(readonly)9 b Fd(:)s(:)d(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22
+b Fc(3)1015 1136 y Fe(redraw-curr)o(en)o(t-l)o(ine)9
+b(\(\))h Fd(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b Fc(45)1015
+1195 y Fe(return)10 b Fd(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)25
+b Fc(4)1015 1253 y Fe(reverse-sea)o(rc)o(h-h)o(ist)o(or)o(y)10
+b(\(C-r\))f Fd(:)d(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)25 b Fc(45)1015 1311 y Fe(revert-line)9
+b(\(M-r\))f Fd(:)t(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+22 b Fc(49)1015 1426 y Fj(S)1015 1493 y Fe(self-insert)9
+b(\(a,)j(b,)g(A,)g(1,)g(!,)g(...\))6 b Fd(:)f(:)h(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)19 b Fc(46)1015
+1551 y Fe(set)6 b Fd(:)f(:)h(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+19 b Fc(20)1015 1609 y Fe(shell-expan)o(d-)o(lin)o(e)10
+b(\(M-C-e\))d Fd(:)s(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fc(49)1015 1667
+y Fe(shift)t Fd(:)5 b(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)17
+b Fc(4)1015 1725 y Fe(source)10 b Fd(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)25 b Fc(9)1015 1783 y Fe(start-kbd-m)o(ac)o(ro)10
+b(\(C-x)h(\(\))t Fd(:)5 b(:)h(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)17
+b Fc(48)1015 1841 y Fe(suspend)9 b Fd(:)t(:)d(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)22
+b Fc(31)1015 1957 y Fj(T)1015 2023 y Fe(tab-insert)9
+b(\(M-TAB\))e Fd(:)t(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)20
+b Fc(46)1015 2081 y Fe(test)5 b Fd(:)g(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)19 b Fc(4)1015 2139 y Fe(tilde-expan)o(d)10
+b(\(M-~\))d Fd(:)t(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)20
+b Fc(49)1015 2198 y Fe(times)t Fd(:)5 b(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)17 b Fc(4)1015 2256 y Fe(transpose-c)o(ha)o(rs)10
+b(\(C-t\))s Fd(:)t(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)16
+b Fc(46)1015 2314 y Fe(transpose-w)o(or)o(ds)10 b(\(M-t\))s
+Fd(:)t(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)16 b Fc(46)1015
+2372 y Fe(trap)5 b Fd(:)g(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)19 b Fc(4)1015 2430 y Fe(type)t Fd(:)5 b(:)h(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)18 b Fc(19)1015 2488 y Fe(typeset)9 b
+Fd(:)t(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)22 b Fc(12)1015 2604
+y Fj(U)1015 2670 y Fe(ulimit)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)24
+b Fc(19)p eop
+55 56 bop 0 -58 a Fl(App)q(endix)17 b(B:)e(Concept)h(Index)1347
+b(55)0 183 y Fe(umask)t Fd(:)t(:)6 b(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)17 b Fc(4)0 241 y Fe(unalias)9 b Fd(:)s(:)e(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22
+b Fc(14)0 299 y Fe(undo)11 b(\(C-)p 153 299 12 2 v 13
+w(,)i(C-x)e(C-u\))c Fd(:)e(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)20 b Fc(49)0 358 y Fe(universal-)o(ar)o(gum)o(en)o(t)10
+b(\(\))s Fd(:)5 b(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)16
+b Fc(48)0 416 y Fe(unix-line-)o(di)o(sca)o(rd)9 b(\(C-u\))g
+Fd(:)c(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fc(47)0 474 y Fe(unix-word-)o(ru)o
+(bou)o(t)10 b(\(C-w\))e Fd(:)e(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)23
+b Fc(47)0 532 y Fe(unset)t Fd(:)t(:)6 b(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)17 b Fc(4)0 590 y Fe(until)t Fd(:)t(:)6 b(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)17 b Fc(1)0 648 y Fe(upcase-wor)o(d)10
+b(\(M-u\))e Fd(:)t(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)
+21 b Fc(46)1015 183 y Fj(W)1015 250 y Fe(wait)5 b Fd(:)g(:)i(:)f(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fc(4)1015 308 y
+Fe(while)t Fd(:)5 b(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)17
+b Fc(1)1015 416 y Fj(Y)1015 482 y Fe(yank)12 b(\(C-y\))d
+Fd(:)t(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)22 b Fc(47)1015 540 y Fe(yank-last-a)o(rg)9
+b(\(M-.,)i(M-)p 1436 540 V 13 w(\))6 b Fd(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+19 b Fc(46)1015 598 y Fe(yank-nth-ar)o(g)10 b(\(M-C-y\))t
+Fd(:)s(:)d(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fc(46)1015
+656 y Fe(yank-pop)10 b(\(M-y\))t Fd(:)t(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fc(47)1015 715
+y(Y)m(anking)e(text)s Fd(:)6 b(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)16 b Fc(39)p
+eop
+56 57 bop 0 -58 a Fl(56)1623 b(Bash)15 b(F)l(eatures)p
+eop
+-1 58 bop 1937 -58 a Fl(i)0 183 y Fh(T)-7 b(able)15 b(of)g(Con)n(ten)n
+(ts)0 351 y Fj(1)67 b(Bourne)23 b(Shell)h(St)n(yle)g(F)-6
+b(eatures)14 b Fb(:)c(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)37 b Fj(1)149
+428 y Fl(1.1)45 b(Lo)q(oping)16 b(Constructs)d Fa(:)7
+b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)27 b Fl(1)149
+491 y(1.2)45 b(Conditional)16 b(Constructs)8 b Fa(:)f(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)22 b Fl(1)149 553 y(1.3)45 b(Shell)17
+b(F)l(unctions)6 b Fa(:)i(:)g(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)20 b Fl(2)149 615 y(1.4)45 b(Bourne)16
+b(Shell)h(Builtins)6 b Fa(:)j(:)e(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)20
+b Fl(3)149 677 y(1.5)45 b(Bourne)16 b(Shell)h(V)l(ariables)d
+Fa(:)7 b(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)27 b Fl(4)149
+740 y(1.6)45 b(Other)15 b(Bourne)h(Shell)h(F)l(eatures)5
+b Fa(:)i(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)19 b Fl(5)299 802 y(1.6.1)44 b(Ma)s(jor)13
+b(Di\013erences)j(from)f(the)g(Bourne)g(Shell)6 b Fa(:)j(:)e(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)20
+b Fl(5)0 927 y Fj(2)67 b(C-Shell)24 b(St)n(yle)g(F)-6
+b(eatures)5 b Fb(:)11 b(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)28 b Fj(7)149 1004 y Fl(2.1)45 b(Tilde)17 b(Expansion)6
+b Fa(:)h(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)20
+b Fl(7)149 1067 y(2.2)45 b(Brace)15 b(Expansion)c Fa(:)d(:)f(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)25 b Fl(7)149
+1129 y(2.3)45 b(C)15 b(Shell)i(Builtins)11 b Fa(:)e(:)e(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)25 b Fl(8)149
+1191 y(2.4)45 b(C)15 b(Shell)i(V)l(ariables)7 b Fa(:)h(:)f(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)21 b Fl(10)0 1316
+y Fj(3)67 b(Korn)22 b(Shell)j(St)n(yle)e(F)-6 b(eatures)17
+b Fb(:)10 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)39 b Fj(11)149
+1394 y Fl(3.1)45 b(Korn)15 b(Shell)i(Constructs)6 b Fa(:)h(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)21 b Fl(11)149 1456 y(3.2)45 b(Korn)15
+b(Shell)i(Builtins)6 b Fa(:)j(:)f(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)20 b Fl(11)149 1518 y(3.3)45 b(Korn)15 b(Shell)i(V)l(ariables)d
+Fa(:)8 b(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)28 b Fl(12)149
+1580 y(3.4)45 b(Aliases)7 b Fa(:)h(:)g(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)22
+b Fl(13)299 1643 y(3.4.1)44 b(Alias)16 b(Builtins)10
+b Fa(:)f(:)e(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)25 b Fl(14)0 1767
+y Fj(4)67 b(Bash)22 b(Sp)r(eci\014c)h(F)-6 b(eatures)11
+b Fb(:)g(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)34
+b Fj(15)149 1845 y Fl(4.1)45 b(In)o(v)o(oking)16 b(Bash)5
+b Fa(:)i(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)
+20 b Fl(15)149 1907 y(4.2)45 b(Bash)15 b(Startup)g(Files)c
+Fa(:)d(:)f(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)26 b
+Fl(16)149 1969 y(4.3)45 b(Is)15 b(This)h(Shell)h(In)o(teractiv)o(e?)9
+b Fa(:)f(:)g(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)24 b Fl(17)149 2032 y(4.4)45
+b(Bash)15 b(Builtin)j(Commands)13 b Fa(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)28
+b Fl(17)149 2094 y(4.5)45 b(The)15 b(Set)h(Builtin)e
+Fa(:)7 b(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)27
+b Fl(20)149 2156 y(4.6)45 b(Bash)15 b(V)l(ariables)9
+b Fa(:)g(:)e(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)24
+b Fl(22)149 2219 y(4.7)45 b(Shell)17 b(Arithmetic)e Fa(:)7
+b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)28
+b Fl(24)299 2281 y(4.7.1)44 b(Arithmetic)16 b(Ev)m(aluation)f
+Fa(:)7 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)29
+b Fl(24)299 2343 y(4.7.2)44 b(Arithmetic)16 b(Expansion)7
+b Fa(:)h(:)f(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)22 b Fl(25)299 2405 y(4.7.3)44 b(Arithmetic)16 b(Builtins)f
+Fa(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)27 b Fl(26)149 2468 y(4.8)45 b(Con)o(trolling)16
+b(the)f(Prompt)e Fa(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)28 b
+Fl(26)0 2592 y Fj(5)67 b(Job)22 b(Con)n(trol)8 b Fb(:)j(:)f(:)g(:)h(:)f
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)31 b Fj(29)149 2670 y Fl(5.1)45 b(Job)15 b(Con)o(trol)g(Basics)
+10 b Fa(:)d(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)24
+b Fl(29)p eop
+-2 59 bop 0 -58 a Fl(ii)1645 b(Bash)15 b(F)l(eatures)149
+42 y(5.2)45 b(Job)15 b(Con)o(trol)g(Builtins)h Fa(:)7
+b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)28 b Fl(30)149 104
+y(5.3)45 b(Job)15 b(Con)o(trol)g(V)l(ariables)c Fa(:)d(:)f(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)25 b Fl(31)0 228 y Fj(6)67 b(Using)22
+b(History)h(In)n(teractiv)n(ely)e Fb(:)10 b(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)41
+b Fj(33)149 306 y Fl(6.1)k(History)15 b(In)o(teraction)8
+b Fa(:)f(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)23
+b Fl(33)299 368 y(6.1.1)44 b(Ev)o(en)o(t)14 b(Designators)t
+Fa(:)7 b(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)19 b Fl(33)299 431 y(6.1.2)44 b(W)l(ord)15
+b(Designators)8 b Fa(:)e(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)23 b Fl(34)299 493
+y(6.1.3)44 b(Mo)q(di\014ers)13 b Fa(:)7 b(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)28 b Fl(34)0 617 y Fj(7)67 b(Command)22
+b(Line)i(Editing)10 b Fb(:)h(:)g(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)33
+b Fj(37)149 695 y Fl(7.1)45 b(In)o(tro)q(duction)16 b(to)f(Line)h
+(Editing)t Fa(:)9 b(:)e(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)19 b Fl(37)149 758 y(7.2)45 b(Readline)17
+b(In)o(teraction)5 b Fa(:)j(:)f(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)20
+b Fl(37)299 820 y(7.2.1)44 b(Readline)17 b(Bare)e(Essen)o(tials)d
+Fa(:)c(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)26
+b Fl(38)299 882 y(7.2.2)44 b(Readline)17 b(Mo)o(v)o(emen)o(t)d
+(Commands)e Fa(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)27 b Fl(38)299
+944 y(7.2.3)44 b(Readline)17 b(Killing)h(Commands)7 b
+Fa(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)22 b Fl(39)299
+1007 y(7.2.4)44 b(Readline)17 b(Argumen)o(ts)c Fa(:)8
+b(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)
+28 b Fl(40)149 1069 y(7.3)45 b(Readline)17 b(Init)g(File)c
+Fa(:)7 b(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)27
+b Fl(40)299 1131 y(7.3.1)44 b(Readline)17 b(Init)f(Syn)o(tax)10
+b Fa(:)d(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)25 b Fl(40)299 1193 y(7.3.2)44 b(Conditional)16
+b(Init)g(Constructs)c Fa(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+27 b Fl(43)149 1256 y(7.4)45 b(Bindable)17 b(Readline)h(Commands)8
+b Fa(:)e(:)i(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)23 b Fl(44)299 1318 y(7.4.1)44 b(Commands)14 b(F)l(or)h(Mo)o
+(ving)e Fa(:)7 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)28 b Fl(44)299 1380 y(7.4.2)44 b(Commands)14 b(F)l(or)h
+(Manipulating)i(The)e(History)8 b Fa(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)23 b Fl(45)299 1443 y(7.4.3)44
+b(Commands)14 b(F)l(or)h(Changing)h(T)l(ext)10 b Fa(:)c(:)i(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)25 b Fl(46)299 1505 y(7.4.4)44 b(Killing)18
+b(And)e(Y)l(anking)10 b Fa(:)e(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)
+h(:)f(:)g(:)g(:)g(:)h(:)f(:)25 b Fl(47)299 1567 y(7.4.5)44
+b(Sp)q(ecifying)17 b(Numeric)f(Argumen)o(ts)8 b Fa(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)
+g(:)g(:)h(:)22 b Fl(48)299 1629 y(7.4.6)44 b(Letting)15
+b(Readline)j(T)o(yp)q(e)d(F)l(or)g(Y)l(ou)5 b Fa(:)i(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)20 b Fl(48)299 1692 y(7.4.7)44 b(Keyb)q(oard)15
+b(Macros)9 b Fa(:)e(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)h(:)f(:)24 b Fl(48)299 1754 y(7.4.8)44
+b(Some)15 b(Miscellaneous)i(Commands)11 b Fa(:)d(:)f(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)27 b Fl(49)149 1816 y(7.5)45 b(Readline)17 b(vi)f(Mo)q(de)d
+Fa(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)27
+b Fl(50)0 1941 y Fj(App)r(endix)d(A)67 b(V)-6 b(ariable)24
+b(Index)15 b Fb(:)c(:)f(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)38 b Fj(51)0
+2081 y(App)r(endix)24 b(B)67 b(Concept)22 b(Index)c Fb(:)10
+b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)39 b Fj(53)p eop end
+userdict /end-hook known{end-hook}if
diff --git a/documentation/features.texi b/documentation/features.texi
new file mode 100644 (file)
index 0000000..bc1d2b3
--- /dev/null
@@ -0,0 +1,1907 @@
+\input texinfo.tex @c -*- texinfo -*-
+@c %**start of header
+@setfilename features.info
+@settitle Bash Features
+@c %**end of header
+
+@ignore
+last change: Thu Aug  4 15:21:56 EDT 1994
+@end ignore
+
+@set EDITION 1.14
+@set VERSION 1.14
+@set UPDATED 4 August 1994
+@set UPDATE-MONTH August 1994
+
+@setchapternewpage odd
+@synindex fn cp
+@set BashFeatures
+@ifinfo
+@format
+This text is a brief description of the features that are present in
+the Bash shell.
+
+This is Edition @value{EDITION}, last updated @value{UPDATED},
+of @cite{The GNU Bash Features Guide},
+for @code{Bash}, Version @value{VERSION}.
+
+Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Bash; see the file COPYING.  If not, write to the Free
+Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+@end format
+@end ifinfo
+
+@titlepage
+@sp 10
+@title Bash Features
+@subtitle Overview Documentation for Bash
+@subtitle Edition @value{EDITION}, for @code{bash} Version @value{VERSION}.
+@subtitle @value{UPDATE-MONTH}
+@author Brian Fox, Free Software Foundation
+@author Chet Ramey, Case Western Reserve University
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1991, 1993 Free Software Foundation, Inc.
+@end titlepage
+
+@ifinfo
+@node Top
+@top Bash Features
+
+Bash contains features that appear in other popular shells, and some
+features that only appear in Bash.  Some of the shells that Bash has
+borrowed concepts from are the Bourne Shell (@file{sh}), the Korn Shell
+(@file{ksh}), and the C-shell (@file{csh} and its successor,
+@file{tcsh}). The following menu breaks the features up into
+categories based upon which one of these other shells inspired the
+feature.
+
+This manual is meant as a brief introduction to features found in
+Bash.  The Bash manual page should be used as the definitive
+reference on shell behavior.
+
+@menu
+* Bourne Shell Features::      Features originally found in the
+                               Bourne shell.
+
+* Csh Features::               Features originally found in the
+                               Berkeley C-Shell.
+
+* Korn Shell Features::                Features originally found in the Korn
+                               Shell.
+
+* Bash Specific Features::     Features found only in Bash.
+
+* Job Control::                        A chapter describing what job control is
+                               and how bash allows you to use it.
+
+* Using History Interactively::        Chapter dealing with history expansion
+                               rules.
+
+* Command Line Editing::       Chapter describing the command line
+                               editing features.
+
+* Variable Index::             Quick reference helps you find the
+                               variable you want.
+
+* Concept Index::              General index for this manual.
+@end menu
+@end ifinfo
+
+@node Bourne Shell Features
+@chapter Bourne Shell Style Features
+
+Bash is an acronym for Bourne Again SHell.  The Bourne shell is
+the traditional Unix shell originally written by Stephen Bourne.
+All of the Bourne shell builtin commands are available in Bash,
+and the rules for evaluation and quoting are taken from the Posix
+1003.2 specification for the `standard' Unix shell. 
+
+This section briefly summarizes things which Bash inherits from
+the Bourne shell: shell control structures, builtins, variables,
+and other features.  It also lists the significant differences
+between Bash and the Bourne Shell.
+
+@menu
+* Looping Constructs::         Shell commands for iterative action.
+* Conditional Constructs::     Shell commands for conditional execution.
+* Shell Functions::            Grouping commands by name.
+* Bourne Shell Builtins::      Builtin commands inherited from the Bourne
+                               Shell.
+* Bourne Shell Variables::     Variables which Bash uses in the same way
+                               as the Bourne Shell.
+* Other Bourne Shell Features::        Addtional aspects of Bash which behave in
+                               the same way as the Bourne Shell.
+@end menu
+
+@node Looping Constructs
+@section Looping Constructs
+
+Note that wherever you see a @samp{;} in the description of a
+command's syntax, it may be replaced indiscriminately with
+one or more newlines.
+
+Bash supports the following looping constructs.
+
+@ftable @code
+@item until
+The syntax of the @code{until} command is:
+@example
+until @var{test-commands}; do @var{consequent-commands}; done
+@end example
+Execute @var{consequent-commands} as long as the final command in
+@var{test-commands} has an exit status which is not zero.
+
+@item while
+The syntax of the @code{while} command is:
+@example
+while @var{test-commands}; do @var{consequent-commands}; done
+@end example
+
+Execute @var{consequent-commands} as long as the final command in
+@var{test-commands} has an exit status of zero.
+
+@item for
+The syntax of the for command is:
+
+@example
+for @var{name} [in @var{words} ...]; do @var{commands}; done
+@end example
+Execute @var{commands} for each member in @var{words}, with @var{name}
+bound to the current member.  If ``@code{in @var{words}}'' is not
+present, ``@code{in "$@@"}'' is assumed.
+
+@end ftable
+
+@node Conditional Constructs
+@section Conditional Constructs
+
+@ftable @code
+@item if
+The syntax of the @code{if} command is:
+
+@example
+if @var{test-commands}; then
+  @var{consequent-commands};
+[elif @var{more-test-commands}; then
+  @var{more-consequents};]
+[else @var{alternate-consequents};]
+fi
+@end example
+
+Execute @var{consequent-commands} only if the final command in
+@var{test-commands} has an exit status of zero.
+Otherwise, each @code{elif} list is executed in turn,
+and if its exit status is zero,
+the corresponding @var{more-consequents} is executed and the   
+command completes.
+If ``@code{else @var{alternate-consequents}}'' is present, and
+the final command in the final @code{if} or @code{elif} clause
+has a non-zero exit status, then execute @var{alternate-consequents}.
+
+@item case
+The syntax of the @code{case} command is:
+
+@example
+@code{case @var{word} in [@var{pattern} [| @var{pattern}]...) @var{commands} ;;]... esac}
+@end example
+
+Selectively execute @var{commands} based upon @var{word} matching
+@var{pattern}.  The `@code{|}' is used to separate multiple patterns.
+
+Here is an example using @code{case} in a script that could be used to
+describe an interesting feature of an animal:
+
+@example
+echo -n "Enter the name of an animal: "
+read ANIMAL
+echo -n "The $ANIMAL has "
+case $ANIMAL in
+  horse | dog | cat) echo -n "four";;
+  man | kangaroo ) echo -n "two";;
+  *) echo -n "an unknown number of";;
+esac
+echo "legs."
+@end example
+
+@end ftable
+
+@node Shell Functions
+@section Shell Functions
+
+Shell functions are a way to group commands for later execution
+using a single name for the group.  They are executed just like
+a "regular" command.  Shell functions are executed in the current
+shell context; no new process is created to interpret them.
+
+Functions are declared using this syntax:
+
+@example
+[ @code{function} ] @var{name} () @{ @var{command-list}; @}
+@end example
+
+This defines a function named @var{name}.  The @var{body} of the
+function is the @var{command-list} between @{ and @}.  This list
+is executed whenever @var{name} is specified as the
+name of a command.  The exit status of a function is
+the exit status of the last command executed in the body.
+
+When a function is executed, the arguments to the
+function become the positional parameters
+during its execution.  The special parameter
+@code{#} that gives the number of positional parameters
+is updated to reflect the change.  Positional parameter 0
+is unchanged.
+
+If the builtin command @code{return}
+is executed in a function, the function completes and
+execution resumes with the next command after the function
+call.  When a function completes, the values of the
+positional parameters and the special parameter @code{#}
+are restored to the values they had prior to function
+execution.
+
+@node Bourne Shell Builtins
+@section Bourne Shell Builtins
+
+The following shell builtin commands are inherited from the Bourne
+shell.  These commands are implemented as specified by the Posix
+1003.2 standard.
+
+@ftable @code
+@item :
+Do nothing beyond expanding any arguments and performing redirections.
+@item .
+Read and execute commands from the @var{filename} argument in the
+current shell context.
+@item break
+Exit from a @code{for}, @code{while}, or @code{until} loop.
+@item cd
+Change the current working directory.
+@item continue
+Resume the next iteration of an enclosing @code{for}, @code{while},
+or @code{until} loop.
+@item echo
+Print the arguments, separated by spaces, to the standard output.
+@item eval
+The arguments are concatenated together into a single
+command, which is then read and executed.
+@item exec
+If a @var{command} argument
+is supplied, it replaces the shell.  If no
+@var{command} is specified, redirections may be used to affect
+the current shell environment.
+@item exit
+Exit the shell.
+@item export
+Mark the arguments as variables to be passed to child processes
+in the environment.
+@item getopts
+Parse options to shell scripts or functions.
+@item hash
+Remember the full pathnames of commands specified as arguments,
+so they need not be searched for on subsequent invocations.
+@item kill
+Send a signal to a process.
+@item pwd
+Print the current working directory.
+@item read
+Read a line from the shell input and use it to set the values of
+specified variables.
+@item readonly
+Mark variables as unchangable.
+@item return
+Cause a shell function to exit with a specified value.
+@item shift
+Shift positional parameters to the left.
+@item test
+@itemx [
+Evaluate a conditional expression.
+@item times
+Print out the user and system times used by the shell and its children.
+@item trap
+Specify commands to be executed when the shell receives signals.
+@item umask
+Set the shell process's file creation mask.
+@item unset
+Cause shell variables to disappear.
+@item wait
+Wait until child processes exit and report their exit status.
+@end ftable
+
+@node Bourne Shell Variables
+@section Bourne Shell Variables
+
+Bash uses certain shell variables in the same way as the Bourne shell.
+In some cases, Bash assigns a default value to the variable.
+
+@vtable @code
+
+@item IFS
+A list of characters that separate fields; used when the shell splits
+words as part of expansion.
+
+@item PATH
+A colon-separated list of directories in which the shell looks for
+commands.
+
+@item HOME
+The current user's home directory.
+
+@item CDPATH
+A colon-separated list of directories used as a search path for
+the @code{cd} command.
+
+@item MAILPATH
+A colon-separated list of files which the shell periodically checks
+for new mail.    You can
+also specify what message is printed by separating the file name from
+the message with a @samp{?}.  When used in the text of the message,
+@code{$_} stands for the name of the current mailfile.
+
+@item PS1
+The primary prompt string.
+
+@item PS2
+The secondary prompt string.
+
+@item OPTIND
+The index of the last option processed by the
+@code{getopts} builtin.
+
+@item OPTARG
+The value of the last option argument processed by the
+@code{getopts} builtin.
+
+@end vtable
+
+@node Other Bourne Shell Features
+@section Other Bourne Shell Features
+
+@menu
+* Major Differences from the Bourne Shell::    Major differences between
+                                               Bash and the Bourne shell.
+@end menu
+
+Bash implements essentially the same grammar, parameter and variable
+expansion, redirection, and quoting as the Bourne Shell.  Bash uses the
+Posix 1003.2 standard as the specification of how these features are to be
+implemented.  There are some differences between the traditional Bourne
+shell and the Posix standard; this section quickly details the differences
+of significance.  A number of these differences are explained in greater
+depth in subsequent sections. 
+
+@node Major Differences from the Bourne Shell
+@subsection Major Differences from the Bourne Shell
+
+Bash implements the @code{!} keyword to negate the return value of
+a pipeline.  Very useful when an @code{if} statement needs to act
+only if a test fails.
+
+Bash includes brace expansion (@pxref{Brace Expansion}).
+
+Bash includes the Posix and @code{ksh}-style pattern removal @code{%%} and
+@code{##} constructs to remove leading or trailing substrings from
+variables.
+
+The Posix and @code{ksh}-style @code{$()} form of command substitution is
+implemented, and preferred to the Bourne shell's @code{``} (which
+is also implemented for backwards compatibility).
+
+Variables present in the shell's initial environment are automatically
+exported to child processes.  The Bourne shell does not normally do
+this unless the variables are explicitly marked using the @code{export}
+command.
+
+The expansion @code{$@{#xx@}}, which returns the length of @code{$xx},
+is supported.
+
+The @code{IFS} variable is used to split only the results of expansion,
+not all words.  This closes a longstanding shell security hole.
+
+It is possible to have a variable and a function with the same name;
+@code{sh} does not separate the two name spaces.
+
+Bash functions are permitted to have local variables, and thus useful
+recursive functions may be written.
+
+The @code{noclobber} option is available to avoid overwriting existing
+files with output redirection.
+
+Bash allows you to write a function to override a builtin, and provides
+access to that builtin's functionality within the function via the
+@code{builtin} and @code{command} builtins.
+
+The @code{command} builtin allows selective disabling of functions
+when command lookup is performed.
+
+Individual builtins may be enabled or disabled using the @code{enable}
+builtin.
+
+Functions may be exported to children via the environment.
+
+The Bash @code{read} builtin will read a line ending in @key{\} with
+the @code{-r} option, and will use the @code{$REPLY} variable as a
+default if no arguments are supplied.
+
+The @code{return} builtin may be used to abort execution of scripts
+executed with the @code{.} or @code{source} builtins.
+
+The @code{umask} builtin allows symbolic mode arguments similar to
+those accepted by @code{chmod}.
+
+The @code{test} builtin is slightly different, as it implements the
+Posix 1003.2 algorithm, which specifies the behavior based on the
+number of arguments.
+
+@node Csh Features
+@chapter C-Shell Style Features
+
+The C-Shell (@dfn{@code{csh}}) was created by Bill Joy at UC Berkeley.  It
+is generally considered to have better features for interactive use than
+the original Bourne shell.  Some of the @code{csh} features present in
+Bash include job control, history expansion, `protected' redirection, and
+several variables for controlling the interactive behaviour of the shell
+(e.g. @code{IGNOREEOF}).
+
+@xref{Using History Interactively} for details on history expansion.
+
+@menu
+* Tilde Expansion::            Expansion of the ~ character.
+* Brace Expansion::            Expansion of expressions within braces.
+* C Shell Builtins::           Builtin commands adopted from the C Shell.
+* C Shell Variables::          Variables which Bash uses in essentially
+                               the same way as the C Shell.
+@end menu
+
+@node Tilde Expansion
+@section Tilde Expansion
+
+Bash has tilde (~) expansion, similar, but not identical, to that of
+@code{csh}.  The following table shows what unquoted words beginning
+with a tilde expand to.
+
+@table @code
+@item ~
+The current value of @code{$HOME}.
+@item ~/foo
+@file{$HOME/foo}
+
+@item ~fred/foo
+The subdirectory @code{foo} of the home directory of the user
+@code{fred}.
+
+@item ~+/foo
+@file{$PWD/foo}
+
+@item ~-
+@file{$OLDPWD/foo}
+@end table
+
+Bash will also tilde expand words following redirection operators
+and words following @samp{=} in assignment statements.
+
+@node Brace Expansion
+@section Brace Expansion
+
+Brace expansion
+is a mechanism by which arbitrary strings
+may be generated.  This mechanism is similar to
+@var{pathname expansion} (see the Bash manual
+page for details), but the file names generated
+need not exist.  Patterns to be brace expanded take
+the form of an optional @var{preamble},
+followed by a series of comma-separated strings
+between a pair of braces, followed by an optional @var{postamble}.
+The preamble is prepended to each string contained
+within the braces, and the postamble is then appended
+to each resulting string, expanding left to right.
+
+Brace expansions may be nested.  The results of each expanded
+string are not sorted; left to right order is preserved.
+For example,
+@example
+a@{d,c,b@}e
+@end example
+expands into
+@var{ade ace abe}.
+
+Brace expansion is performed before any other expansions,
+and any characters special to other expansions are preserved
+in the result.  It is strictly textual.  Bash
+does not apply any syntactic interpretation to the context of the
+expansion or the text between the braces.
+
+A correctly-formed brace expansion must contain unquoted opening
+and closing braces, and at least one unquoted comma.
+Any incorrectly formed brace expansion is left unchanged.
+
+This construct is typically used as shorthand when the common
+prefix of the strings to be generated is longer than in the
+above example:
+@example
+mkdir /usr/local/src/bash/@{old,new,dist,bugs@}
+@end example
+or
+@example
+chown root /usr/@{ucb/@{ex,edit@},lib/@{ex?.?*,how_ex@}@}
+@end example
+
+@node C Shell Builtins
+@section C Shell Builtins
+
+Bash has several builtin commands whose definition is very similar
+to @code{csh}.
+
+@ftable @code
+@item pushd
+@example
+pushd [@var{dir} | @var{+n} | @var{-n}]
+@end example
+
+Save the current directory on a list and then @code{cd} to
+@var{dir}.  With no
+arguments, exchanges the top two directories.
+
+@table @code
+@item +@var{n}
+Brings the @var{n}th directory (counting from the left of the
+list printed by @code{dirs}) to the top of the list by rotating
+the stack.
+@item -@var{n}
+Brings the @var{n}th directory (counting from the right of the
+list printed by @code{dirs}) to the top of the list by rotating
+the stack.
+@item @var{dir}
+Makes the current working directory be the top of the stack, and then
+@var{cd}s to @var{dir}.  You can see the saved directory list
+with the @code{dirs} command.
+@end table
+
+@item popd
+@example
+popd [+@var{n} | -@var{n}]
+@end example
+
+Pops the directory stack, and @code{cd}s to the new top directory.  When
+no arguments are given, removes the top directory from the stack and
+@code{cd}s to the new top directory.  The
+elements are numbered from 0 starting at the first directory listed with
+@code{dirs}; i.e. @code{popd} is equivalent to @code{popd +0}.
+@table @code
+@item +@var{n}
+Removes the @var{n}th directory (counting from the left of the
+list printed by @code{dirs}), starting with zero.
+@item -@var{n}
+Removes the @var{n}th directory (counting from the right of the
+list printed by @code{dirs}), starting with zero.
+@end table
+
+@item dirs
+@example
+dirs [+@var{n} | -@var{n}] [-@var{l}]
+@end example
+Display the list of currently remembered directories.  Directories
+find their way onto the list with the @code{pushd} command; you can get
+back up through the list with the @code{popd} command.
+@table @code
+@item +@var{n}
+Displays the @var{n}th directory (counting from the left of the
+list printed by @code{dirs} when invoked without options), starting
+with zero.
+@item -@var{n}
+Displays the @var{n}th directory (counting from the right of the
+list printed by @code{dirs} when invoked without options), starting
+with zero.
+@item -@var{l}
+Produces a longer listing; the default listing format uses a 
+tilde to denote the home directory.
+@end table
+
+
+@item history
+@example
+history [@var{n}] [ [-w -r -a -n] [@var{filename}]]
+@end example
+
+Display the history list with line numbers.  Lines prefixed with
+with a @code{*} have been modified.  An argument of @var{n} says
+to list only the last @var{n} lines.  Option @code{-w} means
+write out the current history to the history file; @code{-r}
+means to read the current history file and make its contents the
+history list.  An argument of @code{-a} means to append the new
+history lines (history lines entered since the beginning of the
+current Bash session) to the history file.  Finally, the
+@code{-n} argument means to read the history lines not already
+read from the history file into the current history list.  These
+are lines appended to the history file since the beginning of the
+current Bash session.  If @var{filename} is given, then it is used
+as the history file, else if @code{$HISTFILE} has a value,
+that is used, otherwise @file{~/.bash_history} is used.
+
+@item logout
+Exit a login shell.
+
+@item source
+A synonym for @code{.} (@pxref{Bourne Shell Builtins})
+
+@end ftable
+
+@node C Shell Variables
+@section C Shell Variables
+
+@vtable @code
+
+@item IGNOREEOF
+If this variable is set, it represents the number of consecutive
+@code{EOF}s Bash will read before exiting.  By default, Bash will exit
+upon reading a single @code{EOF}.
+
+@item cdable_vars
+If this variable is set, Bash treats arguments to the @code{cd} command
+which are not directories as names of variables whose values are the
+directories to change to.
+@end vtable
+
+@node Korn Shell Features
+@chapter Korn Shell Style Features
+
+This section describes features primarily inspired by the
+Korn Shell (@code{ksh}).  In some cases, the Posix 1003.2
+standard has adopted these commands and variables from the
+Korn Shell; Bash implements those features using the Posix
+standard as a guide.
+
+@menu
+* Korn Shell Constructs::      Shell grammar constructs adopted from the
+                               Korn Shell
+* Korn Shell Builtins::                Builtin commands adopted from the Korn Shell.
+* Korn Shell Variables::       Variables which bash uses in essentially
+                               the same way as the Korn Shell.
+* Aliases::                    Substituting one command for another.
+@end menu
+
+@node Korn Shell Constructs
+@section Korn Shell Constructs
+
+Bash includes the Korn Shell @code{select} construct.  This construct
+allows the easy generation of menus.  It has almost the same syntax as
+the @code{for} command.
+
+The syntax of the @code{select} command is:
+@example
+select @var{name} [in @var{words} ...]; do @var{commands}; done
+@end example
+
+The list of words following @code{in} is expanded, generating a list
+of items.  The set of expanded words is printed on the standard
+error, each preceded by a number.  If the ``@code{in @var{words}}''
+is omitted, the positional parameters are printed.  The
+@code{PS3} prompt is then displayed and a line is read from the standard
+input. If the line consists of the number corresponding to one of
+the displayed words, then the value of @var{name}
+is set to that word.  If the line is empty, the words and prompt
+are displayed again.  If @code{EOF} is read, the @code{select}
+command completes.  Any other value read causes @var{name}
+to be set to null.  The line read is saved in the variable
+@code{REPLY}.
+
+The @var{commands} are executed after each selection until a
+@code{break} or @code{return} command is executed, at which
+point the @code{select} command completes.
+
+@node Korn Shell Builtins
+@section Korn Shell Builtins
+
+This section describes Bash builtin commands taken from @code{ksh}.
+
+@ftable @code
+@item fc
+
+@example
+@code{fc [-e @var{ename}] [-nlr] [@var{first}] [@var{last}]}
+@code{fc -s [@var{pat=rep}] [@var{command}]}
+@end example
+
+Fix Command.  In the first form, a range of commands from @var{first} to
+@var{last} is selected from the history list.  Both @var{first} and
+@var{last} may be specified as a string (to locate the most recent
+command beginning with that string) or as a number (an index into the
+history list, where a negative number is used as an offset from the
+current command number).  If @var{last} is not specified it is set to
+@var{first}.  If @var{first} is not specified it is set to the previous
+command for editing and -16 for listing.  If the @code{-l} flag is
+given, the commands are listed on standard output.  The @code{-n} flag
+suppresses the command numbers when listing.  The @code{-r} flag
+reverses the order of the listing.  Otherwise, the editor given by
+@var{ename} is invoked on a file containing those commands.  If
+@var{ename} is not given, the value of the following variable expansion
+is used: @code{$@{FCEDIT:-$@{EDITOR:-vi@}@}}.  This says to use the
+value of the @code{FCEDIT} variable if set, or the value of the
+@code{EDITOR} variable if that is set, or @code{vi} if neither is set.
+When editing is complete, the edited commands are echoed and executed.
+
+In the second form, @var{command} is re-executed after each instance
+of @var{pat} in the selected command is replaced by @var{rep}.
+
+A useful alias to use with the @code{fc} command is @code{r='fc -s'}, so
+that typing @code{r cc} runs the last command beginning with @code{cc}
+and typing @code{r} re-executes the last command (@pxref{Aliases}).
+
+@item let
+The @code{let} builtin allows arithmetic to be performed on shell variables.
+For details, refer to @ref{Arithmetic Builtins}.
+
+@item typeset
+The @code{typeset} command is supplied for compatibility with the Korn
+shell; however, it has been made obsolete by the
+@code{declare} command (@pxref{Bash Builtins}).
+
+@end ftable
+
+@node Korn Shell Variables
+@section Korn Shell Variables
+
+@vtable @code
+
+@item REPLY
+The default variable for the @code{read} builtin.
+
+@item RANDOM
+Each time this parameter is referenced, a random integer
+is generated.  Assigning a value to this variable seeds
+the random number generator.
+
+@item SECONDS
+This variable expands to the number of seconds since the
+shell was started.  Assignment to this variable resets
+the count to the value assigned, and the expanded value
+becomes the value assigned plus the number of seconds
+since the assignment.
+
+@item PS3
+The value of this variable is used as the prompt for the
+@code{select} command.
+
+@item PS4
+This is the prompt printed before the command line is echoed
+when the @code{-x} option is set (@pxref{The Set Builtin}).
+
+@item PWD
+The current working directory as set by the @code{cd} builtin.
+
+@item OLDPWD
+The previous working directory as set by the @code{cd} builtin.
+
+@item 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.
+Bash terminates after that number of seconds if input does
+not arrive.
+
+@end vtable
+
+@node Aliases
+@section Aliases
+
+@menu
+* Alias Builtins::             Builtins commands to maniuplate aliases.
+@end menu
+
+The shell maintains a list of @var{aliases}
+that may be set and unset with the @code{alias} and
+@code{unalias} builtin commands.
+
+The first word of each command, if unquoted,
+is checked to see if it has an
+alias.  If so, that word is replaced by the text of the alias.
+The alias name and the replacement text may contain any valid
+shell input, including shell metacharacters, with the exception
+that the alias name may not contain @key{=}.
+The first word of the replacement text is tested for
+aliases, but a word that is identical to an alias being expanded
+is not expanded a second time.  This means that one may alias
+@code{ls} to @code{"ls -F"},
+for instance, and Bash does not try to recursively expand the
+replacement text. If the last character of the alias value is a
+space or tab character, then the next command word following the
+alias is also checked for alias expansion.
+
+Aliases are created and listed with the @code{alias}
+command, and removed with the @code{unalias} command.
+
+There is no mechanism for using arguments in the replacement text,
+as in @code{csh}.
+If arguments are needed, a shell function should be used.
+
+Aliases are not expanded when the shell is not interactive.
+
+The rules concerning the definition and use of aliases are
+somewhat confusing.  Bash
+always reads at least one complete line
+of input before executing any
+of the commands on that line.  Aliases are expanded when a
+command is read, not when it is executed.  Therefore, an
+alias definition appearing on the same line as another
+command does not take effect until the next line of input is read.
+This means that the commands following the alias definition
+on that line are not affected by the new alias.
+This behavior is also an issue when functions are executed.
+Aliases are expanded when the function definition is read,
+not when the function is executed, because a function definition
+is itself a compound command.  As a consequence, aliases
+defined in a function are not available until after that
+function is executed.  To be safe, always put
+alias definitions on a separate line, and do not use @code{alias}
+in compound commands.
+
+Note that for almost every purpose, aliases are superseded by
+shell functions.
+
+@node Alias Builtins
+@subsection Alias Builtins
+
+@ftable @code
+@item alias
+@example
+alias [@var{name}[=@var{value}] ...]
+@end example
+
+Without arguments, print the list of aliases on the standard output.
+If arguments are supplied, an alias is defined for each @var{name}
+whose @var{value} is given.  If no @var{value} is given, the name
+and value of the alias is printed.
+
+@item unalias
+@example
+unalias [-a] [@var{name} ... ]
+@end example
+
+Remove each @var{name} from the list of aliases.  If @code{-a} is
+supplied, all aliases are removed.
+@end ftable
+
+@node Bash Specific Features
+@chapter Bash Specific Features
+
+This section describes the features unique to Bash.
+
+@menu
+* Invoking Bash::              Command line options that you can give
+                               to Bash.
+* Bash Startup Files::         When and how Bash executes scripts.
+* Is This Shell Interactive?:: Determining the state of a running Bash.
+* Bash Builtins::              Table of builtins specific to Bash.
+* The Set Builtin::            This builtin is so overloaded it
+                               deserves its own section.
+* Bash Variables::             List of variables that exist in Bash.
+* Shell Arithmetic::           Arithmetic on shell variables.
+* Printing a Prompt::          Controlling the PS1 string.
+@end menu
+
+@node Invoking Bash
+@section Invoking Bash
+
+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 to be recognized. 
+
+@table @code
+@item -norc
+Don't read the @file{~/.bashrc} initialization file in an
+interactive shell.  This is on by default if the shell is
+invoked as @code{sh}.
+
+@item -rcfile @var{filename}
+Execute commands from @var{filename} (instead of @file{~/.bashrc})
+in an interactive shell.
+
+@item -noprofile
+Don't load the system-wide startup file @file{/etc/profile}
+or any of the personal initialization files
+@file{~/.bash_profile}, @file{~/.bash_login}, or @file{~/.profile}
+when bash is invoked as a login shell.
+
+@item -version
+Display the version number of this shell.
+
+@item -login
+Make this shell act as if it were directly invoked from login.
+This is equivalent to @samp{exec - bash} but can be issued from
+another shell, such as @code{csh}.  If you wanted to replace your
+current login shell with a Bash login shell, you would say
+@samp{exec bash -login}.
+
+@item -nobraceexpansion
+Do not perform curly brace expansion (@pxref{Brace Expansion}).
+
+@item -nolineediting
+Do not use the GNU Readline library (@pxref{Command Line Editing})
+to read interactive command lines.
+
+@item -posix
+Change the behavior of Bash where the default operation differs
+from the Posix 1003.2 standard to match the standard.  This
+is intended to make Bash behave as a strict superset of that
+standard.
+
+@end table
+
+There are several single-character options you can give which are
+not available with the @code{set} builtin.
+
+@table @code
+@item -c @var{string}
+Read and execute commands from @var{string} after processing the
+options, then exit.
+
+@item -i
+Force the shell to run interactively.
+
+@item -s
+If this flag is present, or if no arguments remain after option
+processing, then commands are read from the standard input.
+This option allows the positional parameters to be set
+when invoking an interactive shell.
+
+@end table
+
+An @emph{interactive} shell is one whose input and output are both
+connected to terminals (as determined by @code{isatty()}), or one
+started with the @code{-i} option.
+
+@node Bash Startup Files
+@section Bash Startup Files
+
+When and how Bash executes startup files.
+
+@example
+For Login shells (subject to the -noprofile option):
+
+    On logging in:
+       If @file{/etc/profile} exists, then source it.
+
+       If @file{~/.bash_profile} exists, then source it,
+          else if @file{~/.bash_login} exists, then source it,
+             else if @file{~/.profile} exists, then source it.
+
+    On logging out:
+       If @file{~/.bash_logout} exists, source it.
+
+For non-login interactive shells (subject to the -norc and -rcfile options):
+    On starting up:
+       If @file{~/.bashrc} exists, then source it.
+
+For non-interactive shells:
+    On starting up:
+       If the environment variable @code{ENV} is non-null, expand the
+       variable and source the file named by the value.  If Bash is
+       not started in Posix mode, it looks for @code{BASH_ENV} before
+       @code{ENV}.
+@end example
+
+So, typically, your @code{~/.bash_profile} contains the line
+@example
+@code{if [ -f @code{~/.bashrc} ]; then source @code{~/.bashrc}; fi}
+@end example
+@noindent
+after (or before) any login specific initializations.
+
+If Bash is invoked as @code{sh}, it tries to mimic the behavior of
+@code{sh} as closely as possible.  For a login shell, it attempts to
+source only @file{/etc/profile} and @file{~/.profile}, in that order.
+The @code{-noprofile} option may still be used to disable this behavior.
+A shell invoked as @code{sh} does not attempt to source any other
+startup files.
+
+When Bash is started in @var{POSIX} mode, as with the
+@code{-posix} command line option, it follows the Posix 1003.2
+standard for startup files.  In this mode, the @code{ENV}
+variable is expanded and that file sourced; no other startup files
+are read.
+
+@node Is This Shell Interactive?
+@section Is This Shell Interactive?
+
+You may wish to determine within a startup script whether Bash is
+running interactively or not.  To do this, examine the variable
+@code{$PS1}; it is unset in non-interactive shells, and set in
+interactive shells.  Thus:
+
+@example
+if [ -z "$PS1" ]; then
+       echo This shell is not interactive
+else
+       echo This shell is interactive
+fi
+@end example
+
+You can ask an interactive Bash to not run your @file{~/.bashrc} file
+with the @code{-norc} flag.  You can change the name of the
+@file{~/.bashrc} file to any other file name with @code{-rcfile
+@var{filename}}.  You can ask Bash to not run your
+@file{~/.bash_profile} file with the @code{-noprofile} flag.
+
+@node Bash Builtins
+@section Bash Builtin Commands
+
+This section describes builtin commands which are unique to
+or have been extended in Bash.
+
+@ftable @code
+@item builtin
+@example
+builtin [@var{shell-builtin} [@var{args}]]
+@end example
+Run a shell builtin.  This is useful when you wish to rename a
+shell builtin to be a function, but need the functionality of the
+builtin within the function itself.
+
+@item bind
+@example
+bind [-m @var{keymap}] [-lvd] [-q @var{name}]
+bind [-m @var{keymap}] -f @var{filename}
+bind [-m @var{keymap}] @var{keyseq:function-name}
+@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
+@file{.inputrc} (@pxref{Readline Init File}),
+but each binding must be passed as a separate argument:
+@samp{"\C-x\C-r":re-read-init-file}.
+Options, if supplied, have the following meanings:
+
+@table @code
+@item -m keymap
+Use @var{keymap} as the keymap to be affected by
+the subsequent bindings.  Acceptable @var{keymap}
+names are
+@code{emacs},
+@code{emacs-standard},
+@code{emacs-meta},
+@code{emacs-ctlx},
+@code{vi},
+@code{vi-move},
+@code{vi-command}, and
+@code{vi-insert}.
+@code{vi} is equivalent to @code{vi-command};
+@code{emacs} is equivalent to @code{emacs-standard}.
+
+@item -l
+List the names of all readline functions
+
+@item -v
+List current function names and bindings
+
+@item -d
+Dump function names and bindings in such a way that they can be re-read
+
+@item -f filename
+Read key bindings from @var{filename}
+
+@item -q
+Query about which keys invoke the named @var{function}
+@end table
+
+@item command
+@example
+command [-pVv] @var{command} [@var{args} ...]
+@end example
+Runs @var{command} with @var{arg} ignoring shell functions.  If
+you have a shell function called @code{ls}, and you wish to call
+the command @code{ls}, you can say @samp{command ls}.  The
+@code{-p} option means to use a default value for @code{$PATH}
+that is guaranteed to find all of the standard utilities.
+
+If either the @code{-V} or @code{-v} option is supplied, a
+description of @var{command} is printed.  The @code{-v} option
+causes a single word indicating the command or file name used to
+invoke @var{command} to be printed; the @code{-V} option produces
+a more verbose description. 
+
+@item declare
+@example
+declare [-frxi] [@var{name}[=@var{value}]]
+@end example
+
+Declare variables and/or give them attributes.  If no @var{name}s
+are given, then display the values of variables instead. 
+@code{-f} means to use function names only.  @code{-r} says to
+make @var{name}s readonly.  @code{-x} says to mark @var{name}s
+for export.  @code{-i} says that the variable is to be treated as
+an integer; arithmetic evaluation (@pxref{Shell Arithmetic}) is
+performed when the variable is assigned a value.  Using @code{+}
+instead of @code{-} turns off the attribute instead.  When used in
+a function, @code{declare} makes @var{name}s local, as with the
+@code{local} command. 
+
+@item enable
+@example
+enable [-n] [-a] [@var{name} ...]
+@end example
+Enable and disable builtin shell commands.  This allows you to
+use a disk command which has the same name as a shell builtin. 
+If @code{-n} is used, the @var{name}s become disabled.  Otherwise
+@var{name}s are enabled.  For example, to use the @code{test} binary
+found via @code{$PATH} instead of the shell builtin version, type
+@samp{enable -n test}.  The @code{-a} option means to list
+each builtin with an indication of whether or not it is enabled. 
+
+@item help
+@example
+help [@var{pattern}]
+@end example
+Display helpful information about builtin commands.  If
+@var{pattern} is specified, @code{help} gives detailed help
+on all commands matching @var{pattern}, otherwise a list of
+the builtins is printed.
+
+@item local
+@example
+local @var{name}[=@var{value}]
+@end example
+For each argument, create a local variable called @var{name}, and
+give it @var{value}.
+@code{local} can only be used within a function; it makes the variable
+@var{name} have a visible scope restricted to that function and its
+children.
+
+@item type
+@example
+type [-all] [-type | -path] [@var{name} ...]
+@end example
+For each @var{name}, indicate how it would be interpreted if used as a
+command name.
+
+If the @code{-type} flag is used, @code{type} returns a single word
+which is one of ``alias'', ``function'', ``builtin'', ``file'' or
+``keyword'', if @var{name} is an alias, shell function, shell builtin,
+disk file, or shell reserved word, respectively.
+
+If the @code{-path} flag is used, @code{type} either returns the name
+of the disk file that would be executed, or nothing if @code{-type}
+would not return ``file''.
+
+If the @code{-all} flag is used, returns all of the places that contain
+an executable named @var{file}.  This includes aliases and functions,
+if and only if the @code{-path} flag is not also used.
+
+@code{Type} accepts @code{-a}, @code{-t}, and @code{-p} as equivalent to
+@code{-all}, @code{-type}, and @code{-path}, respectively.
+
+@item ulimit
+@example
+ulimit [-acdmstfpnuvSH] [@var{limit}]
+@end example
+@code{Ulimit} provides control over the resources available to processes
+started by the shell, on systems that allow such control.  If an
+option is given, it is interpreted as follows:
+@table @code
+@item -S
+change and report the soft limit associated with a resource (the
+default if the @code{-H} option is not given).
+@item -H
+change and report the hard limit associated with a resource.
+@item -a
+all current limits are reported.
+
+@item -c
+the maximum size of core files created.
+
+@item -d
+the maximum size of a process's data segment.
+
+@item -m
+the maximum resident set size.
+
+@item -s
+the maximum stack size.
+
+@item -t
+the maximum amount of cpu time in seconds.
+
+@item -f
+the maximum size of files created by the shell.
+
+@item -p
+the pipe buffer size.
+
+@item -n
+the maximum number of open file descriptors.
+
+@item -u
+the maximum number of processes available to a single user.
+
+@item -v
+the maximum amount of virtual memory available to the process.
+
+@end table
+
+If @var{limit} is given, it is the new value of the specified resource.
+Otherwise, the current value of the specified resource is printed.  If
+no option is given, then @samp{-f} is assumed.  Values are in 1024-byte
+increments, except for @samp{-t}, which is in seconds, @samp{-p},
+which is in units of 512-byte blocks, and @samp{-n} and @samp{-u}, which
+are unscaled values.
+
+@end ftable
+
+@node The Set Builtin
+@section The Set Builtin
+
+This builtin is so overloaded that it deserves its own section.
+
+@ftable @code
+@item set
+@example
+set [-abefhkmnptuvxldCHP] [-o @var{option}] [@var{argument} ...]
+@end example
+
+@table @code
+@item -a
+Mark variables which are modified or created for export.
+
+@item -b
+Cause the status of terminated background jobs to be reported
+immediately, rather than before printing the next primary prompt.
+
+@item -e
+Exit immediately if a command exits with a non-zero status.
+
+@item -f
+Disable file name generation (globbing).
+
+@item -h
+Locate and remember (hash) commands as functions are defined, rather
+than when the function is executed.
+
+@item -k
+All keyword arguments are placed in the environment for a command, not
+just those that precede the command name.
+
+@item -m
+Job control is enabled (@pxref{Job Control}).
+
+@item -n
+Read commands but do not execute them.
+
+@item -o @var{option-name}
+
+Set the flag corresponding to @var{option-name}:
+
+@table @code
+@item allexport
+same as @code{-a}.
+
+@item braceexpand
+the shell will perform brace expansion (@pxref{Brace Expansion}).
+
+@item emacs
+use an emacs-style line editing interface (@pxref{Command Line Editing}).
+
+@item errexit
+same as @code{-e}.
+
+@item histexpand
+same as @code{-H}.
+
+@item ignoreeof
+the shell will not exit upon reading EOF.
+
+@item interactive-comments
+allow a word beginning with a @samp{#} to cause that word and
+all remaining characters on that line to be ignored in an
+interactive shell.
+
+@item monitor
+same as @code{-m}.
+
+@item noclobber
+same as @code{-C}.
+
+@item noexec
+same as @code{-n}.
+
+@item noglob
+same as @code{-f}.
+
+@item nohash
+same as @code{-d}.
+
+@item notify
+same as @code{-b}.
+
+@item nounset
+same as @code{-u}.
+
+@item physical
+same as @code{-P}.
+
+@item posix
+change the behavior of Bash where the default operation differs
+from the Posix 1003.2 standard to match the standard.  This
+is intended to make Bash behave as a strict superset of that
+standard.
+
+@item privileged
+same as @code{-p}.
+
+@item verbose
+same as @code{-v}.
+
+@item vi
+use a @code{vi}-style line editing interface.
+
+@item xtrace
+same as @code{-x}.
+@end table
+
+@item -p
+Turn on privileged mode.
+In this mode, the @code{$ENV}
+file is not processed, and shell functions
+are not inherited from the environment.  This is enabled automatically
+on startup if the effective user (group) id is not equal to the real
+user (group) id.  Turning this option off causes the effective user
+and group ids to be set to the real user and group ids.
+
+@item -t
+Exit after reading and executing one command.
+
+@item -u
+Treat unset variables as an error when substituting.
+
+@item -v
+Print shell input lines as they are read.
+
+@item -x
+Print commands and their arguments as they are executed.
+
+@item -l
+Save and restore the binding of the @var{name} in a @code{for} command.
+
+@item -d
+Disable the hashing of commands that are looked up for execution.
+Normally, commands are remembered in a hash table, and once found, do
+not have to be looked up again.
+
+@item -C
+Disallow output redirection to existing files.
+
+@item -H
+Enable ! style history substitution.  This flag is on by default.
+
+@item -P
+If set, do not follow symbolic links when performing commands such as
+@code{cd} which change the current directory.  The physical directory
+is used instead.
+
+@item --
+If no arguments follow this flag, then the positional parameters are
+unset.  Otherwise, the positional parameters are set to the
+@var{arguments}, even if some of them begin with a @code{-}.
+
+@item -
+Signal the end of options, cause all remaining @var{arguments}
+to be assigned to the positional parameters.  The @code{-x}
+and @code{-v}  options are turned off.
+If there are no arguments, the positional parameters remain unchanged.
+@end table
+
+Using @samp{+} rather than @samp{-} causes these flags to be
+turned off.  The flags can also be used upon invocation of the
+shell.  The current set of flags may be found in @code{$-}.  The
+remaining N @var{arguments} are positional parameters and are
+assigned, in order, to @code{$1}, @code{$2}, ..  @code{$N}.  If
+no arguments are given, all shell variables are printed. 
+@end ftable
+
+@node Bash Variables
+@section Bash Variables
+
+These variables are set or used by bash, but other shells
+do not normally treat them specially.
+
+@vtable @code
+
+@item HISTCONTROL
+@itemx history_control
+Set to a value of @samp{ignorespace}, it means don't enter lines which
+begin with a space or tab into the history list.  Set to a value
+of @samp{ignoredups}, it means don't enter lines which match the last
+entered line.  A value of @samp{ignoreboth} combines the two options.
+Unset, or set to any other value than those above, means to save
+all lines on the history list. 
+
+@item HISTFILE
+The name of the file to which the command history is saved.
+
+@item HISTSIZE
+If set, this is the maximum number of commands to remember in the
+history.
+
+@item histchars
+Up to three characters which control history expansion, quick
+substitution, and tokenization (@pxref{History Interaction}).
+The first character is the
+@dfn{history-expansion-char}, that is, the character which signifies the
+start of a history expansion, normally @samp{!}.  The second character is the
+character which signifies `quick substitution' when seen as the first
+character on a line, normally @samp{^}.  The optional third character is the
+character which signifies the remainder of the line is a comment, when
+found as the first character of a word, usually @samp{#}.  The history   
+comment character causes history substitution to be skipped for the
+remaining words on the line.  It does not necessarily cause the shell
+parser to treat the rest of the line as a comment.
+
+@item HISTCMD
+The history number, or index in the history list, of the current
+command.  If @code{HISTCMD} is unset, it loses its special properties,
+even if it is subsequently reset.
+
+@item hostname_completion_file
+@itemx HOSTFILE
+Contains the name of a file in the same format as @file{/etc/hosts} that
+should be read when the shell needs to complete a hostname.  You can
+change the file interactively; the next time you attempt to complete a
+hostname, Bash will add the contents of the new file to the already
+existing database.
+
+@item MAILCHECK
+How often (in seconds) that the shell should check for mail
+in the files specified in @code{MAILPATH}.
+
+@item PROMPT_COMMAND
+If present, this contains a string which is a command to execute
+before the printing of each primary prompt (@code{$PS1}).
+
+@item UID
+The numeric real user id of the current user.
+
+@item EUID
+The numeric effective user id of the current user.
+
+@item HOSTTYPE
+A string describing the machine Bash is running on.
+
+@item OSTYPE
+A string describing the operating system Bash is running on.
+
+@item FIGNORE
+A colon-separated list of suffixes to ignore when performing
+filename completion
+A file name whose suffix matches one of the entries in 
+@code{FIGNORE}
+is excluded from the list of matched file names.  A sample
+value is @samp{.o:~}
+
+@item INPUTRC
+The name of the Readline startup file, overriding the default
+of @file{~/.inputrc}.
+
+@item BASH_VERSION
+The version number of the current instance of Bash.
+
+@item IGNOREEOF
+Controls the action of the shell on receipt of an @code{EOF} character
+as the sole input.  If set, then the value of it is the number
+of consecutive @code{EOF} characters that can be read as the
+first characters on an input line
+before the shell will exit.  If the variable exists but does not
+have a numeric value (or has no value) then the default is 10.
+If the variable does not exist, then @code{EOF} signifies the end of 
+input to the shell.  This is only in effect for interactive shells.
+
+@item no_exit_on_failed_exec
+If this variable exists, the shell will not exit in the case that it
+couldn't execute the file specified in the @code{exec} command.
+
+@item nolinks
+If present, says not to follow symbolic links when doing commands
+that change the current working directory.  By default, bash follows
+the logical chain of directories when performing commands such as
+@code{cd} which change the current directory.
+
+For example, if @file{/usr/sys} is a link to @file{/usr/local/sys} then:
+@example
+$ cd /usr/sys; echo $PWD
+/usr/sys
+$ cd ..; pwd
+/usr
+@end example
+
+@noindent
+If @code{nolinks} exists, then:
+@example
+$ cd /usr/sys; echo $PWD
+/usr/local/sys
+$ cd ..; pwd
+/usr/local
+@end example
+
+See also the description of the @code{-P} option to the @code{set}
+builtin, @ref{The Set Builtin}.
+@end vtable
+
+@node Shell Arithmetic
+@section Shell Arithmetic
+
+@menu
+* Arithmetic Evaluation::      How shell arithmetic works.
+* Arithmetic Expansion::       How to use arithmetic in shell expansions.
+* Arithmetic Builtins::                Builtin commands that use shell arithmetic.
+@end menu
+
+@node Arithmetic Evaluation
+@subsection Arithmetic Evaluation
+
+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,
+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. 
+
+@table @code
+@item - +
+unary minus and plus
+
+@item ! ~
+logical and bitwise negation
+
+@item * / %
+multiplication, division, remainder
+
+@item + -
+addition, subtraction
+
+@item << >>
+left and right bitwise shifts
+
+@item <= >= < >
+comparison
+
+@item == !=
+equality and inequality
+
+@item &
+bitwise AND
+
+@item ^
+bitwise exclusive OR
+
+@item |
+bitwise OR
+
+@item &&
+logical AND
+
+@item ||
+logical OR
+
+@item = *= /= %= += -= <<= >>= &= ^= |=
+assignment
+@end table
+
+Shell variables are allowed as operands; parameter expansion is
+performed before the expression is evaluated. 
+The value of a parameter is coerced to a long integer within
+an expression.  A shell variable need not have its integer attribute
+turned on to be used in an expression.
+
+Constants with a leading 0 are interpreted as octal numbers.
+A leading @code{0x} or @code{0X} denotes hexadecimal.  Otherwise,
+numbers take the form [@var{base#}]n, where @var{base} is a
+decimal number between 2 and 36 representing the arithmetic
+base, and @var{n} is a number in that base.  If @var{base} is
+omitted, then base 10 is used.
+
+Operators are evaluated in order of precedence.  Sub-expressions in
+parentheses are evaluated first and may override the precedence
+rules above.
+
+@node Arithmetic Expansion
+@subsection Arithmetic Expansion
+
+Arithmetic expansion allows the evaluation of an arithmetic expression
+and the substitution of the result.  There are two formats for
+arithmetic expansion:
+
+@example
+$[ expression ]
+$(( expression ))
+@end example
+
+The expression is treated as if it were within double quotes, but
+a double quote inside the braces or parentheses is not treated
+specially.  All tokens in the expression undergo parameter
+expansion, command substitution, and quote removal.  Arithmetic
+substitutions may be nested. 
+
+The evaluation is performed according to the rules listed above.
+If the expression is invalid, Bash
+prints a message indicating failure and no substitution occurs.
+
+@node Arithmetic Builtins
+@subsection Arithmetic Builtins
+
+@ftable @code
+@item let
+@example
+let @var{expression} [@var{expression}]
+@end example
+The @code{let} builtin allows arithmetic to be performed on shell
+variables.  Each @var{expression} is evaluated according to the
+rules given previously (@pxref{Arithmetic Evaluation}).  If the
+last @var{expression} evaluates to 0, @code{let} returns 1;
+otherwise 0 is returned.
+@end ftable
+
+@node Printing a Prompt
+@section Controlling the Prompt
+
+The value of the variable @code{$PROMPT_COMMAND} is examined just before
+Bash prints each primary prompt.  If it is set and non-null, then the
+value is executed just as if you had typed it on the command line.
+
+In addition, the following table describes the special characters which
+can appear in the @code{PS1} variable:
+
+@table @code
+@item \t
+the time, in HH:MM:SS format.
+@item \d
+the date, in "Weekday Month Date" format (e.g. "Tue May 26").
+@item \n
+newline.
+@item \s
+the name of the shell, the basename of @code{$0} (the portion
+following the final slash).
+@item \w
+the current working directory.
+@item \W
+the basename of @code{$PWD}.
+@item \u
+your username.
+@item \h
+the hostname.
+@item \#
+the command number of this command.
+@item \!
+the history number of this command.
+@item \nnn
+the character corresponding to the octal number @code{nnn}.
+@item \$
+if the effective uid is 0, @code{#}, otherwise @code{$}.
+@item \\
+a backslash.
+@item \[
+begin a sequence of non-printing characters.  This could be used to
+embed a terminal control sequence into the prompt.
+@item \]
+end a sequence of non-printing characters.
+@end table
+
+@node Job Control
+@chapter Job Control
+
+This chapter disusses what job control is, how it works, and how
+Bash allows you to access its facilities.
+
+@menu
+* Job Control Basics::         How job control works.
+* Job Control Builtins::       Bash builtin commands used to interact
+                               with job control.
+* Job Control Variables::      Variables Bash uses to customize job
+                               control.
+@end menu
+
+@node Job Control Basics
+@section Job Control Basics
+
+Job control
+refers to the ability to selectively stop (suspend)
+the execution of processes and continue (resume)
+their execution at a later point.  A user typically employs
+this facility via an interactive interface supplied jointly
+by the system's terminal driver and Bash.
+
+The shell associates a @var{job} with each pipeline.  It keeps a
+table of currently executing jobs, which may be listed with the
+@code{jobs} command.  When Bash starts a job
+asynchronously (in the background), it prints a line that looks
+like:
+@example
+[1] 25647
+@end example
+indicating that this job is job number 1 and that the process ID
+of the last process in the pipeline associated with this job is
+25647.  All of the processes in a single pipeline are members of
+the same job.  Bash uses the @var{job} abstraction as the
+basis for job control. 
+
+To facilitate the implementation of the user interface to job
+control, the system maintains the notion of a current terminal
+process group ID.  Members of this process group (processes whose
+process group ID is equal to the current terminal process group
+ID) receive keyboard-generated signals such as @code{SIGINT}. 
+These processes are said to be in the foreground.  Background
+processes are those whose process group ID differs from the
+terminal's; such processes are immune to keyboard-generated
+signals.  Only foreground processes are allowed to read from or
+write to the terminal.  Background processes which attempt to
+read from (write to) the terminal are sent a @code{SIGTTIN}
+(@code{SIGTTOU}) signal by the terminal driver, which, unless
+caught, suspends the process. 
+
+If the operating system on which Bash is running supports
+job control, Bash allows you to use it.  Typing the
+@var{suspend} character (typically @samp{^Z}, Control-Z) while a
+process is running causes that process to be stopped and returns
+you to Bash.  Typing the @var{delayed suspend} character
+(typically @samp{^Y}, Control-Y) causes the process to be stopped
+when it attempts to read input from the terminal, and control to
+be returned to Bash.  You may then manipulate the state of
+this job, using the @code{bg} command to continue it in the
+background, the @code{fg} command to continue it in the
+foreground, or the @code{kill} command to kill it.  A @samp{^Z}
+takes effect immediately, and has the additional side effect of
+causing pending output and typeahead to be discarded. 
+
+There are a number of ways to refer to a job in the shell.  The
+character @samp{%} introduces a job name.  Job number @code{n}
+may be referred to as @samp{%n}.  A job may also be referred to
+using a prefix of the name used to start it, or using a substring
+that appears in its command line.  For example, @samp{%ce} refers
+to a stopped @code{ce} job. Using @samp{%?ce}, on the
+other hand, refers to any job containing the string @samp{ce} in
+its command line.  If the prefix or substring matches more than one job,
+Bash reports an error.  The symbols @samp{%%} and
+@samp{%+} refer to the shell's notion of the current job, which
+is the last job stopped while it was in the foreground.  The
+previous job may be referenced using @samp{%-}.  In output
+pertaining to jobs (e.g., the output of the @code{jobs} command),
+the current job is always flagged with a @samp{+}, and the
+previous job with a @samp{-}. 
+
+Simply naming a job can be used to bring it into the foreground:
+@samp{%1} is a synonym for @samp{fg %1} bringing job 1 from the
+background into the foreground.  Similarly, @samp{%1 &} resumes
+job 1 in the background, equivalent to @samp{bg %1}
+
+The shell learns immediately whenever a job changes state. 
+Normally, Bash waits until it is about to print a prompt
+before reporting changes in a job's status so as to not interrupt
+any other output.  If the 
+the @code{-b} option to the @code{set} builtin is set,
+Bash reports such changes immediately (@pxref{The Set Builtin}).
+This feature is also controlled by the variable @code{notify}.
+
+If you attempt to exit bash while jobs are stopped, the
+shell prints a message warning you.  You may then use the
+@code{jobs} command to inspect their status.  If you do this, or
+try to exit again immediately, you are not warned again, and the
+stopped jobs are terminated. 
+
+@node Job Control Builtins
+@section Job Control Builtins
+
+@ftable @code
+
+@item bg
+@example
+bg [@var{jobspec}]
+@end example
+Place @var{jobspec} into the background, as if it had been started
+with @samp{&}.  If @var{jobspec} is not supplied, the current job
+is used.
+
+@item fg
+@example
+fg [@var{jobspec}]
+@end example
+Bring @var{jobspec} into the foreground and make it the current job.
+If @var{jobspec} is not supplied, the current job is used.
+
+@item jobs
+@example
+jobs [-lpn] [@var{jobspec}]
+jobs -x @var{command} [@var{jobspec}]
+@end example
+
+The first form lists the active jobs.  The @code{-l} option lists
+process IDs in addition to the normal information; the @code{-p}
+option lists only the process ID of the job's process group
+leader.  The @code{-n} option displays only jobs that have
+changed status since last notfied.  If @var{jobspec} is given,
+output is restricted to information about that job. 
+If @var{jobspec} is not supplied, the status of all jobs is
+listed.
+
+If the @code{-x} option is supplied, @code{jobs} replaces any
+@var{jobspec} found in @var{command} or @var{arguments} with the
+corresponding process group ID, and executes @var{command},
+passing it @var{argument}s, returning its exit status. 
+
+@item suspend
+@example
+suspend [-f]
+@end example
+Suspend the execution of this shell until it receives a
+@code{SIGCONT} signal.  The @code{-f} option means to suspend
+even if the shell is a login shell.
+
+@end ftable
+
+When job control is active, the @code{kill} and @code{wait}
+builtins also accept @var{jobspec} arguments.
+
+@node Job Control Variables
+@section Job Control Variables
+
+@vtable @code
+
+@item auto_resume
+This variable controls how the shell interacts with the user and
+job control.  If this variable exists then single word simple
+commands without redirects are treated as candidates for resumption
+of an existing job.  There is no ambiguity allowed; if you have
+more than one job beginning with the string that you have typed, then
+the most recently accessed job will be selected.
+The name of a stopped job, in this context, is the command line
+used to start it.  If this variable is set to the value @code{exact},
+the string supplied must match the name of a stopped job exactly;
+if set to @code{substring},
+the string supplied needs to match a substring of the name of a
+stopped job.  The @code{substring} value provides functionality
+analogous to the @code{%?} job id (@pxref{Job Control Basics}).
+If set to any other value, the supplied string must
+be a prefix of a stopped job's name; this provides functionality
+analogous to the @code{%} job id.
+
+@item notify
+Setting this variable to a value is equivalent to
+@samp{set -b}; unsetting it is equivalent to @samp{set +b}
+(@pxref{The Set Builtin}).
+
+@end vtable
+
+@set readline-appendix
+@set history-appendix
+@cindex History, how to use
+@include hsuser.texinfo
+@cindex Readline, how to use
+@include rluser.texinfo
+@clear readline-appendix
+@clear history-appendix
+
+@node Variable Index
+@appendix Variable Index
+@printindex vr
+
+@node Concept Index
+@appendix Concept Index
+@printindex cp
+
+@contents
+@bye
diff --git a/documentation/readline.3 b/documentation/readline.3
new file mode 100644 (file)
index 0000000..bbe9d91
--- /dev/null
@@ -0,0 +1,1216 @@
+.\"
+.\" MAN PAGE COMMENTS to
+.\"
+.\"    Chet Ramey
+.\"    Information Network Services
+.\"    Case Western Reserve University
+.\"    chet@ins.CWRU.Edu
+.\"
+.\"    Last Change: Wed Jul 20 16:13:11 EDT 1994
+.\"
+.TH READLINE 3 "1994 July 26" GNU
+.\"
+.\" File Name macro.  This used to be `.PN', for Path Name,
+.\" but Sun doesn't seem to like that very much.
+.\"
+.de FN
+\fI\|\\$1\|\fP
+..
+.SH NAME
+readline \- get a line from a user with editing
+.SH SYNOPSIS
+.LP
+.nf
+.ft B
+#include <readline.h>
+#include <history.h>
+.ft
+.fi
+.LP
+.nf
+.ft B
+typedef int Function ();
+.LP
+.nf
+.ft B
+char *readline (prompt)
+char *prompt;
+.ft
+.fi
+.LP
+.nf
+.ft B
+int rl_add_defun (name, function, key)
+char *name;
+Function *function;
+int key;
+.ft
+.fi
+.LP
+.nf
+.ft B
+int rl_bind_key (key, function)
+int key;
+Function *function;
+.ft
+.fi
+.LP
+.nf
+.ft B
+int rl_unbind_key (key)
+int key;
+.ft
+.fi
+.LP
+.nf
+.ft B
+int rl_bind_key_in_map (key, function, keymap)
+int key;
+Function *function;
+Keymap keymap;
+.ft
+.fi
+.LP
+.nf
+.ft B
+int rl_unbind_key_in_map (key, keymap)
+int key;
+Keymap keymap;
+.ft
+.fi
+.LP
+.nf
+.ft B
+int rl_macro_bind (keyseq, macro, keymap)
+char *keyseq, *macro;
+Keymap keymap;
+.ft
+.fi
+.LP
+.nf
+.ft B
+int rl_variable_bind (variable, value)
+char *variable, *value;
+.ft
+.fi
+.LP
+.nf
+.ft B
+int rl_parse_and_bind (line)
+char *line;
+.ft
+.fi
+.LP
+.nf
+.ft B
+int rl_translate_keyseq (keyseq, array, len)
+char *keyseq, *array;
+int *len;
+.ft
+.fi
+.LP
+.nf
+.ft B
+Function *rl_named_function (command)
+char *command;
+.ft
+.fi
+.LP
+.nf
+.ft B
+Function *rl_function_of_keyseq (keyseq, keymap, type)
+char *keyseq;
+Keymap keymap;
+int *type;
+.ft
+.fi
+.LP
+.nf
+.ft B
+char **rl_invoking_keyseqs (function)
+Function *function;
+.ft
+.fi
+.LP
+.nf
+.ft B
+char **rl_invoking_keyseqs_in_map (function, keymap)
+Function *function;
+Keymap keymap;
+.ft
+.fi
+.LP
+.nf
+.ft B
+void rl_function_dumper (readable)
+int readable;
+.ft
+.fi
+.LP
+.nf
+.ft B
+char **rl_funmap_names ()
+.ft
+.fi
+.SH COPYRIGHT
+.if n Readline is Copyright (C) 1989, 1991 by the Free Software Foundation, Inc.
+.if t Readline is Copyright \(co 1989, 1991 by the Free Software Foundation, Inc.
+.SH DESCRIPTION
+.LP
+.B readline
+will read a line from the terminal
+and return it, using
+.B prompt
+as a prompt.  If 
+.B prompt
+is null, no prompt is issued.  The line returned is allocated with
+.IR malloc (3),
+so the caller must free it when finished.  The line returned
+has the final newline removed, so only the text of the line
+remains.
+.LP
+.B readline
+offers editing capabilities while the user is entering the
+line.
+By default, the line editing commands
+are similar to those of emacs.
+A vi\-style line editing interface is also available.
+.LP
+In the following descriptions,
+.B keymap
+can be one of \fIemacs_keymap, emacs_meta_keymap, emacs_ctlx_keymap,
+vi_insertion_keymap, or vi_movement_keymap\fP.
+.LP
+.B rl_add_defun
+makes
+.B name
+appear as a bindable readline command, and makes
+.B function
+be the function called when that command is invoked.  If
+.B key
+is not \-1, it is bound to
+.B function
+in the current keymap.
+.LP
+.B rl_bind_key
+causes
+.B key
+to invoke
+.BR function .
+The binding is made in the current keymap.
+.LP
+.B rl_unbind_key
+removes the binding for
+.B key
+in the current keymap.
+.LP
+.B rl_bind_key_in_map
+makes the
+.B key
+entry in
+.B keymap
+invoke
+.BR function .
+.LP
+.B rl_unbind_key_in_map
+removes the binding for
+.B key
+in keymap
+.BR keymap .
+.LP
+.B rl_macro_bind
+makes
+.B keyseq
+insert the string
+.BR macro .
+The binding is performed in
+.BR keymap .
+.LP
+.B rl_variable_bind
+sets the value of the readline variable
+.B variable
+to
+.BR value .
+.LP
+.B rl_parse_and_bind
+takes as an argument a line of the same form as the readline startup
+file (see
+.SM
+.B INITIALIZATION FILE
+below) and executes the commands therein.
+.LP
+.B rl_translate_keyseq
+converts
+.B keyseq
+into a new string, storing the result in
+.BR array .
+This translates control and meta prefixes and the readline
+character escape sequences (see
+.SM
+.B Key Bindings
+below).  The length of the translated sequence is returned in
+.BR *len .
+.LP
+.B rl_named_function
+returns the function that is executed when the readline
+command
+.B command
+is invoked.
+.LP
+.B rl_function_of_keyseq
+returns the function that is executed when
+.B keyseq
+is read and
+.B keymap
+is the current keymap.
+.B type
+is set to indicate whether the return value corresponds to a
+function, macro, or auxiliary keymap.
+.LP
+.B rl_invoking_keyseqs
+returns all of the key sequences in the current keymap that
+invoke
+.BR function .
+.LP
+.B rl_invoking_keyseqs_in_map
+returns all of the key sequences in
+.B keymap
+that invoke
+.BR function .
+.LP
+.B rl_function_dumper
+prints all of the readline functions and their bindings to the
+readline output stream.  If
+.B readable
+is non\-zero, the output is formattted so that it can be read
+back in to restore the bindings.
+.LP
+.B rl_funmap_names
+returns an array of all known readline bindable function names.
+The array is sorted.
+.SH RETURN VALUE
+.LP
+.B readline
+returns the text of the line read.  A blank line
+returns the empty string.  If
+.B EOF
+is encountered while reading a line, and the line is empty,
+.B NULL
+is returned.  If an
+.B EOF
+is read with a non\-empty line, it is
+treated as a newline.
+.LP
+Unless otherwise stated,
+the other functions return 0 on success and non\-zero on failure.
+.SH NOTATION
+.LP
+An emacs\-style notation is used to denote
+keystrokes.  Control keys are denoted by C\-\fIkey\fR, e.g., C\-n
+means Control\-N.  Similarly, 
+.I meta
+keys are denoted by M\-\fIkey\fR, so M\-x means Meta\-X.  (On keyboards
+without a 
+.I meta
+key, M\-\fIx\fP means ESC \fIx\fP, i.e., press the Escape key
+then the
+.I x
+key.  This makes ESC the \fImeta prefix\fP.
+The combination M\-C\-\fIx\fP means ESC\-Control\-\fIx\fP,
+or press the Escape key
+then hold the Control key while pressing the
+.I x
+key.)
+.PP
+Readline commands may be given numeric
+.IR arguments ,
+which normally act as a repeat count.  Sometimes, however, it is the
+sign of the argument that is significant.  Passing a negative argument
+to a command that acts in the forward direction (e.g., \fBkill\-line\fP)
+causes that command to act in a backward direction.  Commands whose
+behavior with arguments deviates from this are noted.
+.PP
+When a command is described as \fIkilling\fP text, the text
+deleted is saved for possible future retrieval
+(\fIyanking\fP).  The killed text is saved in a
+\fIkill\-ring\fP.  Consecutive kills cause the text to be
+accumulated into one unit, which can be yanked all at once. 
+Commands which do not kill text separate the chunks of text
+on the kill\-ring.
+.SH INITIALIZATION FILE
+.LP
+Readline is customized by putting commands in an initialization
+file.  The name of this file is taken from the value of the
+.B INPUTRC
+variable.  If that variable is unset, the default is
+.IR ~/.inputrc .
+When a program which uses the readline library starts up, the
+init file is read, and the key bindings and variables are set.
+There are only a few basic constructs allowed in the
+readline init file.  Blank lines are ignored.
+Lines beginning with a \fB#\fP are comments.
+Lines beginning with a \fB$\fP indicate conditional
+constructs.  Other lines
+denote key bindings and variable settings.
+Each program using this library may add its own commands
+and bindings.
+.PP
+For example, placing
+.RS
+.PP
+M\-Control\-u: universal\-argument
+.RE
+or
+.RS
+C\-Meta\-u: universal\-argument
+.RE
+into the 
+.FN ~/.inputrc
+would make M\-C\-u execute the readline command
+.IR universal\-argument .
+.PP
+The following symbolic character names are recognized while
+processing key bindings:
+.IR RUBOUT ,
+.IR DEL ,
+.IR ESC ,
+.IR LFD ,
+.IR NEWLINE ,
+.IR RET ,
+.IR RETURN ,
+.IR SPC ,
+.IR SPACE ,
+and
+.IR TAB .
+In addition to command names, readline allows keys to be bound
+to a string that is inserted when the key is pressed (a \fImacro\fP).
+.PP
+.SS Key Bindings
+.PP
+The syntax for controlling key bindings in the
+.I ~/.inputrc
+file is simple.  All that is required is the name of the
+command or the text of a macro and a key sequence to which
+it should be bound. The name may be specified in one of two ways:
+as a symbolic key name, possibly with \fIMeta\-\fP or \fIControl\-\fP
+prefixes, or as a key sequence.
+When using the form \fBkeyname\fP:\fIfunction-name\fP or \fImacro\fP,
+.I keyname
+is the name of a key spelled out in English.  For example:
+.sp
+.RS
+Control\-u: universal\-argument
+.br
+Meta\-Rubout: backward\-kill\-word
+.br
+Control\-o: ">&output"
+.RE
+.LP
+In the above example,
+.I C\-u
+is bound to the function
+.BR universal\-argument ,
+.I M-DEL
+is bound to the function
+.BR backward\-kill\-word ,
+and
+.I C\-o
+is bound to run the macro
+expressed on the right hand side (that is, to insert the text
+.I >&output
+into the line).
+.PP
+In the second form, \fB"keyseq"\fP:\fIfunction\-name\fP or \fImacro\fP,
+.B keyseq
+differs from
+.B keyname
+above in that strings denoting
+an entire key sequence may be specified by placing the sequence
+within double quotes.  Some GNU Emacs style key escapes can be
+used, as in the following example.
+.sp
+.RS
+"\eC\-u": universal\-argument
+.br
+"\eC\-x\eC\-r": re\-read\-init\-file
+.br
+"\ee[11~": "Function Key 1"
+.RE
+.PP
+In this example,
+.I C-u
+is again bound to the function
+.BR universal\-argument .
+.I "C-x C-r"
+is bound to the function
+.BR re\-read\-init\-file ,
+and 
+.I "ESC [ 1 1 ~"
+is bound to insert the text
+.BR "Function Key 1" .
+The full set of escape sequences is
+.RS
+.TP
+.B \eC-
+control prefix
+.TP
+.B \eM-
+meta prefix
+.TP
+.B \ee
+an escape character
+.TP
+.B \e\e
+backslash
+.TP
+.B \e"
+literal "
+.TP
+.B \e'
+literal '
+.RE
+.PP
+When entering the text of a macro, single or double quotes should
+be used to indicate a macro definition.  Unquoted text
+is assumed to be a function name.  Backslash
+will quote any character in the macro text, including " and '.
+.PP
+.B Bash
+allows the current readline key bindings to be displayed or modified
+with the
+.B bind
+builtin command.  The editing mode may be switched during interactive
+use by using the
+.B \-o
+option to the
+.B set
+builtin command.  Other programs using this library provide
+similar mechanisms.  The
+.I inputrc
+file may be edited and re\-read if a program does not provide
+any other means to incorporate new bindings.
+.SS Variables
+.PP
+Readline has variables that can be used to further customize its
+behavior.  A variable may be set in the
+.I inputrc
+file with a statement of the form
+.RS
+.PP
+\fBset\fP \fIvariable\-name\fP \fIvalue\fP
+.RE
+.PP
+Except where noted, readline variables can take the values
+.B On
+or
+.BR Off .
+The variables and their default values are:
+.PP
+.PD 0
+.TP
+.B horizontal\-scroll\-mode (Off)
+When set to \fBOn\fP, makes readline use a single line for display,
+scrolling the input horizontally on a single screen line when it
+becomes longer than the screen width rather than wrapping to a new line.
+.TP
+.B editing\-mode (emacs)
+Controls whether readline begins with a set of key bindings similar
+to \fIemacs\fP or \fIvi\fP.
+.B editing\-mode
+can be set to either
+.B emacs
+or
+.BR vi .
+.TP
+.B mark\-modified\-lines (Off)
+If set to \fBOn\fP, history lines that have been modified are displayed
+with a preceding asterisk (\fB*\fP).
+.TP
+.B bell\-style (audible)
+Controls what happens when readline wants to ring the terminal bell.
+If set to \fBnone\fP, readline never rings the bell.  If set to
+\fBvisible\fP, readline uses a visible bell if one is available.
+If set to \fBaudible\fP, readline attempts to ring the terminal's bell.
+.TP
+.B comment\-begin (``#'')
+The string that is inserted in \fBvi\fP mode when the
+.B vi\-comment
+command is executed.
+.TP
+.B meta\-flag (Off)
+If set to \fBOn\fP, readline will enable eight-bit input (that is,
+it will not strip the high bit from the characters it reads),
+regardless of what the terminal claims it can support.
+.TP
+.B convert\-meta (On)
+If set to \fBOn\fP, readline will convert characters with the
+eighth bit set to an ASCII key sequence
+by stripping the eighth bit and prepending an
+escape character (in effect, using escape as the \fImeta prefix\fP).
+.TP
+.B output\-meta (Off)
+If set to \fBOn\fP, readline will display characters with the
+eighth bit set directly rather than as a meta-prefixed escape
+sequence.
+.TP
+.B completion\-query\-items (100)
+This determines when the user is queried about viewing
+the number of possible completions
+generated by the \fBpossible\-completions\fP command.
+It may be set to any integer value greater than or equal to
+zero.  If the number of possible completions is greater than
+or equal to the value of this variable, the user is asked whether
+or not he wishes to view them; otherwise they are simply listed
+on the terminal.
+.TP
+.B keymap (emacs)
+Set the current readline keymap.  The set of legal keymap names is
+\fIemacs, emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,
+vi-command\fP, and
+.IR vi-insert .
+\fIvi\fP is equivalent to \fIvi-command\fP; \fIemacs\fP is
+equivalent to \fIemacs-standard\fP.  The default value is
+.IR emacs ;
+the value of
+.B editing\-mode
+also affects the default keymap.
+.TP
+.B show\-all\-if\-ambiguous (Off)
+This alters the default behavior of the completion functions.  If
+set to
+.BR on ,
+words which have more than one possible completion cause the
+matches to be listed immediately instead of ringing the bell.
+.TP
+.B expand\-tilde (Off)
+If set to \fBon\fP, tilde expansion is performed when readline
+attempts word completion.
+.PD
+.SS Conditional Constructs
+.PP
+Readline implements a facility similar in spirit to the conditional
+compilation features of the C preprocessor which allows key
+bindings and variable settings to be performed as the result
+of tests.  There are three parser directives used.
+.IP \fB$if\fP
+The 
+.B $if
+construct allows bindings to be made based on the
+editing mode, the terminal being used, or the application using
+readline.  The text of the test extends to the end of the line;
+no characters are required to isolate it.
+.RS
+.IP \fBmode\fP
+The \fBmode=\fP form of the \fB$if\fP directive is used to test
+whether readline is in emacs or vi mode.
+This may be used in conjunction
+with the \fBset keymap\fP command, for instance, to set bindings in
+the \fIemacs-standard\fP and \fIemacs-ctlx\fP keymaps only if
+readline is starting out in emacs mode.
+.IP \fBterm\fP
+The \fBterm=\fP form may be used to include terminal-specific
+key bindings, perhaps to bind the key sequences output by the
+terminal's function keys.  The word on the right side of the
+.B =
+is tested against the full name of the terminal and the portion
+of the terminal name before the first \fB\-\fP.  This allows
+.I sun
+to match both
+.I sun
+and
+.IR sun\-cmd ,
+for instance.
+.IP \fBapplication\fP
+The \fBapplication\fP construct is used to include
+application\-specific settings.  Each program using the readline
+library sets the \fIapplication name\fP, and an initialization
+file can test for a particular value.
+This could be used to bind key sequences to functions useful for
+a specific program.  For instance, the following command adds a
+key sequence that quotes the current or previous word in Bash:
+.RS
+.nf
+\fB$if\fP bash
+# Quote the current or previous word
+"\eC-xq": "\eeb\e"\eef\e""
+\fB$endif\fP
+.fi
+.RE
+.RE
+.IP \fB$endif\fP
+This command, as you saw in the previous example, terminates an
+\fB$if\fP command.
+.IP \fB$else\fP
+Commands in this branch of the \fB$if\fP directive are executed if
+the test fails.
+.SH EDITING COMMANDS
+.PP
+The following is a list of the names of the commands and the default
+key sequences to which they are bound.
+.SS Commands for Moving
+.PP
+.PD 0
+.TP
+.B beginning\-of\-line (C\-a)
+Move to the start of the current line.
+.TP
+.B end\-of\-line (C\-e)
+Move to the end of the line.
+.TP
+.B forward\-char (C\-f)
+Move forward a character.
+.TP
+.B backward\-char (C\-b)
+Move back a character.
+.TP
+.B forward\-word (M\-f)
+Move forward to the end of the next word.  Words are composed of
+alphanumeric characters (letters and digits).
+.TP
+.B backward\-word (M\-b)
+Move back to the start of this, or the previous, word.  Words are
+composed of alphanumeric characters (letters and digits).
+.TP
+.B clear\-screen (C\-l)
+Clear the screen leaving the current line at the top of the screen.
+With an argument, refresh the current line without clearing the
+screen.
+.TP
+.B redraw\-current\-line
+Refresh the current line.  By default, this is unbound.
+.PD
+.SS Commands for Manipulating the History
+.PP
+.PD 0
+.TP
+.B accept\-line (Newline, Return)
+Accept the line regardless of where the cursor is.  If this line is
+non\-empty, add it to the history list. If the line is a modified
+history line, then restore the history line to its original state.
+.TP
+.B previous\-history (C\-p)
+Fetch the previous command from the history list, moving back in
+the list.
+.TP
+.B next\-history (C\-n)
+Fetch the next command from the history list, moving forward in the
+list.
+.TP
+.B beginning\-of\-history (M\-<)
+Move to the first line in the history.
+.TP
+.B end\-of\-history (M\->)
+Move to the end of the input history, i.e., the line currently being
+entered.
+.TP
+.B reverse\-search\-history (C\-r)
+Search backward starting at the current line and moving `up' through
+the history as necessary.  This is an incremental search.
+.TP
+.B forward\-search\-history (C\-s)
+Search forward starting at the current line and moving `down' through
+the history as necessary.  This is an incremental search.
+.TP
+.B non\-incremental\-reverse\-search\-history (M\-p)
+Search backward through the history starting at the current line
+using a non\-incremental search for a string supplied by the user.
+.TP
+.B non\-incremental\-forward\-search\-history (M\-n)
+Search forward through the history using a non\-incremental search
+for a string supplied by the user.
+.TP
+.B history\-search\-forward
+Search forward through the history for the string of characters
+between the start of the current line and the current point.  This
+is a non-incremental search.  By default, this command is unbound.
+.TP
+.B history\-search\-backward
+Search backward through the history for the string of characters
+between the start of the current line and the current point.  This
+is a non-incremental search.  By default, this command is unbound.
+.TP
+.B yank\-nth\-arg (M\-C\-y)
+Insert the first argument to the previous command (usually
+the second word on the previous line) at point (the current
+cursor position).  With an argument
+.IR n ,
+insert the \fIn\fPth word from the previous command (the words
+in the previous command begin with word 0).  A negative argument
+inserts the \fIn\fPth word from the end of the previous command.
+.TP
+.B
+yank\-last\-arg (M\-.\^, M\-_\^)
+Insert the last argument to the previous command (the last word on
+the previous line).  With an argument,
+behave exactly like \fByank-nth-arg\fP.
+.PD
+.SS Commands for Changing Text
+.PP
+.PD 0
+.TP
+.B delete\-char (C\-d)
+Delete the character under the cursor.  If point is at the
+beginning of the line, there are no characters in the line, and
+the last character typed was not
+.BR C\-d ,
+then return
+.SM
+.BR EOF .
+.TP
+.B backward\-delete\-char (Rubout)
+Delete the character behind the cursor.  When given a numeric argument,
+save the deleted text on the kill\-ring.
+.TP
+.B quoted\-insert (C\-q, C\-v)
+Add the next character that you type to the line verbatim.  This is
+how to insert characters like \fBC\-q\fP, for example.
+.TP
+.B tab\-insert (M-TAB)
+Insert a tab character.
+.TP
+.B self\-insert (a,\ b,\ A,\ 1,\ !,\ ...)
+Insert the character typed.
+.TP
+.B transpose\-chars (C\-t)
+Drag the character before point forward over the character at point.
+Point moves forward as well.  If point is at the end of the line, then
+transpose the two characters before point.  Negative arguments don't work.
+.TP
+.B transpose\-words (M\-t)
+Drag the word behind the cursor past the word in front of the cursor
+moving the cursor over that word as well.
+.TP
+.B upcase\-word (M\-u)
+Uppercase the current (or following) word.  With a negative argument,
+do the previous word, but do not move point.
+.TP
+.B downcase\-word (M\-l)
+Lowercase the current (or following) word.  With a negative argument,
+do the previous word, but do not move point.
+.TP
+.B capitalize\-word (M\-c)
+Capitalize the current (or following) word.  With a negative argument,
+do the previous word, but do not move point.
+.PD
+.SS Killing and Yanking
+.PP
+.PD 0
+.TP
+.B kill\-line (C\-k)
+Kill the text from the current cursor position to the end of the line.
+.TP
+.B backward\-kill\-line (C\-x Rubout)
+Kill backward to the beginning of the line.
+.TP
+.B unix\-line\-discard (C\-u)
+Kill backward from point to the beginning of the line.
+.\" There is no real difference between this and backward-kill-line
+.TP
+.B kill\-whole\-line
+Kill all characters on the current line, no matter where the
+cursor is.  By default, this is unbound.
+.TP
+.B kill\-word  (M\-d)
+Kill from the cursor to the end of the current word, or if between
+words, to the end of the next word.  Word boundaries are the same as
+those used by \fBforward\-word\fP.
+.TP
+.B backward\-kill\-word (M\-Rubout)
+Kill the word behind the cursor.  Word boundaries are the same as
+those used by \fBbackward\-word\fP.
+.TP
+.B unix\-word\-rubout (C\-w)
+Kill the word behind the cursor, using white space as a word boundary.
+The word boundaries are different from
+.BR backward\-kill\-word .
+.TP
+.B delete\-horizontal\-space
+Delete all spaces and tabs around point.  By default, this is unbound.
+.TP
+.B yank (C\-y)
+Yank the top of the kill ring into the buffer at the cursor.
+.TP
+.B yank\-pop (M\-y)
+Rotate the kill\-ring, and yank the new top.  Only works following
+.B yank
+or
+.BR yank\-pop .
+.PD
+.SS Numeric Arguments
+.PP
+.PD 0
+.TP
+.B digit\-argument (M\-0, M\-1, ..., M\-\-)
+Add this digit to the argument already accumulating, or start a new
+argument.  M\-\- starts a negative argument.
+.TP
+.B universal\-argument
+Each time this is executed, the argument count is multiplied by four.
+The argument count is initially one, so executing this function the
+first time makes the argument count four.  By default, this is not
+bound to a key.
+.PD
+.SS Completing
+.PP
+.PD 0
+.TP
+.B complete (TAB)
+Attempt to perform completion on the text before point.
+The actual completion performed is application-specific.
+.BR Bash ,
+for instance, attempts completion treating the text as a variable
+(if the text begins with \fB$\fP), username (if the text begins with
+\fB~\fP), hostname (if the text begins with \fB@\fP), or
+command (including aliases and functions) in turn.  If none
+of these produces a match, filename completion is attempted.
+.BR Gdb ,
+on the other hand,
+allows completion of program functions and variables, and
+only attempts filename completion under certain circumstances.
+.TP
+.B possible\-completions (M-?)
+List the possible completions of the text before point.
+.TP
+.B insert\-completions
+Insert all completions of the text before point
+that would have been generated by
+\fBpossible\-completions\fP.  By default, this
+is not bound to a key.
+.PD
+.SS Keyboard Macros
+.PP
+.PD 0
+.TP
+.B start\-kbd\-macro (C-x (\^)
+Begin saving the characters typed into the current keyboard macro.
+.TP
+.B end\-kbd\-macro (C-x )\^)
+Stop saving the characters typed into the current keyboard macro
+and save the definition.
+.TP
+.B call\-last\-kbd\-macro (C-x e)
+Re-execute the last keyboard macro defined, by making the characters
+in the macro appear as if typed at the keyboard.
+.PD
+.SS Miscellaneous
+.PP
+.PD 0
+.TP
+.B re-read-init-file (C\-x C\-r)
+Read in the contents of your init file, and incorporate
+any bindings or variable assignments found there.
+.TP
+.B abort (C\-g)
+Abort the current editing command and
+ring the terminal's bell (subject to the setting of
+.BR bell\-style ).
+.TP
+.B do\-uppercase\-version (M\-a, M\-b, ...)
+Run the command that is bound to the corresponding uppercase
+character.
+.TP
+.B prefix\-meta (ESC)
+Metafy the next character typed.
+.SM
+.B ESC
+.B f
+is equivalent to
+.BR Meta\-f .
+.TP
+.B undo (C\-_, C\-x C\-u)
+Incremental undo, separately remembered for each line.
+.TP
+.B revert\-line (M\-r)
+Undo all changes made to this line.  This is like typing the
+.B undo
+command enough times to return the line to its initial state.
+.TP
+.B tilde\-expand (M\-~)
+Perform tilde expansion on the current word.
+.TP
+.B dump\-functions
+Print all of the functions and their key bindings to the
+readline output stream.  If a numeric argument is supplied,
+the output is formatted in such a way that it can be made part
+of an \fIinputrc\fP file.
+.TP
+.B emacs\-editing\-mode (C\-e)
+When in
+.B vi
+editing mode, this causes a switch to
+.B emacs
+editing mode.
+.TP
+.B vi\-editing\-mode (M\-C\-j)
+When in
+.B emacs
+editing mode, this causes a switch to
+.B vi
+editing mode.
+.PD
+.SH DEFAULT KEY BINDINGS
+.LP
+The following is a list of the default emacs and vi bindings.
+Characters with the 8th bit set are written as M-<character>, and
+are referred to as
+.I metafied
+characters.
+The printable ASCII characters not mentioned in the list of emacs
+standard bindings are bound to the
+.I self\-insert
+function, which just inserts the given character into the input line.
+In vi insertion mode, all characters not specifically mentioned are
+bound to
+.IR self\-insert .
+Characters assigned to signal generation by
+.IR stty (1)
+or the terminal driver, such as C-Z or C-C,
+retain that function.
+Upper and lower case
+.I metafied
+characters are bound to the same function in the emacs mode
+meta keymap.
+The remaining characters are unbound, which causes readline
+to ring the bell (subject to the setting of the
+.B bell\-style
+variable).
+.SS Emacs Mode
+.RS +.6i
+.nf
+.ta 2.5i
+.sp
+Emacs Standard bindings
+.sp
+"C-A"  ->  beginning-of-line
+"C-B"  ->  backward-char
+"C-D"  ->  delete-char
+"C-E"  ->  end-of-line
+"C-F"  ->  forward-char
+"C-G"  ->  abort
+"C-H"  ->  backward-delete-char
+"C-I"  ->  complete
+"C-J"  ->  accept-line
+"C-K"  ->  kill-line
+"C-L"  ->  clear-screen
+"C-M"  ->  accept-line
+"C-N"  ->  next-history
+"C-P"  ->  previous-history
+"C-Q"  ->  quoted-insert
+"C-R"  ->  reverse-search-history
+"C-S"  ->  forward-search-history
+"C-T"  ->  transpose-chars
+"C-U"  ->  unix-line-discard
+"C-V"  ->  quoted-insert
+"C-W"  ->  unix-word-rubout
+"C-Y"  ->  yank
+"C-_"  ->  undo
+"\^ " to "/"   ->  self-insert
+"0"  to "9"    ->  self-insert
+":"  to "~"    ->  self-insert
+"C-?"  ->  backward-delete-char
+.PP
+Emacs Meta bindings
+.sp
+"M-C-H"        ->  backward-kill-word
+"M-C-I"        ->  tab-insert
+"M-C-J"        ->  vi-editing-mode
+"M-C-M"        ->  vi-editing-mode
+"M-C-R"        ->  revert-line
+"M-C-Y"        ->  yank-nth-arg
+"M-C-["        ->  complete
+"M-&"  ->  tilde-expand
+"M--"  ->  digit-argument
+"M-0"  ->  digit-argument
+"M-1"  ->  digit-argument
+"M-2"  ->  digit-argument
+"M-3"  ->  digit-argument
+"M-4"  ->  digit-argument
+"M-5"  ->  digit-argument
+"M-6"  ->  digit-argument
+"M-7"  ->  digit-argument
+"M-8"  ->  digit-argument
+"M-9"  ->  digit-argument
+"M-<"  ->  beginning-of-history
+"M->"  ->  end-of-history
+"M-?"  ->  possible-completions
+"M-B"  ->  backward-word
+"M-C"  ->  capitalize-word
+"M-D"  ->  kill-word
+"M-F"  ->  forward-word
+"M-L"  ->  downcase-word
+"M-N"  ->  non-incremental-forward-search-history
+"M-O"  ->  arrow-key-prefix
+"M-P"  ->  non-incremental-reverse-search-history
+"M-R"  ->  revert-line
+"M-T"  ->  transpose-words
+"M-U"  ->  upcase-word
+"M-Y"  ->  yank-pop
+"M-C-Y"        ->  yank-nth-arg
+"M-C-?"        ->  backward-delete-word
+.PP
+Emacs Control-X bindings
+.sp
+"C-XC-G"       ->  abort
+"C-XC-R"       ->  re-read-init-file
+"C-XC-U"       ->  undo
+"C-X(" ->  start-kbd-macro
+"C-X)" ->  end-kbd-macro
+"C-Xe" ->  call-last-kbd-macro
+"C-XC-?"       ->  backward-kill-line
+.sp
+.RE
+.SS VI Mode bindings
+.RS +.6i
+.nf
+.ta 2.5i
+.sp
+.PP
+VI Insert Mode functions
+.sp
+"C-D"  ->  vi-eof-maybe
+"C-H"  ->  backward-delete-char
+"C-I"  ->  complete
+"C-J"  ->  accept-line
+"C-K"  ->  kill-line
+"C-L"  ->  clear-screen
+"C-M"  ->  accept-line
+"C-N"  ->  next-history
+"C-P"  ->  previous-history
+"C-Q"  ->  quoted-insert
+"C-R"  ->  reverse-search-history
+"C-S"  ->  forward-search-history
+"C-T"  ->  transpose-chars
+"C-U"  ->  unix-line-discard
+"C-V"  ->  quoted-insert
+"C-W"  ->  unix-word-rubout
+"C-Y"  ->  yank
+"C-["  ->  vi-movement-mode
+"\^ " to "~"   ->  self-insert
+"C-?"  ->  backward-delete-char
+.PP
+VI Command Mode functions
+.sp
+"C-D"  ->  vi-eof-maybe
+"C-E"  ->  emacs-editing-mode
+"C-G"  ->  abort
+"C-H"  ->  backward-char
+"C-J"  ->  accept-line
+"C-K"  ->  kill-line
+"C-L"  ->  clear-screen
+"C-M"  ->  accept-line
+"C-N"  ->  next-history
+"C-P"  ->  previous-history
+"C-Q"  ->  quoted-insert
+"C-R"  ->  reverse-search-history
+"C-S"  ->  forward-search-history
+"C-T"  ->  transpose-chars
+"C-U"  ->  unix-line-discard
+"C-V"  ->  quoted-insert
+"C-W"  ->  unix-word-rubout
+"C-Y"  ->  yank
+"C-["  ->  abort
+"\^ "  ->  forward-char
+"#"    ->  vi-comment
+"$"    ->  end-of-line
+"%"    ->  vi-match
+"&"    ->  vi-tilde-expand
+"*"    ->  vi-complete
+"+"    ->  down-history
+","    ->  vi-char-search
+"-"    ->  previous-history
+"."    ->  vi-redo
+"/"    ->  vi-search
+"0"    ->  beginning-of-line
+"1" to "9"     ->  vi-arg-digit
+";"    ->  vi-char-search
+"="    ->  vi-complete
+"?"    ->  vi-search
+"@"    ->  is undefined
+"A"    ->  vi-append-eol
+"B"    ->  vi-prev-word
+"C"    ->  vi-change-to
+"D"    ->  vi-delete-to
+"E"    ->  vi-end-word
+"F"    ->  vi-char-search
+"I"    ->  vi-insert-beg
+"N"    ->  vi-search-again
+"P"    ->  vi-put
+"R"    ->  vi-replace
+"S"    ->  vi-subst
+"T"    ->  vi-char-search
+"U"    ->  revert-line
+"W"    ->  vi-next-word
+"X"    ->  backward-delete-char
+"Y"    ->  vi-yank-to
+"\e"   ->  vi-complete
+"^"    ->  vi-first-print
+"_"    ->  vi-yank-arg
+"a"    ->  vi-append-mode
+"b"    ->  vi-prev-word
+"c"    ->  vi-change-to
+"d"    ->  vi-delete-to
+"e"    ->  vi-end-word
+"f"    ->  vi-char-search
+"h"    ->  backward-char
+"i"    ->  vi-insertion-mode
+"j"    ->  next-history
+"k"    ->  prev-history
+"l"    ->  forward-char
+"n"    ->  vi-search-again
+"r"    ->  vi-change-char
+"s"    ->  vi-subst
+"t"    ->  vi-char-search
+"u"    ->  undo
+"w"    ->  vi-next-word
+"x"    ->  vi-delete
+"y"    ->  vi-yank-to
+"|"    ->  vi-column
+"~"    ->  vi-change-case
+.RE
+.SH "SEE ALSO"
+.PD 0
+.TP
+\fIThe Gnu Readline Library\fP, Brian Fox and Chet Ramey
+.TP
+\fIThe Gnu History Library\fP, Brian Fox and Chet Ramey
+.TP
+\fIbash\fP(1)
+.PD
+.SH FILES
+.PD 0
+.TP
+.FN ~/.inputrc
+Individual \fBreadline\fP initialization file
+.PD
+.SH AUTHORS
+.RS
+Brian Fox, Free Software Foundation (primary author)
+.br
+bfox@ai.MIT.Edu
+.PP
+Chet Ramey, Case Western Reserve University
+.br
+chet@ins.CWRU.Edu
+.SH BUG REPORTS
+If you find a bug in
+.B readline,
+you should report it.  But first, you should
+make sure that it really is a bug, and that it appears in the latest
+version of the
+.B readline
+library that you have.
+.PP
+Once you have determined that a bug actually exists, mail a
+bug report to \fIbash\-maintainers\fP@\fIprep.ai.MIT.Edu\fP.
+If you have a fix, you are welcome to mail that
+as well!  Suggestions and `philosophical' bug reports may be mailed
+to \fPbug-bash\fP@\fIprep.ai.MIT.Edu\fP or posted to the Usenet
+newsgroup
+.BR gnu.bash.bug .
+.PP
+Comments and bug reports concerning
+this manual page should be directed to
+.IR chet@ins.CWRU.Edu .
+.SH BUGS
+.PP
+It's too big and too slow.
diff --git a/documentation/readline.ps b/documentation/readline.ps
new file mode 100644 (file)
index 0000000..5e004b1
--- /dev/null
@@ -0,0 +1,1052 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 12
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Times-Italic@0 ENC0/Times-Italic RE
+/Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 342.2(READLINE\(3\) READLINE\(3\))72 48 R/F1 9
+/Times-Bold@0 SF -.18(NA)72 84 S(ME).18 E F0
+(readline \255 get a line from a user with editing)108 96 Q F1(SYNOPSIS)72
+112.8 Q/F2 10/Times-Bold@0 SF(#include <r)108 124.8 Q(eadline.h>)-.18 E
+(#include <history)108 136.8 Q(.h>)-.7 E(typedef int Function \(\);)108 153.6 Q
+(char *r)108 170.4 Q(eadline \(pr)-.18 E(ompt\))-.18 E(char *pr)108 182.4 Q
+(ompt;)-.18 E(int rl_add_defun \(name, function, k)108 199.2 Q(ey\))-.1 E
+(char *name;)108 211.2 Q(Function *function;)108 223.2 Q(int k)108 235.2 Q(ey;)
+-.1 E(int rl_bind_k)108 252 Q(ey \(k)-.1 E(ey)-.1 E 2.5(,f)-.55 G(unction\))
+202.26 252 Q(int k)108 264 Q(ey;)-.1 E(Function *function;)108 276 Q
+(int rl_unbind_k)108 292.8 Q(ey \(k)-.1 E(ey\))-.1 E(int k)108 304.8 Q(ey;)-.1
+E(int rl_bind_k)108 321.6 Q(ey_in_map \(k)-.1 E(ey)-.1 E 2.5(,f)-.55 G
+(unction, k)239.49 321.6 Q(eymap\))-.1 E(int k)108 333.6 Q(ey;)-.1 E
+(Function *function;)108 345.6 Q -.25(Ke)108 357.6 S(ymap k).25 E(eymap;)-.1 E
+(int rl_unbind_k)108 374.4 Q(ey_in_map \(k)-.1 E(ey)-.1 E 2.5(,k)-.55 G
+(eymap\))252.74 374.4 Q(int k)108 386.4 Q(ey;)-.1 E -.25(Ke)108 398.4 S(ymap k)
+.25 E(eymap;)-.1 E(int rl_macr)108 415.2 Q(o_bind \(k)-.18 E(eyseq, macr)-.1 E
+(o, k)-.18 E(eymap\))-.1 E(char *k)108 427.2 Q(eyseq, *macr)-.1 E(o;)-.18 E
+-.25(Ke)108 439.2 S(ymap k).25 E(eymap;)-.1 E(int rl_v)108 456 Q
+(ariable_bind \(v)-.1 E(ariable, v)-.1 E(alue\))-.1 E(char *v)108 468 Q
+(ariable, *v)-.1 E(alue;)-.1 E(int rl_parse_and_bind \(line\))108 484.8 Q
+(char *line;)108 496.8 Q(int rl_translate_k)108 513.6 Q(eyseq \(k)-.1 E
+(eyseq, array)-.1 E 2.5(,l)-.55 G(en\))276.68 513.6 Q(char *k)108 525.6 Q
+(eyseq, *array;)-.1 E(int *len;)108 537.6 Q
+(Function *rl_named_function \(command\))108 554.4 Q(char *command;)108 566.4 Q
+(Function *rl_function_of_k)108 583.2 Q(eyseq \(k)-.1 E(eyseq, k)-.1 E
+(eymap, type\))-.1 E(char *k)108 595.2 Q(eyseq;)-.1 E -.25(Ke)108 607.2 S
+(ymap k).25 E(eymap;)-.1 E(int *type;)108 619.2 Q(char **rl_in)108 636 Q -.1
+(vo)-.4 G(king_k).1 E(eyseqs \(function\))-.1 E(Function *function;)108 648 Q
+(char **rl_in)108 664.8 Q -.1(vo)-.4 G(king_k).1 E(eyseqs_in_map \(function, k)
+-.1 E(eymap\))-.1 E(Function *function;)108 676.8 Q -.25(Ke)108 688.8 S(ymap k)
+.25 E(eymap;)-.1 E -.1(vo)108 705.6 S(id rl_function_dumper \(r).1 E(eadable\))
+-.18 E(int r)108 717.6 Q(eadable;)-.18 E F0 184.005(GNU 1994)72 768 R(July 26)
+2.5 E(1)535 768 Q EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 342.2(READLINE\(3\) READLINE\(3\))72 48 R/F1 10
+/Times-Bold@0 SF(char **rl_funmap_names \(\))108 84 Q/F2 9/Times-Bold@0 SF
+(COPYRIGHT)72 100.8 Q F0(Readline is Cop)108 112.8 Q
+(yright \251 1989, 1991 by the Free Softw)-.1 E(are F)-.1 E(oundation, Inc.)
+-.15 E F2(DESCRIPTION)72 129.6 Q F1 -.18(re)108 141.6 S(adline).18 E F0 .49
+(will read a line from the terminal and return it, using)2.99 F F1(pr)2.99 E
+(ompt)-.18 E F0 .49(as a prompt.)2.99 F(If)5.49 E F1(pr)2.99 E(ompt)-.18 E F0
+.49(is null, no)2.99 F 1.066(prompt is issued.)108 153.6 R 1.066
+(The line returned is allocated with)6.066 F/F3 10/Times-Italic@0 SF(malloc)
+3.566 E F0 1.067(\(3\), so the caller must free it when \214nished.).31 F
+(The line returned has the \214nal ne)108 165.6 Q(wline remo)-.25 E -.15(ve)
+-.15 G(d, so only the te).15 E(xt of the line remains.)-.15 E F1 -.18(re)108
+182.4 S(adline).18 E F0(of)3.79 E 1.29
+(fers editing capabilities while the user is entering the line.)-.25 F 1.289
+(By def)6.289 F 1.289(ault, the line editing com-)-.1 F
+(mands are similar to those of emacs.)108 194.4 Q 2.5(Av)5 G
+(i\255style line editing interf)273.53 194.4 Q(ace is also a)-.1 E -.25(va)-.2
+G(ilable.).25 E 6.74(In the follo)108 211.2 R 6.74(wing descriptions,)-.25 F F1
+-.1(ke)9.24 G(ymap).1 E F0 6.74(can be one of)9.24 F F3(emacs_k)9.24 E -.3(ey)
+-.1 G 6.74(map, emacs_meta_k).3 F -.3(ey)-.1 G(map,).3 E(emacs_ctlx_k)108 223.2
+Q -.3(ey)-.1 G(map, vi_insertion_k).3 E -.3(ey)-.1 G(map, or vi_mo).3 E
+(vement_k)-.1 E -.3(ey)-.1 G(map).3 E F0(.)A F1(rl_add_defun)108 240 Q F0(mak)
+3.356 E(es)-.1 E F1(name)3.356 E F0 .856
+(appear as a bindable readline command, and mak)3.356 F(es)-.1 E F1(function)
+3.355 E F0 .855(be the function)3.355 F(called when that command is in)108 252
+Q -.2(vo)-.4 G -.1(ke).2 G 2.5(d. If).1 F F1 -.1(ke)2.5 G(y).1 E F0
+(is not \2551, it is bound to)2.5 E F1(function)2.5 E F0(in the current k)2.5 E
+-.15(ey)-.1 G(map.).15 E F1(rl_bind_k)108 268.8 Q(ey)-.1 E F0(causes)2.5 E F1
+-.1(ke)2.5 G(y).1 E F0(to in)2.5 E -.2(vo)-.4 G -.1(ke).2 G F1(function)2.6 E
+F0 5(.T)C(he binding is made in the current k)296.55 268.8 Q -.15(ey)-.1 G
+(map.).15 E F1(rl_unbind_k)108 285.6 Q(ey)-.1 E F0(remo)2.5 E -.15(ve)-.15 G
+2.5(st).15 G(he binding for)212.06 285.6 Q F1 -.1(ke)2.5 G(y).1 E F0
+(in the current k)2.5 E -.15(ey)-.1 G(map.).15 E F1(rl_bind_k)108 302.4 Q
+(ey_in_map)-.1 E F0(mak)2.5 E(es the)-.1 E F1 -.1(ke)2.5 G(y).1 E F0(entry in)
+2.5 E F1 -.1(ke)2.5 G(ymap).1 E F0(in)2.5 E -.2(vo)-.4 G -.1(ke).2 G F1
+(function)2.6 E F0(.)A F1(rl_unbind_k)108 319.2 Q(ey_in_map)-.1 E F0(remo)2.5 E
+-.15(ve)-.15 G 2.5(st).15 G(he binding for)249.29 319.2 Q F1 -.1(ke)2.5 G(y).1
+E F0(in k)2.5 E -.15(ey)-.1 G(map).15 E F1 -.1(ke)2.5 G(ymap).1 E F0(.)A F1
+(rl_macr)108 336 Q(o_bind)-.18 E F0(mak)2.5 E(es)-.1 E F1 -.1(ke)2.5 G(yseq).1
+E F0(insert the string)2.5 E F1(macr)2.5 E(o)-.18 E F0 5(.T)C
+(he binding is performed in)338.81 336 Q F1 -.1(ke)2.5 G(ymap).1 E F0(.)A F1
+(rl_v)108 352.8 Q(ariable_bind)-.1 E F0(sets the v)2.5 E
+(alue of the readline v)-.25 E(ariable)-.25 E F1 -.1(va)2.5 G(riable).1 E F0
+(to)2.5 E F1 -.1(va)2.5 G(lue).1 E F0(.)A F1(rl_parse_and_bind)108 369.6 Q F0
+(tak)2.806 E .307(es as an ar)-.1 F .307
+(gument a line of the same form as the readline startup \214le \(see)-.18 F F2
+(INITIAL-)2.807 E(IZA)108 381.6 Q(TION FILE)-.855 E F0(belo)2.25 E(w\) and e)
+-.25 E -.15(xe)-.15 G(cutes the commands therein.).15 E F1(rl_translate_k)108
+398.4 Q(eyseq)-.1 E F0(con)2.975 E -.15(ve)-.4 G(rts).15 E F1 -.1(ke)2.975 G
+(yseq).1 E F0 .475(into a ne)2.975 F 2.975(ws)-.25 G .475
+(tring, storing the result in)312.05 398.4 R F1(array)2.975 E F0 5.475(.T)C
+.475(his translates control)456.28 398.4 R .337(and meta pre\214x)108 410.4 R
+.337(es and the readline character escape sequences \(see)-.15 F F2 -.225(Ke)
+2.837 G 2.587(yB).225 G(indings)404.423 410.4 Q F0(belo)2.588 E 2.838(w\). The)
+-.25 F .338(length of the)2.838 F(translated sequence is returned in)108 422.4
+Q F1(*len)2.5 E F0(.)A F1(rl_named_function)108 439.2 Q F0 2.974
+(returns the function that is e)5.474 F -.15(xe)-.15 G 2.973
+(cuted when the readline command).15 F F1(command)5.473 E F0(is)5.473 E(in)108
+451.2 Q -.2(vo)-.4 G -.1(ke).2 G(d.).1 E F1(rl_function_of_k)108 468 Q(eyseq)
+-.1 E F0 .801(returns the function that is e)3.301 F -.15(xe)-.15 G .801
+(cuted when).15 F F1 -.1(ke)3.301 G(yseq).1 E F0 .801(is read and)3.301 F F1
+-.1(ke)3.302 G(ymap).1 E F0 .802(is the cur)3.302 F(-)-.2 E .267(rent k)108 480
+R -.15(ey)-.1 G(map.).15 E F1(type)5.267 E F0 .267
+(is set to indicate whether the return v)2.767 F .266
+(alue corresponds to a function, macro, or auxiliary)-.25 F -.1(ke)108 492 S
+(ymap.)-.05 E F1(rl_in)108 508.8 Q -.1(vo)-.4 G(king_k).1 E(eyseqs)-.1 E F0
+(returns all of the k)2.5 E .3 -.15(ey s)-.1 H(equences in the current k).15 E
+-.15(ey)-.1 G(map that in).15 E -.2(vo)-.4 G -.1(ke).2 G F1(function)2.6 E F0
+(.)A F1(rl_in)108 525.6 Q -.1(vo)-.4 G(king_k).1 E(eyseqs_in_map)-.1 E F0
+(returns all of the k)2.5 E .3 -.15(ey s)-.1 H(equences in).15 E F1 -.1(ke)2.5
+G(ymap).1 E F0(that in)2.5 E -.2(vo)-.4 G -.1(ke).2 G F1(function)2.6 E F0(.)A
+F1(rl_function_dumper)108 542.4 Q F0 .117(prints all of the readline functions\
+ and their bindings to the readline output stream.)2.617 F(If)5.118 E F1 -.18
+(re)108 554.4 S(adable).18 E F0(is non\255zero, the output is formattted so th\
+at it can be read back in to restore the bindings.)2.5 E F1(rl_funmap_names)108
+571.2 Q F0(returns an array of all kno)2.5 E
+(wn readline bindable function names.)-.25 E(The array is sorted.)5 E F2
+(RETURN V)72 588 Q(ALUE)-1.215 E F1 -.18(re)108 600 S(adline).18 E F0 1.09
+(returns the te)3.59 F 1.09(xt of the line read.)-.15 F 3.589(Ab)6.09 G 1.089
+(lank line returns the empty string.)299.949 600 R(If)6.089 E F1(EOF)3.589 E F0
+1.089(is encountered)3.589 F .283(while reading a line, and the line is empty)
+108 612 R(,)-.65 E F1(NULL)2.783 E F0 .283(is returned.)2.783 F .283(If an)
+5.283 F F1(EOF)2.783 E F0 .283(is read with a non\255empty line, it)2.783 F
+(is treated as a ne)108 624 Q(wline.)-.25 E(Unless otherwise stated, the other\
+ functions return 0 on success and non\255zero on f)108 640.8 Q(ailure.)-.1 E
+F2(NO)72 657.6 Q -.81(TA)-.36 G(TION)-.045 E F0 .037
+(An emacs\255style notation is used to denote k)108 669.6 R -.15(ey)-.1 G
+(strok).15 E 2.536(es. Control)-.1 F -.1(ke)2.536 G .036
+(ys are denoted by C\255)-.05 F F3 -.1(ke)C(y)-.2 E F0 2.536(,e)C .036
+(.g., C\255n means)479.568 669.6 R 2.625(Control\255N. Similarly)108 681.6 R(,)
+-.65 E F3(meta)2.625 E F0 -.1(ke)2.625 G .125(ys are denoted by M\255)-.05 F F3
+-.1(ke)C(y)-.2 E F0 2.625(,s)C 2.625(oM)341.73 681.6 S .125
+(\255x means Meta\255X.)358.245 681.6 R .126(\(On k)5.126 F -.15(ey)-.1 G .126
+(boards without a).15 F F3(meta)108 693.6 Q F0 -.1(ke)3.309 G 2.109 -.65(y, M)
+-.05 H<ad>.65 E F3(x)A F0 .809(means ESC)3.309 F F3(x)3.309 E F0 3.309(,i)C
+.809(.e., press the Escape k)235.914 693.6 R 1.108 -.15(ey t)-.1 H .808
+(hen the).15 F F3(x)3.308 E F0 -.1(ke)3.308 G 4.608 -.65(y. T)-.05 H .808
+(his mak).65 F .808(es ESC the)-.1 F F3 .808(meta pr)3.308 F(e\214x)-.37 E F0
+(.)A .48(The combination M\255C\255)108 705.6 R F3(x)A F0 .48
+(means ESC\255Control\255)2.98 F F3(x)A F0 2.98(,o)C 2.98(rp)317.4 705.6 S .48
+(ress the Escape k)328.71 705.6 R .78 -.15(ey t)-.1 H .48
+(hen hold the Control k).15 F .78 -.15(ey w)-.1 H(hile).15 E(pressing the)108
+717.6 Q F3(x)2.5 E F0 -.1(ke)2.5 G -.65(y.)-.05 G(\)).65 E 184.005(GNU 1994)72
+768 R(July 26)2.5 E(2)535 768 Q EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 342.2(READLINE\(3\) READLINE\(3\))72 48 R .62
+(Readline commands may be gi)108 84 R -.15(ve)-.25 G 3.119(nn).15 G(umeric)
+255.959 84 Q/F1 10/Times-Italic@0 SF(ar)3.119 E(guments)-.37 E F0 3.119(,w).27
+G .619(hich normally act as a repeat count.)341.807 84 R(Sometimes,)5.619 E(ho)
+108 96 Q(we)-.25 E -.15(ve)-.25 G 1.418 -.4(r, i).15 H 3.118(ti).4 G 3.119(st)
+158.456 96 S .619(he sign of the ar)168.245 96 R .619
+(gument that is signi\214cant.)-.18 F -.15(Pa)5.619 G .619(ssing a ne).15 F
+-.05(ga)-.15 G(ti).05 E .919 -.15(ve a)-.25 H -.18(rg).15 G .619
+(ument to a command that).18 F 1.019(acts in the forw)108 108 R 1.018
+(ard direction \(e.g.,)-.1 F/F2 10/Times-Bold@0 SF(kill\255line)3.518 E F0
+3.518(\)c)C 1.018(auses that command to act in a backw)298.478 108 R 1.018
+(ard direction.)-.1 F(Com-)6.018 E(mands whose beha)108 120 Q(vior with ar)-.2
+E(guments de)-.18 E(viates from this are noted.)-.25 E .811
+(When a command is described as)108 136.8 R F1(killing)3.311 E F0(te)3.311 E
+.811(xt, the te)-.15 F .811(xt deleted is sa)-.15 F -.15(ve)-.2 G 3.311(df).15
+G .812(or possible future retrie)403.403 136.8 R -.25(va)-.25 G 3.312(l\().25 G
+F1(yank-)517.79 136.8 Q(ing)108 148.8 Q F0 3.439(\). The)B .939(killed te)3.439
+F .939(xt is sa)-.15 F -.15(ve)-.2 G 3.439(di).15 G 3.438(na)234.794 148.8 S F1
+(kill\255ring)A F0 5.938(.C)C(onsecuti)302.418 148.8 Q 1.238 -.15(ve k)-.25 H
+.938(ills cause the te).15 F .938(xt to be accumulated into one)-.15 F .331
+(unit, which can be yank)108 160.8 R .331(ed all at once.)-.1 F .331
+(Commands which do not kill te)5.331 F .331(xt separate the chunks of te)-.15 F
+.331(xt on the)-.15 F(kill\255ring.)108 172.8 Q/F3 9/Times-Bold@0 SF
+(INITIALIZA)72 189.6 Q(TION FILE)-.855 E F0 .827
+(Readline is customized by putting commands in an initialization \214le.)108
+201.6 R .827(The name of this \214le is tak)5.827 F .827(en from)-.1 F 1.041
+(the v)108 213.6 R 1.041(alue of the)-.25 F F2(INPUTRC)3.541 E F0 -.25(va)3.542
+G 3.542(riable. If).25 F 1.042(that v)3.542 F 1.042(ariable is unset, the def)
+-.25 F 1.042(ault is)-.1 F F1(~/.inputr)3.542 E(c)-.37 E F0 6.042(.W).31 G
+1.042(hen a program)480.156 213.6 R 1.159
+(which uses the readline library starts up, the init \214le is read, and the k)
+108 225.6 R 1.458 -.15(ey b)-.1 H 1.158(indings and v).15 F 1.158
+(ariables are set.)-.25 F .028(There are only a fe)108 237.6 R 2.528(wb)-.25 G
+.028(asic constructs allo)198.13 237.6 R .028(wed in the readline init \214le.)
+-.25 F .029(Blank lines are ignored.)5.029 F .029(Lines be)5.029 F(gin-)-.15 E
+.554(ning with a)108 249.6 R F2(#)3.054 E F0 .554(are comments.)3.054 F .554
+(Lines be)5.554 F .554(ginning with a)-.15 F F2($)3.054 E F0 .554
+(indicate conditional constructs.)3.054 F .553(Other lines denote)5.553 F -.1
+(ke)108 261.6 S 2.986(yb)-.05 G .486(indings and v)130.176 261.6 R .487
+(ariable settings.)-.25 F .487(Each program using this library may add its o)
+5.487 F .487(wn commands and bind-)-.25 F(ings.)108 273.6 Q -.15(Fo)108 290.4 S
+2.5(re).15 G(xample, placing)128.53 290.4 Q(M\255Control\255u: uni)144 307.2 Q
+-.15(ve)-.25 G(rsal\255ar).15 E(gument)-.18 E(or)108 319.2 Q
+(C\255Meta\255u: uni)144 331.2 Q -.15(ve)-.25 G(rsal\255ar).15 E(gument)-.18 E
+(into the)108 343.2 Q F1(~/.inputr)4.166 E(c)-.37 E F0 -.1(wo)4.166 G(uld mak)
+.1 E 2.5(eM)-.1 G(\255C\255u e)244.092 343.2 Q -.15(xe)-.15 G
+(cute the readline command).15 E F1(univer)2.5 E(sal\255ar)-.1 E(gument)-.37 E
+F0(.).68 E .978(The follo)108 360 R .978
+(wing symbolic character names are recognized while processing k)-.25 F 1.277
+-.15(ey b)-.1 H(indings:).15 E F1 -.4(RU)3.477 G(BOUT).4 E F0(,)1.27 E F1(DEL)
+3.477 E F0(,).53 E F1(ESC)108 372 Q F0(,).72 E F1(LFD)2.984 E F0(,).28 E F1
+(NEWLINE)2.984 E F0(,).73 E F1(RET)2.984 E F0(,)1.27 E F1(RETURN)2.984 E F0(,)
+1.1 E F1(SPC)2.984 E F0(,).72 E F1(SP)2.984 E -.3(AC)-.9 G(E).3 E F0 2.984(,a)
+.73 G(nd)337.968 372 Q F1 -.5(TA)2.984 G(B).5 E F0 5.484(.I).27 G 2.984(na)
+379.816 372 S .485(ddition to command names, readline)392.24 372 R(allo)108 384
+Q(ws k)-.25 E -.15(ey)-.1 G 2.5(st).15 G 2.5(ob)159.72 384 S 2.5(eb)172.22 384
+S(ound to a string that is inserted when the k)184.16 384 Q .3 -.15(ey i)-.1 H
+2.5(sp).15 G(ressed \(a)379.73 384 Q F1(macr)2.5 E(o)-.45 E F0(\).)A F2 -.25
+(Ke)87 405.6 S 2.5(yB).25 G(indings)113.14 405.6 Q F0 .724
+(The syntax for controlling k)108 417.6 R 1.024 -.15(ey b)-.1 H .724
+(indings in the).15 F F1(~/.inputr)3.224 E(c)-.37 E F0 .724(\214le is simple.)
+3.224 F .723(All that is required is the name of)5.724 F .938
+(the command or the te)108 429.6 R .938(xt of a macro and a k)-.15 F 1.238 -.15
+(ey s)-.1 H .938(equence to which it should be bound. The name may be).15 F
+.695(speci\214ed in one of tw)108 441.6 R 3.195(ow)-.1 G .695
+(ays: as a symbolic k)212.095 441.6 R .995 -.15(ey n)-.1 H .695
+(ame, possibly with).15 F F1(Meta\255)3.195 E F0(or)3.195 E F1(Contr)3.194 E
+(ol\255)-.45 E F0(pre\214x)3.194 E .694(es, or as a)-.15 F -.1(ke)108 453.6 S
+4.143(ys)-.05 G 4.143(equence. When)130.223 453.6 R 1.643(using the form)4.143
+F F2 -.1(ke)4.143 G(yname).1 E F0(:)A F1(function-name)A F0(or)4.143 E F1(macr)
+4.143 E(o)-.45 E F0(,)A F1 -.1(ke)4.143 G(yname)-.2 E F0 1.644
+(is the name of a k)4.143 F -.15(ey)-.1 G(spelled out in English.)108 465.6 Q
+-.15(Fo)5 G 2.5(re).15 G(xample:)222.98 465.6 Q(Control\255u: uni)144 489.6 Q
+-.15(ve)-.25 G(rsal\255ar).15 E(gument)-.18 E(Meta\255Rubout: backw)144 501.6 Q
+(ard\255kill\255w)-.1 E(ord)-.1 E(Control\255o: ">&output")144 513.6 Q .229
+(In the abo)108 530.4 R .529 -.15(ve ex)-.15 H(ample,).15 E F1(C\255u)2.729 E
+F0 .229(is bound to the function)2.729 F F2(uni)2.729 E -.1(ve)-.1 G
+(rsal\255ar).1 E(gument)-.1 E F0(,)A F1(M-DEL)2.729 E F0 .228
+(is bound to the function)2.729 F F2(backward\255kill\255w)108 542.4 Q(ord)-.1
+E F0 3.837(,a)C(nd)208.977 542.4 Q F1(C\255o)3.837 E F0 1.337
+(is bound to run the macro e)3.837 F 1.337
+(xpressed on the right hand side \(that is, to)-.15 F(insert the te)108 554.4 Q
+(xt)-.15 E F1(>&output)2.5 E F0(into the line\).)2.5 E .115
+(In the second form,)108 571.2 R F2("k)2.615 E(eyseq")-.1 E F0(:)A F1
+(function\255name)A F0(or)2.615 E F1(macr)2.615 E(o)-.45 E F0(,)A F2 -.1(ke)
+2.615 G(yseq).1 E F0(dif)2.615 E .115(fers from)-.25 F F2 -.1(ke)2.615 G(yname)
+.1 E F0(abo)2.615 E .415 -.15(ve i)-.15 H 2.615(nt).15 G .115(hat strings)
+498.495 571.2 R 1.284(denoting an entire k)108 583.2 R 1.584 -.15(ey s)-.1 H
+1.284(equence may be speci\214ed by placing the sequence within double quotes.)
+.15 F(Some)6.284 E(GNU Emacs style k)108 595.2 Q .3 -.15(ey e)-.1 H
+(scapes can be used, as in the follo).15 E(wing e)-.25 E(xample.)-.15 E
+("\\C\255u": uni)144 619.2 Q -.15(ve)-.25 G(rsal\255ar).15 E(gument)-.18 E
+("\\C\255x\\C\255r": re\255read\255init\255\214le)144 631.2 Q
+("\\e[11~": "Function K)144 643.2 Q .3 -.15(ey 1)-.25 H(").15 E .238(In this e)
+108 660 R(xample,)-.15 E F1(C-u)2.738 E F0 .238(is ag)2.738 F .238
+(ain bound to the function)-.05 F F2(uni)2.738 E -.1(ve)-.1 G(rsal\255ar).1 E
+(gument)-.1 E F0(.)A F1 .237(C-x C-r)5.238 F F0 .237(is bound to the function)
+2.737 F F2 -.18(re)108 672 S<ad72>.18 E(ead\255init\255\214le)-.18 E F0 3.909
+(,a)C(nd)191.139 672 Q F1 1.409(ESC [ 1 1 ~)3.909 F F0 1.409
+(is bound to insert the te)3.909 F(xt)-.15 E F2 1.41(Function K)3.91 F 1.41
+(ey 1)-.25 F F0 6.41(.T)C 1.41(he full set of escape)454.94 672 R(sequences is)
+108 684 Q F2(\\C-)144 700.8 Q F0(control pre\214x)180 700.8 Q F2(\\M-)144 717.6
+Q F0(meta pre\214x)180 717.6 Q 184.005(GNU 1994)72 768 R(July 26)2.5 E(3)535
+768 Q EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 342.2(READLINE\(3\) READLINE\(3\))72 48 R/F1 10
+/Times-Bold@0 SF(\\e)144 84 Q F0(an escape character)180 84 Q F1(\\\\)144 100.8
+Q F0(backslash)180 100.8 Q F1(\\")144 117.6 Q F0(literal ")180 117.6 Q F1(\\')
+144 134.4 Q F0(literal ')180 134.4 Q .74(When entering the te)108 151.2 R .74(\
+xt of a macro, single or double quotes should be used to indicate a macro de\
+\214nition.)-.15 F 1.226(Unquoted te)108 163.2 R 1.226
+(xt is assumed to be a function name.)-.15 F 1.227(Backslash will quote an)
+6.226 F 3.727(yc)-.15 G 1.227(haracter in the macro te)430.552 163.2 R(xt,)-.15
+E(including " and '.)108 175.2 Q F1(Bash)108 192 Q F0(allo)2.93 E .43
+(ws the current readline k)-.25 F .73 -.15(ey b)-.1 H .429
+(indings to be displayed or modi\214ed with the).15 F F1(bind)2.929 E F0 -.2
+(bu)2.929 G .429(iltin command.).2 F 1.095
+(The editing mode may be switched during interacti)108 204 R 1.395 -.15(ve u)
+-.25 H 1.095(se by using the).15 F F1<ad6f>3.595 E F0 1.095(option to the)3.595
+F F1(set)3.595 E F0 -.2(bu)3.595 G 1.095(iltin com-).2 F 3.097(mand. Other)108
+216 R .597(programs using this library pro)3.097 F .597
+(vide similar mechanisms.)-.15 F(The)5.597 E/F2 10/Times-Italic@0 SF(inputr)
+3.097 E(c)-.37 E F0 .596(\214le may be edited and)3.096 F
+(re\255read if a program does not pro)108 228 Q(vide an)-.15 E 2.5(yo)-.15 G
+(ther means to incorporate ne)283.85 228 Q 2.5(wb)-.25 G(indings.)412.18 228 Q
+F1 -.92(Va)87 244.8 S(riables).92 E F0 .043(Readline has v)108 256.8 R .044
+(ariables that can be used to further customize its beha)-.25 F(vior)-.2 E
+5.044(.A)-.55 G -.25(va)413.896 256.8 S .044(riable may be set in the).25 F F2
+(inpu-)2.544 E(tr)108 268.8 Q(c)-.37 E F0(\214le with a statement of the form)
+2.5 E F1(set)144 285.6 Q F2(variable\255name value)2.5 E F0 .489
+(Except where noted, readline v)108 302.4 R .489(ariables can tak)-.25 F 2.989
+(et)-.1 G .489(he v)307.123 302.4 R(alues)-.25 E F1(On)2.989 E F0(or)2.989 E F1
+(Off)2.989 E F0 5.489(.T)C .489(he v)404.028 302.4 R .488
+(ariables and their def)-.25 F .488(ault v)-.1 F(al-)-.25 E(ues are:)108 314.4
+Q F1(horizontal\255scr)108 331.2 Q(oll\255mode \(Off\))-.18 E F0 .448
+(When set to)144 343.2 R F1(On)2.948 E F0 2.948(,m)C(ak)222.182 343.2 Q .448
+(es readline use a single line for display)-.1 F 2.948(,s)-.65 G .449
+(crolling the input horizontally on a)398.596 343.2 R 1.194(single screen line\
+ when it becomes longer than the screen width rather than wrapping to a ne)144
+355.2 R(w)-.25 E(line.)144 367.2 Q F1(editing\255mode \(emacs\))108 379.2 Q F0
+.252(Controls whether readline be)144 391.2 R .253(gins with a set of k)-.15 F
+.553 -.15(ey b)-.1 H .253(indings similar to).15 F F2(emacs)2.753 E F0(or)2.753
+E F2(vi)2.753 E F0(.)A F1(editing\255mode)5.253 E F0(can be set to either)144
+403.2 Q F1(emacs)2.5 E F0(or)2.5 E F1(vi)2.5 E F0(.)A F1
+(mark\255modi\214ed\255lines \(Off\))108 415.2 Q F0(If set to)144 427.2 Q F1
+(On)2.5 E F0 2.5(,h)C(istory lines that ha)200.39 427.2 Q .3 -.15(ve b)-.2 H
+(een modi\214ed are displayed with a preceding asterisk \().15 E F1(*)A F0(\).)
+A F1(bell\255style \(audible\))108 439.2 Q F0 .011
+(Controls what happens when readline w)144 451.2 R .011
+(ants to ring the terminal bell.)-.1 F .01(If set to)5.01 F F1(none)2.51 E F0
+2.51(,r)C .01(eadline ne)486.8 451.2 R -.15(ve)-.25 G(r).15 E .94
+(rings the bell.)144 463.2 R .94(If set to)5.94 F F1(visible)3.44 E F0 3.44(,r)
+C .94(eadline uses a visible bell if one is a)278.91 463.2 R -.25(va)-.2 G 3.44
+(ilable. If).25 F .94(set to)3.44 F F1(audible)3.44 E F0(,)A
+(readline attempts to ring the terminal')144 475.2 Q 2.5(sb)-.55 G(ell.)306.21
+475.2 Q F1(comment\255begin \(`)108 487.2 Q(`#')-.63 E('\))-.63 E F0
+(The string that is inserted in)144 499.2 Q F1(vi)2.5 E F0(mode when the)2.5 E
+F1(vi\255comment)2.5 E F0(command is e)2.5 E -.15(xe)-.15 G(cuted.).15 E F1
+(meta\255\215ag \(Off\))108 511.2 Q F0 .228(If set to)144 523.2 R F1(On)2.728 E
+F0 2.728(,r)C .227(eadline will enable eight-bit input \(that is, it will not \
+strip the high bit from the char)199.632 523.2 R(-)-.2 E(acters it reads\), re)
+144 535.2 Q -.05(ga)-.15 G(rdless of what the terminal claims it can support.)
+.05 E F1(con)108 547.2 Q -.1(ve)-.4 G(rt\255meta \(On\)).1 E F0 .612(If set to)
+144 559.2 R F1(On)3.112 E F0 3.112(,r)C .613(eadline will con)201.168 559.2 R
+-.15(ve)-.4 G .613(rt characters with the eighth bit set to an ASCII k).15 F
+.913 -.15(ey s)-.1 H .613(equence by).15 F 1.238
+(stripping the eighth bit and prepending an escape character \(in ef)144 571.2
+R 1.238(fect, using escape as the)-.25 F F2(meta)3.738 E(pr)144 583.2 Q(e\214x)
+-.37 E F0(\).)A F1(output\255meta \(Off\))108 595.2 Q F0 .506(If set to)144
+607.2 R F1(On)3.006 E F0 3.006(,r)C .507(eadline will display characters with \
+the eighth bit set directly rather than as a meta-)200.744 607.2 R(pre\214x)144
+619.2 Q(ed escape sequence.)-.15 E F1(completion\255query\255items \(100\))108
+631.2 Q F0 .53(This determines when the user is queried about vie)144 643.2 R
+.529(wing the number of possible completions gen-)-.25 F .56(erated by the)144
+655.2 R F1(possible\255completions)3.06 E F0 3.06(command. It)3.06 F .561
+(may be set to an)3.061 F 3.061(yi)-.15 G(nte)428.196 655.2 Q .561(ger v)-.15 F
+.561(alue greater than or)-.25 F .783(equal to zero.)144 667.2 R .783
+(If the number of possible completions is greater than or equal to the v)5.783
+F .782(alue of this)-.25 F -.25(va)144 679.2 S .237(riable, the user is ask).25
+F .237(ed whether or not he wishes to vie)-.1 F 2.737(wt)-.25 G .237
+(hem; otherwise the)389.254 679.2 R 2.737(ya)-.15 G .237(re simply listed)
+477.855 679.2 R(on the terminal.)144 691.2 Q F1 -.1(ke)108 703.2 S
+(ymap \(emacs\)).1 E F0 2.323(Set the current readline k)144 715.2 R -.15(ey)
+-.1 G 4.823(map. The).15 F 2.323(set of le)4.823 F -.05(ga)-.15 G 4.823(lk).05
+G -.15(ey)368.478 715.2 S 2.323(map names is).15 F F2 2.323
+(emacs, emacs-standar)4.823 F(d,)-.37 E .808(emacs-meta, emacs-ctlx, vi, vi-mo)
+144 727.2 R(ve)-.1 E 3.308(,v)-.1 G(i-command)300.862 727.2 Q F0 3.308(,a)C(nd)
+356.1 727.2 Q F2(vi-insert)3.308 E F0(.).68 E F2(vi)5.808 E F0 .808(is equi)
+3.308 F -.25(va)-.25 G .809(lent to).25 F F2(vi-command)3.309 E F0(;)A 184.005
+(GNU 1994)72 768 R(July 26)2.5 E(4)535 768 Q EP
+%%Page: 5 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 342.2(READLINE\(3\) READLINE\(3\))72 48 R/F1 10
+/Times-Italic@0 SF(emacs)144 84 Q F0 1.124(is equi)3.624 F -.25(va)-.25 G 1.124
+(lent to).25 F F1(emacs-standar)3.624 E(d)-.37 E F0 6.124(.T)C 1.124(he def)
+317.34 84 R 1.124(ault v)-.1 F 1.124(alue is)-.25 F F1(emacs)3.624 E F0 3.624
+(;t).27 G 1.124(he v)431.47 84 R 1.123(alue of)-.25 F/F2 10/Times-Bold@0 SF
+(editing\255mode)3.623 E F0(also af)144 96 Q(fects the def)-.25 E(ault k)-.1 E
+-.15(ey)-.1 G(map.).15 E F2(sho)108 108 Q(w\255all\255if\255ambiguous \(Off\))
+-.1 E F0 .477(This alters the def)144 120 R .477(ault beha)-.1 F .477
+(vior of the completion functions.)-.2 F .478(If set to)5.478 F F2(on)2.978 E
+F0 2.978(,w)C .478(ords which ha)450.326 120 R .778 -.15(ve m)-.2 H(ore).15 E
+1.264(than one possible completion cause the matches to be listed immediately \
+instead of ringing the)144 132 R(bell.)144 144 Q F2(expand\255tilde \(Off\))108
+156 Q F0(If set to)144 168 Q F2(on)2.5 E F0 2.5(,t)C(ilde e)195.39 168 Q
+(xpansion is performed when readline attempts w)-.15 E(ord completion.)-.1 E F2
+(Conditional Constructs)87 184.8 Q F0 .05(Readline implements a f)108 196.8 R
+.05(acility similar in spirit to the conditional compilation features of the C\
+ preprocessor)-.1 F 1.49(which allo)108 208.8 R 1.49(ws k)-.25 F 1.79 -.15
+(ey b)-.1 H 1.49(indings and v).15 F 1.49
+(ariable settings to be performed as the result of tests.)-.25 F 1.49
+(There are three)6.49 F(parser directi)108 220.8 Q -.15(ve)-.25 G 2.5(su).15 G
+(sed.)180.91 220.8 Q F2($if)108 237.6 Q F0(The)144 237.6 Q F2($if)2.962 E F0
+.462(construct allo)2.962 F .463
+(ws bindings to be made based on the editing mode, the terminal being used,)
+-.25 F .478(or the application using readline.)144 249.6 R .477(The te)5.477 F
+.477(xt of the test e)-.15 F .477(xtends to the end of the line; no characters)
+-.15 F(are required to isolate it.)144 261.6 Q F2(mode)144 278.4 Q F0(The)180
+278.4 Q F2(mode=)3.711 E F0 1.211(form of the)3.711 F F2($if)3.711 E F0
+(directi)3.711 E 1.511 -.15(ve i)-.25 H 3.711(su).15 G 1.211
+(sed to test whether readline is in emacs or vi)351.628 278.4 R 3.065
+(mode. This)180 290.4 R .565(may be used in conjunction with the)3.065 F F2
+.565(set k)3.065 F(eymap)-.1 E F0 .565(command, for instance, to)3.065 F .029
+(set bindings in the)180 302.4 R F1(emacs-standar)2.529 E(d)-.37 E F0(and)2.529
+E F1(emacs-ctlx)2.529 E F0 -.1(ke)2.529 G .029
+(ymaps only if readline is starting out)-.05 F(in emacs mode.)180 314.4 Q F2
+(term)144 331.2 Q F0(The)180 331.2 Q F2(term=)3.197 E F0 .696
+(form may be used to include terminal-speci\214c k)3.197 F .996 -.15(ey b)-.1 H
+.696(indings, perhaps to bind).15 F .654(the k)180 343.2 R .954 -.15(ey s)-.1 H
+.654(equences output by the terminal').15 F 3.154(sf)-.55 G .654(unction k)
+360.138 343.2 R -.15(ey)-.1 G 3.154(s. The).15 F -.1(wo)3.154 G .654
+(rd on the right side of).1 F(the)180 355.2 Q F2(=)3.004 E F0 .504
+(is tested ag)3.004 F .503
+(ainst the full name of the terminal and the portion of the terminal name)-.05
+F(before the \214rst)180 367.2 Q F2<ad>2.5 E F0 5(.T)C(his allo)260.13 367.2 Q
+(ws)-.25 E F1(sun)2.5 E F0(to match both)2.5 E F1(sun)2.5 E F0(and)2.5 E F1
+(sun\255cmd)2.5 E F0 2.5(,f).77 G(or instance.)456.28 367.2 Q F2(application)
+144 384 Q F0(The)180 396 Q F2(application)2.772 E F0 .272
+(construct is used to include application\255speci\214c settings.)2.772 F .272
+(Each program)5.272 F .114(using the readline library sets the)180 408 R F1
+.114(application name)2.614 F F0 2.614(,a)C .114
+(nd an initialization \214le can test for a)395.052 408 R .5(particular v)180
+420 R 3(alue. This)-.25 F .501(could be used to bind k)3 F .801 -.15(ey s)-.1 H
+.501(equences to functions useful for a spe-).15 F .397(ci\214c program.)180
+432 R -.15(Fo)5.397 G 2.896(ri).15 G .396(nstance, the follo)261.31 432 R .396
+(wing command adds a k)-.25 F .696 -.15(ey s)-.1 H .396
+(equence that quotes the).15 F(current or pre)180 444 Q(vious w)-.25 E
+(ord in Bash:)-.1 E F2($if)180 456 Q F0(bash)2.5 E 2.5(#Q)180 468 S
+(uote the current or pre)194.72 468 Q(vious w)-.25 E(ord)-.1 E
+("\\C-xq": "\\eb\\"\\ef\\"")180 480 Q F2($endif)180 492 Q($endif)108 508.8 Q F0
+(This command, as you sa)9.33 E 2.5(wi)-.15 G 2.5(nt)257.73 508.8 S(he pre)
+268.01 508.8 Q(vious e)-.25 E(xample, terminates an)-.15 E F2($if)2.5 E F0
+(command.)2.5 E F2($else)108 525.6 Q F0(Commands in this branch of the)144
+525.6 Q F2($if)2.5 E F0(directi)2.5 E .3 -.15(ve a)-.25 H(re e).15 E -.15(xe)
+-.15 G(cuted if the test f).15 E(ails.)-.1 E/F3 9/Times-Bold@0 SF
+(EDITING COMMANDS)72 542.4 Q F0 1.391(The follo)108 554.4 R 1.391
+(wing is a list of the names of the commands and the def)-.25 F 1.391(ault k)
+-.1 F 1.691 -.15(ey s)-.1 H 1.391(equences to which the).15 F 3.892(ya)-.15 G
+(re)532.23 554.4 Q(bound.)108 566.4 Q F2(Commands f)87 583.2 Q(or Mo)-.25 E
+(ving)-.1 E(beginning\255of\255line \(C\255a\))108 595.2 Q F0(Mo)144 607.2 Q .3
+-.15(ve t)-.15 H 2.5(ot).15 G(he start of the current line.)182.59 607.2 Q F2
+(end\255of\255line \(C\255e\))108 619.2 Q F0(Mo)144 631.2 Q .3 -.15(ve t)-.15 H
+2.5(ot).15 G(he end of the line.)182.59 631.2 Q F2 -.25(fo)108 643.2 S
+(rward\255char \(C\255f\)).25 E F0(Mo)144 655.2 Q .3 -.15(ve f)-.15 H(orw).15 E
+(ard a character)-.1 E(.)-.55 E F2(backward\255char \(C\255b\))108 667.2 Q F0
+(Mo)144 679.2 Q .3 -.15(ve b)-.15 H(ack a character).15 E(.)-.55 E F2 -.25(fo)
+108 691.2 S(rward\255w).25 E(ord \(M\255f\))-.1 E F0(Mo)144 703.2 Q .823 -.15
+(ve f)-.15 H(orw).15 E .523(ard to the end of the ne)-.1 F .523(xt w)-.15 F
+3.023(ord. W)-.1 F .522(ords are composed of alphanumeric characters \(let-)-.8
+F(ters and digits\).)144 715.2 Q 184.005(GNU 1994)72 768 R(July 26)2.5 E(5)535
+768 Q EP
+%%Page: 6 6
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 342.2(READLINE\(3\) READLINE\(3\))72 48 R/F1 10
+/Times-Bold@0 SF(backward\255w)108 84 Q(ord \(M\255b\))-.1 E F0(Mo)144 96 Q
+.748 -.15(ve b)-.15 H .449(ack to the start of this, or the pre).15 F .449
+(vious, w)-.25 F 2.949(ord. W)-.1 F .449
+(ords are composed of alphanumeric char)-.8 F(-)-.2 E
+(acters \(letters and digits\).)144 108 Q F1(clear\255scr)108 120 Q
+(een \(C\255l\))-.18 E F0 .993(Clear the screen lea)144 132 R .993
+(ving the current line at the top of the screen.)-.2 F -.4(Wi)5.993 G .993
+(th an ar).4 F .993(gument, refresh the)-.18 F
+(current line without clearing the screen.)144 144 Q F1 -.18(re)108 156 S
+(draw\255curr).18 E(ent\255line)-.18 E F0(Refresh the current line.)144 168 Q
+(By def)5 E(ault, this is unbound.)-.1 E F1(Commands f)87 184.8 Q
+(or Manipulating the History)-.25 E(accept\255line \(Newline, Retur)108 196.8 Q
+(n\))-.15 E F0 .857(Accept the line re)144 208.8 R -.05(ga)-.15 G .857
+(rdless of where the cursor is.).05 F .857(If this line is non\255empty)5.857 F
+3.357(,a)-.65 G .858(dd it to the history)463.228 208.8 R(list. If the line is\
+ a modi\214ed history line, then restore the history line to its original stat\
+e.)144 220.8 Q F1(pr)108 232.8 Q -.15(ev)-.18 G(ious\255history \(C\255p\)).15
+E F0(Fetch the pre)144 244.8 Q(vious command from the history list, mo)-.25 E
+(ving back in the list.)-.15 E F1(next\255history \(C\255n\))108 256.8 Q F0
+(Fetch the ne)144 268.8 Q(xt command from the history list, mo)-.15 E
+(ving forw)-.15 E(ard in the list.)-.1 E F1
+(beginning\255of\255history \(M\255<\))108 280.8 Q F0(Mo)144 292.8 Q .3 -.15
+(ve t)-.15 H 2.5(ot).15 G(he \214rst line in the history)182.59 292.8 Q(.)-.65
+E F1(end\255of\255history \(M\255>\))108 304.8 Q F0(Mo)144 316.8 Q .3 -.15
+(ve t)-.15 H 2.5(ot).15 G(he end of the input history)182.59 316.8 Q 2.5(,i)
+-.65 G(.e., the line currently being entered.)294.99 316.8 Q F1 -2.29 -.18
+(re v)108 328.8 T(erse\255sear).08 E(ch\255history \(C\255r\))-.18 E F0 1.471
+(Search backw)144 340.8 R 1.471(ard starting at the current line and mo)-.1 F
+1.47(ving `up' through the history as necessary)-.15 F(.)-.65 E
+(This is an incremental search.)144 352.8 Q F1 -.25(fo)108 364.8 S
+(rward\255sear).25 E(ch\255history \(C\255s\))-.18 E F0 1.131(Search forw)144
+376.8 R 1.131(ard starting at the current line and mo)-.1 F 1.132(ving `do)-.15
+F 1.132(wn' through the history as necessary)-.25 F(.)-.65 E
+(This is an incremental search.)144 388.8 Q F1(non\255incr)108 400.8 Q
+(emental\255r)-.18 E -2.3 -.15(ev e)-.18 H(rse\255sear).15 E
+(ch\255history \(M\255p\))-.18 E F0 1.089(Search backw)144 412.8 R 1.088(ard t\
+hrough the history starting at the current line using a non\255incremental sea\
+rch)-.1 F(for a string supplied by the user)144 424.8 Q(.)-.55 E F1
+(non\255incr)108 436.8 Q(emental\255f)-.18 E(orward\255sear)-.25 E
+(ch\255history \(M\255n\))-.18 E F0 1.188(Search forw)144 448.8 R 1.189(ard th\
+rough the history using a non\255incremental search for a string supplied by t\
+he)-.1 F(user)144 460.8 Q(.)-.55 E F1(history\255sear)108 472.8 Q(ch\255f)-.18
+E(orward)-.25 E F0 .249(Search forw)144 484.8 R .249(ard through the history f\
+or the string of characters between the start of the current line)-.1 F
+(and the current point.)144 496.8 Q(This is a non-incremental search.)5 E
+(By def)5 E(ault, this command is unbound.)-.1 E F1(history\255sear)108 508.8 Q
+(ch\255backward)-.18 E F0 .95(Search backw)144 520.8 R .951(ard through the hi\
+story for the string of characters between the start of the current)-.1 F 2.721
+(line and the current point.)144 532.8 R 2.721
+(This is a non-incremental search.)7.721 F 2.72(By def)7.721 F 2.72
+(ault, this command is)-.1 F(unbound.)144 544.8 Q F1(yank\255nth\255ar)108
+556.8 Q 2.5(g\()-.1 G<4dad43ad7929>175.14 556.8 Q F0 .622
+(Insert the \214rst ar)144 568.8 R .622(gument to the pre)-.18 F .622
+(vious command \(usually the second w)-.25 F .622(ord on the pre)-.1 F .622
+(vious line\))-.25 F .682(at point \(the current cursor position\).)144 580.8 R
+-.4(Wi)5.682 G .682(th an ar).4 F(gument)-.18 E/F2 10/Times-Italic@0 SF(n)3.182
+E F0 3.182(,i).24 G .682(nsert the)390.17 580.8 R F2(n)3.182 E F0 .682(th w)B
+.681(ord from the pre)-.1 F(vious)-.25 E .729(command \(the w)144 592.8 R .729
+(ords in the pre)-.1 F .729(vious command be)-.25 F .729(gin with w)-.15 F .729
+(ord 0\).)-.1 F 3.23(An)5.73 G -2.25 -.15(eg a)441.56 592.8 T(ti).15 E 1.03
+-.15(ve a)-.25 H -.18(rg).15 G .73(ument inserts).18 F(the)144 604.8 Q F2(n)2.5
+E F0(th w)A(ord from the end of the pre)-.1 E(vious command.)-.25 E F1
+(yank\255last\255ar)108 616.8 Q 2.5(g\()-.1 G -1.667(M\255. ,)175.69 616.8 R
+-1.667(M\255_ \))2.5 F F0 1.077(Insert the last ar)144 628.8 R 1.077
+(gument to the pre)-.18 F 1.077(vious command \(the last w)-.25 F 1.077
+(ord on the pre)-.1 F 1.077(vious line\).)-.25 F -.4(Wi)6.076 G 1.076(th an).4
+F(ar)144 640.8 Q(gument, beha)-.18 E .3 -.15(ve ex)-.2 H(actly lik).15 E(e)-.1
+E F1(yank-nth-ar)2.5 E(g)-.1 E F0(.)A F1(Commands f)87 657.6 Q(or Changing T)
+-.25 E(ext)-.92 E(delete\255char \(C\255d\))108 669.6 Q F0 .486
+(Delete the character under the cursor)144 681.6 R 5.486(.I)-.55 G 2.987(fp)
+304.636 681.6 S .487(oint is at the be)315.953 681.6 R .487
+(ginning of the line, there are no charac-)-.15 F
+(ters in the line, and the last character typed w)144 693.6 Q(as not)-.1 E F1
+(C\255d)2.5 E F0 2.5(,t)C(hen return)377.34 693.6 Q/F3 9/Times-Bold@0 SF(EOF)
+2.5 E/F4 9/Times-Roman@0 SF(.)A F1(backward\255delete\255char \(Rubout\))108
+705.6 Q F0 .553(Delete the character behind the cursor)144 717.6 R 5.553(.W)
+-.55 G .553(hen gi)315.598 717.6 R -.15(ve)-.25 G 3.053(nan).15 G .553
+(umeric ar)370.457 717.6 R .552(gument, sa)-.18 F .852 -.15(ve t)-.2 H .552
+(he deleted te).15 F .552(xt on)-.15 F(the kill\255ring.)144 729.6 Q 184.005
+(GNU 1994)72 768 R(July 26)2.5 E(6)535 768 Q EP
+%%Page: 7 7
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 342.2(READLINE\(3\) READLINE\(3\))72 48 R/F1 10
+/Times-Bold@0 SF(quoted\255insert \(C\255q, C\255v\))108 84 Q F0 1.228
+(Add the ne)144 96 R 1.228(xt character that you type to the line v)-.15 F
+3.728(erbatim. This)-.15 F 1.228(is ho)3.728 F 3.729(wt)-.25 G 3.729(oi)446.163
+96 S 1.229(nsert characters lik)457.672 96 R(e)-.1 E F1(C\255q)144 108 Q F0 2.5
+(,f)C(or e)170.81 108 Q(xample.)-.15 E F1(tab\255insert \(M-T)108 120 Q(AB\))
+-.9 E F0(Insert a tab character)144 132 Q(.)-.55 E F1
+(self\255insert \(a, b, A, 1, !, ...\))108 144 Q F0
+(Insert the character typed.)144 156 Q F1(transpose\255chars \(C\255t\))108 168
+Q F0 .424(Drag the character before point forw)144 180 R .424(ard o)-.1 F -.15
+(ve)-.15 G 2.924(rt).15 G .424(he character at point.)331.218 180 R .424
+(Point mo)5.424 F -.15(ve)-.15 G 2.924(sf).15 G(orw)477.882 180 Q .424
+(ard as well.)-.1 F 1.03
+(If point is at the end of the line, then transpose the tw)144 192 R 3.531(oc)
+-.1 G 1.031(haracters before point.)382.266 192 R(Ne)6.031 E -.05(ga)-.15 G(ti)
+.05 E 1.331 -.15(ve a)-.25 H -.18(rg).15 G(u-).18 E(ments don')144 204 Q 2.5
+(tw)-.18 G(ork.)200.94 204 Q F1(transpose\255w)108 216 Q(ords \(M\255t\))-.1 E
+F0 .683(Drag the w)144 228 R .682(ord behind the cursor past the w)-.1 F .682
+(ord in front of the cursor mo)-.1 F .682(ving the cursor o)-.15 F -.15(ve)-.15
+G 3.182(rt).15 G(hat)527.78 228 Q -.1(wo)144 240 S(rd as well.).1 E F1
+(upcase\255w)108 252 Q(ord \(M\255u\))-.1 E F0 .702
+(Uppercase the current \(or follo)144 264 R .702(wing\) w)-.25 F 3.202(ord. W)
+-.1 F .702(ith a ne)-.4 F -.05(ga)-.15 G(ti).05 E 1.002 -.15(ve a)-.25 H -.18
+(rg).15 G .702(ument, do the pre).18 F .703(vious w)-.25 F .703(ord, b)-.1 F
+(ut)-.2 E(do not mo)144 276 Q .3 -.15(ve p)-.15 H(oint.).15 E F1(do)108 288 Q
+(wncase\255w)-.1 E(ord \(M\255l\))-.1 E F0(Lo)144 300 Q .641
+(wercase the current \(or follo)-.25 F .641(wing\) w)-.25 F 3.141(ord. W)-.1 F
+.641(ith a ne)-.4 F -.05(ga)-.15 G(ti).05 E .941 -.15(ve a)-.25 H -.18(rg).15 G
+.64(ument, do the pre).18 F .64(vious w)-.25 F .64(ord, b)-.1 F(ut)-.2 E
+(do not mo)144 312 Q .3 -.15(ve p)-.15 H(oint.).15 E F1(capitalize\255w)108 324
+Q(ord \(M\255c\))-.1 E F0 .82(Capitalize the current \(or follo)144 336 R .82
+(wing\) w)-.25 F 3.32(ord. W)-.1 F .82(ith a ne)-.4 F -.05(ga)-.15 G(ti).05 E
+1.12 -.15(ve a)-.25 H -.18(rg).15 G .82(ument, do the pre).18 F .82(vious w)
+-.25 F .82(ord, b)-.1 F(ut)-.2 E(do not mo)144 348 Q .3 -.15(ve p)-.15 H(oint.)
+.15 E F1(Killing and Y)87 364.8 Q(anking)-.85 E(kill\255line \(C\255k\))108
+376.8 Q F0(Kill the te)144 388.8 Q
+(xt from the current cursor position to the end of the line.)-.15 E F1
+(backward\255kill\255line \(C\255x Rubout\))108 400.8 Q F0(Kill backw)144 412.8
+Q(ard to the be)-.1 E(ginning of the line.)-.15 E F1
+(unix\255line\255discard \(C\255u\))108 424.8 Q F0(Kill backw)144 436.8 Q
+(ard from point to the be)-.1 E(ginning of the line.)-.15 E F1
+(kill\255whole\255line)108 448.8 Q F0
+(Kill all characters on the current line, no matter where the cursor is.)144
+460.8 Q(By def)5 E(ault, this is unbound.)-.1 E F1(kill\255w)108 472.8 Q
+(ord \(M\255d\))-.1 E F0 1.044
+(Kill from the cursor to the end of the current w)144 484.8 R 1.043
+(ord, or if between w)-.1 F 1.043(ords, to the end of the ne)-.1 F(xt)-.15 E
+-.1(wo)144 496.8 S 2.5(rd. W).1 F(ord boundaries are the same as those used by)
+-.8 E F1 -.25(fo)2.5 G(rward\255w).25 E(ord)-.1 E F0(.)A F1
+(backward\255kill\255w)108 508.8 Q(ord \(M\255Rubout\))-.1 E F0 3.26
+(Kill the w)144 520.8 R 3.26(ord behind the cursor)-.1 F 8.26(.W)-.55 G 3.26
+(ord boundaries are the same as those used by)304.31 520.8 R F1(back-)5.76 E
+(ward\255w)144 532.8 Q(ord)-.1 E F0(.)A F1(unix\255w)108 544.8 Q
+(ord\255rubout \(C\255w\))-.1 E F0 .482(Kill the w)144 556.8 R .482
+(ord behind the cursor)-.1 F 2.982(,u)-.4 G .482(sing white space as a w)
+281.652 556.8 R .482(ord boundary)-.1 F 5.482(.T)-.65 G .482(he w)445.076 556.8
+R .481(ord boundaries are)-.1 F(dif)144 568.8 Q(ferent from)-.25 E F1
+(backward\255kill\255w)2.5 E(ord)-.1 E F0(.)A F1(delete\255horizontal\255space)
+108 580.8 Q F0(Delete all spaces and tabs around point.)144 592.8 Q(By def)5 E
+(ault, this is unbound.)-.1 E F1(yank \(C\255y\))108 604.8 Q F0 -1(Ya)144 616.8
+S(nk the top of the kill ring into the b)1 E(uf)-.2 E(fer at the cursor)-.25 E
+(.)-.55 E F1(yank\255pop \(M\255y\))108 628.8 Q F0
+(Rotate the kill\255ring, and yank the ne)144 640.8 Q 2.5(wt)-.25 G 2.5
+(op. Only)302.71 640.8 R -.1(wo)2.5 G(rks follo).1 E(wing)-.25 E F1(yank)2.5 E
+F0(or)2.5 E F1(yank\255pop)2.5 E F0(.)A F1(Numeric Ar)87 657.6 Q(guments)-.1 E
+(digit\255ar)108 669.6 Q(gument \(M\2550, M\2551, ..., M\255\255\))-.1 E F0
+.641(Add this digit to the ar)144 681.6 R .641
+(gument already accumulating, or start a ne)-.18 F 3.141(wa)-.25 G -.18(rg)
+425.942 681.6 S 3.142(ument. M\255\255).18 F .642(starts a ne)3.142 F(g-)-.15 E
+(ati)144 693.6 Q .3 -.15(ve a)-.25 H -.18(rg).15 G(ument.).18 E F1(uni)108
+705.6 Q -.1(ve)-.1 G(rsal\255ar).1 E(gument)-.1 E F0 .783(Each time this is e)
+144 717.6 R -.15(xe)-.15 G .783(cuted, the ar).15 F .782
+(gument count is multiplied by four)-.18 F 5.782(.T)-.55 G .782(he ar)437.062
+717.6 R .782(gument count is ini-)-.18 F .175(tially one, so e)144 729.6 R -.15
+(xe)-.15 G .175(cuting this function the \214rst time mak).15 F .176(es the ar)
+-.1 F .176(gument count four)-.18 F 5.176(.B)-.55 G 2.676(yd)485.028 729.6 S
+(ef)497.704 729.6 Q .176(ault, this)-.1 F 184.005(GNU 1994)72 768 R(July 26)2.5
+E(7)535 768 Q EP
+%%Page: 8 8
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 342.2(READLINE\(3\) READLINE\(3\))72 48 R
+(is not bound to a k)144 84 Q -.15(ey)-.1 G(.)-.5 E/F1 10/Times-Bold@0 SF
+(Completing)87 100.8 Q(complete \(T)108 112.8 Q(AB\))-.9 E F0 1.909
+(Attempt to perform completion on the te)144 124.8 R 1.908(xt before point.)
+-.15 F 1.908(The actual completion performed is)6.908 F
+(application-speci\214c.)144 136.8 Q F1(Bash)5.517 E F0 3.017(,f)C .518
+(or instance, attempts completion treating the te)260.304 136.8 R .518
+(xt as a v)-.15 F .518(ariable \(if the)-.25 F(te)144 148.8 Q .657(xt be)-.15 F
+.657(gins with)-.15 F F1($)3.156 E F0 .656(\), username \(if the te)B .656
+(xt be)-.15 F .656(gins with)-.15 F F1(~)3.156 E F0 .656
+(\), hostname \(if the te)B .656(xt be)-.15 F .656(gins with)-.15 F F1(@)3.156
+E F0 .656(\), or)B .929(command \(including aliases and functions\) in turn.)
+144 160.8 R .93(If none of these produces a match, \214lename)5.929 F 1.274
+(completion is attempted.)144 172.8 R F1(Gdb)6.273 E F0 3.773(,o)C 3.773(nt)
+281.603 172.8 S 1.273(he other hand, allo)293.156 172.8 R 1.273
+(ws completion of program functions and)-.25 F -.25(va)144 184.8 S
+(riables, and only attempts \214lename completion under certain circumstances.)
+.25 E F1(possible\255completions \(M-?\))108 196.8 Q F0
+(List the possible completions of the te)144 208.8 Q(xt before point.)-.15 E F1
+(insert\255completions)108 220.8 Q F0 3.372(Insert all completions of the te)
+144 232.8 R 3.372(xt before point that w)-.15 F 3.372(ould ha)-.1 F 3.672 -.15
+(ve b)-.2 H 3.372(een generated by).15 F F1(possi-)5.873 E(ble\255completions)
+144 244.8 Q F0 5(.B)C 2.5(yd)227.76 244.8 S(ef)240.26 244.8 Q
+(ault, this is not bound to a k)-.1 E -.15(ey)-.1 G(.)-.5 E F1 -.25(Ke)87 261.6
+S(yboard Macr).25 E(os)-.18 E(start\255kbd\255macr)108 273.6 Q 2.5(o\()-.18 G
+(C-x \()188.93 273.6 Q(\)).833 E F0(Be)144 285.6 Q(gin sa)-.15 E
+(ving the characters typed into the current k)-.2 E -.15(ey)-.1 G(board macro.)
+.15 E F1(end\255kbd\255macr)108 297.6 Q 2.5(o\()-.18 G(C-x \))184.5 297.6 Q(\))
+.833 E F0(Stop sa)144 309.6 Q(ving the characters typed into the current k)-.2
+E -.15(ey)-.1 G(board macro and sa).15 E .3 -.15(ve t)-.2 H(he de\214nition.)
+.15 E F1(call\255last\255kbd\255macr)108 321.6 Q 2.5(o\()-.18 G(C-x e\))204.64
+321.6 Q F0(Re-e)144 333.6 Q -.15(xe)-.15 G 1(cute the last k).15 F -.15(ey)-.1
+G .999
+(board macro de\214ned, by making the characters in the macro appear as if).15
+F(typed at the k)144 345.6 Q -.15(ey)-.1 G(board.).15 E F1(Miscellaneous)87
+362.4 Q -.18(re)108 374.4 S(-r).18 E(ead-init-\214le \(C\255x C\255r\))-.18 E
+F0 .54(Read in the contents of your init \214le, and incorporate an)144 386.4 R
+3.041(yb)-.15 G .541(indings or v)385.876 386.4 R .541
+(ariable assignments found)-.25 F(there.)144 398.4 Q F1(abort \(C\255g\))108
+410.4 Q F0 3.249(Abort the current editing command and ring the terminal')144
+422.4 R 5.748(sb)-.55 G 3.248(ell \(subject to the setting of)414.6 422.4 R F1
+(bell\255style)144 434.4 Q F0(\).)A F1(do\255upper)108 446.4 Q(case\255v)-.18 E
+(ersion \(M\255a, M\255b, ...\))-.1 E F0
+(Run the command that is bound to the corresponding uppercase character)144
+458.4 Q(.)-.55 E F1(pr)108 470.4 Q(e\214x\255meta \(ESC\))-.18 E F0
+(Metafy the ne)144 482.4 Q(xt character typed.)-.15 E/F2 9/Times-Bold@0 SF(ESC)
+5 E F1(f)2.25 E F0(is equi)2.5 E -.25(va)-.25 G(lent to).25 E F1(Meta\255f)2.5
+E F0(.)A F1(undo \(C\255_, C\255x C\255u\))108 494.4 Q F0
+(Incremental undo, separately remembered for each line.)144 506.4 Q F1 -2.29
+-.18(re v)108 518.4 T(ert\255line \(M\255r\)).08 E F0 .244
+(Undo all changes made to this line.)144 530.4 R .245(This is lik)5.245 F 2.745
+(et)-.1 G .245(yping the)341.895 530.4 R F1(undo)2.745 E F0 .245
+(command enough times to return)2.745 F(the line to its initial state.)144
+542.4 Q F1(tilde\255expand \(M\255~\))108 554.4 Q F0(Perform tilde e)144 566.4
+Q(xpansion on the current w)-.15 E(ord.)-.1 E F1(dump\255functions)108 578.4 Q
+F0 .627(Print all of the functions and their k)144 590.4 R .927 -.15(ey b)-.1 H
+.626(indings to the readline output stream.).15 F .626(If a numeric ar)5.626 F
+(gu-)-.18 E(ment is supplied, the output is formatted in such a w)144 602.4 Q
+(ay that it can be made part of an)-.1 E/F3 10/Times-Italic@0 SF(inputr)2.5 E
+(c)-.37 E F0(\214le.)2.5 E F1(emacs\255editing\255mode \(C\255e\))108 614.4 Q
+F0(When in)144 626.4 Q F1(vi)2.5 E F0(editing mode, this causes a switch to)2.5
+E F1(emacs)2.5 E F0(editing mode.)2.5 E F1
+(vi\255editing\255mode \(M\255C\255j\))108 638.4 Q F0(When in)144 650.4 Q F1
+(emacs)2.5 E F0(editing mode, this causes a switch to)2.5 E F1(vi)2.5 E F0
+(editing mode.)2.5 E F2(DEF)72 667.2 Q -.45(AU)-.81 G 1.656 -.828(LT K).45 H
+(EY BINDINGS).828 E F0 .675(The follo)108 679.2 R .675
+(wing is a list of the def)-.25 F .675(ault emacs and vi bindings.)-.1 F .676
+(Characters with the 8th bit set are written as)5.676 F .002
+(M-<character>, and are referred to as)108 691.2 R F3(meta\214ed)2.502 E F0
+2.502(characters. The)2.502 F .002(printable ASCII characters not mentioned in)
+2.502 F .444(the list of emacs standard bindings are bound to the)108 703.2 R
+F3(self\255insert)2.945 E F0 .445(function, which just inserts the gi)2.945 F
+-.15(ve)-.25 G 2.945(nc).15 G(har)524.1 703.2 Q(-)-.2 E 2.021
+(acter into the input line.)108 715.2 R 2.02(In vi insertion mode, all charact\
+ers not speci\214cally mentioned are bound to)7.021 F F3(self\255insert)108
+727.2 Q F0 5.388(.C).68 G .388(haracters assigned to signal generation by)
+166.658 727.2 R F3(stty)2.889 E F0 .389(\(1\) or the terminal dri).32 F -.15
+(ve)-.25 G 1.189 -.4(r, s).15 H .389(uch as C-Z or C-C,).4 F 184.005(GNU 1994)
+72 768 R(July 26)2.5 E(8)535 768 Q EP
+%%Page: 9 9
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 342.2(READLINE\(3\) READLINE\(3\))72 48 R .221
+(retain that function.)108 84 R .221(Upper and lo)5.221 F .221(wer case)-.25 F
+/F1 10/Times-Italic@0 SF(meta\214ed)2.721 E F0 .22
+(characters are bound to the same function in the emacs)2.721 F .304
+(mode meta k)108 96 R -.15(ey)-.1 G 2.804(map. The).15 F .305(remaining charac\
+ters are unbound, which causes readline to ring the bell \(subject)2.804 F
+(to the setting of the)108 108 Q/F2 10/Times-Bold@0 SF(bell\255style)2.5 E F0
+-.25(va)2.5 G(riable\).).25 E F2(Emacs Mode)87 124.8 Q F0
+(Emacs Standard bindings)151.2 136.8 Q 152.12("C-A" ->)151.2 160.8 R(be)5 E
+(ginning-of-line)-.15 E 152.67("C-B" ->)151.2 172.8 R(backw)5 E(ard-char)-.1 E
+152.12("C-D" ->)151.2 184.8 R(delete-char)5 E 153.23("C-E" ->)151.2 196.8 R
+(end-of-line)5 E 153.78("C-F" ->)151.2 208.8 R(forw)5 E(ard-char)-.1 E 152.12
+("C-G" ->)151.2 220.8 R(abort)5 E 152.12("C-H" ->)151.2 232.8 R(backw)5 E
+(ard-delete-char)-.1 E 156.01("C-I" ->)151.2 244.8 R(complete)5 E 155.45
+("C-J" ->)151.2 256.8 R(accept-line)5 E 152.12("C-K" ->)151.2 268.8 R
+(kill-line)5 E 153.23("C-L" ->)151.2 280.8 R(clear)5 E(-screen)-.2 E 150.45
+("C-M" ->)151.2 292.8 R(accept-line)5 E 152.12("C-N" ->)151.2 304.8 R(ne)5 E
+(xt-history)-.15 E 153.78("C-P" ->)151.2 316.8 R(pre)5 E(vious-history)-.25 E
+152.12("C-Q" ->)151.2 328.8 R(quoted-insert)5 E 152.67("C-R" ->)151.2 340.8 R
+(re)5 E -.15(ve)-.25 G(rse-search-history).15 E 153.78("C-S" ->)151.2 352.8 R
+(forw)5 E(ard-search-history)-.1 E 153.23("C-T" ->)151.2 364.8 R
+(transpose-chars)5 E 152.12("C-U" ->)151.2 376.8 R(unix-line-discard)5 E 152.12
+("C-V" ->)151.2 388.8 R(quoted-insert)5 E 149.9("C-W" ->)151.2 400.8 R(unix-w)5
+E(ord-rubout)-.1 E 152.12("C-Y" ->)151.2 412.8 R(yank)5 E 154.34("C-_" ->)151.2
+424.8 R(undo)5 E 3.333("")151.2 436.8 S(to "/")-.833 E 2.5(-> self-insert)331.2
+436.8 R 2.5("0" to)151.2 448.8 R 135.9("9" ->)2.5 F(self-insert)5 E 2.5(":" to)
+151.2 460.8 R 139.79("~" ->)2.5 F(self-insert)5 E 154.9("C-?" ->)151.2 472.8 R
+(backw)5 E(ard-delete-char)-.1 E(Emacs Meta bindings)151.2 489.6 Q 139.9
+("M-C-H" ->)151.2 513.6 R(backw)5 E(ard-kill-w)-.1 E(ord)-.1 E 143.79
+("M-C-I" ->)151.2 525.6 R(tab-insert)5 E 143.23("M-C-J" ->)151.2 537.6 R
+(vi-editing-mode)5 E 138.23("M-C-M" ->)151.2 549.6 R(vi-editing-mode)5 E 140.45
+("M-C-R" ->)151.2 561.6 R(re)5 E -.15(ve)-.25 G(rt-line).15 E 139.9("M-C-Y" ->)
+151.2 573.6 R(yank-nth-ar)5 E(g)-.18 E 143.79("M-C-[" ->)151.2 585.6 R
+(complete)5 E 149.34("M-&" ->)151.2 597.6 R(tilde-e)5 E(xpand)-.15 E 153.79
+("M--" ->)151.2 609.6 R(digit-ar)5 E(gument)-.18 E 152.12("M-0" ->)151.2 621.6
+R(digit-ar)5 E(gument)-.18 E 152.12("M-1" ->)151.2 633.6 R(digit-ar)5 E(gument)
+-.18 E 152.12("M-2" ->)151.2 645.6 R(digit-ar)5 E(gument)-.18 E 152.12
+("M-3" ->)151.2 657.6 R(digit-ar)5 E(gument)-.18 E 152.12("M-4" ->)151.2 669.6
+R(digit-ar)5 E(gument)-.18 E 152.12("M-5" ->)151.2 681.6 R(digit-ar)5 E(gument)
+-.18 E 152.12("M-6" ->)151.2 693.6 R(digit-ar)5 E(gument)-.18 E 152.12
+("M-7" ->)151.2 705.6 R(digit-ar)5 E(gument)-.18 E 152.12("M-8" ->)151.2 717.6
+R(digit-ar)5 E(gument)-.18 E 152.12("M-9" ->)151.2 729.6 R(digit-ar)5 E(gument)
+-.18 E 184.005(GNU 1994)72 768 R(July 26)2.5 E(9)535 768 Q EP
+%%Page: 10 10
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 342.2(READLINE\(3\) READLINE\(3\))72 48 R 151.48
+("M-<" ->)151.2 84 R(be)5 E(ginning-of-history)-.15 E 151.48("M->" ->)151.2 96
+R(end-of-history)5 E 152.68("M-?" ->)151.2 108 R(possible-completions)5 E
+150.45("M-B" ->)151.2 120 R(backw)5 E(ard-w)-.1 E(ord)-.1 E 150.45("M-C" ->)
+151.2 132 R(capitalize-w)5 E(ord)-.1 E 149.9("M-D" ->)151.2 144 R(kill-w)5 E
+(ord)-.1 E 151.56("M-F" ->)151.2 156 R(forw)5 E(ard-w)-.1 E(ord)-.1 E 151.01
+("M-L" ->)151.2 168 R(do)5 E(wncase-w)-.25 E(ord)-.1 E 149.9("M-N" ->)151.2 180
+R(non-incremental-forw)5 E(ard-search-history)-.1 E 149.9("M-O" ->)151.2 192 R
+(arro)5 E(w-k)-.25 E -.15(ey)-.1 G(-pre\214x).15 E 151.56("M-P" ->)151.2 204 R
+(non-incremental-re)5 E -.15(ve)-.25 G(rse-search-history).15 E 150.45
+("M-R" ->)151.2 216 R(re)5 E -.15(ve)-.25 G(rt-line).15 E 151.01("M-T" ->)151.2
+228 R(transpose-w)5 E(ords)-.1 E 149.9("M-U" ->)151.2 240 R(upcase-w)5 E(ord)
+-.1 E 149.9("M-Y" ->)151.2 252 R(yank-pop)5 E 139.9("M-C-Y" ->)151.2 264 R
+(yank-nth-ar)5 E(g)-.18 E 142.68("M-C-?" ->)151.2 276 R(backw)5 E(ard-delete-w)
+-.1 E(ord)-.1 E(Emacs Control-X bindings)151.2 292.8 Q 134.9("C-XC-G" ->)151.2
+316.8 R(abort)5 E 135.45("C-XC-R" ->)151.2 328.8 R(re-read-init-\214le)5 E
+134.9("C-XC-U" ->)151.2 340.8 R(undo)5 E 148.79("C-X\(" ->)151.2 352.8 R
+(start-kbd-macro)5 E 148.79("C-X\)" ->)151.2 364.8 R(end-kbd-macro)5 E 147.68
+("C-Xe" ->)151.2 376.8 R(call-last-kbd-macro)5 E 137.68("C-XC-?" ->)151.2 388.8
+R(backw)5 E(ard-kill-line)-.1 E/F1 10/Times-Bold@0 SF(VI Mode bindings)87 417.6
+Q F0(VI Insert Mode functions)151.2 429.6 Q 152.12("C-D" ->)151.2 453.6 R
+(vi-eof-maybe)5 E 152.12("C-H" ->)151.2 465.6 R(backw)5 E(ard-delete-char)-.1 E
+156.01("C-I" ->)151.2 477.6 R(complete)5 E 155.45("C-J" ->)151.2 489.6 R
+(accept-line)5 E 152.12("C-K" ->)151.2 501.6 R(kill-line)5 E 153.23("C-L" ->)
+151.2 513.6 R(clear)5 E(-screen)-.2 E 150.45("C-M" ->)151.2 525.6 R
+(accept-line)5 E 152.12("C-N" ->)151.2 537.6 R(ne)5 E(xt-history)-.15 E 153.78
+("C-P" ->)151.2 549.6 R(pre)5 E(vious-history)-.25 E 152.12("C-Q" ->)151.2
+561.6 R(quoted-insert)5 E 152.67("C-R" ->)151.2 573.6 R(re)5 E -.15(ve)-.25 G
+(rse-search-history).15 E 153.78("C-S" ->)151.2 585.6 R(forw)5 E
+(ard-search-history)-.1 E 153.23("C-T" ->)151.2 597.6 R(transpose-chars)5 E
+152.12("C-U" ->)151.2 609.6 R(unix-line-discard)5 E 152.12("C-V" ->)151.2 621.6
+R(quoted-insert)5 E 149.9("C-W" ->)151.2 633.6 R(unix-w)5 E(ord-rubout)-.1 E
+152.12("C-Y" ->)151.2 645.6 R(yank)5 E 156.01("C-[" ->)151.2 657.6 R(vi-mo)5 E
+-.15(ve)-.15 G(ment-mode).15 E 3.333("")151.2 669.6 S(to "~")-.833 E 2.5
+(-> self-insert)331.2 669.6 R 154.9("C-?" ->)151.2 681.6 R(backw)5 E
+(ard-delete-char)-.1 E(VI Command Mode functions)151.2 698.4 Q 152.12("C-D" ->)
+151.2 722.4 R(vi-eof-maybe)5 E 184.005(GNU 1994)72 768 R(July 26)2.5 E(10)530
+768 Q EP
+%%Page: 11 11
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 342.2(READLINE\(3\) READLINE\(3\))72 48 R 153.23
+("C-E" ->)151.2 84 R(emacs-editing-mode)5 E 152.12("C-G" ->)151.2 96 R(abort)5
+E 152.12("C-H" ->)151.2 108 R(backw)5 E(ard-char)-.1 E 155.45("C-J" ->)151.2
+120 R(accept-line)5 E 152.12("C-K" ->)151.2 132 R(kill-line)5 E 153.23
+("C-L" ->)151.2 144 R(clear)5 E(-screen)-.2 E 150.45("C-M" ->)151.2 156 R
+(accept-line)5 E 152.12("C-N" ->)151.2 168 R(ne)5 E(xt-history)-.15 E 153.78
+("C-P" ->)151.2 180 R(pre)5 E(vious-history)-.25 E 152.12("C-Q" ->)151.2 192 R
+(quoted-insert)5 E 152.67("C-R" ->)151.2 204 R(re)5 E -.15(ve)-.25 G
+(rse-search-history).15 E 153.78("C-S" ->)151.2 216 R(forw)5 E
+(ard-search-history)-.1 E 153.23("C-T" ->)151.2 228 R(transpose-chars)5 E
+152.12("C-U" ->)151.2 240 R(unix-line-discard)5 E 152.12("C-V" ->)151.2 252 R
+(quoted-insert)5 E 149.9("C-W" ->)151.2 264 R(unix-w)5 E(ord-rubout)-.1 E
+152.12("C-Y" ->)151.2 276 R(yank)5 E 156.01("C-[" ->)151.2 288 R(abort)5 E
+159.341 3.333("" -)151.2 300 T 5(>f)334.53 300 S(orw)348.5 300 Q(ard-char)-.1 E
+164.34("#" ->)151.2 312 R(vi-comment)5 E 164.34("$" ->)151.2 324 R(end-of-line)
+5 E 161.01("%" ->)151.2 336 R(vi-match)5 E 161.56("&" ->)151.2 348 R
+(vi-tilde-e)5 E(xpand)-.15 E 164.34("*" ->)151.2 360 R(vi-complete)5 E 163.7
+("+" ->)151.2 372 R(do)5 E(wn-history)-.25 E 166.84("," ->)151.2 384 R(vi-char)
+5 E(-search)-.2 E 166.01("-" ->)151.2 396 R(pre)5 E(vious-history)-.25 E 166.84
+("." ->)151.2 408 R(vi-redo)5 E 166.56("/" ->)151.2 420 R(vi-search)5 E 164.34
+("0" ->)151.2 432 R(be)5 E(ginning-of-line)-.15 E("1" to "9")151.2 444 Q 2.5
+(-> vi-ar)331.2 444 R(g-digit)-.18 E 166.56(";" ->)151.2 456 R(vi-char)5 E
+(-search)-.2 E 163.7("=" ->)151.2 468 R(vi-complete)5 E 164.9("?" ->)151.2 480
+R(vi-search)5 E 160.13("@" ->)151.2 492 R(is unde\214ned)5 E 162.12("A" ->)
+151.2 504 R(vi-append-eol)5 E 162.67("B" ->)151.2 516 R(vi-pre)5 E(v-w)-.25 E
+(ord)-.1 E 162.67("C" ->)151.2 528 R(vi-change-to)5 E 162.12("D" ->)151.2 540 R
+(vi-delete-to)5 E 163.23("E" ->)151.2 552 R(vi-end-w)5 E(ord)-.1 E 163.78
+("F" ->)151.2 564 R(vi-char)5 E(-search)-.2 E 166.01("I" ->)151.2 576 R
+(vi-insert-be)5 E(g)-.15 E 162.12("N" ->)151.2 588 R(vi-search-ag)5 E(ain)-.05
+E 163.78("P" ->)151.2 600 R(vi-put)5 E 162.67("R" ->)151.2 612 R(vi-replace)5 E
+163.78("S" ->)151.2 624 R(vi-subst)5 E 163.23("T" ->)151.2 636 R(vi-char)5 E
+(-search)-.2 E 162.12("U" ->)151.2 648 R(re)5 E -.15(ve)-.25 G(rt-line).15 E
+159.9("W" ->)151.2 660 R(vi-ne)5 E(xt-w)-.15 E(ord)-.1 E 162.12("X" ->)151.2
+672 R(backw)5 E(ard-delete-char)-.1 E 162.12("Y" ->)151.2 684 R(vi-yank-to)5 E
+166.56("\\" ->)151.2 696 R(vi-complete)5 E 166.01("^" ->)151.2 708 R
+(vi-\214rst-print)5 E 164.34("_" ->)151.2 720 R(vi-yank-ar)5 E(g)-.18 E 184.005
+(GNU 1994)72 768 R(July 26)2.5 E(11)530 768 Q EP
+%%Page: 12 12
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 342.2(READLINE\(3\) READLINE\(3\))72 48 R 164.9("a" ->)
+151.2 84 R(vi-append-mode)5 E 164.34("b" ->)151.2 96 R(vi-pre)5 E(v-w)-.25 E
+(ord)-.1 E 164.9("c" ->)151.2 108 R(vi-change-to)5 E 164.34("d" ->)151.2 120 R
+(vi-delete-to)5 E 164.9("e" ->)151.2 132 R(vi-end-w)5 E(ord)-.1 E 166.01
+("f" ->)151.2 144 R(vi-char)5 E(-search)-.2 E 164.34("h" ->)151.2 156 R(backw)5
+E(ard-char)-.1 E 166.56("i" ->)151.2 168 R(vi-insertion-mode)5 E 166.56("j" ->)
+151.2 180 R(ne)5 E(xt-history)-.15 E 164.34("k" ->)151.2 192 R(pre)5 E
+(v-history)-.25 E 166.56("l" ->)151.2 204 R(forw)5 E(ard-char)-.1 E 164.34
+("n" ->)151.2 216 R(vi-search-ag)5 E(ain)-.05 E 166.01("r" ->)151.2 228 R
+(vi-change-char)5 E 165.45("s" ->)151.2 240 R(vi-subst)5 E 166.56("t" ->)151.2
+252 R(vi-char)5 E(-search)-.2 E 164.34("u" ->)151.2 264 R(undo)5 E 162.12
+("w" ->)151.2 276 R(vi-ne)5 E(xt-w)-.15 E(ord)-.1 E 164.34("x" ->)151.2 288 R
+(vi-delete)5 E 164.34("y" ->)151.2 300 R(vi-yank-to)5 E 167.34("|" ->)151.2 312
+R(vi-column)5 E 166.01("~" ->)151.2 324 R(vi-change-case)5 E/F1 9/Times-Bold@0
+SF(SEE ALSO)72 340.8 Q/F2 10/Times-Italic@0 SF(The Gnu Readline Libr)108 352.8
+Q(ary)-.15 E F0 2.5(,B)C(rian F)225.35 352.8 Q(ox and Chet Rame)-.15 E(y)-.15 E
+F2(The Gnu History Libr)108 364.8 Q(ary)-.15 E F0 2.5(,B)C(rian F)219.8 364.8 Q
+(ox and Chet Rame)-.15 E(y)-.15 E F2(bash)108 376.8 Q F0(\(1\))A F1(FILES)72
+393.6 Q F2(~/.inputr)109.666 405.6 Q(c)-.37 E F0(Indi)144 417.6 Q(vidual)-.25 E
+/F3 10/Times-Bold@0 SF -.18(re)2.5 G(adline).18 E F0(initialization \214le)2.5
+E F1 -.45(AU)72 434.4 S(THORS).45 E F0(Brian F)144 446.4 Q(ox, Free Softw)-.15
+E(are F)-.1 E(oundation \(primary author\))-.15 E(bfox@ai.MIT)144 458.4 Q(.Edu)
+-.74 E(Chet Rame)144 475.2 Q 1.3 -.65(y, C)-.15 H(ase W).65 E(estern Reserv)-.8
+E 2.5(eU)-.15 G(ni)296.66 475.2 Q -.15(ve)-.25 G(rsity).15 E(chet@ins.CWR)144
+487.2 Q(U.Edu)-.4 E F1 -.09(BU)72 504 S 2.25(GR).09 G(EPOR)100.161 504 Q(TS)
+-.36 E F0 .691(If you \214nd a b)108 516 R .691(ug in)-.2 F F3 -.18(re)3.191 G
+(adline,).18 E F0 .691(you should report it.)3.191 F .69
+(But \214rst, you should mak)5.69 F 3.19(es)-.1 G .69
+(ure that it really is a b)436.35 516 R(ug,)-.2 E
+(and that it appears in the latest v)108 528 Q(ersion of the)-.15 E F3 -.18(re)
+2.5 G(adline).18 E F0(library that you ha)2.5 E -.15(ve)-.2 G(.).15 E 10.782
+(Once you ha)108 544.8 R 11.082 -.15(ve d)-.2 H 10.782(etermined that a b).15 F
+10.782(ug actually e)-.2 F 10.783(xists, mail a b)-.15 F 10.783(ug report to)
+-.2 F F2(bash\255maintainer)108 556.8 Q(s)-.1 E F0(@)A F2(pr)A(ep.ai.MIT)-.37 E
+(.Edu)-.74 E F0 5.169(.I)C 2.669(fy)267.359 556.8 S .169(ou ha)278.358 556.8 R
+.469 -.15(ve a \214)-.2 H .168(x, you are welcome to mail that as well!).15 F
+(Suggestions)5.168 E 2(and `philosophical' b)108 568.8 R 2.001
+(ug reports may be mailed to)-.2 F F2 -.2(bu)4.501 G(g-bash).2 E F0(@)A F2(pr)A
+(ep.ai.MIT)-.37 E(.Edu)-.74 E F0 2.001(or posted to the Usenet)4.501 F(ne)108
+580.8 Q(wsgroup)-.25 E F3(gnu.bash.b)2.5 E(ug)-.2 E F0(.)A(Comments and b)108
+597.6 Q(ug reports concerning this manual page should be directed to)-.2 E F2
+-.15(ch)2.5 G(et@ins.CWR).15 E -.25(U.)-.4 G(Edu).25 E F0(.).25 E F1 -.09(BU)72
+614.4 S(GS).09 E F0(It')108 626.4 Q 2.5(st)-.55 G(oo big and too slo)126.06
+626.4 Q -.65(w.)-.25 G 184.005(GNU 1994)72 768 R(July 26)2.5 E(12)530 768 Q EP
+%%Trailer
+end
+%%EOF
diff --git a/documentation/readline.txt b/documentation/readline.txt
new file mode 100644 (file)
index 0000000..653a984
--- /dev/null
@@ -0,0 +1,1122 @@
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+NAME
+     readline - get a line from a user with editing
+
+SYNOPSIS
+     #include <readline.h>
+     #include <history.h>
+
+     typedef int Function ();
+
+     char *readline (prompt)
+     char *prompt;
+
+     int rl_add_defun (name, function, key)
+     char *name;
+     Function *function;
+     int key;
+
+     int rl_bind_key (key, function)
+     int key;
+     Function *function;
+
+     int rl_unbind_key (key)
+     int key;
+
+     int rl_bind_key_in_map (key, function, keymap)
+     int key;
+     Function *function;
+     Keymap keymap;
+
+     int rl_unbind_key_in_map (key, keymap)
+     int key;
+     Keymap keymap;
+
+     int rl_macro_bind (keyseq, macro, keymap)
+     char *keyseq, *macro;
+     Keymap keymap;
+
+     int rl_variable_bind (variable, value)
+     char *variable, *value;
+
+     int rl_parse_and_bind (line)
+     char *line;
+
+     int rl_translate_keyseq (keyseq, array, len)
+     char *keyseq, *array;
+     int *len;
+
+     Function *rl_named_function (command)
+     char *command;
+
+     Function *rl_function_of_keyseq (keyseq, keymap, type)
+     char *keyseq;
+
+
+
+GNU                 Last change: 1994 July 26                   1
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+     Keymap keymap;
+     int *type;
+
+     char **rl_invoking_keyseqs (function)
+     Function *function;
+
+     char **rl_invoking_keyseqs_in_map (function, keymap)
+     Function *function;
+     Keymap keymap;
+
+     void rl_function_dumper (readable)
+     int readable;
+
+     char **rl_funmap_names ()
+
+COPYRIGHT
+     Readline is Copyright (C) 1989, 1991 by  the  Free  Software
+     Foundation, Inc.
+
+DESCRIPTION
+     readline will read a line from the terminal and  return  it,
+     using  prompt  as a prompt.  If prompt is null, no prompt is
+     issued.  The line returned is allocated with  _\bm_\ba_\bl_\bl_\bo_\bc(3),  so
+     the  caller  must  free it when finished.  The line returned
+     has the final newline removed, so only the text of the  line
+     remains.
+
+     readline offers  editing  capabilities  while  the  user  is
+     entering  the  line.   By default, the line editing commands
+     are similar to those of  emacs.   A  vi-style  line  editing
+     interface is also available.
+
+     In  the  following  descriptions,  keymap  can  be  one   of
+     _\be_\bm_\ba_\bc_\bs__\bk_\be_\by_\bm_\ba_\bp,      _\be_\bm_\ba_\bc_\bs__\bm_\be_\bt_\ba__\bk_\be_\by_\bm_\ba_\bp,     _\be_\bm_\ba_\bc_\bs__\bc_\bt_\bl_\bx__\bk_\be_\by_\bm_\ba_\bp,
+     _\bv_\bi__\bi_\bn_\bs_\be_\br_\bt_\bi_\bo_\bn__\bk_\be_\by_\bm_\ba_\bp, _\bo_\br _\bv_\bi__\bm_\bo_\bv_\be_\bm_\be_\bn_\bt__\bk_\be_\by_\bm_\ba_\bp.
+
+     rl_add_defun makes name appear as a bindable  readline  com-
+     mand,  and  makes  function be the function called when that
+     command is invoked.  If key is not -1, it is bound to  func-
+     tion in the current keymap.
+
+     rl_bind_key causes key to invoke function.  The  binding  is
+     made in the current keymap.
+
+     rl_unbind_key removes the binding for  key  in  the  current
+     keymap.
+
+     rl_bind_key_in_map makes the  key  entry  in  keymap  invoke
+     function.
+
+     rl_unbind_key_in_map removes the binding for key  in  keymap
+     keymap.
+
+
+
+GNU                 Last change: 1994 July 26                   2
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+     rl_macro_bind makes keyseq insert  the  string  macro.   The
+     binding is performed in keymap.
+
+     rl_variable_bind sets the value  of  the  readline  variable
+     variable to value.
+
+     rl_parse_and_bind takes as an argument a line  of  the  same
+     form  as  the readline startup file (see INITIALIZATION FILE
+     below) and executes the commands therein.
+
+     rl_translate_keyseq converts keyseq into a new string, stor-
+     ing  the  result in array.  This translates control and meta
+     prefixes and the readline character  escape  sequences  (see
+     Key  Bindings below).  The length of the translated sequence
+     is returned in *len.
+
+     rl_named_function returns the function that is executed when
+     the readline command command is invoked.
+
+     rl_function_of_keyseq returns the function that is  executed
+     when  keyseq is read and keymap is the current keymap.  type
+     is set to indicate whether the return value corresponds to a
+     function, macro, or auxiliary keymap.
+
+     rl_invoking_keyseqs returns all of the key sequences in  the
+     current keymap that invoke function.
+
+     rl_invoking_keyseqs_in_map returns all of the key  sequences
+     in keymap that invoke function.
+
+     rl_function_dumper prints all of the readline functions  and
+     their  bindings  to the readline output stream.  If readable
+     is non-zero, the output is formattted so that it can be read
+     back in to restore the bindings.
+
+     rl_funmap_names returns an array of all known readline bind-
+     able function names.  The array is sorted.
+
+RETURN VALUE
+     readline returns the text of the line read.   A  blank  line
+     returns the empty string.  If EOF is encountered while read-
+     ing a line, and the line is empty, NULL is returned.  If  an
+     EOF  is  read with a non-empty line, it is treated as a new-
+     line.
+
+     Unless otherwise stated, the other  functions  return  0  on
+     success and non-zero on failure.
+
+NOTATION
+     An emacs-style notation is used to denote keystrokes.   Con-
+     trol  keys  are denoted by C-_\bk_\be_\by, e.g., C-n means Control-N.
+     Similarly, _\bm_\be_\bt_\ba keys are denoted  by  M-_\bk_\be_\by,  so  M-x  means
+
+
+
+GNU                 Last change: 1994 July 26                   3
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+     Meta-X.   (On keyboards without a _\bm_\be_\bt_\ba key, M-_\bx means ESC _\bx,
+     i.e., press the Escape key then the _\bx key.  This  makes  ESC
+     the _\bm_\be_\bt_\ba _\bp_\br_\be_\bf_\bi_\bx.  The combination M-C-_\bx means ESC-Control-_\bx,
+     or press the Escape key then  hold  the  Control  key  while
+     pressing the _\bx key.)
+
+     Readline commands may be given numeric _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs, which nor-
+     mally  act as a repeat count.  Sometimes, however, it is the
+     sign of the argument that is significant.  Passing  a  nega-
+     tive  argument  to a command that acts in the forward direc-
+     tion (e.g., kill-line) causes that command to act in a back-
+     ward  direction.   Commands  whose  behavior  with arguments
+     deviates from this are noted.
+
+     When a command  is  described  as  _\bk_\bi_\bl_\bl_\bi_\bn_\bg  text,  the  text
+     deleted  is  saved  for possible future retrieval (_\by_\ba_\bn_\bk_\bi_\bn_\bg).
+     The killed text is saved in a _\bk_\bi_\bl_\bl-_\br_\bi_\bn_\bg.  Consecutive  kills
+     cause the text to be accumulated into one unit, which can be
+     yanked all at once. Commands which do not kill text separate
+     the chunks of text on the kill-ring.
+
+INITIALIZATION FILE
+     Readline is customized by putting commands in an initializa-
+     tion file.  The name of this file is taken from the value of
+     the INPUTRC  variable.   If  that  variable  is  unset,  the
+     default  is ~/._\bi_\bn_\bp_\bu_\bt_\br_\bc.  When a program which uses the read-
+     line library starts up, the init file is read, and  the  key
+     bindings  and variables are set.  There are only a few basic
+     constructs allowed in the readline init file.   Blank  lines
+     are  ignored.  Lines beginning with a # are comments.  Lines
+     beginning with a $ indicate conditional  constructs.   Other
+     lines  denote key bindings and variable settings.  Each pro-
+     gram using this library may add its own commands  and  bind-
+     ings.
+
+     For example, placing
+
+          M-Control-u: universal-argument
+     or
+          C-Meta-u: universal-argument
+     into the ~/._\bi_\bn_\bp_\bu_\bt_\br_\bc would make M-C-u  execute  the  readline
+     command _\bu_\bn_\bi_\bv_\be_\br_\bs_\ba_\bl-_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt.
+
+     The following symbolic character names are recognized  while
+     processing  key  bindings:  _\bR_\bU_\bB_\bO_\bU_\bT,  _\bD_\bE_\bL, _\bE_\bS_\bC, _\bL_\bF_\bD, _\bN_\bE_\bW_\bL_\bI_\bN_\bE,
+     _\bR_\bE_\bT, _\bR_\bE_\bT_\bU_\bR_\bN, _\bS_\bP_\bC, _\bS_\bP_\bA_\bC_\bE, and _\bT_\bA_\bB.  In  addition  to  command
+     names,  readline allows keys to be bound to a string that is
+     inserted when the key is pressed (a _\bm_\ba_\bc_\br_\bo).
+
+  Key Bindings
+     The syntax for controlling key bindings  in  the  ~/._\bi_\bn_\bp_\bu_\bt_\br_\bc
+     file  is  simple.   All  that is required is the name of the
+
+
+
+GNU                 Last change: 1994 July 26                   4
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+     command or the text of a macro and a key sequence  to  which
+     it  should be bound. The name may be specified in one of two
+     ways: as a symbolic key name, possibly with  _\bM_\be_\bt_\ba-  or  _\bC_\bo_\bn_\b-
+     _\bt_\br_\bo_\bl-  prefixes,  or as a key sequence.  When using the form
+     keyname:_\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn-_\bn_\ba_\bm_\be or _\bm_\ba_\bc_\br_\bo, _\bk_\be_\by_\bn_\ba_\bm_\be is the name of a key
+     spelled out in English.  For example:
+
+          Control-u: universal-argument
+          Meta-Rubout: backward-kill-word
+          Control-o: ">&output"
+
+     In  the  above  example,  _\bC-_\bu  is  bound  to  the   function
+     universal-argument,   _\bM-_\bD_\bE_\bL   is   bound   to  the  function
+     backward-kill-word, and  _\bC-_\bo  is  bound  to  run  the  macro
+     expressed  on  the  right  hand side (that is, to insert the
+     text >&_\bo_\bu_\bt_\bp_\bu_\bt into the line).
+
+     In the second form, "keyseq":_\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn-_\bn_\ba_\bm_\be or _\bm_\ba_\bc_\br_\bo,  keyseq
+     differs  from  keyname  above  in  that  strings denoting an
+     entire key sequence may be specified by placing the sequence
+     within  double quotes.  Some GNU Emacs style key escapes can
+     be used, as in the following example.
+
+          "\C-u": universal-argument
+          "\C-x\C-r": re-read-init-file
+          "\e[11~": "Function Key 1"
+
+     In  this  example,  _\bC-_\bu  is  again  bound  to  the  function
+     universal-argument.   _\bC-_\bx  _\bC-_\br  is  bound  to  the  function
+     re-read-init-file, and _\bE_\bS_\bC [ _\b1 _\b1 ~ is bound  to  insert  the
+     text Function Key 1.  The full set of escape sequences is
+
+          \C-  control prefix
+
+          \M-  meta prefix
+
+          \e   an escape character
+
+          \\   backslash
+
+          " \" literal "
+
+          \'   literal '
+
+     When entering the text of a macro, single or  double  quotes
+     should  be  used  to  indicate a macro definition.  Unquoted
+     text is assumed to be a function name.  Backslash will quote
+     any character in the macro text, including " and '.
+
+     Bash  allows  the  current  readline  key  bindings  to   be
+     displayed  or  modified  with the bind builtin command.  The
+     editing mode may be switched during interactive use by using
+
+
+
+GNU                 Last change: 1994 July 26                   5
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+     the  -o  option  to the set builtin command.  Other programs
+     using this library provide similar mechanisms.  The  _\bi_\bn_\bp_\bu_\bt_\br_\bc
+     file may be edited and re-read if a program does not provide
+     any other means to incorporate new bindings.
+
+  Variables
+     Readline has variables that can be used to further customize
+     its  behavior.   A  variable  may be set in the _\bi_\bn_\bp_\bu_\bt_\br_\bc file
+     with a statement of the form
+
+          set _\bv_\ba_\br_\bi_\ba_\bb_\bl_\be-_\bn_\ba_\bm_\be _\bv_\ba_\bl_\bu_\be
+
+     Except where noted, readline variables can take  the  values
+     On or Off.  The variables and their default values are:
+
+     horizontal-scroll-mode (Off)
+          When set to On, makes readline use a  single  line  for
+          display,  scrolling  the input horizontally on a single
+          screen line when it  becomes  longer  than  the  screen
+          width rather than wrapping to a new line.
+     editing-mode (emacs)
+          Controls whether readline begins  with  a  set  of  key
+          bindings  similar  to _\be_\bm_\ba_\bc_\bs or _\bv_\bi.  editing-mode can be
+          set to either emacs or vi.
+     mark-modified-lines (Off)
+          If set to On, history lines that have been modified are
+          displayed with a preceding asterisk (*).
+     bell-style (audible)
+          Controls what happens when readline wants to  ring  the
+          terminal  bell.   If  set to none, readline never rings
+          the bell.  If set to visible, readline uses  a  visible
+          bell  if one is available.  If set to audible, readline
+          attempts to ring the terminal's bell.
+     comment-begin (``#'')
+          The string  that  is  inserted  in  vi  mode  when  the
+          vi-comment command is executed.
+     meta-flag (Off)
+          If set to On,  readline  will  enable  eight-bit  input
+          (that is, it will not strip the high bit from the char-
+          acters it  reads),  regardless  of  what  the  terminal
+          claims it can support.
+     convert-meta (On)
+          If set to On, readline will convert characters with the
+          eighth  bit  set  to an ASCII key sequence by stripping
+          the eighth bit and prepending an escape  character  (in
+          effect, using escape as the _\bm_\be_\bt_\ba _\bp_\br_\be_\bf_\bi_\bx).
+     output-meta (Off)
+          If set to On, readline will display characters with the
+          eighth  bit set directly rather than as a meta-prefixed
+          escape sequence.
+     completion-query-items (100)
+          This determines when the user is queried about  viewing
+
+
+
+GNU                 Last change: 1994 July 26                   6
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+          the  number  of  possible  completions generated by the
+          possible-completions command.  It may  be  set  to  any
+          integer  value  greater  than or equal to zero.  If the
+          number of possible completions is greater than or equal
+          to  the  value  of  this  variable,  the  user is asked
+          whether or not he wishes to view them;  otherwise  they
+          are simply listed on the terminal.
+     keymap (emacs)
+          Set the current readline keymap.  The set of legal key-
+          map  names is _\be_\bm_\ba_\bc_\bs, _\be_\bm_\ba_\bc_\bs-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd, _\be_\bm_\ba_\bc_\bs-_\bm_\be_\bt_\ba, _\be_\bm_\ba_\bc_\bs-
+          _\bc_\bt_\bl_\bx, _\bv_\bi, _\bv_\bi-_\bm_\bo_\bv_\be, _\bv_\bi-_\bc_\bo_\bm_\bm_\ba_\bn_\bd, and  _\bv_\bi-_\bi_\bn_\bs_\be_\br_\bt.   _\bv_\bi  is
+          equivalent   to  _\bv_\bi-_\bc_\bo_\bm_\bm_\ba_\bn_\bd;  _\be_\bm_\ba_\bc_\bs  is  equivalent  to
+          _\be_\bm_\ba_\bc_\bs-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd.  The default value is _\be_\bm_\ba_\bc_\bs; the  value
+          of editing-mode also affects the default keymap.
+     show-all-if-ambiguous (Off)
+          This alters the  default  behavior  of  the  completion
+          functions.   If  set  to on, words which have more than
+          one possible completion cause the matches to be  listed
+          immediately instead of ringing the bell.
+     expand-tilde (Off)
+          If set to on, tilde expansion is performed  when  read-
+          line attempts word completion.
+
+  Conditional Constructs
+     Readline implements a facility similar in spirit to the con-
+     ditional  compilation  features  of the C preprocessor which
+     allows key bindings and variable settings to be performed as
+     the  result  of  tests.   There  are three parser directives
+     used.
+
+     $if  The $if construct allows bindings to be made  based  on
+          the  editing  mode,  the  terminal  being  used, or the
+          application using  readline.   The  text  of  the  test
+          extends  to  the  end  of  the  line; no characters are
+          required to isolate it.
+
+          mode The mode= form of the $if  directive  is  used  to
+               test  whether  readline  is  in  emacs or vi mode.
+               This may be used in conjunction with the set  key-
+               map  command, for instance, to set bindings in the
+               _\be_\bm_\ba_\bc_\bs-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd  and  _\be_\bm_\ba_\bc_\bs-_\bc_\bt_\bl_\bx  keymaps  only  if
+               readline is starting out in emacs mode.
+
+          term The term= form may be used  to  include  terminal-
+               specific  key  bindings,  perhaps  to bind the key
+               sequences output by the terminal's function  keys.
+               The  word  on  the  right  side of the = is tested
+               against the full name of the terminal and the por-
+               tion  of  the  terminal  name  before the first -.
+               This allows _\bs_\bu_\bn to match both _\bs_\bu_\bn and _\bs_\bu_\bn-_\bc_\bm_\bd, for
+               instance.
+
+
+
+
+GNU                 Last change: 1994 July 26                   7
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+          application
+               The  application  construct  is  used  to  include
+               application-specific settings.  Each program using
+               the readline library sets  the  _\ba_\bp_\bp_\bl_\bi_\bc_\ba_\bt_\bi_\bo_\bn  _\bn_\ba_\bm_\be,
+               and an initialization file can test for a particu-
+               lar  value.   This  could  be  used  to  bind  key
+               sequences  to functions useful for a specific pro-
+               gram.  For instance, the following command adds  a
+               key  sequence  that quotes the current or previous
+               word in Bash:
+               $if bash
+               # Quote the current or previous word
+               "\C-xq": "\eb\"\ef\""
+               $endif
+
+     $endif
+          This command, as you saw in the previous example,  ter-
+          minates an $if command.
+
+     $else
+          Commands in this branch of the $if directive  are  exe-
+          cuted if the test fails.
+
+EDITING COMMANDS
+     The following is a list of the names of the commands and the
+     default key sequences to which they are bound.
+
+  Commands for Moving
+     beginning-of-line (C-a)
+          Move to the start of the current line.
+     end-of-line (C-e)
+          Move to the end of the line.
+     forward-char (C-f)
+          Move forward a character.
+     backward-char (C-b)
+          Move back a character.
+     forward-word (M-f)
+          Move forward to the end of the next  word.   Words  are
+          composed   of   alphanumeric  characters  (letters  and
+          digits).
+     backward-word (M-b)
+          Move back to the start of this, or the previous,  word.
+          Words  are composed of alphanumeric characters (letters
+          and digits).
+     clear-screen (C-l)
+          Clear the screen leaving the current line at the top of
+          the screen.  With an argument, refresh the current line
+          without clearing the screen.
+     redraw-current-line
+          Refresh the current line.  By default, this is unbound.
+
+
+
+
+
+GNU                 Last change: 1994 July 26                   8
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+  Commands for Manipulating the History
+     accept-line (Newline, Return)
+          Accept the line regardless of where the cursor is.   If
+          this  line is non-empty, add it to the history list. If
+          the line is a modified history line, then  restore  the
+          history line to its original state.
+     previous-history (C-p)
+          Fetch the previous command from the history list,  mov-
+          ing back in the list.
+     next-history (C-n)
+          Fetch the next command from the  history  list,  moving
+          forward in the list.
+     beginning-of-history (M-<)
+          Move to the first line in the history.
+     end-of-history (M->)
+          Move to the end of the input history,  i.e.,  the  line
+          currently being entered.
+     reverse-search-history (C-r)
+          Search backward starting at the current line and moving
+          `up'  through  the  history  as  necessary.  This is an
+          incremental search.
+     forward-search-history (C-s)
+          Search forward starting at the current line and  moving
+          `down'  through  the  history as necessary.  This is an
+          incremental search.
+     non-incremental-reverse-search-history (M-p)
+          Search backward through the  history  starting  at  the
+          current  line  using  a  non-incremental  search  for a
+          string supplied by the user.
+     non-incremental-forward-search-history (M-n)
+          Search   forward   through   the   history   using    a
+          non-incremental  search  for  a  string supplied by the
+          user.
+     history-search-forward
+          Search forward through the history for  the  string  of
+          characters  between  the  start of the current line and
+          the current point.  This is a  non-incremental  search.
+          By default, this command is unbound.
+     history-search-backward
+          Search backward through the history for the  string  of
+          characters  between  the  start of the current line and
+          the current point.  This is a  non-incremental  search.
+          By default, this command is unbound.
+     yank-nth-arg (M-C-y)
+          Insert the first argument to the previous command (usu-
+          ally  the  second  word  on the previous line) at point
+          (the current cursor position).   With  an  argument  _\bn,
+          insert  the  _\bnth  word  from  the previous command (the
+          words in the previous command begin with  word  0).   A
+          negative  argument inserts the _\bnth word from the end of
+          the previous command.
+     yank-last-arg (M-., M-_)
+
+
+
+GNU                 Last change: 1994 July 26                   9
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+          Insert the last argument to the previous  command  (the
+          last  word  on  the  previous line).  With an argument,
+          behave exactly like yank-nth-arg.
+
+  Commands for Changing Text
+     delete-char (C-d)
+          Delete the character under the cursor.  If point is  at
+          the  beginning  of the line, there are no characters in
+          the line, and the last character  typed  was  not  C-d,
+          then return EOF.
+     backward-delete-char (Rubout)
+          Delete the character behind the cursor.  When  given  a
+          numeric   argument,   save  the  deleted  text  on  the
+          kill-ring.
+     quoted-insert (C-q, C-v)
+          Add the next character that you type to the line verba-
+          tim.   This  is  how to insert characters like C-q, for
+          example.
+     tab-insert (M-TAB)
+          Insert a tab character.
+     self-insert (a, b, A, 1, !, ...)
+          Insert the character typed.
+     transpose-chars (C-t)
+          Drag the character before point forward over the  char-
+          acter at point.  Point moves forward as well.  If point
+          is at the end of the line, then transpose the two char-
+          acters before point.  Negative arguments don't work.
+     transpose-words (M-t)
+          Drag the word behind the cursor past the word in  front
+          of the cursor moving the cursor over that word as well.
+     upcase-word (M-u)
+          Uppercase the current  (or  following)  word.   With  a
+          negative  argument,  do  the  previous word, but do not
+          move point.
+     downcase-word (M-l)
+          Lowercase the current  (or  following)  word.   With  a
+          negative  argument,  do  the  previous word, but do not
+          move point.
+     capitalize-word (M-c)
+          Capitalize the current (or  following)  word.   With  a
+          negative  argument,  do  the  previous word, but do not
+          move point.
+
+  Killing and Yanking
+     kill-line (C-k)
+          Kill the text from the current cursor position  to  the
+          end of the line.
+     backward-kill-line (C-x Rubout)
+          Kill backward to the beginning of the line.
+     unix-line-discard (C-u)
+          Kill backward from point to the beginning of the line.
+     kill-whole-line
+
+
+
+GNU                 Last change: 1994 July 26                  10
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+          Kill all characters on  the  current  line,  no  matter
+          where the cursor is.  By default, this is unbound.
+     kill-word (M-d)
+          Kill from the cursor to the end of the current word, or
+          if  between  words,  to the end of the next word.  Word
+          boundaries are the same as those used by forward-word.
+     backward-kill-word (M-Rubout)
+          Kill the word behind the cursor.  Word  boundaries  are
+          the same as those used by backward-word.
+     unix-word-rubout (C-w)
+          Kill the word behind the cursor, using white space as a
+          word  boundary.  The word boundaries are different from
+          backward-kill-word.
+     delete-horizontal-space
+          Delete all spaces and tabs around point.   By  default,
+          this is unbound.
+     yank (C-y)
+          Yank the top of the kill ring into the  buffer  at  the
+          cursor.
+     yank-pop (M-y)
+          Rotate the kill-ring, and yank the new top.  Only works
+          following yank or yank-pop.
+
+  Numeric Arguments
+     digit-argument (M-0, M-1, ..., M--)
+          Add this digit to the argument already accumulating, or
+          start a new argument.  M-- starts a negative argument.
+     universal-argument
+          Each time this is executed, the argument count is  mul-
+          tiplied  by four.  The argument count is initially one,
+          so executing this function the  first  time  makes  the
+          argument  count four.  By default, this is not bound to
+          a key.
+
+  Completing
+     complete (TAB)
+          Attempt to perform completion on the text before point.
+          The   actual   completion   performed  is  application-
+          specific.   Bash,  for  instance,  attempts  completion
+          treating  the  text  as  a variable (if the text begins
+          with $), username (if the text begins with ~), hostname
+          (if  the  text  begins  with  @), or command (including
+          aliases and functions) in turn.  If none of these  pro-
+          duces  a match, filename completion is attempted.  Gdb,
+          on the other hand, allows completion of  program  func-
+          tions and variables, and only attempts filename comple-
+          tion under certain circumstances.
+     possible-completions (M-?)
+          List the possible completions of the text before point.
+     insert-completions
+          Insert all completions of the text  before  point  that
+          would  have been generated by possible-completions.  By
+
+
+
+GNU                 Last change: 1994 July 26                  11
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+          default, this is not bound to a key.
+
+  Keyboard Macros
+     start-kbd-macro (C-x ()
+          Begin saving the characters typed into the current key-
+          board macro.
+     end-kbd-macro (C-x ))
+          Stop saving the characters typed into the current  key-
+          board macro and save the definition.
+     call-last-kbd-macro (C-x e)
+          Re-execute the last keyboard macro defined,  by  making
+          the  characters  in the macro appear as if typed at the
+          keyboard.
+
+  Miscellaneous
+     re-read-init-file (C-x C-r)
+          Read in the contents of your init file, and incorporate
+          any bindings or variable assignments found there.
+     abort (C-g)
+          Abort  the  current  editing  command  and   ring   the
+          terminal's bell (subject to the setting of bell-style).
+     do-uppercase-version (M-a, M-b, ...)
+          Run the command that  is  bound  to  the  corresponding
+          uppercase character.
+     prefix-meta (ESC)
+          Metafy the next character typed.  ESC f  is  equivalent
+          to Meta-f.
+     undo (C-_, C-x C-u)
+          Incremental undo, separately remembered for each line.
+     revert-line (M-r)
+          Undo all changes made to this line.  This is like  typ-
+          ing the undo command enough times to return the line to
+          its initial state.
+     tilde-expand (M-~)
+          Perform tilde expansion on the current word.
+     dump-functions
+          Print all of the functions and their  key  bindings  to
+          the  readline  output stream.  If a numeric argument is
+          supplied, the output is formatted in such a way that it
+          can be made part of an _\bi_\bn_\bp_\bu_\bt_\br_\bc file.
+     emacs-editing-mode (C-e)
+          When in vi editing mode, this causes a switch to  emacs
+          editing mode.
+     vi-editing-mode (M-C-j)
+          When in emacs editing mode, this causes a switch to  vi
+          editing mode.
+
+DEFAULT KEY BINDINGS
+     The following is a list of the default emacs  and  vi  bind-
+     ings.   Characters  with  the  8th bit set are written as M-
+     <character>, and are referred  to  as  _\bm_\be_\bt_\ba_\bf_\bi_\be_\bd  characters.
+     The  printable ASCII characters not mentioned in the list of
+
+
+
+GNU                 Last change: 1994 July 26                  12
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+     emacs standard bindings are bound to the  _\bs_\be_\bl_\bf-_\bi_\bn_\bs_\be_\br_\bt  func-
+     tion,  which just inserts the given character into the input
+     line.  In vi insertion mode, all characters not specifically
+     mentioned  are bound to _\bs_\be_\bl_\bf-_\bi_\bn_\bs_\be_\br_\bt.  Characters assigned to
+     signal generation by _\bs_\bt_\bt_\by(1) or the terminal driver, such as
+     C-Z  or  C-C,  retain  that  function.  Upper and lower case
+     _\bm_\be_\bt_\ba_\bf_\bi_\be_\bd characters are bound to the same  function  in  the
+     emacs  mode  meta  keymap.   The  remaining  characters  are
+     unbound, which causes readline to ring the bell (subject  to
+     the setting of the bell-style variable).
+
+  Emacs Mode
+           Emacs Standard bindings
+
+           "C-A"                    ->  beginning-of-line
+           "C-B"                    ->  backward-char
+           "C-D"                    ->  delete-char
+           "C-E"                    ->  end-of-line
+           "C-F"                    ->  forward-char
+           "C-G"                    ->  abort
+           "C-H"                    ->  backward-delete-char
+           "C-I"                    ->  complete
+           "C-J"                    ->  accept-line
+           "C-K"                    ->  kill-line
+           "C-L"                    ->  clear-screen
+           "C-M"                    ->  accept-line
+           "C-N"                    ->  next-history
+           "C-P"                    ->  previous-history
+           "C-Q"                    ->  quoted-insert
+           "C-R"                    ->  reverse-search-history
+           "C-S"                    ->  forward-search-history
+           "C-T"                    ->  transpose-chars
+           "C-U"                    ->  unix-line-discard
+           "C-V"                    ->  quoted-insert
+           "C-W"                    ->  unix-word-rubout
+           "C-Y"                    ->  yank
+           "C-_"                    ->  undo
+           " " to "/"               ->  self-insert
+           "0"  to "9"              ->  self-insert
+           ":"  to "~"              ->  self-insert
+           "C-?"                    ->  backward-delete-char
+
+           Emacs Meta bindings
+
+           "M-C-H"                  ->  backward-kill-word
+           "M-C-I"                  ->  tab-insert
+           "M-C-J"                  ->  vi-editing-mode
+           "M-C-M"                  ->  vi-editing-mode
+           "M-C-R"                  ->  revert-line
+           "M-C-Y"                  ->  yank-nth-arg
+           "M-C-["                  ->  complete
+           "M-&"                    ->  tilde-expand
+
+
+
+GNU                 Last change: 1994 July 26                  13
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+           "M--"                    ->  digit-argument
+           "M-0"                    ->  digit-argument
+           "M-1"                    ->  digit-argument
+           "M-2"                    ->  digit-argument
+           "M-3"                    ->  digit-argument
+           "M-4"                    ->  digit-argument
+           "M-5"                    ->  digit-argument
+           "M-6"                    ->  digit-argument
+           "M-7"                    ->  digit-argument
+           "M-8"                    ->  digit-argument
+           "M-9"                    ->  digit-argument
+           "M-<"                    ->  beginning-of-history
+           "M->"                    ->  end-of-history
+           "M-?"                    ->  possible-completions
+           "M-B"                    ->  backward-word
+           "M-C"                    ->  capitalize-word
+           "M-D"                    ->  kill-word
+           "M-F"                    ->  forward-word
+           "M-L"                    ->  downcase-word
+           "M-N"                    ->  non-incremental-forward-search-history
+           "M-O"                    ->  arrow-key-prefix
+           "M-P"                    ->  non-incremental-reverse-search-history
+           "M-R"                    ->  revert-line
+           "M-T"                    ->  transpose-words
+           "M-U"                    ->  upcase-word
+           "M-Y"                    ->  yank-pop
+           "M-C-Y"                  ->  yank-nth-arg
+           "M-C-?"                  ->  backward-delete-word
+
+           Emacs Control-X bindings
+
+           "C-XC-G"                 ->  abort
+           "C-XC-R"                 ->  re-read-init-file
+           "C-XC-U"                 ->  undo
+           "C-X("                   ->  start-kbd-macro
+           "C-X)"                   ->  end-kbd-macro
+           "C-Xe"                   ->  call-last-kbd-macro
+           "C-XC-?"                 ->  backward-kill-line
+
+
+  VI Mode bindings
+           VI Insert Mode functions
+
+           "C-D"                    ->  vi-eof-maybe
+           "C-H"                    ->  backward-delete-char
+           "C-I"                    ->  complete
+           "C-J"                    ->  accept-line
+           "C-K"                    ->  kill-line
+           "C-L"                    ->  clear-screen
+           "C-M"                    ->  accept-line
+           "C-N"                    ->  next-history
+           "C-P"                    ->  previous-history
+
+
+
+GNU                 Last change: 1994 July 26                  14
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+           "C-Q"                    ->  quoted-insert
+           "C-R"                    ->  reverse-search-history
+           "C-S"                    ->  forward-search-history
+           "C-T"                    ->  transpose-chars
+           "C-U"                    ->  unix-line-discard
+           "C-V"                    ->  quoted-insert
+           "C-W"                    ->  unix-word-rubout
+           "C-Y"                    ->  yank
+           "C-["                    ->  vi-movement-mode
+           " " to "~"               ->  self-insert
+           "C-?"                    ->  backward-delete-char
+
+           VI Command Mode functions
+
+           "C-D"                    ->  vi-eof-maybe
+           "C-E"                    ->  emacs-editing-mode
+           "C-G"                    ->  abort
+           "C-H"                    ->  backward-char
+           "C-J"                    ->  accept-line
+           "C-K"                    ->  kill-line
+           "C-L"                    ->  clear-screen
+           "C-M"                    ->  accept-line
+           "C-N"                    ->  next-history
+           "C-P"                    ->  previous-history
+           "C-Q"                    ->  quoted-insert
+           "C-R"                    ->  reverse-search-history
+           "C-S"                    ->  forward-search-history
+           "C-T"                    ->  transpose-chars
+           "C-U"                    ->  unix-line-discard
+           "C-V"                    ->  quoted-insert
+           "C-W"                    ->  unix-word-rubout
+           "C-Y"                    ->  yank
+           "C-["                    ->  abort
+           " "                      ->  forward-char
+           "#"                      ->  vi-comment
+           "$"                      ->  end-of-line
+           "%"                      ->  vi-match
+           "&"                      ->  vi-tilde-expand
+           "*"                      ->  vi-complete
+           "+"                      ->  down-history
+           ","                      ->  vi-char-search
+           "-"                      ->  previous-history
+           "."                      ->  vi-redo
+           "/"                      ->  vi-search
+           "0"                      ->  beginning-of-line
+           "1" to "9"               ->  vi-arg-digit
+           ";"                      ->  vi-char-search
+           "="                      ->  vi-complete
+           "?"                      ->  vi-search
+           "@"                      ->  is undefined
+           "A"                      ->  vi-append-eol
+           "B"                      ->  vi-prev-word
+
+
+
+GNU                 Last change: 1994 July 26                  15
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+           "C"                      ->  vi-change-to
+           "D"                      ->  vi-delete-to
+           "E"                      ->  vi-end-word
+           "F"                      ->  vi-char-search
+           "I"                      ->  vi-insert-beg
+           "N"                      ->  vi-search-again
+           "P"                      ->  vi-put
+           "R"                      ->  vi-replace
+           "S"                      ->  vi-subst
+           "T"                      ->  vi-char-search
+           "U"                      ->  revert-line
+           "W"                      ->  vi-next-word
+           "X"                      ->  backward-delete-char
+           "Y"                      ->  vi-yank-to
+           "\"                      ->  vi-complete
+           "^"                      ->  vi-first-print
+           "_"                      ->  vi-yank-arg
+           "a"                      ->  vi-append-mode
+           "b"                      ->  vi-prev-word
+           "c"                      ->  vi-change-to
+           "d"                      ->  vi-delete-to
+           "e"                      ->  vi-end-word
+           "f"                      ->  vi-char-search
+           "h"                      ->  backward-char
+           "i"                      ->  vi-insertion-mode
+           "j"                      ->  next-history
+           "k"                      ->  prev-history
+           "l"                      ->  forward-char
+           "n"                      ->  vi-search-again
+           "r"                      ->  vi-change-char
+           "s"                      ->  vi-subst
+           "t"                      ->  vi-char-search
+           "u"                      ->  undo
+           "w"                      ->  vi-next-word
+           "x"                      ->  vi-delete
+           "y"                      ->  vi-yank-to
+           "|"                      ->  vi-column
+           "~"                      ->  vi-change-case
+
+SEE ALSO
+     _\bT_\bh_\be _\bG_\bn_\bu _\bR_\be_\ba_\bd_\bl_\bi_\bn_\be _\bL_\bi_\bb_\br_\ba_\br_\by, Brian Fox and Chet Ramey
+     _\bT_\bh_\be _\bG_\bn_\bu _\bH_\bi_\bs_\bt_\bo_\br_\by _\bL_\bi_\bb_\br_\ba_\br_\by, Brian Fox and Chet Ramey
+     _\bb_\ba_\bs_\bh(1)
+
+FILES
+     ~/._\bi_\bn_\bp_\bu_\bt_\br_\bc
+          Individual readline initialization file
+
+AUTHORS
+          Brian Fox, Free Software Foundation (primary author)
+          bfox@ai.MIT.Edu
+
+
+
+
+GNU                 Last change: 1994 July 26                  16
+
+
+
+
+
+
+READLINE(3)            C LIBRARY FUNCTIONS            READLINE(3)
+
+
+
+          Chet Ramey, Case Western Reserve University
+          chet@ins.CWRU.Edu
+
+BUG REPORTS
+     If you find a bug in readline, you should  report  it.   But
+     first,  you  should  make  sure that it really is a bug, and
+     that it appears  in  the  latest  version  of  the  readline
+     library that you have.
+
+     Once you have determined that a bug actually exists, mail  a
+     bug report to _\bb_\ba_\bs_\bh-_\bm_\ba_\bi_\bn_\bt_\ba_\bi_\bn_\be_\br_\bs@_\bp_\br_\be_\bp._\ba_\bi._\bM_\bI_\bT._\bE_\bd_\bu.  If you have
+     a fix, you are welcome to mail that  as  well!   Suggestions
+     and  `philosophical'  bug  reports  may  be  mailed  to _\bb_\bu_\bg-
+     _\bb_\ba_\bs_\bh@_\bp_\br_\be_\bp._\ba_\bi._\bM_\bI_\bT._\bE_\bd_\bu  or  posted  to  the  Usenet  newsgroup
+     gnu.bash.bug.
+
+     Comments and bug reports concerning this manual page  should
+     be directed to _\bc_\bh_\be_\bt@_\bi_\bn_\bs._\bC_\bW_\bR_\bU._\bE_\bd_\bu.
+
+BUGS
+     It's too big and too slow.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+GNU                 Last change: 1994 July 26                  17
+
+
+
diff --git a/documentation/texinfo.tex b/documentation/texinfo.tex
new file mode 100644 (file)
index 0000000..ce8124e
--- /dev/null
@@ -0,0 +1,4003 @@
+%% TeX macros to handle texinfo files
+
+%   Copyright (C) 1985, 86, 88, 90, 91, 92, 1993 Free Software Foundation, Inc.
+
+%This texinfo.tex 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, or (at
+%your option) any later version.
+
+%This texinfo.tex file 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 texinfo.tex file; see the file COPYING.  If not, write
+%to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+%USA.
+
+
+%In other words, you are welcome to use, share and improve this program.
+%You are forbidden to forbid anyone else to use, share and improve
+%what you give them.   Help stamp out software-hoarding!
+
+\def\texinfoversion{2.108}
+\message{Loading texinfo package [Version \texinfoversion]:}
+
+% Print the version number if in a .fmt file.
+\everyjob{\message{[Texinfo version \texinfoversion]}\message{}}
+
+% Save some parts of plain tex whose names we will redefine.
+
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexdots=\dots
+\let\ptexdot=\.
+\let\ptexstar=\*
+\let\ptexend=\end
+\let\ptexbullet=\bullet
+\let\ptexb=\b
+\let\ptexc=\c
+\let\ptexi=\i
+\let\ptext=\t
+\let\ptexl=\l
+\let\ptexL=\L
+
+\def\tie{\penalty 10000\ }     % Save plain tex definition of ~.
+
+\message{Basics,}
+\chardef\other=12
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset  \bindingoffset=0pt
+\newdimen \normaloffset   \normaloffset=\hoffset
+\newdimen\pagewidth \newdimen\pageheight
+\pagewidth=\hsize \pageheight=\vsize
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal.  We don't just call \tracingall here,
+% since that produces some useless output on the terminal.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{\tracingcommands2 \tracingstats2
+   \tracingpages1 \tracingoutput1 \tracinglostchars1
+   \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+   \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+
+%---------------------Begin change-----------------------
+%
+%%%% For @cropmarks command.
+% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\cornerlong \newdimen\cornerthick
+\newdimen \topandbottommargin
+\newdimen \outerhsize \newdimen \outervsize
+\cornerlong=1pc\cornerthick=.3pt       % These set size of cropmarks
+\outerhsize=7in
+%\outervsize=9.5in
+% Alternative @smallbook page size is 9.25in
+\outervsize=9.25in
+\topandbottommargin=.75in
+%
+%---------------------End change-----------------------
+
+% \onepageout takes a vbox as an argument.  Note that \pagecontents
+% does insertions itself, but you have to call it yourself.
+\chardef\PAGE=255  \output={\onepageout{\pagecontents\PAGE}}
+\def\onepageout#1{\hoffset=\normaloffset
+\ifodd\pageno  \advance\hoffset by \bindingoffset
+\else \advance\hoffset by -\bindingoffset\fi
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}%
+{\let\hsize=\pagewidth \makefootline}}}%
+\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+
+%%%% For @cropmarks command %%%%
+
+% Here is a modification of the main output routine for Near East Publications
+% This provides right-angle cropmarks at all four corners.
+% The contents of the page are centerlined into the cropmarks,
+% and any desired binding offset is added as an \hskip on either
+% site of the centerlined box.  (P. A. MacKay, 12 November, 1986)
+%
+\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+                \shipout
+                \vbox to \outervsize{\hsize=\outerhsize
+                 \vbox{\line{\ewtop\hfill\ewtop}}
+                 \nointerlineskip
+                 \line{\vbox{\moveleft\cornerthick\nstop}
+                       \hfill
+                       \vbox{\moveright\cornerthick\nstop}}
+                 \vskip \topandbottommargin
+                 \centerline{\ifodd\pageno\hskip\bindingoffset\fi
+                       \vbox{
+                       {\let\hsize=\pagewidth \makeheadline}
+                       \pagebody{#1}
+                       {\let\hsize=\pagewidth \makefootline}}
+                       \ifodd\pageno\else\hskip\bindingoffset\fi}
+                \vskip \topandbottommargin plus1fill minus1fill
+                 \boxmaxdepth\cornerthick
+                 \line{\vbox{\moveleft\cornerthick\nsbot}
+                       \hfill
+                       \vbox{\moveright\cornerthick\nsbot}}
+                 \nointerlineskip
+                 \vbox{\line{\ewbot\hfill\ewbot}}
+       }}
+  \advancepageno
+  \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+%
+% Do @cropmarks to get crop marks
+\def\cropmarks{\let\onepageout=\croppageout }
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+%
+% Here are the rules for the cropmarks.  Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+  {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+  {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1.  The argument is the rest of
+% the input line (except we remove a trailing comment).  #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg#1{%
+  \let\next = #1%
+  \begingroup
+    \obeylines
+    \futurelet\temp\parseargx
+}
+
+% If the next token is an obeyed space (from an @example environment or
+% the like), remove it and recurse.  Otherwise, we're done.
+\def\parseargx{%
+  % \obeyedspace is defined far below, after the definition of \sepspaces.
+  \ifx\obeyedspace\temp
+    \expandafter\parseargdiscardspace
+  \else
+    \expandafter\parseargline
+  \fi
+}
+
+% Remove a single space (as the delimiter token to the macro call).
+{\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+{\obeylines %
+  \gdef\parseargline#1^^M{%
+    \endgroup % End of the group started in \parsearg.
+    %
+    % First remove any @c comment, then any @comment.
+    % Result of each macro is put in \toks0.
+    \argremovec #1\c\relax %
+    \expandafter\argremovecomment \the\toks0 \comment\relax %
+    %
+    % Call the caller's macro, saved as \next in \parsearg.
+    \expandafter\next\expandafter{\the\toks0}%
+  }%
+}
+
+% Since all \c{,omment} does is throw away the argument, we can let TeX
+% do that for us.  The \relax here is matched by the \relax in the call
+% in \parseargline; it could be more or less anything, its purpose is
+% just to delimit the argument to the \c.
+\def\argremovec#1\c#2\relax{\toks0 = {#1}}
+\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+%    @end itemize  @c foo
+% will have two active spaces as part of the argument with the
+% `itemize'.  Here we remove all active spaces from #1, and assign the
+% result to \toks0.
+%
+% This loses if there are any *other* active characters besides spaces
+% in the argument -- _ ^ +, for example -- since they get expanded.
+% Fortunately, Texinfo does not define any such commands.  (If it ever
+% does, the catcode of the characters in questionwill have to be changed
+% here.)  But this means we cannot call \removeactivespaces as part of
+% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+% that \parsearg gets might well have any character at all in it.
+%
+\def\removeactivespaces#1{%
+  \begingroup
+    \ignoreactivespaces
+    \edef\temp{#1}%
+    \global\toks0 = \expandafter{\temp}%
+  \endgroup
+}
+
+% Change the active space to expand to nothing.
+%
+\begingroup
+  \obeyspaces
+  \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+\endgroup
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment.  Type Return to continue.}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo  is the same as @foo, for now.
+\newhelp\EMsimple{Type <Return> to continue.}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+% @end foo executes the definition of \Efoo.
+%
+\def\end{\parsearg\endxxx}
+\def\endxxx #1{%
+  \removeactivespaces{#1}%
+  \edef\endthing{\the\toks0}%
+  %
+  \expandafter\ifx\csname E\endthing\endcsname\relax
+    \expandafter\ifx\csname \endthing\endcsname\relax
+      % There's no \foo, i.e., no ``environment'' foo.
+      \errhelp = \EMsimple
+      \errmessage{Undefined command `@end \endthing'}%
+    \else
+      \unmatchedenderror\endthing
+    \fi
+  \else
+    % Everything's ok; the right environment has been started.
+    \csname E\endthing\endcsname
+  \fi
+}
+
+% There is an environment #1, but it hasn't been started.  Give an error.
+%
+\def\unmatchedenderror#1{%
+  \errhelp = \EMsimple
+  \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+}
+
+% Define the control sequence \E#1 to give an unmatched @end error.
+%
+\def\defineunmatchedend#1{%
+  \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+}
+
+
+% Single-spacing is done by various environments (specifically, in
+% \nonfillstart and \quotations).
+\newskip\singlespaceskip \singlespaceskip = \baselineskip
+\def\singlespace{%
+% Why was this kern here?  It messes up equalizing space above and below
+% environments.  --karl, 6may93
+%{\advance \baselineskip by -\singlespaceskip
+%\kern \baselineskip}%
+\baselineskip=\singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt \char '100}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+
+\def\mylbrace {{\tt \char '173}}
+\def\myrbrace {{\tt \char '175}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @w prevents a word break.  Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox.  We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line.  According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0).  If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+\def\group{\begingroup
+  \ifnum\catcode13=\active \else
+    \errhelp = \groupinvalidhelp
+    \errmessage{@group invalid in context where filling is enabled}%
+  \fi
+  %
+  % The \vtop we start below produces a box with normal height and large
+  % depth; thus, TeX puts \baselineskip glue before it, and (when the
+  % next line of text is done) \lineskip glue after it.  (See p.82 of
+  % the TeXbook.)  Thus, space below is not quite equal to space
+  % above.  But it's pretty close.
+  \def\Egroup{%
+    \egroup           % End the \vtop.
+    \endgroup         % End the \group.
+  }%
+  %
+  \vtop\bgroup
+    % We have to put a strut on the last line in case the @group is in
+    % the midst of an example, rather than completely enclosing it.
+    % Otherwise, the interline space between the last line of the group
+    % and the first line afterwards is too small.  But we can't put the
+    % strut in \Egroup, since there it would be on a line by itself.
+    % Hence this just inserts a strut at the beginning of each line.
+    \everypar = {\strut}%
+    %
+    % Since we have a strut on every line, we don't need any of TeX's
+    % normal interline spacing.
+    \offinterlineskip
+    %
+    % OK, but now we have to do something about blank
+    % lines in the input in @example-like environments, which normally
+    % just turn into \lisppar, which will insert no space now that we've
+    % turned off the interline space.  Simplest is to make them be an
+    % empty paragraph.
+    \ifx\par\lisppar
+      \edef\par{\leavevmode \par}%
+      %
+      % Reset ^^M's definition to new definition of \par.
+      \obeylines
+    \fi
+    %
+    % We do @comment here in case we are called inside an environment,
+    % such as @example, where each end-of-line in the input causes an
+    % end-of-line in the output.  We don't want the end-of-line after
+    % the `@group' to put extra space in the output.  Since @group
+    % should appear on a line by itself (according to the Texinfo
+    % manual), we don't worry about eating any user text.
+    \comment
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil  \mil=0.001in
+
+\def\need{\parsearg\needx}
+
+% Old definition--didn't work.
+%\def\needx #1{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000
+%\prevdepth=-1000pt
+%}}
+
+\def\needx#1{%
+  % Go into vertical mode, so we don't make a big box in the middle of a
+  % paragraph.
+  \par
+  %
+  % Don't add any leading before our big empty box, but allow a page
+  % break, since the best break might be right here.
+  \allowbreak
+  \nointerlineskip
+  \vtop to #1\mil{\vfil}%
+  %
+  % TeX does not even consider page breaks if a penalty added to the
+  % main vertical list is 10000 or more.  But in order to see if the
+  % empty box we just added fits on the page, we must make it consider
+  % page breaks.  On the other hand, we don't want to actually break the
+  % page after the empty box.  So we use a penalty of 9999.
+  %
+  % There is an extremely small chance that TeX will actually break the
+  % page at this \penalty, if there are no other feasible breakpoints in
+  % sight.  (If the user is using lots of big @group commands, which
+  % almost-but-not-quite fill up a page, TeX will have a hard time doing
+  % good page breaking, for example.)  However, I could not construct an
+  % example where a page broke at this \penalty; if it happens in a real
+  % document, then we can reconsider our strategy.
+  \penalty9999
+  %
+  % Back up by the size of the box, whether we did a page break or not.
+  \kern -#1\mil
+  %
+  % Do not allow a page break right after this kern.
+  \nobreak
+}
+
+% @br   forces paragraph break
+
+\let\br = \par
+
+% @dots{}  output some dots
+
+\def\dots{$\ldots$}
+
+% @page    forces the start of a new page
+
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\def\exdent{\parsearg\exdentyyy}
+\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+% This defn is used inside nofill environments such as @example.
+\def\nofillexdent{\parsearg\nofillexdentyyy}
+\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+\leftline{\hskip\leftskip{\rm#1}}}}
+
+%\hbox{{\rm#1}}\hfil\break}}
+
+% @include file    insert text of that file as input.
+
+\def\include{\parsearg\includezzz}
+%Use \input\thisfile to avoid blank after \input, which may be an active
+%char (in which case the blank would become the \input argument).
+%The grouping keeps the value of \thisfile correct even when @include
+%is nested.
+\def\includezzz #1{\begingroup
+\def\thisfile{#1}\input\thisfile
+\endgroup}
+
+\def\thisfile{}
+
+% @center line   outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n   outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\par \vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore  is another way to write a comment
+
+\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other%
+\parsearg \commentxxx}
+
+\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 }
+
+\let\c=\comment
+
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+\let\chapter=\relax
+\let\unnumbered=\relax
+\let\top=\relax
+\let\unnumberedsec=\relax
+\let\unnumberedsection=\relax
+\let\unnumberedsubsec=\relax
+\let\unnumberedsubsection=\relax
+\let\unnumberedsubsubsec=\relax
+\let\unnumberedsubsubsection=\relax
+\let\section=\relax
+\let\subsec=\relax
+\let\subsubsec=\relax
+\let\subsection=\relax
+\let\subsubsection=\relax
+\let\appendix=\relax
+\let\appendixsec=\relax
+\let\appendixsection=\relax
+\let\appendixsubsec=\relax
+\let\appendixsubsection=\relax
+\let\appendixsubsubsec=\relax
+\let\appendixsubsubsection=\relax
+\let\contents=\relax
+\let\smallbook=\relax
+\let\titlepage=\relax
+}
+
+% Used in nested conditionals, where we have to parse the Texinfo source
+% and so want to turn off most commands, in case they are used
+% incorrectly.
+%
+\def\ignoremorecommands{%
+  \let\defcv = \relax
+  \let\deffn = \relax
+  \let\deffnx = \relax
+  \let\defindex = \relax
+  \let\defivar = \relax
+  \let\defmac = \relax
+  \let\defmethod = \relax
+  \let\defop = \relax
+  \let\defopt = \relax
+  \let\defspec = \relax
+  \let\deftp = \relax
+  \let\deftypefn = \relax
+  \let\deftypefun = \relax
+  \let\deftypevar = \relax
+  \let\deftypevr = \relax
+  \let\defun = \relax
+  \let\defvar = \relax
+  \let\defvr = \relax
+  \let\ref = \relax
+  \let\xref = \relax
+  \let\printindex = \relax
+  \let\pxref = \relax
+  \let\settitle = \relax
+  \let\include = \relax
+  \let\lowersections = \relax
+  \let\down = \relax
+  \let\raisesections = \relax
+  \let\up = \relax
+  \let\set = \relax
+  \let\clear = \relax
+}
+
+% Ignore @ignore ... @end ignore.
+%
+\def\ignore{\doignore{ignore}}
+
+% Also ignore @ifinfo, @menu, and @direntry text.
+%
+\def\ifinfo{\doignore{ifinfo}}
+\def\menu{\doignore{menu}}
+\def\direntry{\doignore{direntry}}
+
+% Ignore text until a line `@end #1'.
+%
+\def\doignore#1{\begingroup
+  % Don't complain about control sequences we have declared \outer.
+  \ignoresections
+  %
+  % Define a command to swallow text until we reach `@end #1'.
+  \long\def\doignoretext##1\end #1{\enddoignore}%
+  %
+  % Make sure that spaces turn into tokens that match what \doignoretext wants.
+  \catcode32 = 10
+  %
+  % And now expand that command.
+  \doignoretext
+}
+
+% What we do to finish off ignored text.
+%
+\def\enddoignore{\endgroup\ignorespaces}%
+
+\newif\ifwarnedobs\warnedobsfalse
+\def\obstexwarn{%
+  \ifwarnedobs\relax\else
+  % We need to warn folks that they may have trouble with TeX 3.0.
+  % This uses \immediate\write16 rather than \message to get newlines.
+    \immediate\write16{}
+    \immediate\write16{***WARNING*** for users of Unix TeX 3.0!}
+    \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
+    \immediate\write16{If you are running another version of TeX, relax.}
+    \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
+    \immediate\write16{  Then upgrade your TeX installation if you can.}
+    \immediate\write16{If you are stuck with version 3.0, run the}
+    \immediate\write16{  script ``tex3patch'' from the Texinfo distribution}
+    \immediate\write16{  to use a workaround.}
+    \immediate\write16{}
+    \warnedobstrue
+    \fi
+}
+
+% **In TeX 3.0, setting text in \nullfont hangs tex.  For a
+% workaround (which requires the file ``dummy.tfm'' to be installed),
+% uncomment the following line:
+%%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+
+% Ignore text, except that we keep track of conditional commands for
+% purposes of nesting, up to an `@end #1' command.
+%
+\def\nestedignore#1{%
+  \obstexwarn
+  % We must actually expand the ignored text to look for the @end
+  % command, so that nested ignore constructs work.  Thus, we put the
+  % text into a \vbox and then do nothing with the result.  To minimize
+  % the change of memory overflow, we follow the approach outlined on
+  % page 401 of the TeXbook: make the current font be a dummy font.
+  %
+  \setbox0 = \vbox\bgroup
+    % Don't complain about control sequences we have declared \outer.
+    \ignoresections
+    %
+    % Define `@end #1' to end the box, which will in turn undefine the
+    % @end command again.
+    \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
+    %
+    % We are going to be parsing Texinfo commands.  Most cause no
+    % trouble when they are used incorrectly, but some commands do
+    % complicated argument parsing or otherwise get confused, so we
+    % undefine them.
+    %
+    % We can't do anything about stray @-signs, unfortunately;
+    % they'll produce `undefined control sequence' errors.
+    \ignoremorecommands
+    %
+    % Set the current font to be \nullfont, a TeX primitive, and define
+    % all the font commands to also use \nullfont.  We don't use
+    % dummy.tfm, as suggested in the TeXbook, because not all sites
+    % might have that installed.  Therefore, math mode will still
+    % produce output, but that should be an extremely small amount of
+    % stuff compared to the main input.
+    %
+    \nullfont
+    \let\tenrm = \nullfont  \let\tenit = \nullfont  \let\tensl = \nullfont
+    \let\tenbf = \nullfont  \let\tentt = \nullfont  \let\smallcaps = \nullfont
+    \let\tensf = \nullfont
+    %
+    % Don't complain when characters are missing from the fonts.
+    \tracinglostchars = 0
+    %
+    % Don't bother to do space factor calculations.
+    \frenchspacing
+    %
+    % Don't report underfull hboxes.
+    \hbadness = 10000
+    %
+    % Do minimal line-breaking.
+    \pretolerance = 10000
+    %
+    % Do not execute instructions in @tex
+    \def\tex{\doignore{tex}}
+}
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it.
+%
+\def\set{\parsearg\setxxx}
+\def\setxxx#1{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+  \def\temp{#2}%
+  \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+  \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+  \fi
+}
+\def\setzzz#1#2 \endsetzzz{\expandafter\xdef\csname SET#1\endcsname{#2}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+% @value{foo} gets the text saved in variable foo.
+%
+\def\value#1{\expandafter
+               \ifx\csname SET#1\endcsname\relax
+                       {\{No value for ``#1''\}}
+               \else \csname SET#1\endcsname \fi}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+\def\ifset{\parsearg\ifsetxxx}
+\def\ifsetxxx #1{%
+  \expandafter\ifx\csname SET#1\endcsname\relax
+    \expandafter\ifsetfail
+  \else
+    \expandafter\ifsetsucceed
+  \fi
+}
+\def\ifsetsucceed{\conditionalsucceed{ifset}}
+\def\ifsetfail{\nestedignore{ifset}}
+\defineunmatchedend{ifset}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+\def\ifclear{\parsearg\ifclearxxx}
+\def\ifclearxxx #1{%
+  \expandafter\ifx\csname SET#1\endcsname\relax
+    \expandafter\ifclearsucceed
+  \else
+    \expandafter\ifclearfail
+  \fi
+}
+\def\ifclearsucceed{\conditionalsucceed{ifclear}}
+\def\ifclearfail{\nestedignore{ifclear}}
+\defineunmatchedend{ifclear}
+
+% @iftex always succeeds; we read the text following, through @end
+% iftex).  But `@end iftex' should be valid only after an @iftex.
+%
+\def\iftex{\conditionalsucceed{iftex}}
+\defineunmatchedend{iftex}
+
+% We can't just want to start a group at @iftex (for example) and end it
+% at @end iftex, since then @set commands inside the conditional have no
+% effect (they'd get reverted at the end of the group).  So we must
+% define \Eiftex to redefine itself to be its previous value.  (We can't
+% just define it to fail again with an ``unmatched end'' error, since
+% the @ifset might be nested.)
+%
+\def\conditionalsucceed#1{%
+  \edef\temp{%
+    % Remember the current value of \E#1.
+    \let\nece{prevE#1} = \nece{E#1}%
+    %
+    % At the `@end #1', redefine \E#1 to be its previous value.
+    \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+  }%
+  \temp
+}
+
+% We need to expand lots of \csname's, but we don't want to expand the
+% control sequences after we've constructed them.
+%
+\def\nece#1{\expandafter\noexpand\csname#1\endcsname}
+
+% @asis just yields its argument.  Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written.  Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo).  So we must use a
+% control sequence to switch into and out of math mode.
+%
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+%
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{\implicitmath\ptexbullet\implicitmath}
+\def\minus{\implicitmath-\implicitmath}
+
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\nwnode=\node
+\let\lastnode=\relax
+
+\def\donoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\setref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\unnumbnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\appendixnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\let\refill=\relax
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+   \readauxfile
+   \opencontents
+   \openindices
+   \fixbackslash  % Turn off hack to swallow `\input texinfo'.
+   \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+   \comment % Ignore the actual filename.
+}
+
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{See Info file \file{\ignorespaces #3{}},
+  node \samp{\ignorespaces#1{}}}
+
+\message{fonts,}
+
+% Font-change commands.
+
+% Texinfo supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+%% Try out Computer Modern fonts at \magstephalf
+\let\mainmagstep=\magstephalf
+
+\ifx\bigger\relax
+\let\mainmagstep=\magstep1
+\font\textrm=cmr12
+\font\texttt=cmtt12
+\else
+\font\textrm=cmr10 scaled \mainmagstep
+\font\texttt=cmtt10 scaled \mainmagstep
+\fi
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\font\textbf=cmb10 scaled \mainmagstep
+\font\textit=cmti10 scaled \mainmagstep
+\font\textsl=cmsl10 scaled \mainmagstep
+\font\textsf=cmss10 scaled \mainmagstep
+\font\textsc=cmcsc10 scaled \mainmagstep
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun, etc.
+\font\defbf=cmbx10 scaled \magstep1 %was 1314
+\font\deftt=cmtt10 scaled \magstep1
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+% Fonts for indices and small examples.
+% We actually use the slanted font rather than the italic,
+% because texinfo normally uses the slanted fonts for that.
+% Do not make many font distinctions in general in the index, since they
+% aren't very useful.
+\font\ninett=cmtt9
+\font\indrm=cmr9
+\font\indit=cmsl9
+\let\indsl=\indit
+\let\indtt=\ninett
+\let\indsf=\indrm
+\let\indbf=\indrm
+\let\indsc=\indrm
+\font\indi=cmmi9
+\font\indsy=cmsy9
+
+% Fonts for headings
+\font\chaprm=cmbx12 scaled \magstep2
+\font\chapit=cmti12 scaled \magstep2
+\font\chapsl=cmsl12 scaled \magstep2
+\font\chaptt=cmtt12 scaled \magstep2
+\font\chapsf=cmss12 scaled \magstep2
+\let\chapbf=\chaprm
+\font\chapsc=cmcsc10 scaled\magstep3
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+\font\secrm=cmbx12 scaled \magstep1
+\font\secit=cmti12 scaled \magstep1
+\font\secsl=cmsl12 scaled \magstep1
+\font\sectt=cmtt12 scaled \magstep1
+\font\secsf=cmss12 scaled \magstep1
+\font\secbf=cmbx12 scaled \magstep1
+\font\secsc=cmcsc10 scaled\magstep2
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% \font\ssecrm=cmbx10 scaled \magstep1    % This size an font looked bad.
+% \font\ssecit=cmti10 scaled \magstep1    % The letters were too crowded.
+% \font\ssecsl=cmsl10 scaled \magstep1
+% \font\ssectt=cmtt10 scaled \magstep1
+% \font\ssecsf=cmss10 scaled \magstep1
+
+%\font\ssecrm=cmb10 scaled 1315        % Note the use of cmb rather than cmbx.
+%\font\ssecit=cmti10 scaled 1315       % Also, the size is a little larger than
+%\font\ssecsl=cmsl10 scaled 1315       % being scaled magstep1.
+%\font\ssectt=cmtt10 scaled 1315
+%\font\ssecsf=cmss10 scaled 1315
+
+%\let\ssecbf=\ssecrm
+
+\font\ssecrm=cmbx12 scaled \magstephalf
+\font\ssecit=cmti12 scaled \magstephalf
+\font\ssecsl=cmsl12 scaled \magstephalf
+\font\ssectt=cmtt12 scaled \magstephalf
+\font\ssecsf=cmss12 scaled \magstephalf
+\font\ssecbf=cmbx12 scaled \magstephalf
+\font\ssecsc=cmcsc10 scaled \magstep1
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled \magstep1
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% Fonts for title page:
+\font\titlerm = cmbx12 scaled \magstep3
+\let\authorrm = \secrm
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families.  Since
+% texinfo doesn't allow for producing subscripts and superscripts, we
+% don't bother to reset \scriptfont and \scriptscriptfont (which would
+% also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+  \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy
+  \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf
+  \textfont\ttfam = \tentt \textfont\sffam = \tensf
+}
+
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE.  We do this so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current.  Plain TeX does, for example,
+% \def\bf{\fam=\bffam \tenbf}  By redefining \tenbf, we obviate the need
+% to redefine \bf itself.
+\def\textfonts{%
+  \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+  \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+  \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
+  \resetmathfonts}
+\def\chapfonts{%
+  \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+  \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+  \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy
+  \resetmathfonts}
+\def\secfonts{%
+  \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+  \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+  \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
+  \resetmathfonts}
+\def\subsecfonts{%
+  \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+  \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+  \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
+  \resetmathfonts}
+\def\indexfonts{%
+  \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
+  \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
+  \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy
+  \resetmathfonts}
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\font\shortcontrm=cmr12
+\font\shortcontbf=cmbx12
+\font\shortcontsl=cmsl12
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartitalic
+\let\dfn=\smartitalic
+\let\emph=\smartitalic
+\let\cite=\smartitalic
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph.  Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1  \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+\def\t#1{%
+  {\tt \nohyphenation \rawbackslash \frenchspacing #1}%
+  \null
+}
+\let\ttfont = \t
+%\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null}
+\def\samp #1{`\tclose{#1}'\null}
+\def\key #1{{\tt \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+\let\file=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+  {%
+    % Change normal interword space to be same as for the current font.
+    \spaceskip = \fontdimen2\font
+    %
+    % Switch to typewriter.
+    \tt
+    %
+    % But `\ ' produces the large typewriter interword space.
+    \def\ {{\spaceskip = 0pt{} }}%
+    %
+    % Turn off hyphenation.
+    \nohyphenation
+    %
+    \rawbackslash
+    \frenchspacing
+    #1%
+  }%
+  \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in \code.
+% Otherwise, it is too hard to avoid overful hboxes
+% in the Emacs manual, the Library manual, etc.
+
+% Unfortunately, TeX uses one parameter (\hyphenchar) to control
+% both hyphenation at - and hyphenation within words.
+% We must therefore turn them both off (\tclose does that)
+% and arrange explicitly to hyphenate an a dash.
+%  -- rms.
+{
+\catcode `\-=\active
+\catcode `\_=\active
+\global\def\code{\begingroup \catcode `\-=\active \let-\codedash \let_\codeunder \codex}
+}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{\normalunderscore\discretionary{}{}{}}
+\def\codex #1{\tclose{#1}\endgroup}
+
+%\let\exp=\tclose  %Was temporary
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else\tclose{\look}\fi
+\else\tclose{\look}\fi}
+
+% Typeset a dimension, e.g., `in' or `pt'.  The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of
+% @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+\def\l#1{{\li #1}\null}                %
+
+\def\r#1{{\rm #1}}             % roman font
+% Use of \lowercase was suggested.
+\def\sc#1{{\smallcaps#1}}      % smallcaps font
+\def\ii#1{{\it #1}}            % italic font
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page.  Must do @settitle before @titlepage.
+\def\titlefont#1{{\titlerm #1}}
+
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+\def\shorttitlepage{\parsearg\shorttitlepagezzz}
+\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+       \endgroup\page\hbox{}\page}
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+   \let\subtitlerm=\tenrm
+% I deinstalled the following change because \cmr12 is undefined.
+% This change was not in the ChangeLog anyway.  --rms.
+%   \let\subtitlerm=\cmr12
+   \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+   %
+   \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+   %
+   % Leave some space at the very top of the page.
+   \vglue\titlepagetopglue
+   %
+   % Now you can print the title using @title.
+   \def\title{\parsearg\titlezzz}%
+   \def\titlezzz##1{\leftline{\titlefont{##1}}
+                   % print a rule at the page bottom also.
+                   \finishedtitlepagefalse
+                   \vskip4pt \hrule height 4pt \vskip4pt}%
+   % No rule at page bottom unless we print one at the top with @title.
+   \finishedtitlepagetrue
+   %
+   % Now you can put text using @subtitle.
+   \def\subtitle{\parsearg\subtitlezzz}%
+   \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+   %
+   % @author should come last, but may come many times.
+   \def\author{\parsearg\authorzzz}%
+   \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+      {\authorfont \leftline{##1}}}%
+   %
+   % Most title ``pages'' are actually two pages long, with space
+   % at the top of the second.  We don't want the ragged left on the second.
+   \let\oldpage = \page
+   \def\page{%
+      \iffinishedtitlepage\else
+        \finishtitlepage
+      \fi
+      \oldpage
+      \let\page = \oldpage
+      \hbox{}}%
+%   \def\page{\oldpage \hbox{}}
+}
+
+\def\Etitlepage{%
+   \iffinishedtitlepage\else
+      \finishtitlepage
+   \fi
+   % It is important to do the page break before ending the group,
+   % because the headline and footline are only empty inside the group.
+   % If we use the new definition of \page, we always get a blank page
+   % after the title page, which we certainly don't want.
+   \oldpage
+   \endgroup
+   \HEADINGSon
+}
+
+\def\finishtitlepage{%
+   \vskip4pt \hrule height 2pt
+   \vskip\titlepagebottomglue
+   \finishedtitlepagetrue
+}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks \evenheadline    % Token sequence for heading line of even pages
+\newtoks \oddheadline     % Token sequence for heading line of odd pages
+\newtoks \evenfootline    % Token sequence for footing line of even pages
+\newtoks \oddfootline     % Token sequence for footing line of odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+                            \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+                            \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what  @headings on  does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
+\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
+\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+%
+}% unbind the catcode of @.
+
+% @headings double     turns headings on for double-sided printing.
+% @headings single     turns headings on for single-sided printing.
+% @headings off                turns them off.
+% @headings on         same as @headings double, retained for compatibility.
+% @headings after      turns on double-sided headings after this page.
+% @headings doubleafter        turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{\number\day\space
+\ifcase\month\or
+January\or February\or March\or April\or May\or June\or
+July\or August\or September\or October\or November\or December\fi
+\space\number\year}
+
+% Use this if you want the Month Day, Year style of output.
+%\def\today{\ifcase\month\or
+%January\or February\or March\or April\or May\or June\or
+%July\or August\or September\or October\or November\or December\fi
+%\space\number\day, \number\year}
+
+% @settitle line...  specifies the title of the document, for headings
+% It generates no output of its own
+
+\def\thistitle{No Title}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+\message{tables,}
+
+% @tabs -- simple alignment
+
+% These don't work.  For one thing, \+ is defined as outer.
+% So these macros cannot even be defined.
+
+%\def\tabs{\parsearg\tabszzz}
+%\def\tabszzz #1{\settabs\+#1\cr}
+%\def\tabline{\parsearg\tablinezzz}
+%\def\tablinezzz #1{\+#1\cr}
+%\def\&{&}
+
+% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent  \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin  \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @vtable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\par \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \par \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\par \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+                 \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+                 \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+  \advance\hsize by -\rightskip
+  \advance\hsize by -\tableindent
+  \setbox0=\hbox{\itemfont{#1}}%
+  \itemindex{#1}%
+  \nobreak % This prevents a break before @itemx.
+  %
+  % Be sure we are not still in the middle of a paragraph.
+  {\parskip = 0in
+  \par
+  }%
+  %
+  % If the item text does not fit in the space we have, put it on a line
+  % by itself, and do not allow a page break either before or after that
+  % line.  We do not start a paragraph here because then if the next
+  % command is, e.g., @kindex, the whatsit would get put into the
+  % horizontal list on a line by itself, resulting in extra blank space.
+  \ifdim \wd0>\itemmax
+    \setbox0=\hbox{\hskip \leftskip \hskip -\tableindent \unhbox0}\box0
+    %
+    % We're going to be starting a paragraph, but we don't want the
+    % \parskip glue -- logically it's part of the @item we just started.
+    \nobreak \vskip-\parskip
+    %
+    % Stop a page break at the \parskip glue coming up.  Unfortunately
+    % we can't prevent a possible page break at the following
+    % \baselineskip glue.
+    \nobreak
+  \else
+    % The item text fits into the space.  Start a paragraph, so that the
+    % following text (if any) will end up on the same line.  Since that
+    % text will be indented by \tableindent, we make the item text be in
+    % a zero-width box.
+    \noindent
+    \rlap{\hskip -\tableindent\box0}%
+  \fi
+  \endgroup
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+%% Contains a kludge to get @end[description] to work
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1        \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1        \endtabley
+\def\Eftable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+{\obeylines\obeyspaces%
+\gdef\vtablex #1^^M{%
+\tabley\vritemindex#1        \endtabley
+\def\Evtable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+\def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Neccessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\exdentamount=\tableindent
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\afterenvbreak\endgroup}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+  \begingroup % ended by the @end itemsize
+  \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\exdentamount=\itemindent
+\parindent = 0pt %
+\parskip = \smallskipamount %
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\afterenvbreak\endgroup}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+  \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list.  No
+% argument is the same as `1'.
+%
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1  \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+  \begingroup % ended by the @end enumerate
+  %
+  % If we were given no argument, pretend we were given `1'.
+  \def\thearg{#1}%
+  \ifx\thearg\empty \def\thearg{1}\fi
+  %
+  % Detect if the argument is a single token.  If so, it might be a
+  % letter.  Otherwise, the only valid thing it can be is a number.
+  % (We will always have one token, because of the test we just made.
+  % This is a good thing, since \splitoff doesn't work given nothing at
+  % all -- the first parameter is undelimited.)
+  \expandafter\splitoff\thearg\endmark
+  \ifx\rest\empty
+    % Only one token in the argument.  It could still be anything.
+    % A ``lowercase letter'' is one whose \lccode is nonzero.
+    % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+    %   not equal to itself.
+    % Otherwise, we assume it's a number.
+    %
+    % We need the \relax at the end of the \ifnum lines to stop TeX from
+    % continuing to look for a <number>.
+    %
+    \ifnum\lccode\expandafter`\thearg=0\relax
+      \numericenumerate % a number (we hope)
+    \else
+      % It's a letter.
+      \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+        \lowercaseenumerate % lowercase letter
+      \else
+        \uppercaseenumerate % uppercase letter
+      \fi
+    \fi
+  \else
+    % Multiple tokens in the argument.  We hope it's a number.
+    \numericenumerate
+  \fi
+}
+
+% An @enumerate whose labels are integers.  The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+  \itemno = \thearg
+  \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+  \itemno = \expandafter`\thearg
+  \startenumeration{%
+    % Be sure we're not beyond the end of the alphabet.
+    \ifnum\itemno=0
+      \errmessage{No more lowercase letters in @enumerate; get a bigger
+                  alphabet}%
+    \fi
+    \char\lccode\itemno
+  }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+  \itemno = \expandafter`\thearg
+  \startenumeration{%
+    % Be sure we're not beyond the end of the alphabet.
+    \ifnum\itemno=0
+      \errmessage{No more uppercase letters in @enumerate; get a bigger
+                  alphabet}
+    \fi
+    \char\uccode\itemno
+  }%
+}
+
+% Call itemizey, adding a period to the first argument and supplying the
+% common last two arguments.  Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+  \advance\itemno by -1
+  \itemizey{#1.}\Eenumerate\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that        accumulates this index.  The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+
+\def\newindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1        % Open the file
+\expandafter\xdef\csname#1index\endcsname{%    % Define \xxxindex
+\noexpand\doindex {#1}}
+}
+
+% @defindex foo  ==  \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1        % Open the file
+\expandafter\xdef\csname#1index\endcsname{%    % Define \xxxindex
+\noexpand\docodeindex {#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar    makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+\def\synindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{%    % Define \xxxindex
+\noexpand\doindex {#2}}%
+}
+
+% @syncodeindex foo bar   similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{%    % Define \xxxindex
+\noexpand\docodeindex {#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+%  and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+\def\_{{\realbackslash _}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+\def\char{\realbackslash char}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\copyright{\realbackslash copyright }%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\t##1{\realbackslash r {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+\def\dfn##1{\realbackslash dfn {##1}}%
+\def\emph##1{\realbackslash emph {##1}}%
+}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the active chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+@gdef@realbackslash{\}}
+
+\let\indexbackslash=0  %overridden during \printindex.
+
+\def\doind #1#2{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0% Expand all macros now EXCEPT \folio
+\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+% so it will be output as is; and it will print as backslash in the indx.
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2}%
+}%
+% Now produce the complete index entry.  We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}}}%
+\temp }%
+}\penalty\count10}}
+
+\def\dosubind #1#2#3{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0%
+\def\rawbackslashxx{\indexbackslash}%
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2 #3}%
+}%
+% Now produce the complete index entry.  We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}{#3}}}%
+\temp }%
+}\penalty\count10}}
+
+% The index entry written in the file actually looks like
+%  \entry {sortstring}{page}{topic}
+% or
+%  \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+%  \initial {c}
+%     before the first topic whose initial is c
+%  \entry {topic}{pagelist}
+%     for a topic that is used without subtopics
+%  \primary {topic}
+%     for the beginning of a topic that is used with subtopics
+%  \secondary {subtopic}{pagelist}
+%     for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% This is what you call to cause a particular index to get printed.
+% Write
+% @unnumbered Function Index
+% @printindex fn
+
+\def\printindex{\parsearg\doprintindex}
+
+\def\doprintindex#1{%
+  \tex
+  \dobreak \chapheadingskip {10000}
+  \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other
+  \catcode`\$=\other\catcode`\_=\other
+  \catcode`\~=\other
+  %
+  % The following don't help, since the chars were translated
+  % when the raw index was written, and their fonts were discarded
+  % due to \indexnofonts.
+  %\catcode`\"=\active
+  %\catcode`\^=\active
+  %\catcode`\_=\active
+  %\catcode`\|=\active
+  %\catcode`\<=\active
+  %\catcode`\>=\active
+  % %
+  \def\indexbackslash{\rawbackslashxx}
+  \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt
+  \begindoublecolumns
+  %
+  % See if the index file exists and is nonempty.
+  \openin 1 \jobname.#1s
+  \ifeof 1
+    % \enddoublecolumns gets confused if there is no text in the index,
+    % and it loses the chapter title and the aux file entries for the
+    % index.  The easiest way to prevent this problem is to make sure
+    % there is some text.
+    (Index is nonexistent)
+    \else
+    %
+    % If the index file exists but is empty, then \openin leaves \ifeof
+    % false.  We have to make TeX try to read something from the file, so
+    % it can discover if there is anything in it.
+    \read 1 to \temp
+    \ifeof 1
+      (Index is empty)
+    \else
+      \input \jobname.#1s
+    \fi
+  \fi
+  \closein 1
+  \enddoublecolumns
+  \Etex
+}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+% Same as \bigskipamount except no shrink.
+% \balancecolumns gets confused if there is any shrink.
+\newskip\initialskipamount \initialskipamount 12pt plus4pt
+
+\def\initial #1{%
+{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+\ifdim\lastskip<\initialskipamount
+\removelastskip \penalty-200 \vskip \initialskipamount\fi
+\line{\secbf#1\hfill}\kern 2pt\penalty10000}}
+
+% This typesets a paragraph consisting of #1, dot leaders, and then #2
+% flush to the right margin.  It is used for index and table of contents
+% entries.  The paragraph is indented by \leftskip.
+%
+\def\entry #1#2{\begingroup
+  %
+  % Start a new paragraph if necessary, so our assignments below can't
+  % affect previous text.
+  \par
+  %
+  % Do not fill out the last line with white space.
+  \parfillskip = 0in
+  %
+  % No extra space above this paragraph.
+  \parskip = 0in
+  %
+  % Do not prefer a separate line ending with a hyphen to fewer lines.
+  \finalhyphendemerits = 0
+  %
+  % \hangindent is only relevant when the entry text and page number
+  % don't both fit on one line.  In that case, bob suggests starting the
+  % dots pretty far over on the line.  Unfortunately, a large
+  % indentation looks wrong when the entry text itself is broken across
+  % lines.  So we use a small indentation and put up with long leaders.
+  %
+  % \hangafter is reset to 1 (which is the value we want) at the start
+  % of each paragraph, so we need not do anything with that.
+  \hangindent=2em
+  %
+  % When the entry text needs to be broken, just fill out the first line
+  % with blank space.
+  \rightskip = 0pt plus1fil
+  %
+  % Start a ``paragraph'' for the index entry so the line breaking
+  % parameters we've set above will have an effect.
+  \noindent
+  %
+  % Insert the text of the index entry.  TeX will do line-breaking on it.
+  #1%
+  %
+  % If we must, put the page number on a line of its own, and fill out
+  % this line with blank space.  (The \hfil is overwhelmed with the
+  % fill leaders glue in \indexdotfill if the page number does fit.)
+  \hfil\penalty50
+  \null\nobreak\indexdotfill % Have leaders before the page number.
+  %
+  % The `\ ' here is removed by the implicit \unskip that TeX does as
+  % part of (the primitive) \par.  Without it, a spurious underfull
+  % \hbox ensues.
+  \ #2% The page number ends the paragraph.
+  \par
+\endgroup}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+  \hbox{$\mathsurround=0pt \mkern1.5mu . \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
+}}
+
+%% Define two-column mode, which is used in indexes.
+%% Adapted from the TeXbook, page 416.
+\catcode `\@=11
+
+\newbox\partialpage
+
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup
+  % Grab any single-column material above us.
+  \output = {\global\setbox\partialpage
+    =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}%
+  \eject
+  %
+  % Now switch to the double-column output routine.
+  \output={\doublecolumnout}%
+  %
+  % Change the page size parameters.  We could do this once outside this
+  % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+  % format, but then we repeat the same computation.  Repeating a couple
+  % of assignments once per index is clearly meaningless for the
+  % execution time, so we may as well do it once.
+  %
+  % First we halve the line length, less a little for the gutter between
+  % the columns.  We compute the gutter based on the line length, so it
+  % changes automatically with the paper format.  The magic constant
+  % below is chosen so that the gutter has the same value (well, +- <
+  % 1pt) as it did when we hard-coded it.
+  %
+  % We put the result in a separate register, \doublecolumhsize, so we
+  % can restore it in \pagesofar, after \hsize itself has (potentially)
+  % been clobbered.
+  %
+  \doublecolumnhsize = \hsize
+    \advance\doublecolumnhsize by -.04154\hsize
+    \divide\doublecolumnhsize by 2
+  \hsize = \doublecolumnhsize
+  %
+  % Double the \vsize as well.  (We don't need a separate register here,
+  % since nobody clobbers \vsize.)
+  \vsize = 2\vsize
+  \doublecolumnpagegoal
+}
+
+\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage}
+
+\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth
+  \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage
+  \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1}
+  \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3}
+  \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+  \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+}
+\def\doublecolumnpagegoal{%
+  \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@
+}
+\def\pagesofar{\unvbox\partialpage %
+  \hsize=\doublecolumnhsize % have to restore this since output routine
+  \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}}
+\def\doublecolumnout{%
+  \setbox5=\copy255
+  {\vbadness=10000 \doublecolumnsplit}
+  \ifvbox255
+    \setbox0=\vtop to\dimen@{\unvbox0}
+    \setbox2=\vtop to\dimen@{\unvbox2}
+    \onepageout\pagesofar \unvbox255 \penalty\outputpenalty
+  \else
+    \setbox0=\vbox{\unvbox5}
+    \ifvbox0
+      \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+      \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth
+      {\vbadness=10000
+       \loop \global\setbox5=\copy0
+          \setbox1=\vsplit5 to\dimen@
+          \setbox3=\vsplit5 to\dimen@
+          \ifvbox5 \global\advance\dimen@ by1pt \repeat
+        \setbox0=\vbox to\dimen@{\unvbox1}
+        \setbox2=\vbox to\dimen@{\unvbox3}
+        \global\setbox\partialpage=\vbox{\pagesofar}
+        \doublecolumnpagegoal
+      }
+    \fi
+  \fi
+}
+
+\catcode `\@=\other
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno        \secno=0
+\newcount \subsecno     \subsecno=0
+\newcount \subsubsecno  \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount \appendixno  \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+\newwrite \contentsfile
+% This is called from \setfilename.
+\def\opencontents{\openout \contentsfile = \jobname.toc}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it.  @section does likewise
+
+\def\thischapter{} \def\thissection{}
+\def\seccheck#1{\if \pageno<0 %
+\errmessage{@#1 not allowed after generating table of contents}\fi
+%
+}
+
+\def\chapternofonts{%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\def\result{\realbackslash result}
+\def\equiv{\realbackslash equiv}
+\def\expansion{\realbackslash expansion}
+\def\print{\realbackslash print}
+\def\TeX{\realbackslash TeX}
+\def\dots{\realbackslash dots}
+\def\copyright{\realbackslash copyright}
+\def\tt{\realbackslash tt}
+\def\bf{\realbackslash bf }
+\def\w{\realbackslash w}
+\def\less{\realbackslash less}
+\def\gtr{\realbackslash gtr}
+\def\hat{\realbackslash hat}
+\def\char{\realbackslash char}
+\def\tclose##1{\realbackslash tclose {##1}}
+\def\code##1{\realbackslash code {##1}}
+\def\samp##1{\realbackslash samp {##1}}
+\def\r##1{\realbackslash r {##1}}
+\def\b##1{\realbackslash b {##1}}
+\def\key##1{\realbackslash key {##1}}
+\def\file##1{\realbackslash file {##1}}
+\def\kbd##1{\realbackslash kbd {##1}}
+% These are redefined because @smartitalic wouldn't work inside xdef.
+\def\i##1{\realbackslash i {##1}}
+\def\cite##1{\realbackslash cite {##1}}
+\def\var##1{\realbackslash var {##1}}
+\def\emph##1{\realbackslash emph {##1}}
+\def\dfn##1{\realbackslash dfn {##1}}
+}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raise/lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% Choose a numbered-heading macro
+% #1 is heading level if unmodified by @raisesections or @lowersections
+% #2 is text for heading
+\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+  \chapterzzz{#2}
+\or
+  \seczzz{#2}
+\or
+  \numberedsubseczzz{#2}
+\or
+  \numberedsubsubseczzz{#2}
+\else
+  \ifnum \absseclevel<0
+    \chapterzzz{#2}
+  \else
+    \numberedsubsubseczzz{#2}
+  \fi
+\fi
+}
+
+% like \numhead, but chooses appendix heading levels
+\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+  \appendixzzz{#2}
+\or
+  \appendixsectionzzz{#2}
+\or
+  \appendixsubseczzz{#2}
+\or
+  \appendixsubsubseczzz{#2}
+\else
+  \ifnum \absseclevel<0
+    \appendixzzz{#2}
+  \else
+    \appendixsubsubseczzz{#2}
+  \fi
+\fi
+}
+
+% like \numhead, but chooses numberless heading levels
+\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+  \unnumberedzzz{#2}
+\or
+  \unnumberedseczzz{#2}
+\or
+  \unnumberedsubseczzz{#2}
+\or
+  \unnumberedsubsubseczzz{#2}
+\else
+  \ifnum \absseclevel<0
+    \unnumberedzzz{#2}
+  \else
+    \unnumberedsubsubseczzz{#2}
+  \fi
+\fi
+}
+
+
+\def\thischaptername{No Chapter Title}
+\outer\def\chapter{\parsearg\chapteryyy}
+\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz #1{\seccheck{chapter}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \chapno by 1 \message{Chapter \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{Chapter \the\chapno: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp  %
+\donoderef %
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+}}
+
+\outer\def\appendix{\parsearg\appendixyyy}
+\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz #1{\seccheck{appendix}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \appendixno by 1 \message{Appendix \appendixletter}%
+\chapmacro {#1}{Appendix \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry
+  {#1}{Appendix \appendixletter}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp  %
+\appendixnoderef %
+\global\let\section = \appendixsec
+\global\let\subsection = \appendixsubsec
+\global\let\subsubsection = \appendixsubsubsec
+}}
+
+\outer\def\top{\parsearg\unnumberedyyy}
+\outer\def\unnumbered{\parsearg\unnumberedyyy}
+\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0
+%
+% This used to be simply \message{#1}, but TeX fully expands the
+% argument to \message.  Therefore, if #1 contained @-commands, TeX
+% expanded them.  For example, in `@unnumbered The @cite{Book}', TeX
+% expanded @cite (which turns out to cause errors because \cite is meant
+% to be executed, not expanded).
+%
+% Anyway, we don't want the fully-expanded definition of @cite to appear
+% as a result of the \message, we just want `@cite' itself.  We use
+% \the<toks register> to achieve this: TeX expands \the<toks> only once,
+% simply yielding the contents of the <toks register>.
+\toks0 = {#1}\message{(\the\toks0)}%
+%
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp  %
+\unnumbnoderef %
+\global\let\section = \unnumberedsec
+\global\let\subsection = \unnumberedsubsec
+\global\let\subsubsection = \unnumberedsubsubsec
+}}
+
+\outer\def\numberedsec{\parsearg\secyyy}
+\def\secyyy #1{\numhead1{#1}} % normally calls seczzz
+\def\seczzz #1{\seccheck{section}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appenixsection{\parsearg\appendixsecyyy}
+\outer\def\appendixsec{\parsearg\appendixsecyyy}
+\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz #1{\seccheck{appendixsection}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz #1{\seccheck{subsection}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz #1{\seccheck{appendixsubsec}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz #1{\seccheck{subsubsection}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+  {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry %
+  {#1}
+  {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}
+  {\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+  {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry{#1}%
+  {\appendixletter}
+  {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they should now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and
+% such:
+%      1) We use \vbox rather than the earlier \line to permit
+%         overlong headings to fold.
+%      2) \hyphenpenalty is set to 10000 because hyphenation in a
+%         heading is obnoxious; this forbids it.
+%       3) Likewise, headings look best if no \parindent is used, and
+%          if justification is not attempted.  Hence \raggedright.
+
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                  \parindent=0pt\raggedright
+                  \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                  \parindent=0pt\raggedright
+                  \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\heading{\parsearg\secheadingi}
+
+\def\subheading{\parsearg\subsecheadingi}
+
+\def\subsubheading{\parsearg\subsubsecheadingi}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain}
+
+\def\chfplain #1#2{%
+  \pchapsepmacro
+  {%
+    \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                     \parindent=0pt\raggedright
+                     \rm #2\enspace #1}%
+  }%
+  \bigskip
+  \penalty5000
+}
+
+\def\unnchfplain #1{%
+\pchapsepmacro %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                  \parindent=0pt\raggedright
+                  \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                       \parindent=0pt\raggedright
+                       \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen}
+
+% Parameter controlling skip before section headings.
+
+\newskip \subsecheadingskip  \subsecheadingskip = 17pt plus 8pt minus 4pt
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+
+\newskip \secheadingskip  \secheadingskip = 21pt plus 8pt minus 4pt
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+
+% @paragraphindent  is defined for the Info formatting commands only.
+\let\paragraphindent=\comment
+
+% Section fonts are the base font at magstep2, which produces
+% a size a bit more than 14 points in the default situation.
+
+\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}}
+\def\plainsecheading #1{\secheadingi {#1}}
+\def\secheadingi #1{{\advance \secheadingskip by \parskip %
+\secheadingbreak}%
+{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                 \parindent=0pt\raggedright
+                 \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+
+% Subsection fonts are the base font at magstep1,
+% which produces a size of 12 points.
+
+\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}}
+\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                     \parindent=0pt\raggedright
+                     \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+\def\subsubsecfonts{\subsecfonts} % Maybe this should change:
+                                 % Perhaps make sssec fonts scaled
+                                 % magstep half
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}}
+\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                       \parindent=0pt\raggedright
+                       \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000}
+
+
+\message{toc printing,}
+
+% Finish up the main text and prepare to read what we've written
+% to \contentsfile.
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\def\startcontents#1{%
+   \pagealignmacro
+   \immediate\closeout \contentsfile
+   \ifnum \pageno>0
+      \pageno = -1             % Request roman numbered pages.
+   \fi
+   % Don't need to put `Contents' or `Short Contents' in the headline.
+   % It is abundantly clear what they are.
+   \unnumbchapmacro{#1}\def\thischapter{}%
+   \begingroup                 % Set up to handle contents files properly.
+      \catcode`\\=0  \catcode`\{=1  \catcode`\}=2  \catcode`\@=11
+      \raggedbottom             % Worry more about breakpoints than the bottom.
+      \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+}
+
+
+% Normal (long) toc.
+\outer\def\contents{%
+   \startcontents{Table of Contents}%
+      \input \jobname.toc
+   \endgroup
+   \vfill \eject
+}
+
+% And just the chapters.
+\outer\def\summarycontents{%
+   \startcontents{Short Contents}%
+      %
+      \let\chapentry = \shortchapentry
+      \let\unnumbchapentry = \shortunnumberedentry
+      % We want a true roman here for the page numbers.
+      \secfonts
+      \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+      \rm
+      \advance\baselineskip by 1pt % Open it up a little.
+      \def\secentry ##1##2##3##4{}
+      \def\unnumbsecentry ##1##2{}
+      \def\subsecentry ##1##2##3##4##5{}
+      \def\unnumbsubsecentry ##1##2{}
+      \def\subsubsecentry ##1##2##3##4##5##6{}
+      \def\unnumbsubsubsecentry ##1##2{}
+      \input \jobname.toc
+   \endgroup
+   \vfill \eject
+}
+\let\shortcontents = \summarycontents
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+% See comments in \dochapentry re vbox and related settings
+\def\shortchapentry#1#2#3{%
+  \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}%
+}
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
+% We could simplify the code here by writing out an \appendixentry
+% command in the toc file for appendices, instead of using \chapentry
+% for both, but it doesn't seem worth it.
+\setbox0 = \hbox{\shortcontrm Appendix }
+\newdimen\shortappendixwidth \shortappendixwidth = \wd0
+
+\def\shortchaplabel#1{%
+  % We typeset #1 in a box of constant width, regardless of the text of
+  % #1, so the chapter titles will come out aligned.
+  \setbox0 = \hbox{#1}%
+  \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
+  %
+  % This space should be plenty, since a single number is .5em, and the
+  % widest letter (M) is 1em, at least in the Computer Modern fonts.
+  % (This space doesn't include the extra space that gets added after
+  % the label; that gets put in in \shortchapentry above.)
+  \advance\dimen0 by 1.1em
+  \hbox to \dimen0{#1\hfil}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{%
+  \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we would want to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+   \penalty-300 \vskip\baselineskip
+   \begingroup
+     \chapentryfonts
+     \tocentry{#1}{\dopageno{#2}}%
+   \endgroup
+   \nobreak\vskip .25\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+  \secentryfonts \leftskip=\tocindent
+  \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+  \subsecentryfonts \leftskip=2\tocindent
+  \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+  \subsubsecentryfonts \leftskip=3\tocindent
+  \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+% Final typesetting of a toc entry; we use the same \entry macro as for
+% the index entries, but we want to suppress hyphenation here.  (We
+% can't do that in the \entry macro, since index entries might consist
+% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+%
+\def\tocentry#1#2{\begingroup
+  \hyphenpenalty = 10000
+  \entry{#1}{#2}%
+\endgroup}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox    \newbox\longdblarrowbox
+\newbox\pushcharbox    \newbox\bullbox
+\newbox\equivbox       \newbox\errorbox
+
+\let\ptexequiv = \equiv
+
+%{\tentt
+%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+%                                      depth .1ex\hfil}
+%}
+
+\def\point{$\star$}
+
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% Adapted from the TeXbook's \boxit.
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+
+\global\setbox\errorbox=\hbox to \dimen0{\hfil
+   \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+   \advance\hsize by -2\dimen2 % Rules.
+   \vbox{
+      \hrule height\dimen2
+      \hbox{\vrule width\dimen2 \kern3pt          % Space to left of text.
+         \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+         \kern3pt\vrule width\dimen2}% Space to right.
+      \hrule height\dimen2}
+    \hfil}
+
+% The @error{} command.
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex    escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+\catcode `\%=14
+\catcode 43=12
+\catcode`\"=12
+\catcode`\==12
+\catcode`\|=12
+\catcode`\<=12
+\catcode`\>=12
+\escapechar=`\\
+%
+\let\{=\ptexlbrace
+\let\}=\ptexrbrace
+\let\.=\ptexdot
+\let\*=\ptexstar
+\let\dots=\ptexdots
+\def\@{@}%
+\let\bullet=\ptexbullet
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl
+\let\L=\ptexL
+%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^^M gets inside @lisp, @example, and other
+% such environments.  \null is better than a space, since it doesn't
+% have any width.
+\def\lisppar{\null\endgraf}
+
+% Make each space character in the input produce a normal interword
+% space in the output.  Don't allow a line break at this space, as this
+% is used only in environments like @example, where each line of input
+% should produce a line of output anyway.
+%
+{\obeyspaces %
+\gdef\sepspaces{\obeyspaces\let =\tie}}
+
+% Define \obeyedspace to be our active space, whatever it is.  This is
+% for use in \parsearg.
+{\sepspaces %
+\global\let\obeyedspace= }
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical.  We use \parskip here
+% to help in doing that, since in @example-like environments \parskip
+% is reset to zero; thus the \afterenvbreak inserts no space -- but the
+% start of the next paragraph will insert \parskip
+%
+\def\aboveenvbreak{{\advance\envskipamount by \parskip
+\endgraf \ifdim\lastskip<\envskipamount
+\removelastskip \penalty-50 \vskip\envskipamount \fi}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag.  If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \cartouche: draw rectangle w/rounded corners around argument
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+       \ctl\leaders\hrule height\circthick\hfil\ctr
+       \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+       \cbl\leaders\hrule height\circthick\hfil\cbr
+       \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\long\def\cartouche{%
+\begingroup
+       \lskip=\leftskip \rskip=\rightskip
+       \leftskip=0pt\rightskip=0pt %we want these *outside*.
+       \cartinner=\hsize \advance\cartinner by-\lskip
+                         \advance\cartinner by-\rskip
+       \cartouter=\hsize
+       \advance\cartouter by 18pt % allow for 3pt kerns on either
+%                                   side, and for 6pt waste from
+%                                   each corner char
+       \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+       % Flag to tell @lisp, etc., not to narrow margin.
+       \let\nonarrowing=\comment
+       \vbox\bgroup
+               \baselineskip=0pt\parskip=0pt\lineskip=0pt
+               \carttop
+               \hbox\bgroup
+                       \hskip\lskip
+                       \vrule\kern3pt
+                       \vbox\bgroup
+                               \hsize=\cartinner
+                               \kern3pt
+                               \begingroup
+                                       \baselineskip=\normbskip
+                                       \lineskip=\normlskip
+                                       \parskip=\normpskip
+                                       \vskip -\parskip
+\def\Ecartouche{%
+                               \endgroup
+                               \kern3pt
+                       \egroup
+                       \kern3pt\vrule
+                       \hskip\rskip
+               \egroup
+               \cartbot
+       \egroup
+\endgroup
+}}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+  \aboveenvbreak
+  \inENV % This group ends at the end of the body
+  \hfuzz = 12pt % Don't be fussy
+  \sepspaces % Make spaces be word-separators rather than space tokens.
+  \singlespace
+  \let\par = \lisppar % don't ignore blank lines
+  \obeylines % each line of input is a line of output
+  \parskip = 0pt
+  \parindent = 0pt
+  \emergencystretch = 0pt % don't try to avoid overfull boxes
+  % @cartouche defines \nonarrowing to inhibit narrowing
+  % at next level down.
+  \ifx\nonarrowing\relax
+    \advance \leftskip by \lispnarrowing
+    \exdentamount=\lispnarrowing
+    \let\exdent=\nofillexdent
+    \let\nonarrowing=\relax
+  \fi
+}
+
+% To ending an @example-like environment, we first end the paragraph
+% (via \afterenvbreak's vertical glue), and then the group.  That way we
+% keep the zero \parskip that the environments set -- \parskip glue
+% will be inserted at the beginning of the next paragraph in the
+% document, after the environment.
+%
+\def\nonfillfinish{\afterenvbreak\endgroup}%
+
+% This macro is
+\def\lisp{\begingroup
+  \nonfillstart
+  \let\Elisp = \nonfillfinish
+  \tt
+  \rawbackslash % have \ input char produce \ char from current font
+  \gobble
+}
+
+% Define the \E... control sequence only if we are inside the
+% environment, so the error checking in \end will work.
+%
+% We must call \lisp last in the definition, since it reads the
+% return following the @example (or whatever) command.
+%
+\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp}
+\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp}
+\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp}
+
+% @smallexample and @smalllisp.  This is not used unless the @smallbook
+% command is given.  Originally contributed by Pavel@xerox.
+%
+\def\smalllispx{\begingroup
+  \nonfillstart
+  \let\Esmalllisp = \nonfillfinish
+  \let\Esmallexample = \nonfillfinish
+  %
+  % Smaller interline space and fonts for small examples.
+  \baselineskip 10pt
+  \indexfonts \tt
+  \rawbackslash % output the \ character from the current font
+  \gobble
+}
+
+% This is @display; same as @lisp except use roman font.
+%
+\def\display{\begingroup
+  \nonfillstart
+  \let\Edisplay = \nonfillfinish
+  \gobble
+}
+
+% This is @format; same as @display except don't narrow margins.
+%
+\def\format{\begingroup
+  \let\nonarrowing = t
+  \nonfillstart
+  \let\Eformat = \nonfillfinish
+  \gobble
+}
+
+% @flushleft (same as @format) and @flushright.
+%
+\def\flushleft{\begingroup
+  \let\nonarrowing = t
+  \nonfillstart
+  \let\Eflushleft = \nonfillfinish
+  \gobble
+}
+\def\flushright{\begingroup
+  \let\nonarrowing = t
+  \nonfillstart
+  \let\Eflushright = \nonfillfinish
+  \advance\leftskip by 0pt plus 1fill
+  \gobble}
+
+% @quotation does normal linebreaking and narrows the margins.
+%
+\def\quotation{%
+\begingroup\inENV %This group ends at the end of the @quotation body
+{\parskip=0pt  % because we will skip by \parskip too, later
+\aboveenvbreak}%
+\singlespace
+\parindent=0pt
+\let\Equotation = \nonfillfinish
+% @cartouche defines \nonarrowing to inhibit narrowing
+% at next level down.
+\ifx\nonarrowing\relax
+\advance \leftskip by \lispnarrowing
+\advance \rightskip by \lispnarrowing
+\exdentamount=\lispnarrowing
+\let\nonarrowing=\relax
+\fi}
+
+\message{defuns,}
+% Define formatter for defuns
+% First, allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+% Be sure that we always have a definition for `(', etc.  For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+\global\let(=\lparen \global\let)=\rparen
+\global\let[=\lbrack \global\let]=\rbrack
+
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
+\global\advance\parencount by 1 }
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+% also in that case restore the outer-level definition of (.
+\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+\global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text.  This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
+\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+% Get the values of \leftskip and \rightskip as they were
+% outside the @def...
+\dimen2=\leftskip
+\advance\dimen2 by -\defbodyindent
+\dimen3=\rightskip
+\advance\dimen3 by -\defbodyindent
+\noindent        %
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1     %
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+{% Adjust \hsize to exclude the ambient margins,
+% so that \rightline will obey them.
+\advance \hsize by -\dimen2 \advance \hsize by -\dimen3
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}%
+% Make all lines underfull and no complaints:
+\tolerance=10000 \hbadness=10000
+\advance\leftskip by -\defbodyindent
+\exdentamount=\defbodyindent
+{\df #1}\enskip        % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+%    such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\activeparens\spacesplit#3}
+
+\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+
+\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\spacesplit#3}
+
+\def\defvrparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#4}}}
+
+% This seems to work right in all cases.
+\let\deftpparsebody=\defvrparsebody
+% This fails to work.  When given `@deftp {Data Type} foo_t',
+% it thinks the type name is just `f'.
+%%% This is the same as all the others except for the last line.  We need
+%%% to parse the arguments differently for @deftp, since the ``attributes''
+%%% there are optional.
+%%%
+%%\def\deftpparsebody #1#2#3#4 {\begingroup\inENV %
+%%\medbreak %
+%%% Define the end token that this defining construct specifies
+%%% so that it will exit this group.
+%%\def#1{\endgraf\endgroup\medbreak}%
+%%\def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+%%\parindent=0in
+%%\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+%%\exdentamount=\defbodyindent
+%%\begingroup\obeylines\parsetpheaderline{#3{#4}}}
+
+%%{\obeylines %
+%%  % Parse the type name and any attributes (field names, etc.).
+%%  % #1 is the beginning of the macro call that will produce the output,
+%%  %   i.e., \deftpheader{CLASS}; this is passed from \deftpparsebody.
+%%  % #2 is the type name, e.g., `struct termios'.
+%%  % #3 is the (possibly empty) attribute list.
+%%  %
+%%  \gdef\parsetpheaderline#1#2#3^^M{%
+%%    \endgroup % Started in \deftpparsebody.
+%%    %
+%%    % If the attribute list is in fact empty, there will be no space after
+%%    % #2; so we can't put a space in our TeX parameter list.  But if it
+%%    % isn't empty, then #3 will begin with an unwanted space.
+%%    \def\theargs{\ignorespaces #3}%
+%%    %
+%%    % Call the macro to produce the output.
+%%    #1{#2}\theargs %
+%%  }%
+%%}
+
+\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+%  the first is all of #2 before the space token,
+%  the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs #1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\hyphenchar\tensl=0
+#1%
+\hyphenchar\tensl=45
+\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\functionparens
+\code{#1}%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Function}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type.  #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\code{#1} #2}{Function}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% #1 is the classification.  #2 is the data type.  #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup\defname {\code{#2} #3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Macro}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Special Form}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% This definition is run if you use @defunx
+% anywhere other than immediately after a @defun or @defunx.
+
+\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+\def\defunx #1 {\errmessage{@defunx in invalid context}}
+\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}}
+
+% @defmethod, and so on
+
+% @defop {Funny Method} foo-class frobnicate argument
+
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+
+\def\defopheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype{} on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defmethod == @defop Method
+
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+
+\def\defmethodheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% entry in function index
+\begingroup\defname {#2}{Method on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype{} of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar == @defcv {Instance Variable}
+
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+
+\def\defivarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{Instance Variable of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% These definitions are run if you use @defmethodx, etc.,
+% anywhere other than immediately after a @defmethod, etc.
+
+\def\defopx #1 {\errmessage{@defopx in invalid context}}
+\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+% Now @defvar
+
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{Variable}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{User Option}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type.  #2 is the name.
+\def\deftypevarheader #1#2{%
+\doind {vr}{\code{#2}}% Make entry in variables index
+\begingroup\defname {\code{#1} #2}{Variable}%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}%
+\begingroup\defname {\code{#2} #3}{#1}
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% This definition is run if you use @defvarx
+% anywhere other than immediately after a @defvar or @defvarx.
+
+\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+\newif\ifhavexrefs  % True if xref values are known.
+\newif\ifwarnedxrefs  % True if we warned once that they aren't known.
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+\def\appendixsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Yappendixletterandtype}}
+
+% \xref, \pxref, and \ref generate cross-references to specified points.
+% For \xrefX, #1 is the node name, #2 the name of the Info
+% cross-reference, #3 the printed node name, #4 the name of the Info
+% file, #5 the name of the printed manual.  All but the node name can be
+% omitted.
+%
+\def\pxref#1{see \xrefX[#1,,,,,,,]}
+\def\xref#1{See \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup%
+\def\printedmanual{\ignorespaces #5}%
+\def\printednodename{\ignorespaces #3}%
+%
+\setbox1=\hbox{\printedmanual}%
+\setbox0=\hbox{\printednodename}%
+\ifdim \wd0=0pt%
+\def\printednodename{\ignorespaces #1}%
+%%% Uncommment the following line to make the actual chapter or section title
+%%% appear inside the square brackets.
+%\def\printednodename{#1-title}%
+\fi%
+%
+%
+% If we use \unhbox0 and \unhbox1 to print the node names, TeX does
+% not insert empty discretionaries after hyphens, which means that it
+% will not find a line break at a hyphen in a node names.  Since some
+% manuals are best written with fairly long node names, containing
+% hyphens, this is a loss.  Therefore, we simply give the text of
+% the node name again, so it is as if TeX is seeing it for the first
+% time.
+\ifdim \wd1>0pt
+section ``\printednodename'' in \cite{\printedmanual}%
+\else%
+\turnoffactive%
+\refx{#1-snt}{} [\printednodename], page\tie\refx{#1-pg}{}%
+\fi
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \turnoffactive so that punctuation chars such as underscore
+% work in node names.
+\def\dosetq #1#2{{\let\folio=0 \turnoffactive%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into
+% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thischapter}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 Chapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 Section\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+  \let\linenumber = \empty % Non-3.0.
+\else
+  \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+
+\def\refx#1#2{%
+  \expandafter\ifx\csname X#1\endcsname\relax
+    % If not defined, say something at least.
+    $\langle$un\-de\-fined$\rangle$%
+    \ifhavexrefs
+      \message{\linenumber Undefined cross reference `#1'.}%
+    \else
+      \ifwarnedxrefs\else
+        \global\warnedxrefstrue
+        \message{Cross reference values unknown; you must run TeX again.}%
+      \fi
+    \fi
+  \else
+    % It's defined, so just use it.
+    \csname X#1\endcsname
+  \fi
+  #2% Output the suffix in any case.
+}
+
+% Read the last existing aux file, if any.  No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+\def\readauxfile{%
+\begingroup
+\catcode `\^^@=\other
+\catcode `\\ 1=\other
+\catcode `\\ 2=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\\v=\other
+\catcode `\^^L=\other
+\catcode `\\ e=\other
+\catcode `\\ f=\other
+\catcode `\\10=\other
+\catcode `\\11=\other
+\catcode `\\12=\other
+\catcode `\\13=\other
+\catcode `\\14=\other
+\catcode `\\15=\other
+\catcode `\\16=\other
+\catcode `\\17=\other
+\catcode `\\18=\other
+\catcode `\\19=\other
+\catcode 26=\other
+\catcode `\^^[=\other
+\catcode `\^^\=\other
+\catcode `\^^]=\other
+\catcode `\^^^=\other
+\catcode `\^^_=\other
+\catcode `\@=\other
+\catcode `\^=\other
+\catcode `\~=\other
+\catcode `\[=\other
+\catcode `\]=\other
+\catcode`\"=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode `\$=\other
+\catcode `\#=\other
+\catcode `\&=\other
+% `\+ does not work, so use 43.
+\catcode 43=\other
+% the aux file uses ' as the escape.
+% Turn off \ as an escape so we do not lose on
+% entries which were dumped with control sequences in their names.
+% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+% Reference to such entries still does not work the way one would wish,
+% but at least they do not bomb out when the aux file is read in.
+\catcode `\{=1 \catcode `\}=2
+\catcode `\%=\other
+\catcode `\'=0
+\catcode `\\=\other
+\openin 1 \jobname.aux
+\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue
+\global\warnedobstrue
+\fi
+% Open the new aux file.  Tex will close it automatically at exit.
+\openout \auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed.
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only..
+\let\footnotestyle=\comment
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+%
+% Auto-number footnotes.  Otherwise like plain.
+\gdef\footnote{%
+  \global\advance\footnoteno by \@ne
+  \edef\thisfootno{$^{\the\footnoteno}$}%
+  %
+  % In case the footnote comes at the end of a sentence, preserve the
+  % extra spacing after we do the footnote number.
+  \let\@sf\empty
+  \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+  %
+  % Remove inadvertent blank space before typesetting the footnote number.
+  \unskip
+  \thisfootno\@sf
+  \footnotezzz
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter.  Our footnotes don't need to be so general.
+%
+\long\gdef\footnotezzz#1{\insert\footins{%
+  % We want to typeset this text as a normal paragraph, even if the
+  % footnote reference occurs in (for example) a display environment.
+  % So reset some parameters.
+  \interlinepenalty\interfootnotelinepenalty
+  \splittopskip\ht\strutbox % top baseline for broken footnotes
+  \splitmaxdepth\dp\strutbox
+  \floatingpenalty\@MM
+  \leftskip\z@skip
+  \rightskip\z@skip
+  \spaceskip\z@skip
+  \xspaceskip\z@skip
+  \parindent\defaultparindent
+  %
+  % Hang the footnote text off the number.
+  \hang
+  \textindent{\thisfootno}%
+  %
+  % Don't crash into the line above the footnote text.  Since this
+  % expands into a box, it must come within the paragraph, lest it
+  % provide a place where TeX can split the footnote.
+  \footstrut
+  #1\strut}%
+}
+
+}%end \catcode `\@=11
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly.  There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.08333}
+\def\strutheightpercent{.70833}
+\def\strutdepthpercent {.29167}
+%
+\def\setleading#1{%
+  \normalbaselineskip = #1\relax
+  \normallineskip = \lineskipfactor\normalbaselineskip
+  \normalbaselines
+  \setbox\strutbox =\hbox{%
+    \vrule width0pt height\strutheightpercent\baselineskip
+                    depth \strutdepthpercent \baselineskip
+  }%
+}
+
+% @| inserts a changebar to the left of the current line.  It should
+% surround any changed text.  This approach does *not* work if the
+% change spans more than two lines of output.  To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+  % \vadjust can only be used in horizontal mode.
+  \leavevmode
+  %
+  % Append this vertical mode material after the current line in the output.
+  \vadjust{%
+    % We want to insert a rule with the height and depth of the current
+    % leading; that is exactly what \strutbox is supposed to record.
+    \vskip-\baselineskip
+    %
+    % \vadjust-items are inserted at the left edge of the type.  So
+    % the \llap here moves out into the left-hand margin.
+    \llap{%
+      %
+      % For a thicker or thinner bar, change the `1pt'.
+      \vrule height\baselineskip width1pt
+      %
+      % This is the space between the bar and the text.
+      \hskip 12pt
+    }%
+  }%
+}
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+
+% End of control word definitions.
+
+\message{and turning on texinfo input format.}
+
+\def\openindices{%
+   \newindex{cp}%
+   \newcodeindex{fn}%
+   \newcodeindex{vr}%
+   \newcodeindex{tp}%
+   \newcodeindex{ky}%
+   \newcodeindex{pg}%
+}
+
+% Set some numeric style parameters, for 8.5 x 11 format.
+
+%\hsize = 6.5in
+\newdimen\defaultparindent \defaultparindent = 15pt
+\parindent = \defaultparindent
+\parskip 18pt plus 1pt
+\setleading{15pt}
+\advance\topskip by 1.2cm
+
+% Prevent underfull vbox error messages.
+\vbadness=10000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything.  We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize.  This makes it come to about 9pt for the 8.5x11 format.
+%
+\ifx\emergencystretch\thisisundefined
+  % Allow us to assign to \emergencystretch anyway.
+  \def\emergencystretch{\dimen0}%
+\else
+  \emergencystretch = \hsize
+  \divide\emergencystretch by 45
+\fi
+
+% Use @smallbook to reset parameters for 7x9.5 format  (or else 7x9.25)
+\def\smallbook{
+
+% These values for secheadingskip and subsecheadingskip are
+% experiments.  RJC 7 Aug 1992
+\global\secheadingskip = 17pt plus 6pt minus 3pt
+\global\subsecheadingskip = 14pt plus 6pt minus 3pt
+
+\global\lispnarrowing = 0.3in
+\setleading{12pt}
+\advance\topskip by -1cm
+\global\parskip 3pt plus 1pt
+\global\hsize = 5in
+\global\vsize=7.5in
+\global\tolerance=700
+\global\hfuzz=1pt
+\global\contentsrightmargin=0pt
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+
+\global\let\smalllisp=\smalllispx
+\global\let\smallexample=\smalllispx
+\global\def\Esmallexample{\Esmalllisp}
+}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{
+\global\tolerance=700
+\global\hfuzz=1pt
+\setleading{12pt}
+\global\parskip 15pt plus 1pt
+
+\global\vsize= 53\baselineskip
+\advance\vsize by \topskip
+%\global\hsize=   5.85in     % A4 wide 10pt
+\global\hsize=  6.5in
+\global\outerhsize=\hsize
+\global\advance\outerhsize by 0.5in
+\global\outervsize=\vsize
+\global\advance\outervsize by 0.6in
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise.  Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt \char '042}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt \char '176}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\lvvmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+% \lvvmode is equivalent in function to \leavevmode.
+% Using \leavevmode runs into trouble when written out to
+% an index file due to the expansion of \leavevmode into ``\unhbox
+% \voidb@x'' ---which looks to TeX like ``\unhbox \voidb\x'' due to our
+% magic tricks with @.
+\def\lvvmode{\vbox to 0pt{}}
+
+\catcode`\|=\active
+\def|{{\tt \char '174}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+\def\turnoffactive{\let"=\normaldoublequote
+\let~=\normaltilde
+\let^=\normalcaret
+\let_=\normalunderscore
+\let|=\normalverticalbar
+\let<=\normalless
+\let>=\normalgreater
+\let+=\normalplus}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% Say @foo, not \foo, in error messages.
+\escapechar=`\@
+
+% \catcode 17=0   % Define control-q
+\catcode`\\=\active
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+%
+@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi}
+
+%% These look ok in all fonts, so just make them not special.  The @rm below
+%% makes sure that the current font starts out as the newly loaded cmr10
+@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+
+@textfonts
+@rm
+
+@c Local variables:
+@c page-delimiter: "^\\\\message"
+@c End:
diff --git a/endian.c b/endian.c
new file mode 100644 (file)
index 0000000..7de8706
--- /dev/null
+++ b/endian.c
@@ -0,0 +1,148 @@
+/* endian.c -- A trick for determining the byte order of a machine. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include "bashansi.h"
+
+/* The name of this program, as taken from argv[0]. */
+char *progname;
+
+/* The name of the source file that this code is made from. */
+char source_name[256];
+
+/* The name of the define.  Either "BIG_ENDIAN" or "LITTLE_ENDIAN". */
+char *endian_define;
+
+char string[9];
+char nstring[9];
+
+/* Stuff "1234" into a long, and compare it against a character string
+   "1234".  If the results are EQ, the machine is big endian like a 68000
+   or Sparc, otherwise it is little endian, like a Vax, or 386. */
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+#if defined (__STDC__)
+  register size_t i;
+#else
+  register int i;
+#endif /* !__STDC__ */
+  FILE *stream = (FILE *)NULL;
+  char *stream_name = "stdout";
+  union {
+      unsigned long l;
+      char s[sizeof (long)];
+  } u;
+
+  progname = argv[0];
+
+  for (i = strlen (progname); i > 0; i--)
+    if (progname[i] == '/')
+      {
+       progname = progname + i + 1;
+       break;
+      }
+
+  strcpy (source_name, progname);
+  for (i = strlen (source_name); i > 0; i--)
+    if (source_name[i] == '.')
+      {
+       source_name[i] = '\0';
+       break;
+      }
+
+  strcat (source_name, ".c");
+
+  if (argc == 1)
+    {
+      stream_name = "stdout";
+      stream = stdout;
+    }
+  else if (argc == 2)
+    {
+      stream_name = argv[1];
+      stream = fopen (stream_name, "w");
+    }
+  else
+    {
+      fprintf (stderr, "Usage: %s [output-file]\n", progname);
+      exit (1);
+    }
+
+  if (!stream)
+    {
+      fprintf (stderr, "%s: %s Cannot be opened or written to.\n",
+              progname, stream_name);
+      exit (2);
+    }
+
+  if (sizeof (long int) == 4)
+    {
+      u.l = 0x04030201L;
+      (void) strcpy (string, "4321");
+    }
+  else if (sizeof (long int) == 8)
+    {
+#if defined (__GNUC__)
+      unsigned long fake_out_gcc;
+
+      fake_out_gcc = (0x08070605L << 31);
+      fake_out_gcc = (fake_out_gcc << 1);
+      u.l = fake_out_gcc | 0x04030201L;
+#else
+      u.l = (0x08070605L << 32) | 0x04030201L;
+#endif /* !__GNUC__ */
+      (void) strcpy (string, "87654321");
+    }
+  else
+    {
+      fprintf (stderr,
+              "%s: sizeof (long int) = %d, which isn't handled here.\n",
+              progname, sizeof (long int));
+      exit (2);
+    }
+
+  for (i = 0; i < sizeof (long); i++)
+    nstring[i] = u.s[i] + '0';
+  nstring[i] = '\0';
+
+  if (strcmp (nstring, string) == 0)
+    endian_define = "BIG_ENDIAN";
+  else
+    endian_define = "LITTLE_ENDIAN";
+
+  fprintf (stream, "/* %s - Define BIG or LITTLE endian. */\n\n", stream_name);
+  fprintf (stream,
+"/* This file was automatically created by `%s'.  You shouldn't\n\
+   edit this file, because your changes will be overwritten.  Instead,\n\
+   edit the source code file `%s'. */\n\n",
+          progname, source_name);
+
+  fprintf (stream, "#if !defined (%s)\n", endian_define);
+  fprintf (stream, "#  define %s\n", endian_define);
+  fprintf (stream, "#endif /* %s */\n", endian_define);
+
+  if (stream != stdout)
+    fclose (stream);
+
+  exit (0);
+}
diff --git a/error.c b/error.c
new file mode 100644 (file)
index 0000000..5ffd4ab
--- /dev/null
+++ b/error.c
@@ -0,0 +1,244 @@
+/* error.c -- Functions for handling errors. */
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#if defined (HAVE_VFPRINTF)
+#include <varargs.h>
+#endif
+
+#include <errno.h>
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "bashansi.h"
+#include "flags.h"
+#include "error.h"
+#include "command.h"
+#include "general.h"
+
+extern int interactive_shell;
+extern char *dollar_vars[];
+extern char *shell_name;
+extern char *the_current_maintainer;
+#if defined (JOB_CONTROL)
+extern pid_t shell_pgrp;
+#endif /* JOB_CONTROL */
+
+/* Return the name of the shell or the shell script for error reporting. */
+char *
+get_name_for_error ()
+{
+  char *name = (char *) NULL;
+
+  if (!interactive_shell)
+    name = dollar_vars[0];
+  if (!name && shell_name && *shell_name)
+    name = base_pathname (shell_name);
+  if (!name)
+    name = "bash";
+
+  return (name);
+}
+
+/* Report an error having to do with FILENAME. */
+void
+file_error (filename)
+     char *filename;
+{
+  report_error ("%s: %s", filename, strerror (errno));
+}
+
+#if !defined (HAVE_VFPRINTF)
+void
+programming_error (reason, arg1, arg2, arg3, arg4, arg5)
+     char *reason;
+{
+#if defined (JOB_CONTROL)
+  give_terminal_to (shell_pgrp);
+#endif /* JOB_CONTROL */
+
+  report_error (reason, arg1, arg2);
+  fprintf (stderr, "Report this to %s\n", the_current_maintainer);
+  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
+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");
+}
+
+#else /* We have VARARGS support, so use it. */
+
+void
+programming_error (va_alist)
+     va_dcl
+{
+  va_list args;
+  char *format;
+
+#if defined (JOB_CONTROL)
+  give_terminal_to (shell_pgrp);
+#endif /* JOB_CONTROL */
+
+  va_start (args);
+  format = va_arg (args, char *);
+  vfprintf (stderr, format, args);
+  fprintf (stderr, "\n");
+  va_end (args);
+
+  fprintf (stderr, "Tell %s to fix this someday.\n", the_current_maintainer);
+  fprintf (stderr, "Stopping myself...");
+  fflush (stderr);
+  abort ();
+}
+
+void
+report_error (va_alist)
+     va_dcl
+{
+  va_list args;
+  char *format;
+
+  fprintf (stderr, "%s: ", get_name_for_error ());
+  va_start (args);
+  format = va_arg (args, char *);
+  vfprintf (stderr, format, args);
+  fprintf (stderr, "\n");
+
+  va_end (args);
+  if (exit_immediately_on_error)
+    exit (1);
+}
+
+void
+fatal_error (va_alist)
+     va_dcl
+{
+  va_list args;
+  char *format;
+
+  fprintf (stderr, "%s: ", get_name_for_error ());
+  va_start (args);
+  format = va_arg (args, char *);
+  vfprintf (stderr, format, args);
+  fprintf (stderr, "\n");
+
+  va_end (args);
+  exit (2);
+}
+
+void
+internal_error (va_alist)
+     va_dcl
+{
+  va_list args;
+  char *format;
+
+  fprintf (stderr, "%s: ", get_name_for_error ());
+  va_start (args);
+  format = va_arg (args, char *);
+  vfprintf (stderr, format, args);
+  fprintf (stderr, "\n");
+
+  va_end (args);
+}
+
+itrace (va_alist)
+     va_dcl
+{
+  va_list args;
+  char *format;
+
+  fprintf(stderr, "TRACE: pid %d: ", getpid());
+  va_start (args);
+  format = va_arg (args, char *);
+  vfprintf (stderr, format, args);
+  fprintf (stderr, "\n");
+
+  va_end (args);
+
+  fflush(stderr);
+}
+
+#if 0
+/* A trace function for silent debugging -- doesn't require a control
+   terminal. */
+trace (va_alist)
+     va_dcl
+{
+  va_list args;
+  char *format;
+  static FILE *tracefp = (FILE *)NULL;
+
+  if (tracefp == NULL)
+    tracefp = fopen("/usr/tmp/bash-trace.log", "a+");
+
+  if (tracefp == NULL)
+    tracefp = stderr;
+  else
+    fcntl (fileno (tracefp), F_SETFD, 1);     /* close-on-exec */
+
+  fprintf(tracefp, "TRACE: pid %d: ", getpid());
+
+  va_start (args);
+  format = va_arg (args, char *);
+  vfprintf (tracefp, format, args);
+  fprintf (tracefp, "\n");
+
+  va_end (args);
+
+  fflush(tracefp);
+}
+#endif
+#endif /* HAVE_VFPRINTF */
diff --git a/error.h b/error.h
new file mode 100644 (file)
index 0000000..15a5091
--- /dev/null
+++ b/error.h
@@ -0,0 +1,34 @@
+/* error.h -- External declarations of functions appearing in error.c. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Get the name of the shell or shell script for an error message. */
+extern char *get_name_for_error ();
+
+/* Report an error having to do with FILENAME. */
+extern void file_error ();
+
+/* Report a programmer's error, and abort.  Pass REASON, and ARG1 ... ARG5. */
+extern void programming_error ();
+
+/* General error reporting.  Pass FORMAT and ARG1 ... ARG5. */
+extern void report_error ();
+
+/* Report an unrecoverable error and exit.  Pass FORMAT and ARG1 ... ARG5. */
+extern void fatal_error ();
diff --git a/examples/alias-conv.sh b/examples/alias-conv.sh
new file mode 100755 (executable)
index 0000000..edbed86
--- /dev/null
@@ -0,0 +1,22 @@
+#! /bin/sh
+#
+# Convert Csh aliases to Bash aliases.  Adapted from a similar program
+# supplied with zsh.
+#
+# This is a quick script to convert csh aliases to Bash aliases/functions.
+# Pipe the output of csh's alias command through this; it will generate
+# a series of alias/function definitions on stdout, suitable for
+# processing by bash.
+#
+# This is not perfect, but it gets most common aliases; it should manage to
+# cut down a lot of the busy work.
+#
+sed -e 's/     (\(.*\))/       \1/' >/tmp/cz$$.1
+grep ! /tmp/cz$$.1 >/tmp/cz$$.2
+grep -v ! /tmp/cz$$.1 >/tmp/cz$$.3
+sed -e "s/'/'"\\\\"''"/g -e 's/^\([^   ]*\)    \(.*\)$/alias \1='"'\2'/" \
+       /tmp/cz$$.3
+sed -e 's/![:#]*/$/g' -e 's/^\([^      ]*\)    \(.*\)$/\1 () { \2 }/' /tmp/cz$$.2
+rm /tmp/cz$$.?
+
+exit 0
diff --git a/examples/functions/autoload b/examples/functions/autoload
new file mode 100644 (file)
index 0000000..a6ae421
--- /dev/null
@@ -0,0 +1,103 @@
+#
+# An almost ksh-compatible `autoload'.  A function declared as `autoload' will
+# be read in from a file the same name as the function found by searching the
+# $FPATH (which works the same as $PATH), then that definition will be run.
+#
+# To do this without source support, we define a dummy function that, when
+# executed, will load the file (thereby re-defining the function), then 
+# execute that newly-redefined function with the original arguments.
+#
+# It's not identical to ksh because ksh apparently does lazy evaluation
+# and looks for the file to load from only when the function is referenced.
+# This one requires that the file exist when the function is declared as
+# `autoload'.
+#
+# usage: autoload func [func...]
+#
+# The first cut of this was by Bill Trost, trost@reed.bitnet
+#
+# Chet Ramey
+# chet@ins.CWRU.Edu
+
+#
+# Declare a function ($1) to be autoloaded from a file ($2) when it is first
+# called.  This defines a `temporary' function that will `.' the file 
+# containg the real function definition, then execute that new definition with
+# the arguments given to this `fake' function.  The autoload function defined
+# by the file and the file itself *must* be named identically.
+#
+
+aload()
+{
+       eval $1 '() {  . '$2' ; '$1' "$@" ; return $?; }'
+}
+
+#
+# Search $FPATH for a file the same name as the function given as $1, and
+# autoload the function from that file.  There is no default $FPATH.
+#
+
+autoload()
+{
+       #
+       # Save the list of functions; we're going to blow away the arguments
+       # in a second.  If any of the names contain white space, TFB.
+       #
+
+       local args="$*"
+
+       #
+       # This should, I think, list the functions marked as autoload and not
+       # yet defined, but we don't have enough information to do that here.
+       #
+       if [ $# -eq 0 ] ; then
+               echo "usage: autoload function [function...]"
+               return 1
+       fi
+
+       #
+       # If there is no $FPATH, there is no work to be done
+       #
+
+       if [ -z "$FPATH" ] ; then
+               echo autoload: FPATH not set
+               return 1
+       fi
+
+       #
+       # This treats FPATH exactly like PATH: a null field anywhere in the
+       # FPATH is treated the same as the current directory.
+       #
+       # The path splitting command is taken from Kernighan and Pike
+       #
+
+       fp=$(echo $FPATH | sed 's/^:/.:/
+                               s/::/:.:/g
+                               s/:$/:./
+                               s/:/ /g')
+
+       for FUNC in $args ; do
+               #
+               # We're blowing away the arguments to autoload here...
+               # We have to; there are no arrays.
+               #
+               set $fp
+
+               while [ $# -ne 0 ] ; do
+                       if [ -f $1/$FUNC ] ; then
+                               break                   # found it! 
+                       fi
+                       shift
+               done
+
+               if [ $# -eq 0 ] ; then
+                       echo "$FUNC: autoload function not found"
+                       continue
+               fi
+
+#              echo auto-loading $FUNC from $1/$FUNC
+               aload $FUNC $1/$FUNC
+       done
+
+       return 0
+}
diff --git a/examples/functions/basename b/examples/functions/basename
new file mode 100644 (file)
index 0000000..a541349
--- /dev/null
@@ -0,0 +1,23 @@
+# Date: Fri, 11 Oct 91 11:22:36 edt
+# From: friedman@gnu.ai.mit.edu
+# To: bfox@gnu.ai.mit.edu
+
+# A replacement for basename(1).  Not all the systems I use have this
+# program.  Usage: basename [path] {extension}
+function basename ()
+{
+ local path="$1"
+ local suffix="$2"
+ local tpath="${path%/}"
+
+    # Strip trailing '/' characters from path (unusual that this should
+    # ever occur, but basename(1) seems to deal with it.)
+    while [ "${tpath}" != "${path}" ]; do
+       tpath="${path}"
+       path="${tpath%/}"
+    done
+
+    path="${path##*/}"       # Strip off pathname
+    echo ${path%${suffix}}   # Also strip off extension, if any.
+}
+
diff --git a/examples/functions/csh-compat b/examples/functions/csh-compat
new file mode 100644 (file)
index 0000000..8eaf754
--- /dev/null
@@ -0,0 +1,36 @@
+# C-shell compatabilty package.
+# setenv VAR VALUE
+function setenv () {
+  export $1="$2"
+}
+
+function unsetenv () {
+  unset $1
+}
+
+function alias () {
+  local name=$1
+  shift
+  local value="$*"
+
+  if [ "$name" = "" ]; then
+    builtin alias
+  elif [ "$value" = "" ]; then
+    builtin alias $name
+  else
+    builtin alias $name="$value"
+  fi
+}
+
+# Can't write foreach yet.  Need pattern matching, and a few extras.
+function foreach () {
+echo 'Can'\''t do `foreach'\'' yet.  Type "help for".'
+}
+
+# Make this work like csh's.  Special case "term" and "path".
+#set () {
+#}
+
+chdir () {
+  builtin cd $*
+ }
diff --git a/examples/functions/dirfuncs b/examples/functions/dirfuncs
new file mode 100644 (file)
index 0000000..3958bbe
--- /dev/null
@@ -0,0 +1,142 @@
+#
+# Directory manipulation functions from the book 'The Korn Shell'
+# Modified for use with bash Mon Apr 18 08:37 1994 by
+# Ken Konecki (kenk@wfg.com)
+#
+# Modified by Chet Ramey
+#
+# This could stand to have calls to `select' added back in
+# 
+
+alias integer="declare -i"
+
+integer  _push_max=${CDSTACK-31} _push_top=${CDSTACK-31}
+
+unalias cd
+# alias cd=_cd
+
+# Display directory stack -- $HOME display as ~
+dirs()
+{
+    dir="${PWD#$HOME/}" 
+    case $dir in
+    $HOME) dir=\~ ;;
+    /*) ;;
+    *) dir=\~/$dir ;;
+    esac
+
+    integer i=_push_top
+    integer n=1
+
+    echo "$n) $dir"
+    while let "i < $_push_max"
+    do
+       n=n+1
+       eval "echo \$n\) \$_push_stack_$i"
+       i=i+1
+    done
+}
+
+# Change directory and put directory on front of stack
+cd()
+{
+    typeset dir=
+    integer n=0 type=4 i
+    case $1 in
+    -|-1|2) # cd -
+       n=_push_top type=1
+       ;;
+    -[1-9]|-[1-9][0-9]) # cd -n
+       n=_push_top+${1#-}-1 type=2
+       ;;
+
+    1) # keep present directory
+       echo "$PWD"
+       return
+       ;;
+
+    [2-9]|[1-9][0-9]) # cd n
+       n=_push_top+${1}-2 type=2
+       ;;
+
+    *)
+       if let "_push_top <= 0"; then
+           type=3 n=_push_max
+       fi
+       ;;
+    esac
+
+    if let "type < 3"; then
+       if let "n >= _push_max"; then
+           echo cd: Directory stack not that deep
+           return 1
+       else
+           eval dir=\${_push_stack_$n}
+       fi
+    fi
+
+    case $dir in
+    ~*) dir=$HOME${dir#\~} ;;
+    esac
+
+    cd2 ${dir:-$@} > /dev/null || return 1
+    dir=${OLDPWD#$HOME/}
+    case $dir in
+    $HOME)     dir=\~ ;;
+    /*)        ;;
+    *)                 dir=\~/$dir ;;
+    esac
+
+    case $type in
+    1) # swap first two elements
+       eval _push_stack_$_push_top=\$dir ;;
+
+    2|3) # put $dir on top and shift down by one until top
+       i=_push_top
+       unset _dirlist
+       while let "i < $_push_max" ; do
+           eval _dirlist=\"\$_dirlist \$_push_stack_$i\"
+           i=i+1
+       done
+
+       i=_push_top
+       for dir in "$dir" ${_dirlist} ; do
+           let "i > n" && break
+           eval _push_stack_$i=\$dir
+           i=i+1
+       done
+       ;;
+    4) # push name
+       _push_top=_push_top-1;
+       eval _push_stack_$_push_top=\$dir
+       ;;
+    esac
+
+    echo "$PWD"
+
+}
+
+# Menu-driven change directory command
+function mcd
+{
+    dirs
+    echo -n "Select by number or enter a name: "
+    read
+    cd $REPLY
+}
+
+
+# Emulate ksh cd substitution
+cd2()
+{
+    case "$#" in
+    0) builtin cd "$HOME" ;;
+    1)  builtin cd "$1" ;;
+    2)  newDir=$(echo $PWD | sed -e "s:$1:$2:g")
+       case "$newDir" in
+       $PWD)   echo "bash:: cd: bad substitution" >&2 ; return 1 ;;
+       *)      builtin cd "$newDir" ;;
+       esac ;;
+    *)  echo "bash: cd: wrong arg count" 1>&2 ; return 1 ;;
+    esac
+}      
diff --git a/examples/functions/dirname b/examples/functions/dirname
new file mode 100644 (file)
index 0000000..ccb8c84
--- /dev/null
@@ -0,0 +1,21 @@
+# Date: Fri, 11 Oct 91 11:22:36 edt
+# From: friedman@gnu.ai.mit.edu
+# To: bfox@gnu.ai.mit.edu
+
+# A replacement for dirname(1).  This one appears less often on some
+# systems I use than basename(1), and I really depend on it for some
+# things.  Usage: dirname [path]
+function dirname ()
+{
+ local dir="$1"
+ local tdir="${dir%/}"
+
+    # Strip trailing '/' characters from dir (unusual that this should
+    # ever occur, but dirname(1) seems to deal with it.)
+    while [ "${tdir}" != "${dir}" ]; do
+       tdir="${dir}"
+       dir="${tdir%/}"
+    done
+
+    echo "${dir%/*}"
+}
diff --git a/examples/functions/exitstat b/examples/functions/exitstat
new file mode 100644 (file)
index 0000000..bae3f27
--- /dev/null
@@ -0,0 +1,22 @@
+# Contributed by Noah Friedman and Roland McGrath.
+
+# To be run by the PROMPT_COMMAND variable, so that one can see what
+# the exit status of processes are.
+
+function check_exit_status ()
+{
+ local status="$?"
+ local signal=""
+
+    if [ ${status} -ne 0 -a ${status} != 128 ]; then
+       # If process exited by a signal, determine name of signal.
+       if [ ${status} -gt 128 ]; then
+          signal="$(builtin kill -l $[${status} - 128] 2>/dev/null)"
+         if [ "$signal" ]; then signal="($signal)"; fi
+       fi
+       echo "[Exit ${status} ${signal}]" 1>&2
+    fi
+    return 0
+}
+
+PROMPT_COMMAND=check_exit_status
diff --git a/examples/functions/external b/examples/functions/external
new file mode 100644 (file)
index 0000000..c2e52cd
--- /dev/null
@@ -0,0 +1,50 @@
+# Contributed by Noah Friedman.
+
+# To avoid using a function in bash, you can use the `builtin' or
+# `command' builtins, but neither guarantees that you use an external
+# program instead of a bash builtin if there's a builtin by that name.  So
+# this function can be used like `command' except that it guarantees the
+# program is external by first disabling any builtin by that name.  After
+# the command is done executing, the state of the builtin is restored. 
+function external ()
+{
+ local state=""
+ local exit_status
+  
+    if builtin_p "$1"; then
+       state="builtin"
+       enable -n "$1"
+    fi
+
+    command "$@"
+    exit_status=$?
+
+    if [ "$state" = "builtin" ]; then
+       enable "$1"
+    fi
+
+    return ${exit_status}
+}
+
+# What is does is tell you if a particular keyword is currently enabled as
+# a shell builtin.  It does NOT tell you if invoking that keyword will
+# necessarily run the builtin.  For that, do something like
+#
+#       test "$(builtin type -type [keyword])" = "builtin"
+#
+# Note also, that disabling a builtin with "enable -n" will make builtin_p
+# return false, since the builtin is no longer available.
+function builtin_p ()
+{
+ local word
+
+    set $(builtin type -all -type "$1")
+
+    for word in "$@" ; do
+       if [ "${word}" = "builtin" ]; then
+          return 0
+       fi
+    done
+
+    return 1
+}
diff --git a/examples/functions/fact b/examples/functions/fact
new file mode 100644 (file)
index 0000000..cd7bf46
--- /dev/null
@@ -0,0 +1,13 @@
+# Who said shells can't use recursion?  Here is a factorial function.
+# You call it with a number as an argument, and it returns the factorial
+# of that number.
+
+fact ()
+{
+    local num=$1;
+    if [ "$num" = 1 ] ; then
+        echo 1
+        return ;
+    fi;
+    echo $[ $num * $(fact $[ $num - 1 ])]
+}
diff --git a/examples/functions/fstty b/examples/functions/fstty
new file mode 100644 (file)
index 0000000..a770d84
--- /dev/null
@@ -0,0 +1,59 @@
+#
+# A function that works as a front end for both stty and the `bind'
+# builtin, so the tty driver and readline see the same changes
+#
+
+#
+# Convert between the stty ^H control character form and the readline \C-H
+# form
+#
+cvt()
+{
+       echo "$@" | cat -v | sed 's/\^/\\C-/'
+}
+
+#
+# stty front-end.  Parses the argument list and creates two command strings,
+# one for stty, another for bind.
+#
+fstty()
+{
+       local   cmd="" bargs=""
+       local   e
+
+       while [ $# -gt 0 ]
+       do
+               case "$1" in
+               -a)     cmd="$cmd everything"
+                       ;;
+               erase)  shift;
+                       e=$(cvt "$1")
+                       cmd="$cmd erase $1"
+                       bargs="$bargs '\"$e\": backward-delete-char'"
+                       ;;
+               kill)   shift
+                       e=$(cvt "$1")
+                       cmd="$cmd kill $1"
+                       bargs="$bargs '\"$e\": unix-line-discard'"
+                       ;;
+               werase) shift;
+                       e=$(cvt "$1")
+                       cmd="$cmd erase $1"
+                       bargs="$bargs '\"$e\": backward-kill-word'"
+                       ;;
+               lnext)  shift;
+                       e=$(cvt "$1")
+                       cmd="$cmd erase $1"
+                       bargs="$bargs '\"$e\": quoted-insert'"
+                       ;;
+               *)      cmd="$cmd $1"
+                       ;;
+               esac
+               shift
+       done
+
+       command stty $cmd
+       if [ -n "$bargs" ]; then
+               builtin bind $bargs
+       fi
+}
diff --git a/examples/functions/func b/examples/functions/func
new file mode 100644 (file)
index 0000000..710f643
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# func -- print out definitions for functions named by arguments
+#
+# usage: func name [name ...]
+#
+# Chet Ramey
+# chet@ins.CWRU.Edu
+func()
+{
+       local status=0
+
+       if [ $# -eq 0 ] ; then
+               echo "usage: func name [name...]" 1>&2
+               return 1
+       fi
+
+       for f
+       do
+               if [ "$(builtin type -type $f)" != "function" ] ; then
+                       echo "func: $f: not a function" 1>&2
+                       status=1        # one failed
+                       continue
+               fi
+               builtin type $f | sed 1d
+       done
+       return $status
+}
diff --git a/examples/functions/jj.bash b/examples/functions/jj.bash
new file mode 100644 (file)
index 0000000..212c9ce
--- /dev/null
@@ -0,0 +1,12 @@
+jj ()
+{
+       p=$(jobs $1);
+       echo $p
+
+       case "$p" in
+       [*)     echo matches '[*'
+               ;;
+       *)      echo not a match\?
+               ;;
+       esac
+}
diff --git a/examples/functions/kshenv b/examples/functions/kshenv
new file mode 100644 (file)
index 0000000..fbec76f
--- /dev/null
@@ -0,0 +1,183 @@
+#
+# .kshenv -- functions and aliases to provide the beginnings of a ksh 
+#           environment for bash.
+#
+# Chet Ramey
+# chet@ins.CWRU.Edu
+#
+#
+# These are definitions for the ksh compiled-in `exported aliases'.  There
+# are others, but we already have substitutes for them: "history", "type",
+# and "hash".
+#
+alias r="fc -e -"
+alias functions="typeset -f"
+alias integer="typeset -i"
+alias nohup="nohup "
+alias true=":"
+alias false="let 0"
+alias hist="fc"
+
+#
+# An almost-ksh compatible `whence' command.  This is as hairy as it is 
+# because of the desire to exactly mimic ksh (whose behavior was determined
+# empirically).
+# 
+# This depends somewhat on knowing the format of the output of the bash
+# `builtin type' command.
+#
+
+whence()
+{
+       local vflag
+       local path
+
+       vflag=
+       path=
+       if [ "$#" = "0" ] ; then
+               echo "whence: argument expected"
+               return 1
+       fi
+       case "$1" in
+               -v) vflag=1
+                   shift 1
+                   ;;
+               -*) echo "whence: bad option: $1"
+                   return 1
+                   ;;
+                *) ;;
+       esac
+
+       if [ "$#" = "0" ] ; then
+               echo "whence: bad argument count"
+               return 1
+       fi
+
+       for cmd
+       do
+               if [ "$vflag" ]  ; then
+                       echo $(builtin type $cmd | sed 1q)
+               else
+                       path=$(builtin type -path $cmd)
+                       if [ "$path" ] ; then
+                               echo $path
+                       else
+                               case "$cmd" in
+                                       /*) echo ""
+                                           ;;
+                                        *) case "$(builtin type -type $cmd)" in
+                                               "") echo ""
+                                                   ;;
+                                                *) echo "$cmd"
+                                                   ;;
+                                           esac
+                                           ;;
+                               esac
+                       fi
+               fi
+       done
+       return 0
+}
+
+#
+# For real ksh homeboy fanatics, redefine the `type' builtin with a ksh
+# version.
+#
+#type()
+#{
+#      whence -v "$*"
+#}
+
+cd()
+{
+       case $# in
+       0)      builtin cd "$HOME" ;;
+       1)      builtin cd "$@" ;;
+       2)      old="$1"
+               new="$2"
+               dir=$(echo "$PWD" | sed "s:$old:$new:g")
+               case "$dir" in
+               "$PWD") echo "bash: cd: bad substitution" >&2 ; return 1 ;;
+               *)      echo "$dir"
+                       builtin cd "$dir"
+                       ;;
+               esac
+               ;;
+       *)      echo "cd: wrong arg count" >&2 ; return 1 ;;
+       esac
+}
+
+#
+# ksh print emulation
+#
+#      print [-Rnprsu[n]] [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      no-op (print to the history file)
+#      -u n    redirect output to fd n
+#
+
+print()
+{
+       local eflag=-e
+       local nflag=
+       local fd=1
+
+       OPTIND=1
+       while getopts "Rnprsu:" c
+       do
+               case $c in
+               R)      eflag=
+                       ;;
+               r)      eflag=
+                       ;;
+               n)      nflag=-n
+                       ;;
+               u)      fd=$OPTARG
+                       ;;
+               p|s)    ;;
+               esac
+       done
+       shift $[ $OPTIND - 1 ]
+
+       builtin echo $eflag $nflag "$@" >&$fd
+}
+
+# substring function
+# this function should be equivalent to the substring built-in which was
+# eliminated after the 06/29/84 version
+substring ()
+{
+       local lpat flag str     #local variables
+       set -f
+       case $1 in
+       -l|-L)
+               flag=$1
+               lpat=$2
+               shift 2
+               ;;
+       esac
+       # test for too few or too many arguments
+       if [ x"$1" = x -o $# -gt 2 ]; then
+               print -u2 'substring: bad argument count'
+               return 1
+       fi
+       str=$1
+       if [ x"$flag" = x-l ]; then             #substring -l lpat
+               str=${str#$lpat}
+       elif [ x"$flag" = x-L ]; then
+               str=${str##$lpat}               #substring -L lpat
+       fi
+
+       if [ x"$2" != x ]; then
+               echo ${str%$2}
+       else
+               echo $str
+       fi
+
+       return 0
+}
diff --git a/examples/functions/manpage b/examples/functions/manpage
new file mode 100644 (file)
index 0000000..3fdc7ac
--- /dev/null
@@ -0,0 +1,129 @@
+# Written from scratch by Tom Tromey (tromey@cns.caltech.edu)
+#
+# manpage -- find and print a manual page.
+# usage: manpage section name [printing]
+#
+function manpage ()
+{
+  local i h cmd zot sec
+  local num="$1"
+  local page="$2"
+  local printing="$3"
+  local mp
+
+  mp="${MANPATH:-/usr/man}"
+  if [ "$#" -lt 2 ]; then return 1; fi # should print usage
+  if [ "$num" != "" ]; then
+     sec="${num%%[a-zA-Z]*}"
+  else
+     sec='[168234571lnpo]'
+     num="$sec"
+  fi
+  for i in $(echo "$mp" | tr : ' '); do
+    if [ ! -d "$i" ]; then continue; fi
+    file="$i"/man"$sec"/"$page"."$num"*
+    set $file
+    file="$1"
+    if [ -f "$file" ]; then
+      zot=$(head -1 "$file")
+      cmd=${MANROFF:-"nroff -man - | col | cat -s"}
+      h=${zot##"'"'\"'}
+      if [ "$h" != "$zot" ]; then
+        while [ "$h" != "" ]; do
+          case "$h" in
+            *e) cmd="${MANEQN:-neqn} | $cmd";;
+            *r) cmd="refer | $cmd";;
+            *t) cmd="tbl | $cmd";;
+            *v) cmd="vgrind | $cmd";;
+            *) ;; # should print error
+          esac
+          h=${h%?}
+        done
+      fi
+      if [ "$printing" != "" ]; then
+        (cd "$i"; eval "$cmd") < "$file" | ${PAGER:-more}
+      else
+        (cd "$i"; eval "$cmd") < "$file" > /tmp/manpage-$$
+        ${PAGER:-more} /tmp/manpage-$$
+        rm -f /tmp/manpage-$$
+      fi
+      break
+    fi
+  done
+}
+
+function whatis_internal ()
+{
+  local j
+  for j in $(echo "$MANPATH" | tr : ' '); do
+    if [ -f "$j/whatis" ]; then
+      eval $2 -i -e "$1" $j/whatis
+    fi
+  done
+}
+
+function whatis ()
+{
+  local name=$(basename "$1")
+  whatis_internal "$name" "grep -w"
+}
+
+function apropos ()
+{
+  whatis_internal "$1" "fgrep"
+}
+
+# Note: "-" and "-t" together not supported.  This man could be
+# made a lot better, but it does everything I want.
+function man ()
+{
+  local PAGER printing mpath MANROFF num
+  mpath="${MANPATH:-/usr/man}"
+  while true; do
+    case "$1" in
+      -) PAGER=cat
+         printing= ;;
+      -t)
+         MANROFF=${TROFF:-"ptroff -man -t"}
+         PAGER="${TCAT:-lpr}"
+         printing=yes ;;
+      -M)
+         mpath="$2"
+         shift;;
+      *) break;;
+    esac
+    shift
+  done
+  local MANPATH="$mpath"
+  case "$1" in
+    -f | -k)
+      local g a
+      if [ "$1" = "-f" ]; then
+        g="grep -w"
+       a=$(basename "$2")
+      else
+       g=fgrep
+       a="$2"
+      fi
+      whatis_internal "$a" "$g"
+      ;;
+    [0-9npol] | [0-9][a-z]* | new | public | old | local)
+      if [ "$1" = "new" ]; then
+        num=n
+      elif [ "$1" = "public" ]; then
+        num=p
+      elif [ "$1" = "old" ]; then
+        num=o
+      elif [ "$1" = "local" ]; then
+        num=l
+      else
+       num="$1"
+      fi
+      shift
+      manpage "$num" "$1" "$printing"
+      ;;
+    *)
+      manpage "$num" "$1" "$printing"
+      ;;
+  esac
+}
diff --git a/examples/functions/notify.bash b/examples/functions/notify.bash
new file mode 100644 (file)
index 0000000..dafbac5
--- /dev/null
@@ -0,0 +1,58 @@
+trap _notify CHLD
+NOTIFY_ALL=false
+unset NOTIFY_LIST
+unalias false
+
+false()
+{
+       return 1
+}
+
+_notify ()
+{
+       local i j
+       local newlist=
+
+       if $NOTIFY_ALL
+       then
+               return          # let bash take care of this itself
+       elif [ -z "$NOTIFY_LIST" ]; then
+               return
+       else
+               set -- $NOTIFY_LIST
+               for i in "$@"
+               do
+                       j=$(jobs -n %$i)
+                       if [ -n "$j" ]; then
+                               echo "$j"
+                               jobs -n %$i >/dev/null
+                       else
+                               newlist="newlist $i"
+                       fi
+               done
+               NOTIFY_LIST="$newlist"
+       fi
+}
+
+notify ()
+{
+       local i j
+
+       if [ $# -eq 0 ]; then
+               NOTIFY_ALL=:
+               set -b
+               return
+       else
+               for i in "$@"
+               do
+                       # turn a valid job spec into a job number
+                       j=$(jobs $i)
+                       case "$j" in
+                       [*)     j=${j%%]*}
+                               j=${j#[}
+                               NOTIFY_LIST="$NOTIFY_LIST $j"
+                               ;;
+                       esac
+               done
+       fi
+}
diff --git a/examples/functions/shcat b/examples/functions/shcat
new file mode 100644 (file)
index 0000000..55a3096
--- /dev/null
@@ -0,0 +1,7 @@
+shcat()
+{
+       while read line
+       do
+               echo "$line"
+       done
+}
diff --git a/examples/functions/substr b/examples/functions/substr
new file mode 100644 (file)
index 0000000..c557677
--- /dev/null
@@ -0,0 +1,79 @@
+#
+# substr -- a function to emulate the ancient ksh builtin
+#
+
+#
+# -l == shortest from left
+# -L == longest from left
+# -r == shortest from right (the default)
+# -R == longest from right
+
+substr()
+{
+       local flag pat str
+       local usage="usage: substr -lLrR pat string or substr string pat"
+
+       case "$1" in
+       -l | -L | -r | -R)
+               flag="$1"
+               pat="$2"
+               shift 2
+               ;;
+       -*)
+               echo "substr: unknown option: $1"
+               echo "$usage"
+               return 1
+               ;;
+       *)
+               flag="-r"
+               pat="$2"
+               ;;
+       esac
+
+       if [ "$#" -eq 0 -o "$#" -gt 2 ] ; then
+               echo "substr: bad argument count"
+               return 2
+       fi
+
+       str="$1"
+
+       #
+       # We don't want -f, but we don't want to turn it back on if
+       # we didn't have it already
+       #
+       case "$-" in
+       "*f*")
+               ;;
+       *)
+               fng=1
+               set -f
+               ;;
+       esac
+
+       case "$flag" in
+       -l)
+               str="${str#$pat}"               # substr -l pat string
+               ;;
+       -L)
+               str="${str##$pat}"              # substr -L pat string
+               ;;
+       -r)
+               str="${str%$pat}"               # substr -r pat string
+               ;;
+       -R)
+               str="${str%%$pat}"              # substr -R pat string
+               ;;
+       *)
+               str="${str%$2}"                 # substr string pat
+               ;;
+       esac
+
+       echo "$str"
+
+       #
+       # If we had file name generation when we started, re-enable it
+       #
+       if [ "$fng" = "1" ] ; then
+               set +f
+       fi
+}
diff --git a/examples/functions/substr2 b/examples/functions/substr2
new file mode 100644 (file)
index 0000000..f5e7547
--- /dev/null
@@ -0,0 +1,81 @@
+#
+# substr -- a function to emulate the ancient ksh builtin
+#
+
+# -l == remove shortest from left
+# -L == remove longest from left
+# -r == remove shortest from right (the default)
+# -R == remove longest from right
+
+substr()
+{
+       local flag pat str
+       local usage="usage: substr -lLrR pat string or substr string pat"
+       local options="l:L:r:R:"
+
+       OPTIND=1
+       while getopts "$options" c
+       do
+               case "$c" in
+               l | L | r | R)
+                       flag="-$c"
+                       pat="$OPTARG"
+                       ;;
+               '?')
+                       echo "$usage"
+                       return 1
+                       ;;
+               esac
+       done
+
+       if [ "$OPTIND" -gt 1 ] ; then
+               shift $[ $OPTIND -1 ]
+       fi
+
+       if [ "$#" -eq 0 -o "$#" -gt 2 ] ; then
+               echo "substr: bad argument count"
+               return 2
+       fi
+
+       str="$1"
+
+        #
+        # We don't want -f, but we don't want to turn it back on if
+        # we didn't have it already
+        #
+        case "$-" in
+        "*f*")
+                ;;
+        *)
+                fng=1
+                set -f
+               ;;
+        esac
+
+       case "$flag" in
+       -l)
+               str="${str#$pat}"               # substr -l pat string
+               ;;
+       -L)
+               str="${str##$pat}"              # substr -L pat string
+               ;;
+       -r)
+               str="${str%$pat}"               # substr -r pat string
+               ;;
+       -R)
+               str="${str%%$pat}"              # substr -R pat string
+               ;;
+       *)
+               str="${str%$2}"                 # substr string pat
+               ;;
+       esac
+
+       echo "$str"
+
+        #
+        # If we had file name generation when we started, re-enable it
+        #
+        if [ "$fng" = "1" ] ; then
+                set +f
+        fi
+}
diff --git a/examples/functions/term b/examples/functions/term
new file mode 100644 (file)
index 0000000..fbe99f1
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# term -- a shell function to set the terminal type interactively or not.
+#
+
+term()
+{
+       local   t
+
+       if [ $# != 0 ] ; then
+               eval $(tset -sQ $1)
+       else                            # interactive
+               if [ -z "$TERM" ] ; then
+                       TERM="unknown"
+               fi
+
+               case "$TERM" in
+                       network|dialup|unknown|lat)
+                               TERM=unknown
+                               ;;
+                       *)
+                               eval $(tset -sQ)
+                               ;;
+               esac
+
+               while [ "$TERM" = "unknown" ] ; do
+                       echo -n "Terminal type: "
+                       read t
+                       if [ -n "$t" ] ; then
+                               eval $(tset -sQ $t)
+                       fi
+               done
+       fi
+}
+
+               
diff --git a/examples/functions/whatis b/examples/functions/whatis
new file mode 100644 (file)
index 0000000..56c5a58
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# whatis -- and implementation of the 10th Edition Unix sh builtin `whatis'
+#          command.
+#
+# usage: whatis arg [...]
+#
+# For each argument, whatis prints the associated value as a parameter,
+# builtin, function, alias, or executable file as appropriate.  In each
+# case, the value is printed in a form which would yield the same value
+# if typed as input to the shell itself.
+#
+
+whatis()
+{
+       local wusage='usage: whatis arg [arg...]'
+       local fail=0
+
+       if [ $# -eq 0 ] ; then
+               echo "$wusage"
+               return 1
+       fi
+
+       for arg
+       do
+               case $(builtin type -type $arg 2>/dev/null) in
+               "alias")
+                       builtin alias "$arg"
+                       ;;
+               "function")
+                       builtin type "$arg" | sed 1d
+                       ;;
+               "builtin")
+                       echo builtin "$arg"
+                       ;;
+               "file")
+                       builtin type -path "$arg"
+                       ;;
+               *)
+                       # OK, we could have a variable, or we could have nada
+                       if [ "$(eval echo \${$arg+set})" = "set" ] ; then
+                               # It is a variable, and it is set
+                               echo -n "$arg="
+                               eval echo '\"'\$$arg'\"'
+                       else
+                               echo whatis: $arg: not found
+                               fail=1
+                       fi
+                       ;;
+               esac
+       done
+       return $fail
+}
diff --git a/examples/functions/whence b/examples/functions/whence
new file mode 100644 (file)
index 0000000..70b2322
--- /dev/null
@@ -0,0 +1,59 @@
+#
+# An almost-ksh compatible `whence' command.  This is as hairy as it is 
+# because of the desire to exactly mimic ksh.
+# 
+# This depends somewhat on knowing the format of the output of the bash
+# `builtin type' command.
+#
+# Chet Ramey
+# chet@ins.CWRU.Edu
+#
+whence()
+{
+       local vflag= path=
+
+       if [ "$#" = "0" ] ; then
+               echo "whence: argument expected"
+               return 1
+       fi
+       case "$1" in
+               -v) vflag=1
+                   shift 1
+                   ;;
+               -*) echo "whence: bad option: $1"
+                   return 1
+                   ;;
+                *) ;;
+       esac
+
+       if [ "$#" = "0" ] ; then
+               echo "whence: bad argument count"
+               return 1
+       fi
+
+       for cmd
+       do
+               if [ "$vflag" ]  ; then
+                       echo $(builtin type $cmd | sed 1q)
+               else
+                       path=$(builtin type -path $cmd)
+                       if [ "$path" ] ; then
+                               echo $path
+                       else
+                               case "$cmd" in
+                                       /*) if [ -x "$cmd" ]; then
+                                               echo "$cmd"
+                                           fi
+                                           ;;
+                                        *) case "$(builtin type -type $cmd)" in
+                                               "") ;;
+                                                *) echo "$cmd"
+                                                   ;;
+                                           esac
+                                           ;;
+                               esac
+                       fi
+               fi
+       done
+       return 0
+}
diff --git a/examples/scripts/adventure.sh b/examples/scripts/adventure.sh
new file mode 100755 (executable)
index 0000000..a6d2eaa
--- /dev/null
@@ -0,0 +1,545 @@
+#!/bin/bash
+#      ash -- "Adventure shell"
+#      last edit:      86/04/21        D A Gwyn
+#      SCCS ID:        @(#)ash.sh      1.4
+
+OPATH=$PATH
+
+ask()
+{
+       echo -n "$@" '[y/n] '
+       read ans
+
+       case "$ans" in
+       y*|Y*)
+               return 0
+               ;;
+       *)
+               return 1
+               ;;
+       esac
+}
+       
+CAT=${PAGER:-more}
+
+ash_inst()
+{
+       cat <<- EOF
+
+                       Instructions for the Adventure shell
+
+       Welcome to the Adventure shell!  In this exploration of the UNIX file
+       system, I will act as your eyes and hands.  As you move around, I will
+       describe whatever is visible and will carry out your commands.  The
+       general form of a command is
+               Verb Object Extra_stuff.
+       Most commands pay no attention to the "Extra_stuff", and many do not
+       need an "Object".  A typical command is
+               get all
+       which picks up all files in the current "room" (directory).  You can
+       find out what you are carrying by typing the command
+               inventory
+       The command "help" results in a full description of all commands that I
+       understand.  To quit the Adventure shell, type
+               quit
+
+       There are UNIX monsters lurking in the background.  These are also
+       known as "commands with arguments".
+
+       Good luck!
+       EOF
+}
+
+ash_help()
+{
+echo "I understand the following commands (synonyms in parentheses):"
+echo ""
+
+echo "change OBJECT to NEW_NAME       changes the name of the object"
+echo "clone OBJECT as NEW_NAME        duplicates the object"
+echo "drop OBJECTS                    leaves the objects in the room"
+echo "enter (go) PASSAGE              takes the labeled passage"
+echo "examine OBJECTS                 describes the objects in detail"
+echo "feed OBJECT to MONSTER          stuffs the object into a UNIX monster"
+echo "get (take) OBJECTS              picks up the specified objects"
+echo "gripe (bug)                     report a problem with the Adventure shell"
+echo "help                            prints this summary"
+echo "inventory (i)                   tells what you are carrying"
+echo "kill (destroy) OBJECTS          destroys the objects"
+echo "look (l)                        describes the room, including hidden objects"
+echo "open (read) OBJECT              shows the contents of an object"
+echo "quit (exit)                     leaves the Adventure shell"
+echo "resurrect OBJECTS               attempts to restore dead objects"
+echo "steal OBJECT from MONSTER       obtains the object from a UNIX monster"
+echo "throw OBJECT at daemon          feeds the object to the printer daemon"
+echo "up                              takes the overhead passage"
+echo "wake MONSTER                    awakens a UNIX monster"
+echo "where (w)                       tells you where you are"
+echo "xyzzy                           moves you to your home"
+}
+       
+MAINT=chet@ins.cwru.edu
+
+PATH=/usr/ucb:/bin:/usr/bin:/usr/local/bin:.
+export PATH
+
+trap 'echo Ouch!' 2 3
+#trap '' 18                    # disable Berkeley job control
+
+ash_lk(){ echo " $1 " | fgrep " $2 " >&- 2>&-; }
+ash_pr(){ echo $* | tr ' ' '\012' | pr -5 -t -w75 -l$[ ( $# + 4 ) / 5 ]; }
+ash_rm(){ echo " $1 " | sed -e "s/ $2 / /" -e 's/^ //' -e 's/ $//'; }
+
+cd
+LIM=.limbo                     # $HOME/$LIM contains "destroyed" objects
+mkdir $LIM >&- 2>&-
+KNAP=.knapsack                 # $HOME/$KNAP contains objects being "carried"
+if [ ! -d $KNAP ]
+then   mkdir $KNAP >&- 2>&-
+       if [ $? = 0 ]
+       then    echo 'You found a discarded empty knapsack.'
+       else    echo 'You have no knapsack to carry things in.'
+               exit 1
+       fi
+else   echo 'One moment while I peek in your old knapsack...'
+fi
+
+kn=`echo \`ls -a $KNAP | sed -e '/^\.$/d' -e '/^\.\.$/d'\``
+
+if ask 'Welcome to the Adventure shell!  Do you need instructions?'
+then
+       ash_inst
+       echo -n 'Type a newline to continue: '
+       read
+fi
+
+wiz=false
+cha=false
+prev=$LIM
+while :
+do     room=`pwd`
+       if [ $room != $prev ]
+       then    if [ $room = $HOME ]
+               then    echo 'You are in your own home.'
+               else    echo "You have entered $room."
+               fi
+               exs=
+               obs=
+               hexs=
+               hobs=
+               f=false
+               for i in `ls -a`
+               do      case $i in
+                       .|..)   ;;
+                       .*)     if [ -f $i ]
+                               then    hobs="$hobs $i"
+                               elif [ -d $i ]
+                               then    hexs="$hexs $i"
+                               else    f=true
+                               fi
+                               ;;
+                       *)      if [ -f $i ]
+                               then    obs="$obs $i"
+                               elif [ -d $i ]
+                               then    exs="$exs $i"
+                               else    f=true
+                               fi
+                               ;;
+                       esac
+               done
+               if [ "$obs" ]
+               then    echo 'This room contains:'
+                       ash_pr $obs
+               else    echo 'The room looks empty.'
+               fi
+               if [ "$exs" ]
+               then    echo 'There are exits labeled:'
+                       ash_pr $exs
+                       echo 'as well as a passage overhead.'
+               else    echo 'There is a passage overhead.'
+               fi
+               if sh -c $f
+               then    echo 'There are shadowy figures in the corner.'
+               fi
+               prev=$room
+       fi
+
+       echo -n '-advsh> '                      # prompt
+       read verb obj x
+       if [ $? != 0 ]
+       then    verb=quit               # EOF
+       fi
+
+       case $verb in
+       change)         if [ "$obj" ]
+                       then    if ash_lk "$obs $hobs" "$obj"
+                               then    set -- $x
+                                       case "$1" in
+                                       to)     if [ "$2" ]
+                                               then    if [ -f $2 ]
+                                                       then    echo "You must destroy $2 first."
+                                                               set --
+                                                       fi
+                                                       if [ "$2" ]
+                                                       then    if mv $obj $2 >&- 2>&-
+                                                               then    echo "The $obj shimmers and turns into $2."
+                                                                       obs=`ash_rm "$2 $obs" "$obj"`
+                                                               else    echo "There is a cloud of smoke but the $obj is unchanged."
+                                                               fi
+                                                       fi
+                                               else    echo 'To what?'
+                                               fi
+                                               ;;
+                                       *)      echo "Change $obj to what?"
+                                               ;;
+                                       esac
+                               else    if ash_lk "$kn" "$obj"
+                                       then    echo 'You must drop it first.'
+                                       else    echo "I see no $obj here."
+                                       fi
+                               fi
+                       else    echo 'Change what?'
+                       fi
+                       ;;
+       clone)          if [ "$obj" ]
+                       then    if ash_lk "$obs $hobs" "$obj"
+                               then    if [ ! -r $obj ]
+                                       then    echo "The $obj does not wish to be cloned."
+                                       else    set -- $x
+                                               case "$1" in
+                                               as)     if [ "$2" ]
+                                                       then    if [ -f $2 ]
+                                                               then    echo "You must destroy $2 first."
+                                                               else    if cp $obj $2 >&- 2>&-
+                                                                       then    echo "Poof!  When the smoke clears, you see the new $2."
+                                                                               obs="$obs $2"
+                                                                       else    echo 'You hear a dull thud but no clone appears.'
+                                                                       fi
+                                                               fi
+                                                       else    echo 'As what?'
+                                                       fi
+                                                       ;;
+                                               *)      echo "Clone $obj as what?"
+                                                       ;;
+                                               esac
+                                       fi
+                               else    if ash_lk "$kn" "$obj"
+                                       then    echo 'You must drop it first.'
+                                       else    echo "I see no $obj here."
+                                       fi
+                               fi
+                       else    echo 'Clone what?'
+                       fi
+                       ;;
+       drop)           if [ "$obj" ]
+                       then    for it in $obj $x
+                               do      if ash_lk "$kn" "$it"
+                                       then    if [ -w $it ]
+                                               then    echo "You must destroy $it first."
+                                               else    if mv $HOME/$KNAP/$it $it >&- 2>&-
+                                                       then    echo "$it: dropped."
+                                                               kn=`ash_rm "$kn" "$it"`
+                                                               obs=`echo $it $obs`
+                                                       else    echo "The $it is caught in your knapsack."
+                                                       fi
+                                               fi
+                                       else    echo "You're not carrying the $it!"
+                                       fi
+                               done
+                       else    echo 'Drop what?'
+                       fi
+                       ;;
+       enter|go)       if [ "$obj" ]
+                       then    if [ $obj != up ]
+                               then    if ash_lk "$exs $hexs" "$obj"
+                                       then    if [ -x $obj ]
+                                               then    if cd $obj
+                                                       then    echo 'You squeeze through the passage.'
+                                                       else    echo "You can't go that direction."
+                                                       fi
+                                               else    echo 'An invisible force blocks your way.'
+                                               fi
+                                       else    echo 'I see no such passage.'
+                                       fi
+                               else    if cd ..
+                                       then    echo 'You struggle upwards.'
+                                       else    echo "You can't reach that high."
+                                       fi
+                               fi
+                       else    echo 'Which passage?'
+                       fi
+                       ;;
+       examine)        if [ "$obj" ]
+                       then    if [ $obj = all ]
+                               then    $obj=`echo $obs $exs`
+                                       x=
+                               fi
+                               for it in $obj $x
+                               do      if ash_lk "$obs $hobs $exs $hexs" "$it"
+                                       then    echo "Upon close inspection of the $it, you see:"
+                                               ls -ld $it 2>&-
+                                               if [ $? != 0 ]
+                                               then    echo "-- when you look directly at the $it, it vanishes."
+                                               fi
+                                       else    if ash_lk "$kn" "$it"
+                                               then    echo 'You must drop it first.'
+                                               else    echo "I see no $it here."
+                                               fi
+                                       fi
+                               done
+                       else    echo 'Examine what?'
+                       fi
+                       ;;
+       feed)           if [ "$obj" ]
+                       then    if ash_lk "$obs $hobs" "$obj"
+                               then    set -- $x
+                                       case "$1" in
+                                       to)     if [ "$2" ]
+                                               then    shift
+                                                       if PATH=$OPATH $* <$obj 2>&-
+                                                       then    echo "The $1 monster devours your $obj."
+                                                               if rm -f $obj >&- 2>&-
+                                                               then    obs=`ash_rm "$obs" "$obj"`
+                                                               else    echo 'But he spits it back up.'
+                                                               fi
+                                                       else    echo "The $1 monster holds his nose in disdain."
+                                                       fi
+                                               else    echo 'To what?'
+                                               fi
+                                               ;;
+                                       *)      echo "Feed $obj to what?"
+                                               ;;
+                                       esac
+                               else    if ash_lk "$kn" "$obj"
+                                       then    echo 'You must drop it first.'
+                                       else    echo "I see no $obj here."
+                                       fi
+                               fi
+                       else    echo 'Feed what?'
+                       fi
+                       ;;
+       get|take)       if [ "$obj" ]
+                       then    if [ $obj = all ]
+                               then    obj="$obs"
+                                       x=
+                               fi
+                               for it in $obj $x
+                               do      if ash_lk "$obs $hobs" "$it"
+                                       then    if ash_lk "$kn" "$it"
+                                               then    echo 'You already have one.'
+                                               else    if mv $it $HOME/$KNAP/$it >&- 2>&-
+                                                       then    echo "$it: taken."
+                                                               kn="$it $kn"
+                                                               obs=`ash_rm "$obs" "$it"`
+                                                       else    echo "The $it is too heavy."
+                                                       fi
+                                               fi
+                                       else    echo "I see no $it here."
+                                       fi
+                               done
+                       else    echo 'Get what?'
+                       fi
+                       ;;
+       gripe|bug)      echo 'Please describe the problem and your situation at the time it failed.\nEnd the bug report with a line containing just a Ctrl-D.'
+                       cat | mail $MAINT -s 'ash bug'
+                       echo 'Thank you!'
+                       ;;
+       help)           ash_help
+                       ;;
+       inventory|i)    if [ "$kn" ]
+                       then    echo 'Your knapsack contains:'
+                               ash_pr $kn
+                       else    echo 'You are poverty-stricken.'
+                       fi
+                       ;;
+       kill|destroy)   if [ "$obj" ]
+                       then    if [ $obj = all ]
+                               then    x=
+                                       if ask "Do you really want to attempt to $verb them all?"
+                                       then    obj=`echo $obs`
+                                       else    echo 'Chicken!'
+                                               obj=
+                                       fi
+                               fi
+                               for it in $obj $x
+                               do      if ash_lk "$obs $hobs" "$it"
+                                       then    if mv $it $HOME/$LIM <&- >&- 2>&-
+                                               then    if [ $verb = kill ]
+                                                       then    echo "The $it cannot defend himself; he dies."
+                                                       else    echo "You have destroyed the $it; it vanishes."
+                                                       fi
+                                                       obs=`ash_rm "$obs" "$it"`
+                                               else    if [ $verb = kill ]
+                                                       then    echo "Your feeble blows are no match for the $it."
+                                                       else    echo "The $it is indestructible."
+                                                       fi
+                                               fi
+                                       else    if ash_lk "$kn" "$it"
+                                               then    echo "You must drop the $it first."
+                                                       found=false
+                                               else    echo "I see no $it here."
+                                               fi
+                                       fi
+                               done
+                       else    echo 'Kill what?'
+                       fi
+                       ;;
+       look|l)         obs=`echo $obs $hobs`
+                       hobs=
+                       if [ "$obs" ]
+                       then    echo 'The room contains:'
+                               ash_pr $obs
+                       else    echo 'The room is empty.'
+                       fi
+                       exs=`echo $exs $hexs`
+                       hexs=
+                       if [ "$exs" ]
+                       then    echo 'There are exits plainly labeled:'
+                               ash_pr $exs
+                               echo 'and a passage directly overhead.'
+                       else    echo 'The only exit is directly overhead.'
+                       fi
+                       ;;
+       magic)          if [ "$obj" = mode ]
+                       then    if sh -c $cha
+                               then    echo 'You had your chance and you blew it.'
+                               else    if ask 'Are you a wizard?'
+                                       then    echo -n 'Prove it!  Say the magic word: '
+                                               read obj
+                                               if [ "$obj" = armadillo ]
+                                               then    echo 'Yes, master!!'
+                                                       wiz=true
+                                               else    echo "Homie says: I don't think so"
+                                                       cha=true
+                                               fi
+                                       else    echo "I didn't think so."
+                                       fi
+                               fi
+                       else    echo 'Nice try.'
+                       fi
+                       ;;
+       open|read)      if [ "$obj" ]
+                       then    if ash_lk "$obs $hobs" "$obj"
+                               then    if [ -r $obj ]
+                                       then    if [ -s $obj ]
+                                               then    echo "Opening the $obj reveals:"
+                                                       $CAT < $obj
+                                                       if [ $? != 0 ]
+                                                       then    echo '-- oops, you lost the contents!'
+                                                       fi
+                                               else    echo "There is nothing inside the $obj."
+                                               fi
+                                       else    echo "You do not have the proper tools to open the $obj."
+                                       fi
+                               else    if ash_lk "$kn" "$obj"
+                                       then    echo 'You must drop it first.'
+                                               found=false
+                                       else    echo "I see no $obj here."
+                                       fi
+                               fi
+                       else    echo 'Open what?'
+                       fi
+                       ;;
+       quit|exit)      if ask 'Do you really want to quit now?'
+                       then    if [ "$kn" ]
+                               then    echo 'The contents of your knapsack will still be there next time.'
+                               fi
+                               rm -rf $HOME/$LIM
+                               echo 'See you later!'
+                               exit 0
+                       fi
+                       ;;
+       resurrect)      if [ "$obj" ]
+                       then    for it in $obj $x
+                               do      if ash_lk "$obs $hobs" "$it"
+                                       then    echo "The $it is already alive and well."
+                                       else    if mv $HOME/$LIM/$it $it <&- >&- 2>&-
+                                               then    echo "The $it staggers to his feet."
+                                                       obs=`echo $it $obs`
+                                               else    echo "There are sparks but no $it appears."
+                                               fi
+                                       fi
+                               done
+                       else    echo 'Resurrect what?'
+                       fi
+                       ;;
+       steal)          if [ "$obj" ]
+                       then    if ash_lk "$obs $hobs" "$obj"
+                               then    echo 'There is already one here.'
+                               else    set -- $x
+                                       case "$1" in
+                                       from)   if [ "$2" ]
+                                               then    shift
+                                                       if PATH=$OPATH $* >$obj 2>&-
+                                                       then    echo "The $1 monster drops the $obj."
+                                                               obs=`echo $obj $obs`
+                                                       else    echo "The $1 monster runs away as you approach."
+                                                               rm -f $obj >&- 2>&-
+                                                       fi
+                                               else    echo 'From what?'
+                                               fi
+                                               ;;
+                                       *)      echo "Steal $obj from what?"
+                                               ;;
+                                       esac
+                               fi
+                       else    echo 'Steal what?'
+                       fi
+                       ;;
+       throw)          if [ "$obj" ]
+                       then    if ash_lk "$obs $hobs" "$obj"
+                               then    set -- $x
+                                       case "$1" in
+                                       at)     case "$2" in
+                                               daemon) if sh -c "lpr -r $obj"
+                                                       then    echo "The daemon catches the $obj, turns it into paper,\nand leaves it in the basket."
+                                                               obs=`ash_rm "$obs" "$obj"`
+                                                       else    echo "The daemon is nowhere to be found."
+                                                       fi
+                                                       ;;
+                                               *)      echo 'At what?'
+                                                       ;;
+                                               esac
+                                               ;;
+                                       *)      echo "Throw $obj at what?"
+                                               ;;
+                                       esac
+                               else    if ash_lk "$kn" "$obj"
+                                       then    echo 'It is in your knapsack.'
+                                               found=false
+                                       else    echo "I see no $obj here."
+                                       fi
+                               fi
+                       else    echo 'Throw what?'
+                       fi
+                       ;;
+       u|up)           if cd ..
+                       then    echo 'You pull yourself up a level.'
+                       else    echo "You can't reach that high."
+                       fi
+                       ;;
+       wake)           if [ "$obj" ]
+                       then    echo "You awaken the $obj monster:"
+                               PATH=$OPATH $obj $x
+                               echo 'The monster slithers back into the darkness.'
+                       else    echo 'Wake what?'
+                       fi
+                       ;;
+       w|where)        echo "You are in $room."
+                       ;;
+       xyzzy)          if cd
+                       then    echo 'A strange feeling comes over you.'
+                       else    echo 'Your spell fizzles out.'
+                       fi
+                       ;;
+       *)              if [ "$verb" ]
+                       then    if sh -c $wiz
+                               then    PATH=$OPATH $verb $obj $x
+                               else    echo "I don't know how to \"$verb\"."
+                                       echo 'Type "help" for assistance.'
+                               fi
+                       else    echo 'Say something!'
+                       fi
+                       ;;
+       esac
+done
diff --git a/examples/scripts/bcsh.sh b/examples/scripts/bcsh.sh
new file mode 100644 (file)
index 0000000..9d93b30
--- /dev/null
@@ -0,0 +1,1254 @@
+# 1-Feb-86 09:37:35-MST,30567;000000000001
+# Return-Path: <unix-sources-request@BRL.ARPA>
+# Received: from BRL-TGR.ARPA by SIMTEL20.ARPA with TCP; Sat 1 Feb 86 09:36:16-MST
+# Received: from usenet by TGR.BRL.ARPA id a002623; 1 Feb 86 9:33 EST
+# From: chris <chris@globetek.uucp>
+# Newsgroups: net.sources
+# Subject: Improved Bcsh (Bourne Shell Cshell-Emulator)
+# Message-ID: <219@globetek.UUCP>
+# Date: 30 Jan 86 17:34:26 GMT
+# To:       unix-sources@BRL-TGR.ARPA
+#
+# This is a new, improved version of my Bourne shell cshell-emulator.
+# The code has been cleaned up quite a bit, and a couple of new features
+# added (now supports 'noclobber' and 'iclobber' variables).  A bug with
+# 'eval' that caused "illegal I/O" error messages on vanilla V7 shells has
+# also been fixed.
+
+# I have posted the program in its entirety because a context diff of the
+# old and new versions was longer than the new version...
+
+# --Chris
+#      Bcsh -- A Simple Cshell-Like Command Pre-Processor For The Bourne Shell
+#
+#      "Copyright (c) Chris Robertson, December 1985"
+#
+#      This software may be used for any purpose provided the original
+#      copyright notice and this notice are affixed thereto.  No warranties of
+#      any kind whatsoever are provided with this software, and it is hereby
+#      understood that the author is not liable for any damagages arising
+#      from the use of this software.
+#
+#      Features Which the Cshell Does Not Have:
+#      ----------------------------------------
+#
+#      +  command history persists across bcsh sessions
+#      +  global last-command editing via 'g^string1^string2^' syntax
+#      +  edit any command via $EDITOR or $VISUAL editors
+#      +  history file name, .bcshrc file name, alias file name, and number
+#         of commands saved on termination can be set by environment variables
+#      +  prompt may evaluate commands, such as `pwd`, `date`, etc.
+#      +  the whole text of interactive 'for' and 'while' loops and 'if'
+#         statements goes into the history list and may be re-run or edited
+#      +  multiple copies of commands and requests to see command history
+#         are not added to the history list
+#      +  the history mechanism actually stores all commands entered in a
+#         current session, not just $history of them.  This means that you
+#         can increase $history on the fly and at once have a larger history.
+#
+#
+#      Synonyms:
+#      ---------
+#
+#      logout, exit, bye       write out history file and exit
+#      h, history              show current history list
+#      
+#      
+#      Aliases:
+#      --------
+#
+#      alias NAME CMND         create an alias called NAME to run CMND
+#      unalias NAME            remove the alias NAME
+#
+#      There are no 'current-session only' aliases -- all alias and unalias
+#      commands are permanent, and stored in the $aliasfile.
+#
+#      If an alias contains positional variables -- $1, $2, $*, etc. -- any
+#      arguments following the alias name are considered to be values for
+#      those variables, and the alias is turned into a command of the form
+#      'set - arguments;alias'.  Otherwise, a simple substitution is performed
+#      for the alias and the rest of the command preserved.  The cshell
+#      convention of using '\!:n' in an alias to get bits of the current
+#      command is mercifully abandoned.
+#
+#      Quotes are not necessary around the commands comprising an alias;
+#      in fact, any enclosing quotes are stripped when the alias is added
+#      to the file.
+#
+#      A couple of typical aliases might be:
+#
+#              goto    cd $1;pwd
+#              l       ls -F
+#
+#      Note that aliasing something to "commands;logout" will not work -- if
+#      you want something to happen routinely on logout put it in the file
+#      specified by $logoutfile, default = $HOME/.blogout.
+#
+#
+#      Command Substitutions:
+#      ----------------------
+#
+#      !!                      substitute last command from history list
+#      !!:N                    substitute Nth element of last command from
+#                              history list -- 0 = command name, 1 = 1st arg
+#      !!:$                    substitute last element of last command from
+#                              history list
+#      !!:*                    substitute all arguments to last command
+#                              from history list
+#      !NUMBER                 substitute command NUMBER from the history list
+#      !NUMBER:N               as above, but substitute Nth element, where
+#                              0 = command name, 1 = 1st arg, etc.
+#      !NUMBER:$               as above, but substitute last element
+#      !NUMBER:*               as above, but substitute all arguments
+#      !-NUMBER                substitute the command NUMBER lines from the
+#                              end of the history list; 1 = last command
+#      !-NUMBER:N              as above, but substitute Nth element, where
+#                              0 = command name, 1 = 1st arg, etc.
+#      !-NUMBER:$              as above, but substitute last element
+#      !-NUMBER:*              as above, but substitute all arguments
+#      !?STRING                substitute most-recent command from history list
+#                              containing STRING -- STRING must be enclosed in
+#                              braces if followed by any other characters
+#      !?STRING:N              as above, but substitute Nth element, where
+#                              0 = command name, 1 = 1st arg, etc.
+#      !?STRING:$              as above, but substitute last element   
+#      !?STRING:*              as above, but substitute all arguments
+#
+#
+#      Command Editing:
+#      ----------------
+#
+#      CMND~e                  edit CMND using $EDITOR, where CMND may be found
+#                              using a history substitution
+#      CMND~v                  edit CMND using $VISUAL, where CMND may be found
+#                              using a history substitution
+# "    ^string1^string2^       substitute string2 for string1 in last command"
+#                              command and run it
+# "    g^string1^string2^      globally substitute string2 for string1 in  "
+#                              last command and run it
+#      !NUMBER:s/string1/string2/
+#                              substitute string2 for string1 in
+#                              command NUMBER and run it
+#      !NUMBER:gs/string1/string2/
+#                              globally substitute string2 for string1 in
+#                              command NUMBER and run it
+#      !?STRING:s/string1/string2/
+#                              substitute string2 for string1 in last command
+#                              containing STRING and run it
+#      !?STRING:gs/string1/string2/
+#                              globally substitute string2 for string1 in last
+#                              command containing STRING and run it
+#      
+#      Any command which ends in the string ":p" is treated as a normal
+#      command until all substitutions have been completed.  The trailing
+#      ":p" is then stripped, and the command is simply echoed and added to
+#      the history list instead of being executed.
+#
+#      None of the other colon extensions of the cshell are supported.
+#
+#
+#      Shell Environment Variables:
+#      ----------------------------
+#
+#      EDITOR          editor used by ~e command, default = "ed"
+#      VISUAL          editor used by ~v command, default = "vi"
+#      MAIL            your system mailbox
+#      PAGER           paging program used by history command, default = "more"
+#      PS1             primary prompt
+#      PS2             secondary prompt
+#      history         number of commands in history list, default = 22
+#      histfile        file history list is saved in, default = $HOME/.bhistory
+#      savehist        number of commands remembered from last bcsh session
+#      aliasfile       file of aliased commands, default = $HOME/.baliases
+#      logoutfile      file of commands to be executed before termination
+#      inc_cmdno       yes/no -- keep track of command numbers or not
+#      noclobber       if set, existing files are not overwritten by '>'
+#      iclobber        if both noclobber and iclobber are set, the user is
+#                      prompted for confirmation before existing files are
+#                      overwritten by '>'
+#
+#      Note:   if you are setting either noclobber or iclobber mid-session,
+#              set them to 'yes'
+#
+#
+#      Regular Shell Variables:
+#      ------------------------
+#
+#      Shell variables may be set via Bourne or cshell syntax, e.g., both
+#      "set foo=bar" and "foo=bar" set a variable called "foo" with the value
+#      "bar".  However, all variables are automatically set as environment
+#      variables, so there is no need to export them.  Conversely, there
+#      are NO local variables.  Sorry, folks.
+#
+#      A cshell-style "setenv" command is turned into a regular "set" command.
+#
+#
+#      The Prompt:
+#      ----------
+#
+#      You may, if you wish, have a command executed in your prompt.  If
+#      the variable PS1 contains a dollar sign or a backquote, it is
+#      evaluated and the result used as the prompt, provided the evaluation
+#      did not produce a "not found" error message.  The two special cases
+#      of PS1 consisting solely of "$" or "$ " are handled correctly.  For
+#      example, to have the prompt contain the current directory followed
+#      by a space, enter:
+#
+#              PS1=\'echo "`pwd` "\'
+#
+#      You need the backslashed single quotes to prevent the command being
+#      evaluated by the variable-setting mechanism and the shell before it
+#      is assigned to PS1.
+#
+#      To include the command number in your prompt, enter the command:
+#
+#              PS1=\'echo "$cmdno "\'
+#
+#
+#      Shell Control-Flow Syntax:
+#      --------------------------
+#
+#      'While', 'for', 'case', and 'if' commands entered in Bourne shell
+#      syntax are executed as normal.
+#
+#      A valiant attempt is made to convert 'foreach' loops into 'for' loops,
+#      cshell-syntax 'while' loops into Bourne shell syntax, and 'switch'
+#      statements into 'case' statements.  I cannot guarantee to always get it
+#      right.  If you forget the 'do' in a 'while' or 'for' loop, or finish
+#      them with 'end' instead of 'done', this will be corrected.
+#
+#      Note that cshell-to-Bourne control flow conversions do not take place
+#      if control is nested -- e.g., a 'foreach' inside a 'while' will fail.
+#
+#      The simple-case cshell "if (condition) command" is turned into Bourne
+#      syntax.  Other 'if' statements are left alone apart from making the
+#      'then' a separate statement, because constructing a valid interactive
+#      cshell 'if' statement is essentially an exercise in frustration anyway.
+#      The cshell and Bourne shell have sufficiently different ideas about
+#      conditions that if is probably best to resign yourself to learning
+#      the Bourne shell conventions.
+#
+#      Note that since most of the testing built-ins of the cshell are
+#      not available in the Bourne shell, a complex condition in a 'while'
+#      loop or an 'if' statement will probably fail.
+#      
+#
+#      Bugs, Caveats, etc.:
+#      --------------------
+#
+#      This is not a super-speedy program.  Be patient, especially on startup.
+#
+#      To the best of my knowledge this program should work on ANY Bourne
+#      shell -- note that if your shell does not understand 'echo -n' you
+#      will have to re-set the values of '$n' and '$c'.
+#
+#      This program may run out of stack space on a 16-bit machine where
+#      /bin/sh is not split-space.
+#
+#      Mail checking is done every 10 commands if $MAIL is set in your
+#      environment.  For anything fancier, you will have to hack the code.
+#
+#      Because commands are stuffed in a file before sh is invoked on them,
+#      error messages from failed commands are ugly.
+#
+#      Failed history substitutions either give nothing at all, or a
+#      "not found" style of error message.
+#
+#      A command history is kept whether you want it or not.  This may be
+#      perceived as a bug or a feature, depending on which side of bed you
+#      got out on.
+#
+#      If you want a real backslash in a command, you will have to type two
+#      of them  because the shell swallows the first backslash in the initial
+#      command pickup.  This means that to include a non-history '!' in a
+#      command you need '\\!' -- a real wart, especially for net mail,
+#      but unavoidable.
+#
+#      Commands containing an '@' will break all sorts of things.
+#
+#      Very complex history substitutions may fail.
+#
+#      File names containing numbers may break numeric history sustitutions.
+#
+#      Commands containing bizzare sequences of characters may conflict
+#      with internal kludges.
+#
+#      Aliasing something to "commands;logout" will not work -- if you
+#      want something to happen routinely on logout, put it in the file
+#      specified by $logoutfile, default = $HOME/.blogout.
+#
+#      Please send all bug reports to ihnp4!utzoo!globetek!chris.
+#      Flames will be posted to net.general with 'Reply-to' set to your
+# '    path...  :-)                                                    '
+#
+#
+#
+#              ************* VERY IMPORTANT NOTICE *************
+#
+# If your shell supports # comments, then REPLACE all the colon 'comments'
+# with # comments.  If it does not, then REMOVE all the 'comment' lines from the
+# working copy of the file, as it will run MUCH faster -- the shell evaluates
+# lines starting with a colon but does not actually execute them, so you will
+# save the read-and-evaluate time by removing them.
+
+case "`echo -n foo`" in
+       -n*)
+               n=
+               c="\c"
+               ;;
+       foo)
+               n=-n
+               c=
+               ;;
+       *)
+               echo "Your 'echo' command is broken."
+               exit 1
+               ;;
+esac
+history=${history-22}
+savehist=${savehist-22}
+histfile=${histfile-$HOME/.bhistory}
+logoutfile=${logoutfile-$HOME/.blogout}
+EDITOR=${EDITOR-ed}
+VISUAL=${VISUAL-vi}
+PAGER=${PAGER-more}
+
+aliasfile=${aliasfile-$HOME/.baliases}
+
+# the alias file may contain 1 blank line, so a test -s will not work
+
+case "`cat $aliasfile 2> /dev/null`" in
+       "")
+               doalias=no
+               ;;
+       *)
+               doalias=yes
+               ;;
+esac
+
+if test -s "${sourcefile-$HOME/.bcshrc}"
+       then
+       . ${sourcefile-$HOME/.bcshrc}
+fi
+
+if test -s "$histfile"
+       then
+       cmdno="`set - \`wc -l $histfile\`;echo $1`"
+       cmdno="`expr \"$cmdno\" + 1`"
+       lastcmd="`tail -1 $histfile`"
+       copy=false
+       ohist=$histfile
+       while test ! -w "$histfile"
+               do
+               echo "Cannot write to history file '$histfile'."
+               echo $n "Please enter a new history filename: $c"
+               read histfile
+               copy=true
+       done
+       if $copy
+               then
+               cp $ohist $histfile
+       fi
+else
+       cat /dev/null > $histfile
+       cmdno=1
+       lastcmd=
+fi
+
+# keep track of command number as the default
+
+inc_cmdno=${inc_cmdo-yes}
+
+# default prompts -- PS1 and PS2 may be SET but EMPTY, so '${PS1-% }' syntax
+# is not used here
+
+case "$PS1" in
+       "")                                     
+               PS1="% "
+               ;;                              
+esac
+case "$PS2" in
+       "")                                     
+               PS2="> "
+               ;;                              
+esac
+
+export histfile savehist history aliasfile EDITOR VISUAL PAGER cmdno PS1 PS2
+
+case "$MAIL" in
+       "")
+               ;;
+       *)
+               if [ -f $MAIL ]; then
+                       mailsize=`set - \`wc -c $MAIL\`;echo $1`
+               else
+                       mailsize=0
+               fi
+               ;;
+esac
+
+trap ':' 2
+trap exit 3
+trap "tail -$savehist $histfile>/tmp/hist$$;uniq /tmp/hist$$ > $histfile;\
+rm -f /tmp/*$$;exit 0" 15
+
+getcmd=yes
+mailcheck=
+exclaim=
+echoit=
+mailprompt=
+
+while :
+do
+
+       run=yes
+       case "$mailprompt" in
+               "")
+                       ;;
+               *)
+                       echo "$mailprompt"
+                       ;;
+       esac
+       case "$getcmd" in
+       yes)
+               : guess if the prompt should be evaluated or not
+               case "$PS1" in
+               \$|\$\ )
+                       echo $n "$PS1$c"
+                               ;;
+               *\`*|*\$*)
+                       tmp="`(eval $PS1) 2>&1`"
+                       case "$tmp" in
+                       *not\ found)                    
+                               echo $n "$PS1$c"
+                               ;;                      
+                       *)                              
+                               echo $n "$tmp$c"
+                               ;;                      
+                       esac
+                       ;;
+               *)
+                       echo $n "$PS1$c"
+                       ;;
+               esac
+
+               read cmd || cmd="exit"
+               ;;
+       *)      ;;
+       esac
+
+       case "$MAIL" in
+       "")
+               ;;
+       *)
+               : check for mail every 10 commands
+               case "$mailcheck" in
+               1111111111)
+                       mailcheck=
+                       if [ -f $MAIL ]; then
+                               newsize="`set - \`wc -c $MAIL\`;echo $1`"
+                       else
+                               newsize=0
+                       fi
+                       if test "$newsize" -gt "$mailsize"; then
+                               mailprompt="You have new mail"
+                       else
+                               mailprompt=
+                       fi
+                       mailsize=$newsize
+                       ;;
+               *)
+                       mailcheck=1$mailcheck
+                       ;;
+               esac
+               ;;
+       esac
+       hist=no
+
+       case "$cmd" in
+       "")
+               continue
+               ;;
+       sh)
+               sh
+               run=no
+               ;;
+       !!)
+               cmd=$lastcmd
+               echoit=yes
+               getcmd=no
+               continue
+               ;;
+       *:p)
+               cmd="`expr \"$cmd\" : '\(.*\):p'` +~+p"
+               getcmd=no
+               continue
+               ;;
+       foreach[\ \     ]*)
+               while test "$line" != "end"; do
+                       echo $n "$PS2$c"
+                       read line
+                       cmd="${cmd};$line"
+               done
+               echo "$cmd" > /tmp/bcsh$$
+               ed - /tmp/bcsh$$ << ++++
+               s/end/done/
+               s/foreach[      ]\(.*\)(/for \1 in /
+               s/)//
+               s/;/;do /
+               w
+++++
+               ;;
+       for[\ \ ]*|while[\ \    ]*)
+               # try to catch the most common cshell-to-Bourne-shell
+               # mistakes
+
+               echo $n "$PS2$c"
+               read line
+               case "$line" in
+               *do)
+                       line="do :"
+                       ;;
+               *do*)
+                       ;;
+               *)
+                       line="do $line"
+                       ;;
+               esac
+
+               cmd="${cmd};$line"
+               while test "$line" != "done" -a "$line" != "end"
+               do
+                       echo $n "$PS2$c"
+                       read line
+                       case "$line" in
+                       end)
+                               line=done
+                               ;;
+                       esac
+                       cmd="${cmd};$line"
+               done
+               echo "$cmd" > /tmp/bcsh$$
+               ;;
+       if[\ \  ]*)
+               while test "$line" != "fi" -a "$line" != "endif"
+               do
+                       echo $n "$PS2$c"
+                       read line
+                       case "$line" in
+                       *[a-z]*then)
+                               line="`expr \"$line\" : '\(.*\)then'`;then"
+                               ;;
+                       endif)
+                               line=fi
+                               ;;
+                       esac
+                       cmd="${cmd};$line"
+               done
+               echo "$cmd" > /tmp/bcsh$$
+               case "`grep then /tmp/bcsh$$`" in
+               "")
+                       # fix 'if foo bar' cases
+
+                       ed - /tmp/bcsh$$ << ++++
+                       s/)/);then/
+                       s/.*/;fi/
+                       w
+++++
+                       ;;
+               esac
+               ;;
+       case[\ \        ]*)
+               while test "$line" != "esac"
+               do
+                       echo $n "$PS2$c"
+                       read line
+                       cmd="${cmd}@$line"
+               done
+               cmd="`echo \"$cmd\" | tr '@' ' '`"
+               echo "$cmd" > /tmp/bcsh$$
+               ;;
+       switch[\ \      ]*)
+               while test "$line" != "endsw"
+               do
+                       echo $n "$PS2$c"
+                       read line
+                       cmd="${cmd}@$line"
+               done
+               echo "$cmd" > /tmp/bcsh$$
+               ed - /tmp/bcsh$$ << '++++'
+               1,$s/@/\
+/g
+               g/switch.*(/s//case "/
+               s/)/" in/
+               1,$s/case[       ]\(.*\):$/;;\
+       \1)/
+               2d
+               1,$s/endsw/;;\
+esac/
+               g/breaksw/s///
+               1,$s/default.*/;;\
+       *)/
+               w
+++++
+               cmd="`cat /tmp/bcsh$$`"
+               ;;
+       *!*)
+               hist=yes
+               ;;
+       esac
+
+       case "$hist" in
+       yes)
+               # deal with genuine exclamation marks, go back and parse again
+
+               case "$cmd" in
+               *\>![\ \        ]*|*\\!*)
+                       cmd="`echo \"$cmd\" | sed -e 's@\\!@REALEXCLAMATIONMARK@g'`"
+                       exclaim=yes
+                       getcmd=no
+                       continue
+                       ;;
+               esac
+
+               # break command into elements, parse each one
+
+               tmp=
+               for i in $cmd
+               do
+                       # find element with !, peel off stuff up to !
+
+                       case "$i" in
+                       !)
+                               # most likely a typo for !!, so fix it
+                               front=
+                               $i=!!
+                               ;;
+                       !!*)
+                               front=
+                               i="`expr \"$i\" : '.*\(!!.*\)'`"
+                               ;;
+                       *!!*)
+                               front="`expr \"$i\" : '\(.*\)!!.*'`"
+                               i="`expr \"$i\" : '.*\(!!.*\)'`"
+                               ;;
+                       !*)
+                               front=
+                               i="`expr \"$i\" : '.*!\(.*\)'`"
+                               ;;
+                       *)
+                               tmp="$tmp$i "
+                               continue
+                               ;;
+                       esac
+                       case "$i" in
+                       !!*)
+                               # want last command
+
+                               rest="`expr \"$i\" : '!!\(.*\)'`"
+                               i=$lastcmd
+                               ;;
+                       -*)
+                               # we want to search back through the history list
+
+                               case "$i" in
+                               -)
+                                       rest="`expr \"$i\" : '-\(.*\)'`"
+                                       i=$lastcmd
+                                       ;;
+                               -[0-9]*)
+                                       wanted="`expr \"$i\" : '-\([0-9][0-9]*\).*'`"
+                                       rest="`expr \"$i\" : '-[0-9][0-9]*\(.*\)'`"
+                                       i="`tail -$wanted $histfile | sed -e "1q"`"
+                                       ;;
+                               esac
+                               ;;
+                       [0-9]*)
+                               # find which number command is wanted
+
+                               wanted="`expr \"$i\" : '\([0-9][0-9]*\).*'`"
+                               rest="`expr \"$i\" : '[0-9][0-9]*\(.*\)'`"
+                               i="`grep -n . $histfile | grep \"^$wanted\"`"
+                               i="`expr \"$i\" : \"${wanted}.\(.*\)\"`"
+                               ;;
+                       \?*)
+
+                               # find which 'command-contains' match is wanted
+
+                               case "$i" in
+                               \?{*}*)
+                                       wanted="`expr \"$i\" : '?{\(.*\)}.*'`"
+                                       rest="`expr \"$i\" : '?.*}\(.*\)'`"
+                                       ;;
+                               \?*:*)
+                                       wanted="`expr \"$i\" : '?\(.*\):.*'`"
+                                       rest="`expr \"$i\" : '?.*\(:.*\)'`"
+                                       ;;
+                               \?*)
+                                       wanted="`expr \"$i\" : '?\(.*\)'`"
+                                       rest=
+                                       ;;
+                               esac
+                               i="`grep \"$wanted\" $histfile | tail -1`"
+                               ;;
+                       *)
+                               # find which 'start-of-command' match is wanted
+
+                               case "$i" in
+                               {*}*)
+                                       wanted="`expr \"$i\" : '{\(.*\)}.*'`"
+                                       rest="`expr \"$i\" : '.*}\(.*\)'`"
+                                       ;;
+                               *:*)
+                                       wanted="`expr \"$i\" : '\(.*\):.*'`"
+                                       rest="`expr \"$i\" : '.*\(:.*\)'`"
+                                       ;;
+                               *)
+                                       wanted="$i"
+                                       rest=
+                                       ;;
+                               esac
+                               i="`grep \"^$wanted\" $histfile | tail -1`"
+                               ;;
+                       esac
+
+                       # see if we actually found anything to substitute
+
+                       case "$i" in
+                       "")
+                               badsub="Event not found"
+                               break
+                               ;;
+                       *)
+                               badsub=no
+                               ;;
+                       esac
+
+                       case "$rest" in
+                       "")
+                               tmp="$front$tmp$i "
+                               continue
+                               ;;
+                       :[0-9]*)
+                               # find which element of $i is wanted
+
+                               number="`expr \"$rest\" : ':\([0-9][0-9]*\).*'`"
+                               rest="`expr \"$rest\" : ':[0-9][0-9]*\(.*\)'`"
+
+                               # count through $i till we get to the
+                               # right element
+
+                               counter=0
+                               for element in $i
+                               do
+                                       case "$counter" in
+                                       $number)
+                                               break
+                                               ;;
+                                       *)
+                                               counter="`expr \"$counter\" + 1`"
+                                               # counter=$[ $counter + 1 ]
+                                               ;;
+                                       esac
+                               done
+                               case "$counter" in
+                               $number)
+                                       badsub=no
+                                       ;;
+                               *)
+                                       badsub="Bad command element"
+                                       break
+                                       ;;
+                               esac
+                               tmp="$tmp$front$element$rest "
+                               continue
+                               ;;
+                       :\$*)
+                               # spin through $i till we hit the last element
+
+                               rest="`expr \"$rest\" : ':\$\(.*\)'`"
+                               for element in $i
+                               do
+                                       :
+                               done
+                               tmp="$tmp$front$element$rest "
+                               continue
+                               ;;
+                       :\**)
+                               # we want all elements except the command itself
+
+                               rest="`expr \"$rest\" : ':\*\(.*\)'`"
+                               save=$i
+                               set - $i
+                               shift
+                               case "$*" in
+                               "")
+                                       badsub="No arguments to command '$save'"
+                                       break
+                                       ;;
+                               *)
+                                       badsub=no
+                                       ;;
+                               esac
+                               tmp="$tmp$front$*$rest "
+                               continue
+                               ;;
+                       :s*|:gs*)
+                               # we are doing a substitution
+                               # put / on end if needed
+
+                               case "$rest" in
+                               :s/*/*/*|:gs/*/*/*)
+                                       ;;
+                               :s/*/*|:gs/*/*)
+                                       rest="${rest}/"
+                                       ;;
+                               esac
+
+                               # find what substitution is wanted
+
+                               first="`expr \"$rest\" : ':*s\/\(.*\)\/.*\/.*'`"
+                               second="`expr \"$i\" : ':*s/.*/\(.*\)/.*'`"
+
+                               # see if it is a global substitution
+
+                               case "$rest" in
+                               :gs*)
+                                       global=g
+                                       ;;
+                               :s*)
+                                       global=
+                                       ;;
+                               esac
+                               rest="`expr \"$rest\" : '.*/.*/.*/\(.*\)'`"
+                               i="`echo \"$i\" | sed -e \"s@$first@$second@$global\"`"
+
+                               # see if subsitution worked
+
+                               case "$i" in
+                               "")
+                                       badsub="Substiution failed"
+                                       break
+                                       ;;
+                               *)
+                                       badsub=no
+                                       ;;
+                               esac
+                               tmp="$tmp$front$i$rest "
+                               continue
+                               ;;
+                       *)
+                               tmp="$tmp$front$i$rest "
+                               ;;
+                       esac
+               done
+               case "$badsub" in
+               no)
+                       ;;
+               *)
+                       echo "$badsub"
+                       badsub=no
+                       continue
+                       ;;
+               esac
+               cmd="$tmp"
+               echoit=yes
+               getcmd=no
+               continue
+               ;;
+       *)
+               run=yes
+               ;;
+       esac
+
+       case "$cmd" in
+       *\^*\^*\^*)
+               # see if the substitution is global
+               case "$cmd" in
+               g*)
+                       global=g
+                       ;;
+               *)
+                       global=
+                       ;;
+               esac
+
+               # put a '^' on the end if necessary
+               case "$cmd" in
+               *\^)
+                       ;;
+               *)
+                       cmd="${cmd}^"
+                       ;;
+               esac
+
+               # find what substitution is wanted
+
+               first="`expr \"$cmd\" : '*\^\(.*\)\^.*\^.*'`"
+               second="`expr \"$cmd\" : '*\^.*\^\(.*\)\^.*'`"
+               rest="`expr \"$cmd\" : '*\^.*\^.*\^\(.*\)'`"
+               cmd="`echo \"$lastcmd\" | sed -e \"s@$first@$second@$global\"`$rest"
+
+               # see if the substitution worked
+
+               case "$cmd" in
+               "")
+                       echo "Substitution failed"
+                       continue
+                       ;;
+               esac
+               echoit=yes
+               getcmd=no
+               continue
+               ;;
+       *~e)
+               echo "$cmd" | sed -e "s@~e@@" > /tmp/bcsh$$
+               $EDITOR /tmp/bcsh$$
+               cmd="`cat /tmp/bcsh$$`"
+               getcmd=no
+               continue
+               ;;
+       *~v)
+               echo "$cmd" | sed -e "s@~v@@" > /tmp/bcsh$$
+               echo "$lastcmd" > /tmp/bcsh$$
+               $VISUAL /tmp/bcsh$$
+               cmd="`cat /tmp/bcsh$$`"
+               getcmd=no
+               continue
+               ;;
+       exec[\ \        ]*)
+               tail -$savehist $histfile>/tmp/hist$$
+               uniq /tmp/hist$$ > $histfile
+               rm -f /tmp/*$$
+               echo $cmd > /tmp/cmd$$
+               . /tmp/cmd$$
+               ;;
+       login[\ \       ]*|newgrp[\ \   ]*)
+               tail -$savehist $histfile>/tmp/hist$$
+               uniq /tmp/hist$$ > $histfile
+               rm -f /tmp/*$$
+               echo $cmd > /tmp/cmd$$
+               . /tmp/cmd$$
+               ;;
+       logout|exit|bye)
+               if test -s "$logoutfile"
+                       then
+                       # sh $logoutfile
+                       $SHELL $logoutfile
+               fi
+               tail -$savehist $histfile > /tmp/hist$$
+               uniq /tmp/hist$$ > $histfile
+               rm -f /tmp/*$$
+               exit 0
+               ;;
+       h|history)
+               grep -n . $histfile | tail -$history | sed -e 's@:@     @' | $PAGER
+               continue
+               ;;
+       h[\ \   ]\|*|h[\ \      ]\>*|h\|*|h\>*)
+               cmd="`echo \"$cmd\" | sed -e \"s@h@grep -n . $histfile | tail -$history | sed -e 's@:@  @'@\"`"
+               getcmd=no
+               continue
+               ;;
+       history[\ \     ]*\|*|history[\ \       ]*\>*)
+               cmd="`echo \"$cmd\" | sed -e \"s@history@grep -n . $histfile | tail -$history | sed -e 's@:@ @'@\"`"
+               getcmd=no
+               continue
+               ;;
+       source[\ \      ]*)
+               set - $cmd
+               shift
+               echo . $*  > /tmp/cmd$$
+               . /tmp/cmd$$
+               run=no
+               ;;
+       wait)
+               wait
+               run=no
+               ;;
+       .[\ \   ]*)
+               echo $cmd > /tmp/cmd$$
+               . /tmp/cmd$$
+               run=no
+               ;;
+       cd|cd[\ \       ]*)
+               # check if it will work first, or else this shell will terminate
+               # if the cd dies.  If you have a built-in test, you might want
+               # to replace the try-it-and-see below with a couple of tests,
+               # but it is probably just as fast like this.
+
+               echo $cmd > /tmp/cmd$$
+               if ($SHELL /tmp/cmd$$) ; then
+                       . /tmp/cmd$$
+               fi
+               run=no
+               ;;
+       awk[\ \ ]*|dd[\ \       ]*|cc[\ \       ]*|make[\ \     ]*)
+               # these are the only commands I can think of whose syntax
+               # includes an equals sign.  Add others as you find them.
+
+               echo "$cmd" > /tmp/bcsh$$
+               ;;
+       setenv*|*=*)
+               # handle setting shell variables, turning cshell syntax to Bourne
+               # syntax -- note all variables must be exported or they will not
+               # be usable in other commands
+
+               echo "$cmd" > /tmp/cmd$$
+               ed - /tmp/cmd$$ << ++++
+               g/^setenv[      ]/s/[   ]/@/
+               g/^setenv@/s/[  ]/=/
+               g/^setenv@/s///
+               g/^set/s///
+               .t.
+               \$s/=.*//
+               s/^/export /
+               w
+++++
+               . /tmp/cmd$$
+               rm -f /tmp/cmd$$
+               run=no
+               ;;
+       unset[\ \       ]*|umask[\ \    ]*|export[\ \   ]*|set[\ \      ]*)
+               # handle commands which twiddle current environment
+
+               $cmd
+               run=no
+               ;;
+       alias|alias[\ \ ])
+               if [ -f $aliasfile ]; then
+                       $PAGER $aliasfile
+               fi
+               lastcmd=$cmd
+               run=no
+               continue
+               ;;
+       alias[\ \       ]*)
+               case "$cmd" in
+               alias[\ \       ]\|*|alias[\ \  ]\>*)
+                       cmd="`echo \"$cmd\" | sed -e \"s@alias@cat $aliasfile@\"`"
+                       getcmd=no
+                       continue
+                       ;;
+               alias[\ \       ]*[\ \  ]*)
+                       ;;
+               *)
+                       echo "Syntax: alias name command"
+                       cmd=
+                       continue
+                       ;;
+               esac
+               set - $cmd
+               shift
+               cmd="$*"
+
+               # make sure there is always 1 blank line in file so
+               # unaliasing will always work -- ed normally refuses
+               # to write an empty file
+               echo "" >> $aliasfile
+               cat << ++++ >> $aliasfile
+$cmd
+++++
+
+#              ed - $aliasfile << '++++'
+#              g/alias[        ]/s///
+#              g/^['"]\(.*\)['"]$/s//\1/
+#              g/^/s//alias    /
+#              w
+#++++
+
+               sort -u -o $aliasfile $aliasfile
+               doalias=yes
+               cmd="alias $cmd"
+               run=no
+               ;;
+       unalias[\ \     ]*)
+               set - $cmd
+               case "$#" in
+               2)
+                       cmd=$2
+                       ;;
+               *)
+                       echo "Syntax: unalias alias_name"
+                       continue
+                       ;;
+               esac
+               ed - $aliasfile << ++++
+               /^$cmd[         ]/d
+               w
+++++
+               case "`set - \`wc -l $aliasfile\`;echo $1`" in
+               1)
+                       # just removed last alias
+                       doalias=no
+                       ;;
+               esac
+               run=no
+               ;;
+       *)
+               case "$doalias" in
+               yes)
+                       set - $cmd
+                       tmp="`grep \"^$1 \" $aliasfile`"
+                       case "$tmp" in
+                       $1[\ \  ]*)
+                               shift
+                               cmd=$*
+                               set - $tmp
+                               shift
+                               tmp=$*
+                               case "$tmp" in
+                               *\$*)
+                                       # uses positional variables
+
+                                       cmd="set - $cmd ; $tmp"
+                                       getcmd=no
+                                       continue
+                                       ;;
+                               *)
+                                       cmd="$tmp $cmd"
+                                       getcmd=no
+                                       continue
+                                       ;;
+                               esac
+                               ;;
+                       *)
+                               echo "$cmd" > /tmp/bcsh$$
+                               ;;
+                       esac
+                       ;;
+               no)
+                       echo "$cmd" > /tmp/bcsh$$
+                       ;;
+               esac
+               ;;
+       esac
+
+       case "$cmd" in
+       *+~+p)
+               cmd="`expr \"$cmd\" : '\(.*\)+~+p'`"
+               echoit=yes
+               run=no
+               ;;
+       esac
+
+       case "$cmd" in
+       "")
+               continue
+               ;;
+       *)
+               case "$exclaim" in
+               yes)
+                       cmd="`echo \"$cmd\" | sed -e 's@REALEXCLAMATIONMARK@!@g'`"
+                       echo "$cmd" > /tmp/bcsh$$
+                       ;;
+               esac
+               case "$echoit" in
+               yes)
+                       echo $cmd
+                       ;;
+               esac
+               case "$run" in
+               yes)
+                       case "${noclobber+yes}" in
+                       yes)
+                               case "$cmd" in
+                               *\>![\ \        ]*)
+                                       ed - /tmp/bcsh$$ << ++++
+                                       g/>!/s//>/
+                                       w
+++++
+                                       ;;
+                               *\>\>*)
+                                       ;;
+                               *\>*)
+                                       outfile="`expr \"$cmd\" : '.*>\(.*\)'`"
+                                       case "$outfile" in
+                                       \&*)
+                                               ;;
+                                       *)
+                                               set - $outfile
+                                               outfile="$1"
+                                               if test -s "$outfile"
+                                               then
+                                                       case "${iclobber+yes}" in
+                                                       yes)
+                                                               echo $n "Overwrite ${outfile}? $c"
+                                                               read answer
+                                                               case "$answer" in
+                                                               y*)
+                                                                       ;;
+                                                               *)
+                                                                       echo ':' > /tmp/bcsh$$
+                                                                       ;;
+                                                               esac
+                                                               ;;
+                                                       *)
+                                                               echo "${outfile}: file exists"
+                                                               echo ':' > /tmp/bcsh$$
+                                                               ;;
+                                                       esac
+                                               fi
+                                               ;;
+                                       esac
+                                       ;;
+                               esac
+                               ;;
+                       *)
+                               case "$cmd" in
+                               *\>![\ \        ]*)
+                                       ed - /tmp/bcsh$$ << ++++
+                                       g/>!/s//>/g
+                                       w
+++++
+                                       ;;
+                               esac
+                               ;;
+                       esac
+                       (trap 'exit 1' 2 3; $BASH /tmp/bcsh$$)
+                       ;;
+               esac
+               case "$cmd" in
+               $lastcmd)
+                       ;;
+               *)
+                       case "$exclaim" in
+                       yes)
+                               cmd="`echo \"$cmd\" | sed -e 's@!@\\\\!@g'`"
+                               ;;
+                       esac
+
+                       cat << ++++ >> $histfile
+$cmd
+++++
+                       lastcmd=$cmd
+
+                       case "$inc_cmdno" in
+                       yes)
+                               cmdno="`expr \"$cmdno\" + 1`"
+                               # cmdno=$[$cmdno + 1]
+                               ;;
+                       esac
+                       ;;
+               esac
+               ;;
+       esac
+
+       # The next commented-out line sets the prompt to include the command
+       # number -- you should only un-comment this if it is the ONLY thing
+       # you ever want as your prompt, because it will override attempts
+       # to set PS1 from the command level.  If you want the command number
+       # in your prompt without sacrificing the ability to change the prompt
+       # later, replace the default setting for PS1 before the beginning of
+       # the main loop with the following:  PS1='echo -n "${cmdno}% "'
+       # Doing it this way is, however, slower than the simple version below.
+        
+       PS1="${cmdno}% "
+
+       getcmd=yes
+       echoit=no
+       exclaim=no
+done
+exit 0
+
+# Christine Robertson  {linus, ihnp4, decvax}!utzoo!globetek!chris
diff --git a/examples/scripts/precedence b/examples/scripts/precedence
new file mode 100644 (file)
index 0000000..9bbdb97
--- /dev/null
@@ -0,0 +1,75 @@
+# @(#)precedence_test 1.0 91/07/24 Maarten Litmaath
+# test of relative precedences for `&&' and `||' operators
+
+echo "\`Say' echos its argument. Its return value is of no interest."
+case `echo -n` in
+  '') Say () { echo -n "$*" ; } ;;
+   *) Say () { echo "$*\c" ; } ;;
+esac
+
+echo "\`Truth' echos its argument and returns a TRUE result."
+Truth () {
+  Say $1;
+  return 0;
+}
+
+echo "\`False' echos its argument and returns a FALSE result."
+False () {
+  Say $1;
+  return 1;
+}
+
+echo ""
+
+cmd1='$open $test1 && $test2 $close || $test3'
+cmd2='$test1 || $open $test2 && $test3 $close'
+
+grouping_sh=
+grouping_C='( )'
+
+test3='Say 3'
+
+for i in 1 2
+do
+   eval proto=\$cmd$i
+
+   for test1 in 'Truth 1' 'False 1'
+   do
+      for test2 in 'Truth 2' 'False 2'
+      do
+        for precedence in sh C
+        do
+           eval set x \$grouping_$precedence
+           shift
+           open=${1-' '}
+           close=${2-' '}
+           eval cmd=\""$proto"\"
+           Say "$cmd   output="
+           output=`eval "$cmd"`
+           Say "$output"
+           read correct || { echo 'Input fubar.  Abort.' >&2; exit 1; }
+           test "X$output" = "X$correct" || echo "   correct=$correct"
+           echo ''
+        done
+
+        echo ''
+      done
+   done
+done << EOF
+12
+12
+123
+123
+13
+13
+13
+13
+13
+1
+13
+1
+123
+123
+12
+12
+EOF
diff --git a/examples/scripts/shprompt b/examples/scripts/shprompt
new file mode 100755 (executable)
index 0000000..ec8b997
--- /dev/null
@@ -0,0 +1,137 @@
+#
+# shprompt -- give a prompt and get an answer satisfying certain criteria
+#
+# shprompt [-dDfFsy] prompt
+#      s = prompt for string
+#      f = prompt for filename
+#      F = prompt for full pathname to a file or directory
+#      d = prompt for a directory name
+#      D = prompt for a full pathname to a directory
+#      y = prompt for y or n answer
+#
+# Chet Ramey
+# chet@ins.CWRU.Edu
+
+type=file
+
+OPTS=dDfFsy
+
+succeed()
+{
+       echo "$1"
+       exit 0
+}
+
+while getopts "$OPTS" c
+do
+       case "$c" in
+       s)      type=string
+               ;;
+       f)      type=file
+               ;;
+       F)      type=path
+               ;;
+       d)      type=dir
+               ;;
+       D)      type=dirpath
+               ;;
+       y)      type=yesno
+               ;;
+       ?)      echo "usage: $0 [-$OPTS] prompt" 1>&2
+               exit 2
+               ;;
+       esac
+done
+
+if [ "$OPTIND" -gt 1 ] ; then
+       shift $[$OPTIND - 1]
+fi
+
+while :
+do
+       case "$type" in
+       string)
+               echo -n "$1" 1>&2
+               read ans || exit 1
+               if [ -n "$ans" ] ; then
+                       succeed "$ans"
+               fi
+               ;;
+       file|path)
+               echo -n "$1" 1>&2
+               read ans || exit 1
+               #
+               # use `fn' and eval so that bash will do tilde expansion for
+               # me
+               #
+               eval fn="$ans"
+               case "$fn" in
+               /*)     if test -e "$fn" ; then
+                               succeed "$fn"
+                       else
+                               echo "$0: '$fn' does not exist" 1>&2
+                       fi
+                       ;;
+               *)      if [ "$type" = "path" ] ; then
+                               echo "$0: must give full pathname to file" 1>&2
+                       else
+                               if test -e "$fn" ; then
+                                       succeed "$fn"
+                               else
+                                       echo "$0: '$fn' does not exist" 1>&2
+                               fi
+                       fi
+                       ;;
+               esac
+               ;;
+       dir|dirpath)
+               echo -n "$1" 1>&2
+               read ans || exit 1
+               #
+               # use `fn' and eval so that bash will do tilde expansion for
+               # me
+               #
+               eval fn="$ans"
+               case "$fn" in
+               /*)     if test -d "$fn" ; then
+                               succeed "$fn"
+                       elif test -e "$fn" ; then
+                               echo "$0 '$fn' is not a directory" 1>&2
+                       else
+                               echo "$0: '$fn' does not exist" 1>&2
+                       fi
+                       ;;
+               *)      if [ "$type" = "dirpath" ] ; then
+                               echo "$0: must give full pathname to directory" 1>&2
+                       else
+                               if test -d "$fn" ; then
+                                       succeed "$fn"
+                               elif test -e "$fn" ; then
+                                       echo "$0 '$fn' is not a directory" 1>&2
+                               else
+                                       echo "$0: '$fn' does not exist" 1>&2
+                               fi
+                       fi
+                       ;;
+               esac
+               ;;
+       yesno)
+               echo -n "$1" 1>&2
+               read ans || exit 1
+               case "$ans" in
+               y|Y|[yY][eE][sS])
+                       succeed "yes"
+                       ;;
+               n|N|[nN][oO])
+                       succeed "no"
+                       exit 0
+                       ;;
+               *)
+                       echo "$0: yes or no required" 1>&2
+                       ;;
+               esac
+               ;;
+       esac
+done
+
+exit 1
diff --git a/examples/startup-files/Bash_aliases b/examples/startup-files/Bash_aliases
new file mode 100644 (file)
index 0000000..012ad5c
--- /dev/null
@@ -0,0 +1,63 @@
+# Some useful aliases.
+alias texclean='rm -f *.toc *.aux *.log *.cp *.fn *.tp *.vr *.pg *.ky'
+alias clean='echo -n "Really clean this directory?";
+       read yorn;
+       if test "$yorn" = "y"; then
+          rm -f \#* *~ .*~ *.bak .*.bak  *.tmp .*.tmp core a.out;
+          echo "Cleaned.";
+       else
+          echo "Not cleaned.";
+       fi'
+alias h='history'
+alias j="jobs -l"
+alias l="ls -l "
+alias ll="ls -l"
+alias ls="ls -F"
+alias term='set noglob; eval `tset -Q -s `'
+alias pu="pushd"
+alias po="popd"
+
+#
+# Csh compatability:
+#
+alias unsetenv=unset
+function setenv () {
+  export $1="$2"
+}
+
+# Function which adds an alias to the current shell and to
+# the ~/.bash_aliases file.
+add-alias ()
+{
+   local name=$1 value="$2"
+   echo alias $name=\'$value\' >>~/.bash_aliases
+   eval alias $name=\'$value\'
+   alias $name
+}
+
+# "repeat" command.  Like:
+#
+#      repeat 10 echo foo
+repeat ()
+{ 
+    local count="$1" i;
+    shift;
+    for i in $(seq 1 "$count");
+    do
+        eval "$@";
+    done
+}
+
+# Subfunction needed by `repeat'.
+seq ()
+{ 
+    local lower upper output;
+    lower=$1 upper=$2;
+    while [ $lower -le $upper ];
+    do
+        output="$output $lower";
+        lower=$[ $lower + 1 ];
+    done;
+    echo $output
+}
+
diff --git a/examples/startup-files/Bash_profile b/examples/startup-files/Bash_profile
new file mode 100644 (file)
index 0000000..b1b24c0
--- /dev/null
@@ -0,0 +1,20 @@
+# Startup file for bash login shells.
+#
+default_dir=/usr/local/lib/
+
+if [ "$PS1" ]; then
+  PS1='\u@\h(\#)$ '
+  ignoreeof=3
+fi
+
+LOGIN_SHELL=true
+
+# If the user has her own init file, then use that one, else use the
+# canonical one.
+if [ -f ~/.bashrc ]; then
+  source ~/.bashrc
+else if [ -f ${default_dir}Bashrc ]; then
+  source ${default_dir}Bashrc;
+  fi
+fi
+
diff --git a/examples/startup-files/Bashrc b/examples/startup-files/Bashrc
new file mode 100644 (file)
index 0000000..935bff8
--- /dev/null
@@ -0,0 +1,72 @@
+# Bourne Again SHell init file.
+#
+# Files you make look like rw-rw-r
+umask 002
+
+# Don't make useless coredump files.  If you want a coredump,
+# say "ulimit -c unlimited" and then cause a segmentation fault.
+ulimit -c 0
+
+# Sometimes, there are lots of places that one can find tex inputs.
+export TEXINPUTS=.:$HOME/bin:/usr/lib/tex/inputs:/usr/local/lib/tex/inputs
+
+# Where's the Gnu stuff at?
+GNU=/usr/gnu/bin
+X11=/usr/bin/X11
+
+UTIL_PATH=$GNU:$X11
+STANDARD_PATH=/usr/local/bin:/usr/ucb:/bin:/usr/bin:/usr/etc:/etc:/usr/games
+if [ "$HOSTTYPE" = "sony" ]; then STANDARD_PATH=STANDARD_PATH:/usr/sony/bin; fi
+
+if [ -d $HOME/bin/$HOSTTYPE ]; then
+  MY_PATH=$HOME/bin/$HOSTTYPE
+fi
+
+if [ -d $HOME/bin ]; then
+  MY_PATH=$MY_PATH:$HOME/bin
+fi
+
+if [ -d /usr/hosts ]; then
+  STANDARD_PATH=$STANDARD_PATH:/usr/hosts
+fi
+
+PATH=.:$MY_PATH:$UTIL_PATH:$STANDARD_PATH
+
+# If running interactively, then:
+if [ "$PS1" ]; then
+
+  # Set ignoreeof if you don't want EOF as the sole input to the shell to
+  # immediately signal a quit condition.  This only happens at the start
+  # of a line if the line is empty, and you haven't just deleted a character
+  # with C-d.  I turn this on in ~/.bash_profile so that only login shells
+  # have the right to be obnoxious.
+  # ignoreeof=
+
+  # Set auto_resume if you want to resume on "emacs", as well as on
+  # "%emacs".
+  auto_resume=
+
+  # Set notify if you want to be asynchronously notified about background
+  # job completion.
+  notify=
+
+  # Make it so that failed `exec' commands don't flush this shell.
+  no_exit_on_failed_exec=
+
+  if [ ! "$LOGIN_SHELL" ]; then
+    PS1="\u@\h\$ "
+  fi
+
+  HISTSIZE=256
+  MAILCHECK=60
+
+  # A couple of default aliases.
+  alias j='jobs -l'
+  alias po=popd
+  alias pu=pushd
+  alias ls='ls -F'
+
+  if [ -f ~/.bash_aliases ]; then
+    source ~/.bash_aliases
+  fi
+fi
diff --git a/examples/startup-files/bash-profile b/examples/startup-files/bash-profile
new file mode 100644 (file)
index 0000000..01c322a
--- /dev/null
@@ -0,0 +1,54 @@
+HOME=/usr/homes/chet
+MAIL=/usr/homes/chet/mbox
+MAILCHECK=30
+HISTFILE=/usr/homes/chet/.history
+
+MACHINE=$(/usr/local/bin/machine)
+HOST=$(hostname)
+
+PATH1=/usr/homes/chet/bin.$MACHINE:/usr/local/bin/gnu:
+PATH2=/usr/local/bin:/usr/ucb:/bin:/usr/bin/X11:.
+PATH3=/usr/andrew/bin:/usr/bin:/usr/ibm:/usr/local/bin/mh:/usr/new/bin:
+PATH=$PATH1:$PATH2:$PATH3
+
+EDITOR=/usr/homes/chet/bin.$MACHINE/ce
+VISUAL=/usr/homes/chet/bin.$MACHINE/ce
+FCEDIT=/usr/homes/chet/bin.$MACHINE/ce
+
+if [ "$BASH" ] ; then
+       SHELL=$BASH
+else
+       SHELL=/bin/bash
+fi
+
+if [ "$MACHINE" = "ibm032" ] ; then
+       stty erase ^H
+fi
+
+PAGER=/usr/ucb/more
+NNTPSERVER=kiwi
+NS=/nfs/cwjcc/fs1/ns-engr/proj/netsrv/cwpub/proto/src
+
+#
+# Bogus 1003.2 variables.  This should really be in /etc/profile
+#
+LOGNAME=${USER-$(whoami)}
+TZ=EST5EDT
+
+export HOME ENV VISUAL EDITOR MAIL SHELL PATH TERM 
+export PAGER LESS TERMCAP HISTSZIE HISTFILE
+export MAIL MAILCHECK HOST HOSTNAME NNTPSERVER NS LOGNAME TZ
+
+PS1="${HOST}$ "
+PS2='> '
+export PS1 PS2
+
+umask 022
+
+if [ -f /unix ] ; then
+       stty intr ^c
+fi
+
+if [ -f ~/.bashrc ] ; then
+       . ~/.bashrc
+fi
diff --git a/examples/startup-files/bashrc b/examples/startup-files/bashrc
new file mode 100644 (file)
index 0000000..5363e58
--- /dev/null
@@ -0,0 +1,139 @@
+if [ "$PS1" != "" ] ; then
+
+if [ -f /unix ] ; then
+       alias ls='/bin/ls -CF'
+       alias ll='/bin/ls -lCF'
+       alias dir='/bin/ls -bCalF'
+else
+       alias ls='/bin/ls -F'
+       alias ll='/bin/ls -lF'
+       alias dir='/bin/ls -balF'
+fi
+
+alias ss="ps -aux"
+alias mail=/usr/ucb/mail
+alias dot='ls .[a-zA-Z0-9]*'
+alias mroe=more
+alias pwd='echo $PWD'
+alias pdw='echo $PWD'
+alias news="xterm -g 80x45 -e rn -e &"
+alias back='cd $OLDPWD'
+alias manroff="nroff /usr/lib/tmac/tmac.an.4.3"
+alias laser="lpr -Palw2"
+alias lw="lpr -Palw2"
+alias c="clear"
+alias m="more"
+alias j="jobs"
+
+if [ -z "$HOST" ] ; then
+       export HOST=`hostname`
+fi
+
+history_control=ignoredups
+
+psgrep()
+{
+       ps -aux | grep $1 | grep -v grep
+}
+
+#
+# This is a little like `zap' from Kernighan and Pike
+#
+
+pskill()
+{
+       local pid
+
+       pid=$(ps -ax | grep $1 | grep -v grep | awk '{ print $1 }')
+       echo -n "killing $1 (process $pid)..."
+       kill -9 $pid
+       echo "slaughtered."
+}
+
+term()
+{
+        TERM=$1
+       export TERM
+       tset
+}
+
+cd()
+{
+       builtin cd $*
+       xtitle $HOST: $PWD
+}
+
+bold()
+{
+       tput smso
+}
+
+unbold()
+{
+       tput rmso
+}
+
+if [ -f /unix ] ; then
+clear()
+{
+       tput clear
+}
+fi
+
+rot13()
+{
+       if [ $# = 0 ] ; then
+               tr "[a-m][n-z][A-M][N-Z]" "[n-z][a-m][N-Z][A-M]"
+       else
+               tr "[a-m][n-z][A-M][N-Z]" "[n-z][a-m][N-Z][A-M]" < $1
+       fi
+}
+
+watch()
+{
+        if [ $# -ne 1 ] ; then
+                tail -f nohup.out
+        else
+                tail -f $1
+        fi
+}
+
+#
+#       Remote login passing all 8 bits (so meta key will work)
+#
+rl()
+{
+        rlogin $* -8
+}
+
+function setenv()
+{
+       if [ $# -ne 2 ] ; then
+               echo "setenv: Too few arguments"
+       else
+               export $1="$2"
+       fi
+}
+
+function chmog()
+{
+       if [ $# -ne 4 ] ; then
+               echo "usage: chmog mode owner group file"
+               return 1
+       else
+               chmod $1 $4
+               chown $2 $4
+               chgrp $3 $4
+       fi
+}
+
+#
+# Source kshenv for ksh-compatibility definitions
+#
+
+if [ -f ~/.kshenv ] ; then
+       . ~/.kshenv
+fi
+
+fi
+#end of .bashrc
diff --git a/examples/suncmd.termcap b/examples/suncmd.termcap
new file mode 100644 (file)
index 0000000..c3422fb
--- /dev/null
@@ -0,0 +1,30 @@
+#Posted-Date: Fri, 9 Mar 90 18:34:29 EST
+#Date: Fri, 9 Mar 90 18:34:29 EST
+#From: "Eirik Fuller" <wonton.tn.cornell.edu!eirik@ucsbcsl.UUCP>
+#To: bfox@ai.mit.edu (Brian Fox)
+#Subject: Patch to bash 1.05 for SunView
+#
+#I think this works:
+#
+Mu|sun-cmd:am:bs:km:pt:li#34:co#80:cl=^L:ce=\E[K:cd=\E[J:rs=\E[s:
+#
+#Another alternative is to send the ti string at startup time (and, I
+#guess, the te string at exit time); that is how vi works in a cmdtool.
+#The best reason to not do this is that this also disables scrolling
+#which, as I understand it, is why anyone would use cmdtool in the
+#first place.  Sending the ti string at startup time would do strange
+#things on other systems too; in xterm it would use the alternate
+#screen.
+#
+#The problem with cmdtool, in case that is less than obvious, is that
+#almost none of the capabilities advertised in /etc/termcap are enabled
+#while scrolling is enabled.  It has other problems too, like being
+#part of an outdated proprietary windowing system, but there's probably
+#no need to dwell on that.  In a sense, though, the sun-cmd termcap
+#entry doesn't lie about the capabilities; I think the termcap man page
+#does warn about some terminals having cursor motion capabilities only
+#in the "ti/te window".
+#
+#A general solution to this problem would require a termcap capability
+#which somehow tells which features are available outside of the ti/te
+#window.  There is no such capability in termcap now, of course.
diff --git a/execute_cmd.c b/execute_cmd.c
new file mode 100644 (file)
index 0000000..55274ea
--- /dev/null
@@ -0,0 +1,3698 @@
+/* execute_command.c -- Execute a COMMAND structure. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+#if defined (AIX) && defined (RISC6000) && !defined (__GNUC__)
+  #pragma alloca
+#endif /* AIX && RISC6000 && !__GNUC__ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "bashtypes.h"
+#include <sys/file.h>
+#include "filecntl.h"
+#include "posixstat.h"
+#include <signal.h>
+
+#if !defined (SIGABRT)
+#define SIGABRT SIGIOT
+#endif
+
+#include <sys/param.h>
+#include <errno.h>
+
+#if !defined (errno)
+extern int errno;
+#endif
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "shell.h"
+#include "y.tab.h"
+#include "flags.h"
+#include "hash.h"
+#include "jobs.h"
+#include "execute_cmd.h"
+
+#include "sysdefs.h"
+#include "builtins/common.h"
+#include "builtins/builtext.h" /* list of builtins */
+
+#include <glob/fnmatch.h>
+#include <tilde/tilde.h>
+
+#if defined (BUFFERED_INPUT)
+#  include "input.h"
+#endif
+
+extern int posixly_correct;
+extern int breaking, continuing, loop_level;
+extern int interactive, interactive_shell, login_shell;
+extern int parse_and_execute_level;
+extern int command_string_index, variable_context, line_number;
+extern int dot_found_in_search;
+extern char **temporary_env, **function_env, **builtin_env;
+extern char *the_printed_command, *shell_name;
+extern pid_t last_command_subst_pid;
+extern Function *last_shell_builtin, *this_shell_builtin;
+extern jmp_buf top_level, subshell_top_level;
+extern int subshell_argc;
+extern char **subshell_argv, **subshell_envp;
+extern int already_making_children;
+
+extern int getdtablesize ();
+extern int close ();
+
+/* Static functions defined and used in this file. */
+static void close_pipes (), do_piping (), execute_disk_command ();
+static void execute_subshell_builtin_or_function ();
+static void cleanup_redirects (), cleanup_func_redirects (), bind_lastarg ();
+static void add_undo_close_redirect (), add_exec_redirect ();
+static int do_redirection_internal (), do_redirections ();
+static int expandable_redirection_filename (), execute_shell_script ();
+static int execute_builtin_or_function (), add_undo_redirect ();
+static char *find_user_command_internal (), *find_user_command_in_path ();
+
+/* The line number that the currently executing function starts on. */
+static int function_line_number = 0;
+
+/* Set to 1 if fd 0 was the subject of redirection to a subshell. */
+static int stdin_redir = 0;
+
+/* The name of the command that is currently being executed.
+   `test' needs this, for example. */
+char *this_command_name;
+
+struct stat SB;                /* used for debugging */
+
+static REDIRECTEE rd;
+
+/* For catching RETURN in a function. */
+int return_catch_flag = 0;
+int return_catch_value;
+jmp_buf return_catch;
+
+/* The value returned by the last synchronous command. */
+int last_command_exit_value = 0;
+
+/* The list of redirections to perform which will undo the redirections
+   that I made in the shell. */
+REDIRECT *redirection_undo_list = (REDIRECT *)NULL;
+
+/* The list of redirections to perform which will undo the internal
+   redirections performed by the `exec' builtin.  These are redirections
+   that must be undone even when exec discards redirection_undo_list. */
+REDIRECT *exec_redirection_undo_list = (REDIRECT *)NULL;
+
+/* Non-zero if we have just forked and are currently running in a subshell
+   environment. */
+int subshell_environment = 0;
+
+struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL;
+
+#define FD_BITMAP_DEFAULT_SIZE 32
+/* Functions to allocate and deallocate the structures used to pass
+   information from the shell to its children about file descriptors
+   to close. */
+struct fd_bitmap *
+new_fd_bitmap (size)
+     long size;
+{
+  struct fd_bitmap *ret;
+
+  ret = (struct fd_bitmap *)xmalloc (sizeof (struct fd_bitmap));
+
+  ret->size = size;
+
+  if (size)
+    {
+      ret->bitmap = xmalloc (size);
+      bzero (ret->bitmap, size);
+    }
+  else
+    ret->bitmap = (char *)NULL;
+  return (ret);
+}
+
+void
+dispose_fd_bitmap (fdbp)
+     struct fd_bitmap *fdbp;
+{
+  FREE (fdbp->bitmap);
+  free (fdbp);
+}
+
+void
+close_fd_bitmap (fdbp)
+     struct fd_bitmap *fdbp;
+{
+  register int i;
+
+  if (fdbp)
+    {
+      for (i = 0; i < fdbp->size; i++)
+       if (fdbp->bitmap[i])
+         {
+           close (i);
+           fdbp->bitmap[i] = 0;
+         }
+    }
+}
+
+/* Execute the command passed in COMMAND.  COMMAND is exactly what
+   read_command () places into GLOBAL_COMMAND.  See "command.h" for the
+   details of the command structure.
+
+   EXECUTION_SUCCESS or EXECUTION_FAILURE are the only possible
+   return values.  Executing a command with nothing in it returns
+   EXECUTION_SUCCESS. */
+execute_command (command)
+     COMMAND *command;
+{
+  struct fd_bitmap *bitmap;
+  int result;
+
+  current_fds_to_close = (struct fd_bitmap *)NULL;
+  bitmap = new_fd_bitmap (FD_BITMAP_DEFAULT_SIZE);
+  begin_unwind_frame ("execute-command");
+  add_unwind_protect (dispose_fd_bitmap, (char *)bitmap);
+
+  /* Just do the command, but not asynchronously. */
+  result = execute_command_internal (command, 0, NO_PIPE, NO_PIPE, bitmap);
+
+  dispose_fd_bitmap (bitmap);
+  discard_unwind_frame ("execute-command");
+
+#if defined (PROCESS_SUBSTITUTION)
+  unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+
+  return (result);
+}
+
+/* Return 1 if TYPE is a shell control structure type. */
+static int
+shell_control_structure (type)
+     enum command_type type;
+{
+  switch (type)
+    {
+    case cm_for:
+#if defined (SELECT_COMMAND)
+    case cm_select:
+#endif
+    case cm_case:
+    case cm_while:
+    case cm_until:
+    case cm_if:
+    case cm_group:
+      return (1);
+
+    default:
+      return (0);
+    }
+}
+
+/* A function to use to unwind_protect the redirection undo list
+   for loops. */
+static void
+cleanup_redirects (list)
+     REDIRECT *list;
+{
+  do_redirections (list, 1, 0, 0);
+  dispose_redirects (list);
+}
+
+/* Function to unwind_protect the redirections for functions and builtins. */
+static void
+cleanup_func_redirects (list)
+     REDIRECT *list;
+{
+  do_redirections (list, 1, 0, 0);
+}
+
+static void
+dispose_exec_redirects ()
+{
+  if (exec_redirection_undo_list)
+    {
+      dispose_redirects (exec_redirection_undo_list);
+      exec_redirection_undo_list = (REDIRECT *)NULL;
+    }
+}
+
+#if defined (JOB_CONTROL)
+/* A function to restore the signal mask to its proper value when the shell
+   is interrupted or errors occur while creating a pipeline. */
+static int
+restore_signal_mask (set)
+     sigset_t set;
+{
+  return (sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL));
+}
+#endif /* JOB_CONTROL */
+
+/* A debugging function that can be called from gdb, for instance. */
+void
+open_files ()
+{
+  register int i;
+  int f, fd_table_size;
+
+  fd_table_size = getdtablesize ();
+
+  fprintf (stderr, "pid %d open files:", getpid ());
+  for (i = 3; i < fd_table_size; i++)
+    {
+      if ((f = fcntl (i, F_GETFD, 0)) != -1)
+       fprintf (stderr, " %d (%s)", i, f ? "close" : "open");
+    }
+  fprintf (stderr, "\n");
+}
+
+#define DESCRIBE_PID(pid) if (interactive) describe_pid (pid)
+
+/* Execute the command passed in COMMAND, perhaps doing it asynchrounously.
+   COMMAND is exactly what read_command () places into GLOBAL_COMMAND.
+   ASYNCHROUNOUS, if non-zero, says to do this command in the background.
+   PIPE_IN and PIPE_OUT are file descriptors saying where input comes
+   from and where it goes.  They can have the value of NO_PIPE, which means
+   I/O is stdin/stdout.
+   FDS_TO_CLOSE is a list of file descriptors to close once the child has
+   been forked.  This list often contains the unusable sides of pipes, etc.
+
+   EXECUTION_SUCCESS or EXECUTION_FAILURE are the only possible
+   return values.  Executing a command with nothing in it returns
+   EXECUTION_SUCCESS. */
+execute_command_internal (command, asynchronous, pipe_in, pipe_out, 
+                         fds_to_close)
+     COMMAND *command;
+     int asynchronous;
+     int pipe_in, pipe_out;
+     struct fd_bitmap *fds_to_close;
+{
+  int exec_result = EXECUTION_SUCCESS;
+  int invert, ignore_return;
+  REDIRECT *my_undo_list, *exec_undo_list;
+
+  if (!command || breaking || continuing)
+    return (EXECUTION_SUCCESS);
+
+  run_pending_traps ();
+
+  invert = (command->flags & CMD_INVERT_RETURN) != 0;
+
+  /* If a command was being explicitly run in a subshell, or if it is
+     a shell control-structure, and it has a pipe, then we do the command
+     in a subshell. */
+
+  if ((command->flags & CMD_WANT_SUBSHELL) ||
+      (command->flags & CMD_FORCE_SUBSHELL)  ||
+      (shell_control_structure (command->type) &&
+       (pipe_out != NO_PIPE || pipe_in != NO_PIPE || asynchronous)))
+    {
+      pid_t paren_pid;
+
+      /* Fork a subshell, turn off the subshell bit, turn off job
+        control and call execute_command () on the command again. */
+      paren_pid = make_child (savestring (make_command_string (command)),
+                             asynchronous);
+      if (paren_pid == 0)
+       {
+         int user_subshell, return_code, function_value;
+
+         /* Cancel traps, in trap.c. */
+         restore_original_signals ();
+         if (asynchronous)
+           setup_async_signals ();
+
+#if defined (JOB_CONTROL)
+         set_sigchld_handler ();
+#endif /* JOB_CONTROL */
+
+         set_sigint_handler ();
+
+         user_subshell = (command->flags & CMD_WANT_SUBSHELL) != 0;
+         command->flags &= ~(CMD_FORCE_SUBSHELL | CMD_WANT_SUBSHELL | CMD_INVERT_RETURN);
+
+         /* If a command is asynchronous in a subshell (like ( foo ) & or
+            the special case of an asynchronous GROUP command where the
+            the subshell bit is turned on down in case cm_group: below), 
+            turn off `asynchronous', so that two subshells aren't spawned.
+
+            This seems semantically correct to me.  For example, 
+            ( foo ) & seems to say ``do the command `foo' in a subshell
+            environment, but don't wait for that subshell to finish'',
+            and "{ foo ; bar } &" seems to me to be like functions or
+            builtins in the background, which executed in a subshell
+            environment.  I just don't see the need to fork two subshells. */
+
+         /* Don't fork again, we are already in a subshell.  A `doubly
+            async' shell is not interactive, however. */
+         if (asynchronous)
+           {
+#if defined (JOB_CONTROL)
+             /* If a construct like ( exec xxx yyy ) & is given while job
+                control is active, we want to prevent exec from putting the
+                subshell back into the original process group, carefully
+                undoing all the work we just did in make_child. */
+             original_pgrp = -1;
+#endif /* JOB_CONTROL */
+             interactive_shell = 0;
+             asynchronous = 0;
+           }
+
+         /* Subshells are neither login nor interactive. */
+         login_shell = interactive = 0;
+
+         subshell_environment = 1;
+
+#if defined (JOB_CONTROL)
+         /* Delete all traces that there were any jobs running.  This is
+            only for subshells. */
+         without_job_control ();
+#endif /* JOB_CONTROL */
+         do_piping (pipe_in, pipe_out);
+
+         /* If this is a user subshell, set a flag if stdin was redirected.
+            This is used later to decide whether to redirect fd 0 to
+            /dev/null for async commands in the subshell.  This adds more
+            sh compatibility, but I'm not sure it's the right thing to do. */
+         if (user_subshell)
+           {
+             REDIRECT *r;
+
+             for (r = command->redirects; r; r = r->next)
+               switch (r->instruction)
+                 {
+                 case r_input_direction:
+                 case r_inputa_direction:
+                 case r_input_output:
+                 case r_reading_until:
+                 case r_deblank_reading_until:
+                   stdin_redir++;
+                   break;
+                 case r_duplicating_input:
+                 case r_duplicating_input_word:
+                 case r_close_this:
+                   if (r->redirector == 0)
+                     stdin_redir++;
+                   break;
+                 }
+           }
+
+         if (fds_to_close)
+           close_fd_bitmap (fds_to_close);
+
+         /* Do redirections, then dispose of them before recursive call. */
+         if (command->redirects)
+           {
+             if (do_redirections (command->redirects, 1, 0, 0) != 0)
+               exit (EXECUTION_FAILURE);
+
+             dispose_redirects (command->redirects);
+             command->redirects = (REDIRECT *)NULL;
+           }
+
+         /* If this is a simple command, tell execute_disk_command that it
+            might be able to get away without forking and simply exec.
+            This means things like ( sleep 10 ) will only cause one fork. */
+         if (user_subshell && command->type == cm_simple)
+           {
+             command->flags |= CMD_NO_FORK;
+             command->value.Simple->flags |= CMD_NO_FORK;
+           }
+
+         /* If we're inside a function while executing this subshell, we
+            need to handle a possible `return'. */
+         function_value = 0;
+         if (return_catch_flag)
+           function_value =  setjmp (return_catch);
+
+         if (function_value)
+           return_code = return_catch_value;
+         else
+           return_code = execute_command_internal
+             (command, asynchronous, NO_PIPE, NO_PIPE, fds_to_close);
+
+         /* If we were explicitly placed in a subshell with (), we need
+            to do the `shell cleanup' things, such as running traps[0]. */
+         if (user_subshell && signal_is_trapped (0))
+           {
+             last_command_exit_value = return_code;
+             return_code = run_exit_trap ();
+           }
+
+         exit (return_code);
+       }
+      else
+       {
+         close_pipes (pipe_in, pipe_out);
+
+#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
+         unlink_fifo_list ();
+#endif
+         /* If we are part of a pipeline, and not the end of the pipeline,
+            then we should simply return and let the last command in the
+            pipe be waited for.  If we are not in a pipeline, or are the
+            last command in the pipeline, then we wait for the subshell 
+            and return its exit status as usual. */
+         if (pipe_out != NO_PIPE)
+           return (EXECUTION_SUCCESS);
+
+         stop_pipeline (asynchronous, (COMMAND *)NULL);
+
+         if (!asynchronous)
+           {
+             last_command_exit_value = wait_for (paren_pid);
+
+             /* If we have to, invert the return value. */
+             if (invert)
+               {
+                 if (last_command_exit_value == EXECUTION_SUCCESS)
+                   return (EXECUTION_FAILURE);
+                 else
+                   return (EXECUTION_SUCCESS);
+               }
+             else
+               return (last_command_exit_value);
+           }
+         else
+           {
+             DESCRIBE_PID (paren_pid);
+
+             run_pending_traps ();
+
+             return (EXECUTION_SUCCESS);
+           }
+       }
+    }
+
+  /* Handle WHILE FOR CASE etc. with redirections.  (Also '&' input
+     redirection.)  */
+  if (do_redirections (command->redirects, 1, 1, 0) != 0)
+    {
+      cleanup_redirects (redirection_undo_list);
+      redirection_undo_list = (REDIRECT *)NULL;
+      dispose_exec_redirects ();
+      return (EXECUTION_FAILURE);
+    }
+
+  if (redirection_undo_list)
+    {
+      my_undo_list = (REDIRECT *)copy_redirects (redirection_undo_list);
+      dispose_redirects (redirection_undo_list);
+      redirection_undo_list = (REDIRECT *)NULL;
+    }
+  else
+    my_undo_list = (REDIRECT *)NULL;
+
+  if (exec_redirection_undo_list)
+    {
+      exec_undo_list = (REDIRECT *)copy_redirects (exec_redirection_undo_list);
+      dispose_redirects (exec_redirection_undo_list);
+      exec_redirection_undo_list = (REDIRECT *)NULL;
+    }
+  else
+    exec_undo_list = (REDIRECT *)NULL;
+
+  if (my_undo_list || exec_undo_list)
+    begin_unwind_frame ("loop_redirections");
+
+  if (my_undo_list)
+    add_unwind_protect ((Function *)cleanup_redirects, my_undo_list);
+
+  if (exec_undo_list)
+    add_unwind_protect ((Function *)dispose_redirects, exec_undo_list);
+
+  ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
+
+  QUIT;
+
+  switch (command->type)
+    {
+    case cm_for:
+      if (ignore_return)
+       command->value.For->flags |= CMD_IGNORE_RETURN;
+      exec_result = execute_for_command (command->value.For);
+      break;
+
+#if defined (SELECT_COMMAND)
+    case cm_select:
+      if (ignore_return)
+       command->value.Select->flags |= CMD_IGNORE_RETURN;
+      exec_result = execute_select_command (command->value.Select);
+      break;
+#endif
+
+    case cm_case:
+      if (ignore_return)
+       command->value.Case->flags |= CMD_IGNORE_RETURN;
+      exec_result = execute_case_command (command->value.Case);
+      break;
+
+    case cm_while:
+      if (ignore_return)
+       command->value.While->flags |= CMD_IGNORE_RETURN;
+      exec_result = execute_while_command (command->value.While);
+      break;
+
+    case cm_until:
+      if (ignore_return)
+       command->value.While->flags |= CMD_IGNORE_RETURN;
+      exec_result = execute_until_command (command->value.While);
+      break;
+
+    case cm_if:
+      if (ignore_return)
+       command->value.If->flags |= CMD_IGNORE_RETURN;
+      exec_result = execute_if_command (command->value.If);
+      break;
+
+    case cm_group:
+
+      /* This code can be executed from either of two paths: an explicit
+        '{}' command, or via a function call.  If we are executed via a
+        function call, we have already taken care of the function being
+        executed in the background (down there in execute_simple_command ()),
+        and this command should *not* be marked as asynchronous.  If we
+        are executing a regular '{}' group command, and asynchronous == 1,
+        we must want to execute the whole command in the background, so we
+        need a subshell, and we want the stuff executed in that subshell
+        (this group command) to be executed in the foreground of that
+        subshell (i.e. there will not be *another* subshell forked).
+
+        What we do is to force a subshell if asynchronous, and then call
+        execute_command_internal again with asynchronous still set to 1,
+        but with the original group command, so the printed command will
+        look right.
+
+        The code above that handles forking off subshells will note that
+        both subshell and async are on, and turn off async in the child
+        after forking the subshell (but leave async set in the parent, so
+        the normal call to describe_pid is made).  This turning off
+        async is *crucial*; if it is not done, this will fall into an
+        infinite loop of executions through this spot in subshell after
+        subshell until the process limit is exhausted. */
+
+      if (asynchronous)
+       {
+         command->flags |= CMD_FORCE_SUBSHELL;
+         exec_result =
+           execute_command_internal (command, 1, pipe_in, pipe_out,
+                                     fds_to_close);
+       }
+      else
+       {
+         if (ignore_return && command->value.Group->command)
+           command->value.Group->command->flags |= CMD_IGNORE_RETURN;
+         exec_result =
+           execute_command_internal (command->value.Group->command,
+                                     asynchronous, pipe_in, pipe_out,
+                                     fds_to_close);
+       }
+      break;
+
+    case cm_simple:
+      {
+       /* We can't rely on this variable retaining its value across a
+          call to execute_simple_command if a longjmp occurs as the
+          result of a `return' builtin.  This is true for sure with gcc. */
+       pid_t last_pid = last_made_pid;
+
+       if (ignore_return && command->value.Simple)
+         command->value.Simple->flags |= CMD_IGNORE_RETURN;
+       exec_result =
+         execute_simple_command (command->value.Simple, pipe_in, pipe_out,
+                                 asynchronous, fds_to_close);
+
+       /* The temporary environment should be used for only the simple
+          command immediately following its definition. */
+       dispose_used_env_vars ();
+
+#if (defined (Ultrix) && defined (mips)) || !defined (HAVE_ALLOCA)
+       /* Reclaim memory allocated with alloca () on machines which
+          may be using the alloca emulation code. */
+       (void) alloca (0);
+#endif /* (Ultrix && mips) || !HAVE_ALLOCA */
+
+       /* If we forked to do the command, then we must wait_for ()
+          the child. */
+
+       /* XXX - this is something to watch out for if there are problems
+          when the shell is compiled without job control. */
+       if (already_making_children && pipe_out == NO_PIPE &&
+           last_pid != last_made_pid)
+         {
+           stop_pipeline (asynchronous, (COMMAND *)NULL);
+
+           if (asynchronous)
+             {
+               DESCRIBE_PID (last_made_pid);
+             }
+           else
+#if !defined (JOB_CONTROL)
+             /* Do not wait for asynchronous processes started from
+                startup files. */
+           if (last_made_pid != last_asynchronous_pid)
+#endif
+           /* When executing a shell function that executes other
+              commands, this causes the last simple command in
+              the function to be waited for twice. */
+             exec_result = wait_for (last_made_pid);
+         }
+      }
+
+      if (!ignore_return && exit_immediately_on_error && !invert &&
+         (exec_result != EXECUTION_SUCCESS))
+       {
+         last_command_exit_value = exec_result;
+         run_pending_traps ();
+         longjmp (top_level, EXITPROG);
+       }
+
+      break;
+
+    case cm_connection:
+      switch (command->value.Connection->connector)
+       {
+         /* Do the first command asynchronously. */
+       case '&':
+         {
+           COMMAND *tc = command->value.Connection->first;
+           REDIRECT *rp;
+
+           if (!tc)
+             break;
+
+           rp = tc->redirects;
+
+           if (ignore_return && tc)
+             tc->flags |= CMD_IGNORE_RETURN;
+
+           /* If this shell was compiled without job control support, if
+              the shell is not running interactively, if we are currently
+              in a subshell via `( xxx )', or if job control is not active
+              then the standard input for an asynchronous command is
+              forced to /dev/null. */
+#if defined (JOB_CONTROL)
+           if ((!interactive_shell || subshell_environment || !job_control) &&
+               !stdin_redir)
+#else
+           if (!stdin_redir)
+#endif /* JOB_CONTROL */
+           {
+             REDIRECT *tr;
+
+             rd.filename = make_word ("/dev/null");
+             tr = make_redirection (0, r_inputa_direction, rd);
+             tr->next = tc->redirects;
+             tc->redirects = tr;
+           }
+
+           exec_result = execute_command_internal
+             (tc, 1, pipe_in, pipe_out, fds_to_close);
+
+#if defined (JOB_CONTROL)
+           if ((!interactive_shell || subshell_environment || !job_control) &&
+               !stdin_redir)
+#else
+           if (!stdin_redir)
+#endif /* JOB_CONTROL */
+           {
+             /* Remove the redirection we added above.  It matters,
+                especially for loops, which call execute_command ()
+                multiple times with the same command. */
+             REDIRECT *tr, *tl;
+
+             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);
+           }
+
+           {
+             register COMMAND *second;
+
+             second = command->value.Connection->second;
+
+             if (second)
+               {
+                 if (ignore_return)
+                   second->flags |= CMD_IGNORE_RETURN;
+
+                 exec_result = execute_command_internal
+                   (second, asynchronous, pipe_in, pipe_out, fds_to_close);
+               }
+           }
+         }
+         break;
+
+       case ';':
+         /* Just call execute command on both of them. */
+         if (ignore_return)
+           {
+             if (command->value.Connection->first)
+               command->value.Connection->first->flags |= CMD_IGNORE_RETURN;
+             if (command->value.Connection->second)
+               command->value.Connection->second->flags |= CMD_IGNORE_RETURN;
+           }
+         QUIT;
+         execute_command (command->value.Connection->first);
+         QUIT;
+         exec_result =
+           execute_command_internal (command->value.Connection->second,
+                                     asynchronous, pipe_in, pipe_out,
+                                     fds_to_close);
+         break;
+
+       case '|':
+         {
+           int prev, fildes[2], new_bitmap_size, dummyfd;
+           COMMAND *cmd;
+           struct fd_bitmap *fd_bitmap;
+
+#if defined (JOB_CONTROL)
+           sigset_t set, oset;
+           BLOCK_CHILD (set, oset);
+#endif /* JOB_CONTROL */
+
+           prev = pipe_in;
+           cmd = command;
+
+           while (cmd &&
+                  cmd->type == cm_connection &&
+                  cmd->value.Connection &&
+                  cmd->value.Connection->connector == '|')
+             {
+               /* Make a pipeline between the two commands. */
+               if (pipe (fildes) < 0)
+                 {
+                   report_error ("pipe error: %s", strerror (errno));
+#if defined (JOB_CONTROL)
+                   terminate_current_pipeline ();
+                   kill_current_pipeline ();
+#endif /* JOB_CONTROL */
+                   last_command_exit_value = EXECUTION_FAILURE;
+                   /* The unwind-protects installed below will take care
+                      of closing all of the open file descriptors. */
+                   throw_to_top_level ();
+                 }
+               else
+                 {
+                   /* Here is a problem: with the new file close-on-exec
+                      code, the read end of the pipe (fildes[0]) stays open
+                      in the first process, so that process will never get a
+                      SIGPIPE.  There is no way to signal the first process
+                      that it should close fildes[0] after forking, so it
+                      remains open.  No SIGPIPE is ever sent because there
+                      is still a file descriptor open for reading connected
+                      to the pipe.  We take care of that here.  This passes
+                      around a bitmap of file descriptors that must be
+                      closed after making a child process in
+                      execute_simple_command. */
+
+                   /* We need fd_bitmap to be at least as big as fildes[0].
+                      If fildes[0] is less than fds_to_close->size, then
+                      use fds_to_close->size. */
+                   if (fildes[0] < fds_to_close->size)
+                     new_bitmap_size = fds_to_close->size;
+                   else
+                     new_bitmap_size = fildes[0] + 8;
+
+                   fd_bitmap = new_fd_bitmap (new_bitmap_size);
+
+                   /* Now copy the old information into the new bitmap. */
+                   xbcopy ((char *)fds_to_close->bitmap,
+                           (char *)fd_bitmap->bitmap, fds_to_close->size);
+
+                   /* And mark the pipe file descriptors to be closed. */
+                   fd_bitmap->bitmap[fildes[0]] = 1;
+
+                   /* In case there are pipe or out-of-processes errors, we
+                      want all these file descriptors to be closed when
+                      unwind-protects are run, and the storage used for the
+                      bitmaps freed up. */
+                   begin_unwind_frame ("pipe-file-descriptors");
+                   add_unwind_protect (dispose_fd_bitmap, fd_bitmap);
+                   add_unwind_protect (close_fd_bitmap, fd_bitmap);
+                   if (prev >= 0)
+                     add_unwind_protect (close, prev);
+                   dummyfd = fildes[1];
+                   add_unwind_protect (close, dummyfd);
+
+#if defined (JOB_CONTROL)
+                   add_unwind_protect (restore_signal_mask, oset);
+#endif /* JOB_CONTROL */
+
+                   if (ignore_return && cmd->value.Connection->first)
+                     cmd->value.Connection->first->flags |=
+                       CMD_IGNORE_RETURN;
+                   execute_command_internal
+                     (cmd->value.Connection->first, asynchronous, prev,
+                      fildes[1], fd_bitmap);
+
+                   if (prev >= 0)
+                     close (prev);
+                   
+                   prev = fildes[0];
+                   close (fildes[1]);
+
+                   dispose_fd_bitmap (fd_bitmap);
+                   discard_unwind_frame ("pipe-file-descriptors");
+                 }
+               cmd = cmd->value.Connection->second;
+             }
+
+           /* Now execute the rightmost command in the pipeline.  */
+           if (ignore_return && cmd)
+             cmd->flags |= CMD_IGNORE_RETURN;
+           exec_result =
+             execute_command_internal
+               (cmd, asynchronous, prev, pipe_out, fds_to_close);
+
+           if (prev >= 0)
+             close (prev);
+
+#if defined (JOB_CONTROL)
+           UNBLOCK_CHILD (oset);
+#endif
+         }
+         break;
+
+       case AND_AND:
+       case OR_OR:
+         if (asynchronous)
+           {
+             /* If we have something like `a && b &' or `a || b &', run the
+                && or || stuff in a subshell.  Force a subshell and just call
+                execute_command_internal again.  Leave asynchronous on
+                so that we get a report from the parent shell about the
+                background job. */
+             command->flags |= CMD_FORCE_SUBSHELL;
+             exec_result = execute_command_internal (command, 1, pipe_in,
+                             pipe_out, fds_to_close);
+             break;
+           }
+
+         /* Execute the first command.  If the result of that is successful
+            and the connector is AND_AND, or the result is not successful
+            and the connector is OR_OR, then execute the second command,
+            otherwise return. */
+
+         if (command->value.Connection->first)
+           command->value.Connection->first->flags |= CMD_IGNORE_RETURN;
+
+         exec_result = execute_command (command->value.Connection->first);
+         QUIT;
+         if (((command->value.Connection->connector == AND_AND) && 
+              (exec_result == EXECUTION_SUCCESS)) ||
+             ((command->value.Connection->connector == OR_OR) &&
+              (exec_result != EXECUTION_SUCCESS)))
+           {
+             if (ignore_return && command->value.Connection->second)
+               command->value.Connection->second->flags |=
+                 CMD_IGNORE_RETURN;
+
+             exec_result =
+               execute_command (command->value.Connection->second);
+           }
+         break;
+
+       default:
+         programming_error ("Bad connector `%d'!",
+                            command->value.Connection->connector);
+         longjmp (top_level, DISCARD);
+         break;
+       }
+      break;
+
+    case cm_function_def:
+      exec_result = intern_function (command->value.Function_def->name,
+                                    command->value.Function_def->command);
+      break;
+
+    default:
+      programming_error
+       ("execute_command: Bad command type `%d'!", command->type);
+    }
+
+  if (my_undo_list)
+    {
+      do_redirections (my_undo_list, 1, 0, 0);
+      dispose_redirects (my_undo_list);
+    }
+
+  if (exec_undo_list)
+    dispose_redirects (exec_undo_list);
+
+  if (my_undo_list || exec_undo_list)
+    discard_unwind_frame ("loop_redirections");
+
+  /* Invert the return value if we have to */
+  if (invert)
+    {
+      if (exec_result == EXECUTION_SUCCESS)
+       exec_result = EXECUTION_FAILURE;
+      else
+       exec_result = EXECUTION_SUCCESS;
+    }
+
+  last_command_exit_value = exec_result;
+  run_pending_traps ();
+  return (last_command_exit_value);
+}
+
+#if defined (JOB_CONTROL)
+#  define REAP() \
+       do \
+         { \
+           if (!interactive_shell) \
+             reap_dead_jobs (); \
+         } \
+       while (0)
+#else /* !JOB_CONTROL */
+#  define REAP() \
+       do \
+         { \
+           if (!interactive_shell) \
+             cleanup_dead_jobs (); \
+         } \
+       while (0)
+#endif /* !JOB_CONTROL */
+
+
+/* Execute a FOR command.  The syntax is: FOR word_desc IN word_list;
+   DO command; DONE */
+execute_for_command (for_command)
+     FOR_COM *for_command;
+{
+  /* I just noticed that the Bourne shell leaves word_desc bound to the
+     last name in word_list after the FOR statement is done.  This seems
+     wrong to me; I thought that the variable binding should be lexically
+     scoped, i.e., only would last the duration of the FOR command.  This
+     behaviour can be gotten by turning on the lexical_scoping switch. */
+
+  register WORD_LIST *releaser, *list;
+  char *identifier;
+  SHELL_VAR *old_value = (SHELL_VAR *)NULL; /* Remember the old value of x. */
+  int retval = EXECUTION_SUCCESS;
+
+  if (check_identifier (for_command->name, 1) == 0)
+    return (EXECUTION_FAILURE);
+
+  loop_level++;
+  identifier = for_command->name->word;
+
+  list = releaser = expand_words_no_vars (for_command->map_list);
+
+  begin_unwind_frame ("for");
+  add_unwind_protect (dispose_words, releaser);
+
+  if (lexical_scoping)
+    {
+      old_value = copy_variable (find_variable (identifier));
+      if (old_value)
+       add_unwind_protect (dispose_variable, old_value);
+    }
+
+  if (for_command->flags & CMD_IGNORE_RETURN)
+    for_command->action->flags |= CMD_IGNORE_RETURN;
+
+  while (list)
+    {
+      QUIT;
+      bind_variable (identifier, list->word->word);
+      execute_command (for_command->action);
+      retval = last_command_exit_value;
+      REAP ();
+      QUIT;
+
+      if (breaking)
+       {
+         breaking--; 
+         break;
+       }
+
+      if (continuing)
+       {
+         continuing--;
+         if (continuing)
+           break;
+       }
+
+      list = list->next;
+    }
+
+  loop_level--;
+
+  if (lexical_scoping)
+    {
+      if (!old_value)
+       makunbound (identifier, shell_variables);
+      else
+       {
+         SHELL_VAR *new_value;
+
+         new_value = bind_variable (identifier, value_cell(old_value));
+         new_value->attributes = old_value->attributes;
+         dispose_variable (old_value);
+       }
+    }
+
+  dispose_words (releaser);
+  discard_unwind_frame ("for");
+  return (retval);
+}
+
+#if defined (SELECT_COMMAND)
+static int LINES, COLS, tabsize;
+
+#define RP_SPACE ") "
+#define RP_SPACE_LEN 2
+
+/* XXX - does not handle numbers > 1000000 at all. */
+#define NUMBER_LEN(s) \
+((s < 10) ? 1 \
+         : ((s < 100) ? 2 \
+                     : ((s < 1000) ? 3 \
+                                  : ((s < 10000) ? 4 \
+                                                : ((s < 100000) ? 5 \
+                                                               : 6)))))
+
+static int
+print_index_and_element (len, ind, list)
+      int len, ind;
+      WORD_LIST *list;
+{
+  register WORD_LIST *l;
+  register int i;
+
+  if (list == 0)
+    return (0);
+  i = ind;
+  l = list;
+  while (l && --i)
+    l = l->next;
+  fprintf (stderr, "%*d%s%s", len, ind, RP_SPACE, l->word->word);
+  return (STRLEN (l->word->word));
+}
+
+static void
+indent (from, to)
+     int from, to;
+{
+  while (from < to)
+    {
+      if ((to / tabsize) > (from / tabsize))
+       {
+         putc ('\t', stderr);
+         from += tabsize - from % tabsize;
+       }
+      else
+       {
+         putc (' ', stderr);
+         from++;
+       }
+    }
+}
+
+static void
+print_select_list (list, list_len, max_elem_len, indices_len)
+     WORD_LIST *list;
+     int list_len, max_elem_len, indices_len;
+{
+  int ind, row, elem_len, pos, cols, rows;
+  int first_column_indices_len, other_indices_len;
+
+  if (list == 0)
+    {
+      putc ('\n', stderr);
+      return;
+    }
+
+  cols = COLS / max_elem_len;
+  if (cols == 0)
+    cols = 1;
+  rows = list_len ? list_len / cols + (list_len % cols != 0) : 1;
+  cols = list_len ? list_len / rows + (list_len % rows != 0) : 1;
+
+  if (rows == 1)
+    {
+      rows = cols;
+      cols = 1;
+    }
+
+  first_column_indices_len = NUMBER_LEN (rows);
+  other_indices_len = indices_len;
+
+  for (row = 0; row < rows; row++)
+    {
+      ind = row;
+      pos = 0;
+      while (1)
+       {
+         indices_len = (pos == 0) ? first_column_indices_len : other_indices_len;
+         elem_len = print_index_and_element (indices_len, ind + 1, list);
+         elem_len += indices_len + RP_SPACE_LEN;
+         ind += rows;
+         if (ind >= list_len)
+           break;
+         indent (pos + elem_len, pos + max_elem_len);
+         pos += max_elem_len;
+       }
+      putc ('\n', stderr);
+    }
+}
+
+/* Print the elements of LIST, one per line, preceded by an index from 1 to
+   LIST_LEN.  Then display PROMPT and wait for the user to enter a number.
+   If the number is between 1 and LIST_LEN, return that selection.  If EOF
+   is read, return a null string.  If a blank line is entered, the loop is
+   executed again. */
+static char *
+select_query (list, list_len, prompt)
+     WORD_LIST *list;
+     int list_len;
+     char *prompt;
+{
+  int max_elem_len, indices_len, len, reply;
+  WORD_LIST *l;
+  char *repl_string, *t;
+
+  t = get_string_value ("LINES");
+  LINES = (t && *t) ? atoi (t) : 24;
+  t = get_string_value ("COLUMNS");
+  COLS =  (t && *t) ? atoi (t) : 80;
+
+#if 0
+  t = get_string_value ("TABSIZE");
+  tabsize = (t && *t) ? atoi (t) : 8;
+  if (tabsize <= 0)
+    tabsize = 8;
+#else
+  tabsize = 8;
+#endif
+
+  max_elem_len = 0;
+  for (l = list; l; l = l->next)
+    {
+      len = STRLEN (l->word->word);
+      if (len > max_elem_len)
+        max_elem_len = len;
+    }
+  indices_len = NUMBER_LEN (list_len);
+  max_elem_len += indices_len + RP_SPACE_LEN + 2;
+
+  while (1)
+    {
+      print_select_list (list, list_len, max_elem_len, indices_len);
+      printf ("%s", prompt);
+      fflush (stdout);
+      QUIT;
+
+      if (read_builtin ((WORD_LIST *)NULL) == EXECUTION_FAILURE)
+       {
+         putchar ('\n');
+         return ((char *)NULL);
+       }
+      repl_string = get_string_value ("REPLY");
+      if (*repl_string == 0)
+       continue;
+      reply = atoi (repl_string);
+      if (reply < 1 || reply > list_len)
+       return "";
+
+      l = list;
+      while (l && --reply)
+        l = l->next;
+      return (l->word->word);
+    }
+}
+
+/* Execute a SELECT command.  The syntax is:
+   SELECT word IN list DO command_list DONE
+   Only `break' or `return' in command_list will terminate
+   the command. */
+execute_select_command (select_command)
+     SELECT_COM *select_command;
+{
+  WORD_LIST *releaser, *list;
+  char *identifier, *ps3_prompt, *selection;
+  int retval, list_len, return_val;
+#if 0
+  SHELL_VAR *old_value = (SHELL_VAR *)0;
+#endif
+
+
+  retval = EXECUTION_SUCCESS;
+
+  if (check_identifier (select_command->name, 1) == 0)
+    return (EXECUTION_FAILURE);
+
+  loop_level++;
+  identifier = select_command->name->word;
+
+  /* command and arithmetic substitution, parameter and variable expansion,
+     word splitting, pathname expansion, and quote removal. */
+  list = releaser = expand_words_no_vars (select_command->map_list);
+  list_len = list_length (list);
+  if (list == 0 || list_len == 0)
+    {
+      if (list)
+       dispose_words (list);
+      return (EXECUTION_SUCCESS);
+    }
+
+  begin_unwind_frame ("select");
+  add_unwind_protect (dispose_words, releaser);
+
+#if 0
+  if (lexical_scoping)
+    {
+      old_value = copy_variable (find_variable (identifier));
+      if (old_value)
+       add_unwind_protect (dispose_variable, old_value);
+    }
+#endif
+
+  if (select_command->flags & CMD_IGNORE_RETURN)
+    select_command->action->flags |= CMD_IGNORE_RETURN;
+
+  unwind_protect_int (return_catch_flag);
+  unwind_protect_jmp_buf (return_catch);
+  return_catch_flag++;
+
+  while (1)
+    {
+      ps3_prompt = get_string_value ("PS3");
+      if (!ps3_prompt)
+       ps3_prompt = "#? ";
+
+      QUIT;
+      selection = select_query (list, list_len, ps3_prompt);
+      QUIT;
+      if (selection == 0)
+       break;
+      else
+       bind_variable (identifier, selection);
+
+      return_val = setjmp (return_catch);
+
+      if (return_val)
+        {
+         retval = return_catch_value;
+         break;
+        }
+      else
+        retval = execute_command (select_command->action);
+
+      REAP ();
+      QUIT;
+
+      if (breaking)
+       {
+         breaking--;
+         break;
+       }
+    }
+
+  loop_level--;
+
+#if 0
+  if (lexical_scoping)
+    {
+      if (!old_value)
+       makunbound (identifier, shell_variables);
+      else
+       {
+         SHELL_VAR *new_value;
+
+         new_value = bind_variable (identifier, value_cell(old_value));
+         new_value->attributes = old_value->attributes;
+         dispose_variable (old_value);
+       }
+    }
+#endif
+
+  run_unwind_frame ("select");
+  return (retval);
+}
+#endif /* SELECT_COMMAND */
+
+/* Execute a CASE command.  The syntax is: CASE word_desc IN pattern_list ESAC.
+   The pattern_list is a linked list of pattern clauses; each clause contains
+   some patterns to compare word_desc against, and an associated command to
+   execute. */
+execute_case_command (case_command)
+     CASE_COM *case_command;
+{
+  register WORD_LIST *list;
+  WORD_LIST *wlist;
+  PATTERN_LIST *clauses;
+  char *word;
+  int retval;
+
+  /* Posix.2 specifies that the WORD is tilde expanded. */
+  if (member ('~', case_command->word->word))
+    {
+      word = tilde_expand (case_command->word->word);
+      free (case_command->word->word);
+      case_command->word->word = word;
+    }
+
+  wlist = expand_word_no_split (case_command->word, 0);
+  clauses = case_command->clauses;
+  word = (wlist) ? string_list (wlist) : savestring ("");
+  retval = EXECUTION_SUCCESS;
+
+  begin_unwind_frame ("case");
+  add_unwind_protect (dispose_words, wlist);
+  add_unwind_protect ((Function *)xfree, word);
+
+  while (clauses)
+    {
+      QUIT;
+      list = clauses->patterns;
+      while (list)
+       {
+         char *pattern;
+         WORD_LIST *es;
+         int match;
+
+         /* Posix.2 specifies to tilde expand each member of the pattern
+            list. */
+         if (member ('~', list->word->word))
+           {
+             char *expansion = tilde_expand (list->word->word);
+             free (list->word->word);
+             list->word->word = expansion;
+           }
+
+         es = expand_word_leave_quoted (list->word, 0);
+
+         if (es && es->word && es->word->word && *(es->word->word))
+           pattern = quote_string_for_globbing (es->word->word, 1);
+         else
+           pattern = savestring ("");
+
+         /* Since the pattern does not undergo quote removal (as per
+            Posix.2, section 3.9.4.3), the fnmatch () call must be able
+            to recognize backslashes as escape characters. */
+         match = (fnmatch (pattern, word, 0) != FNM_NOMATCH);
+         free (pattern);
+
+         dispose_words (es);
+
+         if (match)
+           {
+             if (clauses->action && 
+                 (case_command->flags & CMD_IGNORE_RETURN))
+               clauses->action->flags |= CMD_IGNORE_RETURN;
+             execute_command (clauses->action);
+             retval = last_command_exit_value;
+             goto exit_command;
+           }
+
+         list = list->next;
+         QUIT;
+       }
+
+      clauses = clauses->next;
+    }
+
+ exit_command:
+  dispose_words (wlist);
+  free (word);  
+  discard_unwind_frame ("case");
+
+  return (retval);
+}
+
+#define CMD_WHILE 0
+#define CMD_UNTIL 1
+
+/* The WHILE command.  Syntax: WHILE test DO action; DONE.
+   Repeatedly execute action while executing test produces
+   EXECUTION_SUCCESS. */
+execute_while_command (while_command)
+     WHILE_COM *while_command;
+{
+  return (execute_while_or_until (while_command, CMD_WHILE));
+}
+
+/* UNTIL is just like WHILE except that the test result is negated. */
+execute_until_command (while_command)
+     WHILE_COM *while_command;
+{
+  return (execute_while_or_until (while_command, CMD_UNTIL));
+}
+
+/* The body for both while and until.  The only difference between the
+   two is that the test value is treated differently.  TYPE is
+   CMD_WHILE or CMD_UNTIL.  The return value for both commands should
+   be EXECUTION_SUCCESS if no commands in the body are executed, and
+   the status of the last command executed in the body otherwise. */
+execute_while_or_until (while_command, type)
+     WHILE_COM *while_command;
+     int type;
+{
+  int return_value, body_status;
+
+  body_status = EXECUTION_SUCCESS;
+  loop_level++;
+
+  while_command->test->flags |= CMD_IGNORE_RETURN;
+  if (while_command->flags & CMD_IGNORE_RETURN)
+    while_command->action->flags |= CMD_IGNORE_RETURN;
+
+  while (1)
+    {
+      return_value = execute_command (while_command->test);
+      REAP ();
+
+      if (type == CMD_WHILE && return_value != EXECUTION_SUCCESS)
+       break;
+      if (type == CMD_UNTIL && return_value == EXECUTION_SUCCESS)
+       break;
+
+      QUIT;
+      body_status = execute_command (while_command->action);
+      QUIT;
+
+      if (breaking)
+       {
+         breaking--;
+         break;
+       }
+
+      if (continuing)
+       {
+         continuing--;
+         if (continuing)
+           break;
+       }
+    }
+  loop_level--;
+
+  return (body_status);
+}
+
+/* IF test THEN command [ELSE command].
+   IF also allows ELIF in the place of ELSE IF, but
+   the parser makes *that* stupidity transparent. */
+execute_if_command (if_command)
+     IF_COM *if_command;
+{
+  int return_value;
+
+  if_command->test->flags |= CMD_IGNORE_RETURN;
+  return_value = execute_command (if_command->test);
+
+  if (return_value == EXECUTION_SUCCESS)
+    {
+      QUIT;
+      if (if_command->true_case && (if_command->flags & CMD_IGNORE_RETURN))
+         if_command->true_case->flags |= CMD_IGNORE_RETURN;
+      return (execute_command (if_command->true_case));
+    }
+  else
+    {
+      QUIT;
+
+      if (if_command->false_case && (if_command->flags & CMD_IGNORE_RETURN))
+       if_command->false_case->flags |= CMD_IGNORE_RETURN;
+
+      return (execute_command (if_command->false_case));
+    }
+}
+
+static void
+bind_lastarg (arg)
+     char *arg;
+{
+  SHELL_VAR *var;
+
+  if (!arg)
+    arg = "";
+  var = bind_variable ("_", arg);
+  var->attributes &= ~att_exported;
+}
+
+/* The meaty part of all the executions.  We have to start hacking the
+   real execution of commands here.  Fork a process, set things up,
+   execute the command. */
+execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
+     SIMPLE_COM *simple_command;
+     int pipe_in, pipe_out, async;
+     struct fd_bitmap *fds_to_close;
+{
+  WORD_LIST *words, *lastword;
+  char *command_line, *lastarg;
+  int first_word_quoted, result;
+  pid_t old_last_command_subst_pid;
+
+  result = EXECUTION_SUCCESS;
+
+  /* If we're in a function, update the pseudo-line-number information. */
+  if (variable_context)
+    line_number = simple_command->line - function_line_number;
+
+  /* Remember what this command line looks like at invocation. */
+  command_string_index = 0;
+  print_simple_command (simple_command);
+  command_line = (char *)alloca (1 + strlen (the_printed_command));
+  strcpy (command_line, the_printed_command);
+
+  first_word_quoted =
+    simple_command->words ? simple_command->words->word->quoted : 0;
+
+  old_last_command_subst_pid = last_command_subst_pid;
+
+  /* If we are re-running this as the result of executing the `command'
+     builtin, do not expand the command words a second time. */
+  if ((simple_command->flags & CMD_INHIBIT_EXPANSION) == 0)
+    {
+      current_fds_to_close = fds_to_close;
+      words = expand_words (simple_command->words);
+      current_fds_to_close = (struct fd_bitmap *)NULL;
+    }
+  else
+    words = copy_word_list (simple_command->words);
+
+  lastarg = (char *)NULL;
+
+  /* It is possible for WORDS not to have anything left in it.
+     Perhaps all the words consisted of `$foo', and there was
+     no variable `$foo'. */
+  if (words)
+    {
+      Function *builtin;
+      SHELL_VAR *func;
+
+      begin_unwind_frame ("simple-command");
+
+      if (echo_command_at_execute)
+       {
+         char *line = string_list (words);
+
+         if (line && *line)
+           fprintf (stderr, "%s%s\n", indirection_level_string (), line);
+
+         FREE (line);
+       }
+
+      if (simple_command->flags & CMD_NO_FUNCTIONS)
+       func = (SHELL_VAR *)NULL;
+      else
+       func = find_function (words->word->word);
+
+      add_unwind_protect (dispose_words, words);
+
+      QUIT;
+
+      /* Bind the last word in this command to "$_" after execution. */
+      for (lastword = words; lastword->next; lastword = lastword->next);
+      lastarg = lastword->word->word;
+
+#if defined (JOB_CONTROL)
+      /* Is this command a job control related thing? */
+      if (words->word->word[0] == '%')
+       {
+         int result;
+
+         if (async)
+           this_command_name = "bg";
+         else
+           this_command_name = "fg";
+
+         last_shell_builtin = this_shell_builtin;
+         this_shell_builtin = builtin_address (this_command_name);
+         result = (*this_shell_builtin) (words);
+         goto return_result;
+       }
+
+      /* One other possiblilty.  The user may want to resume an existing job.
+        If they do, find out whether this word is a candidate for a running
+        job. */
+      {
+       char *auto_resume_value = get_string_value ("auto_resume");
+
+       if (auto_resume_value &&
+           !first_word_quoted &&
+           !words->next &&
+           words->word->word[0] &&
+           !simple_command->redirects &&
+           pipe_in == NO_PIPE &&
+           pipe_out == NO_PIPE &&
+           !async)
+         {
+           char *word = words->word->word;
+           register int i;
+           int wl, cl, exact, substring, match, started_status;
+           register PROCESS *p;
+
+           exact = STREQ (auto_resume_value, "exact");
+           substring = STREQ (auto_resume_value, "substring");
+           wl = strlen (word);
+           for (i = job_slots - 1; i > -1; i--)
+             {
+               if (!jobs[i] || (JOBSTATE (i) != JSTOPPED))
+                 continue;
+
+               p = jobs[i]->pipe;
+               do
+                 {
+                   if (exact)
+                     {
+                       cl = strlen (p->command);
+                       match = STREQN (p->command, word, cl);
+                     }
+                   else if (substring)
+                     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");
+                   last_shell_builtin = this_shell_builtin;
+                   this_shell_builtin = builtin_address ("fg");
+
+                   started_status = start_job (i, 1);
+
+                   if (started_status < 0)
+                     return (EXECUTION_FAILURE);
+                   else
+                     return (started_status);
+                 }
+               while (p != jobs[i]->pipe);
+             }
+         }
+      }
+#endif /* JOB_CONTROL */
+
+      /* Remember the name of this command globally. */
+      this_command_name = words->word->word;
+
+      QUIT;
+
+      /* This command could be a shell builtin or a user-defined function.
+        If so, and we have pipes, then fork a subshell in here.  Else, just
+        do the command. */
+
+      if (func)
+       builtin = (Function *)NULL;
+      else
+       builtin = find_shell_builtin (this_command_name);
+
+      last_shell_builtin = this_shell_builtin;
+      this_shell_builtin = builtin;
+
+      if (builtin || func)
+       {
+         if ((pipe_in != NO_PIPE) || (pipe_out != NO_PIPE) || async)
+           {
+             if (make_child (savestring (command_line), async) == 0)
+               {
+                 /* Cancel traps, in trap.c. */
+                 restore_original_signals ();
+
+                 if (async)
+                   setup_async_signals ();
+
+                 execute_subshell_builtin_or_function
+                   (words, simple_command->redirects, builtin, func,
+                    pipe_in, pipe_out, async, fds_to_close,
+                    simple_command->flags);
+               }
+             else
+               {
+                 close_pipes (pipe_in, pipe_out);
+#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
+                 unlink_fifo_list ();
+#endif
+                 goto return_result;
+               }
+           }
+         else
+           {
+             result = execute_builtin_or_function
+               (words, builtin, func, simple_command->redirects, fds_to_close,
+                simple_command->flags);
+
+             goto return_result;
+           }
+       }
+
+      execute_disk_command (words, simple_command->redirects, command_line,
+                           pipe_in, pipe_out, async, fds_to_close,
+                           (simple_command->flags & CMD_NO_FORK));
+
+      goto return_result;
+    }
+  else if (pipe_in != NO_PIPE || pipe_out != NO_PIPE || async)
+    {
+      /* We have a null command, but we really want a subshell to take
+        care of it.  Just fork, do piping and redirections, and exit. */
+      if (make_child (savestring (""), async) == 0)
+       {
+         /* Cancel traps, in trap.c. */
+         restore_original_signals ();
+
+         do_piping (pipe_in, pipe_out);
+
+         subshell_environment = 1;
+
+         if (do_redirections (simple_command->redirects, 1, 0, 0) == 0)
+           exit (EXECUTION_SUCCESS);
+         else
+           exit (EXECUTION_FAILURE);
+       }
+      else
+       {
+         close_pipes (pipe_in, pipe_out);
+#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
+         unlink_fifo_list ();
+#endif
+         result = EXECUTION_SUCCESS;
+         goto return_result;
+       }
+    }
+  else
+    {
+      /* Even if there aren't any command names, pretend to do the
+        redirections that are specified.  The user expects the side
+        effects to take place.  If the redirections fail, then return
+        failure.  Otherwise, if a command substitution took place while
+        expanding the command or a redirection, return the value of that
+        substitution.  Otherwise, return EXECUTION_SUCCESS. */
+
+      if (do_redirections (simple_command->redirects, 0, 0, 0) != 0)
+       result = EXECUTION_FAILURE;
+      else if (old_last_command_subst_pid != last_command_subst_pid)
+       result = last_command_exit_value;
+      else
+       result = EXECUTION_SUCCESS;
+    }
+
+ return_result:
+  bind_lastarg (lastarg);
+  /* The unwind-protect frame is set up only if WORDS is not empty. */
+  if (words)
+    run_unwind_frame ("simple-command");
+  return (result);
+}
+
+static int
+execute_builtin (builtin, words, flags, subshell)
+     Function *builtin;
+     WORD_LIST *words;
+     int flags, subshell;
+{
+  int old_e_flag = exit_immediately_on_error;
+  int result;
+
+  /* The eval builtin calls parse_and_execute, which does not know about
+     the setting of flags, and always calls the execution functions with
+     flags that will exit the shell on an error if -e is set.  If the
+     eval builtin is being called, and we're supposed to ignore the exit
+     value of the command, we turn the -e flag off ourselves, then
+     restore it when the command completes. */
+  if (subshell == 0 && builtin == eval_builtin && (flags & CMD_IGNORE_RETURN))
+    {
+      begin_unwind_frame ("eval_builtin");
+      unwind_protect_int (exit_immediately_on_error);
+      exit_immediately_on_error = 0;
+    }
+
+  /* The temporary environment for a builtin is supposed to apply to
+     all commands executed by that builtin.  Currently, this is a
+     problem only with the `source' builtin. */
+  if (builtin == source_builtin)
+    {
+      if (subshell == 0)
+       begin_unwind_frame ("builtin_env");
+
+      if (temporary_env)
+       {
+         builtin_env = copy_array (temporary_env);
+         if (subshell == 0)
+           add_unwind_protect (dispose_builtin_env, (char *)NULL);
+         dispose_used_env_vars ();
+       }
+#if 0
+      else
+       builtin_env = (char **)NULL;
+#endif
+    }
+
+  result = ((*builtin) (words->next));
+
+  if (subshell == 0 && builtin == source_builtin)
+    {
+      dispose_builtin_env ();
+      discard_unwind_frame ("builtin_env");
+    }
+
+  if (subshell == 0 && builtin == eval_builtin && (flags & CMD_IGNORE_RETURN))
+    {
+      exit_immediately_on_error += old_e_flag;
+      discard_unwind_frame ("eval_builtin");
+    }
+
+  return (result);
+}
+
+/* XXX -- why do we need to set up unwind-protects for the case where
+   subshell == 1 at all? */
+static int
+execute_function (var, words, flags, fds_to_close, async, subshell)
+     SHELL_VAR *var;
+     WORD_LIST *words;
+     int flags, subshell, async;
+     struct fd_bitmap *fds_to_close;
+{
+  int return_val, result;
+  COMMAND *tc, *fc;
+
+  tc = (COMMAND *)copy_command (function_cell (var));
+  if (tc && (flags & CMD_IGNORE_RETURN))
+    tc->flags |= CMD_IGNORE_RETURN;
+
+  if (subshell)
+    begin_unwind_frame ("subshell_function_calling");
+  else
+    begin_unwind_frame ("function_calling");
+
+  if (subshell == 0)
+    {
+      push_context ();
+      add_unwind_protect (pop_context, (char *)NULL);
+      unwind_protect_int (line_number);
+    }
+  else
+    unwind_protect_int (variable_context);
+
+  unwind_protect_int (loop_level);
+  unwind_protect_int (return_catch_flag);
+  unwind_protect_jmp_buf (return_catch);
+  add_unwind_protect (dispose_command, (char *)tc);
+
+  /* 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);
+      add_unwind_protect (dispose_function_env, (char *)NULL);
+      dispose_used_env_vars ();
+    }
+#if 0
+  else
+    function_env = (char **)NULL;
+#endif
+
+  /* Note the second argument of "1", meaning that we discard
+     the current value of "$*"!  This is apparently the right thing. */
+  remember_args (words->next, 1);
+
+  line_number = function_line_number = tc->line;
+
+  if (subshell)
+    {
+#if defined (JOB_CONTROL)
+      stop_pipeline (async, (COMMAND *)NULL);
+#endif
+      if (tc->type == cm_group)
+       fc = tc->value.Group->command;
+      else
+       fc = tc;
+
+      if (fc && (flags & CMD_IGNORE_RETURN))
+       fc->flags |= CMD_IGNORE_RETURN;
+
+      variable_context++;
+    }
+  else
+    fc = tc;
+
+  return_catch_flag++;
+  return_val = setjmp (return_catch);
+
+  if (return_val)
+    result = return_catch_value;
+  else
+    result = execute_command_internal (fc, 0, NO_PIPE, NO_PIPE, fds_to_close);
+
+  if (subshell)
+    run_unwind_frame ("subshell_function_calling");
+  else
+    run_unwind_frame ("function_calling");
+
+  return (result);
+}
+
+/* Execute a shell builtin or function in a subshell environment.  This
+   routine does not return; it only calls exit().  If BUILTIN is non-null,
+   it points to a function to call to execute a shell builtin; otherwise
+   VAR points at the body of a function to execute.  WORDS is the arguments
+   to the command, REDIRECTS specifies redirections to perform before the
+   command is executed. */
+static void
+execute_subshell_builtin_or_function (words, redirects, builtin, var,
+                                     pipe_in, pipe_out, async, fds_to_close,
+                                     flags)
+     WORD_LIST *words;
+     REDIRECT *redirects;
+     Function *builtin;
+     SHELL_VAR *var;
+     int pipe_in, pipe_out, async;
+     struct fd_bitmap *fds_to_close;
+     int flags;
+{
+  /* A subshell is neither a login shell nor interactive. */
+  login_shell = interactive = 0;
+
+  subshell_environment = 1;
+
+  maybe_make_export_env ();
+
+#if defined (JOB_CONTROL)
+  /* Eradicate all traces of job control after we fork the subshell, so
+     all jobs begun by this subshell are in the same process group as
+     the shell itself. */
+
+  /* Allow the output of `jobs' to be piped. */
+  if (builtin == jobs_builtin && !async &&
+      (pipe_out != NO_PIPE || pipe_in != NO_PIPE))
+    kill_current_pipeline ();
+  else
+    without_job_control ();
+
+  set_sigchld_handler ();
+#endif /* JOB_CONTROL */
+
+  set_sigint_handler ();
+
+  do_piping (pipe_in, pipe_out);
+
+  if (fds_to_close)
+    close_fd_bitmap (fds_to_close);
+
+  if (do_redirections (redirects, 1, 0, 0) != 0)
+    exit (EXECUTION_FAILURE);
+
+  if (builtin)
+    {
+      int result;
+
+      /* Give builtins a place to jump back to on failure,
+        so we don't go back up to main(). */
+      result = setjmp (top_level);
+
+      if (result == EXITPROG)
+       exit (last_command_exit_value);
+      else if (result)
+       exit (EXECUTION_FAILURE);
+      else
+       exit (execute_builtin (builtin, words, flags, 1));
+    }
+  else
+    {
+      exit (execute_function (var, words, flags, fds_to_close, async, 1));
+    }
+}
+
+/* Execute a builtin or function in the current shell context.  If BUILTIN
+   is non-null, it is the builtin command to execute, otherwise VAR points
+   to the body of a function.  WORDS are the command's arguments, REDIRECTS
+   are the redirections to perform.  FDS_TO_CLOSE is the usual bitmap of
+   file descriptors to close.
+
+   If BUILTIN is exec_builtin, the redirections specified in REDIRECTS are
+   not undone before this function returns. */
+static int
+execute_builtin_or_function (words, builtin, var, redirects,
+                            fds_to_close, flags)
+     WORD_LIST *words;
+     Function *builtin;
+     SHELL_VAR *var;
+     REDIRECT *redirects;
+     struct fd_bitmap *fds_to_close;
+     int flags;
+{
+  int result = EXECUTION_FAILURE;
+  REDIRECT *saved_undo_list;
+
+  if (do_redirections (redirects, 1, 1, 0) != 0)
+    {
+      cleanup_redirects (redirection_undo_list);
+      redirection_undo_list = (REDIRECT *)NULL;
+      dispose_exec_redirects ();
+      return (EXECUTION_FAILURE);
+    }
+
+  saved_undo_list = redirection_undo_list;
+
+  /* Calling the "exec" builtin changes redirections forever. */
+  if (builtin == exec_builtin)
+    {
+      dispose_redirects (saved_undo_list);
+      saved_undo_list = exec_redirection_undo_list;
+      exec_redirection_undo_list = (REDIRECT *)NULL;
+    }
+  else
+    dispose_exec_redirects ();
+
+  if (saved_undo_list)
+    {
+      begin_unwind_frame ("saved redirects");
+      add_unwind_protect (cleanup_func_redirects, (char *)saved_undo_list);
+      add_unwind_protect (dispose_redirects, (char *)saved_undo_list);
+    }
+
+  redirection_undo_list = (REDIRECT *)NULL;
+
+  if (builtin)
+    result = execute_builtin (builtin, words, flags, 0);
+  else
+    result = execute_function (var, words, flags, fds_to_close, 0, 0);
+
+  if (saved_undo_list)
+    {
+      redirection_undo_list = saved_undo_list;
+      discard_unwind_frame ("saved redirects");
+    }
+
+  if (redirection_undo_list)
+    {
+      do_redirections (redirection_undo_list, 1, 0, 0);
+      dispose_redirects (redirection_undo_list);
+      redirection_undo_list = (REDIRECT *)NULL;
+    }
+
+  return (result);
+}
+
+void
+setup_async_signals ()
+{
+#if defined (JOB_CONTROL)
+  if (job_control == 0)
+#endif
+    {
+      set_signal_handler (SIGINT, SIG_IGN);
+      set_signal_ignored (SIGINT);
+      set_signal_handler (SIGQUIT, SIG_IGN);
+      set_signal_ignored (SIGQUIT);
+    }
+}
+
+/* Execute a simple command that is hopefully defined in a disk file
+   somewhere.
+
+   1) fork ()
+   2) connect pipes
+   3) look up the command
+   4) do redirections
+   5) execve ()
+   6) If the execve failed, see if the file has executable mode set.
+   If so, and it isn't a directory, then execute its contents as
+   a shell script.
+
+   Note that the filename hashing stuff has to take place up here,
+   in the parent.  This is probably why the Bourne style shells
+   don't handle it, since that would require them to go through
+   this gnarly hair, for no good reason.  */
+static void
+execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
+                     async, fds_to_close, nofork)
+     WORD_LIST *words;
+     REDIRECT *redirects;
+     char *command_line;
+     int pipe_in, pipe_out, async;
+     struct fd_bitmap *fds_to_close;
+     int nofork;       /* Don't fork, just exec, if no pipes */
+{
+  register char *pathname;
+  char *hashed_file, *command, **args;
+  int pid, temp_path;
+  SHELL_VAR *path;
+
+  pathname = words->word->word;
+#if defined (RESTRICTED_SHELL)
+  if (restricted && strchr (pathname, '/'))
+    {
+      report_error ("%s: restricted: cannot specify `/' in command names",
+                   pathname);
+      last_command_exit_value = EXECUTION_FAILURE;
+      return;
+    }
+#endif /* RESTRICTED_SHELL */
+
+  hashed_file = command = (char *)NULL;
+
+  /* If PATH is in the temporary environment for this command, don't use the
+     hash table to search for the full pathname. */
+  temp_path = 0;
+  path = find_tempenv_variable ("PATH");
+  if (path)
+    temp_path = 1;
+
+  /* Don't waste time trying to find hashed data for a pathname
+     that is already completely specified. */
+
+  if (!path && !absolute_program (pathname))
+    hashed_file = find_hashed_filename (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
+     every command found in the hash table.  It seems pretty stupid to me,
+     so I am basing it on the presence of POSIXLY_CORRECT. */
+
+  if (hashed_file && posixly_correct)
+    {
+      int st;
+
+      st = file_status (hashed_file);
+      if ((st ^ (FS_EXISTS | FS_EXECABLE)) != 0)
+       {
+         remove_hashed_filename (pathname);
+         hashed_file = (char *)NULL;
+       }
+    }
+
+  if (hashed_file)
+    command = savestring (hashed_file);
+  else if (absolute_program (pathname))
+    /* A command containing a slash is not looked up in PATH or saved in
+       the hash table. */
+    command = savestring (pathname);
+  else
+    {
+      command = find_user_command (pathname);
+      if (command && !hashing_disabled && !temp_path)
+       remember_filename (pathname, command, dot_found_in_search, 1);
+    }
+
+  maybe_make_export_env ();
+
+  if (command)
+    put_command_name_into_env (command);
+
+  /* We have to make the child before we check for the non-existance
+     of COMMAND, since we want the error messages to be redirected. */
+  /* If we can get away without forking and there are no pipes to deal with,
+     don't bother to fork, just directly exec the command. */
+  if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
+    pid = 0;
+  else
+    pid = make_child (savestring (command_line), async);
+
+  if (pid == 0)
+    {
+      int old_interactive;
+
+      /* Cancel traps, in trap.c. */
+      restore_original_signals ();
+
+      /* restore_original_signals may have undone the work done
+         by make_child to ensure that SIGINT and SIGQUIT are ignored
+         in asynchronous children. */
+      if (async)
+       setup_async_signals ();
+
+      do_piping (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 = make_word_array (words);
+
+      if (async)
+       {
+         old_interactive = interactive;
+         interactive = 0;
+       }
+
+      subshell_environment = 1;
+
+      /* This functionality is now provided by close-on-exec of the
+        file descriptors manipulated by redirection and piping.
+        Some file descriptors still need to be closed in all children
+        because of the way bash does pipes; fds_to_close is a 
+        bitmap of all such file descriptors. */
+      if (fds_to_close)
+       close_fd_bitmap (fds_to_close);
+
+      if (redirects && (do_redirections (redirects, 1, 0, 0) != 0))
+       {
+#if defined (PROCESS_SUBSTITUTION)
+         /* Try to remove named pipes that may have been created as the
+            result of redirections. */
+         unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+         exit (EXECUTION_FAILURE);
+       }
+
+      if (async)
+       interactive = old_interactive;
+
+      if (!command)
+       {
+         report_error ("%s: command not found", args[0]);
+         exit (EX_NOTFOUND);   /* Posix.2 says the exit status is 127 */
+       }
+
+      exit (shell_execve (command, args, export_env));
+    }
+  else
+    {
+      /* Make sure that the pipes are closed in the parent. */
+      close_pipes (pipe_in, pipe_out);
+#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
+      unlink_fifo_list ();
+#endif
+      FREE (command);
+    }
+}
+
+/* If the operating system on which we're running does not handle
+   the #! executable format, then help out.  SAMPLE is the text read
+   from the file, SAMPLE_LEN characters.  COMMAND is the name of
+   the script; it and ARGS, the arguments given by the user, will
+   become arguments to the specified interpreter.  ENV is the environment
+   to pass to the interpreter.
+
+   The word immediately following the #! is the interpreter to execute.
+   A single argument to the interpreter is allowed. */
+static int
+execute_shell_script (sample, sample_len, command, args, env)
+     unsigned char *sample;
+     int sample_len;
+     char *command;
+     char **args, **env;
+{
+  register int i;
+  char *execname, *firstarg;
+  int start, size_increment, larry;
+
+  /* Find the name of the interpreter to exec. */
+  for (i = 2; whitespace (sample[i]) && i < sample_len; i++)
+    ;
+
+  for (start = i;
+       !whitespace (sample[i]) && sample[i] != '\n' && i < sample_len;
+       i++)
+    ;
+
+  execname = xmalloc (1 + (i - start));
+  strncpy (execname, (char *) (sample + start), i - start);
+  execname[i - start] = '\0';
+  size_increment = 1;
+
+  /* Now the argument, if any. */
+  firstarg = (char *)NULL;
+  for (start = i;
+       whitespace (sample[i]) && sample[i] != '\n' && i < sample_len;
+       i++)
+    ;
+
+  /* If there is more text on the line, then it is an argument for the
+     interpreter. */
+  if (i < sample_len && sample[i] != '\n' && !whitespace (sample[i]))
+    {
+      for (start = i;
+          !whitespace (sample[i]) && sample[i] != '\n' && i < sample_len;
+          i++)
+       ;
+      firstarg = xmalloc (1 + (i - start));
+      strncpy (firstarg, (char *)(sample + start), i - start);
+      firstarg[i - start] = '\0';
+
+      size_increment = 2;
+    }
+
+  larry = array_len (args) + size_increment;
+
+  args = (char **)xrealloc ((char *)args, (1 + larry) * sizeof (char *));
+
+  for (i = larry - 1; i; i--)
+    args[i] = args[i - size_increment];
+
+  args[0] = execname;
+  if (firstarg)
+    {
+      args[1] = firstarg;
+      args[2] = command;
+    }
+  else
+    args[1] = command;
+
+  args[larry] = (char *)NULL;
+
+  return (shell_execve (execname, args, env));
+}
+
+/* Call execve (), handling interpreting shell scripts, and handling
+   exec failures. */
+int
+shell_execve (command, args, env)
+     char *command;
+     char **args, **env;
+{
+#if defined (isc386) && defined (_POSIX_SOURCE)
+  __setostype (0);             /* Turn on USGr3 semantics. */
+  execve (command, args, env);
+  __setostype (1);             /* Turn the POSIX semantics back on. */
+#else
+  execve (command, args, env);
+#endif /* !(isc386 && _POSIX_SOURCE) */
+
+  /* If we get to this point, then start checking out the file.
+     Maybe it is something we can hack ourselves. */
+  {
+    struct stat finfo;
+
+    if (errno != ENOEXEC)
+      {
+       if ((stat (command, &finfo) == 0) &&
+           (S_ISDIR (finfo.st_mode)))
+         report_error ("%s: is a directory", args[0]);
+       else
+         file_error (command);
+
+       return (EX_NOEXEC);     /* XXX Posix.2 says that exit status is 126 */
+      }
+    else
+      {
+       /* This file is executable.
+          If it begins with #!, then help out people with losing operating
+          systems.  Otherwise, check to see if it is a binary file by seeing
+          if the first line (or up to 30 characters) are in the ASCII set.
+          Execute the contents as shell commands. */
+       int larray = array_len (args) + 1;
+       int i, should_exec = 0;
+
+       {
+         int fd = open (command, O_RDONLY);
+         if (fd != -1)
+           {
+             unsigned char sample[80];
+             int sample_len = read (fd, &sample[0], 80);
+
+             close (fd);
+
+             if (sample_len == 0)
+               return (EXECUTION_SUCCESS);
+
+             /* Is this supposed to be an executable script?
+                If so, the format of the line is "#! interpreter [argument]".
+                A single argument is allowed.  The BSD kernel restricts
+                the length of the entire line to 32 characters (32 bytes
+                being the size of the BSD exec header), but we allow 80
+                characters. */
+
+             if (sample_len > 0 && sample[0] == '#' && sample[1] == '!')
+               return (execute_shell_script
+                       (sample, sample_len, command, args, env));
+             else if ((sample_len != -1) &&
+                      check_binary_file (sample, sample_len))
+               {
+                 report_error ("%s: cannot execute binary file", command);
+                 return (EX_BINARY_FILE);
+               }
+           }
+       }
+#if defined (JOB_CONTROL)
+       /* Forget about the way that job control was working. We are
+          in a subshell. */
+       without_job_control ();
+#endif /* JOB_CONTROL */
+#if defined (ALIAS)
+       /* Forget about any aliases that we knew of.  We are in a subshell. */
+       delete_all_aliases ();
+#endif /* ALIAS */
+
+#if defined (JOB_CONTROL)
+       set_sigchld_handler ();
+#endif /* JOB_CONTROL */
+       set_sigint_handler ();
+
+       /* Insert the name of this shell into the argument list. */
+       args = (char **)xrealloc ((char *)args, (1 + larray) * sizeof (char *));
+
+       for (i = larray - 1; i; i--)
+         args[i] = args[i - 1];
+
+       args[0] = shell_name;
+       args[1] = command;
+       args[larray] = (char *)NULL;
+
+       if (args[0][0] == '-')
+         args[0]++;
+
+       if (should_exec)
+         {
+           struct stat finfo;
+
+#if defined (isc386) && defined (_POSIX_SOURCE)
+           __setostype (0);    /* Turn on USGr3 semantics. */
+           execve (shell_name, args, env);
+           __setostype (1);    /* Turn the POSIX semantics back on. */
+#else
+           execve (shell_name, args, env);
+#endif /* isc386 && _POSIX_SOURCE */
+
+           /* Oh, no!  We couldn't even exec this! */
+           if ((stat (args[0], &finfo) == 0) && (S_ISDIR (finfo.st_mode)))
+             report_error ("%s: is a directory", args[0]);
+           else
+             file_error (args[0]);
+
+           return (EXECUTION_FAILURE);
+         }
+       else
+         {
+           subshell_argc = larray;
+           subshell_argv = args;
+           subshell_envp = env;
+           longjmp (subshell_top_level, 1);
+         }
+      }
+  }
+}
+
+#if defined (PROCESS_SUBSTITUTION)
+/* Currently unused */
+void
+close_all_files ()
+{
+  register int i, fd_table_size;
+
+  fd_table_size = getdtablesize ();
+  if (fd_table_size > 256)     /* clamp to a reasonable value */
+       fd_table_size = 256;
+
+  for (i = 3; i < fd_table_size; i++)
+    close (i);
+}
+#endif /* PROCESS_SUBSTITUTION */
+
+static void
+close_pipes (in, out)
+     int in, out;
+{
+  if (in >= 0)
+    close (in);
+  if (out >= 0)
+    close (out);
+}
+
+/* Redirect input and output to be from and to the specified pipes.
+   NO_PIPE and REDIRECT_BOTH are handled correctly. */
+static void
+do_piping (pipe_in, pipe_out)
+     int pipe_in, pipe_out;
+{
+  if (pipe_in != NO_PIPE)
+    {
+      if (dup2 (pipe_in, 0) < 0)
+       internal_error ("cannot duplicate fd %d to fd 0: %s",
+                       pipe_in, strerror (errno));
+      if (pipe_in > 0)
+        close (pipe_in);
+    }
+  if (pipe_out != NO_PIPE)
+    {
+      if (pipe_out != REDIRECT_BOTH)
+       {
+         if (dup2 (pipe_out, 1) < 0)
+           internal_error ("cannot duplicate fd %d to fd 1: %s",
+                           pipe_out, strerror (errno));
+         if (pipe_out == 0 || pipe_out > 1)
+           close (pipe_out);
+       }
+      else
+       dup2 (1, 2);
+    }
+}
+
+#define AMBIGUOUS_REDIRECT  -1
+#define NOCLOBBER_REDIRECT  -2
+#define RESTRICTED_REDIRECT -3 /* Only can happen in restricted shells. */
+
+/* Perform the redirections on LIST.  If FOR_REAL, then actually make
+   input and output file descriptors, otherwise just do whatever is
+   neccessary for side effecting.  INTERNAL says to remember how to
+   undo the redirections later, if non-zero.  If SET_CLEXEC is non-zero,
+   file descriptors opened in do_redirection () have their close-on-exec
+   flag set. */
+static int
+do_redirections (list, for_real, internal, set_clexec)
+     REDIRECT *list;
+     int for_real, internal, set_clexec;
+{
+  register int error;
+  register REDIRECT *temp = list;
+
+  if (internal)
+    {
+      if (redirection_undo_list)
+       {
+         dispose_redirects (redirection_undo_list);
+         redirection_undo_list = (REDIRECT *)NULL;
+       }
+      if (exec_redirection_undo_list)
+       dispose_exec_redirects ();
+    }
+
+  while (temp)
+    {
+      error = do_redirection_internal (temp, for_real, internal, set_clexec);
+
+      if (error)
+       {
+         char *filename;
+
+         if (expandable_redirection_filename (temp))
+           {
+             if (posixly_correct && !interactive_shell)
+               disallow_filename_globbing++;
+             filename = redirection_expand (temp->redirectee.filename);
+             if (posixly_correct && !interactive_shell)
+               disallow_filename_globbing--;
+
+             if (!filename)
+               filename = savestring ("");
+           }
+         else
+           filename = itos (temp->redirectee.dest);
+
+         switch (error)
+           {
+           case AMBIGUOUS_REDIRECT:
+             report_error ("%s: Ambiguous redirect", filename);
+             break;
+
+           case NOCLOBBER_REDIRECT:
+             report_error ("%s: Cannot clobber existing file", filename);
+             break;
+
+#if defined (RESTRICTED_SHELL)
+           case RESTRICTED_REDIRECT:
+             report_error ("%s: output redirection restricted", filename);
+             break;
+#endif /* RESTRICTED_SHELL */
+
+           default:
+             report_error ("%s: %s", filename, strerror (error));
+             break;
+           }
+
+         free (filename);
+         return (error);
+       }
+
+      temp = temp->next;
+    }
+  return (0);
+}
+
+/* Return non-zero if the redirection pointed to by REDIRECT has a
+   redirectee.filename that can be expanded. */
+static int
+expandable_redirection_filename (redirect)
+     REDIRECT *redirect;
+{
+  int result;
+
+  switch (redirect->instruction)
+    {
+    case r_output_direction:
+    case r_appending_to:
+    case r_input_direction:
+    case r_inputa_direction:
+    case r_err_and_out:
+    case r_input_output:
+    case r_output_force:
+    case r_duplicating_input_word:
+    case r_duplicating_output_word:
+      result = 1;
+      break;
+
+    default:
+      result = 0;
+    }
+  return (result);
+}
+\f
+/* Expand the word in WORD returning a string.  If WORD expands to
+   multiple words (or no words), then return NULL. */
+char *
+redirection_expand (word)
+     WORD_DESC *word;
+{
+  char *result;
+  WORD_LIST *tlist1, *tlist2;
+
+  tlist1 = make_word_list (copy_word (word), (WORD_LIST *)NULL);
+  tlist2 = expand_words_no_vars (tlist1);
+  dispose_words (tlist1);
+
+  if (!tlist2 || tlist2->next)
+    {
+      /* We expanded to no words, or to more than a single word.
+        Dispose of the word list and return NULL. */
+      if (tlist2)
+       dispose_words (tlist2);
+      return ((char *)NULL);
+    }
+  result = string_list (tlist2);
+  dispose_words (tlist2);
+  return (result);
+}
+
+/* Do the specific redirection requested.  Returns errno in case of error.
+   If FOR_REAL is zero, then just do whatever is neccessary to produce the
+   appropriate side effects.   REMEMBERING, if non-zero, says to remember
+   how to undo each redirection.  If SET_CLEXEC is non-zero, then
+   we set all file descriptors > 2 that we open to be close-on-exec.  */
+static int
+do_redirection_internal (redirect, for_real, remembering, set_clexec)
+     REDIRECT *redirect;
+     int for_real, remembering, set_clexec;
+{
+  WORD_DESC *redirectee = redirect->redirectee.filename;
+  int redir_fd = redirect->redirectee.dest;
+  int fd, redirector = redirect->redirector;
+  char *redirectee_word;
+  enum r_instruction ri = redirect->instruction;
+  REDIRECT *new_redirect;
+
+  if (ri == r_duplicating_input_word || ri == r_duplicating_output_word)
+    {
+      /* We have [N]>&WORD or [N]<&WORD.  Expand WORD, then translate
+        the redirection into a new one and continue. */
+      redirectee_word = redirection_expand (redirectee);
+
+      if (redirectee_word[0] == '-' && redirectee_word[1] == '\0')
+       {
+         rd.dest = 0L;
+         new_redirect = make_redirection (redirector, r_close_this, rd);
+       }
+      else if (all_digits (redirectee_word))
+       {
+         if (ri == r_duplicating_input_word)
+           {
+             rd.dest = atol (redirectee_word);
+             new_redirect = make_redirection (redirector, r_duplicating_input, rd);
+           }
+         else
+           {
+             rd.dest = atol (redirectee_word);
+             new_redirect = make_redirection (redirector, r_duplicating_output, rd);
+           }
+       }
+      else if (ri == r_duplicating_output_word && redirector == 1)
+       {
+         if (!posixly_correct)
+           {
+             rd.filename = make_word (redirectee_word);
+             new_redirect = make_redirection (1, r_err_and_out, rd);
+           }
+         else
+           new_redirect = copy_redirect (redirect);
+       }
+      else
+       {
+         free (redirectee_word);
+         return (AMBIGUOUS_REDIRECT);
+       }
+
+      free (redirectee_word);
+
+      /* Set up the variables needed by the rest of the function from the
+        new redirection. */
+      if (new_redirect->instruction == r_err_and_out)
+       {
+         char *alloca_hack;
+
+         /* Copy the word without allocating any memory that must be
+            explicitly freed. */
+         redirectee = (WORD_DESC *)alloca (sizeof (WORD_DESC));
+         xbcopy ((char *)new_redirect->redirectee.filename,
+                (char *)redirectee, sizeof (WORD_DESC));
+
+         alloca_hack = (char *)
+           alloca (1 + strlen (new_redirect->redirectee.filename->word));
+         redirectee->word = alloca_hack;
+         strcpy (redirectee->word, new_redirect->redirectee.filename->word);
+       }
+      else
+       /* It's guaranteed to be an integer, and shouldn't be freed. */
+       redirectee = new_redirect->redirectee.filename;
+
+      redir_fd = new_redirect->redirectee.dest;
+      redirector = new_redirect->redirector;
+      ri = new_redirect->instruction;
+
+      /* Overwrite the flags element of the old redirect with the new value. */
+      redirect->flags = new_redirect->flags;
+      dispose_redirects (new_redirect);
+    }
+
+  switch (ri)
+    {
+    case r_output_direction:
+    case r_appending_to:
+    case r_input_direction:
+    case r_inputa_direction:
+    case r_err_and_out:                /* command &>filename */
+    case r_input_output:
+    case r_output_force:
+
+      if (posixly_correct && !interactive_shell)
+       disallow_filename_globbing++;
+      redirectee_word = redirection_expand (redirectee);
+      if (posixly_correct && !interactive_shell)
+       disallow_filename_globbing--;
+      
+      if (!redirectee_word)
+       return (AMBIGUOUS_REDIRECT);
+
+#if defined (RESTRICTED_SHELL)
+      if (restricted && (ri == r_output_direction ||
+                        ri == r_input_output ||
+                        ri == r_err_and_out ||
+                        ri == r_appending_to ||
+                        ri == r_output_force))
+       {
+         free (redirectee_word);
+         return (RESTRICTED_REDIRECT);
+       }
+#endif /* RESTRICTED_SHELL */
+
+      /* If we are in noclobber mode, you are not allowed to overwrite
+        existing files.  Check first. */
+      if (noclobber && (ri == r_output_direction ||
+                     ri == r_input_output ||
+                     ri == r_err_and_out))
+       {
+         struct stat finfo;
+         int stat_result;
+
+         stat_result = stat (redirectee_word, &finfo);
+
+         if ((stat_result == 0) && (S_ISREG (finfo.st_mode)))
+           {
+             free (redirectee_word);
+             return (NOCLOBBER_REDIRECT);
+           }
+
+         /* If the file was not present, make sure we open it exclusively
+            so that if it is created before we open it, our open will fail. */
+         if (stat_result != 0)
+           redirect->flags |= O_EXCL;
+
+         fd = open (redirectee_word, redirect->flags, 0666);
+
+         if ((fd < 0) && (errno == EEXIST))
+           {
+             free (redirectee_word);
+             return (NOCLOBBER_REDIRECT);
+           }
+       }
+      else
+       {
+         fd = open (redirectee_word, redirect->flags, 0666);
+#if defined (AFS_CREATE_BUG)
+         if ((fd < 0) && (errno == EACCES))
+           fd = open (redirectee_word, (redirect->flags & ~O_CREAT), 0666);
+#endif /* AFS_CREATE_BUG */
+       }
+      free (redirectee_word);
+
+      if (fd < 0)
+       return (errno);
+
+      if (for_real)
+       {
+         if (remembering)
+           /* Only setup to undo it if the thing to undo is active. */
+           if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
+             add_undo_redirect (redirector);
+           else
+             add_undo_close_redirect (redirector);
+
+#if defined (BUFFERED_INPUT)
+         check_bash_input (redirector);
+#endif
+
+         if ((fd != redirector) && (dup2 (fd, redirector) < 0))
+           return (errno);
+
+#if defined (BUFFERED_INPUT)
+         /* Do not change the buffered stream for an implicit redirection
+            of /dev/null to fd 0 for asynchronous commands without job
+            control (r_inputa_direction). */
+         if (ri == r_input_direction || ri == r_input_output)
+           duplicate_buffered_stream (fd, redirector);
+#endif /* BUFFERED_INPUT */
+
+         /*
+          * If we're remembering, then this is the result of a while, for
+          * or until loop with a loop redirection, or a function/builtin
+          * executing in the parent shell with a redirection.  In the
+          * function/builtin case, we want to set all file descriptors > 2
+          * to be close-on-exec to duplicate the effect of the old
+          * for i = 3 to NOFILE close(i) loop.  In the case of the loops,
+          * both sh and ksh leave the file descriptors open across execs.
+          * The Posix standard mentions only the exec builtin.
+          */
+         if (set_clexec && (redirector > 2))
+           SET_CLOSE_ON_EXEC (redirector);
+       }
+
+      if (fd != redirector)
+       {
+#if defined (BUFFERED_INPUT)
+         if (ri == r_input_direction || ri == r_inputa_direction ||
+             ri == r_input_output)
+           close_buffered_fd (fd);
+         else
+#endif /* !BUFFERED_INPUT */
+           close (fd);         /* Don't close what we just opened! */
+       }
+
+      /* If we are hacking both stdout and stderr, do the stderr
+        redirection here. */
+      if (ri == r_err_and_out)
+       {
+         if (for_real)
+           {
+             if (remembering)
+               add_undo_redirect (2);
+             if (dup2 (1, 2) < 0)
+               return (errno);
+           }
+       }
+      break;
+
+    case r_reading_until:
+    case r_deblank_reading_until:
+      /* REDIRECTEE is a pointer to a WORD_DESC containing the text of
+        the new input.  Place it in a temporary file. */
+      if (redirectee)
+       {
+         char filename[40];
+         pid_t pid = getpid ();
+
+         /* Make the filename for the temp file. */
+         sprintf (filename, "/tmp/t%d-sh", pid);
+
+         fd = open (filename, O_TRUNC | O_WRONLY | O_CREAT, 0666);
+         if (fd < 0)
+           return (errno);
+
+         errno = 0;            /* XXX */
+         if (redirectee->word)
+           {
+             char *document;
+             int document_len;
+
+             /* Expand the text if the word that was specified had
+                no quoting.  The text that we expand is treated
+                exactly as if it were surrounded by double quotes. */
+
+             if (redirectee->quoted)
+               {
+                 document = redirectee->word;
+                 document_len = strlen (document);
+                 /* Set errno to something reasonable if the write fails. */
+                 if (write (fd, document, document_len) < document_len)
+                   {
+                     if (errno == 0)
+                       errno = ENOSPC;
+                     close (fd);
+                     return (errno);
+                   }
+               }
+             else
+               {
+                 WORD_LIST *tlist;
+                 tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT);
+                 if (tlist)
+                   {
+                     int fd2;
+                     FILE *fp;
+                     register WORD_LIST *t;
+
+                     /* Try using buffered I/O (stdio) and writing a word
+                        at a time, letting stdio do the work of buffering
+                        for us rather than managing our own strings.  Most
+                        stdios are not particularly fast, however -- this
+                        may need to be reconsidered later. */
+                     if ((fd2 = dup (fd)) < 0 ||
+                         (fp = fdopen (fd2, "w")) == NULL)
+                       {
+                         if (fd2 >= 0)
+                           close (fd2);
+                         close (fd);
+                         return (errno);
+                       }
+                     errno = 0;        /* XXX */
+                     for (t = tlist; t; t = t->next)
+                       {
+                         /* This is essentially the body of
+                            string_list_internal expanded inline. */
+                         document = t->word->word;
+                         document_len = strlen (document);
+                         if (t != tlist)
+                           putc (' ', fp);     /* separator */
+                         fwrite (document, document_len, 1, fp);
+                         if (ferror (fp))
+                           {
+                             if (errno == 0)
+                               errno = ENOSPC;
+                             break;
+                           }
+                       }
+                     fclose (fp);
+                     dispose_words (tlist);
+                   }
+               }
+           }     
+
+         close (fd);
+         if (errno)
+           return (errno);
+
+         /* Make the document really temporary.  Also make it the input. */
+         fd = open (filename, O_RDONLY, 0666);
+
+         if (unlink (filename) < 0 || fd < 0)
+           {
+             if (fd >= 0)
+               close (fd);
+             return (errno);
+           }
+
+         if (for_real)
+           {
+             if (remembering)
+               /* Only setup to undo it if the thing to undo is active. */
+               if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
+                 add_undo_redirect (redirector);
+               else
+                 add_undo_close_redirect (redirector);
+
+#if defined (BUFFERED_INPUT)
+             check_bash_input (redirector);
+#endif
+             if (dup2 (fd, redirector) < 0)
+               {
+                 close (fd);
+                 return (errno);
+               }
+
+#if defined (BUFFERED_INPUT)
+             duplicate_buffered_stream (fd, redirector);
+#endif
+
+             if (set_clexec && (redirector > 2))
+               SET_CLOSE_ON_EXEC (redirector);
+           }
+
+#if defined (BUFFERED_INPUT)
+         close_buffered_fd (fd);
+#else
+         close (fd);
+#endif
+       }
+      break;
+
+    case r_duplicating_input:
+    case r_duplicating_output:
+      if (for_real && (redir_fd != redirector))
+       {
+         if (remembering)
+           /* Only setup to undo it if the thing to undo is active. */
+           if (fcntl (redirector, F_GETFD, 0) != -1)
+             add_undo_redirect (redirector);
+           else
+             add_undo_close_redirect (redirector);
+
+#if defined (BUFFERED_INPUT)
+         check_bash_input (redirector);
+#endif
+         /* This is correct.  2>&1 means dup2 (1, 2); */
+         if (dup2 (redir_fd, redirector) < 0)
+           return (errno);
+
+#if defined (BUFFERED_INPUT)
+         if (ri == r_duplicating_input)
+           duplicate_buffered_stream (redir_fd, redirector);
+#endif /* BUFFERED_INPUT */
+
+         /* First duplicate the close-on-exec state of redirectee.  dup2
+            leaves the flag unset on the new descriptor, which means it
+            stays open.  Only set the close-on-exec bit for file descriptors
+            greater than 2 in any case, since 0-2 should always be open
+            unless closed by something like `exec 2<&-'. */
+         /* if ((already_set || set_unconditionally) && (ok_to_set))
+               set_it () */
+         if (((fcntl (redir_fd, F_GETFD, 0) == 1) || set_clexec) &&
+              (redirector > 2))
+           SET_CLOSE_ON_EXEC (redirector);
+       }
+      break;
+
+    case r_close_this:
+      if (for_real)
+       {
+         if (remembering && (fcntl (redirector, F_GETFD, 0) != -1))
+           add_undo_redirect (redirector);
+
+#if defined (BUFFERED_INPUT)
+         check_bash_input (redirector);
+         close_buffered_fd (redirector);
+#else /* !BUFFERED_INPUT */
+         close (redirector);
+#endif /* !BUFFERED_INPUT */
+       }
+      break;
+    }
+  return (0);
+}
+
+#define SHELL_FD_BASE  10
+
+/* Remember the file descriptor associated with the slot FD,
+   on REDIRECTION_UNDO_LIST.  Note that the list will be reversed
+   before it is executed.  Any redirections that need to be undone
+   even if REDIRECTION_UNDO_LIST is discarded by the exec builtin
+   are also saved on EXEC_REDIRECTION_UNDO_LIST. */
+static int
+add_undo_redirect (fd)
+     int fd;
+{
+  int new_fd, clexec_flag;
+  REDIRECT *new_redirect, *closer;
+
+  new_fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE);
+
+  if (new_fd < 0)
+    {
+      file_error ("redirection error");
+      return (-1);
+    }
+  else
+    {
+      REDIRECT *dummy_redirect;
+
+      clexec_flag = fcntl (fd, F_GETFD, 0);
+
+      rd.dest = 0L;
+      closer = make_redirection (new_fd, r_close_this, rd);
+      dummy_redirect = copy_redirects (closer);
+
+      rd.dest = (long)new_fd;
+      new_redirect = make_redirection (fd, r_duplicating_output, rd);
+      new_redirect->next = closer;
+
+      closer->next = redirection_undo_list;
+      redirection_undo_list = new_redirect;
+
+      /* Save redirections that need to be undone even if the undo list
+        is thrown away by the `exec' builtin. */
+      add_exec_redirect (dummy_redirect);
+
+      /* File descriptors used only for saving others should always be
+        marked close-on-exec.  Unfortunately, we have to preserve the
+        close-on-exec state of the file descriptor we are saving, since
+        fcntl (F_DUPFD) sets the new file descriptor to remain open
+        across execs.  If, however, the file descriptor whose state we
+        are saving is <= 2, we can just set the close-on-exec flag,
+        because file descriptors 0-2 should always be open-on-exec,
+        and the restore above in do_redirection() will take care of it. */
+      if (clexec_flag || fd < 3)
+       SET_CLOSE_ON_EXEC (new_fd);
+    }
+  return (0);
+}
+
+/* Set up to close FD when we are finished with the current command
+   and its redirections. */
+static void
+add_undo_close_redirect (fd)
+     int fd;
+{
+  REDIRECT *closer;
+
+  rd.dest = 0L;
+  closer = make_redirection (fd, r_close_this, rd);
+  closer->next = redirection_undo_list;
+  redirection_undo_list = closer;
+}
+
+static void
+add_exec_redirect (dummy_redirect)
+     REDIRECT *dummy_redirect;
+{
+  dummy_redirect->next = exec_redirection_undo_list;
+  exec_redirection_undo_list = dummy_redirect;
+}
+
+intern_function (name, function)
+     WORD_DESC *name;
+     COMMAND *function;
+{
+  SHELL_VAR *var;
+
+  if (!check_identifier (name, posixly_correct))
+    return (EXECUTION_FAILURE);
+
+  var = find_function (name->word);
+  if (var && readonly_p (var))
+    {
+      report_error ("%s: readonly function", var->name);
+      return (EXECUTION_FAILURE);
+    }
+
+  bind_function (name->word, function);
+  return (EXECUTION_SUCCESS);
+}
+
+#define u_mode_bits(x) (((x) & 0000700) >> 6)
+#define g_mode_bits(x) (((x) & 0000070) >> 3)
+#define o_mode_bits(x) (((x) & 0000007) >> 0)
+#define X_BIT(x) ((x) & 1)
+
+/* Return some flags based on information about this file.
+   The EXISTS bit is non-zero if the file is found.
+   The EXECABLE bit is non-zero the file is executble.
+   Zero is returned if the file is not found. */
+int
+file_status (name)
+     char *name;
+{
+  struct stat finfo;
+  static int user_id = -1;
+
+  /* Determine whether this file exists or not. */
+  if (stat (name, &finfo) < 0)
+    return (0);
+
+  /* If the file is a directory, then it is not "executable" in the
+     sense of the shell. */
+  if (S_ISDIR (finfo.st_mode))
+    return (FS_EXISTS);
+
+#if defined (AFS)
+  /* We have to use access(2) to determine access because AFS does not
+     support Unix file system semantics.  This may produce wrong
+     answers for non-AFS files when ruid != euid.  I hate AFS. */
+  if (access (name, X_OK) == 0)
+    return (FS_EXISTS | FS_EXECABLE);
+  else
+    return (FS_EXISTS);
+#else /* !AFS */
+
+  /* Find out if the file is actually executable.  By definition, the
+     only other criteria is that the file has an execute bit set that
+     we can use. */
+  if (user_id == -1)
+    user_id = current_user.euid;
+
+  /* Root only requires execute permission for any of owner, group or
+     others to be able to exec a file. */
+  if (user_id == 0)
+    {
+      int bits;
+
+      bits = (u_mode_bits (finfo.st_mode) |
+             g_mode_bits (finfo.st_mode) |
+             o_mode_bits (finfo.st_mode));
+
+      if (X_BIT (bits))
+       return (FS_EXISTS | FS_EXECABLE);
+    }
+
+  /* If we are the owner of the file, the owner execute bit applies. */
+  if (user_id == finfo.st_uid && X_BIT (u_mode_bits (finfo.st_mode)))
+    return (FS_EXISTS | FS_EXECABLE);
+
+  /* If we are in the owning group, the group permissions apply. */
+  if (group_member (finfo.st_gid) && X_BIT (g_mode_bits (finfo.st_mode)))
+    return (FS_EXISTS | FS_EXECABLE);
+
+  /* If `others' have execute permission to the file, then so do we,
+     since we are also `others'. */
+  if (X_BIT (o_mode_bits (finfo.st_mode)))
+    return (FS_EXISTS | FS_EXECABLE);
+  else
+    return (FS_EXISTS);
+#endif /* !AFS */
+}
+
+/* Return non-zero if FILE exists and is executable.
+   Note that this function is the definition of what an
+   executable file is; do not change this unless YOU know
+   what an executable file is. */
+int
+executable_file (file)
+     char *file;
+{
+  return (file_status (file) & FS_EXECABLE);
+}
+
+/* DOT_FOUND_IN_SEARCH becomes non-zero when find_user_command ()
+   encounters a `.' as the directory pathname while scanning the
+   list of possible pathnames; i.e., if `.' comes before the directory
+   containing the file of interest. */
+int dot_found_in_search = 0;
+
+/* Locate the executable file referenced by NAME, searching along
+   the contents of the shell PATH variable.  Return a new string
+   which is the full pathname to the file, or NULL if the file
+   couldn't be found.  If a file is found that isn't executable,
+   and that is the only match, then return that. */
+char *
+find_user_command (name)
+     char *name;
+{
+  return (find_user_command_internal (name, FS_EXEC_PREFERRED));
+}
+
+/* Locate the file referenced by NAME, searching along the contents
+   of the shell PATH variable.  Return a new string which is the full
+   pathname to the file, or NULL if the file couldn't be found.  This
+   returns the first file found. */
+char *
+find_path_file (name)
+     char *name;
+{
+  return (find_user_command_internal (name, FS_EXISTS));
+}
+
+static char *
+find_user_command_internal (name, flags)
+     char *name;
+     int flags;
+{
+  char *path_list;
+  SHELL_VAR *var;
+
+  /* Search for the value of PATH in both the temporary environment, and
+     in the regular list of variables. */
+  if (var = find_variable_internal ("PATH", 1))
+    path_list = value_cell (var);
+  else
+    path_list = (char *)NULL;
+
+  if (path_list == 0 || *path_list == '\0')
+    return (savestring (name));
+
+  return (find_user_command_in_path (name, path_list, flags));
+}
+
+/* Return the next element from PATH_LIST, a colon separated list of
+   paths.  PATH_INDEX_POINTER is the address of an index into PATH_LIST;
+   the index is modified by this function.
+   Return the next element of PATH_LIST or NULL if there are no more. */
+static char *
+get_next_path_element (path_list, path_index_pointer)
+     char *path_list;
+     int *path_index_pointer;
+{
+  char *path;
+
+  path = extract_colon_unit (path_list, path_index_pointer);
+
+  if (!path)
+    return (path);
+
+  if (!*path)
+    {
+      free (path);
+      path = savestring (".");
+    }
+
+  return (path);
+}
+
+char *
+user_command_matches (name, flags, state)
+     char *name;
+     int flags, state;
+{
+  register int i;
+  char *path_list;
+  int  path_index;
+  char *path_element;
+  char *match;
+  static char **match_list = NULL;
+  static int match_list_size = 0;
+  static int match_index = 0;
+
+  if (!state)
+    {
+      /* Create the list of matches. */
+      if (!match_list)
+       {
+         match_list =
+           (char **) xmalloc ((match_list_size = 5) * sizeof(char *));
+
+         for (i = 0; i < match_list_size; i++)
+           match_list[i] = 0;
+       }
+
+      /* Clear out the old match list. */
+      for (i = 0; i < match_list_size; i++)
+       match_list[i] = NULL;
+
+      /* We haven't found any files yet. */
+      match_index = 0;
+
+      path_list = get_string_value ("PATH");
+      path_index = 0;
+
+      while (path_list && path_list[path_index])
+       {
+         path_element = get_next_path_element (path_list, &path_index);
+
+         if (!path_element)
+           break;
+
+         match = find_user_command_in_path (name, path_element, flags);
+
+         free (path_element);
+
+         if (!match)
+           continue;
+
+         if (match_index + 1 == match_list_size)
+           match_list = (char **)xrealloc
+             (match_list, ((match_list_size += 10) + 1) * sizeof (char *));
+         match_list[match_index++] = match;
+         match_list[match_index] = (char *)NULL;
+       }
+
+      /* We haven't returned any strings yet. */
+      match_index = 0;
+    }
+
+  match = match_list[match_index];
+
+  if (match)
+    match_index++;
+
+  return (match);
+}
+
+/* Return 1 if PATH1 and PATH2 are the same file.  This is kind of
+   expensive.  If non-NULL STP1 and STP2 point to stat structures
+   corresponding to PATH1 and PATH2, respectively. */
+int
+same_file (path1, path2, stp1, stp2)
+     char *path1, *path2;
+     struct stat *stp1, *stp2;
+{
+  struct stat st1, st2;
+
+  if (stp1 == NULL)
+    {
+      if (stat (path1, &st1) != 0)
+       return (0);
+      stp1 = &st1;
+    }
+
+  if (stp2 == NULL)
+    {
+      if (stat (path2, &st2) != 0)
+       return (0);
+      stp2 = &st2;
+    }
+
+  return ((stp1->st_dev == stp2->st_dev) && (stp1->st_ino == stp2->st_ino));
+}
+
+/* Turn PATH, a directory, and NAME, a filename, into a full pathname.
+   This allocates new memory and returns it. */
+static char *
+make_full_pathname (path, name, name_len)
+     char *path, *name;
+     int name_len;
+{
+  char *full_path;
+  int path_len;
+
+  path_len = strlen (path);
+  full_path = xmalloc (2 + path_len + name_len);
+  strcpy (full_path, path);
+  full_path[path_len] = '/';
+  strcpy (full_path + path_len + 1, name);
+  return (full_path);
+}
+  
+/* This does the dirty work for find_path_file () and find_user_command ().
+   NAME is the name of the file to search for.
+   PATH_LIST is a colon separated list of directories to search.
+   FLAGS contains bit fields which control the files which are eligible.
+   Some values are:
+      FS_EXEC_ONLY:            The file must be an executable to be found.
+      FS_EXEC_PREFERRED:       If we can't find an executable, then the
+                               the first file matching NAME will do.
+      FS_EXISTS:               The first file found will do.
+*/
+static char *
+find_user_command_in_path (name, path_list, flags)
+     char *name;
+     char *path_list;
+     int flags;
+{
+  char *full_path, *path, *file_to_lose_on;
+  int status, path_index, name_len;
+  struct stat finfo;
+
+  name_len = strlen (name);
+
+  /* The file name which we would try to execute, except that it isn't
+     possible to execute it.  This is the first file that matches the
+     name that we are looking for while we are searching $PATH for a
+     suitable one to execute.  If we cannot find a suitable executable
+     file, then we use this one. */
+  file_to_lose_on = (char *)NULL;
+
+  /* We haven't started looking, so we certainly haven't seen
+     a `.' as the directory path yet. */
+  dot_found_in_search = 0;
+
+  if (absolute_program (name))
+    {
+      full_path = xmalloc (1 + name_len);
+      strcpy (full_path, name);
+
+      status = file_status (full_path);
+
+      /* If the file doesn't exist, quit now. */
+      if (!(status & FS_EXISTS))
+       {
+         free (full_path);
+         return ((char *)NULL);
+       }
+
+      /* If we only care about whether the file exists or not, return
+        this filename. */
+      if (flags & FS_EXISTS)
+       return (full_path);
+
+      /* Otherwise, maybe we care about whether this file is executable.
+        If it is, and that is what we want, return it. */
+      if ((flags & FS_EXEC_ONLY) && (status & FS_EXECABLE))
+       return (full_path);
+      else
+       {
+         free (full_path);
+         return ((char *)NULL);
+       }
+    }
+
+  /* Find out the location of the current working directory. */
+  stat (".", &finfo);
+
+  path_index = 0;
+  while (path_list && path_list[path_index])
+    {
+      /* Allow the user to interrupt out of a lengthy path search. */
+      QUIT;
+
+      path = get_next_path_element (path_list, &path_index);
+
+      if (!path)
+       break;
+
+      if (*path == '~')
+       {
+         char *t = tilde_expand (path);
+         free (path);
+         path = t;
+       }
+
+      /* Remember the location of "." in the path, in all its forms
+        (as long as they begin with a `.', e.g. `./.') */
+      if (!dot_found_in_search && (*path == '.') &&
+         same_file (".", path, &finfo, (struct stat *)NULL))
+       dot_found_in_search = 1;
+
+      full_path = make_full_pathname (path, name, name_len);
+      free (path);
+
+      status = file_status (full_path);
+
+      if (!(status & FS_EXISTS))
+       goto next_file;
+
+      /* The file exists.  If the caller simply wants the first file,
+        here it is. */
+      if (flags & FS_EXISTS)
+       return (full_path);
+
+       /* If the file is executable, then it satisfies the cases of
+         EXEC_ONLY and EXEC_PREFERRED.  Return this file unconditionally. */
+      if (status & FS_EXECABLE)
+       {
+         FREE (file_to_lose_on);
+
+         return (full_path);
+       }
+
+      /* The file is not executable, but it does exist.  If we prefer
+        an executable, then remember this one if it is the first one
+        we have found. */
+      if (flags & FS_EXEC_PREFERRED)
+       {
+         if (!file_to_lose_on)
+           file_to_lose_on = savestring (full_path);
+       }
+
+    next_file:
+      free (full_path);
+    }
+
+  /* We didn't find exactly what the user was looking for.  Return
+     the contents of FILE_TO_LOSE_ON which is NULL when the search
+     required an executable, or non-NULL if a file was found and the
+     search would accept a non-executable as a last resort. */
+  return (file_to_lose_on);
+}
+
+/* Given a string containing units of information separated by colons,
+   return the next one pointed to by (P_INDEX), or NULL if there are no more.
+   Advance (P_INDEX) to the character after the colon. */
+char *
+extract_colon_unit (string, p_index)
+     char *string;
+     int *p_index;
+{
+  int i, start;
+
+  i = *p_index;
+
+  if (!string || (i >= (int)strlen (string)))
+    return ((char *)NULL);
+
+  /* Each call to this routine leaves the index pointing at a colon if
+     there is more to the path.  If I is > 0, then increment past the
+     `:'.  If I is 0, then the path has a leading colon.  Trailing colons
+     are handled OK by the `else' part of the if statement; an empty
+     string is returned in that case. */
+  if (i && string[i] == ':')
+    i++;
+
+  start = i;
+
+  while (string[i] && string[i] != ':') i++;
+
+  *p_index = i;
+
+  if (i == start)
+    {
+      if (string[i])
+       (*p_index)++;
+
+      /* Return "" in the case of a trailing `:'. */
+      return (savestring (""));
+    }
+  else
+    {
+      char *value;
+
+      value = xmalloc (1 + i - start);
+      strncpy (value, string + start, i - start);
+      value [i - start] = '\0';
+
+      return (value);
+    }
+}
+
+/* Return non-zero if the characters from SAMPLE are not all valid
+   characters to be found in the first line of a shell script.  We
+   check up to the first newline, or SAMPLE_LEN, whichever comes first.
+   All of the characters must be printable or whitespace. */
+
+#if !defined (isspace)
+#define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\f')
+#endif
+
+#if !defined (isprint)
+#define isprint(c) (isletter(c) || digit(c) || ispunct(c))
+#endif
+
+int
+check_binary_file (sample, sample_len)
+     unsigned char *sample;
+     int sample_len;
+{
+  register int i;
+
+  for (i = 0; i < sample_len; i++)
+    {
+      if (sample[i] == '\n')
+       break;
+
+      if (!isspace (sample[i]) && !isprint (sample[i]))
+       return (1);
+    }
+  return (0);
+}
diff --git a/execute_cmd.h b/execute_cmd.h
new file mode 100644 (file)
index 0000000..e096103
--- /dev/null
@@ -0,0 +1,47 @@
+/* execute_cmd.h - functions from execute_cmd.c. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_EXECUTE_CMD_H_)
+#define _EXECUTE_CMD_H_
+
+#include "stdc.h"
+
+extern struct fd_bitmap *new_fd_bitmap __P((long));
+extern void dispose_fd_bitmap __P((struct fd_bitmap *));
+extern void close_fd_bitmap __P((struct fd_bitmap *));
+extern int execute_command __P((COMMAND *));
+extern int execute_command_internal __P((COMMAND *, int, int, int, struct fd_bitmap *));
+extern int shell_execve __P((char *, char **, char **));
+extern char *redirection_expand __P((WORD_DESC *));
+extern int file_status __P((char *));
+extern int executable_file __P((char *));
+extern char *find_user_command __P((char *));
+extern char *find_path_file __P((char *));
+extern char *user_command_matches __P((char *, int, int));
+extern int same_file __P((char *, char *, struct stat *, struct stat *));
+extern char *extract_colon_unit __P((char *, int *));
+extern int check_binary_file __P((unsigned char *, int));
+extern void setup_async_signals __P((void));
+
+#if defined (PROCESS_SUBSTITUTION)
+extern void close_all_files __P((void));
+#endif
+
+#endif /* _EXECUTE_CMD_H_ */
diff --git a/expr.c b/expr.c
new file mode 100644 (file)
index 0000000..5f9eb6d
--- /dev/null
+++ b/expr.c
@@ -0,0 +1,902 @@
+/* expr.c -- arithmetic expression evaluation. */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ All arithmetic is done as long 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
+ order of decreasing precedence.
+
+       "-", "+"                [(unary operators)]
+       "!", "~"
+       "*", "/", "%"
+       "+", "-"
+       "<<", ">>"
+       "<=", ">=", "<", ">"
+       "==", "!="
+       "&"
+       "^"
+       "|"
+       "&&"
+       "||"
+       "="
+
+ (Note that most of these operators have special meaning to bash, and an
+ entire expression should be quoted, e.g. "a=$a+1" or "a=a+1" to ensure
+ that it is passed intact to the evaluator when using `let'.  When using
+ the $[] or $(( )) forms, the text between the `[' and `]' or `((' and `))'
+ is treated as if in double quotes.)
+
+ Sub-expressions within parentheses have a precedence level greater than
+ all of the above levels and are evaluated first.  Within a single prece-
+ dence group, evaluation is left-to-right, except for the arithmetic
+ assignment operator (`='), which is evaluated right-to-left (as in C).
+
+ The expression evaluator returns the value of the expression (assignment
+ statements have as a value what is returned by the RHS).  The `let'
+ builtin, on the other hand, returns 0 if the last expression evaluates to
+ a non-zero, and 1 otherwise.
+
+ Implementation is a recursive-descent parser.
+
+ Chet Ramey
+ chet@ins.CWRU.Edu
+*/
+
+#include <stdio.h>
+#include "bashansi.h"
+#include "shell.h"
+
+#define variable_starter(c) (isletter(c) || (c == '_'))
+#define variable_character(c) (isletter(c) || (c == '_') || digit(c))
+
+/* Because of the $((...)) construct, expressions may include newlines.
+   Here is a macro which accepts newlines, tabs and spaces as whitespace. */
+#define cr_whitespace(c) (whitespace(c) || ((c) == '\n'))
+
+extern char    *this_command_name;
+
+static char    *expression = (char *) NULL;    /* The current expression */
+static char    *tp = (char *) NULL;            /* token lexical position */
+static char    *lasttp;
+static int     curtok = 0;                     /* the current token */
+static int     lasttok = 0;                    /* the previous token */
+static int     assigntok = 0;                  /* the OP in OP= */
+static char    *tokstr = (char *) NULL;        /* current token string */
+static int     tokval = 0;                     /* current token value */
+static jmp_buf evalbuf;
+
+static void    readtok ();                     /* lexical analyzer */
+static long    expassign (), exp0 (), exp1 (), exp2 (), exp3 (),
+               exp4 (), exp5 (), expshift (), expland (), explor (),
+               expband (), expbor (), expbxor ();
+static long    strlong ();
+static void    evalerror ();
+
+/* A structure defining a single expression context. */
+typedef struct {
+  int curtok, lasttok;
+  char *expression, *tp;
+  int tokval;
+  char *tokstr;
+} EXPR_CONTEXT;
+
+/* Global var which contains the stack of expression contexts. */
+static EXPR_CONTEXT **expr_stack;
+static int expr_depth = 0;        /* Location in the stack. */
+static int expr_stack_size = 0;           /* Number of slots already allocated. */
+
+/* Size be which the expression stack grows when neccessary. */
+#define EXPR_STACK_GROW_SIZE 10
+
+/* Maximum amount of recursion allowed.  This prevents a non-integer
+   variable such as "num=num+2" from infinitely adding to itself when
+   "let num=num+2" is given.  I have to talk to Chet about this hack. */
+#define MAX_EXPR_RECURSION_LEVEL 1024
+
+/* The Tokens.  Singing "The Lion Sleeps Tonight". */
+
+#define EQEQ   1       /* "==" */
+#define NEQ    2       /* "!=" */
+#define LEQ    3       /* "<=" */
+#define GEQ    4       /* ">=" */
+#define STR    5       /* string */
+#define NUM    6       /* number */
+#define LAND   7       /* "&&" Logical AND */
+#define LOR    8       /* "||" Logical OR */
+#define LSH    9       /* "<<" Left SHift */
+#define RSH    10      /* ">>" Right SHift */
+#define OP_ASSIGN 11   /* op= expassign as in Posix.2 */
+#define EQ     '='
+#define GT     '>'
+#define LT     '<'
+#define PLUS   '+'
+#define MINUS  '-'
+#define MUL    '*'
+#define DIV    '/'
+#define MOD    '%'
+#define NOT    '!'
+#define LPAR   '('
+#define RPAR   ')'
+#define BAND   '&'     /* Bitwise AND */
+#define BOR    '|'     /* Either Bitwise OR, or what Chet is. */
+#define BXOR   '^'     /* Bitwise eXclusive OR. */
+#define BNOT   '~'     /* Bitwise NOT; Two's complement. */
+
+/* Push and save away the contents of the globals describing the
+   current expression context. */
+static void
+pushexp ()
+{
+  EXPR_CONTEXT *context;
+
+  context = (EXPR_CONTEXT *)xmalloc (sizeof (EXPR_CONTEXT));
+
+  if (expr_depth >= MAX_EXPR_RECURSION_LEVEL)
+    evalerror ("expression recursion level exceeded");
+
+  if (expr_depth >= expr_stack_size)
+    {
+      expr_stack = (EXPR_CONTEXT **)
+       xrealloc (expr_stack, (expr_stack_size += EXPR_STACK_GROW_SIZE)
+                 * sizeof (EXPR_CONTEXT *));
+    }
+
+  context->curtok = curtok;
+  context->lasttok = lasttok;
+  context->expression = expression;
+  context->tp = tp;
+  context->tokval = tokval;
+  context->tokstr = tokstr;
+  expr_stack[expr_depth++] = context;
+}
+
+/* Pop the the contents of the expression context stack into the
+   globals describing the current expression context. */
+static void
+popexp ()
+{
+  EXPR_CONTEXT *context;
+
+  if (expr_depth == 0)
+    evalerror ("Recursion stack underflow");
+
+  context = expr_stack[--expr_depth];
+  curtok = context->curtok;
+  lasttok = context->lasttok;
+  expression = context->expression;
+  tp = context->tp;
+  tokval = context->tokval;
+  tokstr = context->tokstr;
+  free (context);
+}
+
+/* Evaluate EXPR, and return the arithmetic result.
+
+   The `while' loop after the longjmp is caught relies on the above
+   implementation of pushexp and popexp leaving in expr_stack[0] the
+   values that the variables had when the program started.  That is,
+   the first things saved are the initial values of the variables that 
+   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
+evalexp (expr)
+     char *expr;
+{
+  long val = 0L;
+  jmp_buf old_evalbuf;
+  char *p;
+
+  for (p = expr; p && *p && cr_whitespace (*p); p++)
+    ;
+
+  if (p == NULL || *p == '\0')
+    return (0);
+
+  /* Save the value of evalbuf to protect it around possible recursive
+     calls to evalexp (). */
+  xbcopy ((char *)evalbuf, (char *)old_evalbuf, sizeof (jmp_buf));
+
+  if (setjmp (evalbuf))
+    {
+      if (tokstr)              /* Clean up local allocation. */
+       free (tokstr);
+
+      if (expression)
+       free (expression);
+
+      while (--expr_depth)
+       {
+         if (expr_stack[expr_depth]->tokstr)
+           free (expr_stack[expr_depth]->tokstr);
+
+         if (expr_stack[expr_depth]->expression)
+           free (expr_stack[expr_depth]->expression);
+       }
+      longjmp (top_level, DISCARD);
+    }
+
+  pushexp ();
+  curtok = lasttok = 0;
+  expression = savestring (expr);
+  tp = expression;
+
+  tokstr = (char *)NULL;
+  tokval = 0l;
+
+  readtok ();
+
+  val = expassign ();
+
+  if (curtok != 0) 
+    evalerror ("syntax error in expression");
+
+  if (tokstr)
+    free (tokstr);
+  if (expression)
+    free (expression);
+
+  popexp ();
+
+  /* Restore the value of evalbuf so that any subsequent longjmp calls
+     will have a valid location to jump to. */
+  xbcopy ((char *)old_evalbuf, (char *)evalbuf, sizeof (jmp_buf));
+
+  return (val);
+}
+
+/* Bind/create a shell variable with the name LHS to the RHS.
+   This creates or modifies a variable such that it is an integer.
+
+   This should really be in variables.c, but it is here so that all of the
+   expression evaluation stuff is localized.  Since we don't want any
+   recursive evaluation from bind_variable() (possible without this code,
+   since bind_variable() calls the evaluator for variables with the integer
+   attribute set), we temporarily turn off the integer attribute for each
+   variable we set here, then turn it back on after binding as necessary. */
+
+void
+bind_int_variable (lhs, rhs)
+     char *lhs, *rhs;
+{
+  register SHELL_VAR *v;
+  int isint = 0;
+
+  v = find_variable (lhs);
+  if (v)
+    {
+      isint = integer_p (v);
+      v->attributes &= ~att_integer;
+    }
+
+  v = bind_variable (lhs, rhs);
+  if (isint)
+    v->attributes |= att_integer;
+}
+
+static long
+expassign ()
+{
+  register long        value;
+  char *lhs, *rhs;
+
+  value = explor ();
+  if (curtok == EQ || curtok == OP_ASSIGN)
+    {
+      int special = curtok == OP_ASSIGN;
+      int op;
+      long lvalue;
+
+      if (lasttok != STR)
+       evalerror ("attempted expassign to non-variable");
+
+      if (special)
+       {
+         op = assigntok;               /* a OP= b */
+         lvalue = value;
+       }
+
+      lhs = savestring (tokstr);
+      readtok ();
+      value = expassign ();
+
+      if (special)
+       {
+         switch (op)
+           {
+           case MUL:
+             lvalue *= value;
+             break;
+           case DIV:
+             lvalue /= value;
+             break;
+           case MOD:
+             lvalue %= value;
+             break;
+           case PLUS:
+             lvalue += value;
+             break;
+           case MINUS:
+             lvalue -= value;
+             break;
+           case LSH:
+             lvalue <<= value;
+             break;
+           case RSH:
+             lvalue >>= value;
+             break;
+           case BAND:
+             lvalue &= value;
+             break;
+           case BOR:
+             lvalue |= value;
+             break;
+           default:
+             evalerror ("bug: bad expassign token %d", assigntok);
+             break;
+           }
+         value = lvalue;
+       }
+
+      rhs = itos (value);
+      bind_int_variable (lhs, rhs);
+      free (rhs);
+      free (lhs);
+      free (tokstr);
+      tokstr = (char *)NULL;           /* For freeing on errors. */
+    }
+  return (value);
+}
+
+/* Logical OR. */
+static long
+explor ()
+{
+  register long val1, val2;
+
+  val1 = expland ();
+
+  while (curtok == LOR)
+    {
+      readtok ();
+      val2 = expland ();
+      val1 = val1 || val2;
+    }
+
+  return (val1);
+}
+
+/* Logical AND. */
+static long
+expland ()
+{
+  register long val1, val2;
+
+  val1 = expbor ();
+
+  while (curtok == LAND)
+    {
+      readtok ();
+      val2 = expbor ();
+      val1 = val1 && val2;
+    }
+
+  return (val1);
+}
+
+/* Bitwise OR. */
+static long
+expbor ()
+{
+  register long val1, val2;
+
+  val1 = expbxor ();
+
+  while (curtok == BOR)
+    {
+      readtok ();
+      val2 = expbxor ();
+      val1 = val1 | val2;
+    }
+
+  return (val1);
+}
+
+/* Bitwise XOR. */
+static long
+expbxor ()
+{
+  register long val1, val2;
+
+  val1 = expband ();
+
+  while (curtok == BXOR)
+    {
+      readtok ();
+      val2 = expband ();
+      val1 = val1 ^ val2;
+    }
+
+  return (val1);
+}
+
+/* Bitwise AND. */
+static long
+expband ()
+{
+  register long val1, val2;
+
+  val1 = exp5 ();
+
+  while (curtok == BAND)
+    {
+      readtok ();
+      val2 = exp5 ();
+      val1 = val1 & val2;
+    }
+
+  return (val1);
+}
+
+static long
+exp5 ()
+{
+  register long val1, val2;
+
+  val1 = exp4 ();
+
+  while ((curtok == EQEQ) || (curtok == NEQ))
+    {
+      int op = curtok;
+
+      readtok ();
+      val2 = exp4 ();
+      if (op == EQEQ)
+       val1 = (val1 == val2);
+      else if (op == NEQ)
+       val1 = (val1 != val2);
+    }
+  return (val1);
+}
+
+static long
+exp4 ()
+{
+  register long val1, val2;
+
+  val1 = expshift ();
+  while ((curtok == LEQ) ||
+        (curtok == GEQ) ||
+        (curtok == LT) ||
+        (curtok == GT))
+    {
+      int op = curtok;
+
+      readtok ();
+      val2 = expshift ();
+
+      if (op == LEQ)
+       val1 = val1 <= val2;
+      else if (op == GEQ)
+       val1 = val1 >= val2;
+      else if (op == LT)
+       val1 = val1 < val2;
+      else if (op == GT)
+       val1 = val1 > val2;
+    }
+  return (val1);
+}
+
+/* Left and right shifts. */
+static long
+expshift ()
+{
+  register long val1, val2;
+
+  val1 = exp3 ();
+
+  while ((curtok == LSH) || (curtok == RSH))
+    {
+      int op = curtok;
+
+      readtok ();
+      val2 = exp3 ();
+
+      if (op == LSH)
+       val1 = val1 << val2;
+      else
+       val1 = val1 >> val2;
+    }
+
+  return (val1);
+}
+
+static long
+exp3 ()
+{
+  register long val1, val2;
+
+  val1 = exp2 ();
+
+  while ((curtok == PLUS) || (curtok == MINUS))
+    {
+      int op = curtok;
+
+      readtok ();
+      val2 = exp2 ();
+
+      if (op == PLUS)
+       val1 += val2;
+      else if (op == MINUS)
+       val1 -= val2;
+    }
+  return (val1);
+}
+
+static long
+exp2 ()
+{
+  register long val1, val2;
+
+  val1 = exp1 ();
+
+  while ((curtok == MUL) ||
+         (curtok == DIV) ||
+         (curtok == MOD))
+    {
+      int op = curtok;
+
+      readtok ();
+
+      val2 = exp1 ();
+
+      if (((op == DIV) || (op == MOD)) && (val2 == 0))
+       evalerror ("division by 0");
+
+      if (op == MUL)
+        val1 *= val2;
+      else if (op == DIV)
+        val1 /= val2;
+      else if (op == MOD)
+        val1 %= val2;
+    }
+  return (val1);
+}
+
+static long
+exp1 ()
+{
+  register long val;
+
+  if (curtok == NOT)
+    {
+      readtok ();
+      val = !exp1 ();
+    }
+  else if (curtok == BNOT)
+    {
+      readtok ();
+      val = ~exp1 ();
+    }
+  else
+    val = exp0 ();
+
+  return (val);
+}
+
+static long
+exp0 ()
+{
+  register long val = 0L;
+
+  if (curtok == MINUS)
+    {
+      readtok ();
+      val = - exp0 ();
+    }
+  else if (curtok == PLUS)
+    {
+      readtok ();
+      val = exp0 ();
+    }
+  else if (curtok == LPAR)
+    {
+      readtok ();
+      val = expassign ();
+
+      if (curtok != RPAR)
+       evalerror ("missing `)'");
+
+      /* Skip over closing paren. */
+      readtok ();
+    }
+  else if ((curtok == NUM) || (curtok == STR))
+    {
+      val = tokval;
+      readtok ();
+    }
+  else
+    evalerror ("syntax error in expression");
+
+  return (val);
+}
+
+/* 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
+   string). */
+static void
+readtok ()
+{
+  register char *cp = tp;
+  register int c, c1;
+
+  /* Skip leading whitespace. */
+  c = 0;
+  while (cp && (c = *cp) && (cr_whitespace (c)))
+    cp++;
+
+  if (c)
+    cp++;
+       
+  lasttp = tp = cp - 1;
+
+  if (c == '\0')
+    {
+      lasttok = curtok;
+      curtok = 0;
+      tp = cp;
+      return;
+    }
+
+  if (variable_starter (c))
+    {
+      /* Semi-bogus K*rn shell compatibility feature -- variable
+        names not preceded with a dollar sign are shell variables. */
+      char *value;
+
+      while (variable_character (c))
+       c = *cp++;
+
+      c = *--cp;
+      *cp = '\0';
+
+      if (tokstr)
+        free (tokstr);
+      tokstr = savestring (tp);
+      value = get_string_value (tokstr);
+
+      if (value && *value)
+       tokval = evalexp (value);
+      else
+       tokval = 0;
+
+      *cp = c;
+      lasttok = curtok;
+      curtok = STR;
+    }
+  else if (digit(c))
+    {
+      while (digit (c) || isletter (c) || c == '#')
+       c = *cp++;
+
+      c = *--cp;
+      *cp = '\0';
+
+      tokval = strlong (tp);
+      *cp = c;
+      lasttok = curtok;
+      curtok = NUM;
+    }
+  else
+    {
+      c1 = *cp++;
+      if ((c == EQ) && (c1 == EQ)) 
+       c = EQEQ;
+      else if ((c == NOT) && (c1 == EQ))
+       c = NEQ;
+      else if ((c == GT) && (c1 == EQ))
+       c = GEQ;
+      else if ((c == LT) && (c1 == EQ))
+       c = LEQ;
+      else if ((c == LT) && (c1 == LT))
+       {
+         if (*cp == '=')       /* a <<= b */
+           {
+             assigntok = LSH;
+             c = OP_ASSIGN;
+             cp++;
+           }
+         else
+           c = LSH;
+       }
+      else if ((c == GT) && (c1 == GT))
+       {
+         if (*cp == '=')
+           {
+             assigntok = RSH;  /* a >>= b */
+             c = OP_ASSIGN;
+             cp++;
+           }
+         else
+           c = RSH;
+       }
+      else if ((c == BAND) && (c1 == BAND))
+       c = LAND;
+      else if ((c == BOR) && (c1 == BOR))
+       c = LOR;
+      else if (c1 == EQ && member(c, "*/%+-&^|"))
+       {
+         assigntok = c;        /* a OP= b */
+         c = OP_ASSIGN;
+       }
+      else
+       cp--;                   /* `unget' the character */
+      lasttok = curtok;
+      curtok = c;
+    }
+  tp = cp;
+}
+
+static void
+evalerror (msg)
+     char *msg;
+{
+  char *name, *t;
+
+  name = this_command_name;
+  if (name == 0)
+    name = get_name_for_error ();
+  for (t = expression; whitespace (*t); t++)
+    ;
+  fprintf (stderr, "%s: %s: %s (remainder of expression is \"%s\")\n",
+                name, t,
+                msg, (lasttp && *lasttp) ? lasttp : "");
+  longjmp (evalbuf, 1);
+}
+
+/* Convert a string to a long integer, with an arbitrary base.
+   0nnn -> base 8
+   0xnn -> base 16
+   Anything else: [base#]number (this is from the ISO Pascal spec). */
+static long
+strlong (num)
+     char *num;
+{
+  register char *s = num;
+  register int c;
+  int base = 10;
+  long val = 0L;
+
+  if (s == NULL || *s == '\0')
+    return 0L;
+
+  if (*s == '0')
+    {
+      s++;
+
+      if (s == NULL || *s == '\0')
+       return 0L;
+      
+       /* Base 16? */
+      if (*s == 'x' || *s == 'X')
+       {
+         base = 16;
+         s++;
+       }
+      else
+       base = 8;
+    }
+
+  for (c = *s++; c; c = *s++)
+    {
+      if (c == '#')
+       {
+         base = (int)val;
+
+         /* Illegal base specifications are silently reset to base 10.
+            I don't think that this is a good idea? */
+         if (base < 2 || base > 36)
+           base = 10;
+
+         val = 0L;
+       }
+      else
+       if (isletter(c) || digit(c))
+         {
+           if (digit(c))
+             c = digit_value(c);
+           else if (c >= 'a' && c <= 'z')
+             c -= 'a' - 10;
+           else if (c >= 'A' && c <= 'Z')
+             c -= 'A' - 10;
+
+           if (c >= base)
+             evalerror ("value too great for base");
+
+           val = (val * base) + c;
+         }
+       else
+         break;
+    }
+  return (val);
+}
+
+#if defined (EXPR_TEST)
+char *
+xmalloc (n)
+     int n;
+{
+  return (malloc (n));
+}
+
+char *
+xrealloc (s, n)
+     char *s;
+     int n;
+{
+  return (realloc (s, n));
+}
+
+SHELL_VAR *find_variable () { return 0;}
+SHELL_VAR *bind_variable () { return 0; }
+
+char *get_string_value () { return 0; }
+
+jmp_buf top_level;
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  register int i;
+  long v;
+
+  if (setjmp (top_level))
+    exit (0);
+
+  for (i = 1; i < argc; i++)
+    {
+      v = evalexp (argv[i]);
+      printf ("'%s' -> %ld\n", argv[i], v);
+    }
+  exit (0);
+}
+
+int
+builtin_error (format, arg1, arg2, arg3, arg4, arg5)
+     char *format;
+{
+  fprintf (stderr, "expr: ");
+  fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
+  fprintf (stderr, "\n");
+  return 0;
+}
+
+char *
+itos (n)
+     int n;
+{
+  return ("42");
+}
+
+#endif /* EXPR_TEST */
diff --git a/externs.h b/externs.h
new file mode 100644 (file)
index 0000000..8330838
--- /dev/null
+++ b/externs.h
@@ -0,0 +1,67 @@
+/* externs.h -- extern function declarations which do not appear in their
+   own header file. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Make sure that this is included *after* config.h! */
+
+#if !defined (__EXTERNS_H__)
+#  define __EXTERNS_H__
+
+#include "stdc.h"
+
+/* Functions from expr.c. */
+extern long evalexp __P((char *));
+
+/* Functions from print_cmd.c. */
+extern char *make_command_string __P((COMMAND *));
+extern void print_command __P((COMMAND *));
+extern void print_simple_command __P((SIMPLE_COM *));
+extern char *named_function_string __P((char *, COMMAND *, int));
+
+/* Functions from shell.c. */
+extern int maybe_execute_file __P((char *, int));
+extern char *indirection_level_string __P((void));
+extern sighandler termination_unwind_protect __P((int));
+extern sighandler sigint_sighandler __P((int));
+extern void reset_terminating_signals __P((void));
+extern char *shell_version_string __P((void));
+extern void show_shell_version __P((void));
+
+/* Functions from test.c. */
+extern int group_member ();
+
+/* Functions from braces.c. */
+#if defined (BRACE_EXPANSION)
+extern char **brace_expand __P((char *));
+#endif
+
+/* Functions from mailcheck.c */
+extern int time_to_check_mail __P((void));
+extern void reset_mail_timer __P((void));
+extern void reset_mail_files __P((void));
+extern void free_mail_files __P((void));
+extern char *make_default_mailpath __P((void));
+extern void remember_mail_dates __P((void));
+extern void check_mail __P((void));
+
+/* Miscellaneous functions not declared anywhere but used. */
+extern char **glob_filename __P((char *));
+
+#endif /* __EXTERNS_H__ */
diff --git a/filecntl.h b/filecntl.h
new file mode 100644 (file)
index 0000000..c0b2081
--- /dev/null
@@ -0,0 +1,36 @@
+/* filecntl.h - Definitions to set file descriptors to close-on-exec. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_FILECNTL_H_)
+#define _FILECNTL_H_
+
+#include <fcntl.h>
+
+/* Definitions to set file descriptors to close-on-exec, the Posix way. */
+#if !defined (FD_CLOEXEC)
+#define FD_CLOEXEC     1
+#endif
+
+#define FD_NCLOEXEC    0
+
+#define SET_CLOSE_ON_EXEC(fd)  (fcntl ((fd), F_SETFD, FD_CLOEXEC))
+#define SET_OPEN_ON_EXEC(fd)   (fcntl ((fd), F_SETFD, FD_NCLOEXEC))
+
+#endif /* ! _FILECNTL_H_ */
diff --git a/flags.c b/flags.c
new file mode 100644 (file)
index 0000000..b812ec9
--- /dev/null
+++ b/flags.c
@@ -0,0 +1,270 @@
+/* flags.c -- Everything about flags except the `set' command.  That
+   is in builtins.c */
+
+/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Flags hacking. */
+
+#include "shell.h"
+#include "flags.h"
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     The Standard Sh Flags.                      */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero means automatically mark variables which are modified or created
+   as auto export variables. */
+int mark_modified_vars = 0;
+
+/* Non-zero causes asynchronous job notification.  Otherwise, job state
+   notification only takes place just before a primary prompt is printed. */
+int asynchronous_notification = 0;
+
+/* Non-zero means exit immediately if a command exits with a non-zero
+   exit status. */
+int exit_immediately_on_error = 0;
+
+/* Non-zero means disable filename globbing. */
+int disallow_filename_globbing = 0;
+
+/* Non-zero means to locate and remember function commands as functions are
+   defined.  Function commands are normally located when the function is
+   executed. */
+int locate_commands_in_functions = 0;
+
+/* Non-zero means that all keyword arguments are placed into the environment
+   for a command, not just those that appear on the line before the command
+   name. */
+int place_keywords_in_env = 0;
+
+/* Non-zero means read commands, but don't execute tham.  This is useful
+   for debugging shell scripts that should do something hairy and possibly
+   desctructive. */
+int read_but_dont_execute = 0;
+
+/* Non-zero means end of file is after one command. */
+int just_one_command = 0;
+
+/* Non-zero means don't overwrite existing files while doing redirections. */
+int noclobber = 0;
+
+/* Non-zero means trying to get the value of $i where $i is undefined
+   causes an error, instead of a null substitution. */
+int unbound_vars_is_error = 0;
+
+/* Non-zero means type out input lines after you read them. */
+int echo_input_at_read = 0;
+
+/* Non-zero means type out the command definition after reading, but
+   before executing. */
+int echo_command_at_execute = 0;
+
+/* Non-zero means turn on the job control features. */
+int jobs_m_flag = 0;
+
+/* Non-zero means this shell is interactive, even if running under a
+   pipe. */
+int forced_interactive = 0;
+
+/* By default, follow the symbolic links as if they were real directories
+   while hacking the `cd' command.  This means that `cd ..' moves up in
+   the string of symbolic links that make up the current directory, instead
+   of the absolute directory.  The shell variable `nolinks' also controls
+   this flag. */
+int no_symbolic_links = 0;
+
+/* **************************************************************** */
+/*                                                                 */
+/*                  Non-Standard Flags Follow Here.                */
+/*                                                                 */
+/* **************************************************************** */
+
+
+/* Non-zero means do lexical scoping in the body of a FOR command. */
+int lexical_scoping = 0;
+
+/* Non-zero means no such thing as invisible variables. */
+int no_invisible_vars = 0;
+
+/* Non-zero means don't look up or remember command names in a hash table, */
+int hashing_disabled = 0;
+
+#if defined (BANG_HISTORY)
+/* Non-zero means that we are doing history expansion.  The default.
+   This means !22 gets the 22nd line of history. */
+int history_expansion = 1;
+#endif /* BANG_HISTORY */
+
+/* Non-zero means that we allow comments to appear in interactive commands. */
+#if defined (INTERACTIVE_COMMENTS)
+int interactive_comments = 1;
+#else
+int interactive_comments = 0;
+#endif /* INTERACTIVE_COMMENTS */
+
+#if defined (RESTRICTED_SHELL)
+/* Non-zero means that this shell is `restricted'.  A restricted shell
+   disallows: changing directories, command or path names containing `/',
+   unsetting or resetting the values of $PATH and $SHELL, and any type of
+   output redirection. */
+int restricted = 0;
+#endif /* RESTRICTED_SHELL */
+
+/* Non-zero means that this shell is running in `privileged' mode.  This
+   mode is entered on startup if the real and effective uids or gids
+   differ. */
+int privileged_mode = 0;
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     The Flags ALIST.                            */
+/*                                                                 */
+/* **************************************************************** */
+
+struct flags_alist shell_flags[] = {
+  /* Standard sh flags. */
+  { 'a', &mark_modified_vars },
+#if defined (JOB_CONTROL)
+  { 'b', &asynchronous_notification },
+#endif /* JOB_CONTROL */
+  { 'e', &exit_immediately_on_error },
+  { 'f', &disallow_filename_globbing },
+  { 'h', &locate_commands_in_functions }, /* Oh, yeah, good mnemonic. */
+  { 'i', &forced_interactive },
+  { 'k', &place_keywords_in_env },
+#if defined (JOB_CONTROL)
+  { 'm', &jobs_m_flag },
+#endif /* JOB_CONTROL */
+  { 'n', &read_but_dont_execute },
+  { 'p', &privileged_mode },
+#if defined (RESTRICTED_SHELL)
+  { 'r', &restricted },
+#endif /* RESTRICTED_SHELL */
+  { 't', &just_one_command },
+  { 'u', &unbound_vars_is_error },
+  { 'v', &echo_input_at_read },
+  { 'x', &echo_command_at_execute },
+  { 'C', &noclobber },
+
+  /* New flags that control non-standard things. */
+  { 'l', &lexical_scoping },
+  { 'I', &no_invisible_vars },
+
+  /* I want `h', but locate_commands_in_functions has it.  Great. */
+  { 'd', &hashing_disabled },
+
+  { 'P', &no_symbolic_links },
+
+#if defined (BANG_HISTORY)
+  /* Once again, we don't have the right mnemonic. */
+  { 'H', &history_expansion },
+#endif /* BANG_HISTORY */
+
+  {0, (int *)NULL}
+};
+
+#define NUM_SHELL_FLAGS (sizeof (shell_flags) / sizeof (struct flags_alist))
+
+int *
+find_flag (name)
+     int name;
+{
+  int i = 0;
+  while (shell_flags[i].name)
+    {
+      if (shell_flags[i].name == name)
+       return (shell_flags[i].value);
+      i++;
+    }
+  return (FLAG_UNKNOWN);
+}
+
+/* Change the state of a flag, and return it's original value, or return
+   FLAG_ERROR if there is no flag called NAME.  ON_OR_OFF should be one
+   of FLAG_ON or FLAG_OFF. */
+int
+change_flag (flag, on_or_off)
+  int flag;
+  int on_or_off;
+{
+  int *value = find_flag (flag);
+  int old_value;
+
+#if defined (RESTRICTED_SHELL)
+  /* Don't allow "set +r" in a shell which is `restricted'. */
+  if (restricted && flag == 'r' && on_or_off == FLAG_OFF)
+    return (FLAG_ERROR);
+#endif /* RESTRICTED_SHELL */
+
+  if (value == (int *)FLAG_UNKNOWN)
+    return (FLAG_ERROR);
+  else
+    old_value = *value;
+
+  if (on_or_off == FLAG_ON)
+    *value = 1;
+  else
+    {
+      if (on_or_off == FLAG_OFF)
+       *value = 0;
+      else
+       return (FLAG_ERROR);
+    }
+
+  /* Special cases for a few flags. */
+  switch (flag)
+    {
+#if defined (JOB_CONTROL)
+    case 'm':
+      set_job_control (on_or_off == '-');
+      break;
+#endif /* JOB_CONTROL */
+
+    case 'p':
+      if (on_or_off == '+')
+       {
+         setuid (current_user.uid);
+         setgid (current_user.gid);
+         current_user.euid = current_user.uid;
+         current_user.egid = current_user.gid;
+       }
+      break;
+    }
+    
+  return (old_value);
+}
+
+/* Return a string which is the names of all the currently
+   set shell flags. */
+char *
+which_set_flags ()
+{
+  char *temp = (char *)xmalloc (1 + NUM_SHELL_FLAGS);
+
+  int i, string_index = 0;
+
+  for (i = 0; shell_flags[i].name; i++)
+    if (*(shell_flags[i].value))
+      temp[string_index++] = shell_flags[i].name;
+
+  temp[string_index] = '\0';
+  return (temp);
+}
diff --git a/flags.h b/flags.h
new file mode 100644 (file)
index 0000000..bcff4ef
--- /dev/null
+++ b/flags.h
@@ -0,0 +1,65 @@
+/* flags.h -- a list of all the flags that the shell knows about.  You add
+   a flag to this program by adding the name here, and in flags.c. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_FLAGS_H)
+#define _FLAGS_H
+
+#include "stdc.h"
+
+/* Welcome to the world of Un*x, where everything is slightly backwards. */
+#define FLAG_ON '-'
+#define FLAG_OFF '+'
+
+#define FLAG_ERROR -1
+#define FLAG_UNKNOWN (int *)0
+
+/* The thing that we build the array of flags out of. */
+struct flags_alist {
+  char name;
+  int *value;
+};
+
+extern struct flags_alist shell_flags[];
+
+extern int
+  mark_modified_vars, exit_immediately_on_error, disallow_filename_globbing,
+  locate_commands_in_functions, place_keywords_in_env, read_but_dont_execute,
+  just_one_command, unbound_vars_is_error, echo_input_at_read,
+  echo_command_at_execute, lexical_scoping, no_invisible_vars, noclobber,
+  hashing_disabled, forced_interactive, privileged_mode,
+  asynchronous_notification, interactive_comments, no_symbolic_links;
+
+#if defined (BANG_HISTORY)
+extern int history_expansion;
+#endif /* BANG_HISTORY */
+
+#if defined (RESTRICTED_SHELL)
+extern int restricted;
+#endif /* RESTRICTED_SHELL */
+
+extern int *find_flag __P((int));
+extern int change_flag __P((int, int));
+extern char *which_set_flags __P((void));
+
+/* A macro for efficiency. */
+#define change_flag_char(flag, on_or_off)  change_flag (flag, on_or_off)
+
+#endif /* _FLAGS_H */
diff --git a/general.c b/general.c
new file mode 100644 (file)
index 0000000..9ccfce6
--- /dev/null
+++ b/general.c
@@ -0,0 +1,1273 @@
+/* general.c -- Stuff that is used by all files. */
+
+/* Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992
+   Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "config.h"    /* includes unistd.h for us */
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include "bashtypes.h"
+#include <sys/param.h>
+#if defined (_POSIX_VERSION)
+#  if defined (amiga) && defined (USGr4)
+#    define _POSIX_SOURCE
+#  endif
+#  include <signal.h>
+#  if defined (amiga) && defined (USGr4)
+#    undef _POSIX_SOURCE
+#  endif
+#endif /* _POSIX_VERSION */
+#include "filecntl.h"
+#include "bashansi.h"
+#include "shell.h"
+#include <tilde/tilde.h>
+
+#if !defined (USG) || defined (HAVE_RESOURCE)
+#  include <sys/time.h>
+#endif
+
+#include <sys/times.h>
+#include "maxpath.h"
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+/* Make the functions strchr and strrchr if they do not exist. */
+#if !defined (HAVE_STRCHR)
+char *
+strchr (string, c)
+     char *string;
+     int c;
+{
+  register int i;
+
+  for (i = 0; string && string[i]; i++)
+    if (string[i] == c)
+      return ((char *) (string + i));
+
+  return ((char *) NULL);
+}
+
+char *
+strrchr (string, c)
+     char *string;
+     int c;
+{
+  register int i;
+
+  if (string)
+    i = strlen (string) - 1;
+  else
+    i = -1;
+
+  for (; string && i > -1; i--)
+    if (string[i] == c)
+      return ((char *) (string + i));
+
+  return ((char *) NULL);
+}
+#endif /* !HAVE_STRCHR */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                Memory Allocation and Deallocation.              */
+/*                                                                 */
+/* **************************************************************** */
+
+char *
+xmalloc (size)
+     int size;
+{
+  register char *temp = (char *)malloc (size);
+
+  if (!temp)
+    fatal_error ("Out of virtual memory!");
+
+  return (temp);
+}
+
+char *
+xrealloc (pointer, size)
+     GENPTR pointer;
+     int size;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = xmalloc (size);
+  else
+    temp = (char *)realloc (pointer, size);
+
+  if (!temp)
+    fatal_error ("Out of virtual memory!");
+
+  return (temp);
+}
+
+/* Use this as the function to call when adding unwind protects so we
+   don't need to know what free() returns. */
+void
+xfree (string)
+     char *string;
+{
+  free (string);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                  Integer to String Conversion                   */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Number of characters that can appear in a string representation
+   of an integer.  32 is larger than the string rep of 2^^31 - 1. */
+#define MAX_INT_LEN 32
+
+/* Integer to string conversion.  This conses the string; the
+   caller should free it. */
+char *
+itos (i)
+     int i;
+{
+  char *buf, *p, *ret;
+  int negative = 0;
+  unsigned int ui;
+
+  buf = xmalloc (MAX_INT_LEN);
+
+  if (i < 0)
+    {
+      negative++;
+      i = -i;
+    }
+
+  ui = (unsigned int) i;
+
+  buf[MAX_INT_LEN - 1] = '\0';
+  p = &buf[MAX_INT_LEN - 2];
+
+  do
+    *p-- = (ui % 10) + '0';
+  while (ui /= 10);
+
+  if (negative)
+    *p-- = '-';
+
+  ret = savestring (p + 1);
+  free (buf);
+  return (ret);
+}
+
+/* Return non-zero if all of the characters in STRING are digits. */
+int
+all_digits (string)
+     char *string;
+{
+  while (*string)
+    {
+      if (!digit (*string))
+       return (0);
+      else
+       string++;
+    }
+  return (1);
+}
+
+/* atol(3) is not universal */
+long
+string_to_long (s)
+     char *s;
+{
+  long ret = 0L;
+  int neg = 0;
+
+  while (s && *s && whitespace (*s))
+    s++;
+  if (*s == '-' || *s == '+')
+    {
+      neg = *s == '-';
+      s++;
+    }
+  for ( ; s && *s && digit (*s); s++)
+    ret = (ret * 10) + digit_value (*s);
+  return (neg ? -ret : ret);
+}
+
+#if defined (RLIMTYPE)
+RLIMTYPE
+string_to_rlimtype (s)
+     char *s;
+{
+  RLIMTYPE ret = 0;
+  int neg = 0;
+
+  while (s && *s && whitespace (*s))
+    s++;
+  if (*s == '-' || *s == '+')
+    {
+      neg = *s == '-';
+      s++;
+    }
+  for ( ; s && *s && digit (*s); s++)
+    ret = (ret * 10) + digit_value (*s);
+  return (neg ? -ret : ret);
+}
+
+void
+print_rlimtype (n, addnl)
+     RLIMTYPE n;
+     int addnl;
+{
+  char s[sizeof (RLIMTYPE) * 3 + 1];
+  int len = sizeof (RLIMTYPE) * 3 + 1;
+
+  if (n == 0)
+    {
+      printf ("0%s", addnl ? "\n" : "");
+      return;
+    }
+
+  if (n < 0)
+    {
+      putchar ('-');
+      n = -n;
+    }
+
+  s[--len] = '\0';
+  for ( ; n != 0; n /= 10)
+    s[--len] = n % 10 + '0';
+  printf ("%s%s", s + len, addnl ? "\n" : "");
+}
+#endif /* RLIMTYPE */
+
+/* Return 1 if this token is a legal shell `identifier'; that is, it consists
+   solely of letters, digits, and underscores, and does not begin with a
+   digit. */
+int
+legal_identifier (name)
+     char *name;
+{
+  register char *s;
+
+  if (!name || !*name || digit (*name))
+    return (0);
+
+  for (s = name; s && *s; s++)
+    {
+      if (!isletter (*s) && !digit (*s) && (*s != '_'))
+        return (0);
+    }
+  return (1);
+}
+
+/* Make sure that WORD is a valid shell identifier, i.e.
+   does not contain a dollar sign, nor is quoted in any way.  Nor
+   does it consist of all digits.  If CHECK_WORD is non-zero,
+   the word is checked to ensure that it consists of only letters,
+   digits, and underscores. */
+check_identifier (word, check_word)
+     WORD_DESC *word;
+     int check_word;
+{
+  if (word->dollar_present || word->quoted || all_digits (word->word))
+    {
+      report_error ("`%s' is not a valid identifier", word->word);
+      return (0);
+    }
+  else if (check_word && legal_identifier (word->word) == 0)
+    {
+      report_error ("`%s' is not a valid identifier", word->word);
+      return (0);
+    }
+  else
+    return (1);
+}
+
+/* A function to unset no-delay mode on a file descriptor.  Used in shell.c
+   to unset it on the fd passed as stdin.  Should be called on stdin if
+   readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
+
+#if !defined (O_NDELAY)
+#  if defined (FNDELAY)
+#    define O_NDELAY FNDELAY
+#  endif
+#endif /* O_NDELAY */
+
+/* Make sure no-delay mode is not set on file descriptor FD. */
+void
+unset_nodelay_mode (fd)
+     int fd;
+{
+  int flags, set = 0;
+
+  if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
+    return;
+
+#if defined (O_NONBLOCK)
+  if (flags & O_NONBLOCK)
+    {
+      flags &= ~O_NONBLOCK;
+      set++;
+    }
+#endif /* O_NONBLOCK */
+
+#if defined (O_NDELAY)
+  if (flags & O_NDELAY)
+    {
+      flags &= ~O_NDELAY;
+      set++;
+    }
+#endif /* O_NDELAY */
+
+  if (set)
+    fcntl (fd, F_SETFL, flags);
+}
+
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Generic List Functions                      */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Call FUNCTION on every member of LIST, a generic list. */
+void
+map_over_list (list, function)
+     GENERIC_LIST *list;
+     Function *function;
+{
+  while (list)
+    {
+      (*function) (list);
+      list = list->next;
+    }
+}
+
+/* Call FUNCTION on every string in WORDS. */
+void
+map_over_words (words, function)
+     WORD_LIST *words;
+     Function *function;
+{
+  while (words)
+    {
+      (*function)(words->word->word);
+      words = words->next;
+    }
+}
+
+/* Reverse the chain of structures in LIST.  Output the new head
+   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)
+     GENERIC_LIST *list;
+{
+  register GENERIC_LIST *next, *prev = (GENERIC_LIST *)NULL;
+
+  while (list)
+    {
+      next = list->next;
+      list->next = prev;
+      prev = list;
+      list = next;
+    }
+  return (prev);
+}
+
+/* Return the number of elements in LIST, a generic list. */
+int
+list_length (list)
+     GENERIC_LIST *list;
+{
+  register int i;
+
+  for (i = 0; list; list = list->next, i++);
+  return (i);
+}
+
+/* A global variable which acts as a sentinel for an `error' list return. */
+GENERIC_LIST global_error_list;
+
+/* Delete the element of LIST which satisfies the predicate function COMPARER.
+   Returns the element that was deleted, so you can dispose of it, or -1 if
+   the element wasn't found.  COMPARER is called with the list element and
+   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");
+   dispose_variable (elt);
+*/
+GENERIC_LIST *
+delete_element (list, comparer, arg)
+     GENERIC_LIST **list;
+     Function *comparer;
+     char *arg;
+{
+  register GENERIC_LIST *prev = (GENERIC_LIST *)NULL;
+  register GENERIC_LIST *temp = *list;
+
+  while (temp)
+    {
+      if ((*comparer) (temp, arg))
+       {
+         if (prev)
+           prev->next = temp->next;
+         else
+           *list = temp->next;
+         return (temp);
+       }
+      prev = temp;
+      temp = temp->next;
+    }
+  return ((GENERIC_LIST *)&global_error_list);
+}
+
+/* Find NAME in ARRAY.  Return the index of NAME, or -1 if not present.
+   ARRAY should be NULL terminated. */
+int
+find_name_in_list (name, array)
+     char *name, **array;
+{
+  int i;
+
+  for (i = 0; array[i]; i++)
+    if (strcmp (name, array[i]) == 0)
+      return (i);
+
+  return (-1);
+}
+
+/* Return the length of ARRAY, a NULL terminated array of char *. */
+int
+array_len (array)
+     char **array;
+{
+  register int i;
+  for (i = 0; array[i]; i++);
+  return (i);
+}
+
+/* Free the contents of ARRAY, a NULL terminated array of char *. */
+void
+free_array (array)
+     char **array;
+{
+  register int i = 0;
+
+  if (!array) return;
+
+  while (array[i])
+    free (array[i++]);
+  free (array);
+}
+
+/* Allocate and return a new copy of ARRAY and its contents. */
+char **
+copy_array (array)
+     char **array;
+{
+  register int i;
+  int len;
+  char **new_array;
+
+  len = array_len (array);
+
+  new_array = (char **)xmalloc ((len + 1) * sizeof (char *));
+  for (i = 0; array[i]; i++)
+    new_array[i] = savestring (array[i]);
+  new_array[i] = (char *)NULL;
+
+  return (new_array);
+}
+
+/* Comparison routine for use with qsort() on arrays of strings. */
+int
+qsort_string_compare (s1, s2)
+     register char **s1, **s2;
+{
+  int result;
+
+  if ((result = **s1 - **s2) == 0)
+    result = strcmp (*s1, *s2);
+
+  return (result);
+}
+
+/* Append LIST2 to LIST1.  Return the header of the list. */
+GENERIC_LIST *
+list_append (head, tail)
+     GENERIC_LIST *head, *tail;
+{
+  register GENERIC_LIST *t_head = head;
+
+  if (!t_head)
+    return (tail);
+
+  while (t_head->next)
+    t_head = t_head->next;
+  t_head->next = tail;
+  return (head);
+}
+
+/* Some random string stuff. */
+
+/* Remove all leading whitespace from STRING.  This includes
+   newlines.  STRING should be terminated with a zero. */
+void
+strip_leading (string)
+     char *string;
+{
+  char *start = string;
+
+  while (*string && (whitespace (*string) || *string == '\n'))
+    string++;
+
+  if (string != start)
+    {
+      int len = strlen (string);
+      FASTCOPY (string, start, len);
+      start[len] = '\0';
+    }
+}
+
+/* Remove all trailing whitespace from STRING.  This includes
+   newlines.  If NEWLINES_ONLY is non-zero, only trailing newlines
+   are removed.  STRING should be terminated with a zero. */
+void
+strip_trailing (string, newlines_only)
+     char *string;
+     int newlines_only;
+{
+  int len = strlen (string) - 1;
+
+  while (len >= 0)
+    {
+      if ((newlines_only && string[len] == '\n') ||
+          (!newlines_only && whitespace (string[len])))
+        len--;
+      else
+        break;
+    }
+  string[len + 1] = '\0';
+}
+
+/* Canonicalize PATH, and return a new path.  The new path differs from PATH
+   in that:
+       Multple `/'s are collapsed to a single `/'.
+       Leading `./'s and trailing `/.'s are removed.
+       Trailing `/'s are removed.
+       Non-leading `../'s and trailing `..'s are handled by removing
+       portions of the path. */
+char *
+canonicalize_pathname (path)
+     char *path;
+{
+  register int i, start;
+  char stub_char;
+  char *result;
+
+  /* The result cannot be larger than the input PATH. */
+  result = savestring (path);
+
+  stub_char = (*path == '/') ? '/' : '.';
+
+  /* Walk along RESULT looking for things to compact. */
+  i = 0;
+  while (1)
+    {
+      if (!result[i])
+       break;
+
+      while (result[i] && result[i] != '/')
+       i++;
+
+      start = i++;
+
+      /* If we didn't find any slashes, then there is nothing left to do. */
+      if (!result[start])
+       break;
+
+      /* Handle multiple `/'s in a row. */
+      while (result[i] == '/')
+       i++;
+
+#if !defined (apollo)
+      if ((start + 1) != i)
+#else
+      if ((start + 1) != i && (start != 0 || i != 2))
+#endif /* apollo */
+       {
+         strcpy (result + start + 1, result + i);
+         i = start + 1;
+       }
+
+#if 0
+      /* Handle backslash-quoted `/'. */
+      if (start > 0 && result[start - 1] == '\\')
+       continue;
+#endif
+
+      /* Check for trailing `/'. */
+      if (start && !result[i])
+       {
+       zero_last:
+         result[--i] = '\0';
+         break;
+       }
+
+      /* Check for `../', `./' or trailing `.' by itself. */
+      if (result[i] == '.')
+       {
+         /* Handle trailing `.' by itself. */
+         if (!result[i + 1])
+           goto zero_last;
+
+         /* Handle `./'. */
+         if (result[i + 1] == '/')
+           {
+             strcpy (result + i, result + i + 1);
+             i = (start < 0) ? 0 : start;
+             continue;
+           }
+
+         /* Handle `../' or trailing `..' by itself. */
+         if (result[i + 1] == '.' &&
+             (result[i + 2] == '/' || !result[i + 2]))
+           {
+             while (--start > -1 && result[start] != '/');
+             strcpy (result + start + 1, result + i + 2);
+             i = (start < 0) ? 0 : start;
+             continue;
+           }
+       }
+    }
+
+  if (!*result)
+    {
+      *result = stub_char;
+      result[1] = '\0';
+    }
+  return (result);
+}
+
+/* Turn STRING (a pathname) into an absolute pathname, assuming that
+   DOT_PATH contains the symbolic location of `.'.  This always
+   returns a new string, even if STRING was an absolute pathname to
+   begin with. */
+char *
+make_absolute (string, dot_path)
+     char *string, *dot_path;
+{
+  char *result;
+  int result_len;
+  
+  if (!dot_path || *string == '/')
+    result = savestring (string);
+  else
+    {
+      if (dot_path && dot_path[0])
+       {
+         result = xmalloc (2 + strlen (dot_path) + strlen (string));
+         strcpy (result, dot_path);
+         result_len = strlen (result);
+         if (result[result_len - 1] != '/')
+           {
+             result[result_len++] = '/';
+             result[result_len] = '\0';
+           }
+       }
+      else
+       {
+         result = xmalloc (3 + strlen (string));
+         result[0] = '.'; result[1] = '/'; result[2] = '\0';
+         result_len = 2;
+       }
+
+      strcpy (result + result_len, string);
+    }
+
+  return (result);
+}
+
+/* Return 1 if STRING contains an absolute pathname, else 0. */
+int
+absolute_pathname (string)
+     char *string;
+{
+  if (!string || !*string)
+    return (0);
+
+  if (*string == '/')
+    return (1);
+
+  if (*string++ == '.')
+    {
+      if (!*string || *string == '/')
+       return (1);
+
+      if (*string == '.' && (string[1] == '\0' || string[1] == '/'))
+       return (1);
+    }
+  return (0);
+}
+
+/* Return 1 if STRING is an absolute program name; it is absolute if it
+   contains any slashes.  This is used to decide whether or not to look
+   up through $PATH. */
+int
+absolute_program (string)
+     char *string;
+{
+  return ((char *)strchr (string, '/') != (char *)NULL);
+}
+
+/* Return the `basename' of the pathname in STRING (the stuff after the
+   last '/').  If STRING is not a full pathname, simply return it. */
+char *
+base_pathname (string)
+     char *string;
+{
+  char *p;
+
+  if (!absolute_pathname (string))
+    return (string);
+
+  p = (char *)strrchr (string, '/');
+  if (p)
+    return (++p);
+  else
+    return (string);
+}
+
+/* Return the full pathname of FILE.  Easy.  Filenames that begin
+   with a '/' are returned as themselves.  Other filenames have
+   the current working directory prepended.  A new string is
+   returned in either case. */
+char *
+full_pathname (file)
+     char *file;
+{
+  char *disposer;
+
+  if (*file == '~')
+    file = tilde_expand (file);
+  else
+    file = savestring (file);
+
+  if ((*file == '/') && absolute_pathname (file))
+    return (file);
+
+  disposer = file;
+
+  {
+    char *current_dir = xmalloc (2 + MAXPATHLEN + strlen (file));
+    int dlen;
+    if (getwd (current_dir) == 0)
+      {
+       report_error (current_dir);
+       free (current_dir);
+       return ((char *)NULL);
+      }
+    dlen = strlen (current_dir);
+    current_dir[dlen++] = '/';
+
+    /* Turn /foo/./bar into /foo/bar. */
+    if (file[0] == '.' && file[1] == '/')
+      file += 2;
+
+    strcpy (current_dir + dlen, file);
+    free (disposer);
+    return (current_dir);
+  }
+}
+
+#if !defined (HAVE_STRCASECMP)
+
+#if !defined (to_upper)
+#  define to_upper(c) (islower(c) ? toupper(c) : (c))
+#endif /* to_upper */
+
+/* Compare at most COUNT characters from string1 to string2.  Case
+   doesn't matter. */
+int
+strnicmp (string1, string2, count)
+     char *string1, *string2;
+     int count;
+{
+  register char ch1, ch2;
+
+  while (count)
+    {
+      ch1 = *string1++;
+      ch2 = *string2++;
+      if (to_upper(ch1) == to_upper(ch2))
+       count--;
+      else
+       break;
+    }
+  return (count);
+}
+
+/* strcmp (), but caseless. */
+int
+stricmp (string1, string2)
+     char *string1, *string2;
+{
+  register char ch1, ch2;
+
+  while (*string1 && *string2)
+    {
+      ch1 = *string1++;
+      ch2 = *string2++;
+      if (to_upper(ch1) != to_upper(ch2))
+       return (1);
+    }
+  return (*string1 - *string2);
+}
+#endif /* !HAVE_STRCASECMP */
+
+/* Determine if s2 occurs in s1.  If so, return a pointer to the
+   match in s1.  The compare is case insensitive. */
+char *
+strindex (s1, s2)
+     char *s1, *s2;
+{
+  register int i, l = strlen (s2);
+  register int len = strlen (s1);
+
+  for (i = 0; (len - i) >= l; i++)
+    if (strnicmp (s1 + i, s2, l) == 0)
+      return (s1 + i);
+  return ((char *)NULL);
+}
+
+/* Set the environment variables $LINES and $COLUMNS in response to
+   a window size change. */
+void
+set_lines_and_columns (lines, cols)
+     int lines, cols;
+{
+  char *val;
+
+  val = itos (lines);
+  bind_variable ("LINES", val);
+  free (val);
+
+  val = itos (cols);
+  bind_variable ("COLUMNS", val);
+  free (val);
+}
+
+/* A wrapper for bcopy that can be prototyped in general.h */
+void
+xbcopy (s, d, n)
+     char *s, *d;
+     int n;
+{
+  FASTCOPY (s, d, n);
+}
+
+/* Return a string corresponding to the error number E.  From
+   the ANSI C spec. */
+#if defined (strerror)
+#  undef strerror
+#endif
+
+#if !defined (HAVE_STRERROR)
+char *
+strerror (e)
+     int e;
+{
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+  static char emsg[40];
+
+  if (e > 0 && e < sys_nerr)
+    return (sys_errlist[e]);
+  else
+    {
+      sprintf (emsg, "Unknown error %d", e);
+      return (&emsg[0]);
+    }
+}
+#endif /* HAVE_STRERROR */
+
+#if (defined (USG) && !defined (HAVE_TIMEVAL)) || defined (Minix)
+#  define TIMEVAL_MISSING
+#endif
+
+#if !defined (TIMEVAL_MISSING) || defined (HAVE_RESOURCE)
+/* Print the contents of a struct timeval * in a standard way. */
+void
+print_timeval (tvp)
+     struct timeval *tvp;
+{
+  int minutes, seconds_fraction;
+  long seconds;
+
+  seconds = tvp->tv_sec;
+
+  seconds_fraction = tvp->tv_usec % 1000000;
+  seconds_fraction = (seconds_fraction * 100) / 1000000;
+
+  minutes = seconds / 60;
+  seconds %= 60;
+
+  printf ("%0dm%0ld.%02ds",  minutes, seconds, seconds_fraction);
+}
+#endif /* !TIMEVAL_MISSING || HAVE_RESOURCE */
+
+/* Print the time defined by a time_t (returned by the `times' and `time'
+   system calls) in a standard way.  This is scaled in terms of HZ, which
+   is what is returned by the `times' call. */
+
+#if !defined (BrainDeath)
+#  if !defined (HZ)
+#    if defined (USG)
+#      define HZ 100           /* From my Sys V.3.2 manual for times(2) */
+#    else
+#      define HZ 60            /* HZ is always 60 on BSD systems */
+#    endif /* USG */
+#  endif /* HZ */
+
+void
+print_time_in_hz (t)
+  time_t t;
+{
+  int minutes, seconds_fraction;
+  long seconds;
+
+  seconds_fraction = t % HZ;
+  seconds_fraction = (seconds_fraction * 100) / HZ;
+
+  seconds = t / HZ;
+
+  minutes = seconds / 60;
+  seconds %= 60;
+
+  printf ("%0dm%0ld.%02ds",  minutes, seconds, seconds_fraction);
+}
+#endif /* BrainDeath */
+
+#if !defined (HAVE_DUP2)
+/* Replacement for dup2 (), for those systems which either don't have it,
+   or supply one with broken behaviour. */
+int
+dup2 (fd1, fd2)
+     int fd1, fd2;
+{
+  extern int getdtablesize ();
+  int saved_errno, r;
+
+  /* If FD1 is not a valid file descriptor, then return immediately with
+     an error. */
+  if (fcntl (fd1, F_GETFL, 0) == -1)
+    return (-1);
+
+  if (fd2 < 0 || fd2 >= getdtablesize ())
+    {
+      errno = EBADF;
+      return (-1);
+    }
+
+  if (fd1 == fd2)
+    return (0);
+
+  saved_errno = errno;
+
+  (void) close (fd2);
+  r = fcntl (fd1, F_DUPFD, fd2);
+
+  if (r >= 0)
+    errno = saved_errno;
+  else
+    if (errno == EINVAL)
+      errno = EBADF;
+
+  /* Force the new file descriptor to remain open across exec () calls. */
+  SET_OPEN_ON_EXEC (fd2);
+  return (r);
+}
+#endif /* !HAVE_DUP2 */
+
+/*
+ * Return the total number of available file descriptors.
+ *
+ * On some systems, like 4.2BSD and its descendents, there is a system call
+ * that returns the size of the descriptor table: getdtablesize().  There are
+ * lots of ways to emulate this on non-BSD systems.
+ *
+ * On System V.3, this can be obtained via a call to ulimit:
+ *     return (ulimit(4, 0L));
+ *
+ * On other System V systems, NOFILE is defined in /usr/include/sys/param.h
+ * (this is what we assume below), so we can simply use it:
+ *     return (NOFILE);
+ *
+ * On POSIX systems, there are specific functions for retrieving various
+ * configuration parameters:
+ *     return (sysconf(_SC_OPEN_MAX));
+ *
+ */
+
+#if !defined (USG) && !defined (HPUX) && !defined (HAVE_GETDTABLESIZE)
+#  define HAVE_GETDTABLESIZE
+#endif /* !USG && !HPUX && !HAVE_GETDTABLESIZE */
+
+#if defined (hppa) && (defined (hpux_8) || defined (hpux_9))
+#  undef HAVE_GETDTABLESIZE
+#endif /* hppa && hpux_8 */
+
+#if !defined (HAVE_GETDTABLESIZE)
+int
+getdtablesize ()
+{
+#  if defined (_POSIX_VERSION) && defined (_SC_OPEN_MAX)
+  return (sysconf(_SC_OPEN_MAX));      /* Posix systems use sysconf */
+#  else /* ! (_POSIX_VERSION && _SC_OPEN_MAX) */
+#    if defined (USGr3)
+  return (ulimit (4, 0L));     /* System V.3 systems use ulimit(4, 0L) */
+#    else /* !USGr3 */
+#      if defined (NOFILE)     /* Other systems use NOFILE */
+  return (NOFILE);
+#      else /* !NOFILE */
+  return (20);                 /* XXX - traditional value is 20 */
+#      endif /* !NOFILE */
+#    endif /* !USGr3 */
+#  endif /* ! (_POSIX_VERSION && _SC_OPEN_MAX) */
+}
+#endif /* !HAVE_GETDTABLESIZE */
+
+#if defined (USG)
+
+#if !defined (HAVE_BCOPY)
+bcopy (s,d,n) char *d,*s; { FASTCOPY (s, d, n); }
+bzero (s,n) char *s; int n; { memset(s, '\0', n); }
+#endif /* !HAVE_BCOPY */
+
+#if !defined (HAVE_GETHOSTNAME)
+#include <sys/utsname.h>
+int
+gethostname (name, namelen)
+     char *name;
+     int namelen;
+{
+  int i;
+  struct utsname ut;
+
+  --namelen;
+
+  uname (&ut);
+  i = strlen (ut.nodename) + 1;
+  strncpy (name, ut.nodename, i < namelen ? i : namelen);
+  name[namelen] = '\0';
+  return (0);
+}
+#endif /* !HAVE_GETHOSTNAME */
+#endif /* USG */
+
+#if !defined (HAVE_GETWD)
+char *
+getwd (string)
+     char *string;
+{
+  extern char *getcwd ();
+  char *result;
+
+  result = getcwd (string, MAXPATHLEN);
+  if (result == NULL)
+    strcpy (string, "getwd: cannot access parent directories");
+  return (result);
+}
+#endif /* !HAVE_GETWD */
+
+/* A slightly related function.  Get the prettiest name of this
+   directory possible. */
+static char tdir[MAXPATHLEN];
+
+/* Return a pretty pathname.  If the first part of the pathname is
+   the same as $HOME, then replace that with `~'.  */
+char *
+polite_directory_format (name)
+     char *name;
+{
+  char *home = get_string_value ("HOME");
+  int l = home ? strlen (home) : 0;
+
+  if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
+    {
+      strcpy (tdir + 1, name + l);
+      tdir[0] = '~';
+      return (tdir);
+    }
+  else
+    return (name);
+}
+
+#if defined (NO_READ_RESTART_ON_SIGNAL)
+static char localbuf[128];
+static int local_index = 0, local_bufused = 0;
+
+/* Posix and USG systems do not guarantee to restart read () if it is
+   interrupted by a signal.  We do the read ourselves, and restart it
+   if it returns EINTR. */
+int
+getc_with_restart (stream)
+     FILE *stream;
+{
+  /* Try local buffering to reduce the number of read(2) calls. */
+  if (local_index == local_bufused || local_bufused == 0)
+    {
+      while (1)
+       {
+         local_bufused = read (fileno (stream), localbuf, sizeof(localbuf));
+         if (local_bufused > 0)
+           break;
+         else if (local_bufused == 0 || errno != EINTR)
+           {
+             local_index = 0;
+             return EOF;
+           }
+       }
+      local_index = 0;
+    }
+  return (localbuf[local_index++]);
+}
+
+int
+ungetc_with_restart (c, fp)
+     int c;
+     FILE *fp;
+{
+  if (local_index == 0 || local_bufused == 0 || c == EOF)
+    return EOF;
+  return (localbuf[--local_index] = c);
+}
+
+#endif /* NO_READ_RESTART_ON_SIGNAL */
+
+#if defined (USG) || defined (AIX) || (defined (_POSIX_VERSION) && defined (Ultrix))
+/* USG and strict POSIX systems do not have killpg ().  But we use it in
+   jobs.c, nojobs.c and some of the builtins.  This can also be redefined
+   as a macro if necessary. */
+#if !defined (_POSIX_VERSION)
+#  define pid_t int
+#endif /* _POSIX_VERSION */
+
+int
+killpg (pgrp, sig)
+     pid_t pgrp;
+     int sig;
+{
+  return (kill (-pgrp, sig));
+}
+#endif /* USG  || AIX || (_POSIX_VERSION && Ultrix) */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                 Tilde Initialization and Expansion              */
+/*                                                                 */
+/* **************************************************************** */
+
+/* If tilde_expand hasn't been able to expand the text, perhaps it
+   is a special shell expansion.  This function is installed as the
+   tilde_expansion_failure_hook.  It knows how to expand ~- and ~+. */
+static char *
+bash_tilde_expand (text)
+     char *text;
+{
+  char *result = (char *)NULL;
+
+  if (!text[1])
+    {
+      if (*text == '+')
+        result = get_string_value ("PWD");
+      else if (*text == '-')
+        result = get_string_value ("OLDPWD");
+    }
+
+  if (result)
+    result = savestring (result);
+
+  return (result);
+}
+
+/* Initialize the tilde expander.  In Bash, we handle `~-' and `~+', as
+   well as handling special tilde prefixes; `:~" and `=~' are indications
+   that we should do tilde expansion. */
+void
+tilde_initialize ()
+{
+  static int times_called = 0;
+
+  /* Tell the tilde expander that we want a crack if it fails. */
+  tilde_expansion_failure_hook = (CPFunction *)bash_tilde_expand;
+
+  /* Tell the tilde expander about special strings which start a tilde
+     expansion, and the special strings that end one.  Only do this once.
+     tilde_initialize () is called from within bashline_reinitialize (). */
+  if (times_called == 0)
+    {
+      tilde_additional_prefixes = (char **)xmalloc (3 * sizeof (char *));
+      tilde_additional_prefixes[0] = "=~";
+      tilde_additional_prefixes[1] = ":~";
+      tilde_additional_prefixes[2] = (char *)NULL;
+
+      tilde_additional_suffixes = (char **)xmalloc (3 * sizeof (char *));
+      tilde_additional_suffixes[0] = ":";
+      tilde_additional_suffixes[1] = "=~";
+      tilde_additional_suffixes[2] = (char *)NULL;
+    }
+  times_called++;
+}
+
+#if defined (_POSIX_VERSION)
+
+#if !defined (SA_INTERRUPT)
+#  define SA_INTERRUPT 0
+#endif
+
+#if !defined (SA_RESTART)
+#  define SA_RESTART 0
+#endif
+
+SigHandler *
+set_signal_handler (sig, handler)
+     int sig;
+     SigHandler *handler;
+{
+  struct sigaction act, oact;
+
+  act.sa_handler = handler;
+  act.sa_flags = 0;
+#if 0
+  if (sig == SIGALRM)
+    act.sa_flags |= SA_INTERRUPT;      /* XXX */
+  else
+    act.sa_flags |= SA_RESTART;                /* XXX */
+#endif
+  sigemptyset (&act.sa_mask);
+  sigemptyset (&oact.sa_mask);
+  sigaction (sig, &act, &oact);
+  return (oact.sa_handler);
+}
+#endif /* _POSIX_VERSION */
diff --git a/general.h b/general.h
new file mode 100644 (file)
index 0000000..5c8f4d1
--- /dev/null
+++ b/general.h
@@ -0,0 +1,247 @@
+/* general.h -- defines that everybody likes to use. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_GENERAL_H)
+#define _GENERAL_H
+
+#include "stdc.h"
+
+/* just to make sure */
+#if defined (HAVE_UNISTD_H)
+#  ifdef CRAY
+#    define word __word
+#  endif
+#  include <unistd.h>
+#  ifdef CRAY
+#    undef word
+#  endif
+#endif
+
+#if !defined (NULL)
+#  if defined (__STDC__)
+#    define NULL ((void *) 0)
+#  else
+#    define NULL 0x0
+#  endif /* !__STDC__ */
+#endif /* !NULL */
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#define pointer_to_int(x) (int)((long)(x))
+
+#if !defined (savestring)
+   extern char *xmalloc ();
+#  if !defined (strcpy)
+   extern char *strcpy ();
+#  endif
+#  define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x))
+#endif
+
+#ifndef whitespace
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#endif
+
+#ifndef digit
+#define digit(c)  ((c) >= '0' && (c) <= '9')
+#endif
+
+#ifndef isletter
+#define isletter(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
+#endif
+
+#ifndef digit_value
+#define digit_value(c) ((c) - '0')
+#endif
+
+/* Definitions used in subst.c and by the `read' builtin for field
+   splitting. */
+#define spctabnl(c)    ((c) == ' ' || (c) == '\t' || (c) == '\n')
+
+#if !defined (__STDC__) && !defined (strchr)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr */
+
+#ifndef member
+#  if defined (alpha) && defined (__GNUC__)    /* XXX */
+     extern char *strchr ();
+#  endif
+#  define member(c, s) ((c) ? ((char *)strchr ((s), (c)) != (char *)NULL) : 0)
+#endif
+
+/* All structs which contain a `next' field should have that field
+   as the first field in the struct.  This means that functions
+   can be written to handle the general case for linked lists. */
+typedef struct g_list {
+  struct g_list *next;
+} GENERIC_LIST;
+
+/* Here is a generic structure for associating character strings
+   with integers.  It is used in the parser for shell tokenization. */
+typedef struct {
+  char *word;
+  int token;
+} STRING_INT_ALIST;
+
+/* A macro to avoid making an uneccessary function call. */
+#define REVERSE_LIST(list, type) \
+  ((list && list->next) ? (type)reverse_list ((GENERIC_LIST *)list) : (type)(list))
+
+#if __GNUC__ > 1
+#  define FASTCOPY(s, d, n)  __builtin_memcpy (d, s, n)
+#else /* !__GNUC__ */
+#  if defined (USG) && !defined (HAVE_BCOPY)
+#    if defined (MEMMOVE_MISSING)
+#      define FASTCOPY(s, d, n)  memcpy (d, s, n)
+#    else
+#      define FASTCOPY(s, d, n)  memmove (d, s, n)
+#    endif /* !MEMMOVE_MISSING */
+#  else
+#    define FASTCOPY(s, d, n)  bcopy (s, d, n)
+#  endif /* !USG || HAVE_BCOPY */
+#endif /* !__GNUC__ */
+
+/* String comparisons that possibly save a function call each. */
+#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)
+
+/* More convenience definitions that possibly save system or libc calls. */
+#define STRLEN(s) (((s) && (s)[0]) ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 0)
+#define FREE(s)  do { if (s) free (s); } while (0)
+#define MEMBER(c, s) (((c) && !(s)[1] && c == s[0]) || (member(c, s)))
+
+/* What type is a `generic' pointer?  This is used as the first argument
+   to xrealloc. */
+#if defined (__STDC__)
+typedef void *GENPTR;
+#else
+typedef char *GENPTR;
+#endif
+
+/* Function pointers can be declared as (Function *)foo. */
+#if !defined (__FUNCTION_DEF)
+#  define __FUNCTION_DEF
+typedef int Function ();
+typedef void VFunction ();
+typedef char *CPFunction ();
+typedef char **CPPFunction ();
+#endif /* _FUNCTION_DEF */
+
+#define NOW    ((time_t) time ((time_t *) 0))
+
+/* Some defines for calling file status functions. */
+#define FS_EXISTS        0x1
+#define FS_EXECABLE      0x2
+#define FS_EXEC_PREFERRED 0x4
+#define FS_EXEC_ONLY     0x8
+
+/* Posix and USG systems do not guarantee to restart a read () that is
+   interrupted by a signal. */
+#if defined (USG) || defined (_POSIX_VERSION)
+#  define NO_READ_RESTART_ON_SIGNAL
+#endif /* USG || _POSIX_VERSION */
+
+/* Here is a definition for set_signal_handler () which simply expands to
+   a call to signal () for non-Posix systems.  The code for set_signal_handler
+   in the Posix case resides in general.c. */
+
+#if defined (VOID_SIGHANDLER)
+#  define sighandler void
+#else
+#  define sighandler int
+#endif /* !VOID_SIGHANDLER */
+
+typedef sighandler SigHandler ();
+
+#if !defined (_POSIX_VERSION)
+#  define set_signal_handler(sig, handler) (SigHandler *)signal (sig, handler)
+#else
+extern SigHandler *set_signal_handler ();
+#endif /* _POSIX_VERSION */
+
+/* This function is defined in trap.c. */
+extern SigHandler *set_sigint_handler __P((void));
+
+/* Declarations for functions defined in general.c */
+extern char *xmalloc __P((int));
+extern char *xrealloc __P((void *, int));
+extern void xfree __P((char *));
+extern char *itos __P((int));
+extern int all_digits __P((char *));
+extern long string_to_long __P((char *));
+extern int legal_identifier __P((char *));
+extern int check_identifier __P((WORD_DESC *, int));
+extern void unset_nodelay_mode __P((int));
+extern void map_over_words __P((WORD_LIST *, Function *));
+
+extern void map_over_list __P((GENERIC_LIST *, Function *));
+extern GENERIC_LIST *reverse_list ();
+extern GENERIC_LIST *delete_element ();
+extern GENERIC_LIST *list_append ();
+extern int list_length ();
+extern int qsort_string_compare ();
+
+extern int find_name_in_list __P((char *, char **));
+extern int array_len __P((char **));
+extern void free_array __P((char **));
+extern char **copy_array __P((char **));
+extern void strip_leading __P((char *));
+extern void strip_trailing __P((char *, int));
+extern char *canonicalize_pathname __P((char *));
+extern char *make_absolute __P((char *, char *));
+extern int absolute_pathname __P((char *));
+extern int absolute_program __P((char *));
+extern char *base_pathname __P((char *));
+extern char *full_pathname __P((char *));
+extern char *strindex __P((char *, char *));
+extern void set_lines_and_columns __P((int, int));
+extern void xbcopy __P((char *, char *, int));
+extern char *polite_directory_format __P((char *));
+extern void tilde_initialize __P((void));
+
+#if !defined (strerror)
+extern char *strerror __P((int));
+#endif
+
+#if defined (RLIMTYPE)
+extern RLIMTYPE string_to_rlimtype __P((char *));
+extern void print_rlimtype __P((RLIMTYPE, int));
+#endif
+
+#if !defined (HAVE_STRCASECMP)
+extern int strnicmp __P((char *, char *, int));
+extern int stricmp __P((char *, char *));
+#else /* HAVE_STRCASECMP */
+#  define stricmp strcasecmp
+#  define strnicmp strncasecmp
+#endif /* HAVE_STRCASECMP */
+
+extern int dup2 __P((int, int));
+extern char *getwd __P((char *));
+extern int getdtablesize __P((void));
+
+#if defined (USG) && !defined (HAVE_GETHOSTNAME)
+extern int gethostname __P((char *, int));
+#endif /* USG && !HAVE_GETHOSTNAME */
+
+#endif /* _GENERAL_H */
diff --git a/getcwd.c b/getcwd.c
new file mode 100644 (file)
index 0000000..6f6eed3
--- /dev/null
+++ b/getcwd.c
@@ -0,0 +1,344 @@
+/* getcwd.c -- stolen from the GNU C library and modified to work with bash. */
+
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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., 675 Mass Ave,
+   Cambridge, MA 02139, USA.  */
+
+#include "bashtypes.h"
+#include <errno.h>
+
+#if defined (HAVE_LIMITS_H)
+#  include <limits.h>
+#endif
+
+#if defined (HAVE_DIRENT_H)
+#  include <dirent.h>
+#else
+#  include <sys/dir.h>
+#  if !defined (dirent)
+#    define dirent direct
+#  endif /* !dirent */
+#endif /* !HAVE_DIRENT_H */
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include "posixstat.h"
+#include "maxpath.h"
+#include "config.h"
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* !HAVE_STDLIB_H */
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#if defined (__STDC__)
+#  define CONST const
+#  define PTR void *
+#else /* !__STDC__ */
+#  define CONST
+#  define PTR char *
+#endif /* !__STDC__ */
+
+#if !defined (PATH_MAX)
+#  if defined (MAXPATHLEN)
+#    define PATH_MAX MAXPATHLEN
+#  else /* !MAXPATHLEN */
+#    define PATH_MAX 1024
+#  endif /* !MAXPATHLEN */
+#endif /* !PATH_MAX */
+
+#if defined (_POSIX_VERSION) || defined (USGr3) || defined (HAVE_DIRENT_H)
+#  if !defined (HAVE_DIRENT)
+#    define HAVE_DIRENT
+#  endif /* !HAVE_DIRENT */
+#endif /* _POSIX_VERSION || USGr3 || HAVE_DIRENT_H */
+
+#if defined (HAVE_DIRENT)
+#  define D_NAMLEN(d)  (strlen ((d)->d_name))
+#else
+#  define D_NAMLEN(d)  ((d)->d_namlen)
+#endif /* ! (_POSIX_VERSION || USGr3) */
+
+#if defined (USG) || defined (USGr3)
+#  define d_fileno d_ino
+#endif
+
+#if !defined (alloca)
+extern char *alloca ();
+#endif /* alloca */
+
+/* Heuristic to tell whether or not the current machine has lstat(2).
+   Can probably be fooled easily. */
+#if !defined (S_ISLNK)
+#  define lstat stat
+#endif
+
+/* Get the pathname of the current working directory,
+   and put it in SIZE bytes of BUF.  Returns NULL if the
+   directory couldn't be determined or SIZE was too small.
+   If successful, returns BUF.  In GNU, if BUF is NULL,
+   an array is allocated with `malloc'; the array is SIZE
+   bytes long, unless SIZE <= 0, in which case it is as
+   big as necessary.  */
+#if defined (__STDC__)
+char *
+getcwd (char *buf, size_t size)
+#else /* !__STDC__ */
+char *
+getcwd (buf, size)
+     char *buf;
+     size_t size;
+#endif /* !__STDC__ */
+{
+  static CONST char dots[]
+    = "../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../..";
+  CONST char *dotp, *dotlist;
+  size_t dotsize;
+  dev_t rootdev, thisdev;
+  ino_t rootino, thisino;
+  char path[PATH_MAX + 1];
+  register char *pathp;
+  char *pathbuf;
+  size_t pathsize;
+  struct stat st;
+
+  if (buf != NULL && size == 0)
+    {
+      errno = EINVAL;
+      return ((char *)NULL);
+    }
+
+  pathsize = sizeof (path);
+  pathp = &path[pathsize];
+  *--pathp = '\0';
+  pathbuf = path;
+
+  if (stat (".", &st) < 0)
+    return ((char *)NULL);
+  thisdev = st.st_dev;
+  thisino = st.st_ino;
+
+  if (stat ("/", &st) < 0)
+    return ((char *)NULL);
+  rootdev = st.st_dev;
+  rootino = st.st_ino;
+
+  dotsize = sizeof (dots) - 1;
+  dotp = &dots[sizeof (dots)];
+  dotlist = dots;
+  while (!(thisdev == rootdev && thisino == rootino))
+    {
+      register DIR *dirstream;
+      register struct dirent *d;
+      dev_t dotdev;
+      ino_t dotino;
+      char mount_point;
+      int namlen;
+
+      /* Look at the parent directory.  */
+      if (dotp == dotlist)
+       {
+         /* My, what a deep directory tree you have, Grandma.  */
+         char *new;
+         if (dotlist == dots)
+           {
+             new = malloc (dotsize * 2 + 1);
+             if (new == NULL)
+               goto lose;
+             memcpy (new, dots, dotsize);
+           }
+         else
+           {
+             new = realloc ((PTR) dotlist, dotsize * 2 + 1);
+             if (new == NULL)
+               goto lose;
+           }
+         memcpy (&new[dotsize], new, dotsize);
+         dotp = &new[dotsize];
+         dotsize *= 2;
+         new[dotsize] = '\0';
+         dotlist = new;
+       }
+
+      dotp -= 3;
+
+      /* Figure out if this directory is a mount point.  */
+      if (stat (dotp, &st) < 0)
+       goto lose;
+      dotdev = st.st_dev;
+      dotino = st.st_ino;
+      mount_point = dotdev != thisdev;
+
+      /* Search for the last directory.  */
+      dirstream = opendir (dotp);
+      if (dirstream == NULL)
+       goto lose;
+      while ((d = readdir (dirstream)) != NULL)
+       {
+         if (d->d_name[0] == '.' &&
+             (d->d_name[1] == '\0' ||
+               (d->d_name[1] == '.' && d->d_name[2] == '\0')))
+           continue;
+         if (mount_point || d->d_fileno == thisino)
+           {
+             char *name;
+
+             namlen = D_NAMLEN(d);
+             name = (char *)
+               alloca (dotlist + dotsize - dotp + 1 + namlen + 1);
+             memcpy (name, dotp, dotlist + dotsize - dotp);
+             name[dotlist + dotsize - dotp] = '/';
+             memcpy (&name[dotlist + dotsize - dotp + 1],
+                     d->d_name, namlen + 1);
+             if (lstat (name, &st) < 0)
+               {
+                 int save = errno;
+                 (void) closedir (dirstream);
+                 errno = save;
+                 goto lose;
+               }
+             if (st.st_dev == thisdev && st.st_ino == thisino)
+               break;
+           }
+       }
+      if (d == NULL)
+       {
+         int save = errno;
+         (void) closedir (dirstream);
+         errno = save;
+         goto lose;
+       }
+      else
+       {
+         size_t space;
+
+         while ((space = pathp - pathbuf) <= namlen)
+           {
+             char *new;
+
+             if (pathbuf == path)
+               {
+                 new = malloc (pathsize * 2);
+                 if (!new)
+                   goto lose;
+               }
+             else
+               {
+                 new = realloc ((PTR) pathbuf, (pathsize * 2));
+                 if (!new)
+                   goto lose;
+                 pathp = new + space;
+               }
+             (void) memcpy (new + pathsize + space, pathp, pathsize - space);
+             pathp = new + pathsize + space;
+             pathbuf = new;
+             pathsize *= 2;
+           }
+
+         pathp -= namlen;
+         (void) memcpy (pathp, d->d_name, namlen);
+         *--pathp = '/';
+         (void) closedir (dirstream);
+       }
+
+      thisdev = dotdev;
+      thisino = dotino;
+    }
+
+  if (pathp == &path[sizeof(path) - 1])
+    *--pathp = '/';
+
+  if (dotlist != dots)
+    free ((PTR) dotlist);
+
+  {
+    size_t len = pathbuf + pathsize - pathp;
+    if (buf == NULL)
+      {
+       if (len < (size_t) size)
+         len = size;
+       buf = (char *) malloc (len);
+       if (buf == NULL)
+         goto lose2;
+      }
+    else if ((size_t) size < len)
+      {
+       errno = ERANGE;
+       goto lose2;
+      }
+    (void) memcpy((PTR) buf, (PTR) pathp, len);
+  }
+
+  if (pathbuf != path)
+    free (pathbuf);
+
+  return (buf);
+
+ lose:
+  if ((dotlist != dots) && dotlist)
+    {
+      int e = errno;
+      free ((PTR) dotlist);
+      errno = e;
+    }
+
+ lose2:
+  if ((pathbuf != path) && pathbuf)
+    {
+      int e = errno;
+      free ((PTR) pathbuf);
+      errno = e;
+    }
+  return ((char *)NULL);
+}
+
+#if defined (TEST)
+#  include <stdio.h>
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char b[PATH_MAX];
+
+  if (getcwd(b, sizeof(b)))
+    {
+      printf ("%s\n", b);
+      exit (0);
+    }
+  else
+    {
+      perror ("cwd: getcwd");
+      exit (1);
+    }
+}
+#endif /* TEST */
diff --git a/hash.c b/hash.c
new file mode 100644 (file)
index 0000000..b955b3f
--- /dev/null
+++ b/hash.c
@@ -0,0 +1,297 @@
+/* Hash.c -- Where hashing for bash is done. */
+
+/* Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* There appears to be library functions for this stuff, but it seems like
+   a lot of overhead, so I just implemented this hashing stuff on my own. */
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "shell.h"
+#include "hash.h"
+
+HASH_TABLE *hashed_filenames;
+
+#define FILENAME_HASH_BUCKETS 107
+
+/* 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;
+}
+
+/* Make a new hash table with BUCKETS number of buckets.  Initialize
+   each slot in the table to NULL. */
+HASH_TABLE *
+make_hash_table (buckets)
+     int buckets;
+{
+  HASH_TABLE *new_table = (HASH_TABLE *)xmalloc (sizeof (HASH_TABLE));
+
+  if (buckets == 0)
+    buckets = DEFAULT_HASH_BUCKETS;
+
+  new_table->bucket_array =
+    (BUCKET_CONTENTS **)xmalloc (buckets * sizeof (BUCKET_CONTENTS *));
+  new_table->nbuckets = buckets;
+  new_table->nentries = 0;
+  initialize_hash_table (new_table);
+  return (new_table);
+}
+
+#if 0
+/* UNUSED */
+/* Create the hash table for filenames that we use in the shell. */
+initialize_hashed_filenames ()
+{
+  hashed_filenames = make_hash_table (FILENAME_HASH_BUCKETS);
+}
+#endif
+
+/* Return the location of the bucket which should contain the data
+   for STRING.  TABLE is a pointer to a HASH_TABLE. */
+
+#define ALL_ONES (~((unsigned long) 0))
+#define BITS(h, n) ((unsigned long)(h) & ~(ALL_ONES << (n)))
+
+int
+hash_string (string, table)
+     char *string;
+     HASH_TABLE *table;
+{
+  register unsigned int i = 0;
+
+  while (*string)
+    i = (i << 2) + *string++;
+
+  return (BITS (i, 31) % table->nbuckets);
+}
+
+/* Return a pointer to the hashed item, or NULL if the item
+   can't be found. */
+BUCKET_CONTENTS *
+find_hash_item (string, table)
+     char *string;
+     HASH_TABLE *table;
+{
+  BUCKET_CONTENTS *list;
+  int which_bucket;
+
+  if (!table)
+    return (BUCKET_CONTENTS *)NULL;
+
+  which_bucket = hash_string (string, table);
+
+  list = table->bucket_array[which_bucket];
+
+  while (list)
+    {
+      if (STREQ (list->key, string))
+       {
+         list->times_found++;
+         return (list);
+       }
+      else list = list->next;
+    }
+  return (BUCKET_CONTENTS *)NULL;
+}
+
+/* Remove the item specified by STRING from the hash table 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)
+     char *string;
+     HASH_TABLE *table;
+{
+  int the_bucket;
+  BUCKET_CONTENTS *prev, *temp;
+
+  if (!table)
+    return (BUCKET_CONTENTS *)NULL;
+
+  the_bucket = hash_string (string, table);
+  prev = (BUCKET_CONTENTS *)NULL;
+  temp = table->bucket_array[the_bucket];
+
+  while (temp)
+    {
+      if (STREQ (temp->key, string))
+       {
+         if (prev)
+           prev->next = temp->next;
+         else
+           table->bucket_array[the_bucket] = temp->next;
+
+         table->nentries--;
+         return (temp);
+       }
+      prev = temp;
+      temp = temp->next;
+    }
+  return ((BUCKET_CONTENTS *) NULL);
+}
+
+/* Create an entry for STRING, in TABLE.  If the entry already
+   exists, then return it. */
+BUCKET_CONTENTS *
+add_hash_item (string, table)
+     char *string;
+     HASH_TABLE *table;
+{
+  BUCKET_CONTENTS *item;
+
+  if (!table)
+    table = make_hash_table (0);
+
+  if ((item = find_hash_item (string, table)) == 0)
+    {
+      int bucket = hash_string (string, table);
+      item = table->bucket_array[bucket];
+
+      while (item && item->next)
+       item = item->next;
+
+      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->key = string;
+      table->nentries++;
+      item->times_found = 0;
+    }
+
+  return (item);
+}
+
+/* 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;
+     HASH_TABLE *table;
+{
+  if (table && bucket < table->nbuckets)
+    return (table->bucket_array[bucket]);
+  else
+    return (BUCKET_CONTENTS *)NULL;
+}
+
+#ifdef TEST_HASHING
+
+#undef NULL
+#include <stdio.h>
+
+HASH_TABLE *table;
+#define NBUCKETS 107
+
+char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *result = (char *)malloc (bytes);
+  if (!result)
+    {
+      fprintf (stderr, "Out of memory!");
+      abort ();
+    }
+  return (result);
+}
+
+main ()
+{
+  char string[256];
+  int count = 0;
+  BUCKET_CONTENTS *tt;
+
+  table = make_hash_table (NBUCKETS);
+  
+  for (;;)
+    {
+      char *temp_string;
+      if (fgets (string, sizeof (string), stdin) == 0)
+        break;
+      if (!*string)
+        break;
+      temp_string = savestring (string);
+      tt = add_hash_item (temp_string, table);
+      if (tt->times_found)
+       {
+         fprintf (stderr, "You have already added item `%s'\n", string);
+         free (temp_string);
+       }
+      else
+       {
+         count++;
+       }
+    }
+  
+  printf ("You have entered %d (%d) items.  The distribution is:\n",
+         table->nentries, count);
+
+  /* Print out a count of how many strings hashed to each bucket, so we can
+     see how even the distribution is. */
+  for (count = 0; count < table->nbuckets; count++)
+    {
+      int bcount;
+      register BUCKET_CONTENTS *list = get_hash_bucket (count, table);
+    
+      printf ("slot %3d: ", count);
+      bcount = 0;
+
+      for (bcount = 0; list; list = list->next)
+        bcount++;
+
+      printf ("%d\n", bcount);
+    }
+    exit (0);
+}
+
+#endif /* TEST_HASHING */
+\f
+/*
+ * Local variables:
+ * compile-command: "gcc -g -DTEST_HASHING -o hash hash.c"
+ * end:
+ */
diff --git a/hash.h b/hash.h
new file mode 100644 (file)
index 0000000..5458787
--- /dev/null
+++ b/hash.h
@@ -0,0 +1,61 @@
+/* hash.h -- the data structures used in hashing in Bash. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_HASH_H_)
+#define _HASH_H_
+
+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. */
+  int times_found;             /* Number of times this item has been found. */
+} BUCKET_CONTENTS;
+
+typedef struct hash_table {
+  BUCKET_CONTENTS **bucket_array;      /* Where the data is kept. */
+  int nbuckets;                        /* How many buckets does this table have. */
+  int nentries;                        /* How many entries does this table have. */
+} HASH_TABLE;
+
+extern int hash_string ();
+extern HASH_TABLE *make_hash_table ();
+extern BUCKET_CONTENTS *find_hash_item ();
+extern BUCKET_CONTENTS *remove_hash_item ();
+extern BUCKET_CONTENTS *add_hash_item ();
+extern BUCKET_CONTENTS *get_hash_bucket ();
+
+/* Redefine the function as a macro for speed. */
+#define get_hash_bucket(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 107
+
+#if !defined (NULL)
+#  if defined (__STDC__)
+#    define NULL ((void *) 0)
+#  else
+#    define NULL 0x0
+#  endif /* !__STDC__ */
+#endif /* !NULL */
+
+#endif /* _HASH_H */
diff --git a/input.c b/input.c
new file mode 100644 (file)
index 0000000..852d369
--- /dev/null
+++ b/input.c
@@ -0,0 +1,464 @@
+/* input.c -- functions to perform buffered input with synchronization. */
+
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* similar to stdio, but input-only. */
+
+#include "bashtypes.h"
+#include <sys/file.h>
+#include "filecntl.h"
+#include "posixstat.h"
+#include <stdio.h>
+#include <errno.h>
+
+#include "bashansi.h"
+#include "config.h"
+#include "command.h"
+#include "general.h"
+#include "input.h"
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#define MAX_INPUT_BUFFER_SIZE  8192
+
+#if !defined (SEEK_CUR)
+#  define SEEK_CUR 1
+#endif /* !SEEK_CUR */
+
+void free_buffered_stream ();
+
+extern int interactive_shell;
+
+int bash_input_fd_changed;
+/* This provides a way to map from a file descriptor to the buffer
+   associated with that file descriptor, rather than just the other
+   way around.  This is needed so that buffers are managed properly
+   in constructs like 3<&4.  buffers[x]->b_fd == x -- that is how the
+   correspondence is maintained. */
+BUFFERED_STREAM **buffers = (BUFFERED_STREAM **)NULL;
+static int nbuffers = 0;
+
+#define max(a, b)  (((a) > (b)) ? (a) : (b))
+
+#define ALLOCATE_BUFFERS(n) \
+       do { if ((n) >= nbuffers) allocate_buffers (n); } while (0)
+
+/* Make sure `buffers' has at least N elements. */
+static void
+allocate_buffers (n)
+     int n;
+{
+  register int i, orig_nbuffers;
+
+  orig_nbuffers = nbuffers;
+  nbuffers = n + 20;
+  buffers = (BUFFERED_STREAM **)xrealloc
+    (buffers, nbuffers * sizeof (BUFFERED_STREAM *));
+
+  /* Zero out the new buffers. */
+  for (i = orig_nbuffers; i < nbuffers; i++)
+    buffers[i] = (BUFFERED_STREAM *)NULL;
+}
+
+/* Construct and return a BUFFERED_STREAM corresponding to file descriptor
+   FD, using BUFFER. */
+static BUFFERED_STREAM *
+make_buffered_stream (fd, buffer, bufsize)
+     int fd;
+     char *buffer;
+     int bufsize;
+{
+  BUFFERED_STREAM *bp;
+
+  bp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
+  ALLOCATE_BUFFERS (fd);
+  buffers[fd] = bp;
+  bp->b_fd = fd;
+  bp->b_buffer = buffer;
+  bp->b_size = bufsize;
+  bp->b_used = 0;
+  bp->b_inputp = 0;
+  bp->b_flag = 0;
+  if (bufsize == 1)
+    bp->b_flag |= B_UNBUFF;
+  return (bp);
+}
+
+/* Allocate a new BUFFERED_STREAM, copy BP to it, and return the new copy. */
+static BUFFERED_STREAM *
+copy_buffered_stream (bp)
+     BUFFERED_STREAM *bp;
+{
+  BUFFERED_STREAM *nbp;
+
+  if (!bp)
+    return ((BUFFERED_STREAM *)NULL);
+
+  nbp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
+  xbcopy ((char *)bp, (char *)nbp, sizeof (BUFFERED_STREAM));
+  return (nbp);
+}
+
+/* Check that file descriptor FD is not the one that bash is currently
+   using to read input from a script.  FD is about to be duplicated onto,
+   which means that the kernel will close it for us.  If FD is the bash
+   input file descriptor, we need to seek backwards in the script (if
+   possible and necessary -- scripts read from stdin are still unbuffered),
+   allocate a new file descriptor to use for bash input, and re-initialize
+   the buffered stream. */
+int
+check_bash_input (fd)
+     int fd;
+{
+  int nfd;
+
+  if (fd > 0 && ((bash_input.type == st_bstream && bash_input.location.buffered_fd == fd) ||
+                (interactive_shell == 0 && default_buffered_input == fd)))
+    {
+      /* Sync the stream so we can re-read from the new file descriptor.  We
+        might be able to avoid this by copying the buffered stream verbatim
+        to the new file descriptor. */
+      if (buffers[fd])
+       sync_buffered_stream (fd);
+
+      /* Now take care of duplicating the file descriptor that bash is
+        using for input, so we can reinitialize it later. */
+      nfd = fcntl (fd, F_DUPFD, 10);
+      if (nfd == -1)
+       {
+         if (fcntl (fd, F_GETFD, 0) == 0)
+           report_error
+             ("cannot allocate new file descriptor for bash input from fd %d: %s",
+               fd, strerror (errno));
+         return -1;
+       }
+
+      if (buffers[nfd])
+       {
+         /* What's this?  A stray buffer without an associated open file
+            descriptor?  Free up the buffer and report the error. */
+         report_error ("check_bash_input: buffer already exists for new fd %d", nfd);
+         free_buffered_stream (buffers[nfd]);
+       }
+
+      /* Reinitialize bash_input.location. */
+      if (bash_input.type == st_bstream)
+       {
+         bash_input.location.buffered_fd = nfd;
+         fd_to_buffered_stream (nfd);
+         close_buffered_fd (fd);       /* XXX */
+       }
+      else
+       /* If the current input type is not a buffered stream, but the shell
+          is not interactive and therefore using a buffered stream to read
+          input (e.g. with an `eval exec 3>output' inside a script), note
+          that the input fd has been changed.  pop_stream() looks at this
+          value and adjusts the input fd to the new value of
+          default_buffered_input accordingly. */
+       bash_input_fd_changed++;
+
+      if (default_buffered_input == fd)
+       default_buffered_input = nfd;
+    }
+  return 0;
+}
+      
+/* This is the buffered stream analogue of dup2(fd1, fd2).  The
+   BUFFERED_STREAM corresponding to fd2 is deallocated, if one exists.
+   BUFFERS[fd1] is copied to BUFFERS[fd2].  This is called by the
+   redirect code for constructs like 4<&0 and 3</etc/rc.local. */
+duplicate_buffered_stream (fd1, fd2)
+     int fd1, fd2;
+{
+  int is_bash_input, m;
+
+  if (fd1 == fd2)
+    return 0;
+
+  m = max (fd1, fd2);
+  ALLOCATE_BUFFERS (m);
+
+  /* If FD2 is the file descriptor bash is currently using for shell input,
+     we need to do some extra work to make sure that the buffered stream
+     actually exists (it might not if fd1 was not active, and the copy
+     didn't actually do anything). */
+  is_bash_input = (bash_input.type == st_bstream) &&
+                 (bash_input.location.buffered_fd == fd2);
+
+  if (buffers[fd2])
+    free_buffered_stream (buffers[fd2]);
+  buffers[fd2] = copy_buffered_stream (buffers[fd1]);
+  if (buffers[fd2])
+    buffers[fd2]->b_fd = fd2;
+
+  if (is_bash_input)
+    {
+      if (!buffers[fd2])
+       fd_to_buffered_stream (fd2);
+    }
+  return (fd2);
+}
+
+/* Return 1 if a seek on FD will succeed. */
+#define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0)
+
+/* Take FD, a file descriptor, and create and return a buffered stream
+   corresponding to it.  If something is wrong and the file descriptor
+   is invalid, return a NULL stream. */
+BUFFERED_STREAM *
+fd_to_buffered_stream (fd)
+     int fd;
+{
+  char *buffer;
+  int size;
+  struct stat sb;
+
+  if (fstat (fd, &sb) < 0)
+    {
+      close (fd);
+      return ((BUFFERED_STREAM *)NULL);
+    }
+
+  if (fd_is_seekable (fd) == 0)
+    size = 1;
+  else
+    size = (sb.st_size > MAX_INPUT_BUFFER_SIZE) ? MAX_INPUT_BUFFER_SIZE
+                                               : sb.st_size;
+      
+  buffer = (char *)xmalloc (size);
+
+  return (make_buffered_stream (fd, buffer, size));
+}
+
+/* Return a buffered stream corresponding to FILE, a file name. */
+BUFFERED_STREAM *
+open_buffered_stream (file)
+     char *file;
+{
+  int fd;
+
+  fd = open (file, O_RDONLY);
+  if (fd == -1)
+    return ((BUFFERED_STREAM *)NULL);
+  return (fd_to_buffered_stream (fd));
+}
+
+/* Deallocate a buffered stream and free up its resources.  Make sure we
+   zero out the slot in BUFFERS that points to BP. */
+void
+free_buffered_stream (bp)
+     BUFFERED_STREAM *bp;
+{
+  int n;
+
+  if (!bp)
+    return;
+
+  n = bp->b_fd;
+  if (bp->b_buffer)
+    free (bp->b_buffer);
+  free (bp);
+  buffers[n] = (BUFFERED_STREAM *)NULL;
+}
+
+/* Close the file descriptor associated with BP, a buffered stream, and free
+   up the stream.  Return the status of closing BP's file descriptor. */
+int
+close_buffered_stream (bp)
+     BUFFERED_STREAM *bp;
+{
+  int fd;
+
+  if (!bp)
+    return (0);
+  fd = bp->b_fd;
+  free_buffered_stream (bp);
+  return (close (fd));
+}
+
+/* Deallocate the buffered stream associated with file descriptor FD, and
+   close FD.  Return the status of the close on FD. */
+int
+close_buffered_fd (fd)
+     int fd;
+{
+  if (fd >= nbuffers || !buffers || !buffers[fd])
+    return (close (fd));
+  return (close_buffered_stream (buffers[fd]));
+}
+
+/* Read a buffer full of characters from BP, a buffered stream. */
+static int
+b_fill_buffer (bp)
+     BUFFERED_STREAM *bp;
+{
+  do
+    {
+      bp->b_used = read (bp->b_fd, bp->b_buffer, bp->b_size);
+    }
+  while (bp->b_used < 0 && errno == EINTR);
+  if (bp->b_used <= 0)
+    {
+      bp->b_buffer[0] = 0;
+      if (bp->b_used == 0)
+       bp->b_flag |= B_EOF;
+      else
+       bp->b_flag |= B_ERROR;
+      return (EOF);
+    }
+  bp->b_inputp = 0;
+  return (bp->b_buffer[bp->b_inputp++] & 0xFF);
+}
+
+/* Get a character from buffered stream BP. */
+#define bufstream_getc(bp) \
+  (bp->b_inputp == bp->b_used || !bp->b_used) \
+               ? b_fill_buffer (bp) \
+               : bp->b_buffer[bp->b_inputp++] & 0xFF
+
+/* Push C back onto buffered stream BP. */
+static int
+bufstream_ungetc(c, bp)
+     int c;
+     BUFFERED_STREAM *bp;
+{
+  if (c == EOF || bp->b_inputp == 0)
+    return (EOF);
+
+  bp->b_buffer[--bp->b_inputp] = c;
+  return (c);
+}
+
+/* Seek backwards on file BFD to synchronize what we've read so far
+   with the underlying file pointer. */
+int
+sync_buffered_stream (bfd)
+     int bfd;
+{
+  BUFFERED_STREAM *bp;
+  int chars_left;
+
+  bp = buffers[bfd];
+  if (!bp)
+    return (-1);
+  chars_left = bp->b_used - bp->b_inputp;
+  if (chars_left)
+    lseek (bp->b_fd, -chars_left, SEEK_CUR);
+  bp->b_used = bp->b_inputp = 0;
+  return (0);
+}
+
+int
+buffered_getchar ()
+{
+  return (bufstream_getc (buffers[bash_input.location.buffered_fd]));
+}
+
+int
+buffered_ungetchar (c)
+     int c;
+{
+  return (bufstream_ungetc (c, buffers[bash_input.location.buffered_fd]));
+}
+
+/* Make input come from file descriptor BFD through a buffered stream. */
+void
+with_input_from_buffered_stream (bfd, name)
+     int bfd;
+     char *name;
+{
+  INPUT_STREAM location;
+
+  location.buffered_fd = bfd;
+  /* Make sure the buffered stream exists. */
+  fd_to_buffered_stream (bfd);
+  init_yy_io (buffered_getchar, buffered_ungetchar, st_bstream, name, location);
+}
+
+#if defined (TEST)
+
+char *
+xmalloc(s)
+int s;
+{
+       return ((char *)malloc (s));
+}
+
+char *
+xrealloc(s, size)
+char   *s;
+int    size;
+{
+       if (!s)
+               return((char *)malloc (size));
+       else
+               return((char *)realloc (s, size));
+}
+
+void
+init_yy_io ()
+{
+}
+
+process(bp)
+BUFFERED_STREAM *bp;
+{
+       int c;
+
+       while ((c = bufstream_getc(bp)) != EOF)
+               putchar(c);
+}
+
+BASH_INPUT bash_input;
+
+struct stat dsb;               /* can be used from gdb */
+
+/* imitate /bin/cat */
+main(argc, argv)
+int    argc;
+char   **argv;
+{
+       register int i;
+       BUFFERED_STREAM *bp;
+
+       if (argc == 1) {
+               bp = fd_to_buffered_stream (0);
+               process(bp);
+               exit(0);
+       }
+       for (i = 1; i < argc; i++) {
+               if (argv[i][0] == '-' && argv[i][1] == '\0') {
+                       bp = fd_to_buffered_stream (0);
+                       if (!bp)
+                               continue;
+                       process(bp);
+                       free_buffered_stream (bp);
+               } else {
+                       bp = open_buffered_stream (argv[i]);
+                       if (!bp)
+                               continue;
+                       process(bp);
+                       close_buffered_stream (bp);
+               }
+       }
+       exit(0);
+}
+#endif
diff --git a/input.h b/input.h
new file mode 100644 (file)
index 0000000..1824b40
--- /dev/null
+++ b/input.h
@@ -0,0 +1,115 @@
+/* input.h -- Structures and unions used for reading input. */
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_INPUT_H)
+#define _INPUT_H
+
+#include "stdc.h"
+
+/* Function pointers can be declared as (Function *)foo. */
+#if !defined (__FUNCTION_DEF)
+#  define __FUNCTION_DEF
+typedef int Function ();
+typedef void VFunction ();
+typedef char *CPFunction ();
+typedef char **CPPFunction ();
+#endif /* _FUNCTION_DEF */
+
+/* Some stream `types'. */
+#define st_none   0
+#define st_stream 1
+#define st_string 2
+#define st_stdin  3
+
+#if defined (BUFFERED_INPUT)
+#define st_bstream 4
+
+/* Possible values for b_flag. */
+#define B_EOF          0x1
+#define B_ERROR                0x2
+#define B_UNBUFF       0x4
+
+/* A buffered stream.  Like a FILE *, but with our own buffering and
+   synchronization.  Look in input.c for the implementation. */
+typedef struct BSTREAM
+{
+  int  b_fd;
+  char *b_buffer;              /* The buffer that holds characters read. */
+  int  b_size;                 /* How big the buffer is. */
+  int  b_used;                 /* How much of the buffer we're using, */
+  int  b_flag;                 /* Flag values. */
+  int  b_inputp;               /* The input pointer, index into b_buffer. */
+} BUFFERED_STREAM;
+
+extern BUFFERED_STREAM **buffers;
+
+extern BUFFERED_STREAM *fd_to_buffered_stream ();
+
+extern int default_buffered_input;
+
+#endif /* BUFFERED_INPUT */
+
+typedef union {
+  FILE *file;
+  char *string;
+#if defined (BUFFERED_INPUT)
+  int buffered_fd;
+#endif
+} INPUT_STREAM;
+
+typedef struct {
+  int type;
+  char *name;
+  INPUT_STREAM location;
+  Function *getter;
+  Function *ungetter;
+} BASH_INPUT;
+
+extern BASH_INPUT bash_input;
+
+/* Functions from parse.y. */
+extern void initialize_bash_input __P((void));
+extern void init_yy_io __P((Function *, Function *, int, char *, INPUT_STREAM));
+extern void with_input_from_stdin __P((void));
+extern void with_input_from_string __P((char *, char *));
+extern void with_input_from_stream __P((FILE *, char *));
+extern int push_stream __P((void));
+extern int pop_stream __P((void));
+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 *));
+
+#if defined (BUFFERED_INPUT)
+/* Functions from input.c. */
+extern int check_bash_input __P((int));
+extern int duplicate_buffered_stream __P((int, int));
+extern BUFFERED_STREAM *fd_to_buffered_stream __P((int));
+extern BUFFERED_STREAM *open_buffered_stream __P((char *));
+extern void free_buffered_stream __P((BUFFERED_STREAM *));
+extern int close_buffered_stream __P((BUFFERED_STREAM *));
+extern int close_buffered_fd __P((int));
+extern int sync_buffered_stream __P((int));
+extern int buffered_getchar __P((void));
+extern int buffered_ungetchar __P((int));
+extern void with_input_from_buffered_stream __P((int, char *));
+#endif /* BUFFERED_INPUT */
+
+#endif /* _INPUT_H */
diff --git a/jobs.c b/jobs.c
new file mode 100644 (file)
index 0000000..40e7f7d
--- /dev/null
+++ b/jobs.c
@@ -0,0 +1,2755 @@
+/* The thing that makes children, remembers them, and contains wait loops. */
+
+/* This file works with both POSIX and BSD systems. */
+
+/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 1, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Something that can be ignored. */
+#define IGNORE_ARG (char *)0
+
+#include "config.h"
+
+#if !defined (JOB_CONTROL)
+#include "nojobs.c"
+#else /* JOB_CONTROL */
+
+#include "bashtypes.h"
+#include "trap.h"
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+
+#if !defined (USG) || defined (HAVE_RESOURCE)
+#include <sys/time.h>
+#endif /* USG */
+
+#if !defined (_POSIX_VERSION)
+#  if defined (HAVE_RESOURCE)
+#    include <sys/resource.h>
+#  endif
+#endif /* _POSIX_VERSION */
+
+#include <sys/file.h>
+#include "filecntl.h"
+#include <sys/ioctl.h>
+#include <sys/param.h>
+
+#if defined (BUFFERED_INPUT)
+#  include "input.h"
+#endif
+
+/* Terminal handling stuff, to save and restore tty state. */
+#define NEW_TTY_DRIVER
+
+/* Define this if your output is getting swallowed.  It's a no-op on
+   machines with the termio or termios tty drivers. */
+/* #define DRAIN_OUTPUT */
+
+#if defined (_POSIX_VERSION) && !defined (TERMIOS_MISSING)
+#  undef NEW_TTY_DRIVER
+#  define TERMIOS_TTY_DRIVER
+#  if defined (sun) && !defined (_POSIX_SOURCE)        /* XXX - SunOS4, SunOS5? */
+#    define _POSIX_SOURCE
+#  endif
+#else /* !_POSIX_VERSION */
+#  if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi)
+#    undef NEW_TTY_DRIVER
+#    define TERMIO_TTY_DRIVER
+#  endif /* USG | hpux | Xenix | sgi */
+#endif /* !_POSIX_VERSION */
+
+/* Include the right header file for the specific type of terminal
+   handler installed on this system. */
+#if defined (NEW_TTY_DRIVER)
+#include <sgtty.h>
+#endif
+
+#if defined (TERMIO_TTY_DRIVER)
+#include <termio.h>
+#endif
+
+#if defined (TERMIOS_TTY_DRIVER)
+/* For Sun workstations we undefine a couple of defines so that
+   the inclusion of termios.h won't cause complaints. */
+#  if defined (SunOS4)
+#    undef ECHO
+#    undef NOFLSH
+#    undef TOSTOP
+#  endif /* SunOS4 */
+#  include <termios.h>
+#endif /* TERMIOS_TTY_DRIVER */
+
+/* For the TIOCGPGRP and TIOCSPGRP ioctl parameters on HP-UX */
+
+#if defined (hpux) && !defined (TERMIOS_TTY_DRIVER)
+#  include <bsdtty.h>
+#endif /* hpux && !TERMIOS_TTY_DRIVER */
+
+#include "bashansi.h"
+#include "shell.h"
+#include "jobs.h"
+
+#include "builtins/builtext.h"
+#include "builtins/common.h"
+
+/* Not all systems declare errno in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+/* Variables used here but defined in other files. */
+extern int interactive, interactive_shell, asynchronous_notification;
+extern int subshell_environment;
+extern int posixly_correct, no_symbolic_links, shell_level;
+extern int interrupt_immediately, last_command_exit_value;
+extern int loop_level, breaking;
+extern Function *this_shell_builtin;
+extern char *shell_name, *this_command_name;
+extern sigset_t top_level_mask;
+
+/* The array of known jobs. */
+JOB **jobs = (JOB **)NULL;
+
+/* The number of slots currently allocated to JOBS. */
+int job_slots = 0;
+
+/* The number of additional slots to allocate when we run out. */
+#define JOB_SLOTS 5
+
+/* The controlling tty for this shell. */
+int shell_tty = -1;
+
+/* The shell's process group. */
+pid_t shell_pgrp = NO_PID;
+
+/* The terminal's process group. */
+pid_t terminal_pgrp = NO_PID;
+
+/* The process group of the shell's parent. */
+pid_t original_pgrp = NO_PID;
+
+/* The process group of the pipeline currently being made. */
+pid_t pipeline_pgrp = (pid_t)0;
+
+#if defined (PGRP_PIPE)
+/* Pipes which each shell uses to communicate with the process group leader
+   until all of the processes in a pipeline have been started.  Then the
+   process leader is allowed to continue. */
+int pgrp_pipe[2] = { -1, -1 };
+#endif
+      
+/* The job which is current; i.e. the one that `%+' stands for. */
+int current_job = NO_JOB;
+
+/* The previous job; i.e. the one that `%-' stands for. */
+int previous_job = NO_JOB;
+
+/* Last child made by the shell.  */
+pid_t last_made_pid = NO_PID;
+
+/* Pid of the last asynchronous child. */
+pid_t last_asynchronous_pid = NO_PID;
+
+/* The pipeline currently being built. */
+PROCESS *the_pipeline = (PROCESS *)NULL;
+
+/* If this is non-zero, do job control. */
+int job_control = 1;
+
+/* Call this when you start making children. */
+int already_making_children = 0;
+
+/* Functions local to this file. */
+static sighandler flush_child ();
+static int waitchld();
+static PROCESS *find_pipeline ();
+static char *current_working_directory ();
+static char *job_working_directory ();
+static pid_t last_pid ();
+static int set_new_line_discipline (), map_over_jobs (), last_running_job ();
+static int most_recent_job_in_state (), last_stopped_job (), find_job ();
+static void notify_of_job_status (), cleanup_dead_jobs (), discard_pipeline ();
+static void add_process (), set_current_job (), reset_current ();
+static void pretty_print_job ();
+static void mark_dead_jobs_as_notified ();
+#if defined (PGRP_PIPE)
+static void pipe_read (), pipe_close ();
+#endif
+
+static int waiting_for_job, sigchld;
+
+/* Set this to non-zero whenever you don't want the jobs list to change at
+   all: no jobs deleted and no status change notifications.  This is used,
+   for example, when executing SIGCHLD traps, which may run arbitrary
+   commands. */
+static int freeze_jobs_list;
+
+#if !defined (_POSIX_VERSION)
+
+/* These are definitions to map POSIX 1003.1 functions onto existing BSD
+   library functions and system calls. */
+#define setpgid(pid, pgrp)     setpgrp (pid, pgrp)
+#define tcsetpgrp(fd, pgrp)    ioctl ((fd), TIOCSPGRP, &(pgrp))
+
+pid_t
+tcgetpgrp (fd)
+     int fd;
+{
+  pid_t pgrp;
+
+  /* ioctl will handle setting errno correctly. */
+  if (ioctl (fd, TIOCGPGRP, &pgrp) < 0)
+    return (-1);
+  return (pgrp);
+}
+
+/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
+sigprocmask (operation, newset, oldset)
+     int operation, *newset, *oldset;
+{
+  int old, new;
+
+  if (newset)
+    new = *newset;
+  else
+    new = 0;
+
+  switch (operation)
+    {
+    case SIG_BLOCK:
+      old = sigblock (new);
+      break;
+
+    case SIG_SETMASK:
+      sigsetmask (new);
+      break;
+
+    default:
+      internal_error ("Bad code in jobs.c: sigprocmask");
+    }
+
+  if (oldset)
+    *oldset = old;
+}
+#endif /* !_POSIX_VERSION */
+
+/* Return the working directory for the current process.  Unlike
+   job_working_directory, this does not call malloc (), nor do any
+   of the functions it calls.  This is so that it can safely be called
+   from a signal handler. */
+static char *
+current_working_directory ()
+{
+  char *dir;
+  static char d[MAXPATHLEN];
+
+  dir = get_string_value ("PWD");
+
+  if (!dir && the_current_working_directory && no_symbolic_links)
+    dir = the_current_working_directory;
+
+  if (!dir)
+    {
+      dir = getwd (d);
+      if (dir)
+       dir = d;
+    }
+
+  if (!dir)
+    return ("<unknown>");
+  else
+    return (dir);
+}
+
+/* Return the working directory for the current process. */
+static char *
+job_working_directory ()
+{
+  char *dir;
+
+  dir = get_string_value ("PWD");
+  if (dir)
+    return (savestring (dir));
+
+  dir = get_working_directory ("job-working-directory");
+  if (dir)
+    return (dir);
+
+  return (savestring ("<unknown>"));
+}
+
+void
+making_children ()
+{
+  if (already_making_children)
+    return;
+
+  already_making_children = 1;
+  start_pipeline ();
+}
+
+void
+stop_making_children ()
+{
+  already_making_children = 0;
+}
+
+void
+cleanup_the_pipeline ()
+{
+  if (the_pipeline)
+    {
+      discard_pipeline (the_pipeline);
+      the_pipeline = (PROCESS *)NULL;
+    }
+}
+
+/* Start building a pipeline.  */
+void
+start_pipeline ()
+{
+  if (the_pipeline)
+    {
+      discard_pipeline (the_pipeline);
+      the_pipeline = (PROCESS *)NULL;
+      pipeline_pgrp = 0;
+#if defined (PGRP_PIPE)
+      pipe_close (pgrp_pipe);
+#endif
+    }
+
+#if defined (PGRP_PIPE)
+  if (job_control)
+    {
+      if (pipe (pgrp_pipe) == -1)
+       internal_error ("start_pipeline: pgrp pipe");
+    }
+#endif
+}
+
+/* Stop building a pipeline.  Install the process list in the job array.
+   This returns the index of the newly installed job.
+   DEFERRED is a command structure to be executed upon satisfactory
+   execution exit of this pipeline. */
+int
+stop_pipeline (async, deferred)
+     int async;
+     COMMAND *deferred;
+{
+  register int i, j;
+  JOB *newjob = (JOB *)NULL;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+#if defined (PGRP_PIPE)
+  /* The parent closes the process group synchronization pipe. */
+  pipe_close (pgrp_pipe);
+#endif
+    
+  cleanup_dead_jobs ();
+
+  if (!job_slots)
+    {
+      jobs =
+       (JOB **)xmalloc ((job_slots = JOB_SLOTS) * sizeof (JOB *));
+
+      /* Now blank out these new entries. */
+      for (i = 0; i < job_slots; i++)
+       jobs[i] = (JOB *)NULL;
+    }
+
+  /* Scan from the last slot backward, looking for the next free one. */
+  if (interactive)
+    {
+      for (i = job_slots; i; i--)
+       if (jobs[i - 1])
+         break;
+    }
+  else
+    {
+      /* If we're not interactive, we don't need to monotonically increase
+        the job number (in fact, we don't care about the job number at all),
+        so we can simply scan for the first free slot.  This helps to keep
+        us from continuously reallocating the jobs array when running
+        certain kinds of shell loops, and saves time spent searching. */
+      for (i = 0; i < job_slots; i++)
+       if (!jobs[i])
+         break;
+    }
+
+  /* Do we need more room? */
+  if (i == job_slots)
+    {
+      job_slots += JOB_SLOTS;
+      jobs = (JOB **)xrealloc (jobs, ((1 + job_slots) * sizeof (JOB *)));
+
+      for (j = i; j < job_slots; j++)
+       jobs[j] = (JOB *)NULL;
+    }
+
+  /* Add the current pipeline to the job list. */
+  if (the_pipeline)
+    {
+      register PROCESS *p;
+
+      newjob = (JOB *)xmalloc (sizeof (JOB));
+
+      for (p = the_pipeline; p->next != the_pipeline; p = p->next);
+      p->next = (PROCESS *)NULL;
+      newjob->pipe = REVERSE_LIST (the_pipeline, PROCESS *);
+      for (p = newjob->pipe; p->next; p = p->next);
+      p->next = newjob->pipe;
+
+      the_pipeline = (PROCESS *)NULL;
+      newjob->pgrp = pipeline_pgrp;
+      pipeline_pgrp = 0;
+
+      newjob->flags = 0;
+
+      /* Flag to see if in another pgrp. */
+      if (job_control)
+       newjob->flags |= J_JOBCONTROL;
+
+      /* Set the state of this pipeline. */
+      {
+       register PROCESS *p = newjob->pipe;
+       register int any_alive = 0;
+       register int any_stopped = 0;
+
+       do
+         {
+           any_alive |= p->running;
+           any_stopped |= WIFSTOPPED (p->status);
+           p = p->next;
+         }
+       while (p != newjob->pipe);
+
+       if (any_alive)
+         {
+           newjob->state = JRUNNING;
+         }
+       else
+         {
+           if (any_stopped)
+             newjob->state = JSTOPPED;
+           else
+             newjob->state = JDEAD;
+         }
+      }
+
+      newjob->wd = job_working_directory ();
+      newjob->deferred = deferred;
+
+      jobs[i] = newjob;
+    }
+
+  if (async)
+    {
+      if (newjob)
+       newjob->flags &= ~J_FOREGROUND;
+      reset_current ();
+    }
+  else
+    {
+      if (newjob)
+       {
+         newjob->flags |= J_FOREGROUND;
+         /*
+          *            !!!!! NOTE !!!!!  (chet@ins.cwru.edu)
+          *
+          * The currently-accepted job control wisdom says to set the
+          * terminal's process group n+1 times in an n-step pipeline:
+          * once in the parent and once in each child.  This is where
+          * the parent gives it away.
+          *
+          */
+         if (job_control && newjob->pgrp)
+           give_terminal_to (newjob->pgrp);
+       }
+    }
+
+  stop_making_children ();
+  UNBLOCK_CHILD (oset);
+  return (current_job);
+}
+
+/* Delete all DEAD jobs that the user had received notification about. */
+static void
+cleanup_dead_jobs ()
+{
+  register int i;
+  sigset_t set, oset;
+
+  if (!job_slots || freeze_jobs_list)
+    return;
+
+  BLOCK_CHILD (set, oset);
+
+  for (i = 0; i < job_slots; i++)
+    if (jobs[i] && JOBSTATE (i) == JDEAD && (jobs[i]->flags & J_NOTIFIED))
+      delete_job (i);
+
+  UNBLOCK_CHILD (oset);
+}
+
+/* Delete the job at INDEX from the job list.  Must be called
+   with SIGCHLD blocked. */
+void
+delete_job (job_index)
+     int job_index;
+{
+  register JOB *temp;
+
+  if (freeze_jobs_list)
+    return;
+
+  temp = jobs[job_index];
+  if (job_index == current_job || job_index == previous_job)
+    reset_current ();
+
+  jobs[job_index] = (JOB *)NULL;
+
+  free (temp->wd);
+  discard_pipeline (temp->pipe);
+
+  if (temp->deferred)
+    dispose_command (temp->deferred);
+
+  free (temp);
+}
+
+/* Get rid of the data structure associated with a process chain. */
+static void
+discard_pipeline (chain)
+     register PROCESS *chain;
+{
+  register PROCESS *this, *next;
+
+  this = chain;
+  do
+    {
+      next = this->next;
+      if (this->command)
+       free (this->command);
+      free (this);
+      this = next;
+    }
+  while (this != chain);
+}
+
+/* Add this process to the chain being built in the_pipeline.
+   NAME is the command string that will be exec'ed later.
+   PID is the process id of the child. */
+static void
+add_process (name, pid)
+     char *name;
+     pid_t pid;
+{
+  PROCESS *t = (PROCESS *)xmalloc (sizeof (PROCESS));
+
+  t->next = the_pipeline;
+  t->pid = pid;
+  WSTATUS (t->status) = 0;
+  t->running = 1;
+  t->command = name;
+  the_pipeline = t;
+
+  if (!(t->next))
+    t->next = t;
+  else
+    {
+      register PROCESS *p = t->next;
+
+      while (p->next != t->next)
+       p = p->next;
+      p->next = t;
+    }
+}
+
+#if 0
+/* Take the last job and make it the first job.  Must be called with
+   SIGCHLD blocked. */
+rotate_the_pipeline ()
+{
+  PROCESS *p;
+
+  if (the_pipeline->next == the_pipeline)
+    return;
+  for (p = the_pipeline; p->next != the_pipeline; p = p->next)
+    ;
+  the_pipeline = p;
+}
+
+/* Reverse the order of the processes in the_pipeline.  Must be called with
+   SIGCHLD blocked. */
+reverse_the_pipeline ()
+{
+  PROCESS *p, *n;
+
+  if (the_pipeline->next == the_pipeline)
+    return;
+
+  for (p = the_pipeline; p->next != the_pipeline; p = p->next)
+    ;
+  p->next = (PROCESS *)NULL;
+
+  n = REVERSE_LIST (the_pipeline, PROCESS *);
+
+  the_pipeline = n;
+  for (p = the_pipeline; p->next; p = p->next)
+    ;
+  p->next = the_pipeline;
+}
+#endif
+
+/* Map FUNC over the list of jobs.  If FUNC returns non-zero,
+   then it is time to stop mapping, and that is the return value
+   for map_over_jobs.  FUNC is called with a JOB, arg1, arg2,
+   and INDEX. */
+static int
+map_over_jobs (func, arg1, arg2)
+     Function *func;
+     int arg1, arg2;
+{
+  register int i;
+  int result;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+  result = 0;
+
+  for (i = 0; i < job_slots; i++)
+    {
+      if (jobs[i])
+       {
+         result = (*func)(jobs[i], arg1, arg2, i);
+         if (result)
+           break;
+       }
+    }
+
+  UNBLOCK_CHILD (oset);
+  return (result);
+}
+
+/* Cause all the jobs in the current pipeline to exit. */
+void
+terminate_current_pipeline ()
+{
+  if (pipeline_pgrp && pipeline_pgrp != shell_pgrp)
+    {
+      killpg (pipeline_pgrp, SIGTERM);
+      killpg (pipeline_pgrp, SIGCONT);
+    }
+}
+
+/* Cause all stopped jobs to exit. */
+void
+terminate_stopped_jobs ()
+{
+  register int i;
+
+  for (i = 0; i < job_slots; i++)
+    {
+      if (jobs[i] && (JOBSTATE (i) == JSTOPPED))
+       {
+         killpg (jobs[i]->pgrp, SIGTERM);
+         killpg (jobs[i]->pgrp, SIGCONT);
+       }
+    }
+}
+
+/* Cause all jobs, running or stopped, to receive a hangup signal. */
+void
+hangup_all_jobs ()
+{
+  register int i;
+
+  for (i = 0; i < job_slots; i++)
+    {
+      if (jobs[i])
+       {
+         killpg (jobs[i]->pgrp, SIGHUP);
+         if (JOBSTATE (i) == JSTOPPED)
+           killpg (jobs[i]->pgrp, SIGCONT);
+       }
+    }
+}
+
+void
+kill_current_pipeline ()
+{
+  stop_making_children ();
+  start_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)
+     pid_t pid;
+{
+  int job;
+
+  /* See if this process is in the pipeline that we are building. */
+  if (the_pipeline)
+    {
+      register PROCESS *p = the_pipeline;
+
+      do
+       {
+         /* Return it if we found it. */
+         if (p->pid == pid)
+           return (p);
+
+         p = p->next;
+       }
+      while (p != the_pipeline);
+    }
+
+  job = find_job (pid);
+
+  if (job == NO_JOB)
+    return ((PROCESS *)NULL);
+  else
+    return (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)
+     pid_t pid;
+{
+  register int i;
+  register PROCESS *p;
+
+  for (i = 0; i < job_slots; i++)
+    {
+      if (jobs[i])
+       {
+         p = jobs[i]->pipe;
+
+         do
+           {
+             if (p->pid == pid)
+               return (i);
+
+             p = p->next;
+           }
+         while (p != jobs[i]->pipe);
+       }
+    }
+
+  return (NO_JOB);
+}
+
+/* Print descriptive information about the job with leader pid PID. */
+void
+describe_pid (pid)
+     pid_t pid;
+{
+  int job;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+  job = find_job (pid);
+
+  if (job != NO_JOB)
+    printf ("[%d] %d\n", job + 1, pid);
+  else
+    programming_error ("describe_pid: No such pid (%d)!\n", pid);
+
+  UNBLOCK_CHILD (oset);
+}
+
+/* This is the way to print out information on a job if you
+   know the index.  FORMAT is:
+
+    JLIST_NORMAL)   [1]+ Running          emacs
+    JLIST_LONG  )   [1]+ 2378 Running      emacs
+    -1   )   [1]+ 2378       emacs
+
+    JLIST_NORMAL)   [1]+ Stopped          ls | more
+    JLIST_LONG  )   [1]+ 2369 Stopped      ls
+                        2367       | more
+    JLIST_PID_ONLY)
+       Just list the pid of the process group leader (really
+       the process group).
+    JLIST_CHANGED_ONLY)
+       Use format JLIST_NORMAL, but list only jobs about which
+       the user has not been notified. */
+static void
+pretty_print_job (job_index, format, stream)
+     int job_index, format;
+     FILE *stream;
+{
+  register PROCESS *p, *first, *last;
+  int name_padding;
+  char retcode_name_buffer[20];
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+  /* Format only pid information about the process group leader? */
+  if (format == JLIST_PID_ONLY)
+    {
+      fprintf (stream, "%d\n", jobs[job_index]->pipe->pid);
+      UNBLOCK_CHILD (oset);
+      return;
+    }
+
+  if (format == JLIST_CHANGED_ONLY)
+    {
+      if (jobs[job_index]->flags & J_NOTIFIED)
+       {
+         UNBLOCK_CHILD (oset);
+         return;
+       }
+      format = JLIST_STANDARD;
+    }
+
+  fprintf (stream, "[%d]%c ", job_index + 1,
+          (job_index == current_job) ? '+':
+          (job_index == previous_job) ? '-' : ' ');
+
+  first = last = p = jobs[job_index]->pipe;
+  while (last->next != first)
+    last = last->next;
+
+  /* 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;
+
+  for (;;)
+    {
+      if (p != first)
+       fprintf (stream, format ? "     " : " |");
+
+      if (format)
+       fprintf (stream, "%5d", p->pid);
+
+      fprintf (stream, " ");
+
+      if (format > -1)
+       {
+         PROCESS *show = format ? p : last;
+         char *temp = "Done";
+
+         if (JOBSTATE (job_index) == JSTOPPED && !format)
+           temp = "Stopped";
+
+         if (JOBSTATE (job_index) == JRUNNING)
+           temp = "Running";
+         else
+           {
+             if (WIFSTOPPED (show->status))
+               temp = strsignal (WSTOPSIG (show->status));
+             else if (WIFSIGNALED (show->status))
+               temp = strsignal (WTERMSIG (show->status));
+             else if (WIFEXITED (show->status))
+               {
+                 int exit_status;
+
+                 temp = retcode_name_buffer;
+                 exit_status = WEXITSTATUS (show->status);
+
+                 if (!exit_status)
+                   strcpy (temp, "Done");
+                 else if (posixly_correct)
+                   sprintf (temp, "Done(%d)", exit_status);
+                 else
+                   sprintf (temp, "Exit %d", exit_status);
+               }
+             else
+               temp = "Unknown status";
+           }
+
+         if (p != first)
+           {
+             if (format)
+               {
+                 if (show->running == first->running &&
+                     WSTATUS (show->status) == WSTATUS (first->status))
+                   temp = "";
+               }
+             else
+               temp = (char *)NULL;
+           }
+
+         if (temp)
+           {
+             int templ = strlen (temp);
+             fprintf (stream, "%s", temp);
+
+             if (templ)
+               name_padding = LONGEST_SIGNAL_DESC - templ;
+             else
+               name_padding = LONGEST_SIGNAL_DESC - 2; /* strlen ("| ") */
+
+             fprintf (stream, "%*s", name_padding, "");
+
+             if ((WIFSTOPPED (show->status) == 0) && (WIFCORED (show->status)))
+               fprintf (stream, "(core dumped) ");
+           }
+       }
+
+      if (p != first && format)
+       fprintf (stream, "| ");
+
+      if (p->command)
+       fprintf (stream, "%s", p->command);
+
+      if (p == last) 
+       {
+         char *wd = current_working_directory ();
+
+         if (JOBSTATE (job_index) == JRUNNING &&
+             !(jobs[job_index]->flags & J_FOREGROUND))
+           fprintf (stream, " &");
+
+         if (strcmp (wd, jobs[job_index]->wd) != 0)
+           fprintf (stream,
+                    "  (wd: %s)", polite_directory_format (jobs[job_index]->wd));
+       }
+
+      if (format || (p == last))
+       fprintf (stream, "\r\n");
+
+      if (p == last)
+       break;
+      p = p->next;
+    }
+
+  fflush (stream);
+  UNBLOCK_CHILD (oset);
+}
+
+int
+list_one_job (job, format, ignore, job_index)
+     JOB *job;
+     int format, ignore, job_index;
+{
+  pretty_print_job (job_index, format, stdout);
+  return (0);
+}
+
+/* List jobs.  If FORMAT is non-zero, then the long form of the information
+   is printed, else just a short version. */
+void
+list_jobs (format)
+     int format;
+{
+  cleanup_dead_jobs ();
+  map_over_jobs (list_one_job, format, (int)IGNORE_ARG);
+}
+
+/* Fork, handling errors.  Returns the pid of the newly made child, or 0.
+   COMMAND is just for remembering the name of the command; we don't do
+   anything else with it.  ASYNC_P says what to do with the tty.  If
+   non-zero, then don't give it away. */
+pid_t
+make_child (command, async_p)
+     char *command;
+     int async_p;
+{
+  sigset_t set, oset;
+  pid_t pid;
+
+  sigemptyset (&set);
+  sigaddset (&set, SIGCHLD);
+  sigaddset (&set, SIGINT);
+  sigemptyset (&oset);
+  sigprocmask (SIG_BLOCK, &set, &oset);
+
+  making_children ();
+
+#if defined (BUFFERED_INPUT)
+  /* If default_buffered_input is active, we are reading a script.  If
+     the command is asynchronous, we have already duplicated /dev/null
+     as fd 0, but have not changed the buffered stream corresponding to
+     the old fd 0.  We don't want to sync the stream in this case. */
+  if (default_buffered_input != -1 &&
+      (!async_p || default_buffered_input > 0))
+    sync_buffered_stream (default_buffered_input);
+#endif /* BUFFERED_INPUT */
+
+  /* Create the child, handle severe errors. */
+  if ((pid = fork ()) < 0)
+    {
+      internal_error ("fork: %s", strerror (errno));
+
+      /* Kill all of the processes in the current pipeline. */
+      terminate_current_pipeline ();
+
+      /* Discard the current pipeline, if any. */
+      if (the_pipeline)
+       kill_current_pipeline ();
+
+      throw_to_top_level ();   /* Reset signals, etc. */
+    }
+
+  if (pid == 0)
+    {
+      /* In the child.  Give this child the right process group, set the
+        signals to the default state for a new process. */
+      pid_t mine = getpid ();
+
+#if defined (BUFFERED_INPUT)
+      /* Close default_buffered_input if it's > 0.  We don't close it if it's
+        0 because that's the file descriptor used when redirecting input,
+        and it's wrong to close the file in that case. */
+      if (default_buffered_input > 0)
+       {
+         close_buffered_fd (default_buffered_input);
+         default_buffered_input = bash_input.location.buffered_fd = -1;
+       }
+#endif /* BUFFERED_INPUT */
+
+      /* Restore top-level signal mask. */
+      sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
+
+      if (job_control)
+       {
+         /* All processes in this pipeline belong in the same
+            process group. */
+
+         if (!pipeline_pgrp)   /* Then this is the first child. */
+           pipeline_pgrp = mine;
+
+         /* Check for running command in backquotes. */
+         if (pipeline_pgrp == shell_pgrp)
+           {
+             set_signal_handler (SIGTSTP, SIG_IGN);
+             set_signal_handler (SIGTTOU, SIG_IGN);
+             set_signal_handler (SIGTTIN, SIG_IGN);
+           }
+         else
+           {
+             set_signal_handler (SIGTSTP, SIG_DFL);
+             set_signal_handler (SIGTTOU, SIG_DFL);
+             set_signal_handler (SIGTTIN, SIG_DFL);
+           }
+
+         /* Set the process group before trying to mess with the terminal's
+            process group.  This is mandated by POSIX. */
+         /* This is in accordance with the Posix 1003.1 standard,
+            section B.7.2.4, which says that trying to set the terminal
+            process group with tcsetpgrp() to an unused pgrp value (like
+            this would have for the first child) is an error.  Section
+            B.4.3.3, p. 237 also covers this, in the context of job control
+            shells. */
+         if (setpgid (mine, pipeline_pgrp) < 0)
+           internal_error ("child setpgid (%d to %d) error %d: %s\n",
+                           mine, pipeline_pgrp, errno, strerror (errno));
+#if defined (PGRP_PIPE)
+         if (pipeline_pgrp == mine)
+           {
+#endif
+             if (!async_p)
+               give_terminal_to (pipeline_pgrp);
+
+#if defined (PGRP_PIPE)
+             pipe_read (pgrp_pipe);
+           }
+#endif
+       }
+      else                     /* Without job control... */
+       {
+         if (!pipeline_pgrp)
+           pipeline_pgrp = shell_pgrp;
+
+         /* If these signals are set to SIG_DFL, we encounter the curious
+            situation of an interactive ^Z to a running process *working*
+            and stopping the process, but being unable to do anything with
+            that process to change its state.  On the other hand, if they
+            are set to SIG_IGN, jobs started from scripts do not stop when
+            the shell running the script gets a SIGTSTP and stops. */
+
+         set_signal_handler (SIGTSTP, SIG_DFL);
+         set_signal_handler (SIGTTOU, SIG_DFL);
+         set_signal_handler (SIGTTIN, SIG_DFL);
+       }
+
+#if defined (PGRP_PIPE)
+      /* Release the process group pipe, since our call to setpgid ()
+        is done.  The last call to pipe_close is done in stop_pipeline. */
+      pipe_close (pgrp_pipe);
+#endif /* PGRP_PIPE */
+
+      if (async_p)
+       last_asynchronous_pid = getpid ();
+    }
+  else
+    {
+      /* In the parent.  Remember the pid of the child just created
+        as the proper pgrp if this is the first child. */
+
+      if (job_control)
+       {
+         if (!pipeline_pgrp)
+           {
+             pipeline_pgrp = pid;
+             /* Don't twiddle terminal pgrps in the parent!  This is the bug,
+                not the good thing of twiddling them in the child! */
+             /* give_terminal_to (pipeline_pgrp); */
+           }
+         /* This is done on the recommendation of the Rationale section of
+            the POSIX 1003.1 standard, where it discusses job control and
+            shells.  It is done to avoid possible race conditions. (Ref.
+            1003.1 Rationale, section B.4.3.3, page 236). */
+         setpgid (pid, pipeline_pgrp);
+       }
+      else
+       {
+         if (!pipeline_pgrp)
+           pipeline_pgrp = shell_pgrp;
+       }
+
+      /* Place all processes into the jobs array regardless of the
+        state of job_control. */
+      add_process (command, pid);
+
+      if (async_p)
+       last_asynchronous_pid = pid;
+
+      last_made_pid = pid;
+
+      /* Unblock SIGINT and SIGCHLD. */
+      sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+    }
+
+  return (pid);
+}
+
+/* When we end a job abnormally, or if we stop a job, we set the tty to the
+   state kept in here.  When a job ends normally, we set the state in here
+   to the state of the tty. */
+
+#if defined (NEW_TTY_DRIVER)
+static struct sgttyb shell_tty_info;
+static struct tchars shell_tchars;
+static struct ltchars shell_ltchars;
+#endif /* NEW_TTY_DRIVER */
+
+#if defined (TERMIO_TTY_DRIVER)
+static struct termio shell_tty_info;
+#endif /* TERMIO_TTY_DRIVER */
+
+#if defined (TERMIOS_TTY_DRIVER)
+static struct termios shell_tty_info;
+#endif /* TERMIOS_TTY_DRIVER */
+
+#if defined (NEW_TTY_DRIVER) && defined (DRAIN_OUTPUT)
+/* Since the BSD tty driver does not allow us to change the tty modes
+   while simultaneously waiting for output to drain and preserving
+   typeahead, we have to drain the output ourselves before calling
+   ioctl.  We cheat by finding the length of the output queue, and
+   using select to wait for an appropriate length of time.  This is
+   a hack, and should be labeled as such (it's a hastily-adapted
+   mutation of a `usleep' implementation).  It's only reason for
+   existing is the flaw in the BSD tty driver. */
+
+static int ttspeeds[] =
+{
+  0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
+  1800, 2400, 4800, 9600, 19200, 38400
+};
+
+static void
+draino (fd, ospeed)
+     int fd, ospeed;
+{
+  register int delay = ttspeeds[ospeed];
+  int n;
+
+  if (!delay)
+    return;
+
+  while ((ioctl (fd, TIOCOUTQ, &n) == 0) && n)
+    {
+      if (n > (delay / 100))
+       {
+         struct timeval tv;
+
+         n *= 10;              /* 2 bits more for conservativeness. */
+         tv.tv_sec = n / delay;
+         tv.tv_usec = ((n % delay) * 1000000) / delay;
+         select (fd, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
+       }
+      else
+       break;
+    }
+}
+#endif /* NEW_TTY_DRIVER && DRAIN_OUTPUT */
+
+/* Return the fd from which we are actually getting input. */
+#define input_tty() (shell_tty != -1) ? shell_tty : fileno (stderr)
+
+/* Fill the contents of shell_tty_info with the current tty info. */
+get_tty_state ()
+{
+  int tty = input_tty ();
+
+  if (tty != -1)
+    {
+#if defined (NEW_TTY_DRIVER)
+      ioctl (tty, TIOCGETP, &shell_tty_info);
+      ioctl (tty, TIOCGETC, &shell_tchars);
+      ioctl (tty, TIOCGLTC, &shell_ltchars);
+#endif /* NEW_TTY_DRIVER */
+
+#if defined (TERMIO_TTY_DRIVER)
+      ioctl (tty, TCGETA, &shell_tty_info);
+#endif /* TERMIO_TTY_DRIVER */
+
+#if defined (TERMIOS_TTY_DRIVER)
+      if (tcgetattr (tty, &shell_tty_info) < 0)
+       {
+#if 0
+         /* Only print an error message if we're really interactive at
+            this time. */
+         if (interactive)
+           internal_error ("[%d: %d] tcgetattr: %s",
+                           getpid (), shell_level, strerror (errno));
+#endif
+         return -1;
+       }
+#endif /* TERMIOS_TTY_DRIVER */
+    }
+  return 0;
+}
+
+/* Make the current tty use the state in shell_tty_info. */
+set_tty_state ()
+{
+  int tty = input_tty ();
+
+  if (tty != -1)
+    {
+#if defined (NEW_TTY_DRIVER)
+#  if defined (DRAIN_OUTPUT)
+      draino (tty, shell_tty_info.sg_ospeed);
+#  endif /* DRAIN_OUTPUT */
+      ioctl (tty, TIOCSETN, &shell_tty_info);
+      ioctl (tty, TIOCSETC, &shell_tchars);
+      ioctl (tty, TIOCSLTC, &shell_ltchars);
+#endif /* NEW_TTY_DRIVER */
+
+#if defined (TERMIO_TTY_DRIVER)
+      ioctl (tty, TCSETAW, &shell_tty_info);
+#endif /* TERMIO_TTY_DRIVER */
+
+#if defined (TERMIOS_TTY_DRIVER)
+      if (tcsetattr (tty, TCSADRAIN, &shell_tty_info) < 0)
+       {
+         /* Only print an error message if we're really interactive at
+            this time. */
+         if (interactive)
+           internal_error ("[%d: %d] tcsetattr: %s",
+                           getpid (), shell_level, strerror (errno));
+         return -1;
+       }
+#endif /* TERMIOS_TTY_DRIVER */
+    }
+  return 0;
+}
+
+/* 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. */
+static pid_t
+last_pid (job)
+     int job;
+{
+  register PROCESS *p;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+  p = jobs[job]->pipe;
+  while (p->next != jobs[job]->pipe)
+    p = p->next;
+
+  UNBLOCK_CHILD (oset);
+  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. */
+int
+wait_for_single_pid (pid)
+     pid_t pid;
+{
+  register PROCESS *child;
+
+  {
+    sigset_t set, oset;
+
+    BLOCK_CHILD (set, oset);
+    child = find_pipeline (pid);
+    UNBLOCK_CHILD (oset);
+  }
+
+  if (!child)
+    {
+      report_error ("wait: pid %d is not a child of this shell", pid);
+      return (127);
+    }
+
+  return (wait_for (pid));
+}
+
+/* Wait for all of the backgrounds of this shell to finish. */
+void
+wait_for_background_pids ()
+{
+  while (1)
+    {
+      register int i, count = 0;
+      sigset_t set, oset;
+
+      BLOCK_CHILD (set, oset);
+
+      for (i = 0; i < job_slots; i++)
+       if (jobs[i] && (JOBSTATE (i) == JRUNNING) &&
+           (jobs[i]->flags & J_FOREGROUND) == 0)
+         {
+           count++;
+           break;
+         }
+
+      if (!count)
+       {
+         UNBLOCK_CHILD (oset);
+         break;
+       }
+
+      for (i = 0; i < job_slots; i++)
+       if (jobs[i] && (JOBSTATE (i) == JRUNNING) &&
+           (jobs[i]->flags & J_FOREGROUND) == 0)
+         {
+           pid_t pid = last_pid (i);
+           UNBLOCK_CHILD (oset);
+           QUIT;
+           wait_for_single_pid (pid);
+           break;
+         }
+    }
+}
+
+/* Make OLD_SIGINT_HANDLER the SIGINT signal handler. */
+#define INVALID_SIGNAL_HANDLER (SigHandler *)wait_for_background_pids
+static SigHandler *old_sigint_handler = INVALID_SIGNAL_HANDLER;
+
+static void
+restore_sigint_handler ()
+{
+  if (old_sigint_handler != INVALID_SIGNAL_HANDLER)
+    {
+      set_signal_handler (SIGINT, old_sigint_handler);
+      old_sigint_handler = INVALID_SIGNAL_HANDLER;
+    }
+}
+
+static int wait_sigint_received = 0;
+
+/* Handle SIGINT while we are waiting for children in a script to exit.
+   The `wait' builtin should be interruptible, but all others should be
+   effectively ignored (i.e. not cause the shell to exit). */
+static sighandler
+wait_sigint_handler (sig)
+     int sig;
+{
+  if (interrupt_immediately ||
+      (this_shell_builtin && this_shell_builtin == wait_builtin))
+    {
+      last_command_exit_value = EXECUTION_FAILURE;
+      restore_sigint_handler ();
+      interrupt_state++;
+      QUIT;
+    }
+
+  wait_sigint_received = 1;    /* XXX - should this be interrupt_state? */
+  /* Otherwise effectively ignore the SIGINT and allow the running job to
+     be killed. */
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* !VOID_SIGHANDLER */
+}
+
+static int
+process_exit_status (status)
+     WAIT status;
+{
+  if (WIFSIGNALED (status))
+    return (128 + WTERMSIG (status));
+  else if (!WIFSTOPPED (status))
+    return (WEXITSTATUS (status));
+  else
+    return (EXECUTION_SUCCESS);
+}
+
+/* Wait for pid (one of our children) to terminate, then
+   return the termination state. */
+int
+wait_for (pid)
+     pid_t pid;
+{
+  int job, termination_state;
+  register PROCESS *child;
+  sigset_t set, oset;
+
+  /* In the case that this code is interrupted, and we longjmp () out of it,
+     we are relying on the code in throw_to_top_level () to restore the
+     top-level signal mask. */
+  BLOCK_CHILD (set, oset);
+
+  /* Ignore interrupts while waiting for a job run without job control
+     to finish.  We don't want the shell to exit if an interrupt is
+     received, only if one of the jobs run is killed via SIGINT.  If
+     job control is not set, the job will be run in the same pgrp as 
+     the shell, and the shell will see any signals the job gets. */
+
+  /* This is possibly a race condition -- should it go in stop_pipeline? */
+  wait_sigint_received = 0;
+  if (!job_control)
+    old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
+
+  termination_state = last_command_exit_value;
+
+  /* If we say wait_for (), then we have a record of this child somewhere.
+     If this child and all of its peers are not running, then don't
+     sigpause (), since there is no need to. */
+ wait_loop:
+
+  /* If the shell is interactive, and job control is disabled, see if the
+     foreground process has died due to SIGINT and jump out of the wait
+     loop if it has.  waitchld has already restored the old SIGINT
+     signal handler. */
+  if (interactive && !job_control)
+    QUIT;
+
+  child = find_pipeline (pid);
+
+  if (!child)
+    {
+      give_terminal_to (shell_pgrp);
+      UNBLOCK_CHILD (oset);
+      programming_error ("wait_for: No record of pid %d", pid);
+    }
+
+  /* If this child is part of a job, then we are really waiting for the
+     job to finish.  Otherwise, we are waiting for the child to finish. */
+
+  job = find_job (pid);
+
+  if (job != NO_JOB)
+    {
+      register int job_state = 0, any_stopped = 0;
+      register PROCESS *p = jobs[job]->pipe;
+
+      do
+       {
+         job_state |= p->running;
+         if (!p->running)
+           any_stopped |= WIFSTOPPED (p->status);
+         p = p->next;
+       }
+      while (p != jobs[job]->pipe);
+
+      if (job_state == 0)
+       {
+         if (any_stopped)
+           jobs[job]->state = JSTOPPED;
+         else
+           jobs[job]->state = JDEAD;
+       }
+    }
+
+  if (child->running || ((job != NO_JOB) && (JOBSTATE (job) == JRUNNING)))
+    {
+#if defined (WAITPID_BROKEN)   /* SCOv4 */
+      sigset_t suspend_set;
+      sigemptyset (&suspend_set);
+      sigsuspend (&suspend_set);
+#else /* !WAITPID_BROKEN */
+#  if defined (MUST_UNBLOCK_CHILD)     /* SCO */
+      struct sigaction act, oact;
+      sigset_t nullset, chldset;
+
+      sigemptyset (&nullset);
+      sigemptyset (&chldset);
+      sigprocmask (SIG_SETMASK, &nullset, &chldset);
+      act.sa_handler = SIG_DFL;
+      sigemptyset (&act.sa_mask);
+      sigemptyset (&oact.sa_mask);
+      act.sa_flags = 0;
+      sigaction (SIGCHLD, &act, &oact);
+#  endif
+      waiting_for_job = 1;
+      waitchld (0);
+      waiting_for_job = 0;
+#  if defined (MUST_UNBLOCK_CHILD)
+      sigaction (SIGCHLD, &oact, (struct sigaction *)NULL);
+      sigprocmask (SIG_SETMASK, &chldset, (sigset_t *)NULL);
+#  endif
+#endif /* !WAITPID_BROKEN */
+      goto wait_loop;
+    }
+
+  /* The exit state of the command is either the termination state of the
+     child, or the termination state of the job.  If a job, the status
+     of the last child in the pipeline is the significant one. */
+
+  if (job != NO_JOB)
+    {
+      register PROCESS *p = jobs[job]->pipe;
+
+      while (p->next != jobs[job]->pipe)
+       p = p->next;
+      termination_state = process_exit_status (p->status);
+    }
+  else
+    termination_state = process_exit_status (child->status);
+
+  if (job == NO_JOB || (jobs[job]->flags & J_JOBCONTROL))
+    give_terminal_to (shell_pgrp);
+
+  /* If the command did not exit cleanly, or the job is just
+     being stopped, then reset the tty state back to what it
+     was before this command.  Reset the tty state and notify
+     the user of the job termination only if the shell is
+     interactive.  Clean up any dead jobs in either case. */
+  if (job != NO_JOB)
+    {
+      if (interactive_shell && !subshell_environment)
+       {
+         if (WIFSIGNALED (child->status) || WIFSTOPPED (child->status))
+           set_tty_state ();
+         else
+           get_tty_state ();
+
+         /* If job control is enabled, the job was started with job
+            control, the job was the foreground job, and it was killed
+            by SIGINT, then print a newline to compensate for the kernel
+            printing the ^C without a trailing newline. */
+         if (job_control && (jobs[job]->flags & J_JOBCONTROL) &&
+               (jobs[job]->flags & J_FOREGROUND) && 
+               WIFSIGNALED (child->status) &&
+               WTERMSIG (child->status) == SIGINT)
+           {
+             /* If SIGINT is not trapped, set the interrupt state if in a
+                loop so the loop will be broken.  If not in a loop, print
+                the newline that the kernel does not. */
+             if (signal_is_trapped (SIGINT) == 0)
+               {
+                 if (loop_level)
+                   interrupt_state++;
+                 else
+                   {
+                     putchar ('\n');
+                     fflush (stdout);
+                   }
+               }
+           }
+
+         notify_and_cleanup ();
+       }
+      else
+       {
+         /* If this job is dead, and the shell is not interactive, make
+            sure we turn on the notify bit so we don't get an unwanted
+            message about the job's termination, and so delete_job really
+            clears the slot in the jobs table. */
+         if (JOBSTATE(job) == JDEAD)
+           jobs[job]->flags |= J_NOTIFIED;
+         cleanup_dead_jobs ();
+       }
+    }
+    
+  UNBLOCK_CHILD (oset);
+
+  /* Restore the original SIGINT signal handler before we return. */
+  restore_sigint_handler ();
+
+  return (termination_state);
+}
+
+/* Wait for the last process in the pipeline for JOB. */
+int
+wait_for_job (job)
+     int job;
+{
+  pid_t pid = last_pid (job);
+  return (wait_for (pid));
+}
+
+/* Print info about dead jobs, and then delete them from the list
+   of known jobs.  This does not actually delete jobs when the
+   shell is not interactive, because the dead jobs are not marked
+   as notified. */
+void
+notify_and_cleanup ()
+{
+  if (freeze_jobs_list)
+    return;
+
+  if (interactive)
+    notify_of_job_status ();
+
+  cleanup_dead_jobs ();
+}
+
+/* Make dead jobs disappear from the jobs array without notification.
+   This is used when the shell is not interactive. */
+void
+reap_dead_jobs ()
+{
+  mark_dead_jobs_as_notified ();
+  cleanup_dead_jobs ();
+}
+
+/* Return the next closest (chronologically) job to JOB which is in
+   STATE.  STATE can be JSTOPPED, JRUNNING.  NO_JOB is returned if
+   there is no next recent job. */
+static int
+most_recent_job_in_state (job, state)
+     int job;
+     JOB_STATE state;
+{
+  register int i, result;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+  result = NO_JOB;
+
+  for (i = job - 1; i >= 0; i--)
+    {
+      if (jobs[i])
+       {
+         if (JOBSTATE (i) == state)
+           {
+             result = i;
+             break;
+           }
+       }
+    }
+  UNBLOCK_CHILD (oset);
+  return (result);
+}
+
+/* Return the newest *stopped* job older than JOB, or NO_JOB if not
+   found. */
+static int
+last_stopped_job (job)
+     int job;
+{
+  return (most_recent_job_in_state (job, JSTOPPED));
+}
+
+/* Return the newest *running* job older than JOB, or NO_JOB if not
+   found. */
+static int
+last_running_job (job)
+     int job;
+{
+  return (most_recent_job_in_state (job, JRUNNING));
+}
+
+/* Make JOB be the current job, and make previous be useful.  Must be
+   called with SIGCHLD blocked. */
+static void
+set_current_job (job)
+     int job;
+{
+  int candidate = NO_JOB;
+
+  if (current_job != job)
+    {
+      previous_job = current_job;
+      current_job = job;
+    }
+
+  /* First choice for previous_job is the old current_job. */
+  if (previous_job != current_job &&
+      previous_job != NO_JOB &&
+      jobs[previous_job] &&
+      JOBSTATE (previous_job) == JSTOPPED)
+    return;
+
+  /* Second choice:  Newest stopped job that is older than
+     the current job. */
+  if (JOBSTATE (current_job) == JSTOPPED)
+    {
+      candidate = last_stopped_job (current_job);
+
+      if (candidate != NO_JOB)
+       {
+         previous_job = candidate;
+         return;
+       }
+    }
+
+  /* If we get here, there is either only one stopped job, in which case it is
+     the current job and the previous job should be set to the newest running
+     job, or there are only running jobs and the previous job should be set to
+     the newest running job older than the current job.  We decide on which
+     alternative to use based on whether or not JOBSTATE(current_job) is
+     JSTOPPED. */
+
+  if (JOBSTATE (current_job) == JRUNNING)
+    candidate = last_running_job (current_job);
+  else
+    candidate = last_running_job (job_slots);
+
+  if (candidate != NO_JOB)
+    {
+      previous_job = candidate;
+      return;
+    }
+
+  /* There is only a single job, and it is both `+' and `-'. */
+  previous_job = current_job;
+}
+
+/* Make current_job be something useful, if it isn't already. */
+
+/* Here's the deal:  The newest non-running job should be `+', and the
+   next-newest non-running job should be `-'.  If there is only a single
+   stopped job, the previous_job is the newest non-running job.  If there
+   are only running jobs, the newest running job is `+' and the
+   next-newest running job is `-'.  Must be called with SIGCHLD blocked. */
+static void
+reset_current ()
+{
+  int candidate = NO_JOB;
+
+  if (current_job != NO_JOB &&
+      job_slots && jobs[current_job] &&
+      JOBSTATE (current_job) == JSTOPPED)
+    {
+      candidate = current_job;
+    }
+  else
+    {
+      /* First choice: the previous job! */
+      if (previous_job != NO_JOB && jobs[previous_job] &&
+         JOBSTATE (previous_job) == JSTOPPED)
+       candidate = previous_job;
+
+      /* Second choice: the most recently stopped job. */
+      if (candidate == NO_JOB)
+       candidate = last_stopped_job (job_slots);
+
+      if (candidate == NO_JOB)
+       {
+         /* Third choice: the newest running job. */
+         candidate = last_running_job (job_slots);
+       }
+    }
+
+  /* If we found a job to use, then use it.  Otherwise, there
+     are no jobs period. */
+  if (candidate != NO_JOB)
+    set_current_job (candidate);
+  else
+    current_job = previous_job = NO_JOB;
+}
+
+/* Start a job.  FOREGROUND if non-zero says to do that.  Otherwise,
+   start the job in the background.  JOB is a zero-based index into
+   JOBS.  Returns -1 if it is unable to start a job, and the return
+   status of the job otherwise. */
+int
+start_job (job, foreground)
+     int job, foreground;
+{
+  register PROCESS *p;
+  int already_running;
+  sigset_t set, oset;
+  char *wd;
+#if defined (NEW_TTY_DRIVER)
+  static struct sgttyb save_stty;
+#endif
+
+#if defined (TERMIO_TTY_DRIVER)
+  static struct termio save_stty;
+#endif
+
+#if defined (TERMIOS_TTY_DRIVER)
+  static struct termios save_stty;
+#endif
+
+  BLOCK_CHILD (set, oset);
+  already_running = (JOBSTATE (job) == JRUNNING);
+
+  if (JOBSTATE (job) == JDEAD)
+    {
+      report_error ("%s: job has terminated", this_command_name);
+      UNBLOCK_CHILD (oset);
+      return (-1);
+    }
+
+  if (!foreground && already_running)
+    {
+      report_error ("%s: bg background job?", this_command_name);
+      UNBLOCK_CHILD (oset);
+      return (-1);
+    }
+
+  wd = current_working_directory ();
+
+  /* You don't know about the state of this job.  Do you? */
+  jobs[job]->flags &= ~J_NOTIFIED;
+
+  if (foreground)
+    {
+      set_current_job (job);
+      jobs[job]->flags |= J_FOREGROUND;
+    }
+
+  /* Tell the outside world what we're doing. */
+  p = jobs[job]->pipe;
+
+  if (!foreground)
+    fprintf (stderr, "[%d]%c ", job + 1,
+          (job == current_job) ? '+': ((job == previous_job) ? '-' : ' '));
+
+  do
+    {
+      fprintf (stderr, "%s%s",
+              p->command ? p->command : "",
+              p->next != jobs[job]->pipe? " | " : "");
+      p = p->next;
+    }
+  while (p != jobs[job]->pipe);
+
+  if (!foreground)
+    fprintf (stderr, " &");
+
+  if (strcmp (wd, jobs[job]->wd) != 0)
+    fprintf (stderr, " (wd: %s)", polite_directory_format (jobs[job]->wd));
+
+  fprintf (stderr, "\n");
+
+  /* Run the job. */
+  if (!already_running)
+    {
+      /* Each member of the pipeline is now running. */
+      p = jobs[job]->pipe;
+
+      do
+       {
+         if (WIFSTOPPED (p->status))
+           p->running = 1;
+         p = p->next;
+       }
+      while (p != jobs[job]->pipe);
+
+      /* This means that the job is running. */
+      JOBSTATE (job) = JRUNNING;
+    }
+
+  /* Save the tty settings before we start the job in the foreground. */
+  if (foreground)
+    {
+      get_tty_state ();
+      save_stty = shell_tty_info;
+    }
+
+  /* Give the terminal to this job. */
+  if (foreground)
+    {
+      if (jobs[job]->flags & J_JOBCONTROL)
+       give_terminal_to (jobs[job]->pgrp);
+    }
+  else
+    jobs[job]->flags &= ~J_FOREGROUND;
+
+  /* If the job is already running, then don't bother jump-starting it. */
+  if (!already_running)
+    {
+      jobs[job]->flags |= J_NOTIFIED;
+      killpg (jobs[job]->pgrp, SIGCONT);
+    }
+
+  UNBLOCK_CHILD (oset);
+
+  if (foreground)
+    {
+      pid_t pid = last_pid (job);
+      int s = wait_for (pid);
+
+      shell_tty_info = save_stty;
+      set_tty_state ();
+      return (s);
+    }
+  else
+    {
+      BLOCK_CHILD (set, oset);
+      reset_current ();
+      UNBLOCK_CHILD (oset);
+      return (0);
+    }
+}
+
+/* Give PID SIGNAL.  This determines what job the pid belongs to (if any).
+   If PID does belong to a job, and the job is stopped, then CONTinue the
+   job after giving it SIGNAL.  Returns -1 on failure.  If GROUP is non-null,
+   then kill the process group associated with PID. */
+int
+kill_pid (pid, sig, group)
+     pid_t pid;
+     int sig, group;
+{
+  register PROCESS *p;
+  int job, result = EXECUTION_SUCCESS;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+  p = find_pipeline (pid);
+  job = find_job (pid);
+
+  if (group)
+    {
+      if (job != NO_JOB)
+       {
+         jobs[job]->flags &= ~J_NOTIFIED;
+
+         /* Kill process in backquotes or one started without job control? */
+         if (jobs[job]->pgrp == shell_pgrp)
+           {
+             p = jobs[job]->pipe;
+
+             do
+               {
+                 kill (p->pid, sig);
+                 if (p->running == 0 && (sig == SIGTERM || sig == SIGHUP))
+                   kill (p->pid, SIGCONT);
+                 p = p->next;
+               }
+             while (p != jobs[job]->pipe);
+           }
+         else
+           {
+             result = killpg (jobs[job]->pgrp, sig);
+             if (p && (JOBSTATE (job) == JSTOPPED) &&
+                 (sig == SIGTERM || sig == SIGHUP))
+               killpg (jobs[job]->pgrp, SIGCONT);
+           }
+       }
+      else
+       result = killpg (pid, sig);
+    }
+  else
+    result = kill (pid, sig);
+
+  UNBLOCK_CHILD (oset);
+  return (result);
+}
+
+/* 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
+   waitpid() function. */
+
+#if defined (Ultrix) && defined (mips) && defined (_POSIX_VERSION)
+#  define WAITPID(pid, statusp, options) \
+       wait3 ((union wait *)statusp, options, (struct rusage *)0)
+#else
+#  if defined (_POSIX_VERSION)
+#    define WAITPID(pid, statusp, options) \
+       waitpid ((pid_t)pid, statusp, options)
+#  else
+#    if defined (hpux)
+#      define WAITPID(pid, statusp, options) \
+       wait3 (statusp, options, (int *)0)
+#    else
+#      define WAITPID(pid, statusp, options) \
+       wait3 (statusp, options, (struct rusage *)0)
+#    endif /* !hpux */
+#  endif /* !_POSIX_VERSION */
+#endif /* !(Ultrix && mips && _POSIX_VERSION) */
+
+/* If the system needs it, REINSTALL_SIGCHLD_HANDLER will reinstall the
+   handler for SIGCHLD. */
+
+#if defined (hpux) && !defined (_POSIX_VERSION)
+#  define REINSTALL_SIGCHLD_HANDLER signal (SIGCHLD, flush_child)
+#else
+#  define REINSTALL_SIGCHLD_HANDLER
+#endif /* !hpux || _POSIX_VERSION */
+
+/* Flush_child () flushes at least one of the children that we are waiting for.
+   It gets run when we have gotten a SIGCHLD signal, and stops when there
+   aren't any children terminating any more.  If SIG is 0, this is to be a
+   blocking wait for a single child. */
+static sighandler
+flush_child (sig)
+     int sig;
+{
+  REINSTALL_SIGCHLD_HANDLER;
+  sigchld++;
+  if (waiting_for_job == 0)
+    waitchld (sig);
+
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* VOID_SIGHANDLER */
+}
+  
+static int
+waitchld (s)
+     int s;
+{
+  WAIT status;
+  PROCESS *child;
+  pid_t pid;
+  int call_set_current = 0, last_stopped_job = NO_JOB;
+  int children_exited = 0, flag;
+
+  do
+    {
+      flag = WUNTRACED;
+      if (sigchld || s)
+       flag |= WNOHANG;
+      pid = WAITPID (-1, &status, flag);
+      if (sigchld && (flag & WNOHANG))
+        sigchld--;
+
+      if (pid > 0)
+       {
+         /* Locate our PROCESS for this pid. */
+         child = find_pipeline (pid);
+
+         /* 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
+            a pipeline in backquote substitution. */
+         if (child)
+           {
+             int job = find_job (pid);
+
+             while (child->pid != pid)
+               child = child->next;
+
+             /* Remember status, and fact that process is not running. */
+             child->status = status;
+             child->running = 0;
+
+             if (job != NO_JOB)
+               {
+                 int job_state = 0;
+                 int any_stopped = 0;
+                 int any_tstped = 0;
+
+                 child = jobs[job]->pipe;
+                 jobs[job]->flags &= ~J_NOTIFIED;
+
+                 /* If all children are not running, but any of them is
+                    stopped, then the job is stopped, not dead. */
+                 do
+                  {
+                     job_state |= child->running;
+                     if (!child->running)
+                       {
+                         any_stopped |= WIFSTOPPED (child->status);
+                         any_tstped |= interactive && job_control &&
+                                       WIFSTOPPED (child->status) &&
+                                       WSTOPSIG (child->status) == SIGTSTP;
+                       }
+                     child = child->next;
+                   }
+                 while (child != jobs[job]->pipe);
+
+                 if (job_state == 0)
+                   {
+                     if (any_stopped)
+                       {
+                         jobs[job]->state = JSTOPPED;
+                         jobs[job]->flags &= ~J_FOREGROUND;
+                         call_set_current++;
+                         last_stopped_job = job;
+                         /* Suspending a job in a loop from the keyboard
+                            breaks out of all active loops. */
+                         if (any_tstped && loop_level)
+                           breaking = loop_level;
+                       }
+                     else
+                       {
+                         jobs[job]->state = JDEAD;
+
+                         if (job == last_stopped_job)
+                           last_stopped_job = NO_JOB;
+
+                         /* If the foreground job is killed by SIGINT when
+                            job control is not active, we need to perform
+                            some special handling. */
+                         /* The check of wait_sigint_received is a way to
+                            determine if the SIGINT came from the keyboard
+                            (in which case the shell has already seen it,
+                            and wait_sigint_received is non-zero, because
+                            keyboard signals are sent to process groups)
+                            or via kill(2) to the foreground process by
+                            another process (or itself).  If the shell did
+                            receive the SIGINT, it needs to perform normal
+                            SIGINT processing. */
+                         if ((WTERMSIG (jobs[job]->pipe->status) == SIGINT) &&
+                             (jobs[job]->flags & J_FOREGROUND) &&
+                             (jobs[job]->flags & J_JOBCONTROL) == 0 &&
+                             wait_sigint_received)
+                           {
+                             wait_sigint_received = 0;
+
+                             /* If SIGINT is trapped, set the exit status so
+                                that the trap handler can see it. */
+                             if (signal_is_trapped (SIGINT))
+                               last_command_exit_value = process_exit_status
+                                 (jobs[job]->pipe->status);
+
+                             /* If the signal is trapped, let the trap handler
+                                get it no matter what and simply return if
+                                the trap handler returns.
+                                maybe_call_trap_handler may cause dead jobs
+                                to be removed from the job table because of
+                                a call to execute_command.  Watch out for
+                                this. */
+                             if (maybe_call_trap_handler (SIGINT) == 0 &&
+                                 old_sigint_handler != INVALID_SIGNAL_HANDLER)
+                               {
+                                 /* wait_sigint_handler () has already
+                                    seen SIGINT and allowed the wait
+                                    builtin to jump out.  We need to
+                                    call the original SIGINT handler. */
+                                 SigHandler *temp_handler;
+                                 temp_handler = old_sigint_handler;
+                                 restore_sigint_handler ();
+                                 if (temp_handler != SIG_IGN)
+                                   (*temp_handler) (SIGINT);
+                               }
+                           }
+                       }
+                   }
+               }
+           }
+         /* If we have caught a child, and a trap was set for SIGCHLD, then
+            bump up the count of the number of children that have exited,
+            so we know how many times to call it. */
+         children_exited++;
+       }
+    }
+  while ((s || sigchld) && pid > (pid_t)0);
+
+  /* If a job was running and became stopped, then set the current
+     job.  Otherwise, don't change a thing. */
+  if (call_set_current)
+    if (last_stopped_job != NO_JOB)
+      set_current_job (last_stopped_job);
+    else
+      reset_current ();
+
+  /* Call a SIGCHLD trap handler for each child that exits, if one is set. */
+  if (job_control && signal_is_trapped (SIGCHLD) &&
+      trap_list[SIGCHLD] != (char *)IGNORE_SIG)
+    {
+      char *trap_command;
+
+      /* Turn off the trap list during the call to parse_and_execute ()
+        to avoid potentially infinite recursive calls.  Preserve the
+        values of last_command_exit_value, last_made_pid, and the_pipeline
+        around the execution of the trap commands. */
+      trap_command = savestring (trap_list[SIGCHLD]);
+
+      begin_unwind_frame ("SIGCHLD trap");
+      unwind_protect_int (last_command_exit_value);
+      unwind_protect_int (last_made_pid);
+      unwind_protect_int (interrupt_immediately);
+      unwind_protect_int (freeze_jobs_list);
+      unwind_protect_pointer (the_pipeline);
+
+      /* We have to add the commands this way because they will be run
+        in reverse order of adding.  We don't want maybe_set_sigchld_trap ()
+        to reference freed memory. */
+      add_unwind_protect ((Function *)xfree, trap_command);
+      add_unwind_protect ((Function *)maybe_set_sigchld_trap, trap_command);
+
+      the_pipeline = (PROCESS *)NULL;
+      restore_default_signal (SIGCHLD);
+      freeze_jobs_list = 1;
+      while (children_exited--)
+       {
+         interrupt_immediately = 1;
+         parse_and_execute (savestring (trap_command), "trap", -1);
+       }
+
+      run_unwind_frame ("SIGCHLD trap");
+    }
+
+  /* We have successfully recorded the useful information about this process
+     that has just changed state.  If we notify asynchronously, and the job
+     that this process belongs to is no longer running, then notify the user
+     of that fact now. */
+  if (asynchronous_notification && interactive)
+    notify_of_job_status ();
+
+}
+
+/* Function to call when you want to notify people of changes
+   in job status.  This prints out all jobs which are pending
+   notification to stderr, and marks those printed as already
+   notified, thus making them candidates for cleanup. */
+static void
+notify_of_job_status ()
+{
+  register int job, termsig;
+  char *dir;
+  sigset_t set, oset;
+
+  sigemptyset (&set);
+  sigaddset (&set, SIGCHLD);
+  sigaddset (&set, SIGTTOU);
+  sigemptyset (&oset);
+  sigprocmask (SIG_BLOCK, &set, &oset);
+
+  dir = (char *)NULL;
+
+  for (job = 0; job < job_slots; job++)
+    {
+      if (jobs[job] && (jobs[job]->flags & J_NOTIFIED) == 0)
+       {
+         WAIT s;
+
+         s = jobs[job]->pipe->status;
+         termsig = WTERMSIG (s);
+
+         /* If job control is disabled, don't print the status messages.
+            Mark dead jobs as notified so that they get cleaned up. */
+         if (!job_control)
+           {
+             if (JOBSTATE (job) == JDEAD)
+               jobs[job]->flags |= J_NOTIFIED;
+             continue;
+           }
+
+         switch (JOBSTATE (job))
+           {
+             /* Print info on jobs that are running in the background,
+                and on foreground jobs that were killed by anything
+                except SIGINT. */
+
+           case JDEAD:
+
+             if (jobs[job]->flags & J_FOREGROUND)
+               {
+                 if (termsig && WIFSIGNALED (s) && termsig != SIGINT)
+                   {
+                     fprintf (stderr, "%s", strsignal (termsig));
+
+                     if (WIFCORED (s))
+                       fprintf (stderr, " (core dumped)");
+
+                     fprintf (stderr, "\n");
+                   }
+               }
+             else
+               {
+                 if (!dir)
+                   dir = current_working_directory ();
+                 pretty_print_job (job, 0, stderr);
+                 if (dir && strcmp (dir, jobs[job]->wd) != 0)
+                   fprintf (stderr,
+                            "(wd now: %s)\n", polite_directory_format (dir));
+               }
+
+             jobs[job]->flags |= J_NOTIFIED;
+             break;
+
+           case JSTOPPED:
+             fprintf (stderr, "\n");
+             if (!dir)
+               dir = current_working_directory ();
+             pretty_print_job (job, 0, stderr);
+             if (dir && (strcmp (dir, jobs[job]->wd) != 0))
+               fprintf (stderr,
+                        "(wd now: %s)\n", polite_directory_format (dir));
+             jobs[job]->flags |= J_NOTIFIED;
+             break;
+
+           case JRUNNING:
+           case JMIXED:
+             break;
+
+           default:
+             programming_error ("notify_of_job_status");
+           }
+       }
+    }
+  sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+}
+
+/* getpgrp () varies between systems.  Even systems that claim to be
+   Posix.1 compatible lie sometimes (Ultrix, SunOS4, apollo). */
+#if defined (_POSIX_VERSION) && !defined (BSD_GETPGRP)
+#  define getpgid(p) getpgrp ()
+#else
+#  define getpgid(p) getpgrp (p)
+#endif /* !_POSIX_VERSION || BSD_GETPGRP */
+
+/* Initialize the job control mechanism, and set up the tty stuff. */
+initialize_jobs ()
+{
+  shell_pgrp = getpgid (0);
+
+  if (shell_pgrp == -1)
+    {
+      internal_error ("initialize_jobs: getpgrp failed: %s", strerror (errno));
+      exit (1);
+    }
+
+  /* We can only have job control if we are interactive?
+     I guess that makes sense. */
+
+  if (!interactive)
+    {
+      job_control = 0;
+      original_pgrp = NO_PID;
+    }
+  else
+    {
+      /* Make sure that we are using the new line discipline. */
+
+      /* Get our controlling terminal.  If job_control is set, or
+        interactive is set, then this is an interactive shell no
+        matter what. */
+      shell_tty = dup (fileno (stderr));
+
+      /* Find the highest unused file descriptor we can. */
+      {
+       int ignore, nds = getdtablesize ();
+
+       if (nds <= 0)
+         nds = 20;
+       else if (nds > 256)
+         nds = 256;
+
+       while (--nds > 3)
+         {
+           if (fcntl (nds, F_GETFD, &ignore) == -1)
+             break;
+         }
+
+       if (nds && shell_tty != nds && (dup2 (shell_tty, nds) != -1))
+         {
+           if (shell_tty != fileno (stderr))
+             close (shell_tty);
+           shell_tty = nds;
+         }
+      }
+
+#if defined (RLOGIN_PGRP_BUG)
+      /* Compensate for a bug in systems that compiled the BSD
+        /usr/etc/rlogind with DEBUG defined, like NeXT and Alliant. */
+      if (shell_pgrp == 0)
+       {
+         shell_pgrp = getpid ();
+         setpgid (0, shell_pgrp);
+         tcsetpgrp (shell_tty, shell_pgrp);
+       }
+#endif /* RLOGIN_PGRP_BUG */
+
+      while ((terminal_pgrp = tcgetpgrp (shell_tty)) != -1)
+       {
+         if (shell_pgrp != terminal_pgrp)
+           {
+             SigHandler *old_ttin = (SigHandler *)set_signal_handler (SIGTTIN, SIG_DFL);
+             kill (0, SIGTTIN);
+             set_signal_handler (SIGTTIN, old_ttin);
+             continue;
+           }
+         break;
+       }
+
+      if (set_new_line_discipline (shell_tty) < 0)
+       {
+         internal_error ("initialize_jobs: line discipline: %s",
+                         strerror (errno));
+         job_control = 0;
+       }
+      else
+       {
+         original_pgrp = shell_pgrp;
+         shell_pgrp = getpid ();
+
+         if ((original_pgrp != shell_pgrp) && (setpgid (0, shell_pgrp) < 0))
+           {
+             internal_error ("initialize_jobs: setpgid: %s", strerror (errno));
+             shell_pgrp = original_pgrp;
+           }
+
+         job_control = 1;
+         if (give_terminal_to (shell_pgrp) < 0)                /* XXX */
+           /* job_control = 0 */;                              /* XXX */
+       }
+      if (job_control == 0)
+        internal_error ("no job control in this shell");       /* XXX */
+    }
+
+  if (shell_tty != fileno (stderr))
+    SET_CLOSE_ON_EXEC (shell_tty);
+
+  set_signal_handler (SIGCHLD, flush_child);
+
+  change_flag ('m', job_control ? '-' : '+');
+
+  if (interactive)
+    get_tty_state ();
+  return job_control;
+}
+
+/* Set the line discipline to the best this system has to offer.
+   Return -1 if this is not possible. */
+static int
+set_new_line_discipline (tty)
+     int tty;
+{
+#if defined (NEW_TTY_DRIVER)
+  int ldisc;
+
+  if (ioctl (tty, TIOCGETD, &ldisc) < 0)
+    return (-1);
+
+  if (ldisc != NTTYDISC)
+    {
+      ldisc = NTTYDISC;
+
+      if (ioctl (tty, TIOCSETD, &ldisc) < 0)
+       return (-1);
+    }
+  return (0);
+#endif /* NEW_TTY_DRIVER */
+
+#if defined (TERMIO_TTY_DRIVER)
+#  if defined (NTTYDISC)
+  if (ioctl (tty, TCGETA, &shell_tty_info) < 0)
+    return (-1);
+
+  if (shell_tty_info.c_line != NTTYDISC)
+    {
+      shell_tty_info.c_line = NTTYDISC;
+      if (ioctl (tty, TCSETAW, &shell_tty_info) < 0)
+       return (-1);
+    }
+#  endif /* NTTYDISC */
+  return (0);
+#endif /* TERMIO_TTY_DRIVER */
+
+#if defined (TERMIOS_TTY_DRIVER)
+#  if defined (TERMIOS_LDISC)
+  if (tcgetattr (tty, &shell_tty_info) < 0)
+    return (-1);
+
+  if (shell_tty_info.c_line != NTTYDISC)
+    {
+      shell_tty_info.c_line = NTTYDISC;
+      if (tcsetattr (tty, TCSADRAIN, &shell_tty_info) < 0)
+       return (-1);
+    }
+#  endif /* TERMIOS_LDISC */
+  return (0);
+#endif /* TERMIOS_TTY_DRIVER */
+
+#if !defined (NEW_TTY_DRIVER) && !defined (TERMIO_TTY_DRIVER) && !defined (TERMIOS_TTY_DRIVER)
+  return (-1);
+#endif
+}
+
+static SigHandler *old_tstp, *old_ttou, *old_ttin;
+static SigHandler *old_cont = (SigHandler *)SIG_DFL;
+static sighandler stop_signal_handler (), cont_signal_handler ();
+
+#if !defined (READLINE) && defined (TIOCGWINSZ) && defined (SIGWINCH)
+static SigHandler *old_winch;
+
+static sighandler
+sigwinch_sighandler (sig)
+     int sig;
+{
+  struct winsize win;
+
+#if defined (USG) && !defined (_POSIX_VERSION)
+  set_signal_handler (SIGWINCH, sigwinch_sighandler);
+#endif /* USG && !_POSIX_VERSION */
+  if ((ioctl (shell_tty, TIOCGWINSZ, &win) == 0) &&
+      win.ws_row > 0 && win.ws_col > 0)
+    {
+#if defined (aixpc)
+      shell_tty_info.c_winsize = win;  /* structure copying */
+#endif
+      set_lines_and_columns (win.ws_row, win.ws_col);
+    }
+}
+#endif /* !READLINE && TIOCGWINSZ && SIGWINCH */
+
+/* Setup this shell to handle C-C, etc. */
+void
+initialize_job_signals ()
+{
+  if (interactive)
+    {
+      set_signal_handler (SIGINT, sigint_sighandler);
+      set_signal_handler (SIGTSTP, SIG_IGN);
+      set_signal_handler (SIGTTOU, SIG_IGN);
+      set_signal_handler (SIGTTIN, SIG_IGN);
+#if !defined (READLINE) && defined (TIOCGWINSZ) && defined (SIGWINCH)
+      old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
+#endif /* !READLINE && TIOCGWINSZ && SIGWINCH */
+    }
+  else if (job_control)
+    {
+      old_tstp = set_signal_handler (SIGTSTP, stop_signal_handler);
+      old_ttou = set_signal_handler (SIGTTOU, stop_signal_handler);
+      old_ttin = set_signal_handler (SIGTTIN, stop_signal_handler);
+    }
+  /* Leave these things alone for non-interactive shells without job
+     control. */
+}
+
+/* Here we handle CONT signals. */
+static sighandler
+cont_signal_handler (sig)
+     int sig;
+{
+  initialize_job_signals ();
+  set_signal_handler (SIGCONT, old_cont);
+  kill (getpid (), SIGCONT);
+
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* VOID_SIGHANDLER */
+}
+
+/* Here we handle stop signals while we are running not as a login shell. */
+static sighandler
+stop_signal_handler (sig)
+     int sig;
+{
+  set_signal_handler (SIGTSTP, old_tstp);
+  set_signal_handler (SIGTTOU, old_ttou);
+  set_signal_handler (SIGTTIN, old_ttin);
+
+  old_cont = set_signal_handler (SIGCONT, cont_signal_handler);
+
+  give_terminal_to (shell_pgrp);
+
+  kill (getpid (), sig);
+
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* VOID_SIGHANDLER */
+}
+
+/* Give the terminal to PGRP.  */
+give_terminal_to (pgrp)
+     pid_t pgrp;
+{
+  sigset_t set, oset;
+  int r = 0;
+
+  if (job_control)
+    {
+      sigemptyset (&set);
+      sigaddset (&set, SIGTTOU);
+      sigaddset (&set, SIGTTIN);
+      sigaddset (&set, SIGTSTP);
+      sigaddset (&set, SIGCHLD);
+      sigemptyset (&oset);
+      sigprocmask (SIG_BLOCK, &set, &oset);
+
+      if (tcsetpgrp (shell_tty, pgrp) < 0)
+       {
+         /* Maybe we should print an error message? */
+/*       internal_error ("tcsetpgrp(%d) failed: pid %d to pgrp %d: %s",
+           shell_tty, getpid(), pgrp, strerror (errno)); */
+         r = -1;
+       }
+      else
+       terminal_pgrp = pgrp;
+
+      sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+    }
+
+  return r;
+}
+
+/* Clear out any jobs in the job array.  This is intended to be used by
+   children of the shell, who should not have any job structures as baggage
+   when they start executing (forking subshells for parenthesized execution
+   and functions with pipes are the two that spring to mind). */
+static void
+delete_all_jobs ()
+{
+  register int i;
+  sigset_t set, oset;
+
+  if (job_slots)
+    {
+      BLOCK_CHILD (set, oset);
+
+      if (job_slots)
+       {
+         current_job = previous_job = NO_JOB;
+
+         for (i = 0; i < job_slots; i++)
+         if (jobs[i] != (JOB *) NULL)
+           delete_job (i);
+
+         free ((char *)jobs);
+         job_slots = 0;
+       }
+
+      UNBLOCK_CHILD (oset);
+    }
+}
+
+/* Mark all dead jobs as notified, so delete_job () cleans them out
+   of the job table properly. */
+static void
+mark_dead_jobs_as_notified ()
+{
+  register int i;
+  sigset_t set, oset;
+
+  if (job_slots)
+    {
+      BLOCK_CHILD (set, oset);
+
+      for (i = 0; i < job_slots; i++)
+       if (jobs[i] && JOBSTATE (i) == JDEAD)
+         jobs[i]->flags |= J_NOTIFIED;
+
+      UNBLOCK_CHILD (oset);
+    }
+}
+
+/* Allow or disallow job control to take place.  Returns the old value
+   of job_control. */
+int
+set_job_control (arg)
+     int arg;
+{
+  int old;
+
+  old = job_control;
+  job_control = arg;
+  return (old);
+}
+
+/* Turn off all traces of job control.  This is run by children of the shell
+   which are going to do shellsy things, like wait (), etc. */
+void
+without_job_control ()
+{
+  stop_making_children ();
+  start_pipeline ();
+  delete_all_jobs ();
+  set_job_control (0);
+}
+
+/* If this shell is interactive, terminate all stopped jobs and
+   restore the original terminal process group.  This is done
+   before the `exec' builtin calls shell_execve. */
+void
+end_job_control ()
+{
+  if (interactive_shell)               /* XXX - should it be interactive? */
+    {
+      terminate_stopped_jobs ();
+
+      if (original_pgrp >= 0)
+       give_terminal_to (original_pgrp);
+    }
+
+  if (original_pgrp >= 0)
+    setpgid (0, original_pgrp);
+}
+
+/* Restart job control by closing shell tty and reinitializing.  This is
+   called after an exec fails in an interactive shell and we do not exit. */
+void
+restart_job_control ()
+{
+  if (shell_tty != -1)
+    close (shell_tty);
+  initialize_jobs ();
+}
+
+/* Set the handler to run when the shell receives a SIGCHLD signal. */
+void
+set_sigchld_handler ()
+{
+  set_signal_handler (SIGCHLD, flush_child);
+}
+
+#if defined (PGRP_PIPE)
+/* Read from the read end of a pipe.  This is how the process group leader
+   blocks until all of the processes in a pipeline have been made. */
+static void
+pipe_read (pp)
+     int *pp;
+{
+  char ch;
+
+  if (pp[1] >= 0)
+    {
+      close (pp[1]);
+      pp[1] = -1;
+    }
+
+  if (pp[0] >= 0)
+    {
+      while (read (pp[0], &ch, 1) == -1 && errno == EINTR)
+       continue;
+    }
+}
+
+/* Close the read and write ends of PP, an array of file descriptors. */
+static void
+pipe_close (pp)
+     int *pp;
+{
+  if (pp[0] >= 0)
+    close (pp[0]);
+
+  if (pp[1] >= 0)
+    close (pp[1]);
+
+  pp[0] = pp[1] = -1;
+}
+
+/* Functional interface closes our local-to-job-control pipes. */
+close_pgrp_pipe ()
+{
+  pipe_close (pgrp_pipe);
+}
+
+#endif /* PGRP_PIPE */
+
+#endif /* JOB_CONTROL */
diff --git a/jobs.h b/jobs.h
new file mode 100644 (file)
index 0000000..18d3d73
--- /dev/null
+++ b/jobs.h
@@ -0,0 +1,345 @@
+/* jobs.h -- structures and stuff used by the jobs.c file. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (__JOBS_H__)
+#  define __JOBS_H__
+
+#include "quit.h"
+#include "siglist.h"
+
+#include "stdc.h"
+
+/* Defines controlling the fashion in which jobs are listed. */
+#define JLIST_STANDARD 0
+#define JLIST_LONG     1
+#define JLIST_PID_ONLY 2
+#define JLIST_CHANGED_ONLY 3
+
+#if defined (HAVE_WAIT_H)
+#  include <sys/wait.h>
+#else /* !HAVE_WAIT_H */
+
+#  include "bash_endian.h"
+
+#  if !defined (_POSIX_VERSION)
+#    if defined (LITTLE_ENDIAN)
+union wait
+  {
+    int        w_status;               /* used in syscall */
+
+    /* Terminated process status. */
+    struct
+      {
+       unsigned short
+         w_Termsig  : 7,       /* termination signal */
+         w_Coredump : 1,       /* core dump indicator */
+         w_Retcode  : 8,       /* exit code if w_termsig==0 */
+         w_Fill1    : 16;      /* high 16 bits unused */
+      } w_T;
+
+    /* Stopped process status.  Returned
+       only for traced children unless requested
+       with the WUNTRACED option bit. */
+    struct
+      {
+       unsigned short
+         w_Stopval : 8,        /* == W_STOPPED if stopped */
+         w_Stopsig : 8,        /* actually zero on XENIX */
+         w_Fill2   : 16;       /* high 16 bits unused */
+      } w_S;
+  };
+
+#    else  /* !LITTLE_ENDIAN */
+
+/* This is for big-endian machines like the IBM RT, HP 9000, or Sun-3 */
+
+union wait
+  {
+    int        w_status;               /* used in syscall */
+
+    /* Terminated process status. */
+    struct
+      {
+       unsigned short w_Fill1    : 16; /* high 16 bits unused */
+       unsigned       w_Retcode  : 8;  /* exit code if w_termsig==0 */
+       unsigned       w_Coredump : 1;  /* core dump indicator */
+       unsigned       w_Termsig  : 7;  /* termination signal */
+      } w_T;
+
+    /* Stopped process status.  Returned
+       only for traced children unless requested
+       with the WUNTRACED option bit. */
+    struct
+      {
+       unsigned short w_Fill2   : 16;  /* high 16 bits unused */
+       unsigned       w_Stopsig : 8;   /* signal that stopped us */
+       unsigned       w_Stopval : 8;   /* == W_STOPPED if stopped */
+      } w_S;
+  };
+
+#    endif /* !LITTLE_ENDIAN */
+
+#    define w_termsig  w_T.w_Termsig
+#    define w_coredump w_T.w_Coredump
+#    define w_retcode  w_T.w_Retcode
+#    define w_stopval  w_S.w_Stopval
+#    define w_stopsig  w_S.w_Stopsig
+
+/* Note that sys/wait.h defines these for Posix systems. */
+#    define WSTOPPED 0177
+#    define WIFSTOPPED(x) (((x) . w_stopval) == WSTOPPED)
+#    define WIFEXITED(x) ((! (WIFSTOPPED (x))) && (((x) . w_termsig) == 0))
+#    define WIFSIGNALED(x) ((! (WIFSTOPPED (x))) && (((x) . w_termsig) != 0))
+#  endif /* !_POSIX_VERSION */
+#endif  /* !HAVE_WAIT_H */
+
+/* How to get the status of a job.  For Posix, this is just an
+   int, but for other systems we have to crack the union wait. */
+#if !defined (_POSIX_VERSION)
+#  define pid_t int
+typedef union wait WAIT;
+#  define WSTATUS(t)  (t.w_status)
+#else /* _POSIX_VERSION */
+typedef int WAIT;
+#  define WSTATUS(t)  (t)
+#endif /* _POSIX_VERSION */
+
+/* Make sure that parameters to wait3 are defined. */
+#if !defined (WNOHANG)
+#  define WNOHANG 1
+#  define WUNTRACED 2
+#endif /* WNOHANG */
+
+/* More Posix P1003.1 definitions.  In the POSIX versions, the parameter is
+   passed as an `int', in the non-POSIX version, as `union wait'. */
+#if defined (_POSIX_VERSION)
+
+#  if !defined (WSTOPSIG)
+#    define WSTOPSIG(s)       ((s) >> 8)
+#  endif /* !WSTOPSIG */
+
+#  if !defined (WTERMSIG)
+#    define WTERMSIG(s)              ((s) & 0177)
+#  endif /* !WTERMSIG */
+
+#  if !defined (WEXITSTATUS)
+#    define WEXITSTATUS(s)    ((s) >> 8)
+#  endif /* !WEXITSTATUS */
+
+#  if !defined (WIFSTOPPED)
+#    define WIFSTOPPED(s)     (((s) & 0177) == 0177)
+#  endif /* !WIFSTOPPED */
+
+#  if !defined (WIFEXITED)
+#    define WIFEXITED(s)      (((s) & 0377) == 0)
+#  endif /* !WIFEXITED */
+
+#  if !defined (WIFSIGNALED)
+#    define WIFSIGNALED(s)    (!WIFSTOPPED(s) && !WIFEXITED(s))
+#  endif /* !WIFSIGNALED */
+
+#  if !defined (WIFCORED)
+#    define WIFCORED(s)       ((s) & 0200)
+#  endif /* !WIFCORED */
+
+#else /* !_POSIX_VERSION */
+
+#  if !defined (WSTOPSIG)
+#    define WSTOPSIG(s)              ((s).w_stopsig)
+#  endif /* !WSTOPSIG */
+
+#  if !defined (WTERMSIG)
+#    define WTERMSIG(s)              ((s).w_termsig)
+#  endif /* !WTERMSIG */
+
+#  if !defined (WEXITSTATUS)
+#    define WEXITSTATUS(s)    ((s).w_retcode)
+#  endif /* !WEXITSTATUS */
+
+#  if !defined (WIFCORED)
+#    define WIFCORED(s)       ((s).w_coredump)
+#  endif /* !WIFCORED */
+
+#endif /* !_POSIX_VERSION */
+
+/* I looked it up.  For pretty_print_job ().  The real answer is 24. */
+#define LONGEST_SIGNAL_DESC 24
+
+/* We keep an array of jobs.  Each entry in the array is a linked list
+   of processes that are piped together.  The first process encountered is
+   the group leader. */
+
+/* Each child of the shell is remembered in a STRUCT PROCESS.  A chain of
+   such structures is a pipeline.  The chain is circular. */
+typedef struct process {
+  struct process *next;        /* Next process in the pipeline.  A circular chain. */
+  pid_t pid;           /* Process ID. */
+  WAIT status;         /* The status of this command as returned by wait. */
+  int running;         /* Non-zero if this process is running. */
+  char *command;       /* The particular program that is running. */
+} PROCESS;
+
+/* A description of a pipeline's state. */
+typedef enum { JRUNNING, JSTOPPED, JDEAD, JMIXED } JOB_STATE;
+#define JOBSTATE(job) (jobs[(job)]->state)
+
+/* Values for the FLAGS field in the JOB struct below. */
+#define J_FOREGROUND 0x01 /* Non-zero if this is running in the foreground.  */
+#define J_NOTIFIED   0x02 /* Non-zero if already notified about job state.   */
+#define J_JOBCONTROL 0x04 /* Non-zero if this job started under job control. */
+
+typedef struct job {
+  char *wd;       /* The working directory at time of invocation. */
+  PROCESS *pipe;   /* The pipeline of processes that make up this job. */
+  pid_t pgrp;     /* The process ID of the process group (necessary). */
+  JOB_STATE state; /* The state that this job is in. */
+  int flags;      /* Flags word: J_NOTIFIED, J_FOREGROUND, or J_JOBCONTROL. */
+#if defined (JOB_CONTROL)
+  COMMAND *deferred;   /* Commands that will execute when this job is done. */
+#endif /* JOB_CONTROL */
+} JOB;
+
+#define NO_JOB  -1     /* An impossible job array index. */
+#define DUP_JOB -2     /* A possible return value for get_job_spec (). */
+
+/* A value which cannot be a process ID. */
+#define NO_PID (pid_t)-1
+
+#if !defined (_POSIX_VERSION) && !defined (sigmask)
+#  define sigmask(x) (1 << ((x)-1))
+#endif /* !POSIX && !sigmask */
+
+#if !defined (SIGABRT)
+#  define SIGABRT SIGIOT
+#endif /* !SIGABRT */
+
+#if !defined (SIGCHLD)
+#  define SIGCHLD SIGCLD
+#endif /* !SIGCHLD */
+
+#if !defined (_POSIX_VERSION)
+#  if !defined (SIG_BLOCK)
+#    define SIG_BLOCK 2
+#    define SIG_SETMASK 3
+#  endif /* SIG_BLOCK */
+
+/* Type of a signal set. */
+#  define sigset_t int
+
+/* Make sure there is nothing inside the signal set. */
+#  define sigemptyset(set) (*(set) = 0)
+
+/* Initialize the signal set to hold all signals. */
+#  define sigfillset(set) (*set) = sigmask (NSIG) - 1
+
+/* Add SIG to the contents of SET. */
+#  define sigaddset(set, sig) *(set) |= sigmask (sig)
+
+/* Delete SIG from signal set SET. */
+#  define sigdelset(set, sig) *(set) &= ~sigmask (sig)
+
+/* Is SIG a member of the signal set SET? */
+#  define sigismember(set, sig) ((*(set) & sigmask (sig)) != 0)
+
+/* Suspend the process until the reception of one of the signals
+   not present in SET. */
+#  define sigsuspend(set) sigpause (*(set))
+#endif /* !_POSIX_VERSION */
+
+/* These definitions are used both in POSIX and non-POSIX implementations. */
+
+#define BLOCK_SIGNAL(sig, nvar, ovar) \
+  sigemptyset (&nvar); \
+  sigaddset (&nvar, sig); \
+  sigemptyset (&ovar); \
+  sigprocmask (SIG_BLOCK, &nvar, &ovar)
+
+#if defined (_POSIX_VERSION)
+#  define BLOCK_CHILD(nvar, ovar) \
+       BLOCK_SIGNAL (SIGCHLD, nvar, ovar)
+#  define UNBLOCK_CHILD(ovar) \
+       sigprocmask (SIG_SETMASK, &ovar, (sigset_t *) NULL)
+#else /* !_POSIX_VERSION */
+#  define BLOCK_CHILD(nvar, ovar) ovar = sigblock (sigmask (SIGCHLD))
+#  define UNBLOCK_CHILD(ovar) sigsetmask (ovar)
+#endif /* !_POSIX_VERSION */
+
+/* System calls. */
+#if !defined (SunOS5) && !defined (USGr4_2) && !defined (__BSD_4_4__)
+extern pid_t fork (), getpid (), getpgrp ();
+#endif /* !SunOS5 && !USGr4_2 && !__BSD_4_4__ */
+
+/* Stuff from the jobs.c file. */
+extern pid_t  original_pgrp, shell_pgrp, pipeline_pgrp;
+extern pid_t last_made_pid, last_asynchronous_pid;
+extern int current_job, previous_job;
+extern int asynchronous_notification;
+extern JOB **jobs;
+extern int job_slots;
+
+extern void making_children __P((void));
+extern void stop_making_children __P((void));
+extern void cleanup_the_pipeline __P((void));
+extern void start_pipeline __P((void));
+extern int stop_pipeline __P((int, COMMAND *));
+extern void delete_job __P((int));
+
+extern void terminate_current_pipeline __P((void));
+extern void terminate_stopped_jobs __P((void));
+extern void hangup_all_jobs __P((void));
+extern void kill_current_pipeline __P((void));
+
+#if defined (__STDC__) && defined (pid_t)
+extern void describe_pid __P((int));
+#else
+extern void describe_pid __P((pid_t));
+#endif
+
+extern int list_one_job __P((JOB *, int, int, int));
+extern void list_jobs __P((int));
+
+extern pid_t make_child __P((char *, int));
+extern int get_tty_state __P((void));
+extern int set_tty_state __P((void));
+
+extern int wait_for_single_pid __P((pid_t));
+extern void wait_for_background_pids __P((void));
+extern int wait_for __P((pid_t));
+extern int wait_for_job __P((int));
+
+extern void notify_and_cleanup __P((void));
+extern void reap_dead_jobs __P((void));
+extern int start_job __P((int, int));
+extern int kill_pid __P((pid_t, int, int));
+extern int initialize_jobs __P((void));
+extern void initialize_job_signals __P((void));
+extern int give_terminal_to __P((pid_t));
+
+extern int set_job_control __P((int));
+extern void without_job_control __P((void));
+extern void end_job_control __P((void));
+extern void restart_job_control __P((void));
+extern void set_sigchld_handler __P((void));
+
+#if defined (JOB_CONTROL)
+extern int job_control;
+#endif
+
+#endif /* __JOBS_H__ */
diff --git a/lib/doc-support/Makefile b/lib/doc-support/Makefile
new file mode 100644 (file)
index 0000000..553b61f
--- /dev/null
@@ -0,0 +1,23 @@
+GETOPT = ${topdir}/builtins/getopt.o
+OBJECTS = texindex.o $(GETOPT)
+SOURCES = texindex.c
+
+LDFLAGS = -g
+
+srcdir = .
+VPATH = .:$(srcdir)
+
+.c.o:
+       rm -f $@
+       $(CC) $(CFLAGS) -c $<
+
+all: texindex
+
+texindex: texindex.o
+       $(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS)
+
+clean:
+       rm -f texindex.o
+
+realclean distclean maintainer-clean:  clean
+       rm -f texindex
diff --git a/lib/doc-support/getopt.h b/lib/doc-support/getopt.h
new file mode 100644 (file)
index 0000000..45541f5
--- /dev/null
@@ -0,0 +1,129 @@
+/* Declarations for getopt.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument         (or 0) if the option does not take an argument,
+   required_argument   (or 1) if the option requires an argument,
+   optional_argument   (or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+struct option
+{
+#if    __STDC__
+  const char *name;
+#else
+  char *name;
+#endif
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+#define        no_argument             0
+#define required_argument      1
+#define optional_argument      2
+
+#if __STDC__
+#if defined(__GNU_LIBRARY__)
+/* Many other libraries have conflicting prototypes for getopt, with
+   differences in the consts, in stdlib.h.  To avoid compilation
+   errors, only prototype getopt for the GNU C library.  */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* not __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+                       const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+                            const char *shortopts,
+                            const struct option *longopts, int *longind);
+
+/* Internal only.  Users should not call this directly.  */
+extern int _getopt_internal (int argc, char *const *argv,
+                            const char *shortopts,
+                            const struct option *longopts, int *longind,
+                            int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* not __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/lib/doc-support/texindex.c b/lib/doc-support/texindex.c
new file mode 100644 (file)
index 0000000..9233bab
--- /dev/null
@@ -0,0 +1,1666 @@
+/* Prepare TeX index dribble output into an actual index.
+
+   Version 1.45
+
+   Copyright (C) 1987, 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+\f
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include "getopt.h"
+#include "bashansi.h"
+
+#if !defined (errno)
+extern int errno;
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#else /* !HAVE_UNISTD_H */
+extern long lseek ();
+#endif /* !HAVE_UNISTD_H */
+
+extern char *mktemp ();
+
+#if !defined (HAVE_STRERROR)
+extern int sys_nerr;
+extern char *sys_errlist[];
+#endif
+
+#include <sys/types.h>
+
+#if defined (_AIX) || !defined (_POSIX_VERSION)
+#  include <sys/file.h>
+#endif
+
+#include <fcntl.h>
+
+#define TI_NO_ERROR 0
+#define TI_FATAL_ERROR 1
+
+#if !defined (SEEK_SET)
+#  define SEEK_SET 0
+#  define SEEK_CUR 1
+#  define SEEK_END 2
+#endif /* !SEEK_SET */
+
+/* When sorting in core, this structure describes one line
+   and the position and length of its first keyfield.  */
+struct lineinfo
+{
+  char *text;          /* The actual text of the line. */
+  union {
+    char *text;                /* The start of the key (for textual comparison). */
+    long number;       /* The numeric value (for numeric comparison). */
+  } key;
+  long keylen;         /* Length of KEY field. */
+};
+
+/* This structure describes a field to use as a sort key. */
+struct keyfield
+{
+  int startwords;      /* Number of words to skip. */
+  int startchars;      /* Number of additional chars to skip. */
+  int endwords;                /* Number of words to ignore at end. */
+  int endchars;                /* Ditto for characters of last word. */
+  char ignore_blanks;  /* Non-zero means ignore spaces and tabs. */
+  char fold_case;      /* Non-zero means case doesn't matter. */
+  char reverse;                /* Non-zero means compare in reverse order. */
+  char numeric;                /* Non-zeros means field is ASCII numeric. */
+  char positional;     /* Sort according to file position. */
+  char braced;         /* Count balanced-braced groupings as fields. */
+};
+
+/* Vector of keyfields to use. */
+struct keyfield keyfields[3];
+
+/* Number of keyfields stored in that vector.  */
+int num_keyfields = 3;
+
+/* Vector of input file names, terminated with a null pointer. */
+char **infiles;
+
+/* Vector of corresponding output file names, or NULL, meaning default it
+   (add an `s' to the end). */
+char **outfiles;
+
+/* Length of `infiles'. */
+int num_infiles;
+
+/* Pointer to the array of pointers to lines being sorted. */
+char **linearray;
+
+/* The allocated length of `linearray'. */
+long nlines;
+
+/* Directory to use for temporary files.  On Unix, it ends with a slash.  */
+char *tempdir;
+
+/* Start of filename to use for temporary files.  */
+char *tempbase;
+
+/* Number of last temporary file.  */
+int tempcount;
+
+/* Number of last temporary file already deleted.
+   Temporary files are deleted by `flush_tempfiles' in order of creation.  */
+int last_deleted_tempcount;
+
+/* During in-core sort, this points to the base of the data block
+   which contains all the lines of data.  */
+char *text_base;
+
+/* Additional command switches .*/
+
+/* Nonzero means do not delete tempfiles -- for debugging. */
+int keep_tempfiles;
+
+/* The name this program was run with. */
+char *program_name;
+
+/* Forward declarations of functions in this file. */
+
+void decode_command ();
+void sort_in_core ();
+void sort_offline ();
+char **parsefile ();
+char *find_field ();
+char *find_pos ();
+long find_value ();
+char *find_braced_pos ();
+char *find_braced_end ();
+void writelines ();
+int compare_field ();
+int compare_full ();
+long readline ();
+int merge_files ();
+int merge_direct ();
+void pfatal_with_name ();
+void fatal ();
+void error ();
+void *xmalloc (), *xrealloc ();
+char *concat ();
+char *maketempname ();
+void flush_tempfiles ();
+char *tempcopy ();
+\f
+#define MAX_IN_CORE_SORT 500000
+
+void
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int i;
+
+  tempcount = 0;
+  last_deleted_tempcount = 0;
+  program_name = argv[0];
+
+  /* Describe the kind of sorting to do. */
+  /* The first keyfield uses the first braced field and folds case. */
+  keyfields[0].braced = 1;
+  keyfields[0].fold_case = 1;
+  keyfields[0].endwords = -1;
+  keyfields[0].endchars = -1;
+
+  /* The second keyfield uses the second braced field, numerically. */
+  keyfields[1].braced = 1;
+  keyfields[1].numeric = 1;
+  keyfields[1].startwords = 1;
+  keyfields[1].endwords = -1;
+  keyfields[1].endchars = -1;
+
+  /* The third keyfield (which is ignored while discarding duplicates)
+     compares the whole line. */
+  keyfields[2].endwords = -1;
+  keyfields[2].endchars = -1;
+
+  decode_command (argc, argv);
+
+  tempbase = mktemp (concat ("txiXXXXXX", "", ""));
+
+  /* Process input files completely, one by one.  */
+
+  for (i = 0; i < num_infiles; i++)
+    {
+      int desc;
+      long ptr;
+      char *outfile;
+
+      desc = open (infiles[i], O_RDONLY, 0);
+      if (desc < 0)
+       pfatal_with_name (infiles[i]);
+      lseek (desc, 0L, SEEK_END);
+      ptr = lseek (desc, 0L, SEEK_CUR);
+
+      close (desc);
+
+      outfile = outfiles[i];
+      if (!outfile)
+       {
+         outfile = concat (infiles[i], "s", "");
+       }
+
+      if (ptr < MAX_IN_CORE_SORT)
+       /* Sort a small amount of data. */
+       sort_in_core (infiles[i], ptr, outfile);
+      else
+       sort_offline (infiles[i], ptr, outfile);
+    }
+
+  flush_tempfiles (tempcount);
+  exit (TI_NO_ERROR);
+}
+\f
+void
+usage ()
+{
+  fprintf (stderr, "\
+Usage: %s [-k] infile [-o outfile] ...\n", program_name);
+  exit (1);
+}
+
+/* Decode the command line arguments to set the parameter variables
+   and set up the vector of keyfields and the vector of input files. */
+
+void
+decode_command (argc, argv)
+     int argc;
+     char **argv;
+{
+  int optc;
+  char **ip;
+  char **op;
+
+  /* Store default values into parameter variables. */
+
+  tempdir = getenv ("TMPDIR");
+  if (tempdir == NULL)
+    tempdir = "/tmp/";
+  else
+    tempdir = concat (tempdir, "/", "");
+
+  keep_tempfiles = 0;
+
+  /* Allocate ARGC input files, which must be enough.  */
+
+  infiles = (char **) xmalloc (argc * sizeof (char *));
+  outfiles = (char **) xmalloc (argc * sizeof (char *));
+  ip = infiles;
+  op = outfiles;
+
+  while ((optc = getopt (argc, argv, "-ko:")) != EOF)
+    {
+      switch (optc)
+       {
+       case 1:         /* Non-option filename. */
+         *ip++ = optarg;
+         *op++ = NULL;
+         break;
+
+       case 'k':
+         keep_tempfiles = 1;
+         break;
+
+       case 'o':
+         if (op > outfiles)
+           *(op - 1) = optarg;
+         break;
+
+       default:
+         usage ();
+       }
+    }
+
+  /* Record number of keyfields and terminate list of filenames. */
+  num_infiles = ip - infiles;
+  *ip = 0;
+  if (num_infiles == 0)
+    usage ();
+}
+\f
+/* Return a name for a temporary file. */
+
+char *
+maketempname (count)
+     int count;
+{
+  char tempsuffix[10];
+  sprintf (tempsuffix, "%d", count);
+  return concat (tempdir, tempbase, tempsuffix);
+}
+
+/* Delete all temporary files up to TO_COUNT. */
+
+void
+flush_tempfiles (to_count)
+     int to_count;
+{
+  if (keep_tempfiles)
+    return;
+  while (last_deleted_tempcount < to_count)
+    unlink (maketempname (++last_deleted_tempcount));
+}
+
+/* Copy the input file open on IDESC into a temporary file
+   and return the temporary file name. */
+
+#define BUFSIZE 1024
+
+char *
+tempcopy (idesc)
+     int idesc;
+{
+  char *outfile = maketempname (++tempcount);
+  int odesc;
+  char buffer[BUFSIZE];
+
+  odesc = open (outfile, O_WRONLY | O_CREAT, 0666);
+
+  if (odesc < 0)
+    pfatal_with_name (outfile);
+
+  while (1)
+    {
+      int nread = read (idesc, buffer, BUFSIZE);
+      write (odesc, buffer, nread);
+      if (!nread)
+       break;
+    }
+
+  close (odesc);
+
+  return outfile;
+}
+\f
+/* Compare LINE1 and LINE2 according to the specified set of keyfields. */
+
+int
+compare_full (line1, line2)
+     char **line1, **line2;
+{
+  int i;
+
+  /* Compare using the first keyfield;
+     if that does not distinguish the lines, try the second keyfield;
+     and so on. */
+
+  for (i = 0; i < num_keyfields; i++)
+    {
+      long length1, length2;
+      char *start1 = find_field (&keyfields[i], *line1, &length1);
+      char *start2 = find_field (&keyfields[i], *line2, &length2);
+      int tem = compare_field (&keyfields[i], start1, length1, *line1 - text_base,
+                              start2, length2, *line2 - text_base);
+      if (tem)
+       {
+         if (keyfields[i].reverse)
+           return -tem;
+         return tem;
+       }
+    }
+
+  return 0;                    /* Lines match exactly. */
+}
+
+/* Compare LINE1 and LINE2, described by structures
+   in which the first keyfield is identified in advance.
+   For positional sorting, assumes that the order of the lines in core
+   reflects their nominal order.  */
+
+int
+compare_prepared (line1, line2)
+     struct lineinfo *line1, *line2;
+{
+  int i;
+  int tem;
+  char *text1, *text2;
+
+  /* Compare using the first keyfield, which has been found for us already. */
+  if (keyfields->positional)
+    {
+      if (line1->text - text_base > line2->text - text_base)
+       tem = 1;
+      else
+       tem = -1;
+    }
+  else if (keyfields->numeric)
+    tem = line1->key.number - line2->key.number;
+  else
+    tem = compare_field (keyfields, line1->key.text, line1->keylen, 0,
+                        line2->key.text, line2->keylen, 0);
+  if (tem)
+    {
+      if (keyfields->reverse)
+       return -tem;
+      return tem;
+    }
+
+  text1 = line1->text;
+  text2 = line2->text;
+
+  /* Compare using the second keyfield;
+     if that does not distinguish the lines, try the third keyfield;
+     and so on. */
+
+  for (i = 1; i < num_keyfields; i++)
+    {
+      long length1, length2;
+      char *start1 = find_field (&keyfields[i], text1, &length1);
+      char *start2 = find_field (&keyfields[i], text2, &length2);
+      int tem = compare_field (&keyfields[i], start1, length1, text1 - text_base,
+                              start2, length2, text2 - text_base);
+      if (tem)
+       {
+         if (keyfields[i].reverse)
+           return -tem;
+         return tem;
+       }
+    }
+
+  return 0;                    /* Lines match exactly. */
+}
+
+/* Like compare_full but more general.
+   You can pass any strings, and you can say how many keyfields to use.
+   POS1 and POS2 should indicate the nominal positional ordering of
+   the two lines in the input.  */
+
+int
+compare_general (str1, str2, pos1, pos2, use_keyfields)
+     char *str1, *str2;
+     long pos1, pos2;
+     int use_keyfields;
+{
+  int i;
+
+  /* Compare using the first keyfield;
+     if that does not distinguish the lines, try the second keyfield;
+     and so on. */
+
+  for (i = 0; i < use_keyfields; i++)
+    {
+      long length1, length2;
+      char *start1 = find_field (&keyfields[i], str1, &length1);
+      char *start2 = find_field (&keyfields[i], str2, &length2);
+      int tem = compare_field (&keyfields[i], start1, length1, pos1,
+                              start2, length2, pos2);
+      if (tem)
+       {
+         if (keyfields[i].reverse)
+           return -tem;
+         return tem;
+       }
+    }
+
+  return 0;                    /* Lines match exactly. */
+}
+
+/* Find the start and length of a field in STR according to KEYFIELD.
+   A pointer to the starting character is returned, and the length
+   is stored into the int that LENGTHPTR points to.  */
+
+char *
+find_field (keyfield, str, lengthptr)
+     struct keyfield *keyfield;
+     char *str;
+     long *lengthptr;
+{
+  char *start;
+  char *end;
+  char *(*fun) ();
+
+  if (keyfield->braced)
+    fun = find_braced_pos;
+  else
+    fun = find_pos;
+
+  start = (*fun) (str, keyfield->startwords, keyfield->startchars,
+                 keyfield->ignore_blanks);
+  if (keyfield->endwords < 0)
+    {
+      if (keyfield->braced)
+       end = find_braced_end (start);
+      else
+       {
+         end = start;
+         while (*end && *end != '\n')
+           end++;
+       }
+    }
+  else
+    {
+      end = (*fun) (str, keyfield->endwords, keyfield->endchars, 0);
+      if (end - str < start - str)
+       end = start;
+    }
+  *lengthptr = end - start;
+  return start;
+}
+
+/* Return a pointer to a specified place within STR,
+   skipping (from the beginning) WORDS words and then CHARS chars.
+   If IGNORE_BLANKS is nonzero, we skip all blanks
+   after finding the specified word.  */
+
+char *
+find_pos (str, words, chars, ignore_blanks)
+     char *str;
+     int words, chars;
+     int ignore_blanks;
+{
+  int i;
+  char *p = str;
+
+  for (i = 0; i < words; i++)
+    {
+      char c;
+      /* Find next bunch of nonblanks and skip them. */
+      while ((c = *p) == ' ' || c == '\t')
+       p++;
+      while ((c = *p) && c != '\n' && !(c == ' ' || c == '\t'))
+       p++;
+      if (!*p || *p == '\n')
+       return p;
+    }
+
+  while (*p == ' ' || *p == '\t')
+    p++;
+
+  for (i = 0; i < chars; i++)
+    {
+      if (!*p || *p == '\n')
+       break;
+      p++;
+    }
+  return p;
+}
+
+/* Like find_pos but assumes that each field is surrounded by braces
+   and that braces within fields are balanced. */
+
+char *
+find_braced_pos (str, words, chars, ignore_blanks)
+     char *str;
+     int words, chars;
+     int ignore_blanks;
+{
+  int i;
+  int bracelevel;
+  char *p = str;
+  char c;
+
+  for (i = 0; i < words; i++)
+    {
+      bracelevel = 1;
+      while ((c = *p++) != '{' && c != '\n' && c)
+       /* Do nothing. */ ;
+      if (c != '{')
+       return p - 1;
+      while (bracelevel)
+       {
+         c = *p++;
+         if (c == '{')
+           bracelevel++;
+         if (c == '}')
+           bracelevel--;
+         if (c == 0 || c == '\n')
+           return p - 1;
+       }
+    }
+
+  while ((c = *p++) != '{' && c != '\n' && c)
+    /* Do nothing. */ ;
+
+  if (c != '{')
+    return p - 1;
+
+  if (ignore_blanks)
+    while ((c = *p) == ' ' || c == '\t')
+      p++;
+
+  for (i = 0; i < chars; i++)
+    {
+      if (!*p || *p == '\n')
+       break;
+      p++;
+    }
+  return p;
+}
+
+/* Find the end of the balanced-brace field which starts at STR.
+   The position returned is just before the closing brace. */
+
+char *
+find_braced_end (str)
+     char *str;
+{
+  int bracelevel;
+  char *p = str;
+  char c;
+
+  bracelevel = 1;
+  while (bracelevel)
+    {
+      c = *p++;
+      if (c == '{')
+       bracelevel++;
+      if (c == '}')
+       bracelevel--;
+      if (c == 0 || c == '\n')
+       return p - 1;
+    }
+  return p - 1;
+}
+
+long
+find_value (start, length)
+     char *start;
+     long length;
+{
+  while (length != 0L)
+    {
+      if (isdigit (*start))
+       return atol (start);
+      length--;
+      start++;
+    }
+  return 0l;
+}
+
+/* Vector used to translate characters for comparison.
+   This is how we make all alphanumerics follow all else,
+   and ignore case in the first sorting.  */
+int char_order[256];
+
+void
+init_char_order ()
+{
+  int i;
+  for (i = 1; i < 256; i++)
+    char_order[i] = i;
+
+  for (i = '0'; i <= '9'; i++)
+    char_order[i] += 512;
+
+  for (i = 'a'; i <= 'z'; i++)
+    {
+      char_order[i] = 512 + i;
+      char_order[i + 'A' - 'a'] = 512 + i;
+    }
+}
+
+/* Compare two fields (each specified as a start pointer and a character count)
+   according to KEYFIELD.
+   The sign of the value reports the relation between the fields. */
+
+int
+compare_field (keyfield, start1, length1, pos1, start2, length2, pos2)
+     struct keyfield *keyfield;
+     char *start1;
+     long length1;
+     long pos1;
+     char *start2;
+     long length2;
+     long pos2;
+{
+  if (keyfields->positional)
+    {
+      if (pos1 > pos2)
+       return 1;
+      else
+       return -1;
+    }
+  if (keyfield->numeric)
+    {
+      long value = find_value (start1, length1) - find_value (start2, length2);
+      if (value > 0)
+       return 1;
+      if (value < 0)
+       return -1;
+      return 0;
+    }
+  else
+    {
+      char *p1 = start1;
+      char *p2 = start2;
+      char *e1 = start1 + length1;
+      char *e2 = start2 + length2;
+
+      while (1)
+       {
+         int c1, c2;
+
+         if (p1 == e1)
+           c1 = 0;
+         else
+           c1 = *p1++;
+         if (p2 == e2)
+           c2 = 0;
+         else
+           c2 = *p2++;
+
+         if (char_order[c1] != char_order[c2])
+           return char_order[c1] - char_order[c2];
+         if (!c1)
+           break;
+       }
+
+      /* Strings are equal except possibly for case.  */
+      p1 = start1;
+      p2 = start2;
+      while (1)
+       {
+         int c1, c2;
+
+         if (p1 == e1)
+           c1 = 0;
+         else
+           c1 = *p1++;
+         if (p2 == e2)
+           c2 = 0;
+         else
+           c2 = *p2++;
+
+         if (c1 != c2)
+           /* Reverse sign here so upper case comes out last.  */
+           return c2 - c1;
+         if (!c1)
+           break;
+       }
+
+      return 0;
+    }
+}
+\f
+/* A `struct linebuffer' is a structure which holds a line of text.
+   `readline' reads a line from a stream into a linebuffer
+   and works regardless of the length of the line.  */
+
+struct linebuffer
+{
+  long size;
+  char *buffer;
+};
+
+/* Initialize LINEBUFFER for use. */
+
+void
+initbuffer (linebuffer)
+     struct linebuffer *linebuffer;
+{
+  linebuffer->size = 200;
+  linebuffer->buffer = (char *) xmalloc (200);
+}
+
+/* Read a line of text from STREAM into LINEBUFFER.
+   Return the length of the line.  */
+
+long
+readline (linebuffer, stream)
+     struct linebuffer *linebuffer;
+     FILE *stream;
+{
+  char *buffer = linebuffer->buffer;
+  char *p = linebuffer->buffer;
+  char *end = p + linebuffer->size;
+
+  while (1)
+    {
+      int c = getc (stream);
+      if (p == end)
+       {
+         buffer = (char *) xrealloc (buffer, linebuffer->size *= 2);
+         p += buffer - linebuffer->buffer;
+         end += buffer - linebuffer->buffer;
+         linebuffer->buffer = buffer;
+       }
+      if (c < 0 || c == '\n')
+       {
+         *p = 0;
+         break;
+       }
+      *p++ = c;
+    }
+
+  return p - buffer;
+}
+\f
+/* Sort an input file too big to sort in core.  */
+
+void
+sort_offline (infile, nfiles, total, outfile)
+     char *infile;
+     int nfiles;
+     long total;
+     char *outfile;
+{
+  /* More than enough. */
+  int ntemps = 2 * (total + MAX_IN_CORE_SORT - 1) / MAX_IN_CORE_SORT;
+  char **tempfiles = (char **) xmalloc (ntemps * sizeof (char *));
+  FILE *istream = fopen (infile, "r");
+  int i;
+  struct linebuffer lb;
+  long linelength;
+  int failure = 0;
+
+  initbuffer (&lb);
+
+  /* Read in one line of input data.  */
+
+  linelength = readline (&lb, istream);
+
+  if (lb.buffer[0] != '\\' && lb.buffer[0] != '@')
+    {
+      error ("%s: not a texinfo index file", infile);
+      return;
+    }
+
+  /* Split up the input into `ntemps' temporary files, or maybe fewer,
+     and put the new files' names into `tempfiles' */
+
+  for (i = 0; i < ntemps; i++)
+    {
+      char *outname = maketempname (++tempcount);
+      FILE *ostream = fopen (outname, "w");
+      long tempsize = 0;
+
+      if (!ostream)
+       pfatal_with_name (outname);
+      tempfiles[i] = outname;
+
+      /* Copy lines into this temp file as long as it does not make file
+        "too big" or until there are no more lines.  */
+
+      while (tempsize + linelength + 1 <= MAX_IN_CORE_SORT)
+       {
+         tempsize += linelength + 1;
+         fputs (lb.buffer, ostream);
+         putc ('\n', ostream);
+
+         /* Read another line of input data.  */
+
+         linelength = readline (&lb, istream);
+         if (!linelength && feof (istream))
+           break;
+
+         if (lb.buffer[0] != '\\' && lb.buffer[0] != '@')
+           {
+             error ("%s: not a texinfo index file", infile);
+             failure = 1;
+             goto fail;
+           }
+       }
+      fclose (ostream);
+      if (feof (istream))
+       break;
+    }
+
+  free (lb.buffer);
+
+fail:
+  /* Record number of temp files we actually needed.  */
+
+  ntemps = i;
+
+  /* Sort each tempfile into another tempfile.
+    Delete the first set of tempfiles and put the names of the second
+    into `tempfiles'. */
+
+  for (i = 0; i < ntemps; i++)
+    {
+      char *newtemp = maketempname (++tempcount);
+      sort_in_core (&tempfiles[i], MAX_IN_CORE_SORT, newtemp);
+      if (!keep_tempfiles)
+       unlink (tempfiles[i]);
+      tempfiles[i] = newtemp;
+    }
+
+  if (failure)
+    return;
+
+  /* Merge the tempfiles together and indexify. */
+
+  merge_files (tempfiles, ntemps, outfile);
+}
+\f
+/* Sort INFILE, whose size is TOTAL,
+   assuming that is small enough to be done in-core,
+   then indexify it and send the output to OUTFILE (or to stdout).  */
+
+void
+sort_in_core (infile, total, outfile)
+     char *infile;
+     long total;
+     char *outfile;
+{
+  char **nextline;
+  char *data = (char *) xmalloc (total + 1);
+  char *file_data;
+  long file_size;
+  int i;
+  FILE *ostream = stdout;
+  struct lineinfo *lineinfo;
+
+  /* Read the contents of the file into the moby array `data'. */
+
+  int desc = open (infile, O_RDONLY, 0);
+
+  if (desc < 0)
+    fatal ("failure reopening %s", infile);
+  for (file_size = 0;;)
+    {
+      i = read (desc, data + file_size, total - file_size);
+      if (i <= 0)
+       break;
+      file_size += i;
+    }
+  file_data = data;
+  data[file_size] = 0;
+
+  close (desc);
+
+  if (file_size > 0 && data[0] != '\\' && data[0] != '@')
+    {
+      error ("%s: not a texinfo index file", infile);
+      return;
+    }
+
+  init_char_order ();
+
+  /* Sort routines want to know this address. */
+
+  text_base = data;
+
+  /* Create the array of pointers to lines, with a default size
+     frequently enough.  */
+
+  nlines = total / 50;
+  if (!nlines)
+    nlines = 2;
+  linearray = (char **) xmalloc (nlines * sizeof (char *));
+
+  /* `nextline' points to the next free slot in this array.
+     `nlines' is the allocated size.  */
+
+  nextline = linearray;
+
+  /* Parse the input file's data, and make entries for the lines.  */
+
+  nextline = parsefile (infile, nextline, file_data, file_size);
+  if (nextline == 0)
+    {
+      error ("%s: not a texinfo index file", infile);
+      return;
+    }
+
+  /* Sort the lines. */
+
+  /* If we have enough space, find the first keyfield of each line in advance.
+     Make a `struct lineinfo' for each line, which records the keyfield
+     as well as the line, and sort them.  */
+
+  lineinfo = (struct lineinfo *) malloc ((nextline - linearray) * sizeof (struct lineinfo));
+
+  if (lineinfo)
+    {
+      struct lineinfo *lp;
+      char **p;
+
+      for (lp = lineinfo, p = linearray; p != nextline; lp++, p++)
+       {
+         lp->text = *p;
+         lp->key.text = find_field (keyfields, *p, &lp->keylen);
+         if (keyfields->numeric)
+           lp->key.number = find_value (lp->key.text, lp->keylen);
+       }
+
+      qsort (lineinfo, nextline - linearray, sizeof (struct lineinfo), compare_prepared);
+
+      for (lp = lineinfo, p = linearray; p != nextline; lp++, p++)
+       *p = lp->text;
+
+      free (lineinfo);
+    }
+  else
+    qsort (linearray, nextline - linearray, sizeof (char *), compare_full);
+
+  /* Open the output file. */
+
+  if (outfile)
+    {
+      ostream = fopen (outfile, "w");
+      if (!ostream)
+       pfatal_with_name (outfile);
+    }
+
+  writelines (linearray, nextline - linearray, ostream);
+  if (outfile)
+    fclose (ostream);
+
+  free (linearray);
+  free (data);
+}
+\f
+/* Parse an input string in core into lines.
+   DATA is the input string, and SIZE is its length.
+   Data goes in LINEARRAY starting at NEXTLINE.
+   The value returned is the first entry in LINEARRAY still unused.
+   Value 0 means input file contents are invalid.  */
+
+char **
+parsefile (filename, nextline, data, size)
+     char *filename;
+     char **nextline;
+     char *data;
+     long size;
+{
+  char *p, *end;
+  char **line = nextline;
+
+  p = data;
+  end = p + size;
+  *end = 0;
+
+  while (p != end)
+    {
+      if (p[0] != '\\' && p[0] != '@')
+       return 0;
+
+      *line = p;
+      while (*p && *p != '\n')
+       p++;
+      if (p != end)
+       p++;
+
+      line++;
+      if (line == linearray + nlines)
+       {
+         char **old = linearray;
+         linearray = (char **) xrealloc (linearray, sizeof (char *) * (nlines *= 4));
+         line += linearray - old;
+       }
+    }
+
+  return line;
+}
+\f
+/* Indexification is a filter applied to the sorted lines
+   as they are being written to the output file.
+   Multiple entries for the same name, with different page numbers,
+   get combined into a single entry with multiple page numbers.
+   The first braced field, which is used for sorting, is discarded.
+   However, its first character is examined, folded to lower case,
+   and if it is different from that in the previous line fed to us
+   a \initial line is written with one argument, the new initial.
+
+   If an entry has four braced fields, then the second and third
+   constitute primary and secondary names.
+   In this case, each change of primary name
+   generates a \primary line which contains only the primary name,
+   and in between these are \secondary lines which contain
+   just a secondary name and page numbers. */
+
+/* The last primary name we wrote a \primary entry for.
+   If only one level of indexing is being done, this is the last name seen. */
+char *lastprimary;
+/* Length of storage allocated for lastprimary. */
+int lastprimarylength;
+
+/* Similar, for the secondary name. */
+char *lastsecondary;
+int lastsecondarylength;
+
+/* Zero if we are not in the middle of writing an entry.
+   One if we have written the beginning of an entry but have not
+   yet written any page numbers into it.
+   Greater than one if we have written the beginning of an entry
+   plus at least one page number. */
+int pending;
+
+/* The initial (for sorting purposes) of the last primary entry written.
+   When this changes, a \initial {c} line is written */
+
+char *lastinitial;
+
+int lastinitiallength;
+
+/* When we need a string of length 1 for the value of lastinitial,
+   store it here.  */
+
+char lastinitial1[2];
+
+/* Initialize static storage for writing an index. */
+
+static void
+xbzero(s, n)
+     char *s;
+     int n;
+{
+  register char *p;
+  for (p = s; n--; )
+    *p++ = '\0';
+}
+
+void
+init_index ()
+{
+  pending = 0;
+  lastinitial = lastinitial1;
+  lastinitial1[0] = 0;
+  lastinitial1[1] = 0;
+  lastinitiallength = 0;
+  lastprimarylength = 100;
+  lastprimary = (char *) xmalloc (lastprimarylength + 1);
+  xbzero (lastprimary, lastprimarylength + 1);
+  lastsecondarylength = 100;
+  lastsecondary = (char *) xmalloc (lastsecondarylength + 1);
+  xbzero (lastsecondary, lastsecondarylength + 1);
+}
+
+/* Indexify.  Merge entries for the same name,
+   insert headers for each initial character, etc.  */
+
+void
+indexify (line, ostream)
+     char *line;
+     FILE *ostream;
+{
+  char *primary, *secondary, *pagenumber;
+  int primarylength, secondarylength = 0, pagelength;
+  int nosecondary;
+  int initiallength;
+  char *initial;
+  char initial1[2];
+  register char *p;
+
+  /* First, analyze the parts of the entry fed to us this time. */
+
+  p = find_braced_pos (line, 0, 0, 0);
+  if (*p == '{')
+    {
+      initial = p;
+      /* Get length of inner pair of braces starting at `p',
+        including that inner pair of braces.  */
+      initiallength = find_braced_end (p + 1) + 1 - p;
+    }
+  else
+    {
+      initial = initial1;
+      initial1[0] = *p;
+      initial1[1] = 0;
+      initiallength = 1;
+
+      if (initial1[0] >= 'a' && initial1[0] <= 'z')
+       initial1[0] -= 040;
+    }
+
+  pagenumber = find_braced_pos (line, 1, 0, 0);
+  pagelength = find_braced_end (pagenumber) - pagenumber;
+  if (pagelength == 0)
+    abort ();
+
+  primary = find_braced_pos (line, 2, 0, 0);
+  primarylength = find_braced_end (primary) - primary;
+
+  secondary = find_braced_pos (line, 3, 0, 0);
+  nosecondary = !*secondary;
+  if (!nosecondary)
+    secondarylength = find_braced_end (secondary) - secondary;
+
+  /* If the primary is different from before, make a new primary entry. */
+  if (strncmp (primary, lastprimary, primarylength))
+    {
+      /* Close off current secondary entry first, if one is open. */
+      if (pending)
+       {
+         fputs ("}\n", ostream);
+         pending = 0;
+       }
+
+      /* If this primary has a different initial, include an entry for
+        the initial. */
+      if (initiallength != lastinitiallength ||
+         strncmp (initial, lastinitial, initiallength))
+       {
+         fprintf (ostream, "\\initial {");
+         fwrite (initial, 1, initiallength, ostream);
+         fprintf (ostream, "}\n", initial);
+         if (initial == initial1)
+           {
+             lastinitial = lastinitial1;
+             *lastinitial1 = *initial1;
+           }
+         else
+           {
+             lastinitial = initial;
+           }
+         lastinitiallength = initiallength;
+       }
+
+      /* Make the entry for the primary.  */
+      if (nosecondary)
+       fputs ("\\entry {", ostream);
+      else
+       fputs ("\\primary {", ostream);
+      fwrite (primary, primarylength, 1, ostream);
+      if (nosecondary)
+       {
+         fputs ("}{", ostream);
+         pending = 1;
+       }
+      else
+       fputs ("}\n", ostream);
+
+      /* Record name of most recent primary. */
+      if (lastprimarylength < primarylength)
+       {
+         lastprimarylength = primarylength + 100;
+         lastprimary = (char *) xrealloc (lastprimary,
+                                          1 + lastprimarylength);
+       }
+      strncpy (lastprimary, primary, primarylength);
+      lastprimary[primarylength] = 0;
+
+      /* There is no current secondary within this primary, now. */
+      lastsecondary[0] = 0;
+    }
+
+  /* Should not have an entry with no subtopic following one with a subtopic. */
+
+  if (nosecondary && *lastsecondary)
+    error ("entry %s follows an entry with a secondary name", line);
+
+  /* Start a new secondary entry if necessary. */
+  if (!nosecondary && strncmp (secondary, lastsecondary, secondarylength))
+    {
+      if (pending)
+       {
+         fputs ("}\n", ostream);
+         pending = 0;
+       }
+
+      /* Write the entry for the secondary.  */
+      fputs ("\\secondary {", ostream);
+      fwrite (secondary, secondarylength, 1, ostream);
+      fputs ("}{", ostream);
+      pending = 1;
+
+      /* Record name of most recent secondary. */
+      if (lastsecondarylength < secondarylength)
+       {
+         lastsecondarylength = secondarylength + 100;
+         lastsecondary = (char *) xrealloc (lastsecondary,
+                                            1 + lastsecondarylength);
+       }
+      strncpy (lastsecondary, secondary, secondarylength);
+      lastsecondary[secondarylength] = 0;
+    }
+
+  /* Here to add one more page number to the current entry. */
+  if (pending++ != 1)
+    fputs (", ", ostream);     /* Punctuate first, if this is not the first. */
+  fwrite (pagenumber, pagelength, 1, ostream);
+}
+
+/* Close out any unfinished output entry. */
+
+void
+finish_index (ostream)
+     FILE *ostream;
+{
+  if (pending)
+    fputs ("}\n", ostream);
+  free (lastprimary);
+  free (lastsecondary);
+}
+\f
+/* Copy the lines in the sorted order.
+   Each line is copied out of the input file it was found in. */
+
+void
+writelines (linearray, nlines, ostream)
+     char **linearray;
+     int nlines;
+     FILE *ostream;
+{
+  char **stop_line = linearray + nlines;
+  char **next_line;
+
+  init_index ();
+
+  /* Output the text of the lines, and free the buffer space. */
+
+  for (next_line = linearray; next_line != stop_line; next_line++)
+    {
+      /* If -u was specified, output the line only if distinct from previous one.  */
+      if (next_line == linearray
+      /* Compare previous line with this one, using only the
+         explicitly specd keyfields. */
+         || compare_general (*(next_line - 1), *next_line, 0L, 0L, num_keyfields - 1))
+       {
+         char *p = *next_line;
+         char c;
+
+         while ((c = *p++) && c != '\n')
+           /* Do nothing. */ ;
+         *(p - 1) = 0;
+         indexify (*next_line, ostream);
+       }
+    }
+
+  finish_index (ostream);
+}
+\f
+/* Assume (and optionally verify) that each input file is sorted;
+   merge them and output the result.
+   Returns nonzero if any input file fails to be sorted.
+
+   This is the high-level interface that can handle an unlimited
+   number of files.  */
+
+#define MAX_DIRECT_MERGE 10
+
+int
+merge_files (infiles, nfiles, outfile)
+     char **infiles;
+     int nfiles;
+     char *outfile;
+{
+  char **tempfiles;
+  int ntemps;
+  int i;
+  int value = 0;
+  int start_tempcount = tempcount;
+
+  if (nfiles <= MAX_DIRECT_MERGE)
+    return merge_direct (infiles, nfiles, outfile);
+
+  /* Merge groups of MAX_DIRECT_MERGE input files at a time,
+     making a temporary file to hold each group's result.  */
+
+  ntemps = (nfiles + MAX_DIRECT_MERGE - 1) / MAX_DIRECT_MERGE;
+  tempfiles = (char **) xmalloc (ntemps * sizeof (char *));
+  for (i = 0; i < ntemps; i++)
+    {
+      int nf = MAX_DIRECT_MERGE;
+      if (i + 1 == ntemps)
+       nf = nfiles - i * MAX_DIRECT_MERGE;
+      tempfiles[i] = maketempname (++tempcount);
+      value |= merge_direct (&infiles[i * MAX_DIRECT_MERGE], nf, tempfiles[i]);
+    }
+
+  /* All temporary files that existed before are no longer needed
+     since their contents have been merged into our new tempfiles.
+     So delete them.  */
+  flush_tempfiles (start_tempcount);
+
+  /* Now merge the temporary files we created.  */
+
+  merge_files (tempfiles, ntemps, outfile);
+
+  free (tempfiles);
+
+  return value;
+}
+\f
+/* Assume (and optionally verify) that each input file is sorted;
+   merge them and output the result.
+   Returns nonzero if any input file fails to be sorted.
+
+   This version of merging will not work if the number of
+   input files gets too high.  Higher level functions
+   use it only with a bounded number of input files.  */
+
+int
+merge_direct (infiles, nfiles, outfile)
+     char **infiles;
+     int nfiles;
+     char *outfile;
+{
+  struct linebuffer *lb1, *lb2;
+  struct linebuffer **thisline, **prevline;
+  FILE **streams;
+  int i;
+  int nleft;
+  int lossage = 0;
+  int *file_lossage;
+  struct linebuffer *prev_out = 0;
+  FILE *ostream = stdout;
+
+  if (outfile)
+    {
+      ostream = fopen (outfile, "w");
+    }
+  if (!ostream)
+    pfatal_with_name (outfile);
+
+  init_index ();
+
+  if (nfiles == 0)
+    {
+      if (outfile)
+       fclose (ostream);
+      return 0;
+    }
+
+  /* For each file, make two line buffers.
+     Also, for each file, there is an element of `thisline'
+     which points at any time to one of the file's two buffers,
+     and an element of `prevline' which points to the other buffer.
+     `thisline' is supposed to point to the next available line from the file,
+     while `prevline' holds the last file line used,
+     which is remembered so that we can verify that the file is properly sorted. */
+
+  /* lb1 and lb2 contain one buffer each per file. */
+  lb1 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer));
+  lb2 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer));
+
+  /* thisline[i] points to the linebuffer holding the next available line in file i,
+     or is zero if there are no lines left in that file.  */
+  thisline = (struct linebuffer **)
+    xmalloc (nfiles * sizeof (struct linebuffer *));
+  /* prevline[i] points to the linebuffer holding the last used line
+     from file i.  This is just for verifying that file i is properly
+     sorted.  */
+  prevline = (struct linebuffer **)
+    xmalloc (nfiles * sizeof (struct linebuffer *));
+  /* streams[i] holds the input stream for file i.  */
+  streams = (FILE **) xmalloc (nfiles * sizeof (FILE *));
+  /* file_lossage[i] is nonzero if we already know file i is not
+     properly sorted.  */
+  file_lossage = (int *) xmalloc (nfiles * sizeof (int));
+
+  /* Allocate and initialize all that storage. */
+
+  for (i = 0; i < nfiles; i++)
+    {
+      initbuffer (&lb1[i]);
+      initbuffer (&lb2[i]);
+      thisline[i] = &lb1[i];
+      prevline[i] = &lb2[i];
+      file_lossage[i] = 0;
+      streams[i] = fopen (infiles[i], "r");
+      if (!streams[i])
+       pfatal_with_name (infiles[i]);
+
+      readline (thisline[i], streams[i]);
+    }
+
+  /* Keep count of number of files not at eof. */
+  nleft = nfiles;
+
+  while (nleft)
+    {
+      struct linebuffer *best = 0;
+      struct linebuffer *exch;
+      int bestfile = -1;
+      int i;
+
+      /* Look at the next avail line of each file; choose the least one.  */
+
+      for (i = 0; i < nfiles; i++)
+       {
+         if (thisline[i] &&
+             (!best ||
+              0 < compare_general (best->buffer, thisline[i]->buffer,
+                                (long) bestfile, (long) i, num_keyfields)))
+           {
+             best = thisline[i];
+             bestfile = i;
+           }
+       }
+
+      /* Output that line, unless it matches the previous one and we
+        don't want duplicates. */
+
+      if (!(prev_out &&
+           !compare_general (prev_out->buffer,
+                             best->buffer, 0L, 1L, num_keyfields - 1)))
+       indexify (best->buffer, ostream);
+      prev_out = best;
+
+      /* Now make the line the previous of its file, and fetch a new
+        line from that file.  */
+
+      exch = prevline[bestfile];
+      prevline[bestfile] = thisline[bestfile];
+      thisline[bestfile] = exch;
+
+      while (1)
+       {
+         /* If the file has no more, mark it empty. */
+
+         if (feof (streams[bestfile]))
+           {
+             thisline[bestfile] = 0;
+             /* Update the number of files still not empty. */
+             nleft--;
+             break;
+           }
+         readline (thisline[bestfile], streams[bestfile]);
+         if (thisline[bestfile]->buffer[0] || !feof (streams[bestfile]))
+           break;
+       }
+    }
+
+  finish_index (ostream);
+
+  /* Free all storage and close all input streams. */
+
+  for (i = 0; i < nfiles; i++)
+    {
+      fclose (streams[i]);
+      free (lb1[i].buffer);
+      free (lb2[i].buffer);
+    }
+  free (file_lossage);
+  free (lb1);
+  free (lb2);
+  free (thisline);
+  free (prevline);
+  free (streams);
+
+  if (outfile)
+    fclose (ostream);
+
+  return lossage;
+}
+\f
+/* Print error message and exit.  */
+
+void
+fatal (s1, s2)
+     char *s1, *s2;
+{
+  error (s1, s2);
+  exit (TI_FATAL_ERROR);
+}
+
+/* Print error message.  S1 is printf control string, S2 is arg for it. */
+
+void
+error (s1, s2)
+     char *s1, *s2;
+{
+  printf ("%s: ", program_name);
+  printf (s1, s2);
+  printf ("\n");
+}
+
+#if !defined (HAVE_STRERROR)
+static char *
+strerror (n)
+     int n;
+{
+  static char ebuf[40];
+
+  if (n < sys_nerr)
+    return sys_errlist[n];
+  else
+    {
+      sprintf (ebuf, "Unknown error %d", n);
+      return ebuf;
+    }
+}
+#endif
+
+void
+perror_with_name (name)
+     char *name;
+{
+  char *s;
+
+  s = concat ("", strerror (errno), " for %s");
+  error (s, name);
+}
+
+void
+pfatal_with_name (name)
+     char *name;
+{
+  char *s;
+
+  s = concat ("", strerror (errno), " for %s");
+  fatal (s, name);
+}
+
+/* Return a newly-allocated string whose contents concatenate those of
+   S1, S2, S3.  */
+
+char *
+concat (s1, s2, s3)
+     char *s1, *s2, *s3;
+{
+  int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+  char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+  strcpy (result, s1);
+  strcpy (result + len1, s2);
+  strcpy (result + len1 + len2, s3);
+  *(result + len1 + len2 + len3) = 0;
+
+  return result;
+}
+
+/* Just like malloc, but kills the program in case of fatal error. */
+void *
+xmalloc (nbytes)
+     int nbytes;
+{
+  void *temp = (void *) malloc (nbytes);
+
+  if (nbytes && temp == (void *)NULL)
+    memory_error ("xmalloc", nbytes);
+
+  return (temp);
+}
+
+/* Like realloc (), but barfs if there isn't enough memory. */
+void *
+xrealloc (pointer, nbytes)
+     void *pointer;
+     int nbytes;
+{
+  void *temp;
+
+  if (!pointer)
+    temp = (void *)xmalloc (nbytes);
+  else
+    temp = (void *)realloc (pointer, nbytes);
+
+  if (nbytes && !temp)
+    memory_error ("xrealloc", nbytes);
+
+  return (temp);
+}
+
+memory_error (callers_name, bytes_wanted)
+     char *callers_name;
+     int bytes_wanted;
+{
+  char printable_string[80];
+
+  sprintf (printable_string,
+          "Virtual memory exhausted in %s ()!  Needed %d bytes.",
+          callers_name, bytes_wanted);
+
+  error (printable_string, "");
+  abort ();
+}
diff --git a/lib/glob/ChangeLog b/lib/glob/ChangeLog
new file mode 100644 (file)
index 0000000..377f0c1
--- /dev/null
@@ -0,0 +1,13 @@
+Thu Oct 29 08:58:12 1992  Brian Fox  (bfox@cubit)
+
+       * glob.c (glob_filename): Fix tiny memory leak.  Rework some
+       comments.
+
+Mon Jul 20 10:57:36 1992  Brian Fox  (bfox@cubit)
+
+       * glob.c: (glob_filename) Change use of rindex () to strrchr ().
+
+Thu Jul  9 10:02:47 1992  Brian Fox  (bfox@cubit)
+
+       * fnmatch.c: (fnmatch) Only process `[' as the start of a bracket
+       expression if there is a closing `]' present in the string.
diff --git a/lib/glob/Makefile b/lib/glob/Makefile
new file mode 100644 (file)
index 0000000..5811ba2
--- /dev/null
@@ -0,0 +1,95 @@
+## -*- text -*- ####################################################
+#                                                                 #
+# Makefile for the GNU Glob Library.                              #
+#                                                                 #
+####################################################################
+
+# This Makefile is hand made from a template file, found in
+# ../template.  Each library must provide several Makefile
+# targets: `all', `clean', `documentation', `install', and
+# `what-tar'.  The `what-tar' target reports the names of the
+# files that need to be included in a tarfile to build the full
+# code and documentation for this library.
+
+# Please note that the values for INCLUDES, CC, AR, RM, CP,
+# RANLIB, and selfdir are passed in from ../Makefile, and do
+# not need to be defined here.
+srcdir = .
+VPATH = .:$(srcdir)
+
+# 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.
+.c.o:
+       $(CC) -c $(CFLAGS) $(INCLUDES) $(LOCAL_DEFINES) $(CPPFLAGS) $<
+
+# LOCAL_DEFINES are flags that are specific to this library.
+# Define -DUSG if you are using a System V operating system.
+LOCAL_DEFINES = $(LOCAL_INCLUDES) #-DUSG
+
+# For libraries which include headers from other libraries.
+LOCAL_INCLUDES = -I..
+
+# The name of the library target.
+LIBRARY_NAME = libglob.a
+
+# The C code source files for this library.
+CSOURCES = $(srcdir)glob.c $(srcdir)fnmatch.c
+
+# The header files for this library.
+HSOURCES = $(srcdir)fnmatch.h
+
+OBJECTS = glob.o fnmatch.o
+
+# The texinfo files which document this library.
+DOCSOURCE = doc/glob.texi
+DOCOBJECT = doc/glob.dvi
+DOCSUPPORT = doc/Makefile
+DOCUMENTATION = $(DOCSOURCE) $(DOCOBJECT) $(DOCSUPPORT)
+
+SUPPORT = Makefile ChangeLog $(DOCSUPPORT)
+
+SOURCES  = $(CSOURCES) $(HSOURCES) $(DOCSOURCE)
+
+THINGS_TO_TAR = $(SOURCES) $(SUPPORT)
+
+######################################################################
+
+all: $(LIBRARY_NAME)
+
+$(LIBRARY_NAME): $(OBJECTS)
+       $(RM) -f $@
+       $(AR) cq $@ $(OBJECTS)
+       -[ -n "$(RANLIB)" ] && $(RANLIB) $@
+
+what-tar:
+       @for file in $(THINGS_TO_TAR); do \
+         echo $(selfdir)$$file; \
+       done
+
+documentation: force
+       -(cd doc && $(MAKE) $(MFLAGS))
+
+force:
+
+# The rule for 'includes' is written funny so that the if statement
+# always returns TRUE unless there really was an error installing the
+# include files.
+install:
+       -$(MV) $(bindir)/$(LIBRARY_NAME) $(bindir)/$(LIBRARY_NAME)-old
+       $(CP) $(LIBRARY_NAME) $(bindir)/$(LIBRARY_NAME)
+       -[ -n "$(RANLIB)" ] && $(RANLIB) -t $(bindir)/$(LIBRARY_NAME)
+
+clean:
+       rm -f $(OBJECTS) $(LIBRARY_NAME)
+       -(cd doc && $(MAKE) $(MFLAGS) $@)
+
+maintainer-clean realclean mostlyclean distclean: clean
+       -(cd doc && $(MAKE) $(MFLAGS) $@)
+
+######################################################################
+#                                                                   #
+#  Dependencies for the object files which make up this library.     #
+#                                                                   #
+######################################################################
+
+fnmatch.o: fnmatch.c fnmatch.h
diff --git a/lib/glob/doc/Makefile b/lib/glob/doc/Makefile
new file mode 100644 (file)
index 0000000..1b6084c
--- /dev/null
@@ -0,0 +1,5 @@
+all:
+       cp glob.texi glob.info
+
+maintainer-clean realclean distclean clean:
+       rm -f glob.?? glob.info
diff --git a/lib/glob/doc/glob.texi b/lib/glob/doc/glob.texi
new file mode 100644 (file)
index 0000000..0262ef1
--- /dev/null
@@ -0,0 +1 @@
+Nothing happens here.
diff --git a/lib/glob/fnmatch.c b/lib/glob/fnmatch.c
new file mode 100644 (file)
index 0000000..6a8b574
--- /dev/null
@@ -0,0 +1,189 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+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., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <errno.h>
+#include "fnmatch.h"
+
+#if !defined (__GNU_LIBRARY__) && !defined (STDC_HEADERS)
+#  if !defined (errno)
+extern int errno;
+#  endif /* !errno */
+#endif
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+   it matches, FNM_NOMATCH if not.  */
+int
+fnmatch (pattern, string, flags)
+     char *pattern;
+     char *string;
+     int flags;
+{
+  register char *p = pattern, *n = string;
+  register char c;
+
+  if ((flags & ~__FNM_FLAGS) != 0)
+    {
+      errno = EINVAL;
+      return (-1);
+    }
+
+  while ((c = *p++) != '\0')
+    {
+      switch (c)
+       {
+       case '?':
+         if (*n == '\0')
+           return (FNM_NOMATCH);
+         else if ((flags & FNM_PATHNAME) && *n == '/')
+           return (FNM_NOMATCH);
+         else if ((flags & FNM_PERIOD) && *n == '.' &&
+                  (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
+           return (FNM_NOMATCH);
+         break;
+
+       case '\\':
+         if (!(flags & FNM_NOESCAPE))
+           c = *p++;
+         if (*n != c)
+           return (FNM_NOMATCH);
+         break;
+
+       case '*':
+         if ((flags & FNM_PERIOD) && *n == '.' &&
+             (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
+           return (FNM_NOMATCH);
+
+         for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
+           if (((flags & FNM_PATHNAME) && *n == '/') ||
+               (c == '?' && *n == '\0'))
+             return (FNM_NOMATCH);
+
+         if (c == '\0')
+           return (0);
+
+         {
+           char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
+           for (--p; *n != '\0'; ++n)
+             if ((c == '[' || *n == c1) &&
+                 fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
+               return (0);
+           return (FNM_NOMATCH);
+         }
+
+       case '[':
+         {
+           /* Nonzero if the sense of the character class is inverted.  */
+           register int not;
+
+           if (*n == '\0')
+             return (FNM_NOMATCH);
+
+           if ((flags & FNM_PERIOD) && *n == '.' &&
+               (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
+             return (FNM_NOMATCH);
+
+           /* Make sure there is a closing `]'.  If there isn't, the `['
+              is just a character to be matched. */
+           {
+             register char *np;
+
+             for (np = p; np && *np && *np != ']'; np++);
+
+             if (np && !*np)
+               {
+                 if (*n != '[')
+                   return (FNM_NOMATCH);
+                 goto next_char;
+               }
+           }
+             
+           not = (*p == '!' || *p == '^');
+           if (not)
+             ++p;
+
+           c = *p++;
+           for (;;)
+             {
+               register char cstart = c, cend = c;
+
+               if (!(flags & FNM_NOESCAPE) && c == '\\')
+                 cstart = cend = *p++;
+
+               if (c == '\0')
+                 /* [ (unterminated) loses.  */
+                 return (FNM_NOMATCH);
+
+               c = *p++;
+
+               if ((flags & FNM_PATHNAME) && c == '/')
+                 /* [/] can never match.  */
+                 return (FNM_NOMATCH);
+
+               if (c == '-' && *p != ']')
+                 {
+                   cend = *p++;
+                   if (!(flags & FNM_NOESCAPE) && cend == '\\')
+                     cend = *p++;
+                   if (cend == '\0')
+                     return (FNM_NOMATCH);
+                   c = *p++;
+                 }
+
+               if (*n >= cstart && *n <= cend)
+                 goto matched;
+
+               if (c == ']')
+                 break;
+             }
+           if (!not)
+             return (FNM_NOMATCH);
+
+         next_char:
+           break;
+
+         matched:
+           /* Skip the rest of the [...] that already matched.  */
+           while (c != ']')
+             {
+               if (c == '\0')
+                 /* [... (unterminated) loses.  */
+                 return (FNM_NOMATCH);
+
+               c = *p++;
+               if (!(flags & FNM_NOESCAPE) && c == '\\')
+                 /* 1003.2d11 is unclear if this is right.  %%% */
+                 ++p;
+             }
+           if (not)
+             return (FNM_NOMATCH);
+         }
+         break;
+
+       default:
+         if (c != *n)
+           return (FNM_NOMATCH);
+       }
+
+      ++n;
+    }
+
+  if (*n == '\0')
+    return (0);
+
+  return (FNM_NOMATCH);
+}
diff --git a/lib/glob/fnmatch.h b/lib/glob/fnmatch.h
new file mode 100644 (file)
index 0000000..62c8c8f
--- /dev/null
@@ -0,0 +1,36 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+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., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef        _FNMATCH_H
+
+#define        _FNMATCH_H      1
+
+/* Bits set in the FLAGS argument to `fnmatch'.  */
+#define        FNM_PATHNAME    (1 << 0)/* No wildcard can ever match `/'.  */
+#define        FNM_NOESCAPE    (1 << 1)/* Backslashes don't quote special chars.  */
+#define        FNM_PERIOD      (1 << 2)/* Leading `.' is matched only explicitly.  */
+#define        __FNM_FLAGS     (FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD)
+
+/* Value returned by `fnmatch' if STRING does not match PATTERN.  */
+#define        FNM_NOMATCH     1
+
+/* Match STRING against the filename pattern PATTERN,
+   returning zero if it matches, FNM_NOMATCH if not.  */
+extern int fnmatch();
+
+#endif /* fnmatch.h */
diff --git a/lib/glob/glob.c b/lib/glob/glob.c
new file mode 100644 (file)
index 0000000..6ff2cb4
--- /dev/null
@@ -0,0 +1,574 @@
+/* File-name wildcard pattern matching for GNU.
+   Copyright (C) 1985, 1988, 1989 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+\f
+/* To whomever it may concern: I have never seen the code which most
+   Unix programs use to perform this function.  I wrote this from scratch
+   based on specifications for the pattern matching.  --RMS.  */
+
+#if defined (SHELL)
+#  if defined (HAVE_STDLIB_H)
+#    include <stdlib.h>
+#  else
+#    include "ansi_stdlib.h"
+#  endif /* HAVE_STDLIB_H */
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if !defined (SHELL) && (defined (_POSIX_VERSION) || defined (USGr3))
+#  if !defined (HAVE_DIRENT_H)
+#    define HAVE_DIRENT_H
+#  endif /* !HAVE_DIRENT_H */
+#endif /* !SHELL && (_POSIX_VERSION || USGr3) */
+
+#if defined (HAVE_DIRENT_H)
+#  include <dirent.h>
+#  if !defined (direct)
+#    define direct dirent
+#  endif /* !direct */
+#  define D_NAMLEN(d) strlen ((d)->d_name)
+#else /* !HAVE_DIRENT_H */
+#  define D_NAMLEN(d) ((d)->d_namlen)
+#  if defined (USG)
+#    if defined (Xenix)
+#      include <sys/ndir.h>
+#    else /* !Xenix (but USG...) */
+#      include "ndir.h"
+#    endif /* !Xenix */
+#  else /* !USG */
+#    include <sys/dir.h>
+#  endif /* !USG */
+#endif /* !HAVE_DIRENT_H */
+
+#if defined (_POSIX_SOURCE)
+/* 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 (USG) || defined (NeXT)
+#  if !defined (HAVE_STRING_H)
+#    define HAVE_STRING_H
+#  endif /* !HAVE_STRING_H */
+#endif /* USG || NeXT */
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#if defined (USG)
+#  if !defined (isc386)
+#    include <memory.h>
+#  endif /* !isc386 */
+#  if defined (RISC6000)
+extern void bcopy ();
+#  else /* !RISC6000 */
+#    define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
+#  endif /* !RISC6000 */
+#endif /* USG */
+
+#include "fnmatch.h"
+
+/* If the opendir () on your system lets you open non-directory files,
+   then we consider that not robust.  Define OPENDIR_NOT_ROBUST in the
+   SYSDEP_CFLAGS for your machines entry in machines.h. */
+#if defined (OPENDIR_NOT_ROBUST)
+#  if defined (SHELL)
+#    include "posixstat.h"
+#  else /* !SHELL */
+#    include <sys/stat.h>
+#  endif /* !SHELL */
+#endif /* OPENDIR_NOT_ROBUST */
+
+#if !defined (HAVE_STDLIB_H)
+extern char *malloc (), *realloc ();
+extern void free ();
+#endif /* !HAVE_STDLIB_H */
+
+#if !defined (NULL)
+#  if defined (__STDC__)
+#    define NULL ((void *) 0)
+#  else
+#    define NULL 0x0
+#  endif /* __STDC__ */
+#endif /* !NULL */
+
+#if defined (SHELL)
+extern int interrupt_state;
+#endif /* SHELL */
+
+/* Global variable which controls whether or not * matches .*.
+   Non-zero means don't match .*.  */
+int noglob_dot_filenames = 1;
+
+/* Global variable to return to signify an error in globbing. */
+char *glob_error_return;
+
+\f
+/* Return nonzero if PATTERN has any special globbing chars in it.  */
+int
+glob_pattern_p (pattern)
+     char *pattern;
+{
+  register char *p = pattern;
+  register char c;
+  int open = 0;
+
+  while ((c = *p++) != '\0')
+    switch (c)
+      {
+      case '?':
+      case '*':
+       return (1);
+
+      case '[':                /* Only accept an open brace if there is a close */
+       open++;         /* brace to match it.  Bracket expressions must be */
+       continue;       /* complete, according to Posix.2 */
+      case ']':
+       if (open)
+         return (1);
+       continue;      
+
+      case '\\':
+       if (*p++ == '\0')
+         return (0);
+      }
+
+  return (0);
+}
+
+/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
+static void
+dequote_pathname (pathname)
+     char *pathname;
+{
+  register int i, j;
+
+  for (i = j = 0; pathname && pathname[i]; )
+    {
+      if (pathname[i] == '\\')
+       i++;
+
+      pathname[j++] = pathname[i++];
+
+      if (!pathname[i - 1])
+       break;
+    }
+  pathname[j] = '\0';
+}
+
+\f
+/* Return a vector of names of files in directory DIR
+   whose names match glob pattern PAT.
+   The names are not in any particular order.
+   Wildcards at the beginning of PAT do not match an initial period.
+
+   The vector is terminated by an element that is a null pointer.
+
+   To free the space allocated, first free the vector's elements,
+   then free the vector.
+
+   Return 0 if cannot get enough memory to hold the pointer
+   and the names.
+
+   Return -1 if cannot access directory DIR.
+   Look in errno for more information.  */
+
+char **
+glob_vector (pat, dir)
+     char *pat;
+     char *dir;
+{
+  struct globval
+    {
+      struct globval *next;
+      char *name;
+    };
+
+  DIR *d;
+  register struct direct *dp;
+  struct globval *lastlink;
+  register struct globval *nextlink;
+  register char *nextname;
+  unsigned int count;
+  int lose, skip;
+  register char **name_vector;
+  register unsigned int i;
+#if defined (OPENDIR_NOT_ROBUST)
+  struct stat finfo;
+
+  if (stat (dir, &finfo) < 0)
+    return ((char **) &glob_error_return);
+
+  if (!S_ISDIR (finfo.st_mode))
+    return ((char **) &glob_error_return);
+#endif /* OPENDIR_NOT_ROBUST */
+
+  d = opendir (dir);
+  if (d == NULL)
+    return ((char **) &glob_error_return);
+
+  lastlink = 0;
+  count = 0;
+  lose = 0;
+  skip = 0;
+
+  /* If PAT is empty, skip the loop, but return one (empty) filename. */
+  if (!pat || !*pat)
+    {
+      nextlink = (struct globval *)alloca (sizeof (struct globval));
+      nextlink->next = lastlink;
+      nextname = (char *) malloc (1);
+      if (!nextname)
+       lose = 1;
+      else
+       {
+         lastlink = nextlink;
+         nextlink->name = nextname;
+         nextname[0] = '\0';
+         count++;
+       }
+      skip = 1;
+    }
+
+  /* Scan the directory, finding all names that match.
+     For each name that matches, allocate a struct globval
+     on the stack and store the name in it.
+     Chain those structs together; lastlink is the front of the chain.  */
+  while (!skip)
+    {
+      int flags;               /* Flags passed to fnmatch (). */
+#if defined (SHELL)
+      /* Make globbing interruptible in the bash shell. */
+      if (interrupt_state)
+       {
+         closedir (d);
+         lose = 1;
+         goto lost;
+       }
+#endif /* SHELL */
+         
+      dp = readdir (d);
+      if (dp == NULL)
+       break;
+
+      /* If this directory entry is not to be used, try again. */
+      if (!REAL_DIR_ENTRY (dp))
+       continue;
+
+      /* If a dot must be explicity matched, check to see if they do. */
+      if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.')
+       continue;
+
+      flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
+
+      if (fnmatch (pat, dp->d_name, flags) != FNM_NOMATCH)
+       {
+         nextlink = (struct globval *) alloca (sizeof (struct globval));
+         nextlink->next = lastlink;
+         nextname = (char *) malloc (D_NAMLEN (dp) + 1);
+         if (nextname == NULL)
+           {
+             lose = 1;
+             break;
+           }
+         lastlink = nextlink;
+         nextlink->name = nextname;
+         bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);
+         ++count;
+       }
+    }
+  (void) closedir (d);
+
+  if (!lose)
+    {
+      name_vector = (char **) malloc ((count + 1) * sizeof (char *));
+      lose |= name_vector == NULL;
+    }
+
+  /* Have we run out of memory?         */
+ lost:
+  if (lose)
+    {
+      /* Here free the strings we have got.  */
+      while (lastlink)
+       {
+         free (lastlink->name);
+         lastlink = lastlink->next;
+       }
+#if defined (SHELL)
+      if (interrupt_state)
+       throw_to_top_level ();
+#endif /* SHELL */
+      return (NULL);
+    }
+
+  /* Copy the name pointers from the linked list into the vector.  */
+  for (i = 0; i < count; ++i)
+    {
+      name_vector[i] = lastlink->name;
+      lastlink = lastlink->next;
+    }
+
+  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. */
+static char **
+glob_dir_to_array (dir, array)
+     char *dir, **array;
+{
+  register unsigned int i, l;
+  int add_slash;
+  char **result;
+
+  l = strlen (dir);
+  if (l == 0)
+    return (array);
+
+  add_slash = dir[l - 1] != '/';
+
+  i = 0;
+  while (array[i] != NULL)
+    ++i;
+
+  result = (char **) malloc ((i + 1) * sizeof (char *));
+  if (result == NULL)
+    return (NULL);
+
+  for (i = 0; array[i] != NULL; i++)
+    {
+      result[i] = (char *) malloc (l + (add_slash ? 1 : 0)
+                                  + strlen (array[i]) + 1);
+      if (result[i] == NULL)
+       return (NULL);
+      sprintf (result[i], "%s%s%s", dir, add_slash ? "/" : "", array[i]);
+    }
+  result[i] = NULL;
+
+  /* Free the input array.  */
+  for (i = 0; array[i] != NULL; i++)
+    free (array[i]);
+  free ((char *) 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)
+     char *pathname;
+{
+  char **result;
+  unsigned int result_size;
+  char *directory_name, *filename;
+  unsigned int directory_len;
+
+  result = (char **) malloc (sizeof (char *));
+  result_size = 1;
+  if (result == NULL)
+    return (NULL);
+
+  result[0] = NULL;
+
+  /* Find the filename.  */
+  filename = strrchr (pathname, '/');
+  if (filename == NULL)
+    {
+      filename = pathname;
+      directory_name = "";
+      directory_len = 0;
+    }
+  else
+    {
+      directory_len = (filename - pathname) + 1;
+      directory_name = (char *) alloca (directory_len + 1);
+
+      bcopy (pathname, directory_name, directory_len);
+      directory_name[directory_len] = '\0';
+      ++filename;
+    }
+
+  /* If directory_name contains globbing characters, then we
+     have to expand the previous levels.  Just recurse. */
+  if (glob_pattern_p (directory_name))
+    {
+      char **directories;
+      register unsigned int i;
+
+      if (directory_name[directory_len - 1] == '/')
+       directory_name[directory_len - 1] = '\0';
+
+      directories = glob_filename (directory_name);
+
+      if (directories == NULL)
+       goto memory_error;
+      else if (directories == (char **)&glob_error_return)
+       {
+         free ((char *)result);
+         return ((char **) &glob_error_return);
+       }
+      else if (*directories == NULL)
+       {
+         free ((char *) directories);
+         free ((char *) result);
+         return ((char **) &glob_error_return);
+       }
+
+      /* We have successfully globbed the preceding directory name.
+        For each name in DIRECTORIES, call glob_vector on it and
+        FILENAME.  Concatenate the results together.  */
+      for (i = 0; directories[i] != NULL; ++i)
+       {
+         char **temp_results;
+
+         /* 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]);
+
+         /* Handle error cases. */
+         if (temp_results == NULL)
+           goto memory_error;
+         else if (temp_results == (char **)&glob_error_return)
+           /* This filename is probably not a directory.  Ignore it.  */
+           ;
+         else
+           {
+             char **array;
+             register unsigned int l;
+
+             array = glob_dir_to_array (directories[i], temp_results);
+             l = 0;
+             while (array[l] != NULL)
+               ++l;
+
+             result =
+               (char **)realloc (result, (result_size + l) * sizeof (char *));
+
+             if (result == NULL)
+               goto memory_error;
+
+             for (l = 0; array[l] != NULL; ++l)
+               result[result_size++ - 1] = array[l];
+
+             result[result_size - 1] = NULL;
+
+             /* Note that the elements of ARRAY are not freed.  */
+             free ((char *) array);
+           }
+       }
+      /* Free the directories.  */
+      for (i = 0; directories[i]; i++)
+       free (directories[i]);
+
+      free ((char *) directories);
+
+      return (result);
+    }
+
+  /* If there is only a directory name, return it. */
+  if (*filename == '\0')
+    {
+      result = (char **) realloc ((char *) result, 2 * sizeof (char *));
+      if (result == NULL)
+       return (NULL);
+      result[0] = (char *) malloc (directory_len + 1);
+      if (result[0] == NULL)
+       goto memory_error;
+      bcopy (directory_name, result[0], directory_len + 1);
+      result[1] = NULL;
+      return (result);
+    }
+  else
+    {
+      char **temp_results;
+
+      /* There are no unquoted globbing characters in DIRECTORY_NAME.
+        Dequote it before we try to open the directory since there may
+        be quoted globbing characters which should be treated verbatim. */
+      if (directory_len > 0)
+       dequote_pathname (directory_name);
+
+      /* We allocated a small array called RESULT, which we won't be using.
+        Free that memory now. */
+      free (result);
+
+      /* Just return what glob_vector () returns appended to the
+        directory name. */
+      temp_results =
+       glob_vector (filename, (directory_len == 0 ? "." : directory_name));
+
+      if (temp_results == NULL || temp_results == (char **)&glob_error_return)
+       return (temp_results);
+
+      return (glob_dir_to_array (directory_name, temp_results));
+    }
+
+  /* We get to memory_error if the program has run out of memory, or
+     if this is the shell, and we have been interrupted. */
+ memory_error:
+  if (result != NULL)
+    {
+      register unsigned int i;
+      for (i = 0; result[i] != NULL; ++i)
+       free (result[i]);
+      free ((char *) result);
+    }
+#if defined (SHELL)
+  if (interrupt_state)
+    throw_to_top_level ();
+#endif /* SHELL */
+  return (NULL);
+}
+\f
+#if defined (TEST)
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  unsigned int i;
+
+  for (i = 1; i < argc; ++i)
+    {
+      char **value = glob_filename (argv[i]);
+      if (value == NULL)
+       puts ("Out of memory.");
+      else if (value == &glob_error_return)
+       perror (argv[i]);
+      else
+       for (i = 0; value[i] != NULL; i++)
+         puts (value[i]);
+    }
+
+  exit (0);
+}
+#endif /* TEST.  */
diff --git a/lib/glob/ndir.h b/lib/glob/ndir.h
new file mode 100644 (file)
index 0000000..31261eb
--- /dev/null
@@ -0,0 +1,50 @@
+/* <dir.h> -- definitions for 4.2BSD-compatible directory access.
+   last edit:  09-Jul-1983     D A Gwyn. */
+
+#if defined (VMS)
+#  if !defined (FAB$C_BID)
+#    include <fab.h>
+#  endif
+#  if !defined (NAM$C_BID)
+#    include <nam.h>
+#  endif
+#  if !defined (RMS$_SUC)
+#    include <rmsdef.h>
+#  endif
+#  include "dir.h"
+#endif /* VMS */
+
+/* Size of directory block. */
+#define DIRBLKSIZ 512
+
+/* NOTE:  MAXNAMLEN must be one less than a multiple of 4 */
+
+#if defined (VMS)
+#  define MAXNAMLEN (DIR$S_NAME + 7)   /* 80 plus room for version #.  */
+#  define MAXFULLSPEC NAM$C_MAXRSS     /* Maximum full spec */
+#else
+#  define MAXNAMLEN 15                 /* Maximum filename length. */
+#endif /* VMS */
+
+/* Data from readdir (). */
+struct direct {
+  long d_ino;                  /* Inode number of entry. */
+  unsigned short d_reclen;     /* Length of this record. */
+  unsigned short d_namlen;     /* Length of string in d_name. */
+  char d_name[MAXNAMLEN + 1];  /* Name of file. */
+};
+
+/* Stream data from opendir (). */
+typedef struct {
+  int dd_fd;                   /* File descriptor. */
+  int dd_loc;                  /* Offset in block. */
+  int dd_size;                 /* Amount of valid data. */
+  char dd_buf[DIRBLKSIZ];      /* Directory block. */
+} DIR;
+
+extern DIR *opendir ();
+extern struct direct *readdir ();
+extern long telldir ();
+extern void seekdir (), closedir ();
+
+#define rewinddir(dirp) seekdir (dirp, 0L)
diff --git a/lib/malloc/Makefile b/lib/malloc/Makefile
new file mode 100644 (file)
index 0000000..4c0ab72
--- /dev/null
@@ -0,0 +1,28 @@
+# Skeleton Makefile for the GNU malloc code
+#
+# Maybe this should really create a library instead of just compiling
+# source files
+
+srcdir = .
+VPATH = .:$(srcdir)
+
+.c.o:
+       $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+
+.s.o:
+       $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+
+MALLOC_SOURCE = malloc.c
+
+ALLOCA_SOURCE = alloca.c
+ALLOCA_OBJECT = alloca.o
+
+malloc.o: malloc.c getpagesize.h
+
+$(ALLOCA_OBJECT): $(ALLOCA_SOURCE)
+
+alloca.o:      $(ALLOCA_SOURCE)
+       $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+       @- if [ "$(ALLOCA_OBJECT)" != alloca.o ]; then \
+               mv $(ALLOCA_OBJECT) alloca.o >/dev/null 2>&1 ; \
+       fi
diff --git a/lib/malloc/alloca.c b/lib/malloc/alloca.c
new file mode 100644 (file)
index 0000000..567ea1b
--- /dev/null
@@ -0,0 +1,480 @@
+/* alloca.c -- allocate automatically reclaimed memory
+   (Mostly) portable public-domain implementation -- D A Gwyn
+
+   This implementation of the PWB library alloca function,
+   which is used to allocate space off the run-time stack so
+   that it is automatically reclaimed upon procedure exit,
+   was inspired by discussions with J. Q. Johnson of Cornell.
+   J.Otto Tennant <jot@cray.com> contributed the Cray support.
+
+   There are some preprocessor constants that can
+   be defined when compiling for your specific system, for
+   improved efficiency; however, the defaults should be okay.
+
+   The general concept of this implementation is to keep
+   track of all alloca-allocated blocks, and reclaim any
+   that are found to be deeper in the stack than the current
+   invocation.  This heuristic does not reclaim storage as
+   soon as it becomes invalid, but it will do so eventually.
+
+   As a special case, alloca(0) reclaims storage without
+   allocating any.  It is a good idea to use alloca(0) in
+   your main control loop, etc. to force garbage collection.  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* If compiling with GCC 2, this file's not needed.  */
+#if !defined (__GNUC__) || __GNUC__ < 2
+
+/* If alloca is defined somewhere, this file is not needed. */
+#ifndef alloca
+
+#ifdef emacs
+#ifdef static
+/* actually, only want this if static is defined as ""
+   -- this is for usg, in which emacs must undefine static
+   in order to make unexec workable
+   */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+/* If your stack is a linked list of frames, you have to
+   provide an "address metric" ADDRESS_FUNCTION macro.  */
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+long i00afunc ();
+#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
+#else
+#define ADDRESS_FUNCTION(arg) &(arg)
+#endif /* CRAY && CRAY_STACKSEG_END */
+
+#if __STDC__
+typedef void *pointer;
+#else
+typedef char *pointer;
+#endif
+
+#define        NULL    0
+
+/* Different portions of Emacs need to call different versions of
+   malloc.  The Emacs executable needs alloca to call xmalloc, because
+   ordinary malloc isn't protected from input signals.  On the other
+   hand, the utilities in lib-src need alloca to call malloc; some of
+   them are very simple, and don't have an xmalloc routine.
+
+   Non-Emacs programs expect this to call use xmalloc.
+
+   Callers below should use malloc.  */
+
+#ifndef emacs
+#define malloc xmalloc
+extern pointer xmalloc ();
+#endif
+
+/* Define STACK_DIRECTION if you know the direction of stack
+   growth for your system; otherwise it will be automatically
+   deduced at run-time.
+
+   STACK_DIRECTION > 0 => grows toward higher addresses
+   STACK_DIRECTION < 0 => grows toward lower addresses
+   STACK_DIRECTION = 0 => direction of growth unknown  */
+
+#ifndef STACK_DIRECTION
+#define        STACK_DIRECTION 0       /* Direction unknown.  */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define        STACK_DIR       STACK_DIRECTION /* Known at compile-time.  */
+
+#else /* STACK_DIRECTION == 0; need run-time code.  */
+
+static int stack_dir;          /* 1 or -1 once known.  */
+#define        STACK_DIR       stack_dir
+
+static void
+find_stack_direction ()
+{
+  static char *addr = NULL;    /* Address of first `dummy', once known.  */
+  auto char dummy;             /* To get stack address.  */
+
+  if (addr == NULL)
+    {                          /* Initial entry.  */
+      addr = ADDRESS_FUNCTION (dummy);
+
+      find_stack_direction (); /* Recurse once.  */
+    }
+  else
+    {
+      /* Second entry.  */
+      if (ADDRESS_FUNCTION (dummy) > addr)
+       stack_dir = 1;          /* Stack grew upward.  */
+      else
+       stack_dir = -1;         /* Stack grew downward.  */
+    }
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/* An "alloca header" is used to:
+   (a) chain together all alloca'ed blocks;
+   (b) keep track of stack depth.
+
+   It is very important that sizeof(header) agree with malloc
+   alignment chunk size.  The following default should work okay.  */
+
+#ifndef        ALIGN_SIZE
+#define        ALIGN_SIZE      sizeof(double)
+#endif
+
+typedef union hdr
+{
+  char align[ALIGN_SIZE];      /* To force sizeof(header).  */
+  struct
+    {
+      union hdr *next;         /* For chaining headers.  */
+      char *deep;              /* For stack depth measure.  */
+    } h;
+} header;
+
+static header *last_alloca_header = NULL;      /* -> last alloca header.  */
+
+/* Return a pointer to at least SIZE bytes of storage,
+   which will be automatically reclaimed upon exit from
+   the procedure that called alloca.  Originally, this space
+   was supposed to be taken from the current stack frame of the
+   caller, but that method cannot be made to work for some
+   implementations of C, for example under Gould's UTX/32.  */
+
+pointer
+alloca (size)
+     unsigned size;
+{
+  auto char probe;             /* Probes stack depth: */
+  register char *depth = ADDRESS_FUNCTION (probe);
+
+#if STACK_DIRECTION == 0
+  if (STACK_DIR == 0)          /* Unknown growth direction.  */
+    find_stack_direction ();
+#endif
+
+  /* Reclaim garbage, defined as all alloca'd storage that
+     was allocated from deeper in the stack than currently. */
+
+  {
+    register header *hp;       /* Traverses linked list.  */
+
+    for (hp = last_alloca_header; hp != NULL;)
+      if ((STACK_DIR > 0 && hp->h.deep > depth)
+         || (STACK_DIR < 0 && hp->h.deep < depth))
+       {
+         register header *np = hp->h.next;
+
+         free ((pointer) hp);  /* Collect garbage.  */
+
+         hp = np;              /* -> next header.  */
+       }
+      else
+       break;                  /* Rest are not deeper.  */
+
+    last_alloca_header = hp;   /* -> last valid storage.  */
+  }
+
+  if (size == 0)
+    return NULL;               /* No allocation required.  */
+
+  /* Allocate combined header + user data storage.  */
+
+  {
+    register pointer new = malloc (sizeof (header) + size);
+    /* Address of header.  */
+
+    ((header *) new)->h.next = last_alloca_header;
+    ((header *) new)->h.deep = depth;
+
+    last_alloca_header = (header *) new;
+
+    /* User storage begins just after header.  */
+
+    return (pointer) ((char *) new + sizeof (header));
+  }
+}
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+#ifdef DEBUG_I00AFUNC
+#include <stdio.h>
+#endif
+
+#ifndef CRAY_STACK
+#define CRAY_STACK
+#ifndef CRAY2
+/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
+struct stack_control_header
+  {
+    long shgrow:32;            /* Number of times stack has grown.  */
+    long shaseg:32;            /* Size of increments to stack.  */
+    long shhwm:32;             /* High water mark of stack.  */
+    long shsize:32;            /* Current size of stack (all segments).  */
+  };
+
+/* The stack segment linkage control information occurs at
+   the high-address end of a stack segment.  (The stack
+   grows from low addresses to high addresses.)  The initial
+   part of the stack segment linkage control information is
+   0200 (octal) words.  This provides for register storage
+   for the routine which overflows the stack.  */
+
+struct stack_segment_linkage
+  {
+    long ss[0200];             /* 0200 overflow words.  */
+    long sssize:32;            /* Number of words in this segment.  */
+    long ssbase:32;            /* Offset to stack base.  */
+    long:32;
+    long sspseg:32;            /* Offset to linkage control of previous
+                                  segment of stack.  */
+    long:32;
+    long sstcpt:32;            /* Pointer to task common address block.  */
+    long sscsnm;               /* Private control structure number for
+                                  microtasking.  */
+    long ssusr1;               /* Reserved for user.  */
+    long ssusr2;               /* Reserved for user.  */
+    long sstpid;               /* Process ID for pid based multi-tasking.  */
+    long ssgvup;               /* Pointer to multitasking thread giveup.  */
+    long sscray[7];            /* Reserved for Cray Research.  */
+    long ssa0;
+    long ssa1;
+    long ssa2;
+    long ssa3;
+    long ssa4;
+    long ssa5;
+    long ssa6;
+    long ssa7;
+    long sss0;
+    long sss1;
+    long sss2;
+    long sss3;
+    long sss4;
+    long sss5;
+    long sss6;
+    long sss7;
+  };
+
+#else /* CRAY2 */
+/* The following structure defines the vector of words
+   returned by the STKSTAT library routine.  */
+struct stk_stat
+  {
+    long now;                  /* Current total stack size.  */
+    long maxc;                 /* Amount of contiguous space which would
+                                  be required to satisfy the maximum
+                                  stack demand to date.  */
+    long high_water;           /* Stack high-water mark.  */
+    long overflows;            /* Number of stack overflow ($STKOFEN) calls.  */
+    long hits;                 /* Number of internal buffer hits.  */
+    long extends;              /* Number of block extensions.  */
+    long stko_mallocs;         /* Block allocations by $STKOFEN.  */
+    long underflows;           /* Number of stack underflow calls ($STKRETN).  */
+    long stko_free;            /* Number of deallocations by $STKRETN.  */
+    long stkm_free;            /* Number of deallocations by $STKMRET.  */
+    long segments;             /* Current number of stack segments.  */
+    long maxs;                 /* Maximum number of stack segments so far.  */
+    long pad_size;             /* Stack pad size.  */
+    long current_address;      /* Current stack segment address.  */
+    long current_size;         /* Current stack segment size.  This
+                                  number is actually corrupted by STKSTAT to
+                                  include the fifteen word trailer area.  */
+    long initial_address;      /* Address of initial segment.  */
+    long initial_size;         /* Size of initial segment.  */
+  };
+
+/* The following structure describes the data structure which trails
+   any stack segment.  I think that the description in 'asdef' is
+   out of date.  I only describe the parts that I am sure about.  */
+
+struct stk_trailer
+  {
+    long this_address;         /* Address of this block.  */
+    long this_size;            /* Size of this block (does not include
+                                  this trailer).  */
+    long unknown2;
+    long unknown3;
+    long link;                 /* Address of trailer block of previous
+                                  segment.  */
+    long unknown5;
+    long unknown6;
+    long unknown7;
+    long unknown8;
+    long unknown9;
+    long unknown10;
+    long unknown11;
+    long unknown12;
+    long unknown13;
+    long unknown14;
+  };
+
+#endif /* CRAY2 */
+#endif /* not CRAY_STACK */
+
+#ifdef CRAY2
+/* Determine a "stack measure" for an arbitrary ADDRESS.
+   I doubt that "lint" will like this much. */
+
+static long
+i00afunc (long *address)
+{
+  struct stk_stat status;
+  struct stk_trailer *trailer;
+  long *block, size;
+  long result = 0;
+
+  /* We want to iterate through all of the segments.  The first
+     step is to get the stack status structure.  We could do this
+     more quickly and more directly, perhaps, by referencing the
+     $LM00 common block, but I know that this works.  */
+
+  STKSTAT (&status);
+
+  /* Set up the iteration.  */
+
+  trailer = (struct stk_trailer *) (status.current_address
+                                   + status.current_size
+                                   - 15);
+
+  /* There must be at least one stack segment.  Therefore it is
+     a fatal error if "trailer" is null.  */
+
+  if (trailer == 0)
+    abort ();
+
+  /* Discard segments that do not contain our argument address.  */
+
+  while (trailer != 0)
+    {
+      block = (long *) trailer->this_address;
+      size = trailer->this_size;
+      if (block == 0 || size == 0)
+       abort ();
+      trailer = (struct stk_trailer *) trailer->link;
+      if ((block <= address) && (address < (block + size)))
+       break;
+    }
+
+  /* Set the result to the offset in this segment and add the sizes
+     of all predecessor segments.  */
+
+  result = address - block;
+
+  if (trailer == 0)
+    {
+      return result;
+    }
+
+  do
+    {
+      if (trailer->this_size <= 0)
+       abort ();
+      result += trailer->this_size;
+      trailer = (struct stk_trailer *) trailer->link;
+    }
+  while (trailer != 0);
+
+  /* We are done.  Note that if you present a bogus address (one
+     not in any segment), you will get a different number back, formed
+     from subtracting the address of the first block.  This is probably
+     not what you want.  */
+
+  return (result);
+}
+
+#else /* not CRAY2 */
+/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
+   Determine the number of the cell within the stack,
+   given the address of the cell.  The purpose of this
+   routine is to linearize, in some sense, stack addresses
+   for alloca.  */
+
+static long
+i00afunc (long address)
+{
+  long stkl = 0;
+
+  long size, pseg, this_segment, stack;
+  long result = 0;
+
+  struct stack_segment_linkage *ssptr;
+
+  /* Register B67 contains the address of the end of the
+     current stack segment.  If you (as a subprogram) store
+     your registers on the stack and find that you are past
+     the contents of B67, you have overflowed the segment.
+
+     B67 also points to the stack segment linkage control
+     area, which is what we are really interested in.  */
+
+  /* This might be _getb67() or GETB67 () or getb67 () */
+  stkl = CRAY_STACKSEG_END ();
+  ssptr = (struct stack_segment_linkage *) stkl;
+
+  /* If one subtracts 'size' from the end of the segment,
+     one has the address of the first word of the segment.
+
+     If this is not the first segment, 'pseg' will be
+     nonzero.  */
+
+  pseg = ssptr->sspseg;
+  size = ssptr->sssize;
+
+  this_segment = stkl - size;
+
+  /* It is possible that calling this routine itself caused
+     a stack overflow.  Discard stack segments which do not
+     contain the target address.  */
+
+  while (!(this_segment <= address && address <= stkl))
+    {
+#ifdef DEBUG_I00AFUNC
+      fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
+#endif
+      if (pseg == 0)
+       break;
+      stkl = stkl - pseg;
+      ssptr = (struct stack_segment_linkage *) stkl;
+      size = ssptr->sssize;
+      pseg = ssptr->sspseg;
+      this_segment = stkl - size;
+    }
+
+  result = address - this_segment;
+
+  /* If you subtract pseg from the current end of the stack,
+     you get the address of the previous stack segment's end.
+     This seems a little convoluted to me, but I'll bet you save
+     a cycle somewhere.  */
+
+  while (pseg != 0)
+    {
+#ifdef DEBUG_I00AFUNC
+      fprintf (stderr, "%011o %011o\n", pseg, size);
+#endif
+      stkl = stkl - pseg;
+      ssptr = (struct stack_segment_linkage *) stkl;
+      size = ssptr->sssize;
+      pseg = ssptr->sspseg;
+      result += size;
+    }
+  return (result);
+}
+
+#endif /* not CRAY2 */
+#endif /* CRAY && CRAY_STACKSEG_END */
+
+#endif /* no alloca */
+#endif /* !__GNUC__ || __GNUC__ < 2 */
diff --git a/lib/malloc/getpagesize.h b/lib/malloc/getpagesize.h
new file mode 100644 (file)
index 0000000..0cb4416
--- /dev/null
@@ -0,0 +1,49 @@
+/* Emulation of getpagesize() for systems that need it.
+   Copyright (C) 1991 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#  if defined (_SC_PAGESIZE)
+#    define getpagesize() sysconf(_SC_PAGESIZE)
+#  endif /* _SC_PAGESIZE */
+#endif
+
+#if !defined (getpagesize)
+#  include <sys/param.h>
+#  if defined (PAGESIZE)
+#     define getpagesize() PAGESIZE
+#  else /* !PAGESIZE */
+#    if defined (EXEC_PAGESIZE)
+#      define getpagesize() EXEC_PAGESIZE
+#    else /* !EXEC_PAGESIZE */
+#      if defined (NBPG)
+#        if !defined (CLSIZE)
+#          define CLSIZE 1
+#        endif /* !CLSIZE */
+#        define getpagesize() (NBPG * CLSIZE)
+#      else /* !NBPG */
+#        if defined (NBPC)
+#          define getpagesize() NBPC
+#        endif /* NBPC */
+#      endif /* !NBPG */
+#    endif /* !EXEC_PAGESIZE */
+#  endif /* !PAGESIZE */
+#endif /* !getpagesize */
+
+#if !defined (getpagesize)
+#  define getpagesize() 4096  /* Just punt and use reasonable value */
+#endif
diff --git a/lib/malloc/i386-alloca.s b/lib/malloc/i386-alloca.s
new file mode 100644 (file)
index 0000000..01b2cfe
--- /dev/null
@@ -0,0 +1,16 @@
+       .file "alloca.s"
+       .text
+       .align 4
+       .def alloca; .val alloca; .scl 2; .type 044; .endef
+       .globl alloca
+alloca:
+       popl %edx
+       popl %eax
+       addl $3,%eax
+       andl $0xfffffffc,%eax
+       subl %eax,%esp
+       movl %esp,%eax
+       pushl %eax
+       pushl %edx
+       ret
+       .def alloca; .val .; .scl -1; .endef
diff --git a/lib/malloc/malloc.c b/lib/malloc/malloc.c
new file mode 100644 (file)
index 0000000..78fb640
--- /dev/null
@@ -0,0 +1,668 @@
+/* dynamic memory allocation for GNU. */
+
+/*  Copyright (C) 1985, 1987 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them.   Help stamp out software-hoarding!  */
+
+/*
+ * @(#)nmalloc.c 1 (Caltech) 2/21/82
+ *
+ *     U of M Modified: 20 Jun 1983 ACT: strange hacks for Emacs
+ *
+ *     Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD.
+ *
+ * This is a very fast storage allocator.  It allocates blocks of a small 
+ * number of different sizes, and keeps free lists of each size.  Blocks
+ * that don't exactly fit are passed up to the next larger size.  In this 
+ * implementation, the available sizes are (2^n)-4 (or -16) bytes long.
+ * This is designed for use in a program that uses vast quantities of
+ * memory, but bombs when it runs out.  To make it a little better, it
+ * warns the user when he starts to get near the end.
+ *
+ * June 84, ACT: modified rcheck code to check the range given to malloc,
+ * rather than the range determined by the 2-power used.
+ *
+ * Jan 85, RMS: calls malloc_warning to issue warning on nearly full.
+ * No longer Emacs-specific; can serve as all-purpose malloc for GNU.
+ * You should call malloc_init to reinitialize after loading dumped Emacs.
+ * Call malloc_stats to get info on memory stats if MSTATS turned on.
+ * realloc knows how to return same block given, just changing its size,
+ * if the power of 2 is correct.
+ */
+
+/*
+ * nextf[i] is the pointer to the next free block of size 2^(i+3).  The
+ * smallest allocatable block is 8 bytes.  The overhead information will
+ * go in the first int of the block, and the returned pointer will point
+ * to the second.
+ *
+#ifdef MSTATS
+ * nmalloc[i] is the difference between the number of mallocs and frees
+ * for a given block size.
+#endif
+ */
+
+#if defined (emacs) || defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif /* emacs */
+
+#if !defined (USG)
+#  if defined (HPUX) || defined (UnixPC) || defined (Xenix)
+#    define USG
+#  endif /* HPUX || UnixPC || Xenix */
+#endif /* !USG */
+
+/* Determine which kind of system this is.  */
+#include <sys/types.h>
+#include <signal.h>
+
+#if !defined (USG) && !defined (USGr4)
+#  ifndef SIGTSTP
+#    ifndef USG
+#      define USG
+#    endif /* !USG */
+#  else /* SIGTSTP */
+#    ifdef SIGIO
+#      define BSD4_2
+#    endif /* SIGIO */
+#  endif /* SIGTSTP */
+#endif /* !USG && !USGr4 */
+
+#ifndef BSD4_2
+   /* Define getpagesize () if the system does not.  */
+#  include "getpagesize.h"
+#endif
+
+#if defined (HAVE_RESOURCE)
+#  include <sys/time.h>
+#  include <sys/resource.h>
+#endif /* HAVE_RESOURCE */
+
+/* Check for the needed symbols.  If they aren't present, this
+   system's <sys/resource.h> isn't very useful to us. */
+#if !defined (RLIMIT_DATA)
+#  undef HAVE_RESOURCE
+#endif
+
+#define start_of_data() &etext
+
+#define ISALLOC ((char) 0xf7)  /* magic byte that implies allocation */
+#define ISFREE ((char) 0x54)   /* magic byte that implies free block */
+                               /* this is for error checking only */
+#define ISMEMALIGN ((char) 0xd6)  /* Stored before the value returned by
+                                    memalign, with the rest of the word
+                                    being the distance to the true
+                                    beginning of the block.  */
+extern char etext;
+
+#if !defined (NO_SBRK_DECL)
+extern char *sbrk ();
+#endif /* !NO_SBRK_DECL */
+
+/* These two are for user programs to look at, when they are interested.  */
+
+unsigned int malloc_sbrk_used;       /* amount of data space used now */
+unsigned int malloc_sbrk_unused;     /* amount more we can have */
+
+/* start of data space; can be changed by calling init_malloc */
+static char *data_space_start;
+
+static void get_lim_data ();
+
+#ifdef MSTATS
+static int nmalloc[30];
+static int nmal, nfre;
+#endif /* MSTATS */
+
+/* If range checking is not turned on, all we have is a flag indicating
+   whether memory is allocated, an index in nextf[], and a size field; to
+   realloc() memory we copy either size bytes or 1<<(index+3) bytes depending
+   on whether the former can hold the exact size (given the value of
+   'index').  If range checking is on, we always need to know how much space
+   is allocated, so the 'size' field is never used. */
+
+struct mhead {
+       char     mh_alloc;      /* ISALLOC or ISFREE */
+       char     mh_index;      /* index in nextf[] */
+/* Remainder are valid only when block is allocated */
+       unsigned short mh_size; /* size, if < 0x10000 */
+#ifdef rcheck
+       unsigned mh_nbytes;     /* number of bytes allocated */
+       int      mh_magic4;     /* should be == MAGIC4 */
+#endif /* rcheck */
+};
+
+/* Access free-list pointer of a block.
+  It is stored at block + 4.
+  This is not a field in the mhead structure
+  because we want sizeof (struct mhead)
+  to describe the overhead for when the block is in use,
+  and we do not want the free-list pointer to count in that.  */
+
+#define CHAIN(a) \
+  (*(struct mhead **) (sizeof (char *) + (char *) (a)))
+
+#ifdef rcheck
+#  include <stdio.h>
+#  if !defined (botch)
+#    define botch(x) abort ()
+#  endif /* botch */
+
+#  if !defined (__STRING)
+#    if defined (__STDC__)
+#      define __STRING(x) #x
+#    else
+#      define __STRING(x) "x"
+#    endif
+#  endif
+
+  /* To implement range checking, we write magic values in at the beginning
+     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 4 bytes before the block's real space */
+#  define MAGIC4 0x55555555
+#  define ASSERT(p) if (!(p)) botch(__STRING(p)); else
+#  define EXTRA  4             /* 4 bytes extra for MAGIC1s */
+#else /* !rcheck */
+#  define ASSERT(p)
+#  define EXTRA  0
+#endif /* rcheck */
+
+/* nextf[i] is free list of blocks of size 2**(i + 3)  */
+
+static struct mhead *nextf[30];
+
+/* busy[i] is nonzero while allocation of block size i is in progress.  */
+
+static char busy[30];
+
+/* Number of bytes of writable memory we can expect to be able to get */
+static unsigned int lim_data;
+
+/* Level number of warnings already issued.
+  0 -- no warnings issued.
+  1 -- 75% warning already issued.
+  2 -- 85% warning already issued.
+*/
+static int warnlevel;
+
+/* Function to call to issue a warning;
+   0 means don't issue them.  */
+static void (*warnfunction) ();
+
+/* nonzero once initial bunch of free blocks made */
+static int gotpool;
+
+char *_malloc_base;
+
+static void getpool ();
+
+/* Cause reinitialization based on job parameters;
+  also declare where the end of pure storage is. */
+void
+malloc_init (start, warnfun)
+     char *start;
+     void (*warnfun) ();
+{
+  if (start)
+    data_space_start = start;
+  lim_data = 0;
+  warnlevel = 0;
+  warnfunction = warnfun;
+}
+
+/* Return the maximum size to which MEM can be realloc'd
+   without actually requiring copying.  */
+
+int
+malloc_usable_size (mem)
+     char *mem;
+{
+  int blocksize = 8 << (((struct mhead *) mem) - 1) -> mh_index;
+
+  return blocksize - sizeof (struct mhead) - EXTRA;
+}
+\f
+static void
+morecore (nu)                  /* ask system for more memory */
+     register int nu;          /* size index to get more of  */
+{
+  register char *cp;
+  register int nblks;
+  register unsigned int siz;
+  int oldmask;
+
+#if defined (BSD4_2)
+  oldmask = sigsetmask (-1);
+#endif /* BSD4_2 */
+
+  if (!data_space_start)
+    {
+      data_space_start = start_of_data ();
+    }
+
+  if (lim_data == 0)
+    get_lim_data ();
+
+ /* On initial startup, get two blocks of each size up to 1k bytes */
+  if (!gotpool)
+    { getpool (); getpool (); gotpool = 1; }
+
+  /* Find current end of memory and issue warning if getting near max */
+
+  cp = sbrk (0);
+  siz = cp - data_space_start;
+  malloc_sbrk_used = siz;
+  malloc_sbrk_unused = lim_data - siz;
+
+  if (warnfunction)
+    switch (warnlevel)
+      {
+      case 0: 
+       if (siz > (lim_data / 4) * 3)
+         {
+           warnlevel++;
+           (*warnfunction) ("Warning: past 75% of memory limit");
+         }
+       break;
+      case 1: 
+       if (siz > (lim_data / 20) * 17)
+         {
+           warnlevel++;
+           (*warnfunction) ("Warning: past 85% of memory limit");
+         }
+       break;
+      case 2: 
+       if (siz > (lim_data / 20) * 19)
+         {
+           warnlevel++;
+           (*warnfunction) ("Warning: past 95% of memory limit");
+         }
+       break;
+      }
+
+  if ((int) cp & 0x3ff)        /* land on 1K boundaries */
+    sbrk (1024 - ((int) cp & 0x3ff));
+
+ /* Take at least 2k, and figure out how many blocks of the desired size
+    we're about to get */
+  nblks = 1;
+  if ((siz = nu) < 8)
+    nblks = 1 << ((siz = 8) - nu);
+
+  if ((cp = sbrk (1 << (siz + 3))) == (char *) -1)
+    return;                    /* no more room! */
+
+  if ((int) cp & 7)
+    {          /* shouldn't happen, but just in case */
+      cp = (char *) (((int) cp + 8) & ~7);
+      nblks--;
+    }
+
+ /* save new header and link the nblks blocks together */
+  nextf[nu] = (struct mhead *) cp;
+  siz = 1 << (nu + 3);
+  while (1)
+    {
+      ((struct mhead *) cp) -> mh_alloc = ISFREE;
+      ((struct mhead *) cp) -> mh_index = nu;
+      if (--nblks <= 0) break;
+      CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz);
+      cp += siz;
+    }
+  CHAIN ((struct mhead *) cp) = 0;
+
+#if defined (BSD4_2)
+  sigsetmask (oldmask);
+#endif /* BSD4_2 */
+}
+
+static void
+getpool ()
+{
+  register int nu;
+  register char *cp = sbrk (0);
+
+  if ((int) cp & 0x3ff)        /* land on 1K boundaries */
+    sbrk (1024 - ((int) cp & 0x3ff));
+
+  /* Record address of start of space allocated by malloc.  */
+  if (_malloc_base == 0)
+    _malloc_base = cp;
+
+  /* Get 2k of storage */
+
+  cp = sbrk (04000);
+  if (cp == (char *) -1)
+    return;
+
+  /* Divide it into an initial 8-word block
+     plus one block of size 2**nu for nu = 3 ... 10.  */
+
+  CHAIN (cp) = nextf[0];
+  nextf[0] = (struct mhead *) cp;
+  ((struct mhead *) cp) -> mh_alloc = ISFREE;
+  ((struct mhead *) cp) -> mh_index = 0;
+  cp += 8;
+
+  for (nu = 0; nu < 7; nu++)
+    {
+      CHAIN (cp) = nextf[nu];
+      nextf[nu] = (struct mhead *) cp;
+      ((struct mhead *) cp) -> mh_alloc = ISFREE;
+      ((struct mhead *) cp) -> mh_index = nu;
+      cp += 8 << nu;
+    }
+}
+\f
+char *
+malloc (n)             /* get a block */
+     unsigned n;
+{
+  register struct mhead *p;
+  register unsigned int nbytes;
+  register int nunits = 0;
+
+  /* Figure out how many bytes are required, rounding up to the nearest
+     multiple of 4, then figure out which nextf[] area to use */
+  nbytes = (n + sizeof *p + EXTRA + 3) & ~3;
+  {
+    register unsigned int   shiftr = (nbytes - 1) >> 2;
+
+    while (shiftr >>= 1)
+      nunits++;
+  }
+
+  /* In case this is reentrant use of malloc from signal handler,
+     pick a block size that no other malloc level is currently
+     trying to allocate.  That's the easiest harmless way not to
+     interfere with the other level of execution.  */
+  while (busy[nunits]) nunits++;
+  busy[nunits] = 1;
+
+  /* If there are no blocks of the appropriate size, go get some */
+  /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */
+  if (nextf[nunits] == 0)
+    morecore (nunits);
+
+  /* Get one block off the list, and set the new list head */
+  if ((p = nextf[nunits]) == 0)
+    {
+      busy[nunits] = 0;
+      return 0;
+    }
+  nextf[nunits] = CHAIN (p);
+  busy[nunits] = 0;
+
+  /* Check for free block clobbered */
+  /* 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)
+#ifdef rcheck
+    botch ("block on free list clobbered");
+#else /* not rcheck */
+    abort ();
+#endif /* not rcheck */
+
+  /* Fill in the info, and if range checking, set up the magic numbers */
+  p -> mh_alloc = ISALLOC;
+#ifdef rcheck
+  p -> mh_nbytes = n;
+  p -> mh_magic4 = MAGIC4;
+  {
+    register char  *m = (char *) (p + 1) + n;
+
+    *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1;
+  }
+#else /* not rcheck */
+  p -> mh_size = n;
+#endif /* not rcheck */
+#ifdef MSTATS
+  nmalloc[nunits]++;
+  nmal++;
+#endif /* MSTATS */
+  return (char *) (p + 1);
+}
+
+void
+free (mem)
+     char *mem;
+{
+  register struct mhead *p;
+  {
+    register char *ap = mem;
+
+    if (ap == 0)
+      return;
+
+    p = (struct mhead *) ap - 1;
+
+    if (p -> mh_alloc == ISMEMALIGN)
+      {
+#ifdef rcheck
+       ap -= p->mh_nbytes;
+#endif
+       p = (struct mhead *) ap - 1;
+      }
+
+#ifndef rcheck
+    if (p -> mh_alloc != ISALLOC)
+      abort ();
+
+#else /* rcheck */
+    if (p -> mh_alloc != ISALLOC)
+      {
+       if (p -> mh_alloc == ISFREE)
+         botch ("free: Called with already freed block argument\n");
+       else
+         botch ("free: Called with bad argument\n");
+      }
+
+    ASSERT (p -> mh_magic4 == MAGIC4);
+    ap += p -> mh_nbytes;
+    ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1);
+    ASSERT (*ap++ == MAGIC1); ASSERT (*ap   == MAGIC1);
+#endif /* rcheck */
+  }
+  {
+    register int nunits = p -> mh_index;
+
+    ASSERT (nunits <= 29);
+    p -> mh_alloc = ISFREE;
+
+    /* Protect against signal handlers calling malloc.  */
+    busy[nunits] = 1;
+    /* Put this block on the free list.  */
+    CHAIN (p) = nextf[nunits];
+    nextf[nunits] = p;
+    busy[nunits] = 0;
+
+#ifdef MSTATS
+    nmalloc[nunits]--;
+    nfre++;
+#endif /* MSTATS */
+  }
+}
+
+char *
+realloc (mem, n)
+     char *mem;
+     register unsigned n;
+{
+  register struct mhead *p;
+  register unsigned int tocopy;
+  register unsigned int nbytes;
+  register int nunits;
+
+  if ((p = (struct mhead *) mem) == 0)
+    return malloc (n);
+  p--;
+  nunits = p -> mh_index;
+  ASSERT (p -> mh_alloc == ISALLOC);
+#ifdef rcheck
+  ASSERT (p -> mh_magic4 == MAGIC4);
+  {
+    register char *m = mem + (tocopy = p -> mh_nbytes);
+    ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1);
+    ASSERT (*m++ == MAGIC1); ASSERT (*m   == MAGIC1);
+  }
+#else /* not rcheck */
+  if (p -> mh_index >= 13)
+    tocopy = (1 << (p -> mh_index + 3)) - sizeof *p;
+  else
+    tocopy = p -> mh_size;
+#endif /* not rcheck */
+
+  /* See if desired size rounds to same power of 2 as actual size. */
+  nbytes = (n + sizeof *p + EXTRA + 7) & ~7;
+
+  /* If ok, use the same block, just marking its size as changed.  */
+  if (nbytes > (4 << nunits) && nbytes <= (8 << nunits))
+    {
+#ifdef rcheck
+      register char *m = mem + tocopy;
+      *m++ = 0;  *m++ = 0;  *m++ = 0;  *m++ = 0;
+      p-> mh_nbytes = n;
+      m = mem + n;
+      *m++ = MAGIC1;  *m++ = MAGIC1;  *m++ = MAGIC1;  *m++ = MAGIC1;
+#else /* not rcheck */
+      p -> mh_size = n;
+#endif /* not rcheck */
+      return mem;
+    }
+
+  if (n < tocopy)
+    tocopy = n;
+  {
+    register char *new;
+
+    if ((new = malloc (n)) == 0)
+      return 0;
+    bcopy (mem, new, tocopy);
+    free (mem);
+    return new;
+  }
+}
+
+char *
+memalign (alignment, size)
+     unsigned alignment, size;
+{
+  register char *ptr = malloc (size + alignment);
+  register char *aligned;
+  register struct mhead *p;
+
+  if (ptr == 0)
+    return 0;
+  /* If entire block has the desired alignment, just accept it.  */
+  if (((int) ptr & (alignment - 1)) == 0)
+    return ptr;
+  /* Otherwise, get address of byte in the block that has that alignment.  */
+  aligned = (char *) (((int) ptr + alignment - 1) & -alignment);
+
+  /* Store a suitable indication of how to free the block,
+     so that free can find the true beginning of it.  */
+  p = (struct mhead *) aligned - 1;
+  p -> mh_size = aligned - ptr;
+  p -> mh_alloc = ISMEMALIGN;
+  return aligned;
+}
+
+#if !defined (HPUX) && !defined (Multimax) && !defined (Multimax32k)
+/* This runs into trouble with getpagesize on HPUX, and Multimax machines.
+   Patching out seems cleaner than the ugly fix needed.  */
+char *
+valloc (size)
+{
+  return memalign (getpagesize (), size);
+}
+#endif /* !HPUX && !Multimax && !Multimax32k */
+\f
+#ifdef MSTATS
+/* Return statistics describing allocation of blocks of size 2**n. */
+
+struct mstats_value
+  {
+    int blocksize;
+    int nfree;
+    int nused;
+  };
+
+struct mstats_value
+malloc_stats (size)
+     int size;
+{
+  struct mstats_value v;
+  register int i;
+  register struct mhead *p;
+
+  v.nfree = 0;
+
+  if (size < 0 || size >= 30)
+    {
+      v.blocksize = 0;
+      v.nused = 0;
+      return v;
+    }
+
+  v.blocksize = 1 << (size + 3);
+  v.nused = nmalloc[size];
+
+  for (p = nextf[size]; p; p = CHAIN (p))
+    v.nfree++;
+
+  return v;
+}
+#endif /* MSTATS */
+\f
+/*
+ *     This function returns the total number of bytes that the process
+ *     will be allowed to allocate via the sbrk(2) system call.  On
+ *     BSD systems this is the total space allocatable to stack and
+ *     data.  On USG systems this is the data space only.
+ */
+
+#if !defined (HAVE_RESOURCE)
+extern long ulimit ();
+
+static void
+get_lim_data ()
+{    
+  lim_data = ulimit (3, 0);
+  lim_data -= (long) data_space_start;
+}
+
+#else /* HAVE_RESOURCE */
+static void
+get_lim_data ()
+{
+  struct rlimit XXrlimit;
+
+  getrlimit (RLIMIT_DATA, &XXrlimit);
+#ifdef RLIM_INFINITY
+  lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */
+#else
+  lim_data = XXrlimit.rlim_cur;        /* soft limit */
+#endif
+}
+
+#endif /* HAVE_RESOURCE */
diff --git a/lib/malloc/x386-alloca.s b/lib/malloc/x386-alloca.s
new file mode 100644 (file)
index 0000000..112d33c
--- /dev/null
@@ -0,0 +1,63 @@
+;; alloca386.s 1.2
+;; GNU-compatible stack allocation function for Xenix/386.
+;; Written by Chip Salzenberg at ComDev.
+;; Last modified 90/01/11
+;;> Is your alloca clearly better than the one in i386-alloca.s?  I haven't
+;;> looked at either.
+;;
+;;They're different because Xenix/386 has a different assembler.  SCO
+;;Xenix has the Microsoft C compiler and the Microsoft macro assembler,
+;;called "masm".  MASM's assembler syntax is quite different from AT&T's
+;;in all sorts of ways.  Xenix people can't use the AT&T version.
+;;-- 
+;;Chip Salzenberg at ComDev/TCT     <chip@tct.uucp>, <uunet!ateng!tct!chip>
+
+       TITLE   $alloca386
+
+       .386
+DGROUP GROUP   CONST, _BSS, _DATA
+_DATA  SEGMENT  DWORD USE32 PUBLIC 'DATA'
+_DATA      ENDS
+_BSS   SEGMENT  DWORD USE32 PUBLIC 'BSS'
+_BSS      ENDS
+CONST  SEGMENT  DWORD USE32 PUBLIC 'CONST'
+CONST      ENDS
+_TEXT  SEGMENT  DWORD USE32 PUBLIC 'CODE'
+       ASSUME   CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
+
+       PUBLIC  _alloca
+_alloca PROC NEAR
+
+; Get argument.
+       pop     edx             ; edx -> return address
+       pop     eax             ; eax = amount to allocate
+
+; Validate allocation amount.
+       add     eax,3
+       and     eax,not 3
+       cmp     eax,0
+       jg      aa_size_ok
+       mov     eax,4
+aa_size_ok:
+
+; Allocate stack space.
+       mov     ecx,esp         ; ecx -> old stack pointer
+       sub     esp,eax         ; perform allocation
+       mov     eax,esp         ; eax -> new stack pointer
+
+; Copy the three saved register variables from old stack top to new stack top.
+; They may not be there.  So we waste twelve bytes.  Big fat hairy deal.
+       push    DWORD PTR 8[ecx]
+       push    DWORD PTR 4[ecx]
+       push    DWORD PTR 0[ecx]
+
+; Push something so the caller can pop it off.
+       push    eax
+
+; Return to caller.
+       jmp     edx
+
+_alloca ENDP
+
+_TEXT   ENDS
+       END
diff --git a/lib/malloc/xmalloc.c b/lib/malloc/xmalloc.c
new file mode 100644 (file)
index 0000000..4f6dc76
--- /dev/null
@@ -0,0 +1,78 @@
+/* xmalloc.c -- safe versions of malloc and realloc */
+
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Readline, a library for reading lines
+   of text with interactive input and history editing.
+
+   Readline is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 1, or (at your option) any
+   later version.
+
+   Readline is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if defined (ALREADY_HAVE_XMALLOC)
+#else
+#include <stdio.h>
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+static void memory_error_and_abort ();
+
+/* **************************************************************** */
+/*                                                                 */
+/*                Memory Allocation and Deallocation.              */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Return a pointer to free()able block of memory large enough
+   to hold BYTES number of bytes.  If the memory cannot be allocated,
+   print an error message and abort. */
+char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ("xmalloc");
+  return (temp);
+}
+
+char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ("xrealloc");
+  return (temp);
+}
+
+static void
+memory_error_and_abort (fname)
+     char *fname;
+{
+  fprintf (stderr, "%s: Out of virtual memory!\n", fname);
+  abort ();
+}
+#endif /* !ALREADY_HAVE_XMALLOC */
diff --git a/lib/malloclib/Makefile b/lib/malloclib/Makefile
new file mode 100644 (file)
index 0000000..7a449c3
--- /dev/null
@@ -0,0 +1,53 @@
+# Copyright (C) 1991 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# 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., 675 Mass Ave,
+# Cambridge, MA 02139, USA.
+
+# Makefile for standalone distribution of malloc.
+
+srcdir = .
+VPATH = .:$(srcdir)
+
+all: libmalloc.a
+
+sources = calloc.c cfree.c free.c malloc.c mcheck.c morecore.c \
+         memalign.c mstats.c mtrace.c realloc.c valloc.c
+objects = calloc.o cfree.o free.o malloc.o mcheck.o morecore.o \
+         memalign.o mstats.o mtrace.o realloc.o valloc.o
+headers = malloc.h getpagesize.h
+
+libmalloc.a: $(objects)
+       ar crv $@ $(objects)
+       ranlib $@
+
+.c.o:
+       $(CC) $(CFLAGS) $(CPPFLAGS) -I. -c $< $(OUTPUT_OPTION)
+
+.PHONY: clean realclean malloc-clean malloc-realclean
+clean malloc-clean:
+       -rm -f libmalloc.a $(objects) core
+realclean malloc-realclean: clean
+       -rm -f TAGS tags *~
+
+calloc.o: malloc.h
+free.o: malloc.h
+malloc.o: malloc.h
+mcheck.o: malloc.h
+memalign.o: malloc.h
+mstats.o: malloc.h
+mtrace.o: malloc.h
+realloc.o: malloc.h
+valloc.o: malloc.h getpagesize.h
diff --git a/lib/malloclib/alloca.c b/lib/malloclib/alloca.c
new file mode 100644 (file)
index 0000000..918d023
--- /dev/null
@@ -0,0 +1,189 @@
+/* alloca -- (mostly) portable public-domain implementation -- D A Gwyn
+
+   last edit:  86/05/30        rms
+   include config.h, since on VMS it renames some symbols.
+   Use xmalloc instead of malloc.
+
+   This implementation of the PWB library alloca() function,
+   which is used to allocate space off the run-time stack so
+   that it is automatically reclaimed upon procedure exit, 
+   was inspired by discussions with J. Q. Johnson of Cornell.
+
+   It should work under any C implementation that uses an
+   actual procedure stack (as opposed to a linked list of
+   frames).  There are some preprocessor constants that can
+   be defined when compiling for your specific system, for
+   improved efficiency; however, the defaults should be okay.
+
+   The general concept of this implementation is to keep
+   track of all alloca()-allocated blocks, and reclaim any
+   that are found to be deeper in the stack than the current
+   invocation.  This heuristic does not reclaim storage as
+   soon as it becomes invalid, but it will do so eventually.
+
+   As a special case, alloca(0) reclaims storage without
+   allocating any.  It is a good idea to use alloca(0) in
+   your main control loop, etc. to force garbage collection.
+*/
+#ifndef lint
+static char    SCCSid[] = "@(#)alloca.c        1.1";   /* for the "what" utility */
+#endif
+
+#ifdef emacs
+#include "config.h"
+#ifdef static
+/* actually, only want this if static is defined as ""
+   -- this is for usg, in which emacs must undefine static
+   in order to make unexec workable
+   */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+#ifdef X3J11
+typedef void   *pointer;               /* generic pointer type */
+#else
+typedef char   *pointer;               /* generic pointer type */
+#endif /* X3J11 */
+
+#define        NULL    0                       /* null pointer constant */
+
+extern void    free();
+extern pointer xmalloc();
+
+/*
+       Define STACK_DIRECTION if you know the direction of stack
+       growth for your system; otherwise it will be automatically
+       deduced at run-time.
+
+       STACK_DIRECTION > 0 => grows toward higher addresses
+       STACK_DIRECTION < 0 => grows toward lower addresses
+       STACK_DIRECTION = 0 => direction of growth unknown
+*/
+
+#ifndef STACK_DIRECTION
+#define        STACK_DIRECTION 0               /* direction unknown */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define        STACK_DIR       STACK_DIRECTION /* known at compile-time */
+
+#else  /* STACK_DIRECTION == 0; need run-time code */
+
+static int     stack_dir;              /* 1 or -1 once known */
+#define        STACK_DIR       stack_dir
+
+static void
+find_stack_direction (/* void */)
+{
+  static char  *addr = NULL;   /* address of first
+                                  `dummy', once known */
+  auto char    dummy;          /* to get stack address */
+
+  if (addr == NULL)
+    {                          /* initial entry */
+      addr = &dummy;
+
+      find_stack_direction (); /* recurse once */
+    }
+  else                         /* second entry */
+    if (&dummy > addr)
+      stack_dir = 1;           /* stack grew upward */
+    else
+      stack_dir = -1;          /* stack grew downward */
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/*
+       An "alloca header" is used to:
+       (a) chain together all alloca()ed blocks;
+       (b) keep track of stack depth.
+
+       It is very important that sizeof(header) agree with malloc()
+       alignment chunk size.  The following default should work okay.
+*/
+
+#ifndef        ALIGN_SIZE
+#define        ALIGN_SIZE      sizeof(double)
+#endif
+
+typedef union hdr
+{
+  char align[ALIGN_SIZE];      /* to force sizeof(header) */
+  struct
+    {
+      union hdr *next;         /* for chaining headers */
+      char *deep;              /* for stack depth measure */
+    } h;
+} header;
+
+/*
+       alloca( size ) returns a pointer to at least `size' bytes of
+       storage which will be automatically reclaimed upon exit from
+       the procedure that called alloca().  Originally, this space
+       was supposed to be taken from the current stack frame of the
+       caller, but that method cannot be made to work for some
+       implementations of C, for example under Gould's UTX/32.
+*/
+
+static header *last_alloca_header = NULL; /* -> last alloca header */
+
+pointer
+alloca (size)                  /* returns pointer to storage */
+     unsigned  size;           /* # bytes to allocate */
+{
+  auto char    probe;          /* probes stack depth: */
+  register char        *depth = &probe;
+
+#if STACK_DIRECTION == 0
+  if (STACK_DIR == 0)          /* unknown growth direction */
+    find_stack_direction ();
+#endif
+
+  /* Reclaim garbage, defined as all alloca()ed storage that
+     was allocated from deeper in the stack than currently. */
+  {
+    register header    *hp;    /* traverses linked list */
+
+    for (hp = last_alloca_header; hp != NULL;)
+      if (STACK_DIR > 0 && hp->h.deep > depth
+         || STACK_DIR < 0 && hp->h.deep < depth)
+       {
+         register header       *np = hp->h.next;
+
+         free ((pointer) hp);  /* collect garbage */
+
+         hp = np;              /* -> next header */
+       }
+      else
+       break;                  /* rest are not deeper */
+
+    last_alloca_header = hp;   /* -> last valid storage */
+  }
+
+  if (size == 0)
+    return NULL;               /* no allocation required */
+
+  /* Allocate combined header + user data storage. */
+
+  {
+    register pointer   new = xmalloc (sizeof (header) + size);
+    /* address of header */
+
+    ((header *)new)->h.next = last_alloca_header;
+    ((header *)new)->h.deep = depth;
+
+    last_alloca_header = (header *)new;
+
+    /* User storage begins just after header. */
+
+    return (pointer)((char *)new + sizeof(header));
+  }
+}
+
diff --git a/lib/malloclib/calloc.c b/lib/malloclib/calloc.c
new file mode 100644 (file)
index 0000000..f870e94
--- /dev/null
@@ -0,0 +1,39 @@
+/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+This 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.
+
+This 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 this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef        _MALLOC_INTERNAL
+#define        _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* Allocate an array of NMEMB elements each SIZE bytes long.
+   The entire array is initialized to zeros.  */
+__ptr_t
+calloc (nmemb, size)
+     register size_t nmemb;
+     register size_t size;
+{
+  register __ptr_t result = malloc (nmemb * size);
+
+  if (result != NULL)
+    (void) memset (result, 0, nmemb * size);
+
+  return result;
+}
diff --git a/lib/malloclib/cfree.c b/lib/malloclib/cfree.c
new file mode 100644 (file)
index 0000000..adc1ff6
--- /dev/null
@@ -0,0 +1,43 @@
+/* Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+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., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef        _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#undef cfree
+
+#ifdef _LIBC
+
+#include <ansidecl.h>
+#include <gnu-stabs.h>
+
+function_alias(cfree, free, void, (ptr),
+              DEFUN(cfree, (ptr), PTR ptr))
+
+#else
+
+void
+cfree (ptr)
+     __ptr_t ptr;
+{
+  free (ptr);
+}
+
+#endif
diff --git a/lib/malloclib/free.c b/lib/malloclib/free.c
new file mode 100644 (file)
index 0000000..db97fcb
--- /dev/null
@@ -0,0 +1,212 @@
+/* Free a block of memory allocated by `malloc'.
+   Copyright 1990, 1991, 1992 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+This 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.
+
+This 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 this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef        _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* Debugging hook for free.  */
+void (*__free_hook) __P ((__ptr_t __ptr));
+
+/* List of blocks allocated by memalign.  */
+struct alignlist *_aligned_blocks = NULL;
+
+/* Return memory to the heap.
+   Like `free' but don't call a __free_hook if there is one.  */
+void
+_free_internal (ptr)
+     __ptr_t ptr;
+{
+  int type;
+  size_t block, blocks;
+  register size_t i;
+  struct list *prev, *next;
+
+  block = BLOCK (ptr);
+
+  type = _heapinfo[block].busy.type;
+  switch (type)
+    {
+    case 0:
+      /* Get as many statistics as early as we can.  */
+      --_chunks_used;
+      _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
+      _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
+
+      /* Find the free cluster previous to this one in the free list.
+        Start searching at the last block referenced; this may benefit
+        programs with locality of allocation.  */
+      i = _heapindex;
+      if (i > block)
+       while (i > block)
+         i = _heapinfo[i].free.prev;
+      else
+       {
+         do
+           i = _heapinfo[i].free.next;
+         while (i > 0 && i < block);
+         i = _heapinfo[i].free.prev;
+       }
+
+      /* Determine how to link this block into the free list.  */
+      if (block == i + _heapinfo[i].free.size)
+       {
+         /* Coalesce this block with its predecessor.  */
+         _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
+         block = i;
+       }
+      else
+       {
+         /* Really link this block back into the free list.  */
+         _heapinfo[block].free.size = _heapinfo[block].busy.info.size;
+         _heapinfo[block].free.next = _heapinfo[i].free.next;
+         _heapinfo[block].free.prev = i;
+         _heapinfo[i].free.next = block;
+         _heapinfo[_heapinfo[block].free.next].free.prev = block;
+         ++_chunks_free;
+       }
+
+      /* Now that the block is linked in, see if we can coalesce it
+        with its successor (by deleting its successor from the list
+        and adding in its size).  */
+      if (block + _heapinfo[block].free.size == _heapinfo[block].free.next)
+       {
+         _heapinfo[block].free.size
+           += _heapinfo[_heapinfo[block].free.next].free.size;
+         _heapinfo[block].free.next
+           = _heapinfo[_heapinfo[block].free.next].free.next;
+         _heapinfo[_heapinfo[block].free.next].free.prev = block;
+         --_chunks_free;
+       }
+
+      /* Now see if we can return stuff to the system.  */
+      blocks = _heapinfo[block].free.size;
+      if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
+         && (*__morecore) (0) == ADDRESS (block + blocks))
+       {
+         register size_t bytes = blocks * BLOCKSIZE;
+         _heaplimit -= blocks;
+         (*__morecore) (-bytes);
+         _heapinfo[_heapinfo[block].free.prev].free.next
+           = _heapinfo[block].free.next;
+         _heapinfo[_heapinfo[block].free.next].free.prev
+           = _heapinfo[block].free.prev;
+         block = _heapinfo[block].free.prev;
+         --_chunks_free;
+         _bytes_free -= bytes;
+       }
+
+      /* Set the next search to begin at this block.  */
+      _heapindex = block;
+      break;
+
+    default:
+      /* Do some of the statistics.  */
+      --_chunks_used;
+      _bytes_used -= 1 << type;
+      ++_chunks_free;
+      _bytes_free += 1 << type;
+
+      /* Get the address of the first free fragment in this block.  */
+      prev = (struct list *) ((char *) ADDRESS (block) +
+                          (_heapinfo[block].busy.info.frag.first << type));
+
+      if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1
+         && _fragblocks[type] > 1)
+       {
+         /* If all fragments of this block are free, remove them
+            from the fragment list and free the whole block.  */
+         --_fragblocks[type];
+         next = prev;
+         for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
+           next = next->next;
+         prev->prev->next = next;
+         if (next != NULL)
+           next->prev = prev->prev;
+         _heapinfo[block].busy.type = 0;
+         _heapinfo[block].busy.info.size = 1;
+
+         /* Keep the statistics accurate.  */
+         ++_chunks_used;
+         _bytes_used += BLOCKSIZE;
+         _chunks_free -= BLOCKSIZE >> type;
+         _bytes_free -= BLOCKSIZE;
+
+         free (ADDRESS (block));
+       }
+      else if (_heapinfo[block].busy.info.frag.nfree != 0)
+       {
+         /* If some fragments of this block are free, link this
+            fragment into the fragment list after the first free
+            fragment of this block. */
+         next = (struct list *) ptr;
+         next->next = prev->next;
+         next->prev = prev;
+         prev->next = next;
+         if (next->next != NULL)
+           next->next->prev = next;
+         ++_heapinfo[block].busy.info.frag.nfree;
+       }
+      else
+       {
+         /* No fragments of this block are free, so link this
+            fragment into the fragment list and announce that
+            it is the first free fragment of this block. */
+         prev = (struct list *) ptr;
+         _heapinfo[block].busy.info.frag.nfree = 1;
+         _heapinfo[block].busy.info.frag.first = (unsigned long int)
+           ((unsigned long int) ((char *) ptr - (char *) NULL)
+            % BLOCKSIZE >> type);
+         prev->next = _fraghead[type].next;
+         prev->prev = &_fraghead[type];
+         prev->prev->next = prev;
+         if (prev->next != NULL)
+           prev->next->prev = prev;
+       }
+      break;
+    }
+}
+
+/* Return memory to the heap.  */
+void
+free (ptr)
+     __ptr_t ptr;
+{
+  register struct alignlist *l;
+
+  if (ptr == NULL)
+    return;
+
+  for (l = _aligned_blocks; l != NULL; l = l->next)
+    if (l->aligned == ptr)
+      {
+       l->aligned = NULL;      /* Mark the slot in the list as free.  */
+       ptr = l->exact;
+       break;
+      }
+
+  if (__free_hook != NULL)
+    (*__free_hook) (ptr);
+  else
+    _free_internal (ptr);
+}
diff --git a/lib/malloclib/getpagesize.h b/lib/malloclib/getpagesize.h
new file mode 100644 (file)
index 0000000..b3aa4ba
--- /dev/null
@@ -0,0 +1,56 @@
+/* Emulation of getpagesize() for systems that need it.
+   Copyright (C) 1991 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#if !defined (USG)
+extern size_t getpagesize __P ((void));
+#  if !defined (HAVE_GETPAGESIZE)
+#    define HAVE_GETPAGESIZE
+#  endif /* !HAVE_GETPAGESIZE */
+#endif /* !USG */
+
+#if !defined (HAVE_GETPAGESIZE) && defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#  if defined (_SC_PAGESIZE)
+#    define getpagesize() sysconf(_SC_PAGESIZE)
+#  endif /* _SC_PAGESIZE */
+#endif
+
+#if !defined (HAVE_GETPAGESIZE)
+#  include <sys/param.h>
+#  if defined (PAGESIZE)
+#     define getpagesize() PAGESIZE
+#  else /* !PAGESIZE */
+#    if defined (EXEC_PAGESIZE)
+#      define getpagesize() EXEC_PAGESIZE
+#    else /* !EXEC_PAGESIZE */
+#      if defined (NBPG)
+#        if !defined (CLSIZE)
+#          define CLSIZE 1
+#        endif /* !CLSIZE */
+#        define getpagesize() (NBPG * CLSIZE)
+#      else /* !NBPG */
+#        if defined (NBPC)
+#          define getpagesize() NBPC
+#        endif /* NBPC */
+#      endif /* !NBPG */
+#    endif /* !EXEC_PAGESIZE */
+#  endif /* !PAGESIZE */
+#endif /* !getpagesize */
+
+#if !defined (HAVE_GETPAGESIZE) && !defined (getpagesize)
+#  define getpagesize() 4096  /* Just punt and use reasonable value */
+#endif /* !HAVE_GETPAGESIZE && !getpagesize */
diff --git a/lib/malloclib/i386-alloca.s b/lib/malloclib/i386-alloca.s
new file mode 100644 (file)
index 0000000..01b2cfe
--- /dev/null
@@ -0,0 +1,16 @@
+       .file "alloca.s"
+       .text
+       .align 4
+       .def alloca; .val alloca; .scl 2; .type 044; .endef
+       .globl alloca
+alloca:
+       popl %edx
+       popl %eax
+       addl $3,%eax
+       andl $0xfffffffc,%eax
+       subl %eax,%esp
+       movl %esp,%eax
+       pushl %eax
+       pushl %edx
+       ret
+       .def alloca; .val .; .scl -1; .endef
diff --git a/lib/malloclib/malloc.c b/lib/malloclib/malloc.c
new file mode 100644 (file)
index 0000000..1d9bc03
--- /dev/null
@@ -0,0 +1,324 @@
+/* Memory allocator `malloc'.
+   Copyright 1990, 1991, 1992, 1993 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+This 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.
+
+This 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 this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef        _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* How to really get more memory.  */
+__ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore;
+
+/* Debugging hook for `malloc'.  */
+__ptr_t (*__malloc_hook) __P ((size_t __size));
+
+/* Pointer to the base of the first block.  */
+char *_heapbase;
+
+/* Block information table.  Allocated with align/__free (not malloc/free).  */
+malloc_info *_heapinfo;
+
+/* Number of info entries.  */
+static size_t heapsize;
+
+/* Search index in the info table.  */
+size_t _heapindex;
+
+/* Limit of valid info table indices.  */
+size_t _heaplimit;
+
+/* Count of large blocks allocated for each fragment size. */
+int _fragblocks[BLOCKLOG];
+
+/* Free lists for each fragment size.  */
+struct list _fraghead[BLOCKLOG];
+
+/* Instrumentation.  */
+size_t _chunks_used;
+size_t _bytes_used;
+size_t _chunks_free;
+size_t _bytes_free;
+
+/* Are you experienced?  */
+int __malloc_initialized;
+
+void (*__after_morecore_hook) __P ((void));
+
+/* Aligned allocation.  */
+static __ptr_t align __P ((size_t));
+static __ptr_t
+align (size)
+     size_t size;
+{
+  __ptr_t result;
+  unsigned long int adj;
+
+  result = (*__morecore) (size);
+  adj = (unsigned long int) ((unsigned long int) ((char *) result -
+                                               (char *) NULL)) % BLOCKSIZE;
+  if (adj != 0)
+    {
+      adj = BLOCKSIZE - adj;
+      (void) (*__morecore) (adj);
+      result = (char *) result + adj;
+    }
+
+  if (__after_morecore_hook)
+    (*__after_morecore_hook) ();
+
+  return result;
+}
+
+/* Set everything up and remember that we have.  */
+static int initialize __P ((void));
+static int
+initialize ()
+{
+  heapsize = HEAP / BLOCKSIZE;
+  _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info));
+
+  _bytes_used = heapsize * sizeof (malloc_info);
+  _chunks_used++;
+
+  if (_heapinfo == NULL)
+    return 0;
+  memset (_heapinfo, 0, heapsize * sizeof (malloc_info));
+  _heapinfo[0].free.size = 0;
+  _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
+  _heapindex = 0;
+  _heapbase = (char *) _heapinfo;
+  __malloc_initialized = 1;
+  return 1;
+}
+
+/* Get neatly aligned memory, initializing or
+   growing the heap info table as necessary. */
+static __ptr_t morecore __P ((size_t));
+static __ptr_t
+morecore (size)
+     size_t size;
+{
+  __ptr_t result;
+  malloc_info *newinfo, *oldinfo;
+  size_t newsize;
+
+  result = align (size);
+  if (result == NULL)
+    return NULL;
+
+  /* Check if we need to grow the info table.  */
+  if ((size_t) BLOCK ((char *) result + size) > heapsize)
+    {
+      newsize = heapsize;
+      while ((size_t) BLOCK ((char *) result + size) > newsize)
+       newsize *= 2;
+      newinfo = (malloc_info *) align (newsize * sizeof (malloc_info));
+      if (newinfo == NULL)
+       {
+         (*__morecore) (-size);
+         return NULL;
+       }
+
+      _bytes_used += newsize * sizeof (malloc_info);
+      _chunks_used++;
+
+      memset (newinfo, 0, newsize * sizeof (malloc_info));
+      memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info));
+      oldinfo = _heapinfo;
+      newinfo[BLOCK (oldinfo)].busy.type = 0;
+      newinfo[BLOCK (oldinfo)].busy.info.size
+       = BLOCKIFY (heapsize * sizeof (malloc_info));
+      _heapinfo = newinfo;
+     
+      heapsize = newsize;
+    }
+
+  _heaplimit = BLOCK ((char *) result + size);
+  return result;
+}
+
+/* Allocate memory from the heap.  */
+__ptr_t
+malloc (size)
+     size_t size;
+{
+  __ptr_t result;
+  size_t block, blocks, lastblocks, start;
+  register size_t i;
+  struct list *next;
+
+  if (size == 0)
+    return NULL;
+
+  if (__malloc_hook != NULL)
+    return (*__malloc_hook) (size);
+
+  if (!__malloc_initialized)
+    if (!initialize ())
+      return NULL;
+
+  if (size < sizeof (struct list))
+      size = sizeof (struct list);
+
+  /* Determine the allocation policy based on the request size.  */
+  if (size <= BLOCKSIZE / 2)
+    {
+      /* Small allocation to receive a fragment of a block.
+        Determine the logarithm to base two of the fragment size. */
+      register size_t log = 1;
+      --size;
+      while ((size /= 2) != 0)
+       ++log;
+
+      /* Look in the fragment lists for a
+        free fragment of the desired size. */
+      next = _fraghead[log].next;
+      if (next != NULL)
+       {
+         /* There are free fragments of this size.
+            Pop a fragment out of the fragment list and return it.
+            Update the block's nfree and first counters. */
+         result = (__ptr_t) next;
+         next->prev->next = next->next;
+         if (next->next != NULL)
+           next->next->prev = next->prev;
+         block = BLOCK (result);
+         if (--_heapinfo[block].busy.info.frag.nfree != 0)
+           _heapinfo[block].busy.info.frag.first = (unsigned long int)
+             ((unsigned long int) ((char *) next->next - (char *) NULL)
+              % BLOCKSIZE) >> log;
+
+         /* Update the statistics.  */
+         ++_chunks_used;
+         _bytes_used += 1 << log;
+         --_chunks_free;
+         _bytes_free -= 1 << log;
+       }
+      else
+       {
+         /* No free fragments of the desired size, so get a new block
+            and break it into fragments, returning the first.  */
+         result = malloc (BLOCKSIZE);
+         if (result == NULL)
+           return NULL;
+         ++_fragblocks[log];
+
+         /* Link all fragments but the first into the free list.  */
+         for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i)
+           {
+             next = (struct list *) ((char *) result + (i << log));
+             next->next = _fraghead[log].next;
+             next->prev = &_fraghead[log];
+             next->prev->next = next;
+             if (next->next != NULL)
+               next->next->prev = next;
+           }
+
+         /* Initialize the nfree and first counters for this block.  */
+         block = BLOCK (result);
+         _heapinfo[block].busy.type = log;
+         _heapinfo[block].busy.info.frag.nfree = i - 1;
+         _heapinfo[block].busy.info.frag.first = i - 1;
+
+         _chunks_free += (BLOCKSIZE >> log) - 1;
+         _bytes_free += BLOCKSIZE - (1 << log);
+         _bytes_used -= BLOCKSIZE - (1 << log);
+       }
+    }
+  else
+    {
+      /* Large allocation to receive one or more blocks.
+        Search the free list in a circle starting at the last place visited.
+        If we loop completely around without finding a large enough
+        space we will have to get more memory from the system.  */
+      blocks = BLOCKIFY (size);
+      start = block = _heapindex;
+      while (_heapinfo[block].free.size < blocks)
+       {
+         block = _heapinfo[block].free.next;
+         if (block == start)
+           {
+             /* Need to get more from the system.  Check to see if
+                the new core will be contiguous with the final free
+                block; if so we don't need to get as much.  */
+             block = _heapinfo[0].free.prev;
+             lastblocks = _heapinfo[block].free.size;
+             if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
+                 (*__morecore) (0) == ADDRESS (block + lastblocks) &&
+                 (morecore ((blocks - lastblocks) * BLOCKSIZE)) != NULL)
+               {
+                 /* Note that morecore() can change the location of
+                    the final block if it moves the info table and the
+                    old one gets coalesced into the final block. */
+                 block = _heapinfo[0].free.prev;
+                 _heapinfo[block].free.size += blocks - lastblocks;
+                 continue;
+               }
+             result = morecore (blocks * BLOCKSIZE);
+             if (result == NULL)
+               return NULL;
+             block = BLOCK (result);
+             _heapinfo[block].busy.type = 0;
+             _heapinfo[block].busy.info.size = blocks;
+             ++_chunks_used;
+             _bytes_used += blocks * BLOCKSIZE;
+             return result;
+           }
+       }
+
+      /* At this point we have found a suitable free list entry.
+        Figure out how to remove what we need from the list. */
+      result = ADDRESS (block);
+      if (_heapinfo[block].free.size > blocks)
+       {
+         /* The block we found has a bit left over,
+            so relink the tail end back into the free list. */
+         _heapinfo[block + blocks].free.size
+           = _heapinfo[block].free.size - blocks;
+         _heapinfo[block + blocks].free.next
+           = _heapinfo[block].free.next;
+         _heapinfo[block + blocks].free.prev
+           = _heapinfo[block].free.prev;
+         _heapinfo[_heapinfo[block].free.prev].free.next
+           = _heapinfo[_heapinfo[block].free.next].free.prev
+           = _heapindex = block + blocks;
+       }
+      else
+       {
+         /* The block exactly matches our requirements,
+            so just remove it from the list. */
+         _heapinfo[_heapinfo[block].free.next].free.prev
+           = _heapinfo[block].free.prev;
+         _heapinfo[_heapinfo[block].free.prev].free.next
+           = _heapindex = _heapinfo[block].free.next;
+         --_chunks_free;
+       }
+
+      _heapinfo[block].busy.type = 0;
+      _heapinfo[block].busy.info.size = blocks;
+      ++_chunks_used;
+      _bytes_used += blocks * BLOCKSIZE;
+      _bytes_free -= blocks * BLOCKSIZE;
+    }
+
+  return result;
+}
diff --git a/lib/malloclib/malloc.h b/lib/malloclib/malloc.h
new file mode 100644 (file)
index 0000000..705a8c0
--- /dev/null
@@ -0,0 +1,268 @@
+/* Declarations for `malloc' and friends.
+   Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+                 Written May 1989 by Mike Haertel.
+
+This 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.
+
+This 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 this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef _MALLOC_H
+
+#define _MALLOC_H      1
+
+#ifdef _MALLOC_INTERNAL
+/* Harmless, gets __GNU_LIBRARY__ defined.
+   We must do this before #defining size_t and ptrdiff_t
+   because <stdio.h> tries to typedef them on some systems.  */
+#include <stdio.h>
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
+#undef __P
+#define        __P(args)       args
+#undef __ptr_t
+#define        __ptr_t         void *
+#else /* Not C++ or ANSI C.  */
+#undef __P
+#define        __P(args)       ()
+#undef const
+#define        const
+#undef __ptr_t
+#define        __ptr_t         char *
+#endif /* C++ or ANSI C.  */
+
+#ifndef        NULL
+#define        NULL    0
+#endif
+
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#undef size_t
+#define        size_t          unsigned int
+#undef ptrdiff_t
+#define        ptrdiff_t       int
+#endif
+
+
+/* Allocate SIZE bytes of memory.  */
+extern __ptr_t malloc __P ((size_t __size));
+/* Re-allocate the previously allocated block
+   in __ptr_t, making the new block SIZE bytes long.  */
+extern __ptr_t realloc __P ((__ptr_t __ptr, size_t __size));
+/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0.  */
+extern __ptr_t calloc __P ((size_t __nmemb, size_t __size));
+/* Free a block allocated by `malloc', `realloc' or `calloc'.  */
+extern void free __P ((__ptr_t __ptr));
+
+/* Allocate SIZE bytes allocated to ALIGNMENT bytes.  */
+extern __ptr_t memalign __P ((size_t __alignment, size_t __size));
+
+/* Allocate SIZE bytes on a page boundary.  */
+extern __ptr_t valloc __P ((size_t __size));
+
+
+#ifdef _MALLOC_INTERNAL
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if    defined(__GNU_LIBRARY__) || defined(STDC_HEADERS) || defined(USG)
+#include <string.h>
+#else
+#ifndef memset
+#define        memset(s, zero, n)      bzero ((s), (n))
+#endif
+#ifndef memcpy
+#define        memcpy(d, s, n)         bcopy ((s), (d), (n))
+#endif
+#ifndef memmove
+#define        memmove(d, s, n)        bcopy ((s), (d), (n))
+#endif
+#endif
+
+
+#if    defined(__GNU_LIBRARY__) || defined(__STDC__)
+#include <limits.h>
+#else
+#define        CHAR_BIT        8
+#endif
+
+/* The allocator divides the heap into blocks of fixed size; large
+   requests receive one or more whole blocks, and small requests
+   receive a fragment of a block.  Fragment sizes are powers of two,
+   and all fragments of a block are the same size.  When all the
+   fragments in a block have been freed, the block itself is freed.  */
+#define INT_BIT                (CHAR_BIT * sizeof(int))
+#define BLOCKLOG       (INT_BIT > 16 ? 12 : 9)
+#define BLOCKSIZE      (1 << BLOCKLOG)
+#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+
+/* Determine the amount of memory spanned by the initial heap table
+   (not an absolute limit).  */
+#define HEAP           (INT_BIT > 16 ? 4194304 : 65536)
+
+/* Number of contiguous free blocks allowed to build up at the end of
+   memory before they will be returned to the system.  */
+#define FINAL_FREE_BLOCKS      8
+
+/* Data structure giving per-block information.  */
+typedef union
+  {
+    /* Heap information for a busy block.  */
+    struct
+      {
+       /* Zero for a large block, or positive giving the
+          logarithm to the base two of the fragment size.  */
+       int type;
+       union
+         {
+           struct
+             {
+               size_t nfree;   /* Free fragments in a fragmented block.  */
+               size_t first;   /* First free fragment of the block.  */
+             } frag;
+           /* Size (in blocks) of a large cluster.  */
+           size_t size;
+         } info;
+      } busy;
+    /* Heap information for a free block
+       (that may be the first of a free cluster).  */
+    struct
+      {
+       size_t size;            /* Size (in blocks) of a free cluster.  */
+       size_t next;            /* Index of next free cluster.  */
+       size_t prev;            /* Index of previous free cluster.  */
+      } free;
+  } malloc_info;
+
+/* Pointer to first block of the heap.  */
+extern char *_heapbase;
+
+/* Table indexed by block number giving per-block information.  */
+extern malloc_info *_heapinfo;
+
+/* Address to block number and vice versa.  */
+#define BLOCK(A)       (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
+#define ADDRESS(B)     ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))
+
+/* Current search index for the heap table.  */
+extern size_t _heapindex;
+
+/* Limit of valid info table indices.  */
+extern size_t _heaplimit;
+
+/* Doubly linked lists of free fragments.  */
+struct list
+  {
+    struct list *next;
+    struct list *prev;
+  };
+
+/* Count of blocks for each fragment size. */
+extern int _fragblocks[];
+
+/* Free list headers for each fragment size.  */
+extern struct list _fraghead[];
+
+/* List of blocks allocated with `memalign' (or `valloc').  */
+struct alignlist
+  {
+    struct alignlist *next;
+    __ptr_t aligned;           /* The address that memaligned returned.  */
+    __ptr_t exact;             /* The address that malloc returned.  */
+  };
+extern struct alignlist *_aligned_blocks;
+
+/* Instrumentation.  */
+extern size_t _chunks_used;
+extern size_t _bytes_used;
+extern size_t _chunks_free;
+extern size_t _bytes_free;
+
+/* Internal version of `free' used in `morecore' (malloc.c). */
+extern void _free_internal __P ((__ptr_t __ptr));
+
+#endif /* _MALLOC_INTERNAL.  */
+
+/* Underlying allocation function; successive calls should
+   return contiguous pieces of memory.  */
+extern __ptr_t (*__morecore) __P ((ptrdiff_t __size));
+
+/* Default value of `__morecore'.  */
+extern __ptr_t __default_morecore __P ((ptrdiff_t __size));
+
+/* If not NULL, this function is called after each time
+   `__morecore' is called to increase the data size.  */
+extern void (*__after_morecore_hook) __P ((void));
+
+/* Nonzero if `malloc' has been called and done its initialization.  */
+extern int __malloc_initialized;
+
+/* Hooks for debugging versions.  */
+extern void (*__free_hook) __P ((__ptr_t __ptr));
+extern __ptr_t (*__malloc_hook) __P ((size_t __size));
+extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
+
+/* Activate a standard collection of debugging hooks.  */
+extern int mcheck __P ((void (*__bfunc) __P ((char *)),
+                       void (*__afunc) __P ((void))));
+
+/* Activate a standard collection of tracing hooks.  */
+extern void mtrace __P ((void));
+
+/* Statistics available to the user.  */
+struct mstats
+  {
+    size_t bytes_total;                /* Total size of the heap. */
+    size_t chunks_used;                /* Chunks allocated by the user. */
+    size_t bytes_used;         /* Byte total of user-allocated chunks. */
+    size_t chunks_free;                /* Chunks in the free list. */
+    size_t bytes_free;         /* Byte total of chunks in the free list. */
+  };
+
+/* Pick up the current statistics. */
+extern struct mstats mstats __P ((void));
+
+/* Call WARNFUN with a warning message when memory usage is high.  */
+extern void memory_warnings __P ((__ptr_t __start,
+                                 void (*__warnfun) __P ((__const char *))));
+
+
+/* Relocating allocator.  */
+
+/* Allocate SIZE bytes, and store the address in *HANDLEPTR.  */
+extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, size_t __size));
+
+/* Free the storage allocated in HANDLEPTR.  */
+extern void r_alloc_free __P ((__ptr_t *__handleptr));
+
+/* Adjust the block at HANDLEPTR to be SIZE bytes long.  */
+extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, size_t __size));
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* malloc.h  */
diff --git a/lib/malloclib/mcheck.c b/lib/malloclib/mcheck.c
new file mode 100644 (file)
index 0000000..f7d9d4f
--- /dev/null
@@ -0,0 +1,133 @@
+/* Standard debugging hooks for `malloc'.
+   Copyright 1990, 1991, 1992, 1993 Free Software Foundation
+   Written May 1989 by Mike Haertel.
+
+This 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.
+
+This 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 this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef        _MALLOC_INTERNAL
+#define        _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* Old hook values.  */
+static void (*old_free_hook) __P ((__ptr_t ptr));
+static __ptr_t (*old_malloc_hook) __P ((size_t size));
+static __ptr_t (*old_realloc_hook) __P ((__ptr_t ptr, size_t size));
+
+/* Function to call when something awful happens.  */
+static void (*abortfunc) __P ((void));
+
+/* Arbitrary magical numbers.  */
+#define MAGICWORD      0xfedabeeb
+#define MAGICBYTE      ((char) 0xd7)
+
+struct hdr
+  {
+    size_t size;               /* Exact size requested by user.  */
+    unsigned long int magic;   /* Magic number to check header integrity.  */
+  };
+
+static void checkhdr __P ((const struct hdr *));
+static void
+checkhdr (hdr)
+     const struct hdr *hdr;
+{
+  if (hdr->magic != MAGICWORD || ((char *) &hdr[1])[hdr->size] != MAGICBYTE)
+    (*abortfunc) ();
+}
+
+static void freehook __P ((__ptr_t));
+static void
+freehook (ptr)
+     __ptr_t ptr;
+{
+  struct hdr *hdr = ((struct hdr *) ptr) - 1;
+  checkhdr (hdr);
+  hdr->magic = 0;
+  __free_hook = old_free_hook;
+  free (hdr);
+  __free_hook = freehook;
+}
+
+static __ptr_t mallochook __P ((size_t));
+static __ptr_t
+mallochook (size)
+     size_t size;
+{
+  struct hdr *hdr;
+
+  __malloc_hook = old_malloc_hook;
+  hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1);
+  __malloc_hook = mallochook;
+  if (hdr == NULL)
+    return NULL;
+
+  hdr->size = size;
+  hdr->magic = MAGICWORD;
+  ((char *) &hdr[1])[size] = MAGICBYTE;
+  return (__ptr_t) (hdr + 1);
+}
+
+static __ptr_t reallochook __P ((__ptr_t, size_t));
+static __ptr_t
+reallochook (ptr, size)
+     __ptr_t ptr;
+     size_t size;
+{
+  struct hdr *hdr = ((struct hdr *) ptr) - 1;
+
+  checkhdr (hdr);
+  __free_hook = old_free_hook;
+  __malloc_hook = old_malloc_hook;
+  __realloc_hook = old_realloc_hook;
+  hdr = (struct hdr *) realloc ((__ptr_t) hdr, sizeof (struct hdr) + size + 1);
+  __free_hook = freehook;
+  __malloc_hook = mallochook;
+  __realloc_hook = reallochook;
+  if (hdr == NULL)
+    return NULL;
+
+  hdr->size = size;
+  ((char *) &hdr[1])[size] = MAGICBYTE;
+  return (__ptr_t) (hdr + 1);
+}
+
+int
+mcheck (func)
+     void (*func) __P ((void));
+{
+  extern void abort __P ((void));
+  static int mcheck_used = 0;
+
+  abortfunc = (func != NULL) ? func : abort;
+
+  /* These hooks may not be safely inserted if malloc is already in use.  */
+  if (!__malloc_initialized && !mcheck_used)
+    {
+      old_free_hook = __free_hook;
+      __free_hook = freehook;
+      old_malloc_hook = __malloc_hook;
+      __malloc_hook = mallochook;
+      old_realloc_hook = __realloc_hook;
+      __realloc_hook = reallochook;
+      mcheck_used = 1;
+    }
+
+  return mcheck_used ? 0 : -1;
+}
diff --git a/lib/malloclib/memalign.c b/lib/malloclib/memalign.c
new file mode 100644 (file)
index 0000000..f5ad17c
--- /dev/null
@@ -0,0 +1,61 @@
+/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+This 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.
+
+This 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 this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef        _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+__ptr_t
+memalign (alignment, size)
+     size_t alignment;
+     size_t size;
+{
+  __ptr_t result;
+  unsigned long int adj;
+
+  size = ((size + alignment - 1) / alignment) * alignment;
+
+  result = malloc (size);
+  if (result == NULL)
+    return NULL;
+  adj = (unsigned long int) ((unsigned long int) ((char *) result -
+                                               (char *) NULL)) % alignment;
+  if (adj != 0)
+    {
+      struct alignlist *l;
+      for (l = _aligned_blocks; l != NULL; l = l->next)
+       if (l->aligned == NULL)
+         /* This slot is free.  Use it.  */
+         break;
+      if (l == NULL)
+       {
+         l = (struct alignlist *) malloc (sizeof (struct alignlist));
+         if (l == NULL)
+           {
+             free (result);
+             return NULL;
+           }
+       }
+      l->exact = result;
+      result = l->aligned = (char *) result + alignment - adj;
+      l->next = _aligned_blocks;
+      _aligned_blocks = l;
+    }
+
+  return result;
+}
diff --git a/lib/malloclib/morecore.c b/lib/malloclib/morecore.c
new file mode 100644 (file)
index 0000000..c9a9ca5
--- /dev/null
@@ -0,0 +1,44 @@
+/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C 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 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the GNU C Library; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef        _MALLOC_INTERNAL
+#define        _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#ifndef        __GNU_LIBRARY__
+#define        __sbrk  sbrk
+#endif
+
+extern __ptr_t __sbrk __P ((int increment));
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Allocate INCREMENT more bytes of data space,
+   and return the start of data space, or NULL on errors.
+   If INCREMENT is negative, shrink data space.  */
+__ptr_t
+__default_morecore (increment)
+     ptrdiff_t increment;
+{
+  __ptr_t result = __sbrk ((int) increment);
+  if (result == (__ptr_t) -1)
+    return NULL;
+  return result;
+}
diff --git a/lib/malloclib/mstats.c b/lib/malloclib/mstats.c
new file mode 100644 (file)
index 0000000..511cdad
--- /dev/null
@@ -0,0 +1,39 @@
+/* Access the statistics maintained by `malloc'.
+   Copyright 1990, 1991, 1992 Free Software Foundation
+                 Written May 1989 by Mike Haertel.
+
+This 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.
+
+This 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 this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef        _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+struct mstats
+mstats ()
+{
+  struct mstats result;
+
+  result.bytes_total = (char *) (*__morecore) (0) - _heapbase;
+  result.chunks_used = _chunks_used;
+  result.bytes_used = _bytes_used;
+  result.chunks_free = _chunks_free;
+  result.bytes_free = _bytes_free;
+  return result;
+}
diff --git a/lib/malloclib/mtrace.awk b/lib/malloclib/mtrace.awk
new file mode 100644 (file)
index 0000000..d7689ce
--- /dev/null
@@ -0,0 +1,36 @@
+#
+#  Awk program to analyze mtrace.c output.
+#
+$1 == "+"      { if (allocated[$2] != "")
+                   print "+", $2, "Alloc", NR, "duplicate:", allocated[$2];
+                 else
+                   allocated[$2] = $3;
+               }
+$1 == "-"      { if (allocated[$2] != "") {
+                   allocated[$2] = "";
+                   if (allocated[$2] != "")
+                       print "DELETE FAILED", $2, allocated[$2];
+                 } else
+                   print "-", $2, "Free", NR, "was never alloc'd";
+               }
+$1 == "<"      { if (allocated[$2] != "")
+                   allocated[$2] = "";
+                 else
+                   print "-", $2, "Realloc", NR, "was never alloc'd";
+               }
+$1 == ">"      { if (allocated[$2] != "")
+                   print "+", $2, "Realloc", NR, "duplicate:", allocated[$2];
+                 else
+                   allocated[$2] = $3;
+               }
+
+# Ignore "= Start"
+$1 == "="      { }
+# Ignore failed realloc attempts for now
+$1 == "!"      { }
+
+
+END            { for (x in allocated) 
+                   if (allocated[x] != "")
+                     print "+", x, allocated[x];
+               }
diff --git a/lib/malloclib/mtrace.c b/lib/malloclib/mtrace.c
new file mode 100644 (file)
index 0000000..ea1d3a4
--- /dev/null
@@ -0,0 +1,150 @@
+/* More debugging hooks for `malloc'.
+   Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+                Written April 2, 1991 by John Gilmore of Cygnus Support.
+                Based on mcheck.c by Mike Haertel.
+
+This 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.
+
+This 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 this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef        _MALLOC_INTERNAL
+#define        _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+/* Don't #include <stdio.h> because <malloc.h> did it for us.  */
+
+#ifndef        __GNU_LIBRARY__
+extern char *getenv ();
+#else
+#include <stdlib.h>
+#endif
+
+static FILE *mallstream;
+static char mallenv[]= "MALLOC_TRACE";
+static char mallbuf[BUFSIZ];   /* Buffer for the output.  */
+
+/* Address to breakpoint on accesses to... */
+__ptr_t mallwatch;
+
+/* Old hook values.  */
+static void (*tr_old_free_hook) __P ((__ptr_t ptr));
+static __ptr_t (*tr_old_malloc_hook) __P ((size_t size));
+static __ptr_t (*tr_old_realloc_hook) __P ((__ptr_t ptr, size_t size));
+
+/* This function is called when the block being alloc'd, realloc'd, or
+   freed has an address matching the variable "mallwatch".  In a debugger,
+   set "mallwatch" to the address of interest, then put a breakpoint on
+   tr_break.  */
+
+void tr_break __P ((void));
+void
+tr_break ()
+{
+}
+
+static void tr_freehook __P ((__ptr_t));
+static void
+tr_freehook (ptr)
+     __ptr_t ptr;
+{
+  fprintf (mallstream, "- %p\n", ptr); /* Be sure to print it first.  */
+  if (ptr == mallwatch)
+    tr_break ();
+  __free_hook = tr_old_free_hook;
+  free (ptr);
+  __free_hook = tr_freehook;
+}
+
+static __ptr_t tr_mallochook __P ((size_t));
+static __ptr_t
+tr_mallochook (size)
+     size_t size;
+{
+  __ptr_t hdr;
+
+  __malloc_hook = tr_old_malloc_hook;
+  hdr = (__ptr_t) malloc (size);
+  __malloc_hook = tr_mallochook;
+
+  /* We could be printing a NULL here; that's OK.  */
+  fprintf (mallstream, "+ %p %x\n", hdr, size);
+
+  if (hdr == mallwatch)
+    tr_break ();
+
+  return hdr;
+}
+
+static __ptr_t tr_reallochook __P ((__ptr_t, size_t));
+static __ptr_t
+tr_reallochook (ptr, size)
+     __ptr_t ptr;
+     size_t size;
+{
+  __ptr_t hdr;
+
+  if (ptr == mallwatch)
+    tr_break ();
+
+  __free_hook = tr_old_free_hook;
+  __malloc_hook = tr_old_malloc_hook;
+  __realloc_hook = tr_old_realloc_hook;
+  hdr = (__ptr_t) realloc (ptr, size);
+  __free_hook = tr_freehook;
+  __malloc_hook = tr_mallochook;
+  __realloc_hook = tr_reallochook;
+  if (hdr == NULL)
+    /* Failed realloc.  */
+    fprintf (mallstream, "! %p %x\n", ptr, size);
+  else
+    fprintf (mallstream, "< %p\n> %p %x\n", ptr, hdr, size);
+
+  if (hdr == mallwatch)
+    tr_break ();
+
+  return hdr;
+}
+
+/* We enable tracing if either the environment variable MALLOC_TRACE
+   is set, or if the variable mallwatch has been patched to an address
+   that the debugging user wants us to stop on.  When patching mallwatch,
+   don't forget to set a breakpoint on tr_break!  */
+
+void
+mtrace ()
+{
+  char *mallfile;
+
+  mallfile = getenv (mallenv);
+  if (mallfile != NULL || mallwatch != NULL)
+    {
+      mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w");
+      if (mallstream != NULL)
+       {
+         /* Be sure it doesn't malloc its buffer!  */
+         setbuf (mallstream, mallbuf);
+         fprintf (mallstream, "= Start\n");
+         tr_old_free_hook = __free_hook;
+         __free_hook = tr_freehook;
+         tr_old_malloc_hook = __malloc_hook;
+         __malloc_hook = tr_mallochook;
+         tr_old_realloc_hook = __realloc_hook;
+         __realloc_hook = tr_reallochook;
+       }
+    }
+}
diff --git a/lib/malloclib/realloc.c b/lib/malloclib/realloc.c
new file mode 100644 (file)
index 0000000..2d31766
--- /dev/null
@@ -0,0 +1,146 @@
+/* Change the size of a block allocated by `malloc'.
+   Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+                    Written May 1989 by Mike Haertel.
+
+This 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.
+
+This 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 this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef        _MALLOC_INTERNAL
+#define _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#define min(A, B) ((A) < (B) ? (A) : (B))
+
+/* Debugging hook for realloc.  */
+__ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
+
+/* Resize the given region to the new size, returning a pointer
+   to the (possibly moved) region.  This is optimized for speed;
+   some benchmarks seem to indicate that greater compactness is
+   achieved by unconditionally allocating and copying to a
+   new region.  This module has incestuous knowledge of the
+   internals of both free and malloc. */
+__ptr_t
+realloc (ptr, size)
+     __ptr_t ptr;
+     size_t size;
+{
+  __ptr_t result;
+  int type;
+  size_t block, blocks, oldlimit;
+
+  if (size == 0)
+    {
+      free (ptr);
+      return malloc (0);
+    }
+  else if (ptr == NULL)
+    return malloc (size);
+
+  if (__realloc_hook != NULL)
+    return (*__realloc_hook) (ptr, size);
+
+  block = BLOCK (ptr);
+
+  type = _heapinfo[block].busy.type;
+  switch (type)
+    {
+    case 0:
+      /* Maybe reallocate a large block to a small fragment.  */
+      if (size <= BLOCKSIZE / 2)
+       {
+         result = malloc (size);
+         if (result != NULL)
+           {
+             memcpy (result, ptr, size);
+             free (ptr);
+             return result;
+           }
+       }
+
+      /* The new size is a large allocation as well;
+        see if we can hold it in place. */
+      blocks = BLOCKIFY (size);
+      if (blocks < _heapinfo[block].busy.info.size)
+       {
+         /* The new size is smaller; return
+            excess memory to the free list. */
+         _heapinfo[block + blocks].busy.type = 0;
+         _heapinfo[block + blocks].busy.info.size
+           = _heapinfo[block].busy.info.size - blocks;
+         _heapinfo[block].busy.info.size = blocks;
+         free (ADDRESS (block + blocks));
+         result = ptr;
+       }
+      else if (blocks == _heapinfo[block].busy.info.size)
+       /* No size change necessary.  */
+       result = ptr;
+      else
+       {
+         /* Won't fit, so allocate a new region that will.
+            Free the old region first in case there is sufficient
+            adjacent free space to grow without moving. */
+         blocks = _heapinfo[block].busy.info.size;
+         /* Prevent free from actually returning memory to the system.  */
+         oldlimit = _heaplimit;
+         _heaplimit = 0;
+         free (ptr);
+         _heaplimit = oldlimit;
+         result = malloc (size);
+         if (result == NULL)
+           {
+             /* Now we're really in trouble.  We have to unfree
+                the thing we just freed.  Unfortunately it might
+                have been coalesced with its neighbors.  */
+             if (_heapindex == block)
+               (void) malloc (blocks * BLOCKSIZE);
+             else
+               {
+                 __ptr_t previous = malloc ((block - _heapindex) * BLOCKSIZE);
+                 (void) malloc (blocks * BLOCKSIZE);
+                 free (previous);
+               }
+             return NULL;
+           }
+         if (ptr != result)
+           memmove (result, ptr, blocks * BLOCKSIZE);
+       }
+      break;
+
+    default:
+      /* Old size is a fragment; type is logarithm
+        to base two of the fragment size.  */
+      if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))
+       /* The new size is the same kind of fragment.  */
+       result = ptr;
+      else
+       {
+         /* The new size is different; allocate a new space,
+            and copy the lesser of the new size and the old. */
+         result = malloc (size);
+         if (result == NULL)
+           return NULL;
+         memcpy (result, ptr, min (size, (size_t) 1 << type));
+         free (ptr);
+       }
+      break;
+    }
+
+  return result;
+}
diff --git a/lib/malloclib/valloc.c b/lib/malloclib/valloc.c
new file mode 100644 (file)
index 0000000..eb5d372
--- /dev/null
@@ -0,0 +1,48 @@
+/* Allocate memory on a page boundary.
+   Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This 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.
+
+This 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 this library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+   The author may be reached (Email) at the address mike@ai.mit.edu,
+   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+
+#ifndef        _MALLOC_INTERNAL
+#define        _MALLOC_INTERNAL
+#include <malloc.h>
+#endif
+
+#if defined (emacs) || defined (HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#ifdef __GNU_LIBRARY__
+extern size_t __getpagesize __P ((void));
+#else
+#include "getpagesize.h"
+#define         __getpagesize()        getpagesize()
+#endif
+
+static size_t pagesize;
+
+__ptr_t
+valloc (size)
+     size_t size;
+{
+  if (pagesize == 0)
+    pagesize = __getpagesize ();
+
+  return memalign (pagesize, size);
+}
diff --git a/lib/malloclib/x386-alloca.s b/lib/malloclib/x386-alloca.s
new file mode 100644 (file)
index 0000000..112d33c
--- /dev/null
@@ -0,0 +1,63 @@
+;; alloca386.s 1.2
+;; GNU-compatible stack allocation function for Xenix/386.
+;; Written by Chip Salzenberg at ComDev.
+;; Last modified 90/01/11
+;;> Is your alloca clearly better than the one in i386-alloca.s?  I haven't
+;;> looked at either.
+;;
+;;They're different because Xenix/386 has a different assembler.  SCO
+;;Xenix has the Microsoft C compiler and the Microsoft macro assembler,
+;;called "masm".  MASM's assembler syntax is quite different from AT&T's
+;;in all sorts of ways.  Xenix people can't use the AT&T version.
+;;-- 
+;;Chip Salzenberg at ComDev/TCT     <chip@tct.uucp>, <uunet!ateng!tct!chip>
+
+       TITLE   $alloca386
+
+       .386
+DGROUP GROUP   CONST, _BSS, _DATA
+_DATA  SEGMENT  DWORD USE32 PUBLIC 'DATA'
+_DATA      ENDS
+_BSS   SEGMENT  DWORD USE32 PUBLIC 'BSS'
+_BSS      ENDS
+CONST  SEGMENT  DWORD USE32 PUBLIC 'CONST'
+CONST      ENDS
+_TEXT  SEGMENT  DWORD USE32 PUBLIC 'CODE'
+       ASSUME   CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
+
+       PUBLIC  _alloca
+_alloca PROC NEAR
+
+; Get argument.
+       pop     edx             ; edx -> return address
+       pop     eax             ; eax = amount to allocate
+
+; Validate allocation amount.
+       add     eax,3
+       and     eax,not 3
+       cmp     eax,0
+       jg      aa_size_ok
+       mov     eax,4
+aa_size_ok:
+
+; Allocate stack space.
+       mov     ecx,esp         ; ecx -> old stack pointer
+       sub     esp,eax         ; perform allocation
+       mov     eax,esp         ; eax -> new stack pointer
+
+; Copy the three saved register variables from old stack top to new stack top.
+; They may not be there.  So we waste twelve bytes.  Big fat hairy deal.
+       push    DWORD PTR 8[ecx]
+       push    DWORD PTR 4[ecx]
+       push    DWORD PTR 0[ecx]
+
+; Push something so the caller can pop it off.
+       push    eax
+
+; Return to caller.
+       jmp     edx
+
+_alloca ENDP
+
+_TEXT   ENDS
+       END
diff --git a/lib/malloclib/xmalloc.c b/lib/malloclib/xmalloc.c
new file mode 100644 (file)
index 0000000..a25cb11
--- /dev/null
@@ -0,0 +1,69 @@
+/* xmalloc.c -- safe versions of malloc and realloc */
+
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Readline, a library for reading lines
+   of text with interactive input and history editing.
+
+   Readline is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 1, or (at your option) any
+   later version.
+
+   Readline is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+static void memory_error_and_abort ();
+
+/* **************************************************************** */
+/*                                                                 */
+/*                Memory Allocation and Deallocation.              */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Return a pointer to free()able block of memory large enough
+   to hold BYTES number of bytes.  If the memory cannot be allocated,
+   print an error message and abort. */
+char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ("xmalloc");
+  return (temp);
+}
+
+char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ("xrealloc");
+  return (temp);
+}
+
+static void
+memory_error_and_abort (fname)
+     char *fname;
+{
+  fprintf (stderr, "%s: Out of virtual memory!\n", fname);
+  abort ();
+}
diff --git a/lib/posixheaders/ansi_stdlib.h b/lib/posixheaders/ansi_stdlib.h
new file mode 100644 (file)
index 0000000..52339da
--- /dev/null
@@ -0,0 +1,41 @@
+/* ansi_stdlib.h -- An ANSI Standard stdlib.h. */
+/* A minimal stdlib.h containing extern declarations for those functions
+   that bash uses. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_STDLIB_H_)
+#define        _STDLIB_H_ 1
+
+/* String conversion functions. */
+extern int atoi ();
+extern long int atol ();
+
+/* Memory allocation functions. */
+extern char *malloc ();
+extern char *realloc ();
+extern void free ();
+
+/* Other miscellaneous functions. */
+extern void abort ();
+extern void exit ();
+extern char *getenv ();
+extern void qsort ();
+
+#endif /* _STDLIB_H  */
diff --git a/lib/posixheaders/filecntl.h b/lib/posixheaders/filecntl.h
new file mode 100644 (file)
index 0000000..c0b2081
--- /dev/null
@@ -0,0 +1,36 @@
+/* filecntl.h - Definitions to set file descriptors to close-on-exec. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_FILECNTL_H_)
+#define _FILECNTL_H_
+
+#include <fcntl.h>
+
+/* Definitions to set file descriptors to close-on-exec, the Posix way. */
+#if !defined (FD_CLOEXEC)
+#define FD_CLOEXEC     1
+#endif
+
+#define FD_NCLOEXEC    0
+
+#define SET_CLOSE_ON_EXEC(fd)  (fcntl ((fd), F_SETFD, FD_CLOEXEC))
+#define SET_OPEN_ON_EXEC(fd)   (fcntl ((fd), F_SETFD, FD_NCLOEXEC))
+
+#endif /* ! _FILECNTL_H_ */
diff --git a/lib/posixheaders/memalloc.h b/lib/posixheaders/memalloc.h
new file mode 100644 (file)
index 0000000..750d53d
--- /dev/null
@@ -0,0 +1,56 @@
+/* memalloc.h -- consolidate code for including alloca.h or malloc.h and
+   defining alloca. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (__MEMALLOC_H__)
+#  define __MEMALLOC_H__
+
+#if defined (sparc) && defined (sun) && !defined (HAVE_ALLOCA_H)
+#  define HAVE_ALLOCA_H
+#endif
+
+#if defined (__GNUC__) && !defined (HAVE_ALLOCA)
+#  define HAVE_ALLOCA
+#endif
+
+#if defined (HAVE_ALLOCA_H) && !defined (HAVE_ALLOCA)
+#  define HAVE_ALLOCA
+#endif /* HAVE_ALLOCA_H && !HAVE_ALLOCA */
+
+#if !defined (BUILDING_MAKEFILE)
+
+#if defined (__GNUC__)
+#  undef alloca
+#  define alloca __builtin_alloca
+#else /* !__GNUC__ */
+#  if defined (HAVE_ALLOCA_H)
+#    if defined (IBMESA)
+#      include <malloc.h>
+#    else /* !IBMESA */
+#      include <alloca.h>
+#    endif /* !IBMESA */
+#  else
+extern char *alloca ();
+#  endif /* !HAVE_ALLOCA_H */
+#endif /* !__GNUC__ */
+
+#endif /* !BUILDING_MAKEFILE */
+
+#endif /* __MEMALLOC_H__ */
diff --git a/lib/posixheaders/posixstat.h b/lib/posixheaders/posixstat.h
new file mode 100644 (file)
index 0000000..7d1cece
--- /dev/null
@@ -0,0 +1,149 @@
+/* posixstat.h -- Posix stat(2) definitions for systems that
+   don't have them. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This file should be included instead of <sys/stat.h>.
+   It relies on the local sys/stat.h to work though. */
+#if !defined (_POSIXSTAT_H)
+#define _POSIXSTAT_H
+
+#include <sys/stat.h>
+
+#if defined (isc386)
+#  if !defined (S_IFDIR)
+#    define S_IFDIR 0040000
+#  endif /* !S_IFDIR */
+#  if !defined (S_IFMT)
+#    define S_IFMT  0170000
+#  endif /* !S_IFMT */
+#endif /* isc386 */
+
+/* This text is taken directly from the Cadmus I was trying to
+   compile on:
+    the following MACROs are defined for X/OPEN compatibility
+    however, is the param correct ??
+   #define S_ISBLK(s) ((s.st_mode & S_IFMT) == S_IFBLK)
+
+  Well, the answer is no.  Thus... */
+#if defined (BrainDeath)
+#  undef S_ISBLK
+#  undef S_ISCHR
+#  undef S_ISDIR
+#  undef S_ISFIFO
+#  undef S_ISREG
+#endif /* BrainDeath */
+
+/* Posix 1003.1 5.6.1.1 <sys/stat.h> file types */
+
+/* Some Posix-wannabe systems define _S_IF* macros instead of S_IF*, but
+   do not provide the S_IS* macros that Posix requires. */
+
+#if defined (_S_IFMT) && !defined (S_IFMT)
+#define S_IFMT _S_IFMT
+#endif
+#if defined (_S_IFIFO) && !defined (S_IFIFO)
+#define S_IFIFO _S_IFIFO
+#endif
+#if defined (_S_IFCHR) && !defined (S_IFCHR)
+#define S_IFCHR _S_IFCHR
+#endif
+#if defined (_S_IFDIR) && !defined (S_IFDIR)
+#define S_IFDIR _S_IFDIR
+#endif
+#if defined (_S_IFBLK) && !defined (S_IFBLK)
+#define S_IFBLK _S_IFBLK
+#endif
+#if defined (_S_IFREG) && !defined (S_IFREG)
+#define S_IFREG _S_IFREG
+#endif
+#if defined (_S_IFLNK) && !defined (S_IFLNK)
+#define S_IFLNK _S_IFLNK
+#endif
+#if defined (_S_IFSOCK) && !defined (S_IFSOCK)
+#define S_IFSOCK _S_IFSOCK
+#endif
+
+/* Test for each symbol individually and define the ones necessary (some
+   systems claiming Posix compatibility define some but not all). */
+
+#if defined (S_IFBLK) && !defined (S_ISBLK)
+#define        S_ISBLK(m)      (((m)&S_IFMT) == S_IFBLK)       /* block device */
+#endif
+
+#if defined (S_IFCHR) && !defined (S_ISCHR)
+#define        S_ISCHR(m)      (((m)&S_IFMT) == S_IFCHR)       /* character device */
+#endif
+
+#if defined (S_IFDIR) && !defined (S_ISDIR)
+#define        S_ISDIR(m)      (((m)&S_IFMT) == S_IFDIR)       /* directory */
+#endif
+
+#if defined (S_IFREG) && !defined (S_ISREG)
+#define        S_ISREG(m)      (((m)&S_IFMT) == S_IFREG)       /* file */
+#endif
+
+#if defined (S_IFIFO) && !defined (S_ISFIFO)
+#define        S_ISFIFO(m)     (((m)&S_IFMT) == S_IFIFO)       /* fifo - named pipe */
+#endif
+
+#if defined (S_IFLNK) && !defined (S_ISLNK)
+#define        S_ISLNK(m)      (((m)&S_IFMT) == S_IFLNK)       /* symbolic link */
+#endif
+
+#if defined (S_IFSOCK) && !defined (S_ISSOCK)
+#define        S_ISSOCK(m)     (((m)&S_IFMT) == S_IFSOCK)      /* socket */
+#endif
+
+/*
+ * POSIX 1003.1 5.6.1.2 <sys/stat.h> File Modes
+ */
+#if !defined (S_IRWXU)
+#  if !defined (S_IREAD)
+#    define S_IREAD    00400
+#    define S_IWRITE   00200
+#    define S_IEXEC    00100
+#  endif /* S_IREAD */
+
+#  if !defined (S_IRUSR)
+#    define S_IRUSR    S_IREAD                 /* read, owner */
+#    define S_IWUSR    S_IWRITE                /* write, owner */
+#    define S_IXUSR    S_IEXEC                 /* execute, owner */
+
+#    define S_IRGRP    (S_IREAD  >> 3)         /* read, group */
+#    define S_IWGRP    (S_IWRITE >> 3)         /* write, group */
+#    define S_IXGRP    (S_IEXEC  >> 3)         /* execute, group */
+
+#    define S_IROTH    (S_IREAD  >> 6)         /* read, other */
+#    define S_IWOTH    (S_IWRITE >> 6)         /* write, other */
+#    define S_IXOTH    (S_IEXEC  >> 6)         /* execute, other */
+#  endif /* !S_IRUSR */
+
+#  define S_IRWXU      (S_IRUSR | S_IWUSR | S_IXUSR)
+#  define S_IRWXG      (S_IRGRP | S_IWGRP | S_IXGRP)
+#  define S_IRWXO      (S_IROTH | S_IWOTH | S_IXOTH)
+#endif /* !S_IRWXU */
+
+/* These are non-standard, but are used in builtins.c$symbolic_umask() */
+#define S_IRUGO                (S_IRUSR | S_IRGRP | S_IROTH)
+#define S_IWUGO                (S_IWUSR | S_IWGRP | S_IWOTH)
+#define S_IXUGO                (S_IXUSR | S_IXGRP | S_IXOTH)
+
+#endif /* _POSIXSTAT_H */
diff --git a/lib/posixheaders/stdc.h b/lib/posixheaders/stdc.h
new file mode 100644 (file)
index 0000000..5dcc32b
--- /dev/null
@@ -0,0 +1,78 @@
+/* stdc.h -- macros to make source compile on both ANSI C and K&R C
+   compilers. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (__STDC_H__)
+#define __STDC_H__
+
+/* Adapted from BSD /usr/include/sys/cdefs.h. */
+
+/* A function can be defined using prototypes and compile on both ANSI C
+   and traditional C compilers with something like this:
+       extern char *func __P((char *, char *, int)); */
+#if defined (__STDC__)
+
+#  if !defined (__P)
+#    define __P(protos) protos
+#  endif
+#  define __STRING(x) #x
+
+#  if !defined (__GNUC__)
+#    define inline
+#  endif
+
+#else /* !__STDC__ */
+
+#  if !defined (__P)
+#    define __P(protos) ()
+#  endif
+#  define __STRING(x) "x"
+
+#if defined (__GNUC__)         /* gcc with -traditional */
+#  if !defined (const)
+#    define const  __const
+#  endif
+#  if !defined (inline)
+#    define inline __inline
+#  endif
+#  if !defined (signed)
+#    define signed __signed
+#  endif
+#  if !defined (volatile)
+#    define volatile __volatile
+#  endif
+#else /* !__GNUC__ */
+#  if !defined (const)
+#    define const
+#  endif
+#  if !defined (inline)
+#    define inline
+#  endif
+#  if !defined (signed)
+#    define signed
+#  endif
+#  if !defined (volatile)
+#    define volatile
+#  endif
+#endif /* !__GNUC__ */
+
+#endif /* !__STDC__ */
+
+#endif /* !__STDC_H__ */
diff --git a/lib/readline/COPYING b/lib/readline/COPYING
new file mode 100644 (file)
index 0000000..1bb82d1
--- /dev/null
@@ -0,0 +1,257 @@
+
+                   GNU GENERAL PUBLIC LICENSE
+                    Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+                   675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+The Free Software Foundation has exempted Bash from the requirement of
+Paragraph 2c of the General Public License.  This is to say, there is
+no requirement for Bash to print a notice when it is started
+interactively in the usual way.         We made this exception because users
+and standards expect shells not to print such messages.         This
+exception applies to any program that serves as a shell and that is
+based primarily on Bash as opposed to other GNU software.
+
+                           Preamble
+
+  The license agreements of most software companies try to keep users
+at the mercy of those companies.  By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must tell them their rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License.  The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications.  Each
+licensee is addressed as "you".
+
+  1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program.         You may charge a fee for the physical act of
+transferring a copy.
+
+  2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+    a) cause the modified files to carry prominent notices stating that
+    you changed the files and the date of any change; and
+
+    b) cause the whole of any work that you distribute or publish, that
+    in whole or in part contains the Program or any part thereof, either
+    with or without modifications, to be licensed at no charge to all
+    third parties under the terms of this General Public License (except
+    that you may choose to grant warranty protection to some or all
+    third parties, at your option).
+
+    c) If the modified program normally reads commands interactively when
+    run, you must cause it, when started running for such interactive use
+    in the simplest and most usual way, to print or display an
+    announcement including an appropriate copyright notice and a notice
+    that there is no warranty (or else, saying that you provide a
+    warranty) and that users may redistribute the program under these
+    conditions, and telling the user how to view a copy of this General
+    Public License.
+
+    d) You may charge a fee for the physical act of transferring a
+    copy, and you may at your option offer warranty protection in
+    exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+\f
+  3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+    a) accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    b) accompany it with a written offer, valid for at least three
+    years, to give any third party free (except for a nominal charge
+    for the cost of distribution) a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    c) accompany it with the information you received as to where the
+    corresponding source code may be obtained. (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it.  For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+  4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License.         However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+  5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions.  You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+\f
+  7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+  8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+  To do so, attach the following notices to the program.  It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy <name of author>
+
+    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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19xx name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License.  Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  program `Gnomovision' (a program to direct compilers to make passes
+  at assemblers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/lib/readline/ChangeLog b/lib/readline/ChangeLog
new file mode 100644 (file)
index 0000000..1cf0c00
--- /dev/null
@@ -0,0 +1,403 @@
+Tue Mar 23 14:36:51 1993  Brian Fox  (bfox@eos.crseo.ucsb.edu)
+
+       * readline.c (rl_copy): Changed name to rl_copy_text.
+
+Mon Mar 22 19:16:05 1993  Brian Fox  (bfox@eos.crseo.ucsb.edu)
+
+       * dispose_cmd.c, several other files. Declare dispose_xxx () as
+       "void".
+
+       * builtins/hashcom.h: Make declarations of hashed_filenames be
+       "extern" to keep the SGI compiler happy.
+
+       * readline.c (rl_initialize_everything): Assign values to
+       out_stream and in_stream immediately, since
+       output_character_function () can be called before
+       readline_internal () is called.
+
+Tue Dec  8 09:30:56 1992  Brian Fox  (bfox@cubit)
+
+       * readline.c (rl_init_terminal) Set PC from BC, not from *buffer.
+
+Mon Nov 30 09:35:47 1992  Brian Fox  (bfox@cubit)
+
+       * readline.c (invoking_keyseqs_in_map, rl_parse_and_bind) Allow
+       backslash to quote characters, such as backslash, double quote,
+       and space. Backslash quotes all character indiscriminately.
+
+       * funmap.c (vi_keymap) Fix type in "vi-replace" declaration.
+
+Fri Nov 20 10:55:05 1992  Brian Fox  (bfox@cubit)
+
+       * readline.c (init_terminal_io, rl_prep_terminal): FINALLY!
+       Declare and use termcap variable `ospeed' when setting up terminal
+       parameters.
+
+Thu Oct  8 08:53:07 1992  Brian J. Fox  (bfox@helios)
+
+       * Makefile, this directory: Include (as links to the canonical
+       sources), tilde.c, tilde.h, posixstat.h and xmalloc.c.
+
+Tue Sep 29 13:07:21 1992  Brian J. Fox  (bfox@helios)
+
+       * readline.c (init_terminal_io) Don't set arrow keys if the key
+       sequences that represent them are already set.
+
+       * readline.c (rl_function_of_keyseq) New function returns the first
+       function (or macro) found while searching a key sequence.
+
+Mon Sep 28 00:34:04 1992  Brian J. Fox  (bfox@helios)
+
+       * readline.c (LibraryVersion) New static char * contains current
+       version number.  Version is at 2.0.
+
+       * readline.c (rl_complete_internal): Incorporated clean changes
+       from gilmore (gnu@cygnus.com) to support quoted substrings within
+       completion functions.
+
+       * readline.c (many locations) Added support for the _GO32_,
+       whatever that is.  Patches supplied by Cygnus, typed in by hand,
+       with cleanups.
+
+Sun Aug 16 12:46:24 1992  Brian Fox  (bfox@cubit)
+
+       * readline.c (init_terminal_io): Find out the values of the keypad
+       arrows and bind them to appropriate RL functions if present.
+
+Mon Aug 10 18:13:24 1992  Brian Fox  (bfox@cubit)
+
+       * history.c (stifle_history): A negative argument to stifle
+       becomes zero.
+
+Tue Jul 28 09:28:41 1992  Brian Fox  (bfox@cubit)
+
+       * readline.c (rl_variable_bind): New local structure describes
+       booleans by name and address; code in rl_variable_bind () looks at
+       structure to set simple variables.
+
+       * parens.c (rl_insert_close): New variable rl_blink_matching_paren
+       is non-zero if we want to blink the matching open when a close is
+       inserted.  If FD_SET is defined, rl_blink_matching_paren defaults
+       to 1, else 0.  If FD_SET is not defined, and
+       rl_blink_matching_paren is non-zero, the close character(s) are/is
+       simply inserted.
+
+Wed Jul 22 20:03:59 1992  Brian Fox  (bfox@cubit)
+
+       * history.c, readline.c, vi_mode.c: Cause the functions strchr ()
+       and strrchr () to be used instead of index () and rindex ()
+       throughout the source.
+
+Mon Jul 13 11:34:07 1992  Brian Fox  (bfox@cubit)
+
+       * readline.c: (rl_variable_bind) New variable "meta-flag" if "on"
+       means force the use of the 8th bit as Meta bit.  Internal variable
+       is called meta_flag.
+
+Thu Jul  9 10:37:56 1992  Brian Fox  (bfox@cubit)
+
+       * history.c (get_history_event) Change INDEX to LOCAL_INDEX.  If
+       compiling for the shell, allow shell metacharacters to separate
+       history tokens as they would for shell tokens.
+
+Sat Jul  4 19:29:12 1992  Brian Fox  (bfox@cubit)
+
+       * vi_keymap.c: According to Posix, TAB self-inserts instead of
+       doing completion.
+
+       * vi_mode.c: (rl_vi_yank_arg) Enter VI insert mode after yanking
+       an arg from the previous line.
+
+       * search.c: New file takes over vi style searching and implements
+       non-incremental searching the history.
+
+       Makefile: Add search.c and search.o.
+
+       funmap.c: Add names for non-incremental-forward-search-history and
+       non-incremental-reverse-search-history.
+
+       readline.h: Add extern definitions for non-incremental searching.
+
+       vi_mode.c: Remove old search code; add calls to code in search.c.
+
+Fri Jul  3 10:36:33 1992  Brian Fox  (bfox@cubit)
+
+       * readline.c (rl_delete_horizontal_space); New function deletes
+       all whitespace surrounding point.
+
+       funmap.c: Add "delete-horizontal-space".
+       emacs_keymap.c: Put rl_delete_horizontal_space () on M-\.
+
+       * readline.c (rl_set_signals, rl_clear_signals); New function
+       rl_set_sighandler () is either defined in a Posix way (if
+       HAVE_POSIX_SIGNALS is defined) or in a BSD way.  Function is
+       called from rl_set_signals () and rl_clear_signals ().
+
+Fri May  8 12:50:15 1992  Brian Fox  (bfox@cubit)
+
+       * readline.c: (readline_default_bindings) Do comparisons with
+       _POSIX_VDISABLE casted to `unsigned char'.  Change tty characters
+       to be unsigned char.
+
+Thu Apr 30 12:36:35 1992  Brian Fox  (bfox@cubit)
+
+       * readline.c: (rl_getc) Handle "read would block" error on
+       non-blocking IO streams.
+
+       * readline.c: (rl_signal_handler): Unblock only the signal that we
+       have caught, not all signals.
+
+Sun Feb 23 03:33:09 1992  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c: Many functions.  Use only the macros META_CHAR and
+       UNMETA to deal with meta characters.  Prior to this, we used
+       numeric values and tests.
+
+       * readline.c (rl_complete_internal) Report exactly the number of
+       possible completions, not the number + 1.
+
+       * vi_mode.c (rl_do_move) Do not change the cursor position when
+       using `cw' or `cW'.
+
+       * vi_mode.c (rl_vi_complete) Enter insert mode after completing
+       with `*' or `\'.
+
+Fri Feb 21 05:58:18 1992  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c (rl_dispatch) Increment rl_key_sequence_length for
+       meta characters that map onto ESC map.
+
+Mon Feb 10 01:41:35 1992  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * history.c (history_do_write) Build a buffer of all of the lines
+       to write and write them in one fell swoop (lower overhead than
+       calling write () for each line).  Suggested by Peter Ho.
+
+       * readline.c: Include hbullx20 as well as hpux for determining
+       USGr3ness.
+
+       * readline.c (rl_unix_word_rubout) As per the "Now REMEMBER"
+       comment, pass arguments to rl_kill_text () in the correct order to
+       preserve prepending and appending of killed text.
+
+       * readline.c (rl_search_history) malloc (), realloc (), and free
+       () SEARCH_STRING so that there are no static limits on searching.
+
+       * vi_mode.c (rl_vi_subst) Don't forget to end the undo group.
+
+Fri Jan 31 14:51:02 1992  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c (rl_signal_handler): Zero the current history entry's
+       pointer after freeing the undo_list when SIGINT received.
+       Reformat a couple of functions.
+
+Sat Jan 25 13:47:35 1992  Brian Fox  (bfox at bears)
+
+        * readline.c (parser_if): free () TNAME after use.
+
+Tue Jan 21 01:01:35 1992  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c (rl_redisplay) and (rl_character_len): Display
+       Control characters as "^c" and Meta characters as "\234", instead
+       of "C-C" and "M-C".
+
+Sun Dec 29 10:59:00 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c (init_terminal_io) Default to environment variables
+       LINES and COLUMNS before termcap entry values.  If all else fails,
+       then assume 80x24 terminal.
+
+Sat Dec 28 16:33:11 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c: If this machine is USG and it is hpux, then define
+       USGr3.
+
+       * history.c: Cosmetic fixes.
+
+Thu Nov 21 00:10:12 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * vi_mode.c: (rl_do_move) Place cursor at end of line, never at
+       next to last character.
+
+Thu Nov 14 05:08:01 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * history.c (get_history_event) Non-anchored searches can have a
+       return index of greater than zero from get_history_event ().
+
+Fri Nov  1 07:02:13 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c (rl_translate_keyseq) Make C-? translate to RUBOUT
+       unconditionally.
+
+Mon Oct 28 11:34:52 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c; Use Posix directory routines and macros.
+
+       * funmap.c; Add entry for call-last-kbd-macro.
+
+       * readline.c (rl_prep_term); Use system EOF character on POSIX
+       systems also.
+
+Thu Oct  3 16:19:53 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c; Make a distinction between having a TERMIOS tty
+       driver, and having POSIX signal handling.  You might one without
+       the other.  New defines used HAVE_POSIX_SIGNALS, and
+       TERMIOS_TTY_DRIVER.
+
+Tue Jul 30 22:37:26 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c: rl_getc () If a call to read () returns without an
+       error, but with zero characters, the file is empty, so return EOF.
+
+Thu Jul 11 20:58:38 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c: (rl_get_next_history, rl_get_previous_history)
+       Reallocate the buffer space if the line being moved to is longer
+       the the current space allocated.  Amazing that no one has found
+       this bug until now.
+
+Sun Jul  7 02:37:05 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c:(rl_parse_and_bind) Allow leading whitespace.
+         Make sure TERMIO and TERMIOS systems treat CR and NL
+         disctinctly.
+       
+Tue Jun 25 04:09:27 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c: Rework parsing conditionals to pay attention to the
+       prior states of the conditional stack.  This makes $if statements
+       work correctly.
+
+Mon Jun 24 20:45:59 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c: support for displaying key binding information
+       includes the functions rl_list_funmap_names (),
+       invoking_keyseqs_in_map (), rl_invoking_keyseqs (),
+       rl_dump_functions (), and rl_function_dumper ().
+
+       funmap.c: support for same includes rl_funmap_names ().
+
+       readline.c, funmap.c: no longer define STATIC_MALLOC.  However,
+       update both version of xrealloc () to handle a null pointer.
+
+Thu Apr 25 12:03:49 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * vi_mode.c (rl_vi_fword, fWord, etc.  All functions use
+       the macro `isident()'.  Fixed movement bug which prevents
+       continious movement through the text.
+
+Fri Jul 27 16:47:01 1990  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c (parser_if) Allow "$if term=foo" construct.
+
+Wed May 23 16:10:33 1990  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c (rl_dispatch) Correctly remember the last command
+       executed.  Fixed typo in username_completion_function ().
+
+Mon Apr  9 19:55:48 1990  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c: username_completion_function (); For text passed in
+       with a leading `~', remember that this could be a filename (after
+       it is completed).
+
+Thu Apr  5 13:44:24 1990  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c: rl_search_history (): Correctly handle case of an
+       unfound search string, but a graceful exit (as with ESC).
+
+       * readline.c: rl_restart_output ();  The Apollo passes the address
+       of the file descriptor to TIOCSTART, not the descriptor itself.
+
+Tue Mar 20 05:38:55 1990  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * readline.c: rl_complete (); second call in a row causes possible
+       completions to be listed.
+
+       * readline.c: rl_redisplay (), added prompt_this_line variable
+       which is the first character character following \n in prompt.
+
+Sun Mar 11 04:32:03 1990  Brian Fox  (bfox at gnuwest.fsf.org)
+
+       * Signals are now supposedly handled inside of SYSV compilation.
+
+Wed Jan 17 19:24:09 1990  Brian Fox  (bfox at sbphy.ucsb.edu)
+
+       * history.c: history_expand (); fixed overwriting memory error,
+       added needed argument to call to get_history_event ().
+
+Thu Jan 11 10:54:04 1990  Brian Fox  (bfox at sbphy.ucsb.edu)
+
+       * readline.c: added mark_modified_lines to control the
+       display of an asterisk on modified history lines.  Also
+       added a user variable called mark-modified-lines to the
+       `set' command.
+
+Thu Jan  4 10:38:05 1990  Brian Fox  (bfox at sbphy.ucsb.edu)
+
+       * readline.c: start_insert ().  Only use IC if we don't have an im
+       capability.
+
+Fri Sep  8 09:00:45 1989  Brian Fox  (bfox at aurel)
+
+       * readline.c: rl_prep_terminal ().  Only turn on 8th bit
+         as meta-bit iff the terminal is not using parity.
+
+Sun Sep  3 08:57:40 1989  Brian Fox  (bfox at aurel)
+
+       * readline.c: start_insert ().  Uses multiple
+         insertion call in cases where that makes sense.
+
+         rl_insert ().  Read type-ahead buffer for additional
+         keys that are bound to rl_insert, and insert them
+         all at once.  Make insertion of single keys given
+         with an argument much more efficient.
+
+Tue Aug  8 18:13:57 1989  Brian Fox  (bfox at aurel)
+
+       * readline.c: Changed handling of EOF.  readline () returns
+        (char *)EOF or consed string.  The EOF character is read from the
+        tty, or if the tty doesn't have one, defaults to C-d.
+
+       * readline.c: Added support for event driven programs.
+         rl_event_hook is the address of a function you want called
+         while Readline is waiting for input.
+
+       * readline.c: Cleanup time.  Functions without type declarations
+         do not use return with a value.
+
+       * history.c: history_expand () has new variable which is the
+         characters to ignore immediately following history_expansion_char.
+
+Sun Jul 16 08:14:00 1989  Brian Fox  (bfox at aurel)
+
+       * rl_prep_terminal ()
+         BSD version turns off C-s, C-q, C-y, C-v.
+
+       * readline.c -- rl_prep_terminal ()
+         SYSV version hacks readline_echoing_p.
+         BSD version turns on passing of the 8th bit for the duration
+         of reading the line.
+
+Tue Jul 11 06:25:01 1989  Brian Fox  (bfox at aurel)
+
+       * readline.c: new variable rl_tilde_expander.
+         If non-null, this contains the address of a function to call if
+         the standard meaning for expanding a tilde fails.  The function is
+         called with the text sans tilde (as in "foo"), and returns a
+         malloc()'ed string which is the expansion, or a NULL pointer if
+         there is no expansion. 
+
+       * readline.h - new file chardefs.h
+         Separates things that only readline.c needs from the standard
+         header file publishing interesting things about readline.
+
+       * readline.c:
+         readline_default_bindings () now looks at terminal chararacters
+         and binds those as well.
+
+Wed Jun 28 20:20:51 1989  Brian Fox  (bfox at aurel)
+
+       * Made readline and history into independent libraries.
+
diff --git a/lib/readline/Makefile b/lib/readline/Makefile
new file mode 100644 (file)
index 0000000..b36cab7
--- /dev/null
@@ -0,0 +1,134 @@
+## -*- text -*- ####################################################
+#                                                                 #
+# Makefile for the GNU Readline and History Libraries.            #
+#                                                                 #
+####################################################################
+
+srcdir = .
+VPATH = .:$(srcdir)
+
+INSTALL = install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+
+RANLIB = ranlib
+AR = ar
+RM = rm
+CP = cp
+MV = mv
+
+# See the file STANDALONE for the -D defines that readline understands
+DEFS =
+# For libraries which include headers from other libraries.
+LOCAL_INCLUDES = -I. -I..
+
+CPPFLAGS = $(DEFS) $(LOCAL_INCLUDES)
+
+# 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.
+.c.o:
+       $(CC) -c $(CPPFLAGS) $(CFLAGS) $<
+
+# The name of the main library target.
+LIBRARY_NAME = libreadline.a
+
+# The C code source files for this library.
+CSOURCES = $(srcdir)readline.c $(srcdir)funmap.c $(srcdir)keymaps.c \
+          $(srcdir)vi_mode.c $(srcdir)parens.c $(srcdir)rltty.c \
+          $(srcdir)complete.c $(srcdir)bind.c $(srcdir)isearch.c \
+          $(srcdir)display.c $(srcdir)signals.c $(srcdir)emacs_keymap.c \
+          $(srcdir)vi_keymap.c $(srcdir)history.c $(srcdir)tilde.c \
+          $(srcdir)xmalloc.c
+
+# The header files for this library.
+HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h \
+          posixstat.h tilde.h rlconf.h
+
+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 \
+         history.o tilde.o xmalloc.o
+
+# The texinfo files which document this library.
+DOCSOURCE = doc/rlman.texinfo doc/rltech.texinfo doc/rluser.texinfo
+DOCOBJECT = doc/readline.dvi
+DOCSUPPORT = doc/Makefile
+DOCUMENTATION = $(DOCSOURCE) $(DOCOBJECT) $(DOCSUPPORT)
+
+SUPPORT = Makefile ChangeLog $(DOCSUPPORT) examples/[-a-z.]*
+
+SOURCES  = $(CSOURCES) $(HSOURCES) $(DOCSOURCE)
+
+THINGS_TO_TAR = $(SOURCES) $(SUPPORT)
+
+##########################################################################
+
+all: libreadline.a libhistory.a
+
+libreadline.a: $(OBJECTS)
+       $(RM) -f $@
+       $(AR) cq $@ $(OBJECTS)
+       -[ -n "$(RANLIB)" ] && $(RANLIB) $@
+
+libhistory.a: history.o
+       $(RM) -f $@
+       $(AR) cq $@ history.o
+       -[ -n "$(RANLIB)" ] && $(RANLIB) $@
+
+documentation: force
+       [ ! -d doc ] && mkdir doc
+       (if [ -d doc ]; then cd doc; $(MAKE) $(MFLAGS); fi)
+
+force:
+
+# The rule for 'includes' is written funny so that the if statement
+# always returns TRUE unless there really was an error installing the
+# include files.
+install: installdirs libreadline.a
+       ${INSTALL_DATA} readline.h keymaps.h chardefs.h history.h \
+               $(incdir)/readline
+       -${MV} $(libdir)/libreadline.a $(libdir)/libreadline.old
+       ${INSTALL_DATA} libreadline.a $(bindir)/libreadline.a
+       -[ -n "$(RANLIB)" ] && $(RANLIB) -t $(bindir)/libreadline.a
+
+installdirs:
+       [ ! -d $(incdir)/readline ] && { \
+         mkdir $(incdir)/readline && chmod chmod 755 $(incdir)/readline; }
+
+uninstall:
+       cd $(incdir)/readline && ${RM} -f ${INSTALLED_HEADERS}
+       cd $(libdir) && ${RM} -f libreadline.a libreadline.old
+
+tags:  force
+       etags $(CSOURCES) $(HSOURCES)
+
+TAGS:  force
+       ctags -x $(CSOURCES) $(HSOURCES) > $@
+
+readline: readline.h rldefs.h chardefs.h
+readline: $(OBJECTS)
+       $(CC) $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
+         $(LOCAL_INCLUDES) -DTEST -o readline readline.c vi_mode.o funmap.o \
+         keymaps.o -ltermcap
+
+clean:
+       $(RM) -f $(OBJECTS) libreadline.a libhistory.a
+       (if [ -d doc ]; then cd doc; $(MAKE) $(MFLAGS) $@; fi)
+
+maintainer-clean realclean distclean mostlyclean: clean
+       (if [ -d doc ]; then cd doc; $(MAKE) $(MFLAGS) $@; fi)
+
+# Dependencies
+readline.o: readline.c readline.h rldefs.h rlconf.h chardefs.h
+readline.o: keymaps.h history.h
+vi_mode.o:  rldefs.h rlconf.h readline.h history.h
+funmap.o:   funmap.c readline.h rlconf.h
+keymaps.o:  keymaps.c emacs_keymap.c vi_keymap.c keymaps.h chardefs.h rlconf.h
+history.o: history.h memalloc.h
+isearch.o: memalloc.h readline.h history.h
+search.o: memalloc.h readline.h history.h
+display.o: readline.h history.h rldefs.h rlconf.h
+complete.o: readline.h rldefs.h rlconf.h
+rltty.o: rldefs.h rlconf.h readline.h
+bind.o: rldefs.h rlconf.h readline.h history.h
+signals.o: rldefs.h rlconf.h readline.h history.h
+parens.o: readline.h
diff --git a/lib/readline/README b/lib/readline/README
new file mode 100644 (file)
index 0000000..131471c
--- /dev/null
@@ -0,0 +1,6 @@
+This is the distribution of the Gnu Readline library.  See the file
+STANDALONE for a description of the #defines that can be passed via
+the makefile to build readline on different systems.
+
+The file rlconf.h contains defines that enable and disable certain
+readline features.
diff --git a/lib/readline/STANDALONE b/lib/readline/STANDALONE
new file mode 100644 (file)
index 0000000..c1387f3
--- /dev/null
@@ -0,0 +1,31 @@
+This is a description of C preprocessor defines that readline accepts.
+Most are passed in from the parent `make'; e.g. from the bash source
+directory.
+
+NO_SYS_FILE            <sys/file.h> is not present
+HAVE_UNISTD_H          <unistd.h> exists
+HAVE_STDLIB_H          <stdlib.h> exists
+HAVE_VARARGS_H         <varargs.h> exists and is usable
+HAVE_STRING_H          <string.h> exists
+HAVE_ALLOCA_H          <alloca.h> exists and is needed for alloca()
+HAVE_ALLOCA            alloca(3) or a define for it exists
+PRAGMA_ALLOCA          use of alloca() requires a #pragma, as in AIX 3.x
+VOID_SIGHANDLER                signal handlers are void functions
+HAVE_DIRENT_H          <dirent.h> exists and is usable
+HAVE_SYS_PTEM_H                <sys/ptem.h> exists 
+HAVE_SYS_PTE_H         <sys/pte.h> exists 
+HAVE_SYS_STREAM_H      <sys/stream.h> exists
+
+System-specific options:
+
+GWINSZ_IN_SYS_IOCTL    need to include <sys/ioctl.h> for TIOCGWINSZ
+HAVE_GETPW_DECLS       the getpw* functions are declared in <pwd.h> and cannot
+                       be redeclared without compiler errors
+HAVE_STRCASECMP                the strcasecmp and strncasecmp functions are available
+
+USG                    Running a variant of System V
+USGr3                  Running System V.3
+XENIX_22               Xenix 2.2
+Linux                  Linux
+CRAY                   running a recent version of Cray UNICOS
+SunOS4                 Running SunOS 4.x
diff --git a/lib/readline/ansi_stdlib.h b/lib/readline/ansi_stdlib.h
new file mode 100644 (file)
index 0000000..52339da
--- /dev/null
@@ -0,0 +1,41 @@
+/* ansi_stdlib.h -- An ANSI Standard stdlib.h. */
+/* A minimal stdlib.h containing extern declarations for those functions
+   that bash uses. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_STDLIB_H_)
+#define        _STDLIB_H_ 1
+
+/* String conversion functions. */
+extern int atoi ();
+extern long int atol ();
+
+/* Memory allocation functions. */
+extern char *malloc ();
+extern char *realloc ();
+extern void free ();
+
+/* Other miscellaneous functions. */
+extern void abort ();
+extern void exit ();
+extern char *getenv ();
+extern void qsort ();
+
+#endif /* _STDLIB_H  */
diff --git a/lib/readline/bind.c b/lib/readline/bind.c
new file mode 100644 (file)
index 0000000..8821599
--- /dev/null
@@ -0,0 +1,1487 @@
+/* bind.c -- key binding and startup file support for the readline library. */
+
+/* Copyright (C) 1987, 1989, 1992 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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#if !defined (NO_SYS_FILE)
+#  include <sys/file.h>
+#endif /* !NO_SYS_FILE */
+#include <signal.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <errno.h>
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+extern int _rl_horizontal_scroll_mode;
+extern int _rl_mark_modified_lines;
+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_complete_show_all;
+#if defined (PAREN_MATCHING)
+extern int rl_blink_matching_paren;
+#endif /* PAREN_MATCHING */
+#if defined (VISIBLE_STATS)
+extern int rl_visible_stats;
+#endif /* VISIBLE_STATS */
+extern int rl_complete_with_tilde_expansion;
+extern int rl_completion_query_items;
+#if defined (VI_MODE)
+extern char *rl_vi_comment_begin;
+#endif
+
+extern int rl_explicit_arg;
+extern int rl_editing_mode;
+extern unsigned short _rl_parsing_conditionalized_out;
+extern Keymap _rl_keymap;
+
+extern char *possible_control_prefixes[], *possible_meta_prefixes[];
+
+extern char **rl_funmap_names ();
+
+/* Forward declarations */
+void rl_set_keymap_from_edit_mode ();
+
+static int glean_key_from_name ();
+
+#if defined (HAVE_STRCASECMP)
+#define stricmp strcasecmp
+#define strnicmp strncasecmp
+#else
+static int stricmp (), strnicmp ();
+#endif
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Binding keys                                */
+/*                                                                 */
+/* **************************************************************** */
+
+/* rl_add_defun (char *name, Function *function, int key)
+   Add NAME to the list of named functions.  Make FUNCTION be the function
+   that gets called.  If KEY is not -1, then bind it. */
+rl_add_defun (name, function, key)
+     char *name;
+     Function *function;
+     int key;
+{
+  if (key != -1)
+    rl_bind_key (key, function);
+  rl_add_funmap_entry (name, function);
+  return 0;
+}
+
+/* Bind KEY to FUNCTION.  Returns non-zero if KEY is out of range. */
+int
+rl_bind_key (key, function)
+     int key;
+     Function *function;
+{
+  if (key < 0)
+    return (key);
+
+  if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
+    {
+      if (_rl_keymap[ESC].type == ISKMAP)
+       {
+         Keymap escmap;
+
+         escmap = FUNCTION_TO_KEYMAP (_rl_keymap, ESC);
+         key = UNMETA (key);
+         escmap[key].type = ISFUNC;
+         escmap[key].function = function;
+         return (0);
+       }
+      return (key);
+    }
+
+  _rl_keymap[key].type = ISFUNC;
+  _rl_keymap[key].function = function;
+  return (0);
+}
+
+/* Bind KEY to FUNCTION in MAP.  Returns non-zero in case of invalid
+   KEY. */
+int
+rl_bind_key_in_map (key, function, map)
+     int key;
+     Function *function;
+     Keymap map;
+{
+  int result;
+  Keymap oldmap = _rl_keymap;
+
+  _rl_keymap = map;
+  result = rl_bind_key (key, function);
+  _rl_keymap = oldmap;
+  return (result);
+}
+
+/* Make KEY do nothing in the currently selected keymap.
+   Returns non-zero in case of error. */
+int
+rl_unbind_key (key)
+     int key;
+{
+  return (rl_bind_key (key, (Function *)NULL));
+}
+
+/* Make KEY do nothing in MAP.
+   Returns non-zero in case of error. */
+int
+rl_unbind_key_in_map (key, map)
+     int key;
+     Keymap map;
+{
+  return (rl_bind_key_in_map (key, (Function *)NULL, map));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+   FUNCTION.  This makes new keymaps as necessary.  The initial
+   place to do bindings is in MAP. */
+rl_set_key (keyseq, function, map)
+     char *keyseq;
+     Function *function;
+     Keymap map;
+{
+  return (rl_generic_bind (ISFUNC, keyseq, function, map));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+   the string of characters MACRO.  This makes new keymaps as
+   necessary.  The initial place to do bindings is in MAP. */
+rl_macro_bind (keyseq, macro, map)
+     char *keyseq, *macro;
+     Keymap map;
+{
+  char *macro_keys;
+  int macro_keys_len;
+
+  macro_keys = (char *)xmalloc ((2 * strlen (macro)) + 1);
+
+  if (rl_translate_keyseq (macro, macro_keys, &macro_keys_len))
+    {
+      free (macro_keys);
+      return -1;
+    }
+  rl_generic_bind (ISMACR, keyseq, macro_keys, map);
+  return 0;
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+   the arbitrary pointer DATA.  TYPE says what kind of data is
+   pointed to by DATA, right now this can be a function (ISFUNC),
+   a macro (ISMACR), or a keymap (ISKMAP).  This makes new keymaps
+   as necessary.  The initial place to do bindings is in MAP. */
+rl_generic_bind (type, keyseq, data, map)
+     int type;
+     char *keyseq, *data;
+     Keymap map;
+{
+  char *keys;
+  int keys_len;
+  register int i;
+
+  /* If no keys to bind to, exit right away. */
+  if (!keyseq || !*keyseq)
+    {
+      if (type == ISMACR)
+       free (data);
+      return -1;
+    }
+
+  keys = xmalloc (1 + (2 * strlen (keyseq)));
+
+  /* Translate the ASCII representation of KEYSEQ into an array of
+     characters.  Stuff the characters into KEYS, and the length of
+     KEYS into KEYS_LEN. */
+  if (rl_translate_keyseq (keyseq, keys, &keys_len))
+    {
+      free (keys);
+      return -1;
+    }
+
+  /* Bind keys, making new keymaps as necessary. */
+  for (i = 0; i < keys_len; i++)
+    {
+      int ic = (int) ((unsigned char)keys[i]);
+
+      if (_rl_convert_meta_chars_to_ascii && META_CHAR (ic))
+       {
+         ic = UNMETA (ic);
+         if (map[ESC].type == ISKMAP)
+           map = FUNCTION_TO_KEYMAP (map, ESC);
+       }
+
+      if ((i + 1) < keys_len)
+       {
+         if (map[ic].type != ISKMAP)
+           {
+             if (map[ic].type == ISMACR)
+               free ((char *)map[ic].function);
+
+             map[ic].type = ISKMAP;
+             map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap());
+           }
+         map = FUNCTION_TO_KEYMAP (map, ic);
+       }
+      else
+       {
+         if (map[ic].type == ISMACR)
+           free ((char *)map[ic].function);
+
+         map[ic].function = KEYMAP_TO_FUNCTION (data);
+         map[ic].type = type;
+       }
+    }
+  free (keys);
+  return 0;
+}
+
+/* Translate the ASCII representation of SEQ, stuffing the values into ARRAY,
+   an array of characters.  LEN gets the final length of ARRAY.  Return
+   non-zero if there was an error parsing SEQ. */
+rl_translate_keyseq (seq, array, len)
+     char *seq, *array;
+     int *len;
+{
+  register int i, c, l = 0;
+
+  for (i = 0; c = seq[i]; i++)
+    {
+      if (c == '\\')
+       {
+         c = seq[++i];
+
+         if (!c)
+           break;
+
+         if (((c == 'C' || c == 'M') &&  seq[i + 1] == '-') ||
+             (c == 'e'))
+           {
+             /* Handle special case of backwards define. */
+             if (strncmp (&seq[i], "C-\\M-", 5) == 0)
+               {
+                 array[l++] = ESC;
+                 i += 5;
+                 array[l++] = CTRL (to_upper (seq[i]));
+                 if (!seq[i])
+                   i--;
+                 continue;
+               }
+
+             switch (c)
+               {
+               case 'M':
+                 i++;
+                 array[l++] = ESC;
+                 break;
+
+               case 'C':
+                 i += 2;
+                 /* Special hack for C-?... */
+                 if (seq[i] == '?')
+                   array[l++] = RUBOUT;
+                 else
+                   array[l++] = CTRL (to_upper (seq[i]));
+                 break;
+
+               case 'e':
+                 array[l++] = ESC;
+               }
+
+             continue;
+           }
+       }
+      array[l++] = c;
+    }
+
+  *len = l;
+  array[l] = '\0';
+  return (0);
+}
+
+/* Return a pointer to the function that STRING represents.
+   If STRING doesn't have a matching function, then a NULL pointer
+   is returned. */
+Function *
+rl_named_function (string)
+     char *string;
+{
+  register int i;
+
+  rl_initialize_funmap ();
+
+  for (i = 0; funmap[i]; i++)
+    if (stricmp (funmap[i]->name, string) == 0)
+      return (funmap[i]->function);
+  return ((Function *)NULL);
+}
+
+/* Return the function (or macro) definition which would be invoked via
+   KEYSEQ if executed in MAP.  If MAP is NULL, then the current keymap is
+   used.  TYPE, if non-NULL, is a pointer to an int which will receive the
+   type of the object pointed to.  One of ISFUNC (function), ISKMAP (keymap),
+   or ISMACR (macro). */
+Function *
+rl_function_of_keyseq (keyseq, map, type)
+     char *keyseq;
+     Keymap map;
+     int *type;
+{
+  register int i;
+
+  if (!map)
+    map = _rl_keymap;
+
+  for (i = 0; keyseq && keyseq[i]; i++)
+    {
+      int ic = keyseq[i];
+
+      if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
+       {
+         if (map[ESC].type != ISKMAP)
+           {
+             if (type)
+               *type = map[ESC].type;
+
+             return (map[ESC].function);
+           }
+         else
+           {
+             map = FUNCTION_TO_KEYMAP (map, ESC);
+             ic = UNMETA (ic);
+           }
+       }
+
+      if (map[ic].type == ISKMAP)
+       {
+         /* If this is the last key in the key sequence, return the
+            map. */
+         if (!keyseq[i + 1])
+           {
+             if (type)
+               *type = ISKMAP;
+
+             return (map[ic].function);
+           }
+         else
+           map = FUNCTION_TO_KEYMAP (map, ic);
+       }
+      else
+       {
+         if (type)
+           *type = map[ic].type;
+
+         return (map[ic].function);
+       }
+    }
+  return ((Function *) NULL);
+}
+
+/* The last key bindings file read. */
+static char *last_readline_init_file = (char *)NULL;
+
+/* Re-read the current keybindings file. */
+rl_re_read_init_file (count, ignore)
+     int count, ignore;
+{
+  int r;
+  r = rl_read_init_file ((char *)NULL);
+  rl_set_keymap_from_edit_mode ();
+  return r;
+}
+
+/* Do key bindings from a file.  If FILENAME is NULL it defaults
+   to the first non-null filename from this list:
+     1. the filename used for the previous call
+     2. the value of the shell variable `INPUTRC'
+     3. ~/.inputrc
+   If the file existed and could be opened and read, 0 is returned,
+   otherwise errno is returned. */
+int
+rl_read_init_file (filename)
+     char *filename;
+{
+  register int i;
+  char *buffer, *openname, *line, *end;
+  struct stat finfo;
+  int file;
+
+  /* Default the filename. */
+  if (!filename)
+    {
+      filename = last_readline_init_file;
+      if (!filename)
+        filename = getenv ("INPUTRC");
+      if (!filename)
+       filename = DEFAULT_INPUTRC;
+    }
+
+  if (!*filename)
+    filename = DEFAULT_INPUTRC;
+
+  openname = tilde_expand (filename);
+
+  if ((stat (openname, &finfo) < 0) ||
+      (file = open (openname, O_RDONLY, 0666)) < 0)
+    {
+      free (openname);
+      return (errno);
+    }
+  else
+    free (openname);
+
+  if (filename != last_readline_init_file)
+    {
+      if (last_readline_init_file)
+       free (last_readline_init_file);
+
+      last_readline_init_file = savestring (filename);
+    }
+
+  /* Read the file into BUFFER. */
+  buffer = (char *)xmalloc ((int)finfo.st_size + 1);
+  i = read (file, buffer, finfo.st_size);
+  close (file);
+
+  if (i != finfo.st_size)
+    return (errno);
+
+  /* Loop over the lines in the file.  Lines that start with `#' are
+     comments; all other lines are commands for readline initialization. */
+  line = buffer;
+  end = buffer + finfo.st_size;
+  while (line < end)
+    {
+      /* Find the end of this line. */
+      for (i = 0; line + i != end && line[i] != '\n'; i++);
+
+      /* Mark end of line. */
+      line[i] = '\0';
+
+      /* Skip leading whitespace. */
+      while (*line && whitespace (*line))
+        {
+         line++;
+         i--;
+        }
+
+      /* If the line is not a comment, then parse it. */
+      if (*line && *line != '#')
+       rl_parse_and_bind (line);
+
+      /* Move to the next line. */
+      line += i + 1;
+    }
+  free (buffer);
+  return (0);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Parser Directives                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Conditionals. */
+
+/* Calling programs set this to have their argv[0]. */
+char *rl_readline_name = "other";
+
+/* Stack of previous values of parsing_conditionalized_out. */
+static unsigned char *if_stack = (unsigned char *)NULL;
+static int if_stack_depth = 0;
+static int if_stack_size = 0;
+
+/* Push _rl_parsing_conditionalized_out, and set parser state based
+   on ARGS. */
+static int
+parser_if (args)
+     char *args;
+{
+  register int i;
+
+  /* Push parser state. */
+  if (if_stack_depth + 1 >= if_stack_size)
+    {
+      if (!if_stack)
+       if_stack = (unsigned char *)xmalloc (if_stack_size = 20);
+      else
+       if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20);
+    }
+  if_stack[if_stack_depth++] = _rl_parsing_conditionalized_out;
+
+  /* If parsing is turned off, then nothing can turn it back on except
+     for finding the matching endif.  In that case, return right now. */
+  if (_rl_parsing_conditionalized_out)
+    return 0;
+
+  /* Isolate first argument. */
+  for (i = 0; args[i] && !whitespace (args[i]); i++);
+
+  if (args[i])
+    args[i++] = '\0';
+
+  /* Handle "if term=foo" and "if mode=emacs" constructs.  If this
+     isn't term=foo, or mode=emacs, then check to see if the first
+     word in ARGS is the same as the value stored in rl_readline_name. */
+  if (rl_terminal_name && strnicmp (args, "term=", 5) == 0)
+    {
+      char *tem, *tname;
+
+      /* Terminals like "aaa-60" are equivalent to "aaa". */
+      tname = savestring (rl_terminal_name);
+      tem = strchr (tname, '-');
+      if (tem)
+       *tem = '\0';
+
+      /* Test the `long' and `short' forms of the terminal name so that
+        if someone has a `sun-cmd' and does not want to have bindings
+        that will be executed if the terminal is a `sun', they can put
+        `$if term=sun-cmd' into their .inputrc. */
+      if ((stricmp (args + 5, tname) == 0) ||
+         (stricmp (args + 5, rl_terminal_name) == 0))
+       _rl_parsing_conditionalized_out = 0;
+      else
+       _rl_parsing_conditionalized_out = 1;
+
+      free (tname);
+    }
+#if defined (VI_MODE)
+  else if (strnicmp (args, "mode=", 5) == 0)
+    {
+      int mode;
+
+      if (stricmp (args + 5, "emacs") == 0)
+       mode = emacs_mode;
+      else if (stricmp (args + 5, "vi") == 0)
+       mode = vi_mode;
+      else
+       mode = no_mode;
+
+      if (mode == rl_editing_mode)
+       _rl_parsing_conditionalized_out = 0;
+      else
+       _rl_parsing_conditionalized_out = 1;
+    }
+#endif /* VI_MODE */
+  /* Check to see if the first word in ARGS is the same as the
+     value stored in rl_readline_name. */
+  else if (stricmp (args, rl_readline_name) == 0)
+    _rl_parsing_conditionalized_out = 0;
+  else
+    _rl_parsing_conditionalized_out = 1;
+  return 0;
+}
+
+/* Invert the current parser state if there is anything on the stack. */
+static int
+parser_else (args)
+     char *args;
+{
+  register int i;
+
+  if (!if_stack_depth)
+    {
+      /* Error message? */
+      return 0;
+    }
+
+  /* Check the previous (n - 1) levels of the stack to make sure that
+     we haven't previously turned off parsing. */
+  for (i = 0; i < if_stack_depth - 1; i++)
+    if (if_stack[i] == 1)
+      return 0;
+
+  /* Invert the state of parsing if at top level. */
+  _rl_parsing_conditionalized_out = !_rl_parsing_conditionalized_out;
+  return 0;
+}
+
+/* Terminate a conditional, popping the value of
+   _rl_parsing_conditionalized_out from the stack. */
+static int
+parser_endif (args)
+     char *args;
+{
+  if (if_stack_depth)
+    _rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
+  else
+    {
+      /* *** What, no error message? *** */
+    }
+  return 0;
+}
+
+/* Associate textual names with actual functions. */
+static struct {
+  char *name;
+  Function *function;
+} parser_directives [] = {
+  { "if", parser_if },
+  { "endif", parser_endif },
+  { "else", parser_else },
+  { (char *)0x0, (Function *)0x0 }
+};
+
+/* Handle a parser directive.  STATEMENT is the line of the directive
+   without any leading `$'. */
+static int
+handle_parser_directive (statement)
+     char *statement;
+{
+  register int i;
+  char *directive, *args;
+
+  /* Isolate the actual directive. */
+
+  /* Skip whitespace. */
+  for (i = 0; whitespace (statement[i]); i++);
+
+  directive = &statement[i];
+
+  for (; statement[i] && !whitespace (statement[i]); i++);
+
+  if (statement[i])
+    statement[i++] = '\0';
+
+  for (; statement[i] && whitespace (statement[i]); i++);
+
+  args = &statement[i];
+
+  /* Lookup the command, and act on it. */
+  for (i = 0; parser_directives[i].name; i++)
+    if (stricmp (directive, parser_directives[i].name) == 0)
+      {
+       (*parser_directives[i].function) (args);
+       return (0);
+      }
+
+  /* *** Should an error message be output? */
+  return (1);
+}
+
+static int substring_member_of_array ();
+
+/* Read the binding command from STRING and perform it.
+   A key binding command looks like: Keyname: function-name\0,
+   a variable binding command looks like: set variable value.
+   A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */
+rl_parse_and_bind (string)
+     char *string;
+{
+  char *funname, *kname;
+  register int c, i;
+  int key, equivalency;
+
+  while (string && whitespace (*string))
+    string++;
+
+  if (!string || !*string || *string == '#')
+    return 0;
+
+  /* If this is a parser directive, act on it. */
+  if (*string == '$')
+    {
+      handle_parser_directive (&string[1]);
+      return 0;
+    }
+
+  /* If we aren't supposed to be parsing right now, then we're done. */
+  if (_rl_parsing_conditionalized_out)
+    return 0;
+
+  i = 0;
+  /* If this keyname is a complex key expression surrounded by quotes,
+     advance to after the matching close quote.  This code allows the
+     backslash to quote characters in the key expression. */
+  if (*string == '"')
+    {
+      int passc = 0;
+
+      for (i = 1; c = string[i]; i++)
+       {
+         if (passc)
+           {
+             passc = 0;
+             continue;
+           }
+
+         if (c == '\\')
+           {
+             passc++;
+             continue;
+           }
+
+         if (c == '"')
+           break;
+       }
+    }
+
+  /* Advance to the colon (:) or whitespace which separates the two objects. */
+  for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
+
+  equivalency = (c == ':' && string[i + 1] == '=');
+
+  /* Mark the end of the command (or keyname). */
+  if (string[i])
+    string[i++] = '\0';
+
+  /* If doing assignment, skip the '=' sign as well. */
+  if (equivalency)
+    string[i++] = '\0';
+
+  /* If this is a command to set a variable, then do that. */
+  if (stricmp (string, "set") == 0)
+    {
+      char *var = string + i;
+      char *value;
+
+      /* Make VAR point to start of variable name. */
+      while (*var && whitespace (*var)) var++;
+
+      /* Make value point to start of value string. */
+      value = var;
+      while (*value && !whitespace (*value)) value++;
+      if (*value)
+       *value++ = '\0';
+      while (*value && whitespace (*value)) value++;
+
+      rl_variable_bind (var, value);
+      return 0;
+    }
+
+  /* Skip any whitespace between keyname and funname. */
+  for (; string[i] && whitespace (string[i]); i++);
+  funname = &string[i];
+
+  /* Now isolate funname.
+     For straight function names just look for whitespace, since
+     that will signify the end of the string.  But this could be a
+     macro definition.  In that case, the string is quoted, so skip
+     to the matching delimiter.  We allow the backslash to quote the
+     delimiter characters in the macro body. */
+  /* This code exists to allow whitespace in macro expansions, which
+     would otherwise be gobbled up by the next `for' loop.*/
+  /* XXX - it may be desirable to allow backslash quoting only if " is
+     the quoted string delimiter, like the shell. */
+  if (*funname == '\'' || *funname == '"')
+    {
+      int delimiter = string[i++];
+      int passc = 0;
+
+      for (; c = string[i]; i++)
+       {
+         if (passc)
+           {
+             passc = 0;
+             continue;
+           }
+
+         if (c == '\\')
+           {
+             passc = 1;
+             continue;
+           }
+
+         if (c == delimiter)
+           break;
+       }
+      if (c)
+       i++;
+    }
+
+  /* Advance to the end of the string.  */
+  for (; string[i] && !whitespace (string[i]); i++);
+
+  /* No extra whitespace at the end of the string. */
+  string[i] = '\0';
+
+  /* Handle equivalency bindings here.  Make the left-hand side be exactly
+     whatever the right-hand evaluates to, including keymaps. */
+  if (equivalency)
+    {
+      return 0;
+    }
+
+  /* If this is a new-style key-binding, then do the binding with
+     rl_set_key ().  Otherwise, let the older code deal with it. */
+  if (*string == '"')
+    {
+      char *seq = xmalloc (1 + strlen (string));
+      register int j, k = 0;
+      int passc = 0;
+
+      for (j = 1; string[j]; j++)
+       {
+         /* Allow backslash to quote characters, but leave them in place.
+            This allows a string to end with a backslash quoting another
+            backslash, or with a backslash quoting a double quote.  The
+            backslashes are left in place for rl_translate_keyseq (). */
+         if (passc || (string[j] == '\\'))
+           {
+             seq[k++] = string[j];
+             passc = !passc;
+             continue;
+           }
+
+         if (string[j] == '"')
+           break;
+
+         seq[k++] = string[j];
+       }
+      seq[k] = '\0';
+
+      /* Binding macro? */
+      if (*funname == '\'' || *funname == '"')
+       {
+         j = strlen (funname);
+
+         /* Remove the delimiting quotes from each end of FUNNAME. */
+         if (j && funname[j - 1] == *funname)
+           funname[j - 1] = '\0';
+
+         rl_macro_bind (seq, &funname[1], _rl_keymap);
+       }
+      else
+       rl_set_key (seq, rl_named_function (funname), _rl_keymap);
+
+      free (seq);
+      return 0;
+    }
+
+  /* Get the actual character we want to deal with. */
+  kname = strrchr (string, '-');
+  if (!kname)
+    kname = string;
+  else
+    kname++;
+
+  key = glean_key_from_name (kname);
+
+  /* Add in control and meta bits. */
+  if (substring_member_of_array (string, possible_control_prefixes))
+    key = CTRL (to_upper (key));
+
+  if (substring_member_of_array (string, possible_meta_prefixes))
+    key = META (key);
+
+  /* Temporary.  Handle old-style keyname with macro-binding. */
+  if (*funname == '\'' || *funname == '"')
+    {
+      char seq[2];
+      int fl = strlen (funname);
+
+      seq[0] = key; seq[1] = '\0';
+      if (fl && funname[fl - 1] == *funname)
+       funname[fl - 1] = '\0';
+
+      rl_macro_bind (seq, &funname[1], _rl_keymap);
+    }
+#if defined (PREFIX_META_HACK)
+  /* Ugly, but working hack to keep prefix-meta around. */
+  else if (stricmp (funname, "prefix-meta") == 0)
+    {
+      char seq[2];
+
+      seq[0] = key;
+      seq[1] = '\0';
+      rl_generic_bind (ISKMAP, seq, (char *)emacs_meta_keymap, _rl_keymap);
+    }
+#endif /* PREFIX_META_HACK */
+  else
+    rl_bind_key (key, rl_named_function (funname));
+  return 0;
+}
+
+/* Simple structure for boolean readline variables (i.e., those that can
+   have one of two values; either "On" or 1 for truth, or "Off" or 0 for
+   false. */
+
+static struct {
+  char *name;
+  int *value;
+} boolean_varlist [] = {
+  { "horizontal-scroll-mode",  &_rl_horizontal_scroll_mode },
+  { "mark-modified-lines",     &_rl_mark_modified_lines },
+  { "meta-flag",               &_rl_meta_flag },
+#if defined (PAREN_MATCHING)
+  { "blink-matching-paren",    &rl_blink_matching_paren },
+#endif
+  { "convert-meta",            &_rl_convert_meta_chars_to_ascii },
+  { "show-all-if-ambiguous",   &_rl_complete_show_all },
+  { "output-meta",             &_rl_output_meta_chars },
+#if defined (VISIBLE_STATS)
+  { "visible-stats",           &rl_visible_stats },
+#endif /* VISIBLE_STATS */
+  { "expand-tilde",            &rl_complete_with_tilde_expansion },
+  { (char *)NULL, (int *)NULL }
+};
+
+rl_variable_bind (name, value)
+     char *name, *value;
+{
+  register int i;
+
+  /* Check for simple variables first. */
+  for (i = 0; boolean_varlist[i].name; i++)
+    {
+      if (stricmp (name, boolean_varlist[i].name) == 0)
+       {
+         /* A variable is TRUE if the "value" is "on", "1" or "". */
+         if ((!*value) ||
+             (stricmp (value, "On") == 0) ||
+             (value[0] == '1' && value[1] == '\0'))
+           *boolean_varlist[i].value = 1;
+         else
+           *boolean_varlist[i].value = 0;
+         return 0;
+       }
+    }
+
+  /* Not a boolean variable, so check for specials. */
+
+  /* Editing mode change? */
+  if (stricmp (name, "editing-mode") == 0)
+    {
+      if (strnicmp (value, "vi", 2) == 0)
+       {
+#if defined (VI_MODE)
+         _rl_keymap = vi_insertion_keymap;
+         rl_editing_mode = vi_mode;
+#endif /* VI_MODE */
+       }
+      else if (strnicmp (value, "emacs", 5) == 0)
+       {
+         _rl_keymap = emacs_standard_keymap;
+         rl_editing_mode = emacs_mode;
+       }
+    }
+
+  /* Comment string change? */
+  else if (stricmp (name, "comment-begin") == 0)
+    {
+#if defined (VI_MODE)
+      if (*value)
+       {
+         if (rl_vi_comment_begin)
+           free (rl_vi_comment_begin);
+
+         rl_vi_comment_begin = savestring (value);
+       }
+#endif /* VI_MODE */
+    }
+  else if (stricmp (name, "completion-query-items") == 0)
+    {
+      int nval = 100;
+      if (*value)
+       {
+         nval = atoi (value);
+         if (nval < 0)
+           nval = 0;
+       }
+      rl_completion_query_items = nval;
+    }
+  else if (stricmp (name, "keymap") == 0)
+    {
+      Keymap kmap;
+      kmap = rl_get_keymap_by_name (value);
+      if (kmap)
+        rl_set_keymap (kmap);
+    }
+  else if (stricmp (name, "bell-style") == 0)
+    {
+      if (!*value)
+        _rl_bell_preference = AUDIBLE_BELL;
+      else
+        {
+          if (stricmp (value, "none") == 0 || stricmp (value, "off") == 0)
+            _rl_bell_preference = NO_BELL;
+          else if (stricmp (value, "audible") == 0 || stricmp (value, "on") == 0)
+            _rl_bell_preference = AUDIBLE_BELL;
+          else if (stricmp (value, "visible") == 0)
+            _rl_bell_preference = VISIBLE_BELL;
+        }
+    }
+  else if (stricmp (name, "prefer-visible-bell") == 0)
+    {
+      /* Backwards compatibility. */
+      if (*value && (stricmp (value, "on") == 0 ||
+                    (*value == '1' && !value[1])))
+        _rl_bell_preference = VISIBLE_BELL;
+      else
+        _rl_bell_preference = AUDIBLE_BELL;
+    }
+
+  return 0;
+}
+
+/* Return the character which matches NAME.
+   For example, `Space' returns ' '. */
+
+typedef struct {
+  char *name;
+  int value;
+} assoc_list;
+
+static assoc_list name_key_alist[] = {
+  { "DEL", 0x7f },
+  { "ESC", '\033' },
+  { "Escape", '\033' },
+  { "LFD", '\n' },
+  { "Newline", '\n' },
+  { "RET", '\r' },
+  { "Return", '\r' },
+  { "Rubout", 0x7f },
+  { "SPC", ' ' },
+  { "Space", ' ' },
+  { "Tab", 0x09 },
+  { (char *)0x0, 0 }
+};
+
+static int
+glean_key_from_name (name)
+     char *name;
+{
+  register int i;
+
+  for (i = 0; name_key_alist[i].name; i++)
+    if (stricmp (name, name_key_alist[i].name) == 0)
+      return (name_key_alist[i].value);
+
+  return (*(unsigned char *)name);     /* XXX was return (*name) */
+}
+
+/* Auxiliary functions to manage keymaps. */
+static struct {
+  char *name;
+  Keymap map;
+} keymap_names[] = {
+  { "emacs", emacs_standard_keymap },
+  { "emacs-standard", emacs_standard_keymap },
+  { "emacs-meta", emacs_meta_keymap },
+  { "emacs-ctlx", emacs_ctlx_keymap },
+#if defined (VI_MODE)
+  { "vi", vi_movement_keymap },
+  { "vi-move", vi_movement_keymap },
+  { "vi-command", vi_movement_keymap },
+  { "vi-insert", vi_insertion_keymap },
+#endif /* VI_MODE */
+  { (char *)0x0, (Keymap)0x0 }
+};
+
+Keymap
+rl_get_keymap_by_name (name)
+     char *name;
+{
+  register int i;
+
+  for (i = 0; keymap_names[i].name; i++)
+    if (strcmp (name, keymap_names[i].name) == 0)
+      return (keymap_names[i].map);
+  return ((Keymap) NULL);
+}
+
+void
+rl_set_keymap (map)
+     Keymap map;
+{
+  if (map)
+    _rl_keymap = map;
+}
+
+Keymap
+rl_get_keymap ()
+{
+  return (_rl_keymap);
+}
+
+void
+rl_set_keymap_from_edit_mode ()
+{
+  if (rl_editing_mode == emacs_mode)
+    _rl_keymap = emacs_standard_keymap;
+#if defined (VI_MODE)
+  else if (rl_editing_mode == vi_mode)
+    _rl_keymap = vi_insertion_keymap;
+#endif /* VI_MODE */
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*               Key Binding and Function Information              */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Each of the following functions produces information about the
+   state of keybindings and functions known to Readline.  The info
+   is always printed to rl_outstream, and in such a way that it can
+   be read back in (i.e., passed to rl_parse_and_bind (). */
+
+/* Print the names of functions known to Readline. */
+void
+rl_list_funmap_names (count, ignore)
+     int count, ignore;
+{
+  register int i;
+  char **funmap_names;
+
+  funmap_names = rl_funmap_names ();
+
+  if (!funmap_names)
+    return;
+
+  for (i = 0; funmap_names[i]; i++)
+    fprintf (rl_outstream, "%s\n", funmap_names[i]);
+
+  free (funmap_names);
+}
+
+/* Return a NULL terminated array of strings which represent the key
+   sequences that are used to invoke FUNCTION in MAP. */
+char **
+rl_invoking_keyseqs_in_map (function, map)
+     Function *function;
+     Keymap map;
+{
+  register int key;
+  char **result;
+  int result_index, result_size;
+
+  result = (char **)NULL;
+  result_index = result_size = 0;
+
+  for (key = 0; key < 128; key++)
+    {
+      switch (map[key].type)
+       {
+       case ISMACR:
+         /* Macros match, if, and only if, the pointers are identical.
+            Thus, they are treated exactly like functions in here. */
+       case ISFUNC:
+         /* If the function in the keymap is the one we are looking for,
+            then add the current KEY to the list of invoking keys. */
+         if (map[key].function == function)
+           {
+             char *keyname = (char *)xmalloc (5);
+
+             if (CTRL_CHAR (key))
+               sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key)));
+             else if (key == RUBOUT)
+               sprintf (keyname, "\\C-?");
+             else if (key == '\\' || key == '"')
+               {
+                 keyname[0] = '\\';
+                 keyname[1] = (char) key;
+                 keyname[2] = '\0';
+               }
+             else
+               {
+                 keyname[0] = (char) key;
+                 keyname[1] = '\0';
+               }
+
+             if (result_index + 2 > result_size)
+               result = (char **) xrealloc
+                 (result, (result_size += 10) * sizeof (char *));
+
+             result[result_index++] = keyname;
+             result[result_index] = (char *)NULL;
+           }
+         break;
+
+       case ISKMAP:
+         {
+           char **seqs = (char **)NULL;
+
+           /* Find the list of keyseqs in this map which have FUNCTION as
+              their target.  Add the key sequences found to RESULT. */
+           if (map[key].function)
+             seqs =
+               rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
+
+           if (seqs)
+             {
+               register int i;
+
+               for (i = 0; seqs[i]; i++)
+                 {
+                   char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
+
+                   if (key == ESC)
+                     sprintf (keyname, "\\e");
+                   else if (CTRL_CHAR (key))
+                     sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key)));
+                   else if (key == RUBOUT)
+                     sprintf (keyname, "\\C-?");
+                   else if (key == '\\' || key == '"')
+                     {
+                       keyname[0] = '\\';
+                       keyname[1] = (char) key;
+                       keyname[2] = '\0';
+                     }
+                   else
+                     {
+                       keyname[0] = (char) key;
+                       keyname[1] = '\0';
+                     }
+
+                   strcat (keyname, seqs[i]);
+                   free (seqs[i]);
+
+                   if (result_index + 2 > result_size)
+                     result = (char **) xrealloc
+                       (result, (result_size += 10) * sizeof (char *));
+
+                   result[result_index++] = keyname;
+                   result[result_index] = (char *)NULL;
+                 }
+
+               free (seqs);
+             }
+         }
+         break;
+       }
+    }
+  return (result);
+}
+
+/* Return a NULL terminated array of strings which represent the key
+   sequences that can be used to invoke FUNCTION using the current keymap. */
+char **
+rl_invoking_keyseqs (function)
+     Function *function;
+{
+  return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
+}
+
+/* Print all of the current functions and their bindings to
+   rl_outstream.  If an explicit argument is given, then print
+   the output in such a way that it can be read back in. */
+int
+rl_dump_functions (count, key)
+     int count, key;
+{
+  rl_function_dumper (rl_explicit_arg);
+  rl_on_new_line ();
+  return (0);
+}
+
+/* Print all of the functions and their bindings to rl_outstream.  If
+   PRINT_READABLY is non-zero, then print the output in such a way
+   that it can be read back in. */
+void
+rl_function_dumper (print_readably)
+     int print_readably;
+{
+  register int i;
+  char **names;
+  char *name;
+
+  names = rl_funmap_names ();
+
+  fprintf (rl_outstream, "\n");
+
+  for (i = 0; name = names[i]; i++)
+    {
+      Function *function;
+      char **invokers;
+
+      function = rl_named_function (name);
+      invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap);
+
+      if (print_readably)
+       {
+         if (!invokers)
+           fprintf (rl_outstream, "# %s (not bound)\n", name);
+         else
+           {
+             register int j;
+
+             for (j = 0; invokers[j]; j++)
+               {
+                 fprintf (rl_outstream, "\"%s\": %s\n",
+                          invokers[j], name);
+                 free (invokers[j]);
+               }
+
+             free (invokers);
+           }
+       }
+      else
+       {
+         if (!invokers)
+           fprintf (rl_outstream, "%s is not bound to any keys\n",
+                    name);
+         else
+           {
+             register int j;
+
+             fprintf (rl_outstream, "%s can be found on ", name);
+
+             for (j = 0; invokers[j] && j < 5; j++)
+               {
+                 fprintf (rl_outstream, "\"%s\"%s", invokers[j],
+                          invokers[j + 1] ? ", " : ".\n");
+               }
+
+             if (j == 5 && invokers[j])
+               fprintf (rl_outstream, "...\n");
+
+             for (j = 0; invokers[j]; j++)
+               free (invokers[j]);
+
+             free (invokers);
+           }
+       }
+    }
+}
+
+/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. */
+void
+_rl_bind_if_unbound (keyseq, default_func)
+     char *keyseq;
+     Function *default_func;
+{
+  Function *func;
+
+  if (keyseq)
+    {
+      func = rl_function_of_keyseq (keyseq, _rl_keymap, (int *)NULL);
+      if (!func || func == rl_do_lowercase_version)
+       rl_set_key (keyseq, default_func, _rl_keymap);
+    }
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     String Utility Functions                    */
+/*                                                                 */
+/* **************************************************************** */
+
+static char *strindex ();
+
+/* Return non-zero if any members of ARRAY are a substring in STRING. */
+static int
+substring_member_of_array (string, array)
+     char *string, **array;
+{
+  while (*array)
+    {
+      if (strindex (string, *array))
+       return (1);
+      array++;
+    }
+  return (0);
+}
+
+#if !defined (HAVE_STRCASECMP)
+/* Whoops, Unix doesn't have strnicmp. */
+
+/* Compare at most COUNT characters from string1 to string2.  Case
+   doesn't matter. */
+static int
+strnicmp (string1, string2, count)
+     char *string1, *string2;
+     int count;
+{
+  register char ch1, ch2;
+
+  while (count)
+    {
+      ch1 = *string1++;
+      ch2 = *string2++;
+      if (to_upper(ch1) == to_upper(ch2))
+       count--;
+      else
+        break;
+    }
+  return (count);
+}
+
+/* strcmp (), but caseless. */
+static int
+stricmp (string1, string2)
+     char *string1, *string2;
+{
+  register char ch1, ch2;
+
+  while (*string1 && *string2)
+    {
+      ch1 = *string1++;
+      ch2 = *string2++;
+      if (to_upper(ch1) != to_upper(ch2))
+       return (1);
+    }
+  return (*string1 - *string2);
+}
+#endif /* !HAVE_STRCASECMP */
+
+/* Determine if s2 occurs in s1.  If so, return a pointer to the
+   match in s1.  The compare is case insensitive. */
+static char *
+strindex (s1, s2)
+     register char *s1, *s2;
+{
+  register int i, l = strlen (s2);
+  register int len = strlen (s1);
+
+  for (i = 0; (len - i) >= l; i++)
+    if (strnicmp (s1 + i, s2, l) == 0)
+      return (s1 + i);
+  return ((char *)NULL);
+}
diff --git a/lib/readline/chardefs.h b/lib/readline/chardefs.h
new file mode 100644 (file)
index 0000000..8c92811
--- /dev/null
@@ -0,0 +1,122 @@
+/* chardefs.h -- Character definitions for readline. */
+
+/* Copyright (C) 1994 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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _CHARDEFS_H
+#define _CHARDEFS_H
+
+#include <ctype.h>
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else
+#  include <strings.h>
+#endif /* HAVE_STRING_H */
+
+#ifndef whitespace
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#endif
+
+#ifdef CTRL
+#undef CTRL
+#endif
+
+/* Some character stuff. */
+#define control_character_threshold 0x020   /* Smaller than this is control. */
+#define control_character_mask 0x1f        /* 0x20 - 1 */
+#define meta_character_threshold 0x07f     /* Larger than this is Meta. */
+#define control_character_bit 0x40         /* 0x000000, must be off. */
+#define meta_character_bit 0x080           /* x0000000, must be on. */
+#define largest_char 255                   /* Largest character value. */
+
+#define CTRL_CHAR(c) ((c) < control_character_threshold)
+#define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char)
+
+#define CTRL(c) ((c) & control_character_mask)
+#define META(c) ((c) | meta_character_bit)
+
+#define UNMETA(c) ((c) & (~meta_character_bit))
+#define UNCTRL(c) to_upper(((c)|control_character_bit))
+
+/* Old versions
+#define lowercase_p(c) (((c) > ('a' - 1) && (c) < ('z' + 1)))
+#define uppercase_p(c) (((c) > ('A' - 1) && (c) < ('Z' + 1)))
+#define digit_p(c)  ((c) >= '0' && (c) <= '9')
+*/
+
+#define lowercase_p(c) (islower(c))
+#define uppercase_p(c) (isupper(c))
+#define digit_p(x)  (isdigit (x))
+
+#define pure_alphabetic(c) (lowercase_p(c) || uppercase_p(c))
+
+/* Old versions
+#  define to_upper(c) (lowercase_p(c) ? ((c) - 32) : (c))
+#  define to_lower(c) (uppercase_p(c) ? ((c) + 32) : (c))
+*/
+
+#ifndef to_upper
+#  define to_upper(c) (islower(c) ? toupper(c) : (c))
+#  define to_lower(c) (isupper(c) ? tolower(c) : (c))
+#endif
+
+#ifndef digit_value
+#define digit_value(x) ((x) - '0')
+#endif
+
+#ifndef NEWLINE
+#define NEWLINE '\n'
+#endif
+
+#ifndef RETURN
+#define RETURN CTRL('M')
+#endif
+
+#ifndef RUBOUT
+#define RUBOUT 0x7f
+#endif
+
+#ifndef TAB
+#define TAB '\t'
+#endif
+
+#ifdef ABORT_CHAR
+#undef ABORT_CHAR
+#endif
+#define ABORT_CHAR CTRL('G')
+
+#ifdef PAGE
+#undef PAGE
+#endif
+#define PAGE CTRL('L')
+
+#ifdef SPACE
+#undef SPACE
+#endif
+#define SPACE ' '      /* XXX - was 0x20 */
+
+#ifdef ESC
+#undef ESC
+#endif
+
+#define ESC CTRL('[')
+
+#endif  /* _CHARDEFS_H */
diff --git a/lib/readline/complete.c b/lib/readline/complete.c
new file mode 100644 (file)
index 0000000..f219877
--- /dev/null
@@ -0,0 +1,1459 @@
+/* complete.c -- filename completion for readline. */
+
+/* Copyright (C) 1987, 1989, 1992 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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#if !defined (NO_SYS_FILE)
+#  include <sys/file.h>
+#endif /* !NO_SYS_FILE */
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <errno.h>
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include <pwd.h>
+#if defined (USG) && !defined (HAVE_GETPW_DECLS)
+extern struct passwd *getpwent ();
+#endif /* USG && !HAVE_GETPW_DECLS */
+
+/* ISC systems don't define getpwent() if _POSIX_SOURCE is defined. */
+#if defined (isc386) && defined (_POSIX_SOURCE)
+#  if defined (__STDC__)
+extern struct passwd *getpwent (void);
+#  else
+extern struct passwd *getpwent ();
+#  endif /* !__STDC__ */
+#endif /* isc386 && _POSIX_SOURCE */
+
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+
+/* Possible values for do_replace in rl_complete_internal. */
+#define NO_MATCH       0
+#define SINGLE_MATCH   1
+#define MULT_MATCH     2
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+extern char *tilde_expand ();
+extern char *rl_copy_text ();
+
+extern Function *rl_last_func;
+extern int rl_editing_mode;
+extern int screenwidth;
+
+/* Forward declarations for functions defined and used in this file. */
+char *filename_completion_function ();
+char **completion_matches ();
+
+static int compare_strings ();
+static char *rl_strpbrk ();
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+\f
+/* If non-zero, then this is the address of a function to call when
+   completing on a directory name.  The function is called with
+   the address of a string (the current directory name) as an arg. */
+Function *rl_directory_completion_hook = (Function *)NULL;
+
+/* Non-zero means readline completion functions perform tilde expansion. */
+int rl_complete_with_tilde_expansion = 0;
+
+/* If non-zero, non-unique completions always show the list of matches. */
+int _rl_complete_show_all = 0;
+
+#if defined (VISIBLE_STATS)
+#  if !defined (X_OK)
+#    define X_OK 1
+#  endif
+
+static int stat_char ();
+
+/* Non-zero means add an additional character to each filename displayed
+   during listing completion iff rl_filename_completion_desired which helps
+   to indicate the type of file being listed. */
+int rl_visible_stats = 0;
+#endif /* VISIBLE_STATS */
+
+/* **************************************************************** */
+/*                                                                 */
+/*     Completion matching, from readline's point of view.         */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Pointer to the generator function for completion_matches ().
+   NULL means to use filename_entry_function (), the default filename
+   completer. */
+Function *rl_completion_entry_function = (Function *)NULL;
+
+/* Pointer to alternative function to create matches.
+   Function is called with TEXT, START, and END.
+   START and END are indices in RL_LINE_BUFFER saying what the boundaries
+   of TEXT are.
+   If this function exists and returns NULL then call the value of
+   rl_completion_entry_function to try to match, otherwise use the
+   array of strings returned. */
+CPPFunction *rl_attempted_completion_function = (CPPFunction *)NULL;
+
+/* Non-zero means to suppress normal filename completion after the
+   user-specified completion function has been called. */
+int rl_attempted_completion_over = 0;
+
+/* Local variable states what happened during the last completion attempt. */
+static int completion_changed_buffer = 0;
+
+/* Complete the word at or before point.  You have supplied the function
+   that does the initial simple matching selection algorithm (see
+   completion_matches ()).  The default is to do filename completion. */
+
+rl_complete (ignore, invoking_key)
+     int ignore, invoking_key;
+{
+  if (rl_last_func == rl_complete && !completion_changed_buffer)
+    return (rl_complete_internal ('?'));
+  else if (_rl_complete_show_all)
+    return (rl_complete_internal ('!'));
+  else
+    return (rl_complete_internal (TAB));
+}
+
+/* List the possible completions.  See description of rl_complete (). */
+rl_possible_completions (ignore, invoking_key)
+     int ignore, invoking_key;
+{
+  return (rl_complete_internal ('?'));
+}
+
+rl_insert_completions (ignore, invoking_key)
+     int ignore, invoking_key;
+{
+  return (rl_complete_internal ('*'));
+}
+
+/* The user must press "y" or "n". Non-zero return means "y" pressed. */
+get_y_or_n ()
+{
+  int c;
+
+  for (;;)
+    {
+      c = rl_read_key ();
+      if (c == 'y' || c == 'Y' || c == ' ')
+       return (1);
+      if (c == 'n' || c == 'N' || c == RUBOUT)
+       return (0);
+      if (c == ABORT_CHAR)
+       rl_abort ();
+      ding ();
+    }
+}
+
+/* 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. */
+int rl_completion_query_items = 100;
+
+/* 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\"\\'`@$><=" */
+char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(";
+
+/* The list of characters that signal a break between words for
+   rl_complete_internal.  The default list is the contents of
+   rl_basic_word_break_characters.  */
+char *rl_completer_word_break_characters = (char *)NULL;
+
+/* List of characters which can be used to quote a substring of the line.
+   Completion occurs on the entire substring, and within the substring
+   rl_completer_word_break_characters are treated as any other character,
+   unless they also appear within this list. */
+char *rl_completer_quote_characters = (char *)NULL;
+
+/* List of characters that are word break characters, but should be left
+   in TEXT when it is passed to the completion function.  The shell uses
+   this to help determine what kind of completing to do. */
+char *rl_special_prefixes = (char *)NULL;
+
+/* If non-zero, then disallow duplicates in the matches. */
+int rl_ignore_completion_duplicates = 1;
+
+/* Non-zero means that the results of the matches are to be treated
+   as filenames.  This is ALWAYS zero on entry, and can only be changed
+   within a completion entry finder function. */
+int rl_filename_completion_desired = 0;
+
+/* Non-zero means that the results of the matches are to be quoted using
+   double quotes (or an application-specific quoting mechanism) if the
+   filename contains any characters in rl_word_break_chars.  This is
+   ALWAYS non-zero on entry, and can only be changed within a completion
+   entry finder function. */
+int rl_filename_quoting_desired = 1;
+
+/* 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 (char**) known as matches in the code below.
+   It consists of a NULL-terminated array of pointers to potential
+   matching strings.  The 1st element (matches[0]) is the maximal
+   substring that is common to all matches. This function can re-arrange
+   the list of matches as required, but all elements of the array must be
+   free()'d if they are deleted. The main intent of this function is
+   to implement FIGNORE a la SunOS csh. */
+Function *rl_ignore_some_completions_function = (Function *)NULL;
+
+#if defined (SHELL)
+/* A function to strip quotes that are not protected by backquotes.  It
+   allows single quotes to appear within double quotes, and vice versa.
+   It should be smarter.  It's fairly shell-specific, hence the SHELL
+   definition wrapper. */
+static char *
+_delete_quotes (text)
+     char *text;
+{
+  char *ret, *p, *r;
+  int l, quoted;
+
+  l = strlen (text);
+  ret = xmalloc (l + 1);
+  for (quoted = 0, p = text, r = ret; p && *p; p++)
+    {
+      /* Allow backslash-quoted characters to pass through unscathed. */
+      if (*p == '\\')
+        continue;
+      /* Close quote. */
+      if (quoted && *p == quoted)
+       {
+         quoted = 0;
+         continue;
+       }
+      /* Open quote. */
+      if (quoted == 0 && (*p == '\'' || *p == '"'))
+       {
+         quoted = *p;
+         continue;
+       }
+      *r++ = *p;
+    }
+  *r = '\0';
+  return ret;
+}
+#endif /* SHELL */
+
+/* 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. */
+static char *
+printable_part (pathname)
+      char *pathname;
+{
+  char *temp = (char *)NULL;
+
+  if (rl_filename_completion_desired)
+    temp = strrchr (pathname, '/');
+
+  if (!temp)
+    return (pathname);
+  else
+    return (++temp);
+}
+
+/* Output TO_PRINT to rl_outstream.  If VISIBLE_STATS is defined and we
+   are using it, check for and output a single character for `special'
+   filenames.  Return 1 if we printed an extension character, 0 if not. */
+#define PUTX(c) \
+      if (CTRL_CHAR (c)) \
+        { \
+          putc ('^', rl_outstream); \
+          putc (UNCTRL (c), rl_outstream); \
+        } \
+      else if (c == RUBOUT) \
+        { \
+          putc ('^', rl_outstream); \
+          putc ('?', rl_outstream); \
+        } \
+      else \
+        putc (c, rl_outstream)
+
+static int
+print_filename (to_print, full_pathname)
+     char *to_print, *full_pathname;
+{
+#if !defined (VISIBLE_STATS)
+  char *s;
+
+  for (s = to_print; *s; s++)
+    {
+      PUTX (*s);
+    }
+  return 0;
+#else  
+  char *s, c, *new_full_pathname;
+  int extension_char = 0, slen, tlen;
+
+  for (s = to_print; *s; s++)
+    {
+      PUTX (*s);
+    }  
+
+  if (rl_filename_completion_desired && rl_visible_stats)
+    {
+      /* If to_print != full_pathname, to_print is the basename of the
+        path passed.  In this case, we try to expand the directory
+        name before checking for the stat character. */
+      if (to_print != full_pathname)
+       {
+         /* Terminate the directory name. */
+         c = to_print[-1];
+         to_print[-1] = '\0';
+
+         s = tilde_expand (full_pathname);
+         if (rl_directory_completion_hook)
+           (*rl_directory_completion_hook) (&s);
+
+         slen = strlen (s);
+         tlen = strlen (to_print);
+         new_full_pathname = xmalloc (slen + tlen + 2);
+         strcpy (new_full_pathname, s);
+         new_full_pathname[slen] = '/';
+         strcpy (new_full_pathname + slen + 1, to_print);
+
+         extension_char = stat_char (new_full_pathname);
+
+         free (new_full_pathname);
+         to_print[-1] = c;
+       }
+      else
+       {
+         s = tilde_expand (full_pathname);
+         extension_char = stat_char (s);
+       }
+
+      free (s);
+      if (extension_char)
+       putc (extension_char, rl_outstream);
+      return (extension_char != 0);
+    }
+  else
+    return 0;
+#endif /* VISIBLE_STATS */
+}
+
+/* Complete the word at or before point.
+   WHAT_TO_DO says what to do with the completion.
+   `?' means list the possible completions.
+   TAB means do standard completion.
+   `*' means insert all of the possible completions.
+   `!' means to do standard completion, and list all possible completions if
+   there is more than one. */
+rl_complete_internal (what_to_do)
+     int what_to_do;
+{
+  char **matches;
+  Function *our_func;
+  int start, scan, end, delimiter = 0, pass_next;
+  char *text, *saved_line_buffer;
+  char *replacement;
+  char quote_char = '\0';
+  int found_quote = 0;
+
+  if (rl_line_buffer)
+    saved_line_buffer = savestring (rl_line_buffer);
+  else
+    saved_line_buffer = (char *)NULL;
+
+  if (rl_completion_entry_function)
+    our_func = rl_completion_entry_function;
+  else
+    our_func = (Function *)filename_completion_function;
+
+  /* Only the completion entry function can change these. */
+  rl_filename_completion_desired = 0;
+  rl_filename_quoting_desired = 1;
+
+  /* We now look backwards for the start of a filename/variable word. */
+  end = rl_point;
+
+  if (rl_point)
+    {
+      if (rl_completer_quote_characters)
+       {
+         /* We have a list of characters which can be used in pairs to
+            quote substrings for the completer.  Try to find the start
+            of an unclosed quoted substring. */
+         /* FOUND_QUOTE is set so we know what kind of quotes we found. */
+         for (scan = pass_next = 0; scan < end; scan++)
+           {
+             if (pass_next)
+               {
+                 pass_next = 0;
+                 continue;
+               }
+
+             if (rl_line_buffer[scan] == '\\')
+               {
+                 pass_next = 1;
+                 found_quote |= 4;
+                 continue;
+               }
+
+             if (quote_char != '\0')
+               {
+                 /* Ignore everything until the matching close quote char. */
+                 if (rl_line_buffer[scan] == quote_char)
+                   {
+                     /* Found matching close.  Abandon this substring. */
+                     quote_char = '\0';
+                     rl_point = end;
+                   }
+               }
+             else if (strchr (rl_completer_quote_characters, rl_line_buffer[scan]))
+               {
+                 /* Found start of a quoted substring. */
+                 quote_char = rl_line_buffer[scan];
+                 rl_point = scan + 1;
+                 /* Shell-like quoting conventions. */
+                 if (quote_char == '\'')
+                   found_quote |= 1;
+                 else if (quote_char == '"')
+                   found_quote |= 2;
+               }
+           }
+       }
+
+      if (rl_point == end && quote_char == '\0')
+       {
+         int quoted = 0;
+         /* 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. */
+         while (--rl_point)
+           {
+             scan = rl_line_buffer[rl_point];
+
+             if (strchr (rl_completer_word_break_characters, scan) == 0)
+               continue;
+
+#if defined (SHELL)
+             /* Don't let word break characters in quoted substrings break
+                words for the completer. */
+             if (found_quote && char_is_quoted (rl_line_buffer, rl_point))
+               continue;
+#endif /* SHELL */
+
+             /* Convoluted code, but it avoids an n^2 algorithm with calls
+                to char_is_quoted. */
+             break;
+           }
+       }
+
+      /* If we are at an unquoted word break, then advance past it. */
+      scan = rl_line_buffer[rl_point];
+#if defined (SHELL)
+      if ((found_quote == 0 || char_is_quoted (rl_line_buffer, rl_point) == 0) &&
+          strchr (rl_completer_word_break_characters, scan))
+#else
+      if (strchr (rl_completer_word_break_characters, scan))
+#endif
+       {
+         /* If the character that caused the word break was a quoting
+            character, then remember it as the delimiter. */
+         if (strchr ("\"'", scan) && (end - rl_point) > 1)
+           delimiter = scan;
+
+         /* If the character isn't needed to determine something special
+            about what kind of completion to perform, then advance past it. */
+         if (!rl_special_prefixes || strchr (rl_special_prefixes, scan) == 0)
+           rl_point++;
+       }
+    }
+
+  /* At this point, we know we have an open quote if quote_char != '\0'. */
+  start = rl_point;
+  rl_point = end;
+  text = rl_copy_text (start, end);
+
+  /* If the user wants to TRY to complete, but then wants to give
+     up and use the default completion function, they set the
+     variable rl_attempted_completion_function. */
+  if (rl_attempted_completion_function)
+    {
+      matches = (*rl_attempted_completion_function) (text, start, end);
+
+      if (matches || rl_attempted_completion_over)
+       {
+         rl_attempted_completion_over = 0;
+         our_func = (Function *)NULL;
+         goto after_usual_completion;
+       }
+    }
+
+#if defined (SHELL)
+  /* Beware -- we're stripping the quotes here.  Do this only if we know
+     we are doing filename completion. */
+  if (found_quote && our_func == (Function *)filename_completion_function)
+    {
+      /* delete single and double quotes */
+      replacement = _delete_quotes (text);
+      free (text);
+      text = replacement;
+      replacement = (char *)0;
+    }
+#endif /* SHELL */
+
+  matches = completion_matches (text, our_func);
+
+ after_usual_completion:
+  free (text);
+
+  if (!matches)
+    ding ();
+  else
+    {
+      register int i;
+      int should_quote;
+
+      /* 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. */
+      if (rl_ignore_completion_duplicates)
+       {
+         char *lowest_common;
+         int j, newlen = 0;
+         char dead_slot;
+         char **temp_array;
+
+         /* Sort the items. */
+         /* It is safe to sort this array, because the lowest common
+            denominator found in matches[0] will remain in place. */
+         for (i = 0; matches[i]; i++)
+           ;
+         /* Try sorting the array without matches[0], since we need it to
+            stay in place no matter what. */
+         if (i)
+           qsort (matches+1, i-1, sizeof (char *), compare_strings);
+
+         /* Remember the lowest common denominator for it may be unique. */
+         lowest_common = savestring (matches[0]);
+
+         for (i = 0; matches[i + 1]; i++)
+           {
+             if (strcmp (matches[i], matches[i + 1]) == 0)
+               {
+                 free (matches[i]);
+                 matches[i] = (char *)&dead_slot;
+               }
+             else
+               newlen++;
+           }
+
+         /* We have marked all the dead slots with (char *)&dead_slot.
+            Copy all the non-dead entries into a new array. */
+         temp_array = (char **)xmalloc ((3 + newlen) * sizeof (char *));
+         for (i = j = 1; matches[i]; i++)
+           {
+             if (matches[i] != (char *)&dead_slot)
+               temp_array[j++] = matches[i];
+           }
+         temp_array[j] = (char *)NULL;
+
+         if (matches[0] != (char *)&dead_slot)
+           free (matches[0]);
+         free (matches);
+
+         matches = temp_array;
+
+         /* Place the lowest common denominator back in [0]. */
+         matches[0] = lowest_common;
+
+         /* If there is one string left, and it is identical to the
+            lowest common denominator, then the LCD is the string to
+            insert. */
+         if (j == 2 && strcmp (matches[0], matches[1]) == 0)
+           {
+             free (matches[1]);
+             matches[1] = (char *)NULL;
+           }
+       }
+
+      switch (what_to_do)
+       {
+       case TAB:
+       case '!':
+         /* If we are matching filenames, then here is our chance to
+            do clever processing by re-examining the list.  Call the
+            ignore function with the array as a parameter.  It can
+            munge the array, deleting matches as it desires. */
+         if (rl_ignore_some_completions_function &&
+             our_func == (Function *)filename_completion_function)
+           {
+             (void)(*rl_ignore_some_completions_function)(matches);
+             if (matches == 0 || matches[0] == 0)
+               {
+                 if (matches)
+                   free (matches);
+                 ding ();
+                 return;
+               }
+           }
+
+         /* If we are doing completion on quoted substrings, and any matches
+            contain any of the completer_word_break_characters, then auto-
+            matically prepend the substring with a quote character (just pick
+            the first one from the list of such) if it does not already begin
+            with a quote string.  FIXME: Need to remove any such automatically
+            inserted quote character when it no longer is necessary, such as
+            if we change the string we are completing on and the new set of
+            matches don't require a quoted substring. */
+         replacement = matches[0];
+
+         should_quote = matches[0] && rl_completer_quote_characters &&
+                        rl_filename_completion_desired &&
+                        rl_filename_quoting_desired;
+
+         if (should_quote)
+#if defined (SHELL)
+           should_quote = should_quote && (!quote_char || quote_char == '"');
+#else
+           should_quote = should_quote && !quote_char;
+#endif
+
+         if (should_quote)
+           {
+             int do_replace;
+
+             do_replace = NO_MATCH;
+
+             /* If there is a single match, see if we need to quote it.
+                This also checks whether the common prefix of several
+                matches needs to be quoted.  If the common prefix should
+                not be checked, add !matches[1] to the if clause. */
+             should_quote = rl_strpbrk (matches[0], rl_completer_word_break_characters) != 0;
+#if defined (SHELL)
+             should_quote = should_quote || rl_strpbrk (matches[0], "#$`?*[!") != 0;
+#endif
+
+             if (should_quote)
+               do_replace = matches[1] ? MULT_MATCH : SINGLE_MATCH;
+
+             if (do_replace != NO_MATCH)
+               {
+#if defined (SHELL)
+                 /* Quote the replacement, since we found an
+                    embedded word break character in a potential
+                    match. */
+                 char *rtext, *mtext;
+                 int rlen;
+                 extern char *double_quote (); /* in builtins/common.c */
+
+                 /* If DO_REPLACE == MULT_MATCH, it means that there is
+                    more than one match.  In this case, we do not add
+                    the closing quote or attempt to perform tilde
+                    expansion.  If DO_REPLACE == SINGLE_MATCH, we try
+                    to perform tilde expansion, because double quotes
+                    inhibit tilde expansion by the shell. */
+
+                 mtext = matches[0];
+                 if (mtext[0] == '~' && do_replace == SINGLE_MATCH)
+                   mtext = tilde_expand (matches[0]);
+                 rtext = double_quote (mtext);
+                 if (mtext != matches[0])
+                   free (mtext);
+
+                 rlen = strlen (rtext);
+                 replacement = xmalloc (rlen + 1);
+                 /* If we're completing on a quoted string where the user
+                    has already supplied the opening quote, we don't want
+                    the quote in the replacement text, and we reset
+                    QUOTE_CHAR to 0 to avoid an extra closing quote. */
+                 if (quote_char == '"')
+                   {
+                     strcpy (replacement, rtext + 1);
+                     rlen--;
+                     quote_char = 0;
+                   }
+                 else
+                   strcpy (replacement, rtext);
+                 if (do_replace == MULT_MATCH)
+                   replacement[rlen - 1] = '\0';
+                 free (rtext);
+#else /* !SHELL */
+                 /* Found an embedded word break character in a potential
+                    match, so we need to prepend a quote character if we
+                    are replacing the completion string. */
+                 replacement = xmalloc (strlen (matches[0]) + 2);
+                 quote_char = *rl_completer_quote_characters;
+                 *replacement = quote_char;
+                 strcpy (replacement + 1, matches[0]);
+#endif /* SHELL */
+               }
+           }
+
+         if (replacement)
+           {
+             rl_begin_undo_group ();
+             rl_delete_text (start, rl_point);
+             rl_point = start;
+             rl_insert_text (replacement);
+             rl_end_undo_group ();
+             if (replacement != matches[0])
+               free (replacement);
+           }
+
+         /* If there are more matches, ring the bell to indicate.
+            If this was the only match, and we are hacking files,
+            check the file to see if it was a directory.  If so,
+            add a '/' to the name.  If not, and we are at the end
+            of the line, then add a space. */
+         if (matches[1])
+           {
+             if (what_to_do == '!')
+               goto display_matches;           /* XXX */
+             else if (rl_editing_mode != vi_mode)
+               ding ();        /* There are other matches remaining. */
+           }
+         else
+           {
+             char temp_string[4];
+             int temp_string_index = 0;
+
+             if (quote_char)
+               temp_string[temp_string_index++] = quote_char;
+
+             temp_string[temp_string_index++] = delimiter ? delimiter : ' ';
+             temp_string[temp_string_index++] = '\0';
+
+             if (rl_filename_completion_desired)
+               {
+                 struct stat finfo;
+                 char *filename = tilde_expand (matches[0]);
+
+                 if ((stat (filename, &finfo) == 0) && S_ISDIR (finfo.st_mode))
+                   {
+                     if (rl_line_buffer[rl_point] != '/')
+                       rl_insert_text ("/");
+                   }
+                 else
+                   {
+                     if (rl_point == rl_end)
+                       rl_insert_text (temp_string);
+                   }
+                 free (filename);
+               }
+             else
+               {
+                 if (rl_point == rl_end)
+                   rl_insert_text (temp_string);
+               }
+           }
+         break;
+
+       case '*':
+         {
+           int i = 1;
+
+           rl_begin_undo_group ();
+           rl_delete_text (start, rl_point);
+           rl_point = start;
+           if (matches[1])
+             {
+               while (matches[i])
+                 {
+                   rl_insert_text (matches[i++]);
+                   rl_insert_text (" ");
+                 }
+             }
+           else
+             {
+               rl_insert_text (matches[0]);
+               rl_insert_text (" ");
+             }
+           rl_end_undo_group ();
+         }
+         break;
+
+       case '?':
+         {
+           int len, count, limit, max;
+           int j, k, l;
+
+           /* Handle simple case first.  What if there is only one answer? */
+           if (!matches[1])
+             {
+               char *temp;
+
+               temp = printable_part (matches[0]);
+               crlf ();
+               print_filename (temp, matches[0]);
+               crlf ();
+               goto restart;
+             }
+
+           /* There is more than one answer.  Find out how many there are,
+              and find out what the maximum printed length of a single entry
+              is. */
+         display_matches:
+           for (max = 0, i = 1; matches[i]; i++)
+             {
+               char *temp;
+               int name_length;
+
+               temp = printable_part (matches[i]);
+               name_length = strlen (temp);
+
+               if (name_length > max)
+                 max = name_length;
+             }
+
+           len = i - 1;
+
+           /* If there are many items, then ask the user if she
+              really wants to see them all. */
+           if (len >= rl_completion_query_items)
+             {
+               crlf ();
+               fprintf (rl_outstream,
+                        "There are %d possibilities.  Do you really", len);
+               crlf ();
+               fprintf (rl_outstream, "wish to see them all? (y or n)");
+               fflush (rl_outstream);
+               if (!get_y_or_n ())
+                 {
+                   crlf ();
+                   goto restart;
+                 }
+             }
+
+           /* How many items of MAX length can we fit in the screen window? */
+           max += 2;
+           limit = screenwidth / max;
+           if (limit != 1 && (limit * max == screenwidth))
+             limit--;
+
+           /* Avoid a possible floating exception.  If max > screenwidth,
+              limit will be 0 and a divide-by-zero fault will result. */
+           if (limit == 0)
+             limit = 1;
+
+           /* How many iterations of the printing loop? */
+           count = (len + (limit - 1)) / limit;
+
+           /* Watch out for special case.  If LEN is less than LIMIT, then
+              just do the inner printing loop.
+              0 < len <= limit  implies  count = 1. */
+
+           /* Sort the items if they are not already sorted. */
+           if (!rl_ignore_completion_duplicates)
+             qsort (matches + 1, len - 1, sizeof (char *), compare_strings);
+
+           /* Print the sorted items, up-and-down alphabetically, like
+              ls might. */
+           crlf ();
+
+           for (i = 1; i <= count; i++)
+             {
+               for (j = 0, l = i; j < limit; j++)
+                 {
+                   if (l > len || !matches[l])
+                     break;
+                   else
+                     {
+                       char *temp;
+                       int printed_length;
+
+                       temp = printable_part (matches[l]);
+                       printed_length = strlen (temp);
+                       printed_length += print_filename (temp, matches[l]);
+
+                       if (j + 1 < limit)
+                         {
+                           for (k = 0; k < max - printed_length; k++)
+                             putc (' ', rl_outstream);
+                         }
+                     }
+                   l += count;
+                 }
+               crlf ();
+             }
+         restart:
+
+           rl_on_new_line ();
+         }
+         break;
+
+       default:
+         fprintf (stderr, "\r\nreadline: bad value for what_to_do in rl_complete\n");
+         abort ();
+       }
+
+      for (i = 0; matches[i]; i++)
+       free (matches[i]);
+      free (matches);
+    }
+
+  /* Check to see if the line has changed through all of this manipulation. */
+  if (saved_line_buffer)
+    {
+      if (strcmp (rl_line_buffer, saved_line_buffer) != 0)
+       completion_changed_buffer = 1;
+      else
+       completion_changed_buffer = 0;
+
+      free (saved_line_buffer);
+    }
+  return 0;
+}
+
+#if defined (VISIBLE_STATS)
+/* Return the character which best describes FILENAME.
+     `@' for symbolic links
+     `/' for directories
+     `*' for executables
+     `=' for sockets */
+static int
+stat_char (filename)
+     char *filename;
+{
+  struct stat finfo;
+  int character, r;
+
+#if defined (S_ISLNK)
+  r = lstat (filename, &finfo);
+#else
+  r = stat (filename, &finfo);
+#endif
+
+  if (r == -1)
+    return (0);
+
+  character = 0;
+  if (S_ISDIR (finfo.st_mode))
+    character = '/';
+#if defined (S_ISLNK)
+  else if (S_ISLNK (finfo.st_mode))
+    character = '@';
+#endif /* S_ISLNK */
+#if defined (S_ISSOCK)
+  else if (S_ISSOCK (finfo.st_mode))
+    character = '=';
+#endif /* S_ISSOCK */
+  else if (S_ISREG (finfo.st_mode))
+    {
+      if (access (filename, X_OK) == 0)
+       character = '*';
+    }
+  return (character);
+}
+#endif /* VISIBLE_STATS */
+
+/* Stupid comparison routine for qsort () ing strings. */
+static int
+compare_strings (s1, s2)
+  char **s1, **s2;
+{
+  int result;
+
+  result = **s1 - **s2;
+  if (result == 0)
+    result = strcmp (*s1, *s2);
+
+  return result;
+}
+
+/* A completion function for usernames.
+   TEXT contains a partial username preceded by a random
+   character (usually `~').  */
+char *
+username_completion_function (text, state)
+     int state;
+     char *text;
+{
+#if defined (__GO32__)
+  return (char *)NULL;
+#else /* !__GO32__ */
+  static char *username = (char *)NULL;
+  static struct passwd *entry;
+  static int namelen, first_char, first_char_loc;
+
+  if (!state)
+    {
+      if (username)
+       free (username);
+
+      first_char = *text;
+
+      if (first_char == '~')
+       first_char_loc = 1;
+      else
+       first_char_loc = 0;
+
+      username = savestring (&text[first_char_loc]);
+      namelen = strlen (username);
+      setpwent ();
+    }
+
+  while (entry = getpwent ())
+    {
+      /* Null usernames should result in all users as possible completions. */
+      if (namelen == 0)
+        break;
+      else if ((username[0] == entry->pw_name[0]) &&
+              (strncmp (username, entry->pw_name, namelen) == 0))
+       break;
+    }
+
+  if (!entry)
+    {
+      endpwent ();
+      return ((char *)NULL);
+    }
+  else
+    {
+      char *value = xmalloc (2 + strlen (entry->pw_name));
+
+      *value = *text;
+
+      strcpy (value + first_char_loc, entry->pw_name);
+
+      if (first_char == '~')
+       rl_filename_completion_desired = 1;
+
+      return (value);
+    }
+#endif /* !__GO32__ */
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                          Completion                             */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero means that case is not significant in completion. */
+int completion_case_fold = 0;
+
+/* Return an array of (char *) which is a list of completions for TEXT.
+   If there are no completions, return a NULL pointer.
+   The first entry in the returned array is the substitution for TEXT.
+   The remaining entries are the possible completions.
+   The array is terminated with a NULL pointer.
+
+   ENTRY_FUNCTION is a function of two args, and returns a (char *).
+     The first argument is TEXT.
+     The second is a state argument; it should be zero on the first call, and
+     non-zero on subsequent calls.  It returns a NULL pointer to the caller
+     when there are no more matches.
+ */
+char **
+completion_matches (text, entry_function)
+     char *text;
+     CPFunction *entry_function;
+{
+  /* Number of slots in match_list. */
+  int match_list_size;
+
+  /* The list of matches. */
+  char **match_list =
+    (char **)xmalloc (((match_list_size = 10) + 1) * sizeof (char *));
+
+  /* Number of matches actually found. */
+  int matches = 0;
+
+  /* Temporary string binder. */
+  char *string;
+
+  match_list[1] = (char *)NULL;
+
+  while (string = (*entry_function) (text, matches))
+    {
+      if (matches + 1 == match_list_size)
+       match_list = (char **)xrealloc
+         (match_list, ((match_list_size += 10) + 1) * sizeof (char *));
+
+      match_list[++matches] = string;
+      match_list[matches + 1] = (char *)NULL;
+    }
+
+  /* If there were any matches, then look through them finding out the
+     lowest common denominator.  That then becomes match_list[0]. */
+  if (matches)
+    {
+      register int i = 1;
+      int low = 100000;                /* Count of max-matched characters. */
+
+      /* If only one match, just use that. */
+      if (matches == 1)
+       {
+         match_list[0] = match_list[1];
+         match_list[1] = (char *)NULL;
+       }
+      else
+       {
+         /* Otherwise, compare each member of the list with
+            the next, finding out where they stop matching. */
+
+         while (i < matches)
+           {
+             register int c1, c2, si;
+
+             if (completion_case_fold)
+               {
+                 for (si = 0;
+                      (c1 = to_lower(match_list[i][si])) &&
+                      (c2 = to_lower(match_list[i + 1][si]));
+                      si++)
+                   if (c1 != c2) break;
+               }
+             else
+               {
+                 for (si = 0;
+                      (c1 = match_list[i][si]) &&
+                      (c2 = match_list[i + 1][si]);
+                      si++)
+                   if (c1 != c2) break;
+               }
+
+             if (low > si) low = si;
+             i++;
+           }
+         match_list[0] = xmalloc (low + 1);
+         strncpy (match_list[0], match_list[1], low);
+         match_list[0][low] = '\0';
+       }
+    }
+  else                         /* There were no matches. */
+    {
+      free (match_list);
+      match_list = (char **)NULL;
+    }
+  return (match_list);
+}
+
+/* Okay, now we write the entry_function for filename completion.  In the
+   general case.  Note that completion in the shell is a little different
+   because of all the pathnames that must be followed when looking up the
+   completion for a command. */
+char *
+filename_completion_function (text, state)
+     int state;
+     char *text;
+{
+  static DIR *directory;
+  static char *filename = (char *)NULL;
+  static char *dirname = (char *)NULL;
+  static char *users_dirname = (char *)NULL;
+  static int filename_len;
+
+  struct dirent *entry = (struct dirent *)NULL;
+
+  /* If we don't have any state, then do some initialization. */
+  if (!state)
+    {
+      char *temp;
+
+      if (dirname) free (dirname);
+      if (filename) free (filename);
+      if (users_dirname) free (users_dirname);
+
+      filename = savestring (text);
+      if (!*text) text = ".";
+      dirname = savestring (text);
+
+      temp = strrchr (dirname, '/');
+
+      if (temp)
+       {
+         strcpy (filename, ++temp);
+         *temp = '\0';
+       }
+      else
+       strcpy (dirname, ".");
+
+      /* We aren't done yet.  We also support the "~user" syntax. */
+
+      /* Save the version of the directory that the user typed. */
+      users_dirname = savestring (dirname);
+      {
+       char *temp_dirname;
+       int replace_dirname;
+
+       temp_dirname = tilde_expand (dirname);
+       free (dirname);
+       dirname = temp_dirname;
+
+       replace_dirname = 0;
+       if (rl_directory_completion_hook)
+         replace_dirname = (*rl_directory_completion_hook) (&dirname);
+       if (replace_dirname)
+         {
+           free (users_dirname);
+           users_dirname = savestring (dirname);
+         }
+      }
+      directory = opendir (dirname);
+      filename_len = strlen (filename);
+
+      rl_filename_completion_desired = 1;
+    }
+
+  /* At this point we should entertain the possibility of hacking wildcarded
+     filenames, like /usr/man/man<WILD>/te<TAB>.  If the directory name
+     contains globbing characters, then build an array of directories, and
+     then map over that list while completing. */
+  /* *** UNIMPLEMENTED *** */
+
+  /* Now that we have some state, we can read the directory. */
+
+  while (directory && (entry = readdir (directory)))
+    {
+      /* Special case for no filename.
+        All entries except "." and ".." match. */
+      if (!filename_len)
+       {
+         if ((strcmp (entry->d_name, ".") != 0) &&
+             (strcmp (entry->d_name, "..") != 0))
+           break;
+       }
+      else
+       {
+         /* Otherwise, if these match up to the length of filename, then
+            it is a match. */
+           if ((entry->d_name[0] == filename[0]) &&
+               (((int)D_NAMLEN (entry)) >= filename_len) &&
+               (strncmp (filename, entry->d_name, filename_len) == 0))
+             break;
+       }
+    }
+
+  if (!entry)
+    {
+      if (directory)
+       {
+         closedir (directory);
+         directory = (DIR *)NULL;
+       }
+      if (dirname)
+       {
+         free (dirname);
+         dirname = (char *)NULL;
+       }
+      if (filename)
+       {
+         free (filename);
+         filename = (char *)NULL;
+       }
+      if (users_dirname)
+       {
+         free (users_dirname);
+         users_dirname = (char *)NULL;
+       }
+
+      return (char *)NULL;
+    }
+  else
+    {
+      char *temp;
+
+      /* dirname && (strcmp (dirname, ".") != 0) */
+      if (dirname && (dirname[0] != '.' || dirname[1]))
+       {
+         if (rl_complete_with_tilde_expansion && *users_dirname == '~')
+           {
+             int dirlen = strlen (dirname);
+             temp = xmalloc (2 + dirlen + D_NAMLEN (entry));
+             strcpy (temp, dirname);
+             /* Canonicalization cuts off any final slash present.  We need
+                to add it back. */
+             if (dirname[dirlen - 1] != '/')
+               {
+                 temp[dirlen] = '/';
+                 temp[dirlen + 1] = '\0';
+               }
+           }
+         else
+           {
+             temp = xmalloc (1 + strlen (users_dirname) + D_NAMLEN (entry));
+             strcpy (temp, users_dirname);
+           }
+
+         strcat (temp, entry->d_name);
+       }
+      else
+       temp = (savestring (entry->d_name));
+
+      return (temp);
+    }
+}
+
+/* A function for simple tilde expansion. */
+int
+rl_tilde_expand (ignore, key)
+     int ignore, key;
+{
+  register int start, end;
+  char *homedir;
+
+  end = rl_point;
+  start = end - 1;
+
+  if (rl_point == rl_end && rl_line_buffer[rl_point] == '~')
+    {
+      homedir = tilde_expand ("~");
+      goto insert;
+    }
+  else if (rl_line_buffer[start] != '~')
+    {
+      for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--);
+      start++;
+    }
+
+  end = start;
+  do
+    {
+      end++;
+    }
+  while (!whitespace (rl_line_buffer[end]) && end < rl_end);
+
+  if (whitespace (rl_line_buffer[end]) || end >= rl_end)
+    end--;
+
+  /* If the first character of the current word is a tilde, perform
+     tilde expansion and insert the result.  If not a tilde, do
+     nothing. */
+  if (rl_line_buffer[start] == '~')
+    {
+      char *temp;
+      int len;
+
+      len = end - start + 1;
+      temp = xmalloc (len + 1);
+      strncpy (temp, rl_line_buffer + start, len);
+      temp[len] = '\0';
+      homedir = tilde_expand (temp);
+      free (temp);
+
+    insert:
+      rl_begin_undo_group ();
+      rl_delete_text (start, end + 1);
+      rl_point = start;
+      rl_insert_text (homedir);
+      rl_end_undo_group ();
+    }
+
+  return (0);
+}
+
+/* Find the first occurrence in STRING1 of any character from STRING2.
+   Return a pointer to the character in STRING1. */
+static char *
+rl_strpbrk (string1, string2)
+     char *string1, *string2;
+{
+  register char *scan;
+
+  for (; *string1; string1++)
+    {
+      for (scan = string2; *scan; scan++)
+       {
+         if (*string1 == *scan)
+           {
+             return (string1);
+           }
+       }
+    }
+  return ((char *)NULL);
+}
+
+#if defined (STATIC_MALLOC)
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
diff --git a/lib/readline/display.c b/lib/readline/display.c
new file mode 100644 (file)
index 0000000..daf736c
--- /dev/null
@@ -0,0 +1,1276 @@
+/* display.c -- readline redisplay facility. */
+
+/* Copyright (C) 1987, 1989, 1992 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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+/* Global and pseudo-global variables and functions
+   imported from readline.c. */
+extern char *rl_prompt;
+extern int readline_echoing_p;
+extern char *term_clreol, *term_im, *term_ic,  *term_ei, *term_DC;
+/* Termcap variables. */
+extern char *term_up, *term_dc, *term_cr, *term_IC;
+extern int screenheight, screenwidth, screenchars;
+extern int terminal_can_insert, term_xn;
+
+extern void _rl_output_some_chars ();
+extern int _rl_output_character_function ();
+
+extern int _rl_output_meta_chars;
+extern int _rl_horizontal_scroll_mode;
+extern int _rl_mark_modified_lines;
+extern int _rl_prefer_visible_bell;
+
+/* Pseudo-global functions (local to the readline library) exported
+   by this file. */
+void _rl_move_cursor_relative (), _rl_output_some_chars ();
+void _rl_move_vert ();
+
+static void update_line (), clear_to_eol (), space_to_eol ();
+static void delete_chars (), insert_some_chars ();
+
+extern char *xmalloc (), *xrealloc ();
+
+/* Heuristic used to decide whether it is faster to move from CUR to NEW
+   by backing up or outputting a carriage return and moving forward. */
+#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Display stuff                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* This is the stuff that is hard for me.  I never seem to write good
+   display routines in C.  Let's see how I do this time. */
+
+/* (PWP) Well... Good for a simple line updater, but totally ignores
+   the problems of input lines longer than the screen width.
+
+   update_line and the code that calls it makes a multiple line,
+   automatically wrapping line update.  Careful attention needs
+   to be paid to the vertical position variables. */
+
+/* Keep two buffers; one which reflects the current contents of the
+   screen, and the other to draw what we think the new contents should
+   be.  Then compare the buffers, and make whatever changes to the
+   screen itself that we should.  Finally, make the buffer that we
+   just drew into be the one which reflects the current contents of the
+   screen, and place the cursor where it belongs.
+
+   Commands that want to can fix the display themselves, and then let
+   this function know that the display has been fixed by setting the
+   RL_DISPLAY_FIXED variable.  This is good for efficiency. */
+
+/* Global variables declared here. */
+/* What YOU turn on when you have handled all redisplay yourself. */
+int rl_display_fixed = 0;
+
+/* The stuff that gets printed out before the actual text of the line.
+   This is usually pointing to rl_prompt. */
+char *rl_display_prompt = (char *)NULL;
+
+/* Pseudo-global variables declared here. */
+/* The visible cursor position.  If you print some text, adjust this. */
+int _rl_last_c_pos = 0;
+int _rl_last_v_pos = 0;
+
+/* Number of lines currently on screen minus 1. */
+int _rl_vis_botlin = 0;
+
+/* Variables used only in this file. */
+/* The last left edge of text that was displayed.  This is used when
+   doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
+static int last_lmargin = 0;
+
+/* The line display buffers.  One is the line currently displayed on
+   the screen.  The other is the line about to be displayed. */
+static char *visible_line = (char *)NULL;
+static char *invisible_line = (char *)NULL;
+
+/* A buffer for `modeline' messages. */
+static char msg_buf[128];
+
+/* Non-zero forces the redisplay even if we thought it was unnecessary. */
+static int forced_display = 0;
+
+/* Default and initial buffer size.  Can grow. */
+static int line_size = 1024;
+
+static char *last_prompt_string = (char *)NULL;
+static char *local_prompt, *local_prompt_prefix;
+static int visible_length, prefix_length;
+
+/* The number of invisible characters in the line currently being
+   displayed on the screen. */
+static int visible_wrap_offset = 0;
+
+/* The length (buffer offset) of the first line of the last (possibly
+   multi-line) buffer displayed on the screen. */
+static int visible_first_line_len = 0;
+
+/* Expand the prompt string S and return the number of visible
+   characters in *LP, if LP is not null.  This is currently more-or-less
+   a placeholder for expansion. */
+
+/* Current implementation:
+       \001 (^A) start non-visible characters
+       \002 (^B) end non-visible characters
+   all characters except \001 and \002 (following a \001) are copied to
+   the returned string; all characters except those between \001 and
+   \002 are assumed to be `visible'. */        
+
+static char *
+expand_prompt (pmt, lp)
+     char *pmt;
+     int *lp;
+{
+  char *r, *ret, *p;
+  int l, rl, ignoring;
+
+  /* Short-circuit if we can. */
+  if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
+    {
+      r = savestring (pmt);
+      if (lp)
+       *lp = strlen (r);
+      return r;
+    }
+
+  l = pmt ? strlen (pmt) : 0;
+  r = ret = xmalloc (l + 1);
+  
+  for (rl = ignoring = 0, p = pmt; p && *p; p++)
+    {
+      /* This code strips the invisible character string markers
+        RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
+      if (*p == RL_PROMPT_START_IGNORE)
+       {
+         ignoring++;
+         continue;
+       }
+      else if (ignoring && *p == RL_PROMPT_END_IGNORE)
+       {
+         ignoring = 0;
+         continue;
+       }
+      else
+       {
+         *r++ = *p;
+         if (!ignoring)
+           rl++;
+       }
+    }
+
+  *r = '\0';
+  if (lp)
+    *lp = rl;
+  return ret;
+}
+
+/*
+ * Expand the prompt string into the various display components, if
+ * necessary.
+ *
+ * local_prompt = expanded last line of string in rl_display_prompt
+ *               (portion after the final newline)
+ * local_prompt_prefix = portion before last newline of rl_display_prompt,
+ *                      expanded via expand_prompt
+ * visible_length = number of visible characters in local_prompt
+ * prefix_length = number of visible characters in local_prompt_prefix
+ *
+ * This function is called once per call to readline().  It may also be
+ * called arbitrarily to expand the primary prompt.
+ *
+ * The return value is the number of visible characters on the last line
+ * of the (possibly multi-line) prompt.
+ */
+int
+rl_expand_prompt (prompt)
+     char *prompt;
+{
+  char *p, *t;
+  int c;
+
+  /* Clear out any saved values. */
+  if (local_prompt)
+    free (local_prompt);
+  if (local_prompt_prefix)
+    free (local_prompt_prefix);
+  local_prompt = local_prompt_prefix = (char *)0;
+
+  if (prompt == 0 || *prompt == '\0')
+    return (0);
+
+  p = strrchr (prompt, '\n');
+  if (!p)
+    {
+      /* The prompt is only one line. */
+      local_prompt = expand_prompt (prompt, &visible_length);
+      local_prompt_prefix = (char *)0;
+      return (visible_length);
+    }
+  else
+    {
+      /* The prompt spans multiple lines. */
+      t = ++p;
+      local_prompt = expand_prompt (p, &visible_length);
+      c = *t; *t = '\0';
+      /* The portion of the prompt string up to and including the
+        final newline is now null-terminated. */
+      local_prompt_prefix = expand_prompt (prompt, &prefix_length);
+      *t = c;
+      return (prefix_length);
+    }
+}
+
+/* Basic redisplay algorithm. */
+void
+rl_redisplay ()
+{
+  register int in, out, c, linenum;
+  register char *line = invisible_line;
+  int c_pos = 0, inv_botlin = 0, wrap_offset, wrap_column;
+  char *prompt_this_line;
+
+  if (!readline_echoing_p)
+    return;
+
+  if (!rl_display_prompt)
+    rl_display_prompt = "";
+
+  if (!invisible_line)
+    {
+      visible_line = xmalloc (line_size);
+      invisible_line = xmalloc (line_size);
+      line = invisible_line;
+      for (in = 0; in < line_size; in++)
+       {
+         visible_line[in] = 0;
+         invisible_line[in] = 1;
+       }
+      rl_on_new_line ();
+    }
+
+  /* Draw the line into the buffer. */
+  c_pos = -1;
+
+  /* Mark the line as modified or not.  We only do this for history
+     lines. */
+  out = 0;
+  if (_rl_mark_modified_lines && current_history () && rl_undo_list)
+    {
+      line[out++] = '*';
+      line[out] = '\0';
+    }
+
+  /* If someone thought that the redisplay was handled, but the currently
+     visible line has a different modification state than the one about
+     to become visible, then correct the caller's misconception. */
+  if (visible_line[0] != invisible_line[0])
+    rl_display_fixed = 0;
+
+  /* If the prompt to be displayed is the `primary' readline prompt (the
+     one passed to readline()), use the values we have already expanded.
+     If not, use what's already in rl_display_prompt.  WRAP_OFFSET is the
+     number of non-visible characters in the prompt string. */
+  if (rl_display_prompt == rl_prompt)
+    {
+      int local_len = local_prompt ? strlen (local_prompt) : 0;
+      if (local_prompt_prefix && forced_display)
+       _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
+
+      if (local_len > 0)
+       strncpy (line + out, local_prompt, local_len);
+      out += local_len;
+      line[out] = '\0';
+      wrap_offset = local_len - visible_length;
+    }
+  else
+    {
+      int pmtlen;
+      prompt_this_line = strrchr (rl_display_prompt, '\n');
+      if (!prompt_this_line)
+       prompt_this_line = rl_display_prompt;
+      else
+       {
+         prompt_this_line++;
+         if (forced_display)
+           _rl_output_some_chars (rl_display_prompt, prompt_this_line - rl_display_prompt);
+       }
+
+      pmtlen = strlen (prompt_this_line);
+      strncpy (line + out,  prompt_this_line, pmtlen);
+      out += pmtlen;
+      line[out] = '\0';
+      wrap_offset = 0;
+    }
+
+  for (in = 0; in < rl_end; in++)
+    {
+      c = (unsigned char)rl_line_buffer[in];
+
+      if (out + 8 >= line_size)                /* XXX - 8 for \t */
+       {
+         line_size *= 2;
+         visible_line = xrealloc (visible_line, line_size);
+         invisible_line = xrealloc (invisible_line, line_size);
+         line = invisible_line;
+       }
+
+      if (in == rl_point)
+       c_pos = out;
+
+      if (META_CHAR (c))
+       {
+         if (_rl_output_meta_chars == 0)
+           {
+             sprintf (line + out, "\\%o", c);
+             out += 4;
+           }
+         else
+           line[out++] = c;      
+       }
+#if defined (DISPLAY_TABS)
+      else if (c == '\t')
+       {
+         register int newout = (out | (int)7) + 1;
+         while (out < newout)
+           line[out++] = ' ';
+       }
+#endif
+      else if (c < ' ')
+       {
+         line[out++] = '^';
+         line[out++] = UNCTRL (c);     /* XXX was c ^ 0x40 */
+       }
+      else if (c == 127)
+       {
+         line[out++] = '^';
+         line[out++] = '?';
+       }
+      else
+       line[out++] = c;
+    }
+  line[out] = '\0';
+  if (c_pos < 0)
+    c_pos = out;
+
+  /* C_POS == position in buffer where cursor should be placed. */
+
+  /* PWP: now is when things get a bit hairy.  The visible and invisible
+     line buffers are really multiple lines, which would wrap every
+     (screenwidth - 1) characters.  Go through each in turn, finding
+     the changed region and updating it.  The line order is top to bottom. */
+
+  /* If we can move the cursor up and down, then use multiple lines,
+     otherwise, let long lines display in a single terminal line, and
+     horizontally scroll it. */
+
+  if (!_rl_horizontal_scroll_mode && term_up && *term_up)
+    {
+      int total_screen_chars = screenchars;
+      int nleft, cursor_linenum, pos, changed_screen_line;
+
+      if (!rl_display_fixed || forced_display)
+       {
+         forced_display = 0;
+
+         /* If we have more than a screenful of material to display, then
+            only display a screenful.  We should display the last screen,
+            not the first.  I'll fix this in a minute. */
+         if (out >= total_screen_chars)
+           out = total_screen_chars - 1;
+
+         /* Number of screen lines to display.  The first line wraps at
+            (screenwidth + wrap_offset) chars, the rest of the lines have
+            screenwidth chars. */
+         nleft = out - wrap_offset + term_xn - 1;
+         inv_botlin = (nleft > 0) ? nleft / screenwidth : 0;
+
+         /* The first line is at character position 0 in the buffer.  The
+            second and subsequent lines start at N * screenwidth, offset by
+            OFFSET.  OFFSET is wrap_offset for the invisible line and
+            visible_wrap_offset for the line currently displayed. */
+
+#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
+#define L_OFFSET(n, offset) ((n) > 0 ? ((n) * screenwidth) + (offset) : 0)
+#define VIS_CHARS(line) &visible_line[L_OFFSET((line), visible_wrap_offset)]
+#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
+#define INV_LINE(line) &invisible_line[L_OFFSET((line), wrap_offset)]
+
+         /* For each line in the buffer, do the updating display. */
+         for (linenum = 0; linenum <= inv_botlin; linenum++)
+           {
+             update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
+                          screenwidth + W_OFFSET(linenum, visible_wrap_offset),
+                          screenwidth + W_OFFSET(linenum, wrap_offset),
+                          inv_botlin);
+
+             /* If this is the line with the prompt, we might need to
+                compensate for invisible characters in the new line. Do
+                this only if there is not more than one new line (which
+                implies that we completely overwrite the old visible line)
+                and the new line is shorter than the old. */
+             if (linenum == 0 &&
+                 inv_botlin == 0 &&
+                 (wrap_offset > visible_wrap_offset) &&
+                 (_rl_last_c_pos < visible_first_line_len))
+               {
+                 nleft = screenwidth + wrap_offset - _rl_last_c_pos;
+                 if (nleft)
+                   clear_to_eol (nleft);
+               }
+
+             /* Since the new first line is now visible, save its length. */
+             if (linenum == 0)
+               visible_first_line_len = (inv_botlin > 0) ? screenwidth : out - wrap_offset;
+           }
+
+         /* We may have deleted some lines.  If so, clear the left over
+            blank ones at the bottom out. */
+         if (_rl_vis_botlin > inv_botlin)
+           {
+             char *tt;
+             for (; linenum <= _rl_vis_botlin; linenum++)
+               {
+                 tt = VIS_CHARS (linenum);
+                 _rl_move_vert (linenum);
+                 _rl_move_cursor_relative (0, tt);
+                 clear_to_eol
+                   ((linenum == _rl_vis_botlin) ? strlen (tt) : screenwidth);
+               }
+           }
+         _rl_vis_botlin = inv_botlin;
+
+         /* Move the cursor where it should be. */
+         /* Which line? */
+         nleft = c_pos - wrap_offset + term_xn - 1;
+         cursor_linenum = (nleft > 0) ? nleft / screenwidth : 0;
+
+         /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
+            different screen line during this redisplay. */
+         changed_screen_line = _rl_last_v_pos != cursor_linenum;
+         if (changed_screen_line)
+           {
+             _rl_move_vert (cursor_linenum);
+             /* If we moved up to the line with the prompt using term_up,
+                the physical cursor position on the screen stays the same,
+                but the buffer position needs to be adjusted to account
+                for invisible characters. */
+             if (cursor_linenum == 0 && wrap_offset)
+               _rl_last_c_pos += wrap_offset;
+           }
+
+         /* We have to reprint the prompt if it contains invisible
+            characters, since it's not generally OK to just reprint
+            the characters from the current cursor position. */
+         nleft = visible_length + wrap_offset;
+         if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
+             _rl_last_c_pos <= nleft && local_prompt)
+           {
+             if (term_cr)
+               tputs (term_cr, 1, _rl_output_character_function);
+             _rl_output_some_chars (local_prompt, nleft);
+             _rl_last_c_pos = nleft;
+           }
+
+         /* Where on that line?  And where does that line start
+            in the buffer? */
+         pos = L_OFFSET(cursor_linenum, wrap_offset);
+         /* nleft == number of characters in the line buffer between the
+            start of the line and the cursor position. */
+         nleft = c_pos - pos;
+
+         /* Since backspace() doesn't know about invisible characters in the
+            prompt, and there's no good way to tell it, we compensate for
+            those characters here and call backspace() directly. */
+         if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
+           {
+             backspace (_rl_last_c_pos - nleft);
+             _rl_last_c_pos = nleft;
+           }
+
+         if (nleft != _rl_last_c_pos)
+           _rl_move_cursor_relative (nleft, &invisible_line[pos]);
+       }
+    }
+  else                         /* Do horizontal scrolling. */
+    {
+#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
+      int lmargin, ndisp, nleft, phys_c_pos, t;
+
+      /* Always at top line. */
+      _rl_last_v_pos = 0;
+
+      /* Compute where in the buffer the displayed line should start.  This
+        will be LMARGIN. */
+
+      /* The number of characters that will be displayed before the cursor. */
+      ndisp = c_pos - wrap_offset;
+      nleft  = visible_length + wrap_offset;
+      /* Where the new cursor position will be on the screen.  This can be
+         longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
+      phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
+      t = screenwidth / 3;
+
+      /* If the number of characters had already exceeded the screenwidth,
+         last_lmargin will be > 0. */
+
+      /* If the number of characters to be displayed is more than the screen
+         width, compute the starting offset so that the cursor is about
+         two-thirds of the way across the screen. */
+      if (phys_c_pos > screenwidth - 2)
+       {
+         lmargin = c_pos - (2 * t);
+         if (lmargin < 0)
+           lmargin = 0;
+         /* If the left margin would be in the middle of a prompt with
+            invisible characters, don't display the prompt at all. */
+         if (wrap_offset && lmargin > 0 && lmargin < nleft)
+           lmargin = nleft;
+       }
+      else if (ndisp < screenwidth - 2)                /* XXX - was -1 */
+        lmargin = 0;
+      else if (phys_c_pos < 1)
+       {
+         /* If we are moving back towards the beginning of the line and
+            the last margin is no longer correct, compute a new one. */
+         lmargin = ((c_pos - 1) / t) * t;      /* XXX */
+         if (wrap_offset && lmargin > 0 && lmargin < nleft)
+           lmargin = nleft;
+       }
+      else
+        lmargin = last_lmargin;
+
+      /* If the first character on the screen isn't the first character
+        in the display line, indicate this with a special character. */
+      if (lmargin > 0)
+       line[lmargin] = '<';
+
+      /* If SCREENWIDTH characters starting at LMARGIN do not encompass
+         the whole line, indicate that with a special characters at the
+         right edge of the screen.  If LMARGIN is 0, we need to take the
+         wrap offset into account. */
+      t = lmargin + M_OFFSET (lmargin, wrap_offset) + screenwidth;
+      if (t < out)
+        line[t - 1] = '>';
+
+      if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
+       {
+         forced_display = 0;
+         update_line (&visible_line[last_lmargin],
+                      &invisible_line[lmargin],
+                      0,
+                      screenwidth + visible_wrap_offset,
+                      screenwidth + (lmargin ? 0 : wrap_offset),
+                      0);
+
+         /* If the visible new line is shorter than the old, but the number
+            of invisible characters is greater, and we are at the end of
+            the new line, we need to clear to eol. */
+         t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
+         if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
+             (_rl_last_c_pos == out) &&
+             t < visible_first_line_len)
+           {
+             nleft = screenwidth - t;
+             clear_to_eol (nleft);
+           }
+         visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
+         if (visible_first_line_len > screenwidth)
+           visible_first_line_len = screenwidth;
+
+         _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
+         last_lmargin = lmargin;
+       }
+    }
+  fflush (rl_outstream);
+
+  /* Swap visible and non-visible lines. */
+  {
+    char *temp = visible_line;
+    visible_line = invisible_line;
+    invisible_line = temp;
+    rl_display_fixed = 0;
+    /* If we are displaying on a single line, and last_lmargin is > 0, we
+       are not displaying any invisible characters, so set visible_wrap_offset
+       to 0. */
+    if (_rl_horizontal_scroll_mode && last_lmargin)
+      visible_wrap_offset = 0;
+    else
+      visible_wrap_offset = wrap_offset;
+  }
+}
+
+/* PWP: update_line() is based on finding the middle difference of each
+   line on the screen; vis:
+
+                            /old first difference
+       /beginning of line   |        /old last same       /old EOL
+       v                    v        v             v
+old:   eddie> Oh, my little gruntle-buggy is to me, as lurgid as
+new:   eddie> Oh, my little buggy says to me, as lurgid as
+       ^                    ^  ^                          ^
+       \beginning of line   |  \new last same     \new end of line
+                            \new first difference
+
+   All are character pointers for the sake of speed.  Special cases for
+   no differences, as well as for end of line additions must be handeled.
+
+   Could be made even smarter, but this works well enough */
+static void
+update_line (old, new, current_line, omax, nmax, inv_botlin)
+     register char *old, *new;
+     int current_line, omax, nmax;
+{
+  register char *ofd, *ols, *oe, *nfd, *nls, *ne;
+  int temp, lendiff, wsatend, od, nd;
+
+  /* If we're at the right edge of a terminal that supports xn, we're
+     ready to wrap around, so do so.  This fixes problems with knowing
+     the exact cursor position and cut-and-paste with certain terminal
+     emulators.  In this calculation, TEMP is the physical screen
+     position of the cursor. */
+  temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
+  if (temp == screenwidth && term_xn && !_rl_horizontal_scroll_mode
+      && _rl_last_v_pos == current_line - 1)
+    {
+      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. */
+  for (ofd = old, nfd = new;
+       (ofd - old < omax) && *ofd && (*ofd == *nfd);
+       ofd++, nfd++)
+    ;
+
+  /* Move to the end of the screen line.  ND and OD are used to keep track
+     of the distance between ne and new and oe and old, respectively, to
+     move a subtraction out of each loop. */
+  for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
+  for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
+
+  /* If no difference, continue to next line. */
+  if (ofd == oe && nfd == ne)
+    return;
+
+  wsatend = 1;                 /* flag for trailing whitespace */
+  ols = oe - 1;                        /* find last same */
+  nls = ne - 1;
+  while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
+    {
+      if (*ols != ' ')
+       wsatend = 0;
+      ols--;
+      nls--;
+    }
+
+  if (wsatend)
+    {
+      ols = oe;
+      nls = ne;
+    }
+  else if (*ols != *nls)
+    {
+      if (*ols)                        /* don't step past the NUL */
+       ols++;
+      if (*nls)
+       nls++;
+    }
+
+  _rl_move_vert (current_line);
+
+  /* If this is the first line and there are invisible characters in the
+     prompt string, and the prompt string has not changed, then redraw
+     the entire prompt string.  We can only do this reliably if the
+     terminal supports a `cr' capability.
+
+     This is more than just an efficiency hack -- there is a problem with
+     redrawing portions of the prompt string if they contain terminal
+     escape sequences (like drawing the `unbold' sequence without a
+     corresponding `bold') that manifests itself on certain terminals. */
+
+  lendiff = local_prompt ? strlen (local_prompt) : 0;
+  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
+      lendiff > visible_length &&
+      _rl_last_c_pos > 0 && (ofd - old) >= lendiff && term_cr)
+    {
+      tputs (term_cr, 1, _rl_output_character_function);
+      _rl_output_some_chars (local_prompt, lendiff);
+      _rl_last_c_pos = lendiff;
+    }
+
+  _rl_move_cursor_relative (ofd - old, old);
+
+  /* if (len (new) > len (old)) */
+  lendiff = (nls - nfd) - (ols - ofd);
+
+  /* Insert (diff (len (old), len (new)) ch. */
+  temp = ne - nfd;
+  if (lendiff > 0)
+    {
+      /* Non-zero if we're increasing the number of lines. */
+      int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
+      /* Sometimes it is cheaper to print the characters rather than
+        use the terminal's capabilities.  If we're growing the number
+        of lines, make sure we actually cause the new line to wrap
+        around on auto-wrapping terminals. */
+      if (terminal_can_insert && ((2 * temp) >= lendiff || term_IC) && (!term_xn || !gl))
+       {
+         /* If lendiff > visible_length and _rl_last_c_pos == 0 and
+            _rl_horizontal_scroll_mode == 1, inserting the characters with
+            term_IC or term_ic will screw up the screen because of the
+            invisible characters.  We need to just draw them. */
+         if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
+                       lendiff <= visible_length))
+           {
+             insert_some_chars (nfd, lendiff);
+             _rl_last_c_pos += lendiff;
+           }
+         else
+           {
+             /* At the end of a line the characters do not have to
+                be "inserted".  They can just be placed on the screen. */
+             _rl_output_some_chars (nfd, lendiff);
+             _rl_last_c_pos += lendiff;
+           }
+         /* Copy (new) chars to screen from first diff to last match. */
+         temp = nls - nfd;
+         if ((temp - lendiff) > 0)
+           {
+             _rl_output_some_chars (nfd + lendiff, temp - lendiff);
+             _rl_last_c_pos += temp - lendiff;
+           }
+       }
+      else
+       {
+         /* cannot insert chars, write to EOL */
+         _rl_output_some_chars (nfd, temp);
+         _rl_last_c_pos += temp;
+       }
+    }
+  else                         /* Delete characters from line. */
+    {
+      /* If possible and inexpensive to use terminal deletion, then do so. */
+      if (term_dc && (2 * temp) >= -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;
+
+         if (lendiff)
+           delete_chars (-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;
+           }
+       }
+      /* Otherwise, print over the existing material. */
+      else
+       {
+         if (temp > 0)
+           {
+             _rl_output_some_chars (nfd, temp);
+             _rl_last_c_pos += temp;
+           }
+         lendiff = (oe - old) - (ne - new);
+         if (term_xn && current_line < inv_botlin)
+           space_to_eol (lendiff);
+         else
+           clear_to_eol (lendiff);
+       }
+    }
+}
+
+/* Tell the update routines that we have moved onto a new (empty) line. */
+rl_on_new_line ()
+{
+  if (visible_line)
+    visible_line[0] = '\0';
+
+  _rl_last_c_pos = _rl_last_v_pos = 0;
+  _rl_vis_botlin = last_lmargin = 0;
+  return 0;
+}
+
+/* Actually update the display, period. */
+rl_forced_update_display ()
+{
+  if (visible_line)
+    {
+      register char *temp = visible_line;
+
+      while (*temp) *temp++ = '\0';
+    }
+  rl_on_new_line ();
+  forced_display++;
+  rl_redisplay ();
+  return 0;
+}
+
+/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
+   DATA is the contents of the screen line of interest; i.e., where
+   the movement is being done. */
+void
+_rl_move_cursor_relative (new, data)
+     int new;
+     char *data;
+{
+  register int i;
+
+  /* If we don't have to do anything, then return. */
+  if (_rl_last_c_pos == new) return;
+
+  /* It may be faster to output a CR, and then move forwards instead
+     of moving backwards. */
+  /* i == current physical cursor position. */
+  i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
+  if (CR_FASTER (new, _rl_last_c_pos) || (term_xn && i == screenwidth))
+    {
+#if defined (__MSDOS__)
+      putc ('\r', rl_outstream);
+#else
+      tputs (term_cr, 1, _rl_output_character_function);
+#endif /* !__MSDOS__ */
+      _rl_last_c_pos = 0;
+    }
+
+  if (_rl_last_c_pos < new)
+    {
+      /* Move the cursor forward.  We do it by printing the command
+        to move the cursor forward if there is one, else print that
+        portion of the output buffer again.  Which is cheaper? */
+
+      /* The above comment is left here for posterity.  It is faster
+        to print one character (non-control) than to print a control
+        sequence telling the terminal to move forward one character.
+        That kind of control is for people who don't know what the
+        data is underneath the cursor. */
+#if defined (HACK_TERMCAP_MOTION)
+      extern char *term_forward_char;
+
+      if (term_forward_char)
+       for (i = _rl_last_c_pos; i < new; i++)
+         tputs (term_forward_char, 1, _rl_output_character_function);
+      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 */
+    }
+  else if (_rl_last_c_pos != new)
+    backspace (_rl_last_c_pos - new);
+  _rl_last_c_pos = new;
+}
+
+/* PWP: move the cursor up or down. */
+void
+_rl_move_vert (to)
+     int to;
+{
+  register int delta, i;
+
+  if (_rl_last_v_pos == to || to > screenheight)
+    return;
+
+#if defined (__GO32__)
+  {
+    int row, col;
+
+    ScreenGetCursor (&row, &col);
+    ScreenSetCursor ((row + to - _rl_last_v_pos), col);
+  }
+#else /* !__GO32__ */
+
+  if ((delta = to - _rl_last_v_pos) > 0)
+    {
+      for (i = 0; i < delta; i++)
+       putc ('\n', rl_outstream);
+      tputs (term_cr, 1, _rl_output_character_function);
+      _rl_last_c_pos = 0;
+    }
+  else
+    {                  /* delta < 0 */
+      if (term_up && *term_up)
+       for (i = 0; i < -delta; i++)
+         tputs (term_up, 1, _rl_output_character_function);
+    }
+#endif /* !__GO32__ */
+  _rl_last_v_pos = to;         /* Now TO is here */
+}
+
+/* Physically print C on rl_outstream.  This is for functions which know
+   how to optimize the display.  Return the number of characters output. */
+rl_show_char (c)
+     int c;
+{
+  int n = 1;
+  if (META_CHAR (c) && (_rl_output_meta_chars == 0))
+    {
+      fprintf (rl_outstream, "M-");
+      n += 2;
+      c = UNMETA (c);
+    }
+
+#if defined (DISPLAY_TABS)
+  if (c < 32 && c != '\t')
+#else
+  if (c < 32)
+#endif /* !DISPLAY_TABS */
+    {
+      fprintf (rl_outstream, "C-");
+      n += 2;
+      c += 64;
+    }
+
+  putc (c, rl_outstream);
+  fflush (rl_outstream);
+  return n;
+}
+
+int
+rl_character_len (c, pos)
+     register int c, pos;
+{
+  unsigned char uc;
+
+  uc = (unsigned char)c;
+
+  if (META_CHAR (uc))
+    return ((_rl_output_meta_chars == 0) ? 4 : 1);
+
+  if (uc == '\t')
+    {
+#if defined (DISPLAY_TABS)
+      return (((pos | 7) + 1) - pos);
+#else
+      return (2);
+#endif /* !DISPLAY_TABS */
+    }
+
+  return ((isprint (uc)) ? 1 : 2);
+}
+
+/* How to print things in the "echo-area".  The prompt is treated as a
+   mini-modeline. */
+
+#if defined (HAVE_VARARGS_H)
+rl_message (va_alist)
+     va_dcl
+{
+  char *format;
+  va_list args;
+
+  va_start (args);
+  format = va_arg (args, char *);
+  vsprintf (msg_buf, format, args);
+  va_end (args);
+
+  rl_display_prompt = msg_buf;
+  rl_redisplay ();
+  return 0;
+}
+#else /* !HAVE_VARARGS_H */
+rl_message (format, arg1, arg2)
+     char *format;
+{
+  sprintf (msg_buf, format, arg1, arg2);
+  rl_display_prompt = msg_buf;
+  rl_redisplay ();
+  return 0;
+}
+#endif /* !HAVE_VARARGS_H */
+
+/* How to clear things from the "echo-area". */
+rl_clear_message ()
+{
+  rl_display_prompt = rl_prompt;
+  rl_redisplay ();
+  return 0;
+}
+
+rl_reset_line_state ()
+{
+  rl_on_new_line ();
+
+  rl_display_prompt = rl_prompt ? rl_prompt : "";
+  forced_display = 1;
+  return 0;
+}
+
+/* Quick redisplay hack when erasing characters at the end of the line. */
+void
+_rl_erase_at_end_of_line (l)
+     int l;
+{
+  register int i;
+
+  backspace (l);
+  for (i = 0; i < l; i++)
+    putc (' ', rl_outstream);
+  backspace (l);
+  for (i = 0; i < l; i++)
+    visible_line[--_rl_last_c_pos] = '\0';
+  rl_display_fixed++;
+}
+
+/* Clear to the end of the line.  COUNT is the minimum
+   number of character spaces to clear, */
+static void
+clear_to_eol (count)
+     int count;
+{
+#if !defined (__GO32__)
+  if (term_clreol)
+    {
+      tputs (term_clreol, 1, _rl_output_character_function);
+    }
+  else
+#endif /* !__GO32__ */
+    space_to_eol (count);
+}
+
+/* Clear to the end of the line using spaces.  COUNT is the minimum
+   number of character spaces to clear, */
+static void
+space_to_eol (count)
+     int count;
+{
+  register int i;
+
+  for (i = 0; i < count; i++)
+   putc (' ', rl_outstream);
+
+  _rl_last_c_pos += count;
+}
+
+/* Insert COUNT characters from STRING to the output stream. */
+static void
+insert_some_chars (string, count)
+     char *string;
+     int count;
+{
+#if defined (__GO32__)
+  int row, col, width;
+  char *row_start;
+
+  ScreenGetCursor (&row, &col);
+  width = ScreenCols ();
+  row_start = ScreenPrimary + (row * width);
+
+  memcpy (row_start + col + count, row_start + col, width - col - count);
+
+  /* Place the text on the screen. */
+  _rl_output_some_chars (string, count);
+#else /* !_GO32 */
+
+  /* If IC is defined, then we do not have to "enter" insert mode. */
+  if (term_IC)
+    {
+      char *tgoto (), *buffer;
+      buffer = tgoto (term_IC, 0, count);
+      tputs (buffer, 1, _rl_output_character_function);
+      _rl_output_some_chars (string, count);
+    }
+  else
+    {
+      register int i;
+
+      /* If we have to turn on insert-mode, then do so. */
+      if (term_im && *term_im)
+       tputs (term_im, 1, _rl_output_character_function);
+
+      /* If there is a special command for inserting characters, then
+        use that first to open up the space. */
+      if (term_ic && *term_ic)
+       {
+         for (i = count; i--; )
+           tputs (term_ic, 1, _rl_output_character_function);
+       }
+
+      /* Print the text. */
+      _rl_output_some_chars (string, count);
+
+      /* If there is a string to turn off insert mode, we had best use
+        it now. */
+      if (term_ei && *term_ei)
+       tputs (term_ei, 1, _rl_output_character_function);
+    }
+#endif /* !__GO32__ */
+}
+
+/* Delete COUNT characters from the display line. */
+static void
+delete_chars (count)
+     int count;
+{
+#if defined (__GO32__)
+  int row, col, width;
+  char *row_start;
+
+  ScreenGetCursor (&row, &col);
+  width = ScreenCols ();
+  row_start = ScreenPrimary + (row * width);
+
+  memcpy (row_start + col, row_start + col + count, width - col - count);
+  memset (row_start + width - count, 0, count * 2);
+#else /* !_GO32 */
+
+  if (count > screenwidth)     /* XXX */
+    return;
+
+  if (term_DC && *term_DC)
+    {
+      char *tgoto (), *buffer;
+      buffer = tgoto (term_DC, count, count);
+      tputs (buffer, count, _rl_output_character_function);
+    }
+  else
+    {
+      if (term_dc && *term_dc)
+       while (count--)
+         tputs (term_dc, 1, _rl_output_character_function);
+    }
+#endif /* !__GO32__ */
+}
+
+void
+_rl_update_final ()
+{
+  int full_lines;
+
+  full_lines = 0;
+  if (_rl_vis_botlin && visible_line[screenwidth * _rl_vis_botlin] == 0)
+    {
+      _rl_vis_botlin--;
+      full_lines = 1;
+    }
+  _rl_move_vert (_rl_vis_botlin);
+  if (full_lines && term_xn)
+    {
+      /* Remove final line-wrap flag in xterm. */
+      char *last_line;
+      last_line = &visible_line[screenwidth * _rl_vis_botlin];
+      _rl_move_cursor_relative (screenwidth - 1, last_line);
+      clear_to_eol (0);
+      putc (last_line[screenwidth - 1], rl_outstream);
+    }
+  _rl_vis_botlin = 0;
+  crlf ();
+  fflush (rl_outstream);
+  rl_display_fixed++;
+}
+
+/* Move to the start of the current line. */
+static void
+cr ()
+{
+  if (term_cr)
+    {
+      tputs (term_cr, 1, _rl_output_character_function);
+      _rl_last_c_pos = 0;
+    }
+}
+
+/* Redisplay the current line after a SIGWINCH is received. */
+void
+_rl_redisplay_after_sigwinch ()
+{
+  char *t, *oldp;
+
+  /* Clear the current line and put the cursor at column 0.  Make sure
+     the right thing happens if we have wrapped to a new screen line. */
+  if (term_cr)
+    {
+      tputs (term_cr, 1, _rl_output_character_function);
+      _rl_last_c_pos = 0;
+      if (term_clreol)
+       tputs (term_clreol, 1, _rl_output_character_function);
+      else
+       {
+         space_to_eol (screenwidth);
+         tputs (term_cr, 1, _rl_output_character_function);
+       }
+      if (_rl_last_v_pos > 0)
+       _rl_move_vert (0);
+    }
+  else
+    crlf ();
+
+  /* Redraw only the last line of a multi-line prompt. */
+  t = strrchr (rl_display_prompt, '\n');
+  if (t)
+    {
+      oldp = rl_display_prompt;
+      rl_display_prompt = ++t;
+      rl_forced_update_display ();
+      rl_display_prompt = oldp;
+    }
+  else
+    rl_forced_update_display ();
+}
diff --git a/lib/readline/doc/Makefile b/lib/readline/doc/Makefile
new file mode 100644 (file)
index 0000000..72b8ce7
--- /dev/null
@@ -0,0 +1,55 @@
+# This makefile for History library documentation is in -*- text -*- mode.
+# Emacs likes it that way.
+
+DOC_SUPPORT = ../../doc-support/
+TEXINDEX    = $(DOC_SUPPORT)/texindex
+
+TEX    = tex
+
+RLSRC = rlman.texinfo rluser.texinfo rltech.texinfo
+HISTSRC = hist.texinfo hsuser.texinfo hstech.texinfo
+
+DVIOBJ = readline.dvi history.dvi
+INFOOBJ = readline.info history.info
+PSOBJ = readline.ps history.ps
+
+all: info dvi
+
+readline.dvi: $(RLSRC)
+       $(TEX) rlman.texinfo
+       $(TEXINDEX) rlman.??
+       $(TEX) rlman.texinfo
+       mv rlman.dvi readline.dvi
+
+readline.info: $(RLSRC)
+       makeinfo rlman.texinfo
+
+history.dvi: ${HISTSRC}
+       $(TEX) hist.texinfo
+       $(TEXINDEX) hist.??
+       $(TEX) hist.texinfo
+       mv hist.dvi history.dvi
+
+history.info: ${HISTSRC}
+       makeinfo hist.texinfo
+
+readline.ps:   readline.dvi
+       dvips -D 300 -o $@ readline.dvi
+
+history.ps:    history.dvi
+       dvips -D 300 -o $@ history.dvi
+
+info:  $(INFOOBJ)
+dvi:   $(DVIOBJ)
+ps:    $(PSOBJ)
+
+
+$(TEXINDEX):
+       (cd $(DOC_SUPPORT); $(MAKE) $(MFLAGS) CFLAGS='$(CFLAGS)' texindex)
+
+distclean mostlyclean clean:
+       rm -f *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps *.pgs \
+             *.fns *.kys *.tps *.vrs *.o core
+
+maintainer-clean realclean:    clean
+       rm -f *.dvi *.info *.info-*  *.ps
diff --git a/lib/readline/doc/hist.texinfo b/lib/readline/doc/hist.texinfo
new file mode 100644 (file)
index 0000000..cc80efa
--- /dev/null
@@ -0,0 +1,113 @@
+\input texinfo    @c -*-texinfo-*-
+@c %**start of header (This is for running Texinfo on a region.)
+@setfilename history.info
+@settitle GNU History Library
+@c %**end of header (This is for running Texinfo on a region.)
+
+@setchapternewpage odd
+
+@ignore
+last change: Wed Jul 20 09:57:17 EDT 1994
+@end ignore
+
+@set EDITION 2.0
+@set VERSION 2.0
+@set UPDATED 20 July 1994
+@set UPDATE-MONTH July 1994
+
+@ifinfo
+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, 1991 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+pare preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@titlepage
+@sp 10
+@title GNU History Library
+@subtitle Edition @value{EDITION}, for @code{History Library} Version @value{VERSION}.
+@subtitle @value{UPDATE-MONTH}
+@author Brian Fox, Free Software Foundation
+@author Chet Ramey, Case Western Reserve University
+
+@page
+This document describes the GNU History library, a programming tool that
+provides a consistent user interface for recalling lines of previously
+typed input.
+
+Published by the Free Software Foundation @*
+675 Massachusetts Avenue, @*
+Cambridge, MA 02139 USA
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
+@end titlepage
+
+@ifinfo
+@node Top
+@top GNU History Library
+
+This document describes the GNU History library, a programming tool that
+provides a consistent user interface for recalling lines of previously
+typed input.
+
+@menu
+* Using History Interactively::          GNU History User's Manual.
+* Programming with GNU History::  GNU History Programmer's Manual.
+* Concept Index::                Index of concepts described in this manual.
+* Function and Variable Index::          Index of externally visible functions
+                                 and variables.
+@end menu
+@end ifinfo
+
+@syncodeindex fn vr
+
+@include hsuser.texinfo
+@include hstech.texinfo
+
+@node Concept Index
+@appendix Concept Index
+@printindex cp
+
+@node Function and Variable Index
+@appendix Function and Variable Index
+@printindex vr
+
+@contents
+@bye
diff --git a/lib/readline/doc/history.dvi b/lib/readline/doc/history.dvi
new file mode 100644 (file)
index 0000000..60d7376
Binary files /dev/null and b/lib/readline/doc/history.dvi differ
diff --git a/lib/readline/doc/history.info b/lib/readline/doc/history.info
new file mode 100644 (file)
index 0000000..6df0bd9
--- /dev/null
@@ -0,0 +1,744 @@
+This is Info file history.info, produced by Makeinfo-1.55 from the
+input file hist.texinfo.
+
+   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, 1991 Free Software Foundation, Inc.
+
+   Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice pare
+preserved on all copies.
+
+   Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+   Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+\1f
+File: history.info,  Node: Top,  Next: Using History Interactively,  Prev: (DIR),  Up: (DIR)
+
+GNU History Library
+*******************
+
+   This document describes the GNU History library, a programming tool
+that provides a consistent user interface for recalling lines of
+previously typed input.
+
+* Menu:
+
+* Using History Interactively::          GNU History User's Manual.
+* Programming with GNU History::  GNU History Programmer's Manual.
+* Concept Index::                Index of concepts described in this manual.
+* Function and Variable Index::          Index of externally visible functions
+                                 and variables.
+
+\1f
+File: history.info,  Node: Using History Interactively,  Next: Programming with GNU History,  Prev: Top,  Up: Top
+
+Using History Interactively
+***************************
+
+   This chapter describes how to use the GNU History Library
+interactively, from a user's standpoint.  It should be considered a
+user's guide.  For information on using the GNU History Library in your
+own programs, *note Programming with GNU History::..
+
+* Menu:
+
+* History Interaction::                What it feels like using History as a user.
+
+\1f
+File: history.info,  Node: History Interaction,  Up: Using History Interactively
+
+History Interaction
+===================
+
+   The History library provides a history expansion feature that is
+similar to the history expansion provided by `csh'.  The following text
+describes the syntax used to manipulate the history information.
+
+   History expansion takes place in two parts.  The first is to
+determine which line from the previous history should be used during
+substitution.  The second is to select portions of that line for
+inclusion into the current one.  The line selected from the previous
+history is called the "event", and the portions of that line that are
+acted upon are called "words".  The line is broken into words in the
+same fashion that Bash does, so that several English (or Unix) words
+surrounded by quotes are considered as one word.
+
+* Menu:
+
+* Event Designators::  How to specify which history line to use.
+* Word Designators::   Specifying which words are of interest.
+* Modifiers::          Modifying the results of substitution.
+
+\1f
+File: history.info,  Node: Event Designators,  Next: Word Designators,  Up: History Interaction
+
+Event Designators
+-----------------
+
+   An event designator is a reference to a command line entry in the
+history list.
+
+`!'
+     Start a history substitution, except when followed by a space, tab,
+     the end of the line, = or (.
+
+`!!'
+     Refer to the previous command.  This is a synonym for `!-1'.
+
+`!n'
+     Refer to command line N.
+
+`!-n'
+     Refer to the command N lines back.
+
+`!string'
+     Refer to the most recent command starting with STRING.
+
+`!?string'[`?']
+     Refer to the most recent command containing STRING.
+
+`!#'
+     The entire command line typed so far.
+
+`^string1^string2^'
+     Quick Substitution.  Repeat the last command, replacing STRING1
+     with STRING2.  Equivalent to `!!:s/string1/string2/'.
+
+\1f
+File: history.info,  Node: Word Designators,  Next: Modifiers,  Prev: Event Designators,  Up: History Interaction
+
+Word Designators
+----------------
+
+   A : separates the event specification from the word designator.  It
+can be omitted if the word designator begins with a ^, $, * or %.
+Words are numbered from the beginning of the line, with the first word
+being denoted by a 0 (zero).
+
+`0 (zero)'
+     The `0'th word.  For many applications, this is the command word.
+
+`n'
+     The Nth word.
+
+`^'
+     The first argument;  that is, word 1.
+
+`$'
+     The last argument.
+
+`%'
+     The word matched by the most recent `?string?' search.
+
+`x-y'
+     A range of words; `-Y' abbreviates `0-Y'.
+
+`*'
+     All of the words, except the `0'th.  This is a synonym for `1-$'.
+     It is not an error to use * if there is just one word in the event;
+     the empty string is returned in that case.
+
+`x*'
+     Abbreviates `x-$'
+
+`x-'
+     Abbreviates `x-$' like `x*', but omits the last word.
+
+\1f
+File: history.info,  Node: Modifiers,  Prev: Word Designators,  Up: History Interaction
+
+Modifiers
+---------
+
+   After the optional word designator, you can add a sequence of one or
+more of the following modifiers, each preceded by a :.
+
+`h'
+     Remove a trailing pathname component, leaving only the head.
+
+`r'
+     Remove a trailing suffix of the form `.'SUFFIX, leaving the
+     basename.
+
+`e'
+     Remove all but the trailing suffix.
+
+`t'
+     Remove all leading  pathname  components, leaving the tail.
+
+`p'
+     Print the new command but do not execute it.
+
+`s/old/new/'
+     Substitute NEW for the first occurrence of OLD in the event line.
+     Any delimiter may be used in place of /.  The delimiter may be
+     quoted in OLD and NEW with a single backslash.  If & appears in
+     NEW, it is replaced by OLD.  A single backslash will quote the &.
+     The final delimiter is optional if it is the last character on the
+     input line.
+
+`&'
+     Repeat the previous substitution.
+
+`g'
+     Cause changes to be applied over the entire event line.  Used in
+     conjunction with `s', as in `gs/old/new/', or with `&'.
+
+\1f
+File: history.info,  Node: Programming with GNU History,  Next: Concept Index,  Prev: Using History Interactively,  Up: Top
+
+Programming with GNU History
+****************************
+
+   This chapter describes how to interface programs that you write with
+the GNU History Library.  It should be considered a technical guide.
+For information on the interactive use of GNU History, *note Using
+History Interactively::..
+
+* Menu:
+
+* Introduction to History::    What is the GNU History library for?
+* History Storage::            How information is stored.
+* History Functions::          Functions that you can use.
+* History Variables::          Variables that control behaviour.
+* History Programming Example::        Example of using the GNU History Library.
+
+\1f
+File: history.info,  Node: Introduction to History,  Next: History Storage,  Up: Programming with GNU History
+
+Introduction to History
+=======================
+
+   Many programs read input from the user a line at a time.  The GNU
+History library is able to keep track of those lines, associate
+arbitrary data with each line, and utilize information from previous
+lines in composing new ones.
+
+   The programmer using the History library has available functions for
+remembering lines on a history list, associating arbitrary data with a
+line, removing lines from the list, searching through the list for a
+line containing an arbitrary text string, and referencing any line in
+the list directly.  In addition, a history "expansion" function is
+available which provides for a consistent user interface across
+different programs.
+
+   The user using programs written with the History library has the
+benefit of a consistent user interface with a set of well-known
+commands for manipulating the text of previous lines and using that text
+in new commands.  The basic history manipulation commands are similar to
+the history substitution provided by `csh'.
+
+   If the programmer desires, he can use the Readline library, which
+includes some history manipulation by default, and has the added
+advantage of command line editing.
+
+\1f
+File: history.info,  Node: History Storage,  Next: History Functions,  Prev: Introduction to History,  Up: Programming with GNU History
+
+History Storage
+===============
+
+   The history list is an array of history entries.  A history entry is
+declared as follows:
+
+     typedef struct _hist_entry {
+       char *line;
+       char *data;
+     } HIST_ENTRY;
+
+   The history list itself might therefore be declared as
+
+     HIST_ENTRY **the_history_list;
+
+   The state of the History library is encapsulated into a single
+structure:
+
+     /* A structure used to pass the current state of the history stuff around. */
+     typedef struct _hist_state {
+       HIST_ENTRY **entries;         /* Pointer to the entries themselves. */
+       int offset;                   /* The location pointer within this array. */
+       int length;                   /* Number of elements within this array. */
+       int size;                     /* Number of slots allocated to this array. */
+       int flags;
+     } HISTORY_STATE;
+
+   If the flags member includes `HS_STIFLED', the history has been
+stifled.
+
+\1f
+File: history.info,  Node: History Functions,  Next: History Variables,  Prev: History Storage,  Up: Programming with GNU History
+
+History Functions
+=================
+
+   This section describes the calling sequence for the various functions
+present in GNU History.
+
+* Menu:
+
+* Initializing History and State Management::  Functions to call when you
+                                               want to use history in a
+                                               program.
+* History List Management::            Functions used to manage the list
+                                       of history entries.
+* Information About the History List:: Functions returning information about
+                                       the history list.
+* Moving Around the History List::     Functions used to change the position
+                                       in the history list.
+* Searching the History List::         Functions to search the history list
+                                       for entries containing a string.
+* Managing the History File::          Functions that read and write a file
+                                       containing the history list.
+* History Expansion::                  Functions to perform csh-like history
+                                       expansion.
+
+\1f
+File: history.info,  Node: Initializing History and State Management,  Next: History List Management,  Up: History Functions
+
+Initializing History and State Management
+-----------------------------------------
+
+   This section describes functions used to initialize and manage the
+state of the History library when you want to use the history functions
+in your program.
+
+ - Function: void using_history ()
+     Begin a session in which the history functions might be used.  This
+     initializes the interactive variables.
+
+ - Function: HISTORY_STATE * history_get_history_state ()
+     Return a structure describing the current state of the input
+     history.
+
+ - Function: void history_set_history_state (HISTORY_STATE *state)
+     Set the state of the history list according to STATE.
+
+\1f
+File: history.info,  Node: History List Management,  Next: Information About the History List,  Prev: Initializing History and State Management,  Up: History Functions
+
+History List Management
+-----------------------
+
+   These functions manage individual entries on the history list, or set
+parameters managing the list itself.
+
+ - Function: void add_history (char *string)
+     Place STRING at the end of the history list.  The associated data
+     field (if any) is set to `NULL'.
+
+ - Function: HIST_ENTRY * remove_history (int which)
+     Remove history entry at offset WHICH from the history.  The
+     removed element is returned so you can free the line, data, and
+     containing structure.
+
+ - Function: HIST_ENTRY * replace_history_entry (int which, char *line,
+          char *data)
+     Make the history entry at offset WHICH have LINE and DATA.  This
+     returns the old entry so you can dispose of the data.  In the case
+     of an invalid WHICH, a `NULL' pointer is returned.
+
+ - Function: void stifle_history (int max)
+     Stifle the history list, remembering only the last MAX entries.
+
+ - Function: int unstifle_history ()
+     Stop stifling the history.  This returns the previous amount the
+     history was stifled.  The value is positive if the history was
+     stifled, negative if it wasn't.
+
+ - Function: int history_is_stifled ()
+     Returns non-zero if the history is stifled, zero if it is not.
+
+\1f
+File: history.info,  Node: Information About the History List,  Next: Moving Around the History List,  Prev: History List Management,  Up: History Functions
+
+Information About the History List
+----------------------------------
+
+   These functions return information about the entire history list or
+individual list entries.
+
+ - Function: HIST_ENTRY ** history_list ()
+     Return a `NULL' terminated array of `HIST_ENTRY' which is the
+     current input history.  Element 0 of this list is the beginning of
+     time.  If there is no history, return `NULL'.
+
+ - Function: int where_history ()
+     Returns the offset of the current history element.
+
+ - Function: HIST_ENTRY * current_history ()
+     Return the history entry at the current position, as determined by
+     `where_history ()'.  If there is no entry there, return a `NULL'
+     pointer.
+
+ - Function: HIST_ENTRY * history_get (int offset)
+     Return the history entry at position OFFSET, starting from
+     `history_base'.  If there is no entry there, or if OFFSET is
+     greater than the history length, return a `NULL' pointer.
+
+ - Function: int history_total_bytes ()
+     Return the number of bytes that the primary history entries are
+     using.  This function returns the sum of the lengths of all the
+     lines in the history.
+
+\1f
+File: history.info,  Node: Moving Around the History List,  Next: Searching the History List,  Prev: Information About the History List,  Up: History Functions
+
+Moving Around the History List
+------------------------------
+
+   These functions allow the current index into the history list to be
+set or changed.
+
+ - Function: int history_set_pos (int pos)
+     Set the position in the history list to POS, an absolute index
+     into the list.
+
+ - Function: HIST_ENTRY * previous_history ()
+     Back up the current history offset to the previous history entry,
+     and return a pointer to that entry.  If there is no previous
+     entry, return a `NULL' pointer.
+
+ - Function: HIST_ENTRY * next_history ()
+     Move the current history offset forward to the next history entry,
+     and return the a pointer to that entry.  If there is no next
+     entry, return a `NULL' pointer.
+
+\1f
+File: history.info,  Node: Searching the History List,  Next: Managing the History File,  Prev: Moving Around the History List,  Up: History Functions
+
+Searching the History List
+--------------------------
+
+   These functions allow searching of the history list for entries
+containing a specific string.  Searching may be performed both forward
+and backward from the current history position.  The search may be
+"anchored", meaning that the string must match at the beginning of the
+history entry.
+
+ - Function: int history_search (char *string, int direction)
+     Search the history for STRING, starting at the current history
+     offset.  If DIRECTION < 0, then the search is through previous
+     entries, else through subsequent.  If STRING is found, then the
+     current history index is set to that history entry, and the value
+     returned is the offset in the line of the entry where STRING was
+     found.  Otherwise, nothing is changed, and a -1 is returned.
+
+ - Function: int history_search_prefix (char *string, int direction)
+     Search the history for STRING, starting at the current history
+     offset.  The search is anchored: matching lines must begin with
+     STRING.  If DIRECTION < 0, then the search is through previous
+     entries, else through subsequent.  If STRING is found, then the
+     current history index is set to that entry, and the return value
+     is 0.  Otherwise, nothing is changed, and a -1 is returned.
+
+ - Function: int history_search_pos (char *string, int direction, int
+          pos)
+     Search for STRING in the history list, starting at POS, an
+     absolute index into the list.  If DIRECTION is negative, the search
+     proceeds backward from POS, otherwise forward.  Returns the
+     absolute index of the history element where STRING was found, or
+     -1 otherwise.
+
+\1f
+File: history.info,  Node: Managing the History File,  Next: History Expansion,  Prev: Searching the History List,  Up: History Functions
+
+Managing the History File
+-------------------------
+
+   The History library can read the history from and write it to a file.
+This section documents the functions for managing a history file.
+
+ - Function: int read_history (char *filename)
+     Add the contents of FILENAME to the history list, a line at a
+     time.  If FILENAME is `NULL', then read from `~/.history'.
+     Returns 0 if successful, or errno if not.
+
+ - Function: int read_history_range (char *filename, int from, int to)
+     Read a range of lines from FILENAME, adding them to the history
+     list.  Start reading at line FROM and end at TO.  If FROM is zero,
+     start at the beginning.  If TO is less than FROM, then read until
+     the end of the file.  If FILENAME is `NULL', then read from
+     `~/.history'.  Returns 0 if successful, or `errno' if not.
+
+ - Function: int write_history (char *filename)
+     Write the current history to FILENAME, overwriting FILENAME if
+     necessary.  If FILENAME is `NULL', then write the history list to
+     `~/.history'.  Values returned are as in `read_history ()'.
+
+ - Function: int append_history (int nelements, char *filename)
+     Append the last NELEMENTS of the history list to FILENAME.
+
+ - Function: int history_truncate_file (char *filename, int nlines)
+     Truncate the history file FILENAME, leaving only the last NLINES
+     lines.
+
+\1f
+File: history.info,  Node: History Expansion,  Prev: Managing the History File,  Up: History Functions
+
+History Expansion
+-----------------
+
+   These functions implement `csh'-like history expansion.
+
+ - Function: int history_expand (char *string, char **output)
+     Expand STRING, placing the result into OUTPUT, a pointer to a
+     string (*note History Interaction::.).  Returns:
+    `0'
+          If no expansions took place (or, if the only change in the
+          text was the de-slashifying of the history expansion
+          character);
+
+    `1'
+          if expansions did take place;
+
+    `-1'
+          if there was an error in expansion;
+
+    `2'
+          if the returned line should only be displayed, but not
+          executed, as with the `:p' modifier (*note Modifiers::.).
+
+     If an error ocurred in expansion, then OUTPUT contains a
+     descriptive error message.
+
+ - Function: char * history_arg_extract (int first, int last, char
+          *string)
+     Extract a string segment consisting of the FIRST through LAST
+     arguments present in STRING.  Arguments are broken up as in Bash.
+
+ - Function: char * get_history_event (char *string, int *cindex, int
+          qchar)
+     Returns the text of the history event beginning at STRING +
+     *CINDEX.  *CINDEX is modified to point to after the event
+     specifier.  At function entry, CINDEX points to the index into
+     STRING where the history event specification begins.  QCHAR is a
+     character that is allowed to end the event specification in
+     addition to the "normal" terminating characters.
+
+ - Function: char ** history_tokenize (char *string)
+     Return an array of tokens parsed out of STRING, much as the shell
+     might.  The tokens are split on white space and on the characters
+     `()<>;&|$', and shell quoting conventions are obeyed.
+
+\1f
+File: history.info,  Node: History Variables,  Next: History Programming Example,  Prev: History Functions,  Up: Programming with GNU History
+
+History Variables
+=================
+
+   This section describes the externally visible variables exported by
+the GNU History Library.
+
+ - Variable: int history_base
+     The logical offset of the first entry in the history list.
+
+ - Variable: int history_length
+     The number of entries currently stored in the history list.
+
+ - Variable: int max_input_history
+     The maximum number of history entries.  This must be changed using
+     `stifle_history ()'.
+
+ - Variable: char history_expansion_char
+     The character that starts a history event.  The default is `!'.
+
+ - Variable: char history_subst_char
+     The character that invokes word substitution if found at the start
+     of a line.  The default is `^'.
+
+ - Variable: char history_comment_char
+     During tokenization, if this character is seen as the first
+     character of a word, then it and all subsequent characters up to a
+     newline are ignored, suppressing history expansion for the
+     remainder of the line.  This is disabled by default.
+
+ - Variable: char * history_no_expand_chars
+     The list of characters which inhibit history expansion if found
+     immediately following HISTORY_EXPANSION_CHAR.  The default is
+     whitespace and `='.
+
+\1f
+File: history.info,  Node: History Programming Example,  Prev: History Variables,  Up: Programming with GNU History
+
+History Programming Example
+===========================
+
+   The following program demonstrates simple use of the GNU History
+Library.
+
+     main ()
+     {
+       char line[1024], *t;
+       int len, done = 0;
+     
+       line[0] = 0;
+     
+       using_history ();
+       while (!done)
+         {
+           printf ("history$ ");
+           fflush (stdout);
+           t = fgets (line, sizeof (line) - 1, stdin);
+           if (t && *t)
+             {
+               len = strlen (t);
+               if (t[len - 1] == '\n')
+                 t[len - 1] = '\0';
+             }
+     
+           if (!t)
+             strcpy (line, "quit");
+     
+           if (line[0])
+             {
+               char *expansion;
+               int result;
+     
+               result = history_expand (line, &expansion);
+               if (result)
+                 fprintf (stderr, "%s\n", expansion);
+     
+               if (result < 0 || result == 2)
+                 {
+                   free (expansion);
+                   continue;
+                 }
+     
+               add_history (expansion);
+               strncpy (line, expansion, sizeof (line) - 1);
+               free (expansion);
+             }
+     
+           if (strcmp (line, "quit") == 0)
+             done = 1;
+           else if (strcmp (line, "save") == 0)
+             write_history ("history_file");
+           else if (strcmp (line, "read") == 0)
+             read_history ("history_file");
+           else if (strcmp (line, "list") == 0)
+             {
+               register HIST_ENTRY **the_list;
+               register int i;
+     
+               the_list = history_list ();
+               if (the_list)
+                 for (i = 0; the_list[i]; i++)
+                   printf ("%d: %s\n", i + history_base, the_list[i]->line);
+             }
+           else if (strncmp (line, "delete", 6) == 0)
+             {
+               int which;
+               if ((sscanf (line + 6, "%d", &which)) == 1)
+                 {
+                   HIST_ENTRY *entry = remove_history (which);
+                   if (!entry)
+                     fprintf (stderr, "No such entry %d\n", which);
+                   else
+                     {
+                       free (entry->line);
+                       free (entry);
+                     }
+                 }
+               else
+                 {
+                   fprintf (stderr, "non-numeric arg given to `delete'\n");
+                 }
+             }
+         }
+     }
+
+\1f
+File: history.info,  Node: Concept Index,  Next: Function and Variable Index,  Prev: Programming with GNU History,  Up: Top
+
+Concept Index
+*************
+
+* Menu:
+
+* anchored search:                      Searching the History List.
+* event designators:                    Event Designators.
+* expansion:                            History Interaction.
+* history events:                       Event Designators.
+* History Searching:                    Searching the History List.
+
+\1f
+File: history.info,  Node: Function and Variable Index,  Prev: Concept Index,  Up: Top
+
+Function and Variable Index
+***************************
+
+* Menu:
+
+* add_history:                          History List Management.
+* append_history:                       Managing the History File.
+* current_history:                      Information About the History List.
+* get_history_event:                    History Expansion.
+* history_arg_extract:                  History Expansion.
+* history_base:                         History Variables.
+* history_comment_char:                 History Variables.
+* history_expand:                       History Expansion.
+* history_expansion_char:               History Variables.
+* history_get:                          Information About the History List.
+* history_get_history_state:            Initializing History and State Management.
+* history_is_stifled:                   History List Management.
+* history_length:                       History Variables.
+* history_list:                         Information About the History List.
+* history_no_expand_chars:              History Variables.
+* history_search:                       Searching the History List.
+* history_search_pos:                   Searching the History List.
+* history_search_prefix:                Searching the History List.
+* history_set_history_state:            Initializing History and State Management.
+* history_set_pos:                      Moving Around the History List.
+* history_subst_char:                   History Variables.
+* history_tokenize:                     History Expansion.
+* history_total_bytes:                  Information About the History List.
+* history_truncate_file:                Managing the History File.
+* max_input_history:                    History Variables.
+* next_history:                         Moving Around the History List.
+* previous_history:                     Moving Around the History List.
+* read_history:                         Managing the History File.
+* read_history_range:                   Managing the History File.
+* remove_history:                       History List Management.
+* replace_history_entry:                History List Management.
+* stifle_history:                       History List Management.
+* unstifle_history:                     History List Management.
+* using_history:                        Initializing History and State Management.
+* where_history:                        Information About the History List.
+* write_history:                        Managing the History File.
+
+
+\1f
+Tag Table:
+Node: Top\7f975
+Node: Using History Interactively\7f1569
+Node: History Interaction\7f2077
+Node: Event Designators\7f3122
+Node: Word Designators\7f3952
+Node: Modifiers\7f4936
+Node: Programming with GNU History\7f6065
+Node: Introduction to History\7f6791
+Node: History Storage\7f8112
+Node: History Functions\7f9205
+Node: Initializing History and State Management\7f10176
+Node: History List Management\7f10968
+Node: Information About the History List\7f12396
+Node: Moving Around the History List\7f13702
+Node: Searching the History List\7f14587
+Node: Managing the History File\7f16419
+Node: History Expansion\7f17925
+Node: History Variables\7f19769
+Node: History Programming Example\7f21138
+Node: Concept Index\7f23742
+Node: Function and Variable Index\7f24223
+\1f
+End Tag Table
diff --git a/lib/readline/doc/history.ps b/lib/readline/doc/history.ps
new file mode 100644 (file)
index 0000000..839598f
--- /dev/null
@@ -0,0 +1,2037 @@
+%!PS-Adobe-2.0
+%%Creator: dvipsk 5.490s Copyright 1986, 1992 Radical Eye Software
+%%Title: history.dvi
+%%Pages: 22 1
+%%BoundingBox: 0 0 612 792
+%%EndComments
+%DVIPSCommandLine: dvips -D 300 -o history.ps history.dvi
+%%BeginProcSet: tex.pro
+%!
+/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N /X{S N}
+B /TR{translate}N /isls false N /vsize 11 72 mul N /@rigin{isls{[0 -1 1 0 0 0]
+concat}if 72 Resolution div 72 VResolution div neg scale isls{Resolution hsize
+-72 div mul 0 TR}if Resolution VResolution vsize -72 div 1 add mul TR matrix
+currentmatrix dup dup 4 get round 4 exch put dup dup 5 get round 5 exch put
+setmatrix}N /@landscape{/isls true N}B /@manualfeed{statusdict /manualfeed
+true put}B /@copies{/#copies X}B /FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N
+/IE 0 N /ctr 0 N /df-tail{/nn 8 dict N nn begin /FontType 3 N /FontMatrix
+fntrx N /FontBBox FBB N string /base X array /BitMaps X /BuildChar{
+CharBuilder}N /Encoding IE N end dup{/foo setfont}2 array copy cvx N load 0 nn
+put /ctr 0 N[}B /df{/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0
+0 sf neg 0 0]N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data
+dup length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{128
+ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub get 127
+sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data dup type
+/stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N /rc 0 N /gp 0 N
+/cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup /base get 2 index get
+S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx 0 ch-xoff ch-yoff ch-height
+sub ch-xoff ch-width add ch-yoff setcachedevice ch-width ch-height true[1 0 0
+-1 -.1 ch-xoff sub ch-yoff .1 add]{ch-image}imagemask restore}B /D{/cc X dup
+type /stringtype ne{]}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1
+ne{dup dup length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}
+B /I{cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin
+0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul add
+.99 lt{/FV}{/RV}ifelse load def pop}N /eop{SI restore showpage userdict
+/eop-hook known{eop-hook}if}N /@start{userdict /start-hook known{start-hook}
+if /VResolution X /Resolution X 1000 div /DVImag X /IE 256 array N 0 1 255{IE
+S 1 string dup 0 3 index put cvn put}for 65781.76 div /vsize X 65781.76 div
+/hsize X}N /p{show}N /RMat[1 0 0 -1 0 0]N /BDot 260 string N /rulex 0 N /ruley
+0 N /v{/ruley X /rulex X V}B /V{}B /RV statusdict begin /product where{pop
+product dup length 7 ge{0 7 getinterval dup(Display)eq exch 0 4 getinterval
+(NeXT)eq or}{pop false}ifelse}{false}ifelse end{{gsave TR -.1 -.1 TR 1 1 scale
+rulex ruley false RMat{BDot}imagemask grestore}}{{gsave TR -.1 -.1 TR rulex
+ruley scale 1 1 false RMat{BDot}imagemask grestore}}ifelse B /FV{gsave
+transform round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg
+rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail{dup
+/delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M}B /d{-3 M}
+B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{4 M}B /w{0
+rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{p 1 w}B /r{p 2 w}
+B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p a}B /bos{/SS save N}B
+/eos{SS restore}B end
+%%EndProcSet
+TeXDict begin 40258431 52099146 1000 300 300 @start /Fa 1 59
+df<70F8F8F87005057C840D>58 D E /Fb 1 59 df<78FCFCFCFC7806067B8510>58
+D E /Fc 24 123 df<1FC0007FF000707800201800001C00001C0007FC001FFC003C1C00701C00
+E01C00E01C00E01C00707C003FFF800F8F8011107E8F14>97 D<FC0000FC00001C00001C00001C
+00001C00001C00001CF8001DFE001F07001E03001C03801C01C01C01C01C01C01C01C01C01C01C
+01C01C03801E03001F0E001DFC000CF8001217809614>I<03F80FFC1C1C380870006000E000E0
+00E000E00060007000380E1C1E0FFC03F00F107E8F14>I<007E00007E00000E00000E00000E00
+000E00000E0007CE000FFE001C3E00301E00700E00E00E00E00E00E00E00E00E00E00E00E00E00
+700E00301E00383E001FEFC007CFC012177F9614>I<07E00FF01C38301C700CE00EE00EFFFEFF
+FEE00060007000380E1C1E0FFC03F00F107E8F14>I<007C00FE01CE03840380038003807FFEFF
+FE0380038003800380038003800380038003800380038003807FFC7FFC0F177F9614>I<07CF00
+1FFF80383B80301800701C00701C00701C003018003838003FF00037C0007000007000003FF800
+1FFC003FFE00700F00E00380E00380E00380E003807007003C1E001FFC0007F00011197F8F14>
+I<FC0000FC00001C00001C00001C00001C00001C00001C78001DFE001F86001E07001C07001C07
+001C07001C07001C07001C07001C07001C07001C07001C0700FF8FE0FF8FE01317809614>I<03
+0007800780030000000000000000007F807F800380038003800380038003800380038003800380
+03800380FFFCFFFC0E187D9714>I<FC0000FC00001C00001C00001C00001C00001C00001DFF80
+1DFF801C3C001C78001CF0001DE0001FC0001FC0001FE0001EF0001C70001C38001C38001C1C00
+FE3F80FE3F8011177F9614>107 D<FF80FF800380038003800380038003800380038003800380
+038003800380038003800380038003800380FFFEFFFE0F177E9614>I<FB8E00FFDF003CF3803C
+F38038E38038E38038E38038E38038E38038E38038E38038E38038E38038E380FEFBE0FE79E013
+10808F14>I<FC7800FDFE001F86001E07001C07001C07001C07001C07001C07001C07001C0700
+1C07001C07001C0700FF8FE0FF8FE01310808F14>I<07C01FF03C78701C701CE00EE00EE00EE0
+0EE00EE00E701C783C3C781FF007C00F107E8F14>I<FCF800FDFE001F07001E03001C03801C01
+C01C01C01C01C01C01C01C01C01C01C01C03801E03001F0E001DFC001CF8001C00001C00001C00
+001C00001C00001C0000FF8000FF80001218808F14>I<FE1F00FE7F800EE3800F81000F00000F
+00000E00000E00000E00000E00000E00000E00000E00000E0000FFF000FFF00011107F8F14>
+114 D<0FD83FF86038C038C038F0007F803FF007F8001C6006E006F006F81CFFF8CFE00F107E8F
+14>I<030007000700070007007FFCFFFC07000700070007000700070007000700070E070E070E
+070C03FC00F00F157F9414>I<FC3F00FC3F001C07001C07001C07001C07001C07001C07001C07
+001C07001C07001C07001C07001C1F000FFFE003E7E01310808F14>I<FE3F80FE3F801C1C001C
+1C001C1C001C1C000E38000E38000E380006300007700007700007700003E00003E00003E00011
+107F8F14>I<FF7F80FF7F80380E00380E00380E00380E0039CE0039CE0019CC001B6C001B6C00
+1A6C001A6C001E7C000E78000E780011107F8F14>I<7E3F007E3F001E38000E780007700007E0
+0003E00001C00003C00003E0000770000E78000E38001C1C00FE3F80FE3F8011107F8F14>I<FE
+3F80FE3F801C1C001C1C001C1C000E1C000E38000E380007380007300007300003700003700001
+E00001E00001E00001C00001C00001C0000380007380007700007E00003C000011187F8F14>I<
+3FFF7FFF700E701C7038007000E001C0038007000E001C0738077007FFFFFFFF10107F8F14>I
+E /Fd 1 59 df<60F0F06004047D830B>58 D E /Fe 25 122 df<078018603030303060186018
+E01CE01CE01CE01CE01CE01CE01CE01CE01CE01CE01CE01C6018601870383030186007800E187E
+9713>48 D<03000700FF0007000700070007000700070007000700070007000700070007000700
+070007000700070007000700FFF00C187D9713>I<0F80106020304038803CC01CE01C401C003C
+003800380070006000C001800100020004040804100430083FF87FF8FFF80E187E9713>I<01E0
+06100C1818383038300070006000E000E7C0E860F030F018E018E01CE01CE01C601C601C701830
+183030186007C00E187E9713>54 D<40007FFE7FFC7FFC40088010801080200040004000800180
+01800100030003000300030007000700070007000700070002000F197E9813>I<078018603030
+201860186018601870103C303E600F8007C019F030F86038401CC00CC00CC00CC00C6008201018
+600FC00E187E9713>I<07801860303070306018E018E018E01CE01CE01C601C603C303C185C0F
+9C001C00180018003870307060604021801F000E187E9713>I<FFE7FF0E00700E00700E00700E
+00700E00700E00700E00700E00700E00700E00700E00700FFFF00E00700E00700E00700E00700E
+00700E00700E00700E00700E00700E00700E00700E0070FFE7FF181A7E991D>72
+D<0FC21836200E6006C006C002C002C002E00070007E003FE01FF807FC003E000E000700038003
+80038003C002C006E004D81887E0101A7E9915>83 D<3F8070C070E020700070007007F01C7030
+707070E070E071E071E0F171FB1E3C10107E8F13>97 D<07F80C1C381C30087000E000E000E000
+E000E000E0007000300438080C1807E00E107F8F11>99 D<007E00000E00000E00000E00000E00
+000E00000E00000E00000E00000E0003CE000C3E00380E00300E00700E00E00E00E00E00E00E00
+E00E00E00E00E00E00600E00700E00381E001C2E0007CFC0121A7F9915>I<07C01C3030187018
+600CE00CFFFCE000E000E000E0006000300438080C1807E00E107F8F11>I<0FCE187330307038
+703870387038303018602FC02000600070003FF03FFC1FFE600FC003C003C003C0036006381C07
+E010187F8F13>103 D<FC00001C00001C00001C00001C00001C00001C00001C00001C00001C00
+001CF8001D0C001E0E001E0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E
+001C0E001C0E00FF9FC0121A7F9915>I<18003C003C001800000000000000000000000000FC00
+1C001C001C001C001C001C001C001C001C001C001C001C001C001C00FF80091A80990A>I<FCF8
+001D0C001E0E001E0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E
+001C0E00FF9FC012107F8F15>110 D<07E01C38300C700E6006E007E007E007E007E007E00760
+06700E381C1C3807E010107F8F13>I<FCF8001F0E001E07001C03801C03801C01C01C01C01C01
+C01C01C01C01C01C01C01C03801C03001E07001F0C001CF0001C00001C00001C00001C00001C00
+001C0000FF800012177F8F15>I<FCE01D701E701E201C001C001C001C001C001C001C001C001C
+001C001C00FFC00C107F8F0F>114 D<1F2060E04020C020C020F0007F003FC01FE000F0807080
+30C030C020F0408F800C107F8F0F>I<0400040004000C000C001C003C00FFC01C001C001C001C
+001C001C001C001C001C201C201C201C201C200E4003800B177F960F>I<FF1F803C06001C0400
+1C04001E0C000E08000E080007100007100007900003A00003A00001C00001C00001C000008000
+11107F8F14>118 D<FF3F803C1C001C18000E100007200007600003C00001C00001E00003E000
+027000043800083800181C00381E00FC3FC012107F8F14>120 D<FF1F803C06001C04001C0400
+1E0C000E08000E080007100007100007900003A00003A00001C00001C00001C000008000008000
+010000010000E10000E20000E4000078000011177F8F14>I E /Ff 2 42
+df<007000E001C00380078007000E001E001E003C003C003C0078007800780078007000F000F0
+00F000F000F000F000F000F000F000F000F000F000700078007800780078003C003C003C001E00
+1E000E0007000780038001C000E000700C2E7EA112>40 D<E000700038001C001E000E00070007
+80078003C003C003C001E001E001E001E000E000F000F000F000F000F000F000F000F000F000F0
+00F000F000E001E001E001E001E003C003C003C00780078007000E001E001C0038007000E0000C
+2E7DA112>I E /Fg 25 123 df<0007F800007FFC0001FC0E0003F01F0007E03F000FC03F000F
+C03F000FC03F000FC01E000FC00C000FC000000FC000000FC0FF80FFFFFF80FFFFFF800FC01F80
+0FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F
+800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F807FF8FFF07FF8FFF01C23
+7FA220>12 D<000FFF80007FFF8001FC1F8003F03F8007E03F800FC03F800FC01F800FC01F800F
+C01F800FC01F800FC01F800FC01F800FC01F80FFFFFF80FFFFFF800FC01F800FC01F800FC01F80
+0FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F
+800FC01F800FC01F800FC01F800FC01F800FC01F807FF8FFF07FF8FFF01C237FA220>I<07FE00
+001FFF80003F07E0003F03F0003F01F0003F01F8001E01F8000001F8000001F800003FF80003FD
+F8001F81F8003E01F8007C01F800F801F800F801F800F801F800F801F8007C02F8007E0CF8001F
+F87F8007E03F8019167E951C>97 D<FF800000FF8000001F8000001F8000001F8000001F800000
+1F8000001F8000001F8000001F8000001F8000001F8000001F8000001F87F0001FBFFC001FF03E
+001FC01F001F800F801F800FC01F8007C01F8007E01F8007E01F8007E01F8007E01F8007E01F80
+07E01F8007E01F8007C01F8007C01F800FC01F800F801FC01F001E707E001C3FFC00180FE0001B
+237EA220>I<00FF8007FFE00F83F01F03F03E03F07E03F07C01E07C0000FC0000FC0000FC0000
+FC0000FC0000FC00007C00007E00007E00003F00301F00600FC0E007FF8000FE0014167E9519>
+I<0001FF000001FF0000003F0000003F0000003F0000003F0000003F0000003F0000003F000000
+3F0000003F0000003F0000003F0000FE3F0007FFBF000FC1FF001F007F003E003F007E003F007C
+003F007C003F00FC003F00FC003F00FC003F00FC003F00FC003F00FC003F00FC003F007C003F00
+7E003F003E003F001F007F000F81FF0007FF3FE001FC3FE01B237EA220>I<00FE0007FF800F83
+C01F01E03E00F07E00F07C00F87C0078FC0078FFFFF8FFFFF8FC0000FC0000FC00007C00007C00
+003E00183E00181F00300F80E003FFC000FF0015167E951A>I<00FE0F8003FF9FC00F83E3C01F
+01F3C01E00F0003E00F8003E00F8003E00F8003E00F8003E00F8001E00F0001F01F0000F83E000
+0BFF800008FE000018000000180000001C0000001FFFE0001FFFFC000FFFFF0007FFFF001FFFFF
+807C001FC078000FC0F80007C0F80007C0F80007C07C000F803E001F001F807E000FFFFC0001FF
+E0001A217F951D>103 D<FF800000FF8000001F8000001F8000001F8000001F8000001F800000
+1F8000001F8000001F8000001F8000001F8000001F8000001F83F0001F8FFC001F987E001FA03E
+001FC03F001FC03F001F803F001F803F001F803F001F803F001F803F001F803F001F803F001F80
+3F001F803F001F803F001F803F001F803F001F803F001F803F00FFF1FFE0FFF1FFE01B237DA220
+>I<1E003F007F807F807F807F803F001E00000000000000000000000000FF80FF801F801F801F
+801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F80FFF0FFF00C247EA3
+0F>I<FF800000FF8000001F8000001F8000001F8000001F8000001F8000001F8000001F800000
+1F8000001F8000001F8000001F8000001F80FF801F80FF801F803C001F8030001F80E0001F81C0
+001F8300001F8600001F9E00001FBE00001FFF00001FDF80001F8FC0001F07C0001F07E0001F03
+F0001F01F8001F00F8001F00FC001F007E00FFE1FFC0FFE1FFC01A237EA21E>107
+D<FF80FF801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F80
+1F801F801F801F801F801F801F801F801F801F801F801F801F801F80FFF0FFF00C237EA20F>I<
+FF03F803F800FF0FFE0FFE001F183F183F001F201F201F001F401FC01F801F401FC01F801F801F
+801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F80
+1F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F
+801F80FFF0FFF0FFF0FFF0FFF0FFF02C167D9531>I<FF03F000FF0FFC001F187E001F203E001F
+403F001F403F001F803F001F803F001F803F001F803F001F803F001F803F001F803F001F803F00
+1F803F001F803F001F803F001F803F001F803F001F803F00FFF1FFE0FFF1FFE01B167D9520>I<
+00FF0007FFE00F81F01F00F83E007C7C003E7C003E7C003EFC003FFC003FFC003FFC003FFC003F
+FC003FFC003F7C003E7E007E3E007C1F00F80F81F007FFE000FF0018167E951D>I<FF87F000FF
+BFFC001FF07E001FC01F001F800F801F800FC01F800FC01F8007E01F8007E01F8007E01F8007E0
+1F8007E01F8007E01F8007E01F8007C01F800FC01F800FC01F801F801FC01F001FF07E001FBFFC
+001F8FE0001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F800000FFF0
+0000FFF000001B207E9520>I<FF0F80FF1FE01F33F01F63F01F43F01F43F01FC1E01F80001F80
+001F80001F80001F80001F80001F80001F80001F80001F80001F80001F80001F8000FFF800FFF8
+0014167E9518>114 D<07F9801FFF80380780700380F00180F00180F80000FF0000FFF8007FFE
+003FFF001FFF8007FF80003FC0C007C0C003C0E003C0E003C0F00380FC0F00EFFE00C3F8001216
+7E9517>I<00C00000C00000C00000C00001C00001C00003C00007C0000FC0001FC000FFFF00FF
+FF000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC1800F
+C1800FC1800FC1800FC18007C18007E30003FE0000FC0011207F9F16>I<FF81FF00FF81FF001F
+803F001F803F001F803F001F803F001F803F001F803F001F803F001F803F001F803F001F803F00
+1F803F001F803F001F803F001F803F001F803F001F807F001F80FF000FC1BF0007FF3FE001FC3F
+E01B167D9520>I<FFF01FE0FFF01FE00FC007000FC006000FE00E0007E00C0007F01C0003F018
+0003F8180001F8300001F8300000FC600000FC6000007EC000007EC000007FC000003F8000003F
+8000001F0000001F0000000E0000000E00001B167F951E>I<FFF3FF87FCFFF3FF87FC1F807C00
+E00FC07C00C00FC07E00C00FE03E01C007E03F018007E07F018003F07F030003F0CF830001F8CF
+860001F8CFC60001FD87C60000FD87CC0000FF03EC00007F03F800007F03F800007E01F800003E
+01F000003C00F000001C00E000001800600026167F9529>I<FFF0FFC0FFF0FFC00FC01C0007E0
+380007F0700003F0E00001F8C00000FD8000007F0000007F0000003F0000001F8000003FC00000
+37E0000067F00000C3F00001C1F8000380FC000700FE000E007E00FFC1FFE0FFC1FFE01B167F95
+1E>I<FFF01FE0FFF01FE00FC007000FC006000FE00E0007E00C0007F01C0003F0180003F81800
+01F8300001F8300000FC600000FC6000007EC000007EC000007FC000003F8000003F8000001F00
+00001F0000000E0000000E0000000C0000000C00000018000078180000FC380000FC300000FC60
+000069E000007F8000001F0000001B207F951E>I<7FFFE07FFFE0780FC0701FC0601F80E03F00
+C07F00C07E00C0FC0001FC0001F80003F00007F03007E0300FC0301FC0701F80703F00607F00E0
+7E03E0FFFFE0FFFFE014167E9519>I E /Fh 22 119 df<00E00000E00000E00000E00040E040
+F0E1E0F8E3E07EEFC01FFF0007FC0003F80007FC001FFF007EEFC0F8E3E0F0E1E040E04000E000
+00E00000E00000E00013157D991A>42 D<003800007C00007C00006C0000EE0000EE0000EE0000
+EE0000C60001C70001C70001C70001C7000383800383800383800383800783C00701C007FFC007
+FFC007FFC00E00E00E00E00E00E00E00E01C00707F83FCFF83FE7F83FC171E7F9D1A>65
+D<7FFFFCFFFFFC7FFFFC0E001C0E001C0E001C0E001C0E001C0E00000E00000E07000E07000E07
+000FFF000FFF000FFF000E07000E07000E07000E00000E00000E00000E000E0E000E0E000E0E00
+0E0E000E7FFFFEFFFFFE7FFFFE171E7F9D1A>69 D<FF8FF8FF8FF8FF8FF81C01C01C01C01C01C0
+1C01C01C01C01C01C01C01C01C01C01C01C01C01C01FFFC01FFFC01FFFC01C01C01C01C01C01C0
+1C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C0FF8FF8FF8FF8FF8FF8151E7E9D1A>
+72 D<FFFF80FFFF80FFFF8001C00001C00001C00001C00001C00001C00001C00001C00001C000
+01C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C000
+01C00001C000FFFF80FFFF80FFFF80111E7C9D1A>I<FE0FF8FF0FF8FF0FF81D81C01D81C01D81
+C01D81C01DC1C01CC1C01CC1C01CE1C01CE1C01C61C01C61C01C71C01C71C01C31C01C31C01C39
+C01C39C01C19C01C19C01C1DC01C0DC01C0DC01C0DC01C0DC0FF87C0FF87C0FF83C0151E7E9D1A
+>78 D<0FFE003FFF807FFFC07C07C07001C0F001E0E000E0E000E0E000E0E000E0E000E0E000E0
+E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0F001E0F001E0
+7001C07C07C07FFFC03FFF800FFE00131E7D9D1A>I<FFF000FFFC00FFFF001C0F801C07801C03
+C01C01C01C01C01C01C01C01C01C03C01C07801C0F801FFF001FFC001FFE001C0F001C07001C03
+801C03801C03801C03801C03801C03841C038E1C038E1C038EFF81FCFF81FCFF8070171E7E9D1A
+>82 D<03F1C00FFDC03FFFC07C0FC07003C0E003C0E001C0E001C0E001C0E00000700000780000
+3F00001FF00007FE0000FF00000F800003C00001C00000E00000E06000E0E000E0E000E0E001C0
+F001C0FC0780FFFF80EFFE00E3F800131E7D9D1A>I<7FFFFEFFFFFEFFFFFEE0380EE0380EE038
+0EE0380EE0380E0038000038000038000038000038000038000038000038000038000038000038
+0000380000380000380000380000380000380000380000380003FF8007FFC003FF80171E7F9D1A
+>I<FF01FEFF83FEFF01FE1E00F00E00E00E00E00701C00701C003838003838003C78001C70001
+C70000EE0000EE00007C00007C0000380000380000380000380000380000380000380000380000
+380000380001FF0001FF0001FF00171E7F9D1A>89 D<7FFFC0FFFFE0FFFFE07FFFC013047D7E1A
+>95 D<1FF0003FFC007FFE00780F00300700000380000380007F8007FF801FFF803F8380780380
+700380E00380E00380E00380700780780F803FFFFC1FFDFC07F0FC16157D941A>97
+D<00FF8003FFC00FFFE01F01E03C00C0780000700000700000E00000E00000E00000E00000E000
+007000007000007800703C00701F01F00FFFE003FFC000FE0014157D941A>99
+D<001FC0001FC0001FC00001C00001C00001C00001C00001C00001C001F1C007FDC00FFFC01E0F
+C03C07C07803C07001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C07003C07003C03807
+C03E0FC01FFFFC07FDFC01F1FC161E7E9D1A>I<FE0000FE0000FE00000E00000E00000E00000E
+00000E00000E00000E3E000EFF800FFFC00FC1C00F80E00F00E00E00E00E00E00E00E00E00E00E
+00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E0FFE3FEFFE3FEFFE3FE171E7F9D1A>
+104 D<01C00003E00003E00003E00001C0000000000000000000000000000000007FE000FFE000
+7FE00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E000
+00E00000E00000E000FFFFC0FFFFC0FFFFC0121F7C9E1A>I<FE3E00FEFF80FFFFC00FC1C00F80
+E00F00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00
+E0FFE3FEFFE3FEFFE3FE17157F941A>110 D<01F00007FC001FFF003E0F803C07807803C07001
+C0E000E0E000E0E000E0E000E0E000E0E000E0F001E07001C07803C03C07803E0F801FFF0007FC
+0001F00013157D941A>I<FF83F0FF8FF8FFBFFC03FC3C03F01803E00003C00003C00003800003
+8000038000038000038000038000038000038000038000038000FFFF00FFFF80FFFF0016157E94
+1A>114 D<00C00001C00001C00001C00001C00001C00001C0007FFFE0FFFFE0FFFFE001C00001
+C00001C00001C00001C00001C00001C00001C00001C00001C00001C07001C07001C07001C07000
+E0E000FFE0007FC0001F00141C7F9B1A>116 D<7FC7FCFFC7FE7FC7FC0E00E00E00E00F01E007
+01C00701C00783C003838003838003838001C70001C70001C70000EE0000EE0000EE00007C0000
+7C0000380017157F941A>118 D E /Fi 41 123 df<0003FC00003FFE00007E070001F80F8003
+F01F8003E01F8007E01F8007E01F8007E01F8007E0060007E0000007E0000007E0000007E0FFC0
+FFFFFFC0FFFFFFC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00F
+C007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E0
+0FC007E00FC007E00FC07FFC7FFC7FFC7FFC1E267FA522>12 D<3C7EFFFFFFFF7E3C08087C8711
+>46 D<001C00003C0000FC00FFFC00FFFC0000FC0000FC0000FC0000FC0000FC0000FC0000FC00
+00FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC00
+00FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC007FFFFC7FFFFC16237CA21F>49
+D<01FF0007FFC01E07F03803F86001FC7C00FEFE00FEFE00FFFE007FFE007F7C007F3800FF0000
+FF0000FE0000FE0001FC0001F80003F00007E0000780000F00001E00003C0000700000E00301C0
+030380070700060600060FFFFE1FFFFE3FFFFE7FFFFCFFFFFCFFFFFC18237DA21F>I<01FF0007
+FFE01E03F03801F83C01FC7E00FE7E00FE7E00FE3E00FE1C01FE0001FC0001FC0003F80007F000
+0FC001FF0001FF000007E00001F00001F80000FC0000FE0000FF0000FF1000FF7C00FFFE00FFFE
+00FFFE00FEFE00FE7C01FC7001F83E07F00FFFC001FF0018237DA21F>I<000038000000780000
+0078000000F8000001F8000003F8000007F8000006F800000CF800001CF8000038F8000030F800
+0060F80000E0F80001C0F8000180F8000300F8000700F8000E00F8001C00F8001800F8003000F8
+007000F800E000F800FFFFFFC0FFFFFFC00001F8000001F8000001F8000001F8000001F8000001
+F8000001F800007FFFC0007FFFC01A237EA21F>I<18000C1F007C1FFFF81FFFF01FFFE01FFFC0
+1FFF801FFE0018000018000018000018000018000018FF001BFFE01F01F01C00F80800FC00007E
+00007E00007E00007F00007F78007FFC007FFC007FFC007FFC007EF8007E6000FC7000FC3801F8
+1E07E007FFC001FE0018237DA21F>I<001FC0007FF001F83803E00C07803E0F807E1F007E3F00
+7E3F007E7E003C7E00007E00007E0000FE3FC0FE7FF0FE80F8FF80FCFF007CFF007EFE007EFE00
+7FFE007FFE007FFE007F7E007F7E007F7E007F7E007F3E007E3F007E1F007C0F80F807C1F003FF
+C0007F0018237DA21F>I<300000003C0000003FFFFFC03FFFFFC03FFFFF807FFFFF007FFFFE00
+7FFFFC006000180060001800E0003000C0006000C000C000000180000001800000030000000700
+0000060000000E0000001E0000001E0000001E0000003C0000003C0000007C0000007C0000007C
+0000007C000000FC000000FC000000FC000000FC000000FC000000FC000000FC00000078000000
+3000001A257DA41F>I<00001C00000000001C00000000003E00000000003E00000000003E0000
+0000007F00000000007F0000000000FF8000000000FF8000000000FF80000000019FC000000001
+9FC0000000031FE0000000030FE0000000030FE00000000607F00000000607F00000000C07F800
+00000C03F80000001C03FC0000001801FC0000001801FC0000003001FE0000003000FE0000007F
+FFFF0000007FFFFF00000060007F000000C0007F800000C0003F800001C0003FC0000180001FC0
+000180001FC0000300000FE0000300000FE0000780000FF000FFF801FFFF80FFF801FFFF802925
+7EA42E>65 D<FFFFFFE00000FFFFFFFC000003F800FF000003F8001FC00003F80007E00003F800
+03F00003F80001F80003F80001FC0003F80000FC0003F80000FE0003F80000FE0003F800007F00
+03F800007F0003F800007F0003F800007F8003F800007F8003F800007F8003F800007F8003F800
+007F8003F800007F8003F800007F8003F800007F8003F800007F8003F800007F8003F800007F00
+03F800007F0003F800007F0003F80000FE0003F80000FE0003F80001FC0003F80001F80003F800
+03F00003F80007E00003F8001FC00003F800FF8000FFFFFFFE0000FFFFFFE0000029257EA42F>
+68 D<FFFFFFFF00FFFFFFFF0003F8007F0003F8000F8003F800078003F800038003F800038003
+F800018003F800018003F800018003F80000C003F80600C003F80600C003F806000003F8060000
+03F80E000003F81E000003FFFE000003FFFE000003F81E000003F80E000003F806000003F80600
+0003F806006003F806006003F800006003F80000C003F80000C003F80000C003F80000C003F800
+01C003F80003C003F80003C003F8000F8003F8003F80FFFFFFFF80FFFFFFFF8023257EA428>I<
+FFFFFFFE00FFFFFFFE0003F800FE0003F8001F0003F8000F0003F800070003F800070003F80003
+0003F800030003F800030003F800018003F806018003F806018003F806000003F806000003F80E
+000003F81E000003FFFE000003FFFE000003F81E000003F80E000003F806000003F806000003F8
+06000003F806000003F800000003F800000003F800000003F800000003F800000003F800000003
+F800000003F800000003F800000003F8000000FFFFF00000FFFFF0000021257EA427>I<FFFFE0
+FFFFE0FFFFE0FFFFE003F80003F80003F80003F80003F80003F80003F80003F80003F80003F800
+03F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F800
+03F80003F80003F80003F80003F80003F80003F80003FFFFFFF80003FFFFFFF80003F80003F800
+03F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F800
+03F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F800
+03F80003F80003F80003F800FFFFE0FFFFE0FFFFE0FFFFE02B257EA430>72
+D<FFFFE0FFFFE003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F8
+0003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F8
+0003F80003F80003F80003F80003F80003F80003F80003F80003F800FFFFE0FFFFE013257EA417
+>I<FFFFF000FFFFF00003F8000003F8000003F8000003F8000003F8000003F8000003F8000003
+F8000003F8000003F8000003F8000003F8000003F8000003F8000003F8000003F8000003F80000
+03F8000003F8000003F8000003F8000003F8000603F8000603F8000603F8000C03F8000C03F800
+0C03F8001C03F8001C03F8003C03F8007C03F800F803F803F8FFFFFFF8FFFFFFF81F257EA425>
+76 D<FFF8000000FFF8FFFC000001FFF803FC000001FE00037E0000037E00037E0000037E0003
+7E0000037E00033F0000067E00033F0000067E00031F80000C7E00031F80000C7E00030FC00018
+7E00030FC000187E000307E000307E000307E000307E000307E000307E000303F000607E000303
+F000607E000301F800C07E000301F800C07E000300FC01807E000300FC01807E0003007E03007E
+0003007E03007E0003007E03007E0003003F06007E0003003F06007E0003001F8C007E0003001F
+8C007E0003000FD8007E0003000FD8007E00030007F0007E00030007F0007E00030007F0007E00
+030003E0007E00078003E0007E00FFFC01C01FFFF8FFFC01C01FFFF835257EA43A>I<00FF0080
+07FFE3800F80F7801E001F803C000F807800078078000380F8000380F8000180F8000180FC0001
+80FC000000FF0000007FE000007FFF00003FFFE0003FFFF8001FFFFE0007FFFF0003FFFF80007F
+FF800003FFC000003FC000000FE0000007E0000007E0C00003E0C00003E0C00003E0C00003C0E0
+0003C0F00007C0F8000780FC000F00FFC03E00E3FFF800803FE0001B257DA422>83
+D<FFFF83FFFE01FFF0FFFF83FFFE01FFF007F0001FC0000F0007F0001FC000060003F8000FE000
+0C0003F8000FE0000C0003FC000FF0001C0001FC0007F000180001FC0007F000180000FE000FF8
+00300000FE000FF800300000FE000FFC003000007F0019FC006000007F0019FC006000007F8039
+FE00E000003F8030FE00C000003F8030FE00C000001FC0607F018000001FC0607F018000001FE0
+607F818000000FE0C03F830000000FE0C03F830000000FF1C03FC700000007F1801FC600000007
+F1801FC600000003FB000FEC00000003FB000FEC00000003FF000FFC00000001FE0007F8000000
+01FE0007F800000001FE0007F800000000FC0003F000000000FC0003F000000000780001E00000
+0000780001E000000000780001E000000000300000C000003C257FA43F>87
+D<07FF00001FFFC0003E03E0003F01F0003F01F8003F00FC001E00FC000000FC000000FC000000
+FC00003FFC0003FCFC000FC0FC003F00FC007E00FC007E00FC00FC00FC00FC00FC00FC00FC00FC
+017C007E017C003F067C001FFC3FE007F01FE01B187E971E>97 D<FFC00000FFC000000FC00000
+0FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000
+000FC000000FC3F8000FCFFE000FF81F800FE00FC00FC007E00FC007E00FC003F00FC003F00FC0
+03F80FC003F80FC003F80FC003F80FC003F80FC003F80FC003F80FC003F80FC003F00FC003F00F
+C007E00FC007C00FE00FC00F383F000E1FFE000C07F0001D267EA522>I<007FE003FFF807C07C
+1F80FC1F00FC3F00FC7E00787E0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000
+7E00007F00003F000C1F800C1FC01807E07003FFE0007F0016187E971B>I<0001FF800001FF80
+00001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F
+8000001F8000001F80007F1F8003FFDF8007E0FF801F803F803F001F803F001F807E001F807E00
+1F80FE001F80FE001F80FE001F80FE001F80FE001F80FE001F80FE001F80FE001F807E001F807E
+001F803F001F803F003F801F807F800FC0FF8003FF9FF800FE1FF81D267EA522>I<007F0003FF
+C007C1F00F80F81F00F83F007C7E007C7E007EFE007EFE007EFFFFFEFFFFFEFE0000FE0000FE00
+007E00007E00007E00063F00061F000C0F801807E07003FFE0007F8017187E971C>I<000FC000
+7FF000F8F001F1F803F1F803E1F807E0F007E00007E00007E00007E00007E00007E00007E000FF
+FF00FFFF0007E00007E00007E00007E00007E00007E00007E00007E00007E00007E00007E00007
+E00007E00007E00007E00007E00007E00007E00007E00007E0007FFF007FFF0015267EA513>I<
+01FF07C007FFDFE00F83F1E01F01F1E03E00F8007E00FC007E00FC007E00FC007E00FC007E00FC
+007E00FC003E00F8001F01F0000F83E0000FFFC00011FF00003000000030000000380000003C00
+00003FFFE0001FFFFC001FFFFE000FFFFF001FFFFF803C003F8078000FC0F80007C0F80007C0F8
+0007C0F80007C07C000F803E001F001F807E0007FFF80000FFC0001B247E971F>I<FFC00000FF
+C000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC00000
+0FC000000FC000000FC000000FC1F8000FC7FE000FCC3F000FD01F000FF01F800FE01F800FE01F
+800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC0
+1F800FC01F800FC01F800FC01F800FC01F800FC01F80FFFCFFF8FFFCFFF81D267DA522>I<0F00
+1F803FC03FC03FC03FC01F800F000000000000000000000000000000FFC0FFC00FC00FC00FC00F
+C00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0FFF8FFF80D27
+7EA611>I<FFC0FFC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0
+0FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0FF
+FCFFFC0E267EA511>108 D<FF81FC01FC00FF87FF07FF000F8C1F8C1F800F980F980F800FB00F
+F00FC00FA00FE00FC00FA00FE00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0
+0FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00F
+C00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0FFFCFFFCFFFCFFFCFFFCFFFC
+2E187D9733>I<FF81F800FF87FE000F8C3F000F901F000FB01F800FA01F800FA01F800FC01F80
+0FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F
+800FC01F800FC01F800FC01F800FC01F80FFFCFFF8FFFCFFF81D187D9722>I<007F800003FFF0
+0007C0F8001F807E003F003F003F003F007E001F807E001F80FE001FC0FE001FC0FE001FC0FE00
+1FC0FE001FC0FE001FC0FE001FC0FE001FC07E001F807E001F803F003F003F003F001F807E000F
+C0FC0003FFF000007F80001A187E971F>I<FFC3F800FFCFFE000FF83F800FE00FC00FC00FE00F
+C007E00FC007F00FC003F00FC003F80FC003F80FC003F80FC003F80FC003F80FC003F80FC003F8
+0FC003F80FC007F00FC007F00FC007E00FC00FC00FE01FC00FF83F000FDFFE000FC7F0000FC000
+000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC00000FFFC0000FFFC
+00001D237E9722>I<FF87C0FF8FF00F98F80FB1F80FA1F80FA1F80FE0F00FC0000FC0000FC000
+0FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC000FFFE00
+FFFE0015187E9719>114 D<07F9801FFF803C0F80700380F00180F00180F00180FC0000FF8000
+7FFC007FFE003FFF800FFFC003FFC0001FE00003E0C001E0C001E0E001E0E001C0F003C0FC0780
+EFFF00C3FC0013187E9718>I<00600000600000600000600000E00000E00001E00001E00003E0
+0007E0001FE000FFFFC0FFFFC007E00007E00007E00007E00007E00007E00007E00007E00007E0
+0007E00007E00007E00007E06007E06007E06007E06007E06007E06003E0C003F0C001FF80007E
+0013237FA218>I<FFC1FF80FFC1FF800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F
+800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC0
+1F800FC03F800FC03F8007C07F8007E0DF8003FF9FF800FE1FF81D187D9722>I<FFF80FF8FFF8
+0FF80FC003C00FE0018007E0030007E0030003F0060003F0060003F80E0001F80C0001FC1C0000
+FC180000FE1800007E3000007E3000003F6000003F6000001FC000001FC000001FC000000F8000
+000F800000070000000700001D187F9720>I<FFF83FF0FFF83FF00FC00F0007E00C0003F01C00
+03F8380001FC700000FCE000007EC000003F8000003F8000001F8000000FC000001FE000001FF0
+000033F8000071F80000E0FC0001C07E0003807F0003003F000F001F80FFC07FF8FFC07FF81D18
+7F9720>120 D<FFF80FF8FFF80FF80FC003C00FE0018007E0030007E0030003F0060003F00600
+03F80E0001F80C0001FC1C0000FC180000FE1800007E3000007E3000003F6000003F6000001FC0
+00001FC000001FC000000F8000000F800000070000000700000006000000060000000C0000300C
+0000781C0000FC180000FC380000FC70000078E000007FC000001F0000001D237F9720>I<3FFF
+F83FFFF83E03F03807F0300FE0700FC0701F80603F80603F00607E0000FE0000FC0001F80003F8
+1803F01807E0180FE0180FC0381F80303F80707F00707E01F0FFFFF0FFFFF015187E971B>I
+E /Fj 29 122 df<0003F07C001E0DC600380F0F00701E0F00E01E0E00E00C0001C01C0001C01C
+0001C01C0001C01C0001C01C00038038007FFFFFC0038038000380380003803800038038000700
+700007007000070070000700700007007000070070000E00E0000E00E0000E00E0000E00E0000E
+00E0000E00E0001C01C0001E01E000FF8FFE0020207E9F1B>11 D<0003E0001C1800381800703C
+00E03C00E03801C00001C00001C00001C00001C0000380007FFFF0038070038070038070038070
+0700E00700E00700E00700E00700E00700E00E01C00E01C00E01C00E01C00E01C00E01C01C0380
+1E03C0FF0FF816207E9F19>I<0003F03F00001E09E08000380F80C000701F01E000E03E01E000
+E01E01C001C01C000001C01C000001C01C000001C01C000001C01C000003803800007FFFFFFF80
+038038038003803803800380380380038038038007007007000700700700070070070007007007
+00070070070007007007000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E0
+0E001C01C01C001E01E01E00FF8FF8FFC023207E9F26>14 D<0020000060000060000060000060
+007061C03843800E4E0007580001E00001E00006B8001C9C00708700E083800180000180000180
+0001800001000012147AA117>42 D<FFC0FFC00A027D8A0F>45 D<000C001C00FC0F3800380038
+00380038003800700070007000700070007000E000E000E000E000E000E001C001C001C001C001
+C001C0038003C0FFFE0F1E7C9D17>49 D<003F8000C1E00100F00200780400780400780F007C0F
+807C0F807C0F00780600780000F80000F00001E00001C0000380000700000E00001C0000380000
+600000C0000180000300200600200800401000403FFFC07FFF80FFFF80161E7E9D17>I<07F800
+0C0C001E06001E07001C070000070000070000070000FF0007C7001E07003C0E00780E00F00E10
+F00E10F00E10F01E10F02E20784F401F878014147D9317>97 D<01FC07060E0F1C0F380E780070
+00F000F000F000F000E000E000E000E000F0027004300818300FC010147C9314>99
+D<0000700003F00000F00000700000700000E00000E00000E00000E00000E00000E00001C000F9
+C00305C00E03C01C03C03801C0780380700380F00380F00380F00380F00380E00700E00700E007
+00E00700E00700700F00301E00186F000F8FE014207C9F19>I<00F800070E000E07001C070038
+0380780380700380F00380F00380FFFF80F00000E00000E00000E00000E00000F0010070020030
+04001C180007E00011147D9314>I<0007800018C00031E00061E000E1C000C00001C00001C000
+01C00001C00001C0000380007FF800038000038000038000038000070000070000070000070000
+0700000700000E00000E00000E00000E00000E00000E00001C00001E0000FFE00013207E9F0E>
+I<00000E003E1100E1A301C1C20381E00780E00701E00F01E00F01E00F01E00703C00703800787
+0004FC000800000800001800001C00000FFF000FFFC007FFE01800F0300030600030C00030C000
+30C000306000603000C01C070007FC00181F809417>I<00E00007E00001E00000E00000E00001
+C00001C00001C00001C00001C00001C000038000038F800390E003A0E003C0600380600780E007
+00E00700E00700E00700E00700E00E01C00E01C00E01C00E01C00E01C00E01C01C03801E03C0FF
+CFF815207E9F19>I<01C003E003E003C0018000000000000000000000000003801F8007800380
+03800700070007000700070007000E000E000E000E000E000E001C001E00FF800B1F7F9E0C>I<
+00E007E001E000E000E001C001C001C001C001C001C00380038003800380038003800700070007
+000700070007000E000E000E000E000E000E001C001E00FFC00B207F9F0C>108
+D<0387C07C001F9861860007A072070003C0340300038038030007807807000700700700070070
+07000700700700070070070007007007000E00E00E000E00E00E000E00E00E000E00E00E000E00
+E00E000E00E00E001C01C01C001E01E01E00FFCFFCFFC022147E9326>I<038F801F90E007A0E0
+03C0600380600780E00700E00700E00700E00700E00700E00E01C00E01C00E01C00E01C00E01C0
+0E01C01C03801E03C0FFCFF815147E9319>I<00FC000387000E01801C00C03800E03800E07000
+F0F000F0F000F0F000F0F000F0E001E0E001E0E001C0E003C0F00380700700380E001C1C0007E0
+0014147D9317>I<00E3E007EC3800F01C00E01E00E00E01C00E01C00F01C00F01C00F01C00F01
+C00F03801E03801E03801C03803C0380380380700740E00721C0071F000700000700000700000E
+00000E00000E00000E00001E0000FFC000181D809319>I<00F040038CC00E04C01C03C03C03C0
+780380780380F00380F00380F00380F00380E00700E00700E00700F00700F00F00700F00301E00
+186E000F8E00000E00000E00000E00001C00001C00001C00001C00003C0001FF80121D7C9318>
+I<038E001FB38007C78003C7800383000780000700000700000700000700000700000E00000E00
+000E00000E00000E00000E00001C00001E0000FFE00011147E9312>I<01F2060E080618061802
+380438001E001FE00FF003F8003C401C400C400C600C6018E010D0608FC00F147E9312>I<0080
+010001000100030007000F001E00FFF80E000E000E000E001C001C001C001C001C001C00380038
+203820382038203840384018800F000D1C7C9B12>I<1C0380FC1F803C07801C03801C03803807
+00380700380700380700380700380700700E00700E00700E00700E00701E00701E00703C00305E
+001F9FC012147B9319>I<FF83F81E00E01C00C01C00800E00800E01000E02000E02000F040007
+040007080007080007100003900003A00003E00003C00003800001800001000015147C9318>I<
+FF9FE1FC3E0780701C0300601C0300401C0380401C0380800E0780800E0581000E0981000E09C2
+000E11C2000731C4000721C4000760C8000740C8000780F0000780F0000300E000030060000200
+40001E147C9321>I<1FF0FF03C07801C06001C04000E08000E180007300007600003C00003C00
+001C00002E00004E000087000107000203800603800C01C03E03E0FF07FC18147F9318>I<0FF8
+3F8001E00E0001C00C0001C0080000E0180000E0100000E0200000E0200000F040000070400000
+708000007080000071000000390000003A0000003E0000003C0000003800000018000000100000
+0010000000200000002000000040000070C00000F0800000F1000000E20000007C000000191D80
+9318>I E /Fk 36 122 df<0001C0000003C000000FC000007FC0001FFFC000FFFFC000FFBFC0
+00E03FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003F
+C000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC00000
+3FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000
+003FC000003FC000003FC000003FC000003FC000003FC000003FC0007FFFFFE07FFFFFE07FFFFF
+E01B2E7AAD28>49 D<003FE00001FFFE0007FFFF800F80FFC01E003FE038001FF07C000FF87E00
+07FCFF0007FCFF8007FEFF8007FEFF8003FEFF8003FE7F0003FE3E0007FE000007FE000007FC00
+0007FC00000FF800000FF800000FF000001FE000001FC000003F8000007F0000007E000000F800
+0001F0000003E0000007C000000F0000001E000E003C000E0038000E0070001E00E0001C01C000
+1C0300003C07FFFFFC0FFFFFFC1FFFFFFC3FFFFFFC7FFFFFF8FFFFFFF8FFFFFFF8FFFFFFF81F2E
+7CAD28>I<0000007800000000000078000000000000FC000000000000FC000000000000FC0000
+00000001FE000000000001FE000000000003FF000000000003FF000000000007FF800000000007
+FF800000000007FF80000000000FFFC0000000000E7FC0000000001E7FE0000000001C3FE00000
+00001C3FE000000000383FF000000000381FF000000000781FF800000000700FF800000000700F
+F800000000E00FFC00000000E007FC00000001E007FE00000001C003FE00000001C003FE000000
+038003FF000000038001FF000000078001FF800000070000FF800000070000FF8000000FFFFFFF
+C000000FFFFFFFC000001FFFFFFFE000001C00003FE000003C00003FF000003800001FF0000038
+00001FF000007000001FF800007000000FF80000F000000FFC0000E0000007FC0000E0000007FC
+0001C0000007FE0003E0000003FE00FFFF8001FFFFFCFFFF8001FFFFFCFFFF8001FFFFFC36317D
+B03D>65 D<FFFFFFFFE00000FFFFFFFFFE0000FFFFFFFFFF800000FF0000FFC00000FF00003FF0
+0000FF00001FF80000FF00000FF80000FF000007FC0000FF000007FC0000FF000007FE0000FF00
+0003FE0000FF000003FE0000FF000003FE0000FF000003FE0000FF000007FE0000FF000007FE00
+00FF000007FC0000FF000007FC0000FF00000FF80000FF00001FF00000FF00003FE00000FF0000
+FF800000FF000FFF000000FFFFFFFE000000FFFFFFFFC00000FF00001FF00000FF000007F80000
+FF000003FE0000FF000003FE0000FF000001FF0000FF000001FF8000FF000000FF8000FF000000
+FFC000FF000000FFC000FF000000FFC000FF000000FFC000FF000000FFC000FF000000FFC000FF
+000000FFC000FF000000FF8000FF000001FF8000FF000001FF0000FF000003FF0000FF000007FE
+0000FF00000FFC0000FF00007FF800FFFFFFFFFFE000FFFFFFFFFF8000FFFFFFFFFC000032317E
+B039>I<000003FF80018000003FFFF003800001FFFFFC07800007FF003F0F80001FF800079F80
+003FC00001FF8000FF800000FF8001FE0000007F8003FC0000003F8007FC0000001F8007F80000
+000F800FF00000000F801FF000000007801FF000000007803FE000000007803FE000000003807F
+E000000003807FE000000003807FC000000000007FC00000000000FFC00000000000FFC0000000
+0000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC0
+0000000000FFC000000000007FC000000000007FC000000000007FE000000000007FE000000003
+803FE000000003803FE000000003801FF000000003801FF000000007800FF0000000070007F800
+0000070007FC0000000E0003FC0000001E0001FE0000001C0000FF8000007800003FC00000F000
+001FF80003E0000007FF003F80000001FFFFFE000000003FFFF80000000003FF80000031317CB0
+3A>I<FFFFFFFFFFE0FFFFFFFFFFE0FFFFFFFFFFE000FF80007FE000FF80000FF000FF800003F0
+00FF800001F000FF800001F000FF800000F000FF800000F000FF8000007000FF8000007000FF80
+00007000FF8000003800FF8000003800FF8007003800FF8007003800FF8007000000FF80070000
+00FF8007000000FF800F000000FF801F000000FF803F000000FFFFFF000000FFFFFF000000FFFF
+FF000000FF803F000000FF801F000000FF800F000000FF8007000000FF8007000000FF80070000
+00FF8007000000FF8007000000FF8000000000FF8000000000FF8000000000FF8000000000FF80
+00000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF80000000
+00FF80000000FFFFFFE00000FFFFFFE00000FFFFFFE000002D317EB033>70
+D<000003FF00030000007FFFF007000001FFFFFC0F000007FF007E1F00001FF0000FBF00007FC0
+0003FF0000FF800001FF0001FE0000007F0003FC0000007F0007FC0000003F000FF80000001F00
+0FF00000001F001FF00000000F001FF00000000F003FE000000007003FE000000007007FE00000
+0007007FE000000007007FC00000000000FFC00000000000FFC00000000000FFC00000000000FF
+C00000000000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC0000000
+0000FFC00000000000FFC00007FFFFFC7FC00007FFFFFC7FE00007FFFFFC7FE0000001FF003FE0
+000001FF003FE0000001FF001FF0000001FF001FF0000001FF000FF0000001FF000FF8000001FF
+0007FC000001FF0003FC000001FF0001FE000001FF0000FF800001FF00007FC00003FF00001FF8
+00077F000007FF003E3F000001FFFFFC1F0000007FFFF00F00000003FF80030036317CB03F>I<
+FFFFFF807FFFFFC0FFFFFF807FFFFFC0FFFFFF807FFFFFC000FF8000007FC00000FF8000007FC0
+0000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007F
+C00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF800000
+7FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000
+007FC00000FF8000007FC00000FF8000007FC00000FFFFFFFFFFC00000FFFFFFFFFFC00000FFFF
+FFFFFFC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF
+8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000
+FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC000
+00FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC0
+0000FF8000007FC00000FF8000007FC000FFFFFF807FFFFFC0FFFFFF807FFFFFC0FFFFFF807FFF
+FFC03A317EB03F>I<FFFFFF80FFFFFF80FFFFFF8000FF800000FF800000FF800000FF800000FF
+800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000
+FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF8000
+00FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF80
+0000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF8000FFFF
+FF80FFFFFF80FFFFFF8019317EB01E>I<FFFF800001FFFFC0FFFFC00001FFFFC0FFFFE00001FF
+FFC000FFF0000003E00000FFF8000001C00000EFFC000001C00000E7FC000001C00000E7FE0000
+01C00000E3FF000001C00000E1FF800001C00000E0FFC00001C00000E07FE00001C00000E03FE0
+0001C00000E03FF00001C00000E01FF80001C00000E00FFC0001C00000E007FE0001C00000E003
+FE0001C00000E001FF0001C00000E001FF8001C00000E000FFC001C00000E0007FE001C00000E0
+003FF001C00000E0001FF001C00000E0001FF801C00000E0000FFC01C00000E00007FE01C00000
+E00003FF01C00000E00001FF81C00000E00000FF81C00000E00000FFC1C00000E000007FE1C000
+00E000003FF1C00000E000001FF9C00000E000000FFDC00000E0000007FDC00000E0000007FFC0
+0000E0000003FFC00000E0000001FFC00000E0000000FFC00000E00000007FC00000E00000003F
+C00000E00000003FC00000E00000001FC00000E00000000FC00001F000000007C000FFFFE00000
+03C000FFFFE0000001C000FFFFE0000001C0003A317EB03F>78 D<FFFFFFFFE000FFFFFFFFFE00
+FFFFFFFFFF8000FF8000FFE000FF80003FF000FF80000FF800FF800007FC00FF800007FC00FF80
+0003FE00FF800003FE00FF800003FF00FF800003FF00FF800003FF00FF800003FF00FF800003FF
+00FF800003FF00FF800003FF00FF800003FE00FF800003FE00FF800007FC00FF800007F800FF80
+000FF800FF80003FE000FF8000FFC000FFFFFFFF0000FFFFFFF80000FF8000000000FF80000000
+00FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF80
+00000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF80000000
+00FF8000000000FF8000000000FF8000000000FF8000000000FF80000000FFFFFF800000FFFFFF
+800000FFFFFF80000030317EB037>80 D<7FFFFFFFFFFF007FFFFFFFFFFF007FFFFFFFFFFF007F
+C00FF801FF007E000FF8003F007C000FF8001F0078000FF8000F0078000FF8000F0070000FF800
+0700F0000FF8000780F0000FF8000780F0000FF8000780E0000FF8000380E0000FF8000380E000
+0FF8000380E0000FF8000380E0000FF800038000000FF800000000000FF800000000000FF80000
+0000000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000000F
+F800000000000FF800000000000FF800000000000FF800000000000FF800000000000FF8000000
+00000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000000FF8
+00000000000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000
+000FF800000000000FF800000000000FF8000000007FFFFFFF0000007FFFFFFF0000007FFFFFFF
+000031307DAF38>84 D<FFFFFF8003FFFF80FFFFFF8003FFFF80FFFFFF8003FFFF8000FF800000
+07C00000FF80000003800000FF80000003800000FF80000003800000FF80000003800000FF8000
+0003800000FF80000003800000FF80000003800000FF80000003800000FF80000003800000FF80
+000003800000FF80000003800000FF80000003800000FF80000003800000FF80000003800000FF
+80000003800000FF80000003800000FF80000003800000FF80000003800000FF80000003800000
+FF80000003800000FF80000003800000FF80000003800000FF80000003800000FF800000038000
+00FF80000003800000FF80000003800000FF80000003800000FF80000003800000FF8000000380
+0000FF80000003800000FF80000003800000FF800000038000007F800000038000007F80000007
+0000007FC00000070000003FC000000E0000003FC000000E0000001FE000001C0000000FF00000
+3800000007F800007000000003FC0001E000000000FF801FC0000000003FFFFF80000000000FFF
+FE000000000000FFE000000039317EB03E>I<FFFFFC0000FFFFFFFFFC0000FFFFFFFFFC0000FF
+FF03FF00000003C001FF000000038001FF800000078000FF800000070000FFC000000700007FC0
+00000E00007FC000000E00007FE000001E00003FE000001C00003FF000003C00001FF000003800
+001FF800003800000FF800007000000FFC000070000007FC0000E0000007FC0000E0000007FE00
+01E0000003FE0001C0000003FF0003C0000001FF000380000001FF800380000000FF8007000000
+00FFC00700000000FFC00F000000007FC00E000000007FE01E000000003FE01C000000003FF03C
+000000001FF038000000001FF838000000000FF870000000000FF870000000000FFCF000000000
+07FCE00000000007FFE00000000003FFC00000000003FFC00000000001FF800000000001FF8000
+00000000FF000000000000FF000000000000FF0000000000007E0000000000007E000000000000
+3C0000000000003C00000038317EB03D>I<00FFF0000003FFFE00000F803F80000FC00FE0001F
+E007F0001FE007F0001FE003F8000FC003FC00078003FC00000003FC00000003FC00000003FC00
+000003FC000000FFFC00001FFFFC0000FFE3FC0003FC03FC000FF003FC001FC003FC003FC003FC
+007F8003FC007F8003FC00FF0003FC00FF0003FC00FF0003FC00FF0007FC00FF0007FC007F800D
+FC003FC019FE001FE070FFF007FFE07FF000FF803FF024207E9F27>97 D<01F8000000FFF80000
+00FFF8000000FFF80000000FF800000007F800000007F800000007F800000007F800000007F800
+000007F800000007F800000007F800000007F800000007F800000007F800000007F800000007F8
+00000007F83FE00007F8FFFC0007FBE07F0007FF001F8007FE000FC007FC000FE007F80007F007
+F80007F807F80007F807F80003FC07F80003FC07F80003FC07F80003FE07F80003FE07F80003FE
+07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FC07F80003FC07F80003
+FC07F80007F807F80007F807F80007F007FC000FE007FE000FC007E7003F8007C3C0FE000780FF
+F80007003FC00027327EB12D>I<000FFF00007FFFC001FC01F003F003F007E007F80FE007F81F
+C007F83FC003F03FC001E07F8000007F8000007F800000FF800000FF800000FF800000FF800000
+FF800000FF800000FF800000FF8000007F8000007F8000007F8000003FC0001C3FC0001C1FC000
+380FE0003807E0007003F001E001FC07C0007FFF00000FF8001E207D9F24>I<0000000FC00000
+07FFC0000007FFC0000007FFC00000007FC00000003FC00000003FC00000003FC00000003FC000
+00003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC0
+0000003FC00007F83FC0003FFF3FC000FE07BFC003F801FFC007E0007FC00FE0007FC01FC0003F
+C03FC0003FC03FC0003FC07F80003FC07F80003FC07F80003FC0FF80003FC0FF80003FC0FF8000
+3FC0FF80003FC0FF80003FC0FF80003FC0FF80003FC0FF80003FC07F80003FC07F80003FC07F80
+003FC03FC0003FC03FC0003FC01FC0003FC00FE0007FC007E000FFC003F003FFE001FC0F3FFE00
+7FFE3FFE000FF03FFE27327DB12D>I<000FFC00007FFF8001FC0FC003F003E007E001F00FE001
+F81FC000FC3FC000FE3FC000FE7F80007E7F80007F7F80007FFF80007FFF80007FFFFFFFFFFFFF
+FFFFFF800000FF800000FF800000FF8000007F8000007F8000007F8000003FC000071FC000071F
+C0000E0FE0000E07F0001C03F8007800FE03E0003FFFC00007FE0020207E9F25>I<0001FE0000
+0FFF80001FC3C0007F07E000FE0FF001FE0FF001FC0FF003FC0FF003FC07E003FC018003FC0000
+03FC000003FC000003FC000003FC000003FC000003FC000003FC0000FFFFFC00FFFFFC00FFFFFC
+0003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC
+000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003
+FC000003FC000003FC000003FC000003FC000003FC000003FC00007FFFF0007FFFF0007FFFF000
+1C327EB119>I<001FF007C000FFFE3FE001F83F79F007E00FC3F00FE00FE1F00FC007E0E01FC0
+07F0001FC007F0003FC007F8003FC007F8003FC007F8003FC007F8003FC007F8001FC007F0001F
+C007F0000FC007E0000FE00FE00007E00FC00003F83F000006FFFE00000E1FF000000E00000000
+1E000000001E000000001F000000001F800000001FFFFF80000FFFFFF0000FFFFFFC0007FFFFFE
+0003FFFFFF0003FFFFFF800FFFFFFFC01F00007FC07E00001FE07C00000FE0FC000007E0FC0000
+07E0FC000007E0FC000007E07E00000FC03E00000F803F00001F800FC0007E0007F803FC0001FF
+FFF000001FFF0000242F7E9F28>I<01F8000000FFF8000000FFF8000000FFF80000000FF80000
+0007F800000007F800000007F800000007F800000007F800000007F800000007F800000007F800
+000007F800000007F800000007F800000007F800000007F800000007F807F80007F83FFE0007F8
+783F0007F8C03F8007F9801FC007FB001FC007FE001FE007FC001FE007FC001FE007FC001FE007
+F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE0
+07F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001F
+E007F8001FE007F8001FE007F8001FE0FFFFC3FFFFFFFFC3FFFFFFFFC3FFFF28327DB12D>I<03
+C00007E0000FF0001FF8001FF8001FF8001FF8000FF00007E00003C00000000000000000000000
+000000000000000000000000000000000001F800FFF800FFF800FFF8000FF80007F80007F80007
+F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007
+F80007F80007F80007F80007F80007F80007F80007F80007F800FFFF80FFFF80FFFF8011337DB2
+17>I<01F800FFF800FFF800FFF8000FF80007F80007F80007F80007F80007F80007F80007F800
+07F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F800
+07F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F800
+07F80007F80007F80007F80007F80007F80007F80007F80007F800FFFFC0FFFFC0FFFFC012327D
+B117>108 D<03F007F8001FE000FFF03FFE00FFF800FFF0783F01E0FC00FFF0C03F8300FE000F
+F1801FC6007F0007F3001FCC007F0007F6001FF8007F8007FC001FF0007F8007FC001FF0007F80
+07FC001FF0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F
+8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE000
+7F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0
+007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001F
+E0007F80FFFFC3FFFF0FFFFCFFFFC3FFFF0FFFFCFFFFC3FFFF0FFFFC3E207D9F43>I<03F007F8
+00FFF03FFE00FFF0783F00FFF0C03F800FF1801FC007F3001FC007F6001FE007FC001FE007FC00
+1FE007FC001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8
+001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007
+F8001FE007F8001FE007F8001FE007F8001FE007F8001FE0FFFFC3FFFFFFFFC3FFFFFFFFC3FFFF
+28207D9F2D>I<0007FC0000007FFFC00001FC07F00003F001F80007E000FC000FC0007E001FC0
+007F003FC0007F803F80003F807F80003FC07F80003FC07F80003FC0FF80003FE0FF80003FE0FF
+80003FE0FF80003FE0FF80003FE0FF80003FE0FF80003FE0FF80003FE07F80003FC07F80003FC0
+7F80003FC03FC0007F803FC0007F801FC0007F000FE000FE0007E000FC0003F803F80001FE0FF0
+00007FFFC0000007FC000023207E9F28>I<01F83FE000FFF8FFFC00FFFBE07F00FFFF003F8007
+FE001FC007FC000FE007F8000FF007F80007F807F80007F807F80007FC07F80003FC07F80003FC
+07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003
+FE07F80003FC07F80007FC07F80007FC07F80007F807F80007F807F8000FF007FC000FE007FE00
+1FC007FF003F8007FBC0FE0007F8FFF80007F83FC00007F800000007F800000007F800000007F8
+00000007F800000007F800000007F800000007F800000007F800000007F800000007F8000000FF
+FFC00000FFFFC00000FFFFC00000272E7E9F2D>I<03F03F00FFF07FC0FFF1C3E0FFF187E00FF3
+0FF007F60FF007F60FF007FC07E007FC03C007FC000007FC000007F8000007F8000007F8000007
+F8000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F80000
+07F8000007F8000007F8000007F8000007F80000FFFFE000FFFFE000FFFFE0001C207E9F21>
+114 D<01FF860007FFFE001F00FE003C003E0078001E0078000E00F8000E00F8000E00F8000E00
+FC000000FF800000FFFC00007FFFC0007FFFF0003FFFF8001FFFFC0007FFFE0001FFFF00003FFF
+000000FF8000003F8060001F80E0000F80E0000F80F0000F80F0000F00F8000F00FC001E00FE00
+1C00FF807800F3FFF000C07F800019207D9F20>I<001C0000001C0000001C0000001C0000001C
+0000003C0000003C0000003C0000007C0000007C000000FC000001FC000003FC000007FC00001F
+FFFE00FFFFFE00FFFFFE0003FC000003FC000003FC000003FC000003FC000003FC000003FC0000
+03FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC03
+8003FC038003FC038003FC038003FC038003FC038003FC038001FC038001FC070000FE0700007F
+0E00003FFC000007F000192E7FAD1F>I<01F80007E0FFF803FFE0FFF803FFE0FFF803FFE00FF8
+003FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007
+F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE0
+07F8001FE007F8001FE007F8001FE007F8001FE007F8003FE007F8003FE003F8007FE003F8007F
+E001FC00DFF000FE039FFF007FFF1FFF000FFC1FFF28207D9F2D>I<FFFF801FFCFFFF801FFCFF
+FF801FFC0FF80003C007F800038007FC00078003FC00070003FE000F0001FE000E0001FF000E00
+00FF001C0000FF001C00007F803800007F803800007FC07800003FC07000003FE0F000001FE0E0
+00001FF1E000000FF1C000000FF9C0000007FB80000007FB80000003FF00000003FF00000003FF
+00000001FE00000001FE00000000FC00000000FC00000000780000000078000026207E9F2B>I<
+FFFF1FFFE07FF8FFFF1FFFE07FF8FFFF1FFFE07FF80FF000FE0007800FF800FE00078007F800FE
+00070007F8007F00070003FC007F000E0003FC00FF800E0003FE00FF801E0001FE00FF801C0001
+FE01DFC01C0001FF01DFC03C0000FF03DFE0380000FF838FE07800007F838FE07000007F8707F0
+7000007FC707F0F000003FCF07F8E000003FCE03F8E000001FEE03F9C000001FFC01FDC000001F
+FC01FFC000000FFC01FF8000000FF800FF80000007F800FF00000007F0007F00000007F0007F00
+000003F0007E00000003E0003E00000001E0003C00000001C0001C000035207E9F3A>I<7FFF80
+7FFC7FFF807FFC7FFF807FFC03FE000F0001FE001E0000FF003C0000FF807800007FC07800003F
+E0F000001FE1E000000FF3C000000FFF80000007FF00000003FE00000001FE00000000FF000000
+00FF80000000FFC0000001FFC0000003DFE00000078FF00000078FF800000F07FC00001E03FC00
+003C01FE00007800FF0000F000FF8000E0007FC001E0003FC0FFFC01FFFFFFFC01FFFFFFFC01FF
+FF28207F9F2B>I<FFFF801FFCFFFF801FFCFFFF801FFC0FF80003C007F800038007FC00078003
+FC00070003FE000F0001FE000E0001FF000E0000FF001C0000FF001C00007F803800007F803800
+007FC07800003FC07000003FE0F000001FE0E000001FF1E000000FF1C000000FF9C0000007FB80
+000007FB80000003FF00000003FF00000003FF00000001FE00000001FE00000000FC00000000FC
+000000007800000000780000000070000000007000000000F000000000E000000001E000007C01
+C00000FE03C00000FE03800000FE07800000FE0F000000FC1E000000787C0000003FF00000000F
+C0000000262E7E9F2B>I E /Fl 1 14 df<0001FE00000007FF8000001E01E000007800780000
+E0001C000180000600030000030006000001800C000000C00C000000C018000000603000000030
+30000000303000000030600000001860000000186000000018C00000000CC00000000CC0000000
+0CC00000000CC00000000CC00000000CC00000000CC00000000CC00000000C6000000018600000
+0018600000001830000000303000000030300000003018000000600C000000C00C000000C00600
+0001800300000300018000060000E0001C000078007800001E01E0000007FF80000001FE000026
+2B7DA02D>13 D E /Fm 46 122 df<3C007F00FF80FF80FFC0FFC0FFC07FC03EC000C000C00180
+018001800300030006000E001C00380030000A157B8813>44 D<1C007F007F00FF80FF80FF807F
+007F001C0009097B8813>46 D<000E00001E00007E0007FE00FFFE00FFFE00F8FE0000FE0000FE
+0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE
+0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE
+0000FE007FFFFE7FFFFE7FFFFE17277BA622>49 D<00FF800007FFF0000FFFFC001E03FE003800
+FF807C003F80FE003FC0FF001FC0FF001FE0FF000FE0FF000FE07E000FE03C001FE000001FE000
+001FC000001FC000003F8000003F0000007E000000FC000000F8000001F0000003E00000078000
+000F0000001E0000003C00E0007000E000E000E001C001C0038001C0060001C00FFFFFC01FFFFF
+C03FFFFFC07FFFFFC0FFFFFF80FFFFFF80FFFFFF801B277DA622>I<007F800003FFF00007FFFC
+000F80FE001F007F003F807F003F803F803F803F803F803F801F803F801F003F8000007F000000
+7F0000007E000000FC000001F8000007F00000FFC00000FFC0000001F80000007E0000003F0000
+003F8000001FC000001FC000001FE000001FE03C001FE07E001FE0FF001FE0FF001FE0FF001FC0
+FF003FC0FE003F807C007F003F00FE001FFFFC0007FFF00000FF80001B277DA622>I<00000E00
+00001E0000003E0000007E000000FE000000FE000001FE000003FE0000077E00000E7E00000E7E
+00001C7E0000387E0000707E0000E07E0000E07E0001C07E0003807E0007007E000E007E000E00
+7E001C007E0038007E0070007E00E0007E00FFFFFFF8FFFFFFF8FFFFFFF80000FE000000FE0000
+00FE000000FE000000FE000000FE000000FE000000FE00007FFFF8007FFFF8007FFFF81D277EA6
+22>I<180003001F801F001FFFFE001FFFFC001FFFF8001FFFF0001FFFC0001FFF00001C000000
+1C0000001C0000001C0000001C0000001C0000001C0000001C7FC0001DFFF8001F80FC001E003F
+0008003F0000001F8000001FC000001FC000001FE000001FE018001FE07C001FE0FE001FE0FE00
+1FE0FE001FE0FE001FC0FC001FC078003F8078003F803C007F001F01FE000FFFFC0003FFF00000
+FF80001B277DA622>I<380000003E0000003FFFFFF03FFFFFF03FFFFFF07FFFFFE07FFFFFC07F
+FFFF807FFFFF0070000E0070000E0070001C00E0003800E0007000E000E0000001E0000001C000
+000380000007800000070000000F0000001F0000001E0000003E0000003E0000007E0000007C00
+00007C000000FC000000FC000000FC000000FC000001FC000001FC000001FC000001FC000001FC
+000001FC000001FC000000F80000007000001C297CA822>55 D<00000780000000000780000000
+000FC0000000000FC0000000000FC0000000001FE0000000001FE0000000003FF0000000003FF0
+000000003FF00000000077F80000000077F800000000F7FC00000000E3FC00000000E3FC000000
+01C1FE00000001C1FE00000003C1FF0000000380FF0000000380FF00000007007F80000007007F
+8000000F007FC000000E003FC000000E003FC000001C001FE000001C001FE000003FFFFFF00000
+3FFFFFF000003FFFFFF00000700007F80000700007F80000F00007FC0000E00003FC0000E00003
+FC0001C00001FE0001C00001FE0003C00001FF00FFFE003FFFFCFFFE003FFFFCFFFE003FFFFC2E
+297EA833>65 D<FFFFFFF800FFFFFFFF00FFFFFFFFC003F8001FE003F8000FF003F80007F803F8
+0003F803F80003FC03F80003FC03F80001FC03F80001FC03F80001FC03F80003FC03F80003F803
+F80003F803F80007F003F8000FF003F8001FC003F800FF8003FFFFFE0003FFFFFFC003F8000FF0
+03F80003F803F80001FC03F80001FE03F80000FE03F80000FE03F80000FF03F80000FF03F80000
+FF03F80000FF03F80000FF03F80000FF03F80000FE03F80001FE03F80003FC03F80007FC03F800
+1FF8FFFFFFFFE0FFFFFFFFC0FFFFFFFE0028297DA830>I<00007FE0030007FFFC07001FFFFF0F
+007FF00F9F00FF0001FF01FC0000FF03F800007F07F000003F0FE000001F1FC000001F1FC00000
+0F3F8000000F3F800000077F800000077F800000077F00000000FF00000000FF00000000FF0000
+0000FF00000000FF00000000FF00000000FF00000000FF00000000FF000000007F000000007F80
+0000007F800000073F800000073F800000071FC00000071FC000000E0FE000000E07F000001C03
+F800003C01FC00007800FF0001F0007FF007C0001FFFFF800007FFFE0000007FF00028297CA831
+>I<FFFFFFFFE0FFFFFFFFE0FFFFFFFFE003FC001FE003FC0007F003FC0001F003FC0001F003FC
+0000F003FC00007003FC00007003FC00007003FC01C07803FC01C03803FC01C03803FC01C03803
+FC03C00003FC03C00003FC0FC00003FFFFC00003FFFFC00003FFFFC00003FC0FC00003FC03C000
+03FC03C00003FC01C00E03FC01C00E03FC01C00E03FC01C01C03FC00001C03FC00001C03FC0000
+1C03FC00003C03FC00003803FC00007803FC0000F803FC0001F803FC0003F803FC001FF8FFFFFF
+FFF0FFFFFFFFF0FFFFFFFFF027297EA82C>69 D<FFFFFFFFC0FFFFFFFFC0FFFFFFFFC003FC003F
+C003FC000FE003FC0003E003FC0001E003FC0001E003FC0000E003FC0000E003FC0000E003FC00
+00F003FC01C07003FC01C07003FC01C07003FC01C00003FC03C00003FC03C00003FC0FC00003FF
+FFC00003FFFFC00003FFFFC00003FC0FC00003FC03C00003FC03C00003FC01C00003FC01C00003
+FC01C00003FC01C00003FC00000003FC00000003FC00000003FC00000003FC00000003FC000000
+03FC00000003FC00000003FC000000FFFFFC0000FFFFFC0000FFFFFC000024297EA82A>I<0000
+7FE003000007FFFC0700001FFFFF0F00007FF00F9F0000FF0001FF0001FC0000FF0003F800007F
+0007F000003F000FE000001F001FC000001F001FC000000F003F8000000F003F80000007007F80
+000007007F80000007007F0000000000FF0000000000FF0000000000FF0000000000FF00000000
+00FF0000000000FF0000000000FF0000000000FF0000000000FF0000FFFFF87F0000FFFFF87F80
+00FFFFF87F800000FF003F800000FF003F800000FF001FC00000FF001FC00000FF000FE00000FF
+0007F00000FF0003F80000FF0001FC0000FF0000FF0001FF00007FF007FF00001FFFFF9F000007
+FFFE0F0000007FF003002D297CA835>I<FFFFF00FFFFFFFFFF00FFFFFFFFFF00FFFFF03FC0000
+3FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003
+FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC0000
+3FC003FC00003FC003FFFFFFFFC003FFFFFFFFC003FFFFFFFFC003FC00003FC003FC00003FC003
+FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC0000
+3FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003
+FC00003FC003FC00003FC0FFFFF00FFFFFFFFFF00FFFFFFFFFF00FFFFF30297EA835>I<FFFFFC
+FFFFFCFFFFFC01FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE00
+01FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE00
+01FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE00FFFFFCFFFFFC
+FFFFFC16297FA819>I<FFFE0000003FFF80FFFE0000003FFF80FFFF0000007FFF8003FF000000
+7FE00003FF0000007FE00003BF800000EFE00003BF800000EFE000039FC00001CFE000039FC000
+01CFE000038FE000038FE000038FE000038FE000038FE000038FE0000387F000070FE0000387F0
+00070FE0000383F8000E0FE0000383F8000E0FE0000381FC001C0FE0000381FC001C0FE0000381
+FC001C0FE0000380FE00380FE0000380FE00380FE00003807F00700FE00003807F00700FE00003
+803F80E00FE00003803F80E00FE00003803F80E00FE00003801FC1C00FE00003801FC1C00FE000
+03800FE3800FE00003800FE3800FE000038007F7000FE000038007F7000FE000038007F7000FE0
+00038003FE000FE000038003FE000FE000038001FC000FE000038001FC000FE000038000F8000F
+E000FFFE00F803FFFF80FFFE00F803FFFF80FFFE007003FFFF8039297DA840>77
+D<FFFC00007FFFFFFE00007FFFFFFF00007FFF03FF800001C003FFC00001C003BFE00001C0039F
+E00001C0039FF00001C0038FF80001C00387FC0001C00383FE0001C00381FF0001C00380FF8001
+C003807F8001C003807FC001C003803FE001C003801FF001C003800FF801C0038007FC01C00380
+03FC01C0038003FE01C0038001FF01C0038000FF81C00380007FC1C00380003FE1C00380001FF1
+C00380000FF1C00380000FF9C003800007FDC003800003FFC003800001FFC003800000FFC00380
+00007FC0038000007FC0038000003FC0038000001FC0038000000FC00380000007C0FFFE000003
+C0FFFE000001C0FFFE000001C030297EA835>I<FFFFFFF800FFFFFFFF00FFFFFFFFC003FC003F
+E003FC0007F003FC0003F803FC0003FC03FC0001FC03FC0001FE03FC0001FE03FC0001FE03FC00
+01FE03FC0001FE03FC0001FE03FC0001FE03FC0001FC03FC0003FC03FC0003F803FC0007F003FC
+003FE003FFFFFF8003FFFFFE0003FC00000003FC00000003FC00000003FC00000003FC00000003
+FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC000000
+03FC00000003FC00000003FC000000FFFFF00000FFFFF00000FFFFF0000027297EA82E>80
+D<FFFFFFE00000FFFFFFFE0000FFFFFFFF800003FC003FE00003FC000FF00003FC0007F80003FC
+0003FC0003FC0001FC0003FC0001FE0003FC0001FE0003FC0001FE0003FC0001FE0003FC0001FE
+0003FC0001FE0003FC0001FC0003FC0003F80003FC0007F80003FC000FE00003FC003FC00003FF
+FFFE000003FFFFFE000003FC00FF800003FC003FC00003FC001FE00003FC000FF00003FC0007F8
+0003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC
+0007F80003FC0007F80003FC0007F80E03FC0007F80E03FC0003F80E03FC0001FC1CFFFFF000FE
+1CFFFFF0007FF8FFFFF0000FE02F297EA832>82 D<00FF00C003FFE1C00FFFF9C01F80FFC03F00
+3FC03E000FC07C0007C07C0007C0FC0003C0FC0003C0FC0001C0FE0001C0FE0001C0FF000000FF
+C000007FFC00007FFFE0003FFFF8001FFFFE001FFFFF0007FFFF8003FFFFC000FFFFC0000FFFE0
+00007FE000001FF000000FF0000007F0E00003F0E00003F0E00003F0E00003F0F00003E0F00003
+E0F80007E0FC0007C0FF000F80FFE01F80E3FFFF00E1FFFC00C01FF0001C297CA825>I<FFFFF0
+00FFFEFFFFF000FFFEFFFFF000FFFE03FC0000038003FC0000038003FC0000038003FC00000380
+03FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC00
+00038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC00000380
+03FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC00
+00038003FC0000038003FC0000038003FC0000038003FC0000038001FC0000070001FE00000700
+00FE00000E00007F00000E00003F00003C00001FC0007800000FF003F0000007FFFFE0000000FF
+FF800000001FFC00002F297EA834>85 D<FFFFF0007FFFFFFFF0007FFFFFFFF0007FFF03FE0000
+01C001FE0000038001FE0000038000FF0000070000FF0000070000FF80000F00007F80000E0000
+7FC0000E00003FC0001C00003FE0001C00001FE0003800001FE0003800001FF0007800000FF000
+7000000FF800F0000007F800E0000007FC00E0000003FC01C0000003FC01C0000003FE03C00000
+01FE0380000001FF0780000000FF0700000000FF87000000007F8E000000007F8E000000007FDE
+000000003FDC000000003FFC000000001FF8000000001FF8000000000FF0000000000FF0000000
+000FF00000000007E00000000007E00000000003C00000000003C0000030297FA833>I<FFFFE0
+FFFFE01FFFC0FFFFE0FFFFE01FFFC0FFFFE0FFFFE01FFFC003FC0003FC0000700003FC0003FC00
+00700003FE0003FE0000F00001FE0001FE0000E00001FE0001FE0000E00001FF0001FF0001E000
+00FF0001FF0001C00000FF0001FF0001C000007F8003FF80038000007F8003FF80038000007FC0
+07FFC0078000003FC0073FC0070000003FC0073FC0070000003FE00F3FE00F0000001FE00E1FE0
+0E0000001FE00E1FE00E0000000FF01C0FF01C0000000FF01C0FF01C0000000FF01C0FF81C0000
+0007F83807F83800000007F83807F83800000007FC7807FC7800000003FC7003FC7000000003FC
+7003FC7000000003FEF003FEF000000001FEE001FEE000000001FEE001FEE000000000FFC000FF
+C000000000FFC000FFC000000000FFC000FFC0000000007F80007F80000000007F80007F800000
+00007F80007F80000000003F00003F00000000003F00003F00000000003F00003F00000000001E
+00001E00000000001E00001E00000042297FA845>I<03FF80000FFFF0001F01FC003F80FE003F
+807F003F803F003F803F801F003F8000003F8000003F8000003F8000003F80003FFF8001FC3F80
+0FE03F801F803F803F003F807E003F80FC003F80FC003F80FC003F80FC003F80FC005F807E00DF
+803F839FFC1FFE0FFC03F803FC1E1B7E9A21>97 D<FFE00000FFE00000FFE000000FE000000FE0
+00000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000F
+E000000FE1FE000FE7FF800FFE07E00FF803F00FF001F80FE000FC0FE000FC0FE0007E0FE0007E
+0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007E0FE000
+7E0FE0007E0FE000FC0FE000FC0FF001F80FF803F00F9C0FE00F0FFF800E01FC00202A7EA925>
+I<003FF00001FFFC0003F03E000FC07F001F807F003F007F003F007F007F003E007E0000007E00
+0000FE000000FE000000FE000000FE000000FE000000FE000000FE0000007E0000007E0000007F
+0000003F0003803F8003801F8007000FE00E0003F83C0001FFF800003FC000191B7E9A1E>I<00
+007FF000007FF000007FF0000007F0000007F0000007F0000007F0000007F0000007F0000007F0
+000007F0000007F0000007F0000007F0000007F0003F87F001FFF7F007F03FF00FC00FF01F8007
+F03F0007F03F0007F07E0007F07E0007F07E0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE00
+07F0FE0007F0FE0007F0FE0007F07E0007F07E0007F03F0007F03F0007F01F800FF00FC01FF007
+E07FFF01FFE7FF007F87FF202A7EA925>I<003FC00001FFF00003E07C000F803E001F801F001F
+001F003F000F807E000F807E000FC07E000FC0FE0007C0FE0007C0FFFFFFC0FFFFFFC0FE000000
+FE000000FE0000007E0000007E0000007F0000003F0001C01F0001C00F80038007C0070003F01E
+0000FFFC00003FE0001A1B7E9A1F>I<0007F8003FFC007E3E01FC7F03F87F03F07F07F07F07F0
+3E07F00007F00007F00007F00007F00007F00007F000FFFFC0FFFFC0FFFFC007F00007F00007F0
+0007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F0
+0007F00007F00007F00007F00007F0007FFF807FFF807FFF80182A7EA915>I<007F80F001FFE3
+F807C0FE1C0F807C7C1F003E7C1F003E103F003F003F003F003F003F003F003F003F003F003F00
+3F001F003E001F003E000F807C0007C0F80005FFE0000C7F8000180000001C0000001C0000001E
+0000001FFFF8001FFFFF000FFFFFC007FFFFE003FFFFF00FFFFFF03E0007F07C0001F8F80000F8
+F80000F8F80000F8F80000F87C0001F07C0001F03F0007E00FC01F8007FFFF00007FF0001E287E
+9A22>I<FFE00000FFE00000FFE000000FE000000FE000000FE000000FE000000FE000000FE000
+000FE000000FE000000FE000000FE000000FE000000FE000000FE07E000FE1FF800FE30FC00FE4
+0FE00FE807E00FF807F00FF007F00FF007F00FE007F00FE007F00FE007F00FE007F00FE007F00F
+E007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F0
+0FE007F0FFFE3FFFFFFE3FFFFFFE3FFF202A7DA925>I<07000F801FC03FE03FE03FE01FC00F80
+07000000000000000000000000000000FFE0FFE0FFE00FE00FE00FE00FE00FE00FE00FE00FE00F
+E00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE0FFFEFFFEFFFE0F2B7EAA12>I<FF
+E0FFE0FFE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE0
+0FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE0FF
+FEFFFEFFFE0F2A7EA912>108 D<FFC07F001FC000FFC1FFC07FF000FFC307E0C1F8000FC407F1
+01FC000FC803F200FC000FD803FE00FE000FD003FC00FE000FD003FC00FE000FE003F800FE000F
+E003F800FE000FE003F800FE000FE003F800FE000FE003F800FE000FE003F800FE000FE003F800
+FE000FE003F800FE000FE003F800FE000FE003F800FE000FE003F800FE000FE003F800FE000FE0
+03F800FE000FE003F800FE000FE003F800FE000FE003F800FE00FFFE3FFF8FFFE0FFFE3FFF8FFF
+E0FFFE3FFF8FFFE0331B7D9A38>I<FFC07E00FFC1FF80FFC30FC00FC40FE00FC807E00FD807F0
+0FD007F00FD007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007
+F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F0FFFE3FFFFFFE
+3FFFFFFE3FFF201B7D9A25>I<003FE00001FFFC0003F07E000FC01F801F800FC03F0007E03F00
+07E07E0003F07E0003F07E0003F0FE0003F8FE0003F8FE0003F8FE0003F8FE0003F8FE0003F8FE
+0003F8FE0003F87E0003F07E0003F03F0007E03F0007E01F800FC00FC01F8007F07F0001FFFC00
+003FE0001D1B7E9A22>I<FFE1FE00FFE7FF80FFFE0FE00FF803F00FF001F80FE001FC0FE000FC
+0FE000FE0FE000FE0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE000
+7F0FE0007E0FE000FE0FE000FE0FE000FC0FE001FC0FF001F80FF803F00FFC0FE00FEFFF800FE1
+FC000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE00000FF
+FE0000FFFE0000FFFE000020277E9A25>I<FFC3E0FFC7F8FFCC7C0FD8FE0FD0FE0FD0FE0FF0FE
+0FE07C0FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE000
+0FE0000FE0000FE0000FE000FFFF00FFFF00FFFF00171B7E9A1B>114 D<03FE300FFFF03E03F0
+7800F07000F0F00070F00070F80070FE0000FFE0007FFF007FFFC03FFFE01FFFF007FFF800FFF8
+0007FC0000FCE0007CE0003CF0003CF00038F80038FC0070FF01E0E7FFC0C1FF00161B7E9A1B>
+I<00700000700000700000700000F00000F00000F00001F00003F00003F00007F0001FFFE0FFFF
+E0FFFFE007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F0
+0007F00007F07007F07007F07007F07007F07007F07007F07003F0E001F8C000FFC0003F001426
+7FA51A>I<FFE07FF0FFE07FF0FFE07FF00FE007F00FE007F00FE007F00FE007F00FE007F00FE0
+07F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00F
+E007F00FE007F00FE007F00FE00FF00FE00FF007E017F003F067FF01FFC7FF007F87FF201B7D9A
+25>I<FFFE07FFFFFE07FFFFFE07FF07F000E007F000E007F801E003F801C003F801C001FC0380
+01FC038001FE078000FE070000FF0F00007F0E00007F0E00003F9C00003F9C00003FFC00001FF8
+00001FF800000FF000000FF000000FF0000007E0000007E0000003C0000003C000201B7F9A23>
+I<FFFC7FFC1FFCFFFC7FFC1FFCFFFC7FFC1FFC0FE00FE001C007F007E0038007F007E0038007F8
+07F0078003F807F0070003F807F8070001FC0FF80E0001FC0FF80E0001FE1FFC1E0000FE1CFC1C
+0000FE1CFE1C0000FF387E3C00007F387E3800007F787F3800003FF03F7000003FF03F7000003F
+E01FF000001FE01FE000001FE01FE000000FC00FC000000FC00FC000000FC00FC0000007800780
+000007800780002E1B7F9A31>I<FFFC1FFEFFFC1FFEFFFC1FFE07F0078003F8070001FC0F0001
+FE1E0000FE3C00007F7800003FF800003FF000001FE000000FE0000007F0000007F800000FF800
+001FFC00003DFE000038FF0000787F0000F03F8001E03FC003C01FE003800FE0FFF03FFFFFF03F
+FFFFF03FFF201B7F9A23>I<FFFE07FFFFFE07FFFFFE07FF07F000E007F000E007F801E003F801
+C003F801C001FC038001FC038001FE078000FE070000FF0F00007F0E00007F0E00003F9C00003F
+9C00003FFC00001FF800001FF800000FF000000FF0000007F0000007E0000007E0000003C00000
+03C000000380000003800000078000380700007C070000FE0E0000FE0E0000FE1C0000FE380000
+7C7000003FE000000F80000020277F9A23>I E /Fn 75 127 df<70F8F8F8F8F8F8F8F8F8F8F8
+F8F8F8F8F870000000000070F8F8F870051C779B18>33 D<4010E038F078E038E038E038E038E0
+38E038E038E038E038E03860300D0E7B9C18>I<030600078F00078F00078F00078F00078F0007
+8F007FFFC0FFFFE0FFFFE07FFFC00F1E000F1E000F1E000F1E000F1E000F1E007FFFC0FFFFE0FF
+FFE07FFFC01E3C001E3C001E3C001E3C001E3C001E3C000C1800131C7E9B18>I<00C00001C000
+01C00001C00003F0000FFC003FFE007DCF0071C700E1C380E1C780E1C780E1C780F1C00079C000
+3DC0001FE0000FF80003FC0001DE0001CF0001C70061C380F1C380F1C380E1C380E1C70071C700
+79DE003FFE001FF80007E00001C00001C00001C00000C00011247D9F18>I<3803007C07807C07
+80EE0F80EE0F00EE0F00EE1F00EE1E00EE1E00EE3E007C3C007C3C00387C0000780000780000F8
+0000F00001F00001E00001E00003E00003C00003C00007C0000783800787C00F87C00F0EE00F0E
+E01F0EE01E0EE01E0EE03E0EE03C07C03C07C018038013247E9F18>I<01C00007E0000FF0000E
+70001C38001C38001C38001C38001C73F01C73F01CE3F00FE3800FC7000F87000F07001F0E003F
+0E007B8E0073DC00E1DC00E0F800E0F800E07070E0787070FC707FFFE03FCFE00F03C0141C7F9B
+18>I<387C7C7E3E0E0E0E1C1C38F8F0C0070E789B18>I<007000F001E003C007800F001E001C00
+380038007000700070007000E000E000E000E000E000E000E000E0007000700070007000380038
+001C001E000F00078003C001F000F000700C24799F18>I<6000F00078003C001E000F00078003
+8001C001C000E000E000E000E00070007000700070007000700070007000E000E000E000E001C0
+01C0038007800F001E003C007800F00060000C247C9F18>I<01C00001C00001C00001C000C1C1
+80F1C780F9CF807FFF001FFC0007F00007F0001FFC007FFF00F9CF80F1C780C1C18001C00001C0
+0001C00001C00011147D9718>I<00600000F00000F00000F00000F00000F00000F00000F0007F
+FFC0FFFFE0FFFFE07FFFC000F00000F00000F00000F00000F00000F00000F00000600013147E97
+18>I<1C3E7E7F3F1F070E1E7CF860080C788518>I<7FFF00FFFF80FFFF807FFF0011047D8F18>
+I<3078FCFC78300606778518>I<000300000780000780000F80000F00001F00001E00001E0000
+3E00003C00007C0000780000780000F80000F00001F00001E00003E00003C00003C00007C00007
+80000F80000F00000F00001F00001E00003E00003C00003C00007C0000780000F80000F00000F0
+000060000011247D9F18>I<01F00007FC000FFE001F1F001C07003803807803C07001C07001C0
+E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0F001E07001C07001C07803C0
+3803801C07001F1F000FFE0007FC0001F000131C7E9B18>I<01800380038007800F803F80FF80
+FB80438003800380038003800380038003800380038003800380038003800380038003807FFCFF
+FE7FFC0F1C7B9B18>I<03F0000FFE003FFF007C0F807003C0E001C0F000E0F000E06000E00000
+E00000E00001C00001C00003C0000780000F00001E00003C0000780000F00001E00007C0000F80
+001E00E03C00E07FFFE0FFFFE07FFFE0131C7E9B18>I<001F00003F0000770000770000E70001
+E70001C7000387000787000707000E07001E07003C0700380700780700F00700FFFFF8FFFFF8FF
+FFF8000700000700000700000700000700000700007FF000FFF8007FF0151C7F9B18>52
+D<007E0001FF0007FF800F83C01E03C01C03C0380180380000700000700000E1F800E7FE00FFFF
+00FE0780F803C0F001C0F000E0E000E0F000E07000E07000E07000E03801C03C03C01E07800FFF
+0007FE0001F800131C7E9B18>54 D<3078FCFC783000000000000000003078FCFC783006147793
+18>58 D<183C7E7E3C180000000000000000183C7E7E3E1E0E1C3C78F060071A789318>I<0003
+00000780001F80003F00007E0001FC0003F00007E0001FC0003F00007E0000FC0000FC00007E00
+003F00001FC00007E00003F00001FC00007E00003F00001F8000078000030011187D9918>I<7F
+FFC0FFFFE0FFFFE0FFFFE0000000000000000000000000FFFFE0FFFFE0FFFFE07FFFC0130C7E93
+18>I<600000F00000FC00007E00003F00001FC00007E00003F00001FC00007E00003F00001F80
+001F80003F00007E0001FC0003F00007E0001FC0003F00007E0000FC0000F0000060000011187D
+9918>I<0FF0003FFC007FFF00700F00F00380F00380600780000F00003E00007C0001F00001E0
+0003C00003C00003C00003C00003C00003800000000000000000000000000000000003800007C0
+0007C00007C000038000111C7D9B18>I<00700000F80000F80000D80000D80001DC0001DC0001
+DC00018C00038E00038E00038E00038E000306000707000707000707000707000FFF800FFF800F
+FF800E03800E03801C01C01C01C07F07F0FF8FF87F07F0151C7F9B18>65
+D<7FF800FFFE007FFF001C0F801C03C01C03C01C01E01C00E01C00E01C00F01C00701C00701C00
+701C00701C00701C00701C00701C00701C00F01C00E01C00E01C01E01C01C01C03C01C0F807FFF
+00FFFE007FF800141C7F9B18>68 D<FFFFF0FFFFF0FFFFF01C00701C00701C00701C00701C0000
+1C00001C0E001C0E001C0E001FFE001FFE001FFE001C0E001C0E001C0E001C00001C00001C0038
+1C00381C00381C00381C0038FFFFF8FFFFF8FFFFF8151C7F9B18>I<FFFFE0FFFFE0FFFFE01C00
+E01C00E01C00E01C00E01C00001C00001C1C001C1C001C1C001FFC001FFC001FFC001C1C001C1C
+001C1C001C00001C00001C00001C00001C00001C00001C0000FFC000FFC000FFC000131C7E9B18
+>I<7F07F0FF8FF87F07F01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01F
+FFC01FFFC01FFFC01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C07F
+07F0FF8FF87F07F0151C7F9B18>72 D<7FFF00FFFF807FFF0001C00001C00001C00001C00001C0
+0001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C0
+0001C00001C00001C00001C0007FFF00FFFF807FFF00111C7D9B18>I<7FE000FFE0007FE0000E
+00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E
+00000E00000E00000E00000E00700E00700E00700E00700E00707FFFF0FFFFF07FFFF0141C7F9B
+18>76 D<7E07F0FF0FF87F07F01D81C01D81C01D81C01DC1C01CC1C01CC1C01CE1C01CE1C01CE1
+C01C61C01C71C01C71C01C31C01C39C01C39C01C39C01C19C01C19C01C1DC01C0DC01C0DC01C0D
+C07F07C0FF87C07F03C0151C7F9B18>78 D<0FF8003FFE007FFF00780F00700700F00780E00380
+E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380
+E00380E00380F00780700700780F007FFF003FFE000FF800111C7D9B18>I<FFFE00FFFF80FFFF
+C01C03C01C01E01C00E01C00701C00701C00701C00701C00701C00E01C01E01C03C01FFFC01FFF
+801FFE001C00001C00001C00001C00001C00001C00001C00001C0000FF8000FF8000FF8000141C
+7F9B18>I<7FF800FFFE007FFF001C0F801C03801C03C01C01C01C01C01C01C01C03C01C03801C
+0F801FFF001FFE001FFE001C0F001C07001C03801C03801C03801C03801C03801C039C1C039C1C
+039C7F01F8FF81F87F00F0161C7F9B18>82 D<03F3801FFF803FFF807C0F80700780E00380E003
+80E00380E000007000007800003F00001FF00007FE0000FF00000F800003C00001C00000E00000
+E06000E0E000E0E001E0F001C0F80780FFFF80FFFE00E7F800131C7E9B18>I<7FFFF8FFFFF8FF
+FFF8E07038E07038E07038E0703800700000700000700000700000700000700000700000700000
+700000700000700000700000700000700000700000700000700000700007FF0007FF0007FF0015
+1C7F9B18>I<FF83FEFF83FEFF83FE1C00701C00701C00701C00701C00701C00701C00701C0070
+1C00701C00701C00701C00701C00701C00701C00701C00701C00701C00701C00700E00E00F01E0
+0783C003FF8001FF00007C00171C809B18>I<FF07F8FF07F8FF07F81C01C01E03C00E03800F07
+80070700070700038E00038E0001DC0001DC0001DC0000F80000F8000070000070000070000070
+0000700000700000700000700000700001FC0003FE0001FC00151C7F9B18>89
+D<FFF8FFF8FFF8E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000
+E000E000E000E000E000E000E000E000E000E000E000E000E000E000FFF8FFF8FFF80D24779F18
+>91 D<600000F00000F00000F800007800007C00003C00003C00003E00001E00001F00000F0000
+0F00000F800007800007C00003C00003C00003E00001E00001F00000F00000F800007800007800
+007C00003C00003E00001E00001E00001F00000F00000F8000078000078000030011247D9F18>
+I<FFF8FFF8FFF80038003800380038003800380038003800380038003800380038003800380038
+00380038003800380038003800380038003800380038003800380038FFF8FFF8FFF80D247F9F18
+>I<018007C01FF07EFCF83EE00E0F067C9B18>I<7FFF00FFFF80FFFF807FFF0011047D7F18>I<
+061E3E387070E0E0E0F8FC7C7C38070E789E18>I<1FE0003FF8007FFC00781E00300E00000700
+00070000FF0007FF001FFF007F0700780700E00700E00700E00700F00F00781F003FFFF01FFBF0
+07E1F014147D9318>I<7E0000FE00007E00000E00000E00000E00000E00000E00000E3E000EFF
+800FFFC00FC1E00F80E00F00700E00700E00380E00380E00380E00380E00380E00380F00700F00
+700F80E00FC1E00FFFC00EFF80063E00151C809B18>I<01FE0007FF001FFF803E078038030070
+0000700000E00000E00000E00000E00000E00000E000007000007001C03801C03E03C01FFF8007
+FF0001FC0012147D9318>I<001F80003F80001F8000038000038000038000038000038003E380
+0FFB801FFF803C1F80380F80700780700380E00380E00380E00380E00380E00380E00380700780
+700780380F803C1F801FFFF00FFBF803E3F0151C7E9B18>I<01F00007FC001FFE003E0F003807
+80700380700380E001C0E001C0FFFFC0FFFFC0FFFFC0E000007000007001C03801C03E03C01FFF
+8007FF0001FC0012147D9318>I<001F80007FC000FFE000E1E001C0C001C00001C00001C0007F
+FFC0FFFFC0FFFFC001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001
+C00001C00001C00001C0007FFF007FFF007FFF00131C7F9B18>I<01E1F007FFF80FFFF81E1E30
+1C0E003807003807003807003807003807001C0E001E1E001FFC001FF80039E0003800001C0000
+1FFE001FFFC03FFFE07801F0700070E00038E00038E00038E000387800F07E03F01FFFC00FFF80
+01FC00151F7F9318>I<7E0000FE00007E00000E00000E00000E00000E00000E00000E3E000EFF
+800FFFC00FC1C00F80E00F00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00
+E00E00E00E00E07FC3FCFFE7FE7FC3FC171C809B18>I<03800007C00007C00007C00003800000
+00000000000000000000007FC000FFC0007FC00001C00001C00001C00001C00001C00001C00001
+C00001C00001C00001C00001C00001C00001C00001C000FFFF00FFFF80FFFF00111D7C9C18>I<
+7FE000FFE0007FE00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E000
+00E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E0007FFFC0
+FFFFE07FFFC0131C7E9B18>108 D<7CE0E000FFFBF8007FFFF8001F1F1C001E1E1C001E1E1C00
+1C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C
+001C1C1C007F1F1F00FFBFBF807F1F1F001914819318>I<7E3E00FEFF807FFFC00FC1C00F80E0
+0F00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E07FC3FC
+FFE7FE7FC3FC1714809318>I<01F0000FFE001FFF003E0F803803807001C07001C0E000E0E000
+E0E000E0E000E0E000E0F001E07001C07803C03C07803E0F801FFF000FFE0001F00013147E9318
+>I<7E3E00FEFF807FFFC00FC1E00F80E00F00700E00700E00380E00380E00380E00380E00380E
+00380F00700F00700F80E00FC1E00FFFC00EFF800E3E000E00000E00000E00000E00000E00000E
+00000E00007FC000FFE0007FC000151E809318>I<01E38007FB801FFF803E1F80380F80700780
+700780E00380E00380E00380E00380E00380E00380700780700780380F803C1F801FFF800FFB80
+03E380000380000380000380000380000380000380000380003FF8003FF8003FF8151E7E9318>
+I<7F87E0FF9FF07FBFF803F87803F03003E00003C00003C0000380000380000380000380000380
+000380000380000380000380007FFE00FFFF007FFE0015147F9318>I<07F7003FFF007FFF0078
+0F00E00700E00700E007007C00007FE0001FFC0003FE00001F00600780E00380E00380F00380F8
+0F00FFFF00FFFC00E7F00011147D9318>I<0180000380000380000380000380007FFFC0FFFFC0
+FFFFC00380000380000380000380000380000380000380000380000380000380400380E00380E0
+0380E001C1C001FFC000FF80003E0013197F9818>I<7E07E0FE0FE07E07E00E00E00E00E00E00
+E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E01E00F03E007FFFC03FF
+FE01FCFC1714809318>I<7F8FF0FF8FF87F8FF01E03C00E03800E03800E038007070007070007
+0700038E00038E00038E00038E0001DC0001DC0001DC0000F80000F80000700015147F9318>I<
+FF8FF8FF8FF8FF8FF83800E03800E03800E01C01C01C01C01C71C01CF9C01CF9C01CD9C01CD9C0
+0DDD800DDD800DDD800D8D800F8F800F8F8007070015147F9318>I<7F8FF07F9FF07F8FF00707
+00078E00039E0001DC0001F80000F80000700000F00000F80001DC00039E00038E000707000F07
+807F8FF0FF8FF87F8FF015147F9318>I<7F8FF0FF8FF87F8FF00E01C00E03800E038007038007
+0700070700038700038600038E0001CE0001CE0000CC0000CC0000DC0000780000780000780000
+700000700000700000F00000E00079E0007BC0007F80003F00001E0000151E7F9318>I<3FFFF0
+7FFFF07FFFF07001E07003C0700780000F00001E00003C0000F80001F00003C0000780000F0070
+1E00703C0070780070FFFFF0FFFFF0FFFFF014147F9318>I<0007E0001FE0007FE000780000E0
+0000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00001E0007FC000FF80
+00FF80007FC00001E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E0
+0000E000007800007FE0001FE00007E013247E9F18>I<60F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0
+F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0600424769F18>I<7C0000FF0000FFC00003C000
+00E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000F000007FC0
+003FE0003FE0007FC000F00000E00000E00000E00000E00000E00000E00000E00000E00000E000
+00E00000E00003C000FFC000FF00007C000013247E9F18>I<060C1F1E3FBEFBF8F1F060C00F06
+7C9B18>I E /Fo 75 123 df<001F83E000F06E3001C078780380F8780300F030070070000700
+70000700700007007000070070000700700007007000FFFFFF8007007000070070000700700007
+007000070070000700700007007000070070000700700007007000070070000700700007007000
+07007000070070000700700007007000070070007FE3FF001D20809F1B>11
+D<003F0000E0C001C0C00381E00701E00701E0070000070000070000070000070000070000FFFF
+E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700
+E00700E00700E00700E00700E00700E07FC3FE1720809F19>I<003FE000E0E001C1E00381E007
+00E00700E00700E00700E00700E00700E00700E00700E0FFFFE00700E00700E00700E00700E007
+00E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E007
+00E07FE7FE1720809F19>I<001F81F80000F04F040001C07C06000380F80F000300F00F000700
+F00F00070070000007007000000700700000070070000007007000000700700000FFFFFFFF0007
+007007000700700700070070070007007007000700700700070070070007007007000700700700
+070070070007007007000700700700070070070007007007000700700700070070070007007007
+00070070070007007007007FE3FE3FF02420809F26>I<7038F87CFC7EFC7E743A040204020402
+0804080410081008201040200F0E7E9F17>34 D<70F8FCFC74040404080810102040060E7C9F0D
+>39 D<0020004000800100020006000C000C00180018003000300030007000600060006000E000
+E000E000E000E000E000E000E000E000E000E000E0006000600060007000300030003000180018
+000C000C000600020001000080004000200B2E7DA112>I<800040002000100008000C00060006
+000300030001800180018001C000C000C000C000E000E000E000E000E000E000E000E000E000E0
+00E000E000C000C000C001C001800180018003000300060006000C00080010002000400080000B
+2E7DA112>I<70F8FCFC74040404080810102040060E7C840D>44 D<FFC0FFC00A027F8A0F>I<70
+F8F8F87005057C840D>I<03F0000E1C001C0E00180600380700700380700380700380700380F0
+03C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C070
+03807003807003807807803807001806001C0E000E1C0003F000121F7E9D17>48
+D<018003800F80F380038003800380038003800380038003800380038003800380038003800380
+03800380038003800380038003800380038007C0FFFE0F1E7C9D17>I<03F0000C1C00100E0020
+0700400780800780F007C0F803C0F803C0F803C02007C00007C0000780000780000F00000E0000
+1C0000380000700000600000C0000180000300000600400C00401800401000803FFF807FFF80FF
+FF80121E7E9D17>I<03F0000C1C00100E00200F00780F80780780780780380F80000F80000F00
+000F00000E00001C0000380003F000003C00000E00000F000007800007800007C02007C0F807C0
+F807C0F807C0F00780400780400F00200E001C3C0003F000121F7E9D17>I<000600000600000E
+00000E00001E00002E00002E00004E00008E00008E00010E00020E00020E00040E00080E00080E
+00100E00200E00200E00400E00C00E00FFFFF0000E00000E00000E00000E00000E00000E00000E
+0000FFE0141E7F9D17>I<1803001FFE001FFC001FF8001FE00010000010000010000010000010
+000010000011F000161C00180E001007001007800003800003800003C00003C00003C07003C0F0
+03C0F003C0E00380400380400700200600100E000C380003E000121F7E9D17>I<007C00018200
+0701000E03800C07801C0780380300380000780000700000700000F1F000F21C00F40600F80700
+F80380F80380F003C0F003C0F003C0F003C0F003C07003C07003C0700380380380380700180700
+0C0E00061C0001F000121F7E9D17>I<4000007FFFC07FFF807FFF804001008002008002008004
+0000080000080000100000200000200000400000400000C00000C00001C0000180000380000380
+00038000038000078000078000078000078000078000078000078000030000121F7D9D17>I<03
+F0000C0C001006003003002001806001806001806001807001807803003E03003F06001FC8000F
+F00003F80007FC000C7E00103F00300F806003804001C0C001C0C000C0C000C0C000C0C0008060
+01802001001002000C0C0003F000121F7E9D17>I<03F0000E18001C0C00380600380700700700
+700380F00380F00380F003C0F003C0F003C0F003C0F003C07007C07007C03807C0180BC00E13C0
+03E3C0000380000380000380000700300700780600780E00700C002018001070000FC000121F7E
+9D17>I<70F8F8F8700000000000000000000070F8F8F87005147C930D>I<70F8F8F87000000000
+00000000000070F0F8F878080808101010202040051D7C930D>I<000100000003800000038000
+000380000007C0000007C0000007C0000009E0000009E0000009E0000010F0000010F0000010F0
+0000207800002078000020780000403C0000403C0000403C0000801E0000801E0000FFFE000100
+0F0001000F0001000F00020007800200078002000780040003C00E0003C01F0007E0FFC03FFE1F
+207F9F22>65 D<FFFFE0000F80380007801E0007801F0007800F0007800F8007800F8007800F80
+07800F8007800F8007800F0007801F0007801E0007803C0007FFF00007803C0007801E0007800F
+0007800F8007800780078007C0078007C0078007C0078007C0078007C00780078007800F800780
+0F0007801F000F803C00FFFFF0001A1F7E9E20>I<000FC040007030C001C009C0038005C00700
+03C00E0001C01E0000C01C0000C03C0000C07C0000407C00004078000040F8000000F8000000F8
+000000F8000000F8000000F8000000F8000000F8000000F8000000780000007C0000407C000040
+3C0000401C0000401E0000800E000080070001000380020001C0040000703800000FC0001A217D
+9F21>I<FFFFE0000F803C0007801E000780070007800380078003C0078001E0078001E0078001
+F0078000F0078000F0078000F8078000F8078000F8078000F8078000F8078000F8078000F80780
+00F8078000F8078000F0078000F0078000F0078001E0078001E0078003C0078003800780070007
+800E000F803C00FFFFE0001D1F7E9E23>I<FFFFFF000F800F0007800300078003000780010007
+800180078000800780008007800080078080800780800007808000078080000781800007FF8000
+078180000780800007808000078080000780800007800020078000200780002007800040078000
+4007800040078000C0078000C0078001800F800F80FFFFFF801B1F7E9E1F>I<FFFFFF000F800F
+000780030007800300078001000780018007800080078000800780008007800080078080000780
+800007808000078080000781800007FF8000078180000780800007808000078080000780800007
+800000078000000780000007800000078000000780000007800000078000000FC00000FFFE0000
+191F7E9E1E>I<000FE0200078186000E004E0038002E0070001E00F0000E01E0000601E000060
+3C0000603C0000207C00002078000020F8000000F8000000F8000000F8000000F8000000F80000
+00F8000000F8007FFCF80003E0780001E07C0001E03C0001E03C0001E01E0001E01E0001E00F00
+01E0070001E0038002E000E0046000781820000FE0001E217D9F24>I<FFF8FFF80F800F800780
+0F0007800F0007800F0007800F0007800F0007800F0007800F0007800F0007800F0007800F0007
+800F0007800F0007FFFF0007800F0007800F0007800F0007800F0007800F0007800F0007800F00
+07800F0007800F0007800F0007800F0007800F0007800F0007800F000F800F80FFF8FFF81D1F7E
+9E22>I<FFFC0FC007800780078007800780078007800780078007800780078007800780078007
+80078007800780078007800780078007800780078007800FC0FFFC0E1F7F9E10>I<0FFFC0007C
+00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C
+00003C00003C00003C00003C00003C00003C00003C00003C00203C00F83C00F83C00F83C00F038
+0040780040700030E0000F800012207E9E17>I<FFFE000FC00007800007800007800007800007
+800007800007800007800007800007800007800007800007800007800007800007800007800007
+800007800207800207800207800207800607800407800407800C07801C0F807CFFFFFC171F7E9E
+1C>76 D<FF80001FF80F80001F800780001F0005C0002F0005C0002F0005C0002F0004E0004F00
+04E0004F000470008F000470008F000470008F000438010F000438010F000438010F00041C020F
+00041C020F00041C020F00040E040F00040E040F00040E040F000407080F000407080F00040708
+0F000403900F000403900F000401E00F000401E00F000401E00F000E00C00F001F00C01F80FFE0
+C1FFF8251F7E9E2A>I<FF803FF807C007C007C0038005E0010005E0010004F001000478010004
+780100043C0100043C0100041E0100040F0100040F010004078100040781000403C1000401E100
+0401E1000400F1000400F1000400790004003D0004003D0004001F0004001F0004000F00040007
+00040007000E0003001F000300FFE001001D1F7E9E22>I<001F800000F0F00001C0380007801E
+000F000F000E0007001E0007803C0003C03C0003C07C0003E0780001E0780001E0F80001F0F800
+01F0F80001F0F80001F0F80001F0F80001F0F80001F0F80001F0F80001F0780001E07C0003E07C
+0003E03C0003C03C0003C01E0007800E0007000F000F0007801E0001C0380000F0F000001F8000
+1C217D9F23>I<FFFFE0000F80780007801C0007801E0007800F0007800F8007800F8007800F80
+07800F8007800F8007800F8007800F0007801E0007801C000780780007FFE00007800000078000
+000780000007800000078000000780000007800000078000000780000007800000078000000780
+0000078000000FC00000FFFC0000191F7E9E1F>I<001F800000F0F00001C0380007801E000F00
+0F000E0007001E0007803C0003C03C0003C07C0003E07C0003E0780001E0F80001F0F80001F0F8
+0001F0F80001F0F80001F0F80001F0F80001F0F80001F0F80001F0780001E0780001E07C0003E0
+3C0003C03C0F03C01E1087800E2047000F204F0007A03E0001E0380000F0F010001FB010000030
+10000038300000387000003FF000001FE000001FE000000FC0000007801C297D9F23>I<FFFF80
+000F80F0000780780007803C0007801E0007801E0007801F0007801F0007801F0007801F000780
+1E0007801E0007803C00078078000780F00007FF80000781C0000780E0000780F0000780700007
+807800078078000780780007807C0007807C0007807C0007807C0407807E0407803E040FC01E08
+FFFC0F10000003E01E207E9E21>I<07E0800C1980100780300380600180600180E00180E00080
+E00080E00080F00000F000007800007F00003FF0001FFC000FFE0003FF00001F800007800003C0
+0003C00001C08001C08001C08001C08001C0C00180C00380E00300F00600CE0C0081F80012217D
+9F19>I<7FFFFFE0780F01E0600F0060400F0020400F0020C00F0030800F0010800F0010800F00
+10800F0010000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F
+0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F000000
+0F0000001F800007FFFE001C1F7E9E21>I<FFFC3FF80FC007C007800380078001000780010007
+800100078001000780010007800100078001000780010007800100078001000780010007800100
+078001000780010007800100078001000780010007800100078001000780010007800100038002
+000380020001C0020001C0040000E008000070180000382000000FC0001D207E9E22>I<FFF003
+FE1F8000F80F0000600F800060078000400780004003C0008003C0008003C0008001E0010001E0
+010001F0010000F0020000F0020000F806000078040000780400003C0800003C0800003C080000
+1E1000001E1000001F3000000F2000000F20000007C0000007C0000007C0000003800000038000
+00038000000100001F207F9E22>I<FFF07FF81FF01F800FC007C00F00078003800F0007800100
+0F0007C00100078007C00200078007C00200078007C0020003C009E0040003C009E0040003C009
+E0040003E010F00C0001E010F0080001E010F0080001F02078080000F02078100000F020781000
+00F0403C10000078403C20000078403C20000078C03E2000003C801E4000003C801E4000003C80
+1E4000001F000F8000001F000F8000001F000F8000001E00078000000E00070000000E00070000
+000C000300000004000200002C207F9E2F>I<FEFEC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0
+C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0FEFE072D7CA10D>91
+D<080410082010201040204020804080408040B85CFC7EFC7E7C3E381C0F0E7B9F17>I<FEFE06
+060606060606060606060606060606060606060606060606060606060606060606060606060606
+06FEFE072D7FA10D>I<081020204040808080B8FCFC7C38060E7D9F0D>96
+D<1FE000303000781800781C00300E00000E00000E00000E0000FE00078E001E0E00380E00780E
+00F00E10F00E10F00E10F01E10781E103867200F83C014147E9317>I<0E0000FE00000E00000E
+00000E00000E00000E00000E00000E00000E00000E00000E00000E3E000EC3800F01C00F00E00E
+00E00E00700E00700E00780E00780E00780E00780E00780E00780E00700E00700E00E00F00E00D
+01C00CC300083E0015207F9F19>I<03F80E0C1C1E381E380C70007000F000F000F000F000F000
+F00070007000380138011C020E0C03F010147E9314>I<000380003F8000038000038000038000
+038000038000038000038000038000038000038003E380061B801C078038038038038070038070
+0380F00380F00380F00380F00380F00380F003807003807003803803803807801C07800E1B8003
+E3F815207E9F19>I<03F0000E1C001C0E00380700380700700700700380F00380F00380FFFF80
+F00000F00000F000007000007000003800801800800C010007060001F80011147F9314>I<007C
+00C6018F038F07060700070007000700070007000700FFF0070007000700070007000700070007
+0007000700070007000700070007000700070007007FF01020809F0E>I<0000E003E3300E3C30
+1C1C30380E00780F00780F00780F00780F00780F00380E001C1C001E380033E000200000200000
+3000003000003FFE001FFF800FFFC03001E0600070C00030C00030C00030C000306000603000C0
+1C038003FC00141F7F9417>I<0E0000FE00000E00000E00000E00000E00000E00000E00000E00
+000E00000E00000E00000E3E000E43000E81800F01C00F01C00E01C00E01C00E01C00E01C00E01
+C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C0FFE7FC16207F9F19>I<1C
+003E003E003E001C000000000000000000000000000E007E000E000E000E000E000E000E000E00
+0E000E000E000E000E000E000E000E000E000E00FFC00A1F809E0C>I<00E001F001F001F000E0
+000000000000000000000000007007F000F0007000700070007000700070007000700070007000
+7000700070007000700070007000700070007000706070F060F0C061803F000C28829E0E>I<0E
+0000FE00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E0FF00E
+03C00E03000E02000E04000E08000E10000E30000E70000EF8000F38000E1C000E1E000E0E000E
+07000E07800E03800E03C00E03E0FFCFF815207F9F18>I<0E00FE000E000E000E000E000E000E
+000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E00
+0E000E000E000E00FFE00B20809F0C>I<0E1F01F000FE618618000E81C81C000F00F00E000F00
+F00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E
+00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E00FFE7FE7FE0
+23147F9326>I<0E3E00FE43000E81800F01C00F01C00E01C00E01C00E01C00E01C00E01C00E01
+C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C0FFE7FC16147F9319>I<01F80007
+0E001C03803801C03801C07000E07000E0F000F0F000F0F000F0F000F0F000F0F000F07000E070
+00E03801C03801C01C0380070E0001F80014147F9317>I<0E3E00FEC3800F01C00F00E00E00E0
+0E00F00E00700E00780E00780E00780E00780E00780E00780E00700E00F00E00E00F01E00F01C0
+0EC3000E3E000E00000E00000E00000E00000E00000E00000E00000E0000FFE000151D7F9319>
+I<03E0800619801C05803C0780380380780380700380F00380F00380F00380F00380F00380F003
+807003807803803803803807801C0B800E138003E3800003800003800003800003800003800003
+80000380000380003FF8151D7E9318>I<0E78FE8C0F1E0F1E0F0C0E000E000E000E000E000E00
+0E000E000E000E000E000E000E000E00FFE00F147F9312>I<1F9030704030C010C010C010E000
+78007F803FE00FF00070803880188018C018C018E030D0608F800D147E9312>I<020002000200
+060006000E000E003E00FFF80E000E000E000E000E000E000E000E000E000E000E000E080E080E
+080E080E080610031001E00D1C7F9B12>I<0E01C0FE1FC00E01C00E01C00E01C00E01C00E01C0
+0E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E03C00603C0030DC001F1FC
+16147F9319>I<FF83F81E01E01C00C00E00800E00800E00800701000701000382000382000382
+0001C40001C40001EC0000E80000E80000700000700000700000200015147F9318>I<FF9FE1FC
+3C0780701C0300601C0380200E0380400E0380400E03C0400707C0800704C0800704E080038861
+000388710003C8730001D0320001D03A0000F03C0000E01C0000E01C0000601800004008001E14
+7F9321>I<7FC3FC0F01E00701C007018003810001C20000E40000EC00007800003800003C0000
+7C00004E000087000107000303800201C00601E01E01E0FF07FE1714809318>I<FF83F81E01E0
+1C00C00E00800E00800E008007010007010003820003820003820001C40001C40001EC0000E800
+00E800007000007000007000002000002000004000004000004000F08000F08000F10000620000
+3C0000151D7F9318>I<3FFF380E200E201C40384078407000E001E001C00380078007010E011E
+011C0338027006700EFFFE10147F9314>I E /Fp 13 122 df<0000001FFC0000C000000003FF
+FFC001C00000001FFFFFF003C00000007FFFFFFC07C0000001FFFC00FE0FC0000007FFC0001F9F
+C000000FFE000007FFC000003FF8000003FFC000007FF0000000FFC00000FFE00000007FC00001
+FFC00000007FC00001FF800000003FC00003FF000000001FC00007FE000000001FC0000FFE0000
+00000FC0000FFC000000000FC0001FFC0000000007C0001FFC0000000007C0003FF80000000007
+C0003FF80000000003C0003FF80000000003C0007FF80000000003C0007FF80000000003C0007F
+F0000000000000007FF000000000000000FFF000000000000000FFF000000000000000FFF00000
+0000000000FFF000000000000000FFF000000000000000FFF000000000000000FFF00000000000
+0000FFF000000000000000FFF000000000000000FFF000000000000000FFF000001FFFFFFF807F
+F000001FFFFFFF807FF000001FFFFFFF807FF800001FFFFFFF807FF800000001FFC0003FF80000
+0001FFC0003FF800000001FFC0003FF800000001FFC0001FFC00000001FFC0001FFC00000001FF
+C0000FFE00000001FFC0000FFE00000001FFC00007FF00000001FFC00003FF00000001FFC00001
+FF80000001FFC00001FFC0000001FFC00000FFE0000001FFC000007FF0000003FFC000003FFC00
+0003FFC000000FFF000007FFC0000007FFC0001FBFC0000001FFFC00FF1FC00000007FFFFFFE0F
+C00000001FFFFFF803C000000003FFFFE000C0000000001FFE00000000413D7BBB4C>71
+D<FFFFFFF803FFFFFFE0FFFFFFF803FFFFFFE0FFFFFFF803FFFFFFE0FFFFFFF803FFFFFFE0007F
+F0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF00000
+01FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC0
+00007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007F
+F0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF00000
+01FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC0
+00007FFFFFFFFFFFC000007FFFFFFFFFFFC000007FFFFFFFFFFFC000007FFFFFFFFFFFC000007F
+F0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF00000
+01FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC0
+00007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007F
+F0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF00000
+01FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC0
+00007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000FFFFFFF803FFFFFFE0FFFF
+FFF803FFFFFFE0FFFFFFF803FFFFFFE0FFFFFFF803FFFFFFE0433B7CBA4C>I<FFFFFFFE000000
+FFFFFFFE000000FFFFFFFE000000FFFFFFFE000000007FF000000000007FF000000000007FF000
+000000007FF000000000007FF000000000007FF000000000007FF000000000007FF00000000000
+7FF000000000007FF000000000007FF000000000007FF000000000007FF000000000007FF00000
+0000007FF000000000007FF000000000007FF000000000007FF000000000007FF000000000007F
+F000000000007FF000000000007FF000000000007FF000000000007FF000000000007FF0000000
+00007FF000000000007FF000000000007FF000000000007FF000000000007FF000000000007FF0
+00000000007FF000000780007FF000000780007FF000000780007FF000000780007FF000000780
+007FF000000F80007FF000000F00007FF000000F00007FF000000F00007FF000001F00007FF000
+001F00007FF000001F00007FF000003F00007FF000003F00007FF000007F00007FF00000FF0000
+7FF00001FF00007FF00003FF00007FF0000FFE00007FF0007FFE00FFFFFFFFFFFE00FFFFFFFFFF
+FE00FFFFFFFFFFFE00FFFFFFFFFFFE00313B7CBA3A>76 D<FFFFF0000007FFFFE0FFFFF8000007
+FFFFE0FFFFFC000007FFFFE0FFFFFE000007FFFFE0007FFE00000007E000007FFF00000003C000
+007FFF80000003C000007BFFC0000003C000007BFFE0000003C0000079FFE0000003C0000078FF
+F0000003C00000787FF8000003C00000783FFC000003C00000783FFE000003C00000781FFE0000
+03C00000780FFF000003C000007807FF800003C000007803FFC00003C000007803FFE00003C000
+007801FFE00003C000007800FFF00003C0000078007FF80003C0000078003FFC0003C000007800
+3FFE0003C0000078001FFF0003C0000078000FFF0003C00000780007FF8003C00000780003FFC0
+03C00000780003FFE003C00000780001FFF003C00000780000FFF003C000007800007FF803C000
+007800003FFC03C000007800003FFE03C000007800001FFF03C000007800000FFF03C000007800
+0007FF83C0000078000003FFC3C0000078000003FFE3C0000078000001FFF3C0000078000000FF
+F3C00000780000007FFBC00000780000003FFFC00000780000003FFFC00000780000001FFFC000
+00780000000FFFC000007800000007FFC000007800000003FFC000007800000003FFC000007800
+000001FFC000007800000000FFC0000078000000007FC0000078000000003FC000007800000000
+3FC00000FC000000001FC000FFFFFC0000000FC000FFFFFC00000007C000FFFFFC00000003C000
+FFFFFC00000003C000433B7CBA4C>78 D<FFFFFFF8001FFFFF80FFFFFFF8001FFFFF80FFFFFFF8
+001FFFFF80FFFFFFF8001FFFFF80007FF00000001F8000007FF00000000F0000007FF00000000F
+0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F000000
+7FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF000
+00000F0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F
+0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F000000
+7FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF000
+00000F0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F
+0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F000000
+7FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF000
+00000F0000007FF00000000F0000007FF00000000F0000003FF00000001E0000003FF00000001E
+0000003FF80000001E0000001FF80000003C0000001FF80000003C0000000FFC00000078000000
+07FC000000F800000007FE000001F000000003FF000003F000000001FF800007E000000000FFE0
+001FC0000000003FFC01FF80000000001FFFFFFE000000000007FFFFF8000000000000FFFFE000
+00000000000FFE00000000413C7CBA4A>85 D<003FFE00000001FFFFE0000007FFFFF800000FE0
+07FC00000FF001FE00001FF800FF00001FF8007F80001FF8007FC0001FF8003FC0000FF0003FE0
+0007E0003FE00003C0003FE0000000003FE0000000003FE0000000003FE0000000003FE0000000
+FFFFE000001FFFFFE000007FF83FE00003FF803FE00007FC003FE0000FF0003FE0001FE0003FE0
+003FE0003FE0007FC0003FE0007FC0003FE000FF80003FE000FF80003FE000FF80003FE000FF80
+003FE000FF80007FE0007FC0007FE0007FC000DFE0003FE0039FF0001FF80F0FFFE007FFFE0FFF
+E001FFF807FFE0003FE000FFE02B267DA52F>97 D<00FE00000000FFFE00000000FFFE00000000
+FFFE00000000FFFE0000000007FE0000000003FE0000000003FE0000000003FE0000000003FE00
+00000003FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE00000000
+03FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE01
+FF000003FE1FFFF00003FE7FFFFC0003FEFC03FE0003FFF000FF0003FFC0003F8003FF00001FC0
+03FE00001FE003FE00000FF003FE00000FF803FE00000FF803FE000007FC03FE000007FC03FE00
+0007FC03FE000007FE03FE000007FE03FE000007FE03FE000007FE03FE000007FE03FE000007FE
+03FE000007FE03FE000007FE03FE000007FE03FE000007FC03FE000007FC03FE000007FC03FE00
+000FFC03FE00000FF803FE00000FF003FE00001FF003FF00001FE003FF80003FC003FFC0007F80
+03F9E000FF0003F0FC07FE0003F07FFFF80003E01FFFE00003C003FE00002F3C7DBB36>I<01E0
+0007F8000FFC000FFC001FFE001FFE001FFE001FFE000FFC000FFC0007F80001E0000000000000
+0000000000000000000000000000000000000000000000000000000000FE00FFFE00FFFE00FFFE
+00FFFE0007FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE
+0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE
+0003FE0003FE0003FE0003FE00FFFFF0FFFFF0FFFFF0FFFFF0143D7DBC1A>105
+D<0001FFC00000000FFFF80000007FFFFF000000FF80FF800003FE003FE00007F8000FF0000FF0
+0007F8000FF00007F8001FE00003FC003FE00003FE003FE00003FE007FC00001FF007FC00001FF
+007FC00001FF007FC00001FF00FFC00001FF80FFC00001FF80FFC00001FF80FFC00001FF80FFC0
+0001FF80FFC00001FF80FFC00001FF80FFC00001FF80FFC00001FF807FC00001FF007FC00001FF
+007FC00001FF003FE00003FE003FE00003FE001FE00003FC001FF00007FC000FF00007F80007F8
+000FF00003FE003FE00000FF80FF8000007FFFFF0000000FFFF800000001FFC0000029267DA530
+>111 D<01FC03F000FFFC0FFC00FFFC1FFF00FFFC3C3F80FFFC707F8007FCE0FFC003FCC0FFC0
+03FD80FFC003FD80FFC003FF807F8003FF003F0003FF001E0003FF00000003FE00000003FE0000
+0003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00
+000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE
+00000003FE00000003FE00000003FE000000FFFFFC0000FFFFFC0000FFFFFC0000FFFFFC000022
+267DA528>114 D<003FF07003FFFEF007FFFFF01FC01FF03F0003F03E0001F07C0001F07C0000
+F0FC0000F0FC0000F0FE0000F0FF000000FFC00000FFFC00007FFFF0003FFFFE003FFFFF801FFF
+FFC00FFFFFE003FFFFF000FFFFF8001FFFFC00007FFC000007FE700001FEF00000FEF000007EF8
+00007EF800007EFC00007EFC00007CFE0000FCFF0000F8FF8001F0FFF00FE0F9FFFFC0F07FFF00
+C01FF8001F267DA526>I<000F0000000F0000000F0000000F0000000F0000001F0000001F0000
+001F0000001F0000003F0000003F0000007F0000007F000000FF000001FF000003FF000007FF00
+001FFFFFF0FFFFFFF0FFFFFFF0FFFFFFF001FF000001FF000001FF000001FF000001FF000001FF
+000001FF000001FF000001FF000001FF000001FF000001FF000001FF000001FF000001FF000001
+FF000001FF000001FF000001FF000001FF003C01FF003C01FF003C01FF003C01FF003C01FF003C
+01FF003C01FF003C00FF007800FF8078007F80F0003FC1E0001FFFC0000FFF800001FE001E377E
+B626>I<FFFFF001FFFCFFFFF001FFFCFFFFF001FFFCFFFFF001FFFC03FE00001F8003FF00001F
+0001FF00001E0001FF80003E0000FF80003C0000FF80003C00007FC0007800007FC0007800007F
+E000F800003FE000F000003FF001F000001FF001E000001FF803E000000FF803C000000FFC03C0
+000007FC0780000007FC0780000007FE0F80000003FE0F00000003FF1F00000001FF1E00000001
+FFBE00000000FFBC00000000FFFC000000007FF8000000007FF8000000007FF8000000003FF000
+0000003FF0000000001FE0000000001FE0000000000FC0000000000FC000000000078000000000
+0780000000000F80000000000F00000000001F00000000001E00000008003E0000007F003C0000
+007F007C000000FF8078000000FF80F8000000FF80F0000000FF81E00000007F07C00000007C1F
+800000003FFF000000001FFE0000000007F0000000002E377EA533>121
+D E end
+%%EndProlog
+%%BeginSetup
+%%Feature: *Resolution 300dpi
+TeXDict begin
+
+%%EndSetup
+%%Page: 1 1
+0 bop 0 1152 a Fp(GNU)33 b(History)f(Library)p 0 1201 1950
+17 v 1035 1250 a Fo(Edition)16 b(2.0,)e(for)h Fn(History)f(Library)g
+Fo(V)l(ersion)i(2.0.)1759 1304 y(July)g(1994)0 2443 y Fm(Brian)23
+b(F)-6 b(o)n(x,)23 b(F)-6 b(ree)23 b(Soft)n(w)n(are)f(F)-6
+b(oundation)0 2509 y(Chet)22 b(Ramey)-6 b(,)23 b(Case)e(W)-6
+b(estern)23 b(Reserv)n(e)f(Univ)n(ersit)n(y)p 0 2545 1950 9
+v eop
+%%Page: 2 2
+1 bop 0 295 a Fo(This)16 b(do)q(cumen)o(t)g(describ)q(es)h(the)f(GNU)f
+(History)g(library)l(,)h(a)g(programming)e(to)q(ol)i(that)f(pro)o(vides)h(a)f
+(consisten)o(t)0 358 y(user)g(in)o(terface)h(for)e(recalling)j(lines)g(of)e
+(previously)h(t)o(yp)q(ed)g(input.)0 495 y(Published)h(b)o(y)f(the)f(F)l(ree)
+g(Soft)o(w)o(are)f(F)l(oundation)0 557 y(675)g(Massac)o(h)o(usetts)g(Av)o(en)
+o(ue,)0 619 y(Cam)o(bridge,)h(MA)g(02139)f(USA)0 756 y(P)o(ermission)f(is)g
+(gran)o(ted)f(to)f(mak)o(e)h(and)h(distribute)h(v)o(erbatim)e(copies)h(of)f
+(this)h(man)o(ual)g(pro)o(vided)g(the)f(cop)o(yrigh)o(t)0 818
+y(notice)k(and)f(this)h(p)q(ermission)h(notice)e(are)g(preserv)o(ed)h(on)f
+(all)h(copies.)0 955 y(P)o(ermission)f(is)f(gran)o(ted)f(to)h(cop)o(y)g(and)g
+(distribute)h(mo)q(di\014ed)h(v)o(ersions)e(of)f(this)i(man)o(ual)f(under)h
+(the)f(conditions)0 1018 y(for)e(v)o(erbatim)g(cop)o(ying,)h(pro)o(vided)h
+(that)d(the)i(en)o(tire)g(resulting)h(deriv)o(ed)f(w)o(ork)f(is)h
+(distributed)h(under)f(the)g(terms)0 1080 y(of)i(a)g(p)q(ermission)h(notice)g
+(iden)o(tical)h(to)e(this)g(one.)0 1217 y(P)o(ermission)20
+b(is)g(gran)o(ted)f(to)g(cop)o(y)h(and)f(distribute)i(translations)f(of)f
+(this)h(man)o(ual)f(in)o(to)h(another)f(language,)0 1279 y(under)c(the)f(ab)q
+(o)o(v)o(e)g(conditions)h(for)e(mo)q(di\014ed)j(v)o(ersions,)e(except)g(that)
+g(this)g(p)q(ermission)i(notice)e(ma)o(y)g(b)q(e)h(stated)0
+1341 y(in)h(a)f(translation)g(appro)o(v)o(ed)g(b)o(y)g(the)g(F)l(oundation.)0
+2636 y(Cop)o(yrigh)o(t)226 2635 y(c)214 2636 y Fl(\015)g Fo(1989,)f(1991)g(F)
+l(ree)h(Soft)o(w)o(are)f(F)l(oundation,)h(Inc.)p eop
+%%Page: 1 3
+2 bop 0 -83 a Fo(Chapter)15 b(1:)k(Using)d(History)f(In)o(teractiv)o(ely)1157
+b(1)0 158 y Fk(1)41 b(Using)14 b(History)h(In)n(teractiv)n(ely)62
+330 y Fo(This)i(c)o(hapter)e(describ)q(es)j(ho)o(w)d(to)h(use)g(the)g(GNU)g
+(History)f(Library)i(in)o(teractiv)o(ely)l(,)g(from)e(a)g(user's)h(stand-)0
+392 y(p)q(oin)o(t.)23 b(It)16 b(should)h(b)q(e)f(considered)i(a)d(user's)h
+(guide.)23 b(F)l(or)15 b(information)h(on)g(using)h(the)f(GNU)g(History)f
+(Library)0 454 y(in)h(y)o(our)f(o)o(wn)f(programs,)g(see)i(Chapter)e(2)h
+([Programming)f(with)i(GNU)f(History],)f(page)h(5.)0 663 y
+Fm(1.1)33 b(History)15 b(In)n(teraction)62 800 y Fo(The)j(History)g(library)g
+(pro)o(vides)h(a)e(history)h(expansion)h(feature)e(that)g(is)i(similar)g(to)e
+(the)h(history)f(expan-)0 862 y(sion)k(pro)o(vided)h(b)o(y)f
+Fn(csh)p Fo(.)36 b(The)22 b(follo)o(wing)f(text)g(describ)q(es)h(the)f(syn)o
+(tax)f(used)i(to)e(manipulate)i(the)f(history)0 924 y(information.)62
+1061 y(History)11 b(expansion)i(tak)o(es)d(place)i(in)h(t)o(w)o(o)d(parts.)18
+b(The)11 b(\014rst)g(is)h(to)f(determine)h(whic)o(h)g(line)h(from)e(the)g
+(previous)0 1124 y(history)h(should)h(b)q(e)f(used)h(during)f(substitution.)
+20 b(The)12 b(second)g(is)h(to)e(select)h(p)q(ortions)g(of)g(that)f(line)i
+(for)f(inclusion)0 1186 y(in)o(to)f(the)h(curren)o(t)f(one.)18
+b(The)12 b(line)h(selected)f(from)f(the)g(previous)h(history)g(is)f(called)i
+(the)e Fj(ev)o(en)o(t)p Fo(,)h(and)f(the)h(p)q(ortions)0 1248
+y(of)h(that)g(line)i(that)e(are)g(acted)g(up)q(on)h(are)g(called)h
+Fj(w)o(ords)p Fo(.)j(The)c(line)h(is)f(brok)o(en)f(in)o(to)h(w)o(ords)f(in)h
+(the)f(same)h(fashion)0 1310 y(that)j(Bash)h(do)q(es,)h(so)e(that)g(sev)o
+(eral)h(English)i(\(or)d(Unix\))h(w)o(ords)f(surrounded)i(b)o(y)f(quotes)f
+(are)h(considered)h(as)0 1373 y(one)c(w)o(ord.)0 1565 y Fi(1.1.1)30
+b(Ev)n(en)n(t)16 b(Designators)62 1702 y Fo(An)g(ev)o(en)o(t)f(designator)g
+(is)g(a)g(reference)h(to)f(a)g(command)g(line)i(en)o(try)d(in)i(the)g
+(history)f(list.)0 1847 y Fn(!)216 b Fo(Start)14 b(a)g(history)h
+(substitution,)g(except)h(when)f(follo)o(w)o(ed)g(b)o(y)g(a)f(space,)h(tab,)f
+(the)h(end)g(of)g(the)g(line,)240 1909 y Fn(=)g Fo(or)g Fn(\()p
+Fo(.)0 1989 y Fn(!!)192 b Fo(Refer)16 b(to)e(the)i(previous)f(command.)20
+b(This)c(is)g(a)f(synon)o(ym)g(for)f Fn(!-1)p Fo(.)0 2068 y
+Fn(!n)192 b Fo(Refer)16 b(to)e(command)h(line)i Fj(n)p Fo(.)0
+2148 y Fn(!-n)168 b Fo(Refer)16 b(to)e(the)i(command)f Fj(n)g
+Fo(lines)i(bac)o(k.)0 2227 y Fn(!string)72 b Fo(Refer)16 b(to)e(the)i(most)e
+(recen)o(t)h(command)g(starting)g(with)g Fj(string)p Fo(.)0
+2298 y Fn(!?string)p Fo([)p Fn(?)p Fo(])240 2360 y(Refer)h(to)e(the)i(most)e
+(recen)o(t)h(command)g(con)o(taining)h Fj(string)p Fo(.)0 2440
+y Fn(!#)192 b Fo(The)15 b(en)o(tire)h(command)f(line)i(t)o(yp)q(ed)f(so)e
+(far.)0 2510 y Fn(^string1^string2^)240 2573 y Fo(Quic)o(k)j(Substitution.)22
+b(Rep)q(eat)16 b(the)g(last)f(command,)h(replacing)h Fj(string1)h
+Fo(with)e Fj(string2)p Fo(.)21 b(Equiv-)240 2635 y(alen)o(t)15
+b(to)g Fn(!!:s/string1/string2/)p Fo(.)p eop
+%%Page: 2 4
+3 bop 0 -83 a Fo(2)1497 b(GNU)15 b(History)g(Library)0 158
+y Fi(1.1.2)30 b(W)-5 b(ord)15 b(Designators)62 295 y Fo(A)i
+Fn(:)g Fo(separates)f(the)h(ev)o(en)o(t)f(sp)q(eci\014cation)j(from)d(the)g
+(w)o(ord)g(designator.)25 b(It)17 b(can)g(b)q(e)g(omitted)g(if)g(the)g(w)o
+(ord)0 358 y(designator)d(b)q(egins)h(with)f(a)f Fn(^)p Fo(,)h
+Fn($)p Fo(,)f Fn(*)h Fo(or)f Fn(\045)p Fo(.)20 b(W)l(ords)13
+b(are)h(n)o(um)o(b)q(ered)g(from)f(the)h(b)q(eginning)i(of)d(the)h(line,)i
+(with)e(the)0 420 y(\014rst)h(w)o(ord)f(b)q(eing)j(denoted)f(b)o(y)f(a)g(0)f
+(\(zero\).)0 569 y Fn(0)h(\(zero\))57 b Fo(The)15 b Fn(0)p
+Fo(th)g(w)o(ord.)20 b(F)l(or)14 b(man)o(y)h(applications,)h(this)g(is)g(the)f
+(command)g(w)o(ord.)0 656 y Fn(n)216 b Fo(The)15 b Fj(n)p Fo(th)h(w)o(ord.)0
+744 y Fn(^)216 b Fo(The)15 b(\014rst)g(argumen)o(t;)f(that)h(is,)g(w)o(ord)g
+(1.)0 831 y Fn($)216 b Fo(The)15 b(last)h(argumen)o(t.)0 918
+y Fn(\045)216 b Fo(The)15 b(w)o(ord)g(matc)o(hed)g(b)o(y)g(the)g(most)g
+(recen)o(t)g Fn(?string?)f Fo(searc)o(h.)0 1005 y Fn(x-y)168
+b Fo(A)15 b(range)g(of)g(w)o(ords;)f Fn(-)p Fj(y)19 b Fo(abbreviates)c
+Fn(0-)p Fj(y)t Fo(.)0 1092 y Fn(*)216 b Fo(All)17 b(of)f(the)g(w)o(ords,)f
+(except)i(the)f Fn(0)p Fo(th.)22 b(This)17 b(is)f(a)g(synon)o(ym)g(for)f
+Fn(1-$)p Fo(.)22 b(It)17 b(is)f(not)g(an)g(error)f(to)h(use)240
+1155 y Fn(*)f Fo(if)h(there)f(is)h(just)f(one)g(w)o(ord)f(in)i(the)g(ev)o(en)
+o(t;)e(the)i(empt)o(y)e(string)i(is)f(returned)h(in)g(that)e(case.)0
+1242 y Fn(x*)192 b Fo(Abbreviates)16 b Fn(x-$)0 1329 y(x-)192
+b Fo(Abbreviates)16 b Fn(x-$)f Fo(lik)o(e)h Fn(x*)p Fo(,)e(but)i(omits)f(the)
+g(last)g(w)o(ord.)0 1537 y Fi(1.1.3)30 b(Mo)r(di\014ers)62
+1674 y Fo(After)20 b(the)f(optional)i(w)o(ord)e(designator,)h(y)o(ou)f(can)h
+(add)g(a)g(sequence)h(of)e(one)h(or)f(more)g(of)g(the)h(follo)o(wing)0
+1736 y(mo)q(di\014ers,)c(eac)o(h)f(preceded)i(b)o(y)e(a)g Fn(:)p
+Fo(.)0 1885 y Fn(h)216 b Fo(Remo)o(v)o(e)15 b(a)g(trailing)h(pathname)f(comp)
+q(onen)o(t,)g(lea)o(ving)h(only)g(the)f(head.)0 1973 y Fn(r)216
+b Fo(Remo)o(v)o(e)15 b(a)g(trailing)h(su\016x)f(of)g(the)g(form)g(`)p
+Fn(.)p Fo(')p Fj(su\016x)p Fo(,)f(lea)o(ving)i(the)f(basename.)0
+2060 y Fn(e)216 b Fo(Remo)o(v)o(e)15 b(all)h(but)g(the)f(trailing)h(su\016x.)
+0 2147 y Fn(t)216 b Fo(Remo)o(v)o(e)15 b(all)h(leading)h(pathname)e(comp)q
+(onen)o(ts,)g(lea)o(ving)h(the)f(tail.)0 2234 y Fn(p)216 b
+Fo(Prin)o(t)15 b(the)g(new)h(command)f(but)g(do)g(not)g(execute)h(it.)0
+2309 y Fn(s/old/new/)240 2371 y Fo(Substitute)g Fj(new)k Fo(for)15
+b(the)h(\014rst)f(o)q(ccurrence)h(of)g Fj(old)h Fo(in)g(the)e(ev)o(en)o(t)h
+(line.)22 b(An)o(y)16 b(delimiter)h(ma)o(y)e(b)q(e)240 2433
+y(used)e(in)f(place)h(of)f Fn(/)p Fo(.)19 b(The)12 b(delimiter)i(ma)o(y)d(b)q
+(e)i(quoted)f(in)h Fj(old)h Fo(and)e Fj(new)17 b Fo(with)12
+b(a)g(single)h(bac)o(kslash.)240 2496 y(If)g Fn(&)h Fo(app)q(ears)f(in)h
+Fj(new)p Fo(,)f(it)h(is)g(replaced)g(b)o(y)f Fj(old)p Fo(.)20
+b(A)13 b(single)i(bac)o(kslash)e(will)i(quote)e(the)h Fn(&)p
+Fo(.)19 b(The)13 b(\014nal)240 2558 y(delimiter)k(is)f(optional)g(if)f(it)h
+(is)f(the)h(last)f(c)o(haracter)f(on)h(the)h(input)g(line.)0
+2645 y Fn(&)216 b Fo(Rep)q(eat)16 b(the)f(previous)h(substitution.)p
+eop
+%%Page: 3 5
+4 bop 0 -83 a Fo(Chapter)15 b(1:)k(Using)d(History)f(In)o(teractiv)o(ely)1157
+b(3)0 158 y Fn(g)216 b Fo(Cause)15 b(c)o(hanges)g(to)f(b)q(e)i(applied)h(o)o
+(v)o(er)d(the)h(en)o(tire)g(ev)o(en)o(t)g(line.)21 b(Used)16
+b(in)g(conjunction)g(with)f Fn(s)p Fo(,)f(as)240 221 y(in)i
+Fn(gs/old/new/)p Fo(,)d(or)i(with)h Fn(&)p Fo(.)p eop
+%%Page: 4 6
+5 bop 0 -83 a Fo(4)1497 b(GNU)15 b(History)g(Library)p eop
+%%Page: 5 7
+6 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1039
+b(5)0 158 y Fk(2)41 b(Programming)16 b(with)f(GNU)h(History)62
+347 y Fo(This)e(c)o(hapter)f(describ)q(es)i(ho)o(w)d(to)h(in)o(terface)g
+(programs)f(that)h(y)o(ou)g(write)g(with)g(the)h(GNU)f(History)g(Library)l(.)
+0 409 y(It)j(should)g(b)q(e)g(considered)h(a)f(tec)o(hnical)h(guide.)22
+b(F)l(or)15 b(information)h(on)f(the)h(in)o(teractiv)o(e)g(use)g(of)f(GNU)g
+(History)l(,)0 471 y(see)g(Chapter)g(1)g([Using)h(History)f(In)o(teractiv)o
+(ely],)g(page)g(1.)0 698 y Fm(2.1)33 b(In)n(tro)r(duction)17
+b(to)e(History)62 835 y Fo(Man)o(y)j(programs)g(read)h(input)h(from)e(the)g
+(user)h(a)g(line)h(at)f(a)f(time.)31 b(The)19 b(GNU)g(History)f(library)i(is)
+f(able)0 897 y(to)e(k)o(eep)g(trac)o(k)f(of)h(those)g(lines,)i(asso)q(ciate)e
+(arbitrary)g(data)g(with)g(eac)o(h)g(line,)j(and)d(utilize)i(information)f
+(from)0 960 y(previous)e(lines)h(in)f(comp)q(osing)f(new)h(ones.)62
+1097 y(The)i(programmer)f(using)h(the)g(History)g(library)g(has)g(a)o(v)m
+(ailable)h(functions)g(for)e(remem)o(b)q(ering)h(lines)i(on)d(a)0
+1159 y(history)f(list,)g(asso)q(ciating)g(arbitrary)g(data)f(with)h(a)f
+(line,)j(remo)o(ving)d(lines)j(from)d(the)h(list,)g(searc)o(hing)g(through)0
+1221 y(the)h(list)h(for)e(a)h(line)h(con)o(taining)g(an)f(arbitrary)f(text)h
+(string,)g(and)g(referencing)h(an)o(y)f(line)h(in)g(the)f(list)h(directly)l
+(.)0 1284 y(In)d(addition,)h(a)e(history)h Fj(expansion)h Fo(function)g(is)f
+(a)o(v)m(ailable)h(whic)o(h)g(pro)o(vides)f(for)f(a)h(consisten)o(t)g(user)g
+(in)o(terface)0 1346 y(across)f(di\013eren)o(t)i(programs.)62
+1483 y(The)i(user)g(using)g(programs)f(written)g(with)h(the)g(History)f
+(library)i(has)e(the)h(b)q(ene\014t)h(of)e(a)g(consisten)o(t)h(user)0
+1545 y(in)o(terface)d(with)g(a)f(set)h(of)f(w)o(ell-kno)o(wn)h(commands)g
+(for)f(manipulating)i(the)f(text)f(of)g(previous)h(lines)h(and)f(using)0
+1608 y(that)g(text)g(in)i(new)e(commands.)22 b(The)15 b(basic)i(history)e
+(manipulation)j(commands)d(are)g(similar)i(to)e(the)h(history)0
+1670 y(substitution)g(pro)o(vided)g(b)o(y)f Fn(csh)p Fo(.)62
+1807 y(If)g(the)g(programmer)e(desires,)i(he)g(can)g(use)g(the)f(Readline)j
+(library)l(,)e(whic)o(h)h(includes)g(some)f(history)f(manip-)0
+1870 y(ulation)i(b)o(y)f(default,)h(and)f(has)g(the)g(added)h(adv)m(an)o
+(tage)f(of)g(command)g(line)h(editing.)0 2096 y Fm(2.2)33 b(History)15
+b(Storage)62 2234 y Fo(The)h(history)f(list)h(is)g(an)f(arra)o(y)f(of)g
+(history)i(en)o(tries.)k(A)15 b(history)g(en)o(try)g(is)h(declared)g(as)f
+(follo)o(ws:)120 2358 y Fn(typedef)23 b(struct)g(_hist_entry)f({)168
+2408 y(char)h(*line;)168 2458 y(char)g(*data;)120 2508 y(})h(HIST_ENTRY;)62
+2645 y Fo(The)16 b(history)f(list)h(itself)g(migh)o(t)f(therefore)g(b)q(e)h
+(declared)g(as)p eop
+%%Page: 6 8
+7 bop 0 -83 a Fo(6)1497 b(GNU)15 b(History)g(Library)120 158
+y Fn(HIST_ENTRY)22 b(**the_history_list;)62 302 y Fo(The)16
+b(state)e(of)h(the)g(History)g(library)h(is)g(encapsulated)g(in)o(to)f(a)g
+(single)i(structure:)120 434 y Fn(/*)24 b(A)f(structure)g(used)g(to)h(pass)f
+(the)h(current)f(state)g(of)g(the)h(history)f(stuff)g(around.)g(*/)120
+484 y(typedef)g(struct)g(_hist_state)f({)168 534 y(HIST_ENTRY)g(**entries;)
+214 b(/*)23 b(Pointer)g(to)h(the)f(entries)g(themselves.)f(*/)168
+584 y(int)h(offset;)453 b(/*)23 b(The)h(location)e(pointer)h(within)g(this)h
+(array.)f(*/)168 633 y(int)g(length;)453 b(/*)23 b(Number)g(of)h(elements)f
+(within)g(this)g(array.)g(*/)168 683 y(int)g(size;)501 b(/*)23
+b(Number)g(of)h(slots)f(allocated)g(to)g(this)h(array.)f(*/)168
+733 y(int)g(flags;)120 783 y(})h(HISTORY_STATE;)62 927 y Fo(If)16
+b(the)f(\015ags)g(mem)o(b)q(er)g(includes)j Fn(HS_STIFLED)p
+Fo(,)13 b(the)i(history)h(has)f(b)q(een)h(sti\015ed.)0 1215
+y Fm(2.3)33 b(History)15 b(F)-6 b(unctions)62 1359 y Fo(This)16
+b(section)g(describ)q(es)h(the)e(calling)i(sequence)f(for)f(the)g(v)m(arious)
+h(functions)g(presen)o(t)f(in)h(GNU)f(History)l(.)0 1631 y
+Fi(2.3.1)30 b(Initializing)15 b(History)g(and)g(State)g(Managemen)n(t)62
+1775 y Fo(This)j(section)g(describ)q(es)h(functions)f(used)g(to)e(initialize)
+21 b(and)c(manage)g(the)g(state)g(of)g(the)g(History)g(library)0
+1837 y(when)f(y)o(ou)f(w)o(an)o(t)f(to)g(use)i(the)f(history)g(functions)h
+(in)g(y)o(our)f(program.)1725 2021 y(F)l(unction)-1899 b Fh(void)20
+b Fg(using)p 258 2021 18 3 v 20 w(history)j Ff(\(\))120 2083
+y Fo(Begin)g(a)f(session)g(in)h(whic)o(h)g(the)f(history)g(functions)g(migh)o
+(t)g(b)q(e)h(used.)40 b(This)23 b(initializes)i(the)120 2145
+y(in)o(teractiv)o(e)16 b(v)m(ariables.)1725 2328 y(F)l(unction)-1899
+b Fh(HISTORY_STATE)21 b(*)e Fg(history)p 582 2328 V 21 w(get)p
+680 2328 V 21 w(history)p 876 2328 V 21 w(state)j Ff(\(\))120
+2391 y Fo(Return)16 b(a)f(structure)g(describing)i(the)e(curren)o(t)g(state)f
+(of)h(the)g(input)i(history)l(.)1725 2574 y(F)l(unction)-1899
+b Fh(void)20 b Fg(history)p 302 2574 V 20 w(set)p 393 2574
+V 21 w(history)p 589 2574 V 21 w(state)j Ff(\()p Fn(HISTORY_STATE)13
+b(*state)p Ff(\))120 2636 y Fo(Set)i(the)h(state)e(of)h(the)g(history)g(list)
+h(according)g(to)e Fj(state)p Fo(.)p eop
+%%Page: 7 9
+8 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1039
+b(7)0 158 y Fi(2.3.2)30 b(History)15 b(List)g(Managemen)n(t)62
+295 y Fo(These)i(functions)h(manage)e(individual)k(en)o(tries)d(on)f(the)h
+(history)g(list,)g(or)f(set)h(parameters)e(managing)i(the)0
+358 y(list)f(itself.)1725 520 y(F)l(unction)-1899 b Fh(void)20
+b Fg(add)p 219 520 18 3 v 20 w(history)j Ff(\()p Fn(char)14
+b(*string)p Ff(\))120 582 y Fo(Place)j Fj(string)k Fo(at)16
+b(the)g(end)i(of)e(the)g(history)h(list.)25 b(The)17 b(asso)q(ciated)g(data)f
+(\014eld)h(\(if)g(an)o(y\))f(is)h(set)g(to)120 644 y Fn(NULL)p
+Fo(.)1725 806 y(F)l(unction)-1899 b Fh(HIST_ENTRY)21 b(*)e
+Fg(remo)n(v)n(e)p 509 806 V 20 w(history)k Ff(\()p Fn(int)14
+b(which)p Ff(\))120 868 y Fo(Remo)o(v)o(e)d(history)g(en)o(try)g(at)g
+(o\013set)f Fj(whic)o(h)i Fo(from)f(the)g(history)l(.)19 b(The)11
+b(remo)o(v)o(ed)g(elemen)o(t)h(is)g(returned)120 930 y(so)j(y)o(ou)g(can)g
+(free)g(the)h(line,)g(data,)e(and)i(con)o(taining)g(structure.)1725
+1092 y(F)l(unction)-1899 b Fh(HIST_ENTRY)21 b(*)e Fg(replace)p
+505 1092 V 22 w(history)p 702 1092 V 20 w(en)n(try)24 b Ff(\()p
+Fn(int)14 b(which,)g(char)h(*line,)f(char)208 1155 y(*data)p
+Ff(\))120 1217 y Fo(Mak)o(e)d(the)i(history)f(en)o(try)g(at)f(o\013set)h
+Fj(whic)o(h)h Fo(ha)o(v)o(e)e Fj(line)17 b Fo(and)12 b Fj(data)p
+Fo(.)19 b(This)12 b(returns)g(the)h(old)g(en)o(try)e(so)120
+1279 y(y)o(ou)i(can)g(disp)q(ose)h(of)e(the)h(data.)19 b(In)13
+b(the)g(case)g(of)f(an)h(in)o(v)m(alid)i Fj(whic)o(h)p Fo(,)f(a)f
+Fn(NULL)f Fo(p)q(oin)o(ter)i(is)f(returned.)1725 1441 y(F)l(unction)-1899
+b Fh(void)20 b Fg(sti\015e)p 245 1441 V 21 w(history)j Ff(\()p
+Fn(int)14 b(max)p Ff(\))120 1503 y Fo(Sti\015e)i(the)f(history)h(list,)f
+(remem)o(b)q(ering)h(only)g(the)f(last)g Fj(max)j Fo(en)o(tries.)1725
+1665 y(F)l(unction)-1899 b Fh(int)20 b Fg(unsti\015e)p 283
+1665 V 21 w(history)i Ff(\(\))120 1728 y Fo(Stop)13 b(sti\015ing)h(the)f
+(history)l(.)19 b(This)14 b(returns)f(the)g(previous)h(amoun)o(t)e(the)h
+(history)g(w)o(as)g(sti\015ed.)20 b(The)120 1790 y(v)m(alue)c(is)g(p)q
+(ositiv)o(e)g(if)g(the)f(history)g(w)o(as)g(sti\015ed,)h(negativ)o(e)f(if)g
+(it)h(w)o(asn't.)1725 1952 y(F)l(unction)-1899 b Fh(int)20
+b Fg(history)p 276 1952 V 20 w(is)p 334 1952 V 21 w(sti\015ed)k
+Ff(\(\))120 2014 y Fo(Returns)16 b(non-zero)f(if)h(the)f(history)g(is)h
+(sti\015ed,)g(zero)f(if)g(it)h(is)g(not.)0 2222 y Fi(2.3.3)30
+b(Information)14 b(Ab)r(out)h(the)g(History)g(List)62 2359
+y Fo(These)h(functions)g(return)f(information)g(ab)q(out)g(the)h(en)o(tire)f
+(history)g(list)h(or)f(individual)j(list)f(en)o(tries.)1725
+2521 y(F)l(unction)-1899 b Fh(HIST_ENTRY)21 b(**)e Fg(history)p
+530 2521 V 21 w(list)24 b Ff(\(\))120 2583 y Fo(Return)e(a)e
+Fn(NULL)h Fo(terminated)g(arra)o(y)f(of)g Fn(HIST_ENTRY)g Fo(whic)o(h)i(is)f
+(the)g(curren)o(t)g(input)h(history)l(.)120 2645 y(Elemen)o(t)16
+b(0)f(of)f(this)i(list)g(is)g(the)f(b)q(eginning)i(of)e(time.)20
+b(If)c(there)f(is)h(no)f(history)l(,)g(return)g Fn(NULL)p Fo(.)p
+eop
+%%Page: 8 10
+9 bop 0 -83 a Fo(8)1497 b(GNU)15 b(History)g(Library)1725 158
+y(F)l(unction)-1899 b Fh(int)20 b Fg(where)p 250 158 18 3 v
+20 w(history)j Ff(\(\))120 221 y Fo(Returns)16 b(the)f(o\013set)f(of)h(the)g
+(curren)o(t)g(history)g(elemen)o(t.)1725 378 y(F)l(unction)-1899
+b Fh(HIST_ENTRY)21 b(*)e Fg(curren)n(t)p 512 378 V 21 w(history)k
+Ff(\(\))120 440 y Fo(Return)14 b(the)g(history)g(en)o(try)f(at)h(the)g
+(curren)o(t)f(p)q(osition,)i(as)e(determined)j(b)o(y)d Fn(where_history)h
+(\(\))p Fo(.)120 502 y(If)h(there)h(is)f(no)h(en)o(try)e(there,)h(return)g(a)
+g Fn(NULL)g Fo(p)q(oin)o(ter.)1725 660 y(F)l(unction)-1899
+b Fh(HIST_ENTRY)21 b(*)e Fg(history)p 504 660 V 21 w(get)j
+Ff(\()p Fn(int)15 b(offset)p Ff(\))120 722 y Fo(Return)g(the)g(history)f(en)o
+(try)g(at)g(p)q(osition)i Fj(o\013set)p Fo(,)d(starting)h(from)g
+Fn(history_base)p Fo(.)k(If)c(there)h(is)g(no)120 784 y(en)o(try)g(there,)g
+(or)f(if)i Fj(o\013set)f Fo(is)h(greater)e(than)h(the)h(history)f(length,)g
+(return)g(a)g Fn(NULL)g Fo(p)q(oin)o(ter.)1725 942 y(F)l(unction)-1899
+b Fh(int)20 b Fg(history)p 276 942 V 20 w(total)p 412 942 V
+22 w(b)n(ytes)j Ff(\(\))120 1004 y Fo(Return)17 b(the)f(n)o(um)o(b)q(er)g(of)
+g(b)o(ytes)g(that)f(the)h(primary)g(history)g(en)o(tries)h(are)e(using.)23
+b(This)17 b(function)120 1066 y(returns)e(the)g(sum)h(of)e(the)i(lengths)f
+(of)g(all)h(the)g(lines)g(in)g(the)g(history)l(.)0 1265 y Fi(2.3.4)30
+b(Mo)n(ving)15 b(Around)h(the)f(History)g(List)62 1402 y Fo(These)h
+(functions)g(allo)o(w)f(the)g(curren)o(t)h(index)g(in)o(to)f(the)h(history)f
+(list)h(to)e(b)q(e)i(set)f(or)g(c)o(hanged.)1725 1559 y(F)l(unction)-1899
+b Fh(int)20 b Fg(history)p 276 1559 V 20 w(set)p 367 1559 V
+21 w(p)r(os)h Ff(\()p Fn(int)15 b(pos)p Ff(\))120 1621 y Fo(Set)g(the)h(p)q
+(osition)g(in)g(the)f(history)g(list)h(to)f Fj(p)q(os)p Fo(,)g(an)g(absolute)
+g(index)i(in)o(to)e(the)g(list.)1725 1779 y(F)l(unction)-1899
+b Fh(HIST_ENTRY)21 b(*)e Fg(previous)p 540 1779 V 20 w(history)k
+Ff(\(\))120 1841 y Fo(Bac)o(k)16 b(up)h(the)g(curren)o(t)f(history)h
+(o\013set)e(to)h(the)h(previous)g(history)g(en)o(try)l(,)f(and)h(return)f(a)g
+(p)q(oin)o(ter)120 1903 y(to)f(that)f(en)o(try)l(.)20 b(If)15
+b(there)g(is)h(no)f(previous)h(en)o(try)l(,)f(return)g(a)g
+Fn(NULL)g Fo(p)q(oin)o(ter.)1725 2061 y(F)l(unction)-1899 b
+Fh(HIST_ENTRY)21 b(*)e Fg(next)p 439 2061 V 21 w(history)k
+Ff(\(\))120 2123 y Fo(Mo)o(v)o(e)c(the)h(curren)o(t)g(history)f(o\013set)g
+(forw)o(ard)g(to)g(the)h(next)g(history)g(en)o(try)l(,)g(and)g(return)g(the)g
+(a)120 2185 y(p)q(oin)o(ter)c(to)e(that)h(en)o(try)l(.)k(If)d(there)f(is)h
+(no)f(next)g(en)o(try)l(,)g(return)g(a)g Fn(NULL)g Fo(p)q(oin)o(ter.)0
+2384 y Fi(2.3.5)30 b(Searc)n(hing)15 b(the)h(History)f(List)62
+2521 y Fo(These)e(functions)g(allo)o(w)f(searc)o(hing)h(of)f(the)g(history)g
+(list)h(for)f(en)o(tries)h(con)o(taining)g(a)f(sp)q(eci\014c)i(string.)19
+b(Searc)o(h-)0 2583 y(ing)e(ma)o(y)g(b)q(e)g(p)q(erformed)g(b)q(oth)g(forw)o
+(ard)f(and)h(bac)o(kw)o(ard)f(from)g(the)h(curren)o(t)f(history)h(p)q
+(osition.)26 b(The)17 b(searc)o(h)0 2645 y(ma)o(y)d(b)q(e)i
+Fj(anc)o(hored)p Fo(,)f(meaning)h(that)f(the)g(string)g(m)o(ust)g(matc)o(h)f
+(at)h(the)g(b)q(eginning)i(of)e(the)h(history)f(en)o(try)l(.)p
+eop
+%%Page: 9 11
+10 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1039
+b(9)1725 158 y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p
+276 158 18 3 v 20 w(searc)n(h)j Ff(\()p Fn(char)14 b(*string,)g(int)h
+(direction)p Ff(\))120 221 y Fo(Searc)o(h)k(the)g(history)g(for)f
+Fj(string)p Fo(,)i(starting)e(at)g(the)h(curren)o(t)g(history)g(o\013set.)30
+b(If)19 b Fj(direction)h Fn(<)f Fo(0,)120 283 y(then)14 b(the)f(searc)o(h)g
+(is)h(through)e(previous)i(en)o(tries,)g(else)g(through)f(subsequen)o(t.)20
+b(If)13 b Fj(string)k Fo(is)d(found,)120 345 y(then)f(the)g(curren)o(t)g
+(history)g(index)i(is)e(set)g(to)f(that)h(history)g(en)o(try)l(,)f(and)i(the)
+f(v)m(alue)h(returned)f(is)h(the)120 407 y(o\013set)h(in)i(the)f(line)i(of)d
+(the)h(en)o(try)g(where)g Fj(string)k Fo(w)o(as)c(found.)22
+b(Otherwise,)17 b(nothing)f(is)h(c)o(hanged,)120 470 y(and)e(a)g(-1)g(is)h
+(returned.)1725 659 y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p
+276 659 V 20 w(searc)n(h)p 452 659 V 21 w(pre\014x)i Ff(\()p
+Fn(char)15 b(*string,)f(int)g(direction)p Ff(\))120 721 y Fo(Searc)o(h)22
+b(the)h(history)f(for)f Fj(string)p Fo(,)j(starting)e(at)f(the)i(curren)o(t)f
+(history)g(o\013set.)40 b(The)22 b(searc)o(h)g(is)120 783 y(anc)o(hored:)i
+(matc)o(hing)18 b(lines)h(m)o(ust)d(b)q(egin)j(with)f Fj(string)p
+Fo(.)26 b(If)17 b Fj(direction)i Fn(<)e Fo(0,)g(then)h(the)f(searc)o(h)g(is)
+120 845 y(through)e(previous)h(en)o(tries,)f(else)i(through)d(subsequen)o(t.)
+21 b(If)16 b Fj(string)j Fo(is)d(found,)f(then)h(the)f(curren)o(t)120
+908 y(history)20 b(index)i(is)e(set)g(to)g(that)f(en)o(try)l(,)i(and)f(the)g
+(return)h(v)m(alue)g(is)g(0.)34 b(Otherwise,)22 b(nothing)e(is)120
+970 y(c)o(hanged,)15 b(and)h(a)e(-1)h(is)h(returned.)1725 1159
+y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p 276 1159 V 20
+w(searc)n(h)p 452 1159 V 21 w(p)r(os)h Ff(\()p Fn(char)15 b(*string,)f(int)g
+(direction,)g(int)h(pos)p Ff(\))120 1221 y Fo(Searc)o(h)d(for)f
+Fj(string)k Fo(in)d(the)g(history)f(list,)i(starting)e(at)g
+Fj(p)q(os)p Fo(,)h(an)f(absolute)h(index)h(in)o(to)e(the)h(list.)19
+b(If)12 b Fj(di-)120 1283 y(rection)g Fo(is)h(negativ)o(e,)f(the)g(searc)o(h)
+g(pro)q(ceeds)h(bac)o(kw)o(ard)e(from)g Fj(p)q(os)p Fo(,)i(otherwise)f(forw)o
+(ard.)17 b(Returns)120 1345 y(the)e(absolute)h(index)g(of)f(the)g(history)h
+(elemen)o(t)f(where)h Fj(string)j Fo(w)o(as)14 b(found,)h(or)g(-1)g
+(otherwise.)0 1634 y Fi(2.3.6)30 b(Managing)14 b(the)i(History)f(File)62
+1780 y Fo(The)f(History)g(library)h(can)f(read)g(the)g(history)g(from)f(and)i
+(write)f(it)g(to)f(a)h(\014le.)20 b(This)15 b(section)g(do)q(cumen)o(ts)f
+(the)0 1842 y(functions)i(for)f(managing)g(a)f(history)i(\014le.)1725
+2031 y(F)l(unction)-1899 b Fh(int)20 b Fg(read)p 211 2031 V
+20 w(history)i Ff(\()p Fn(char)15 b(*filename)p Ff(\))120 2093
+y Fo(Add)i(the)f(con)o(ten)o(ts)g(of)g Fj(\014lename)k Fo(to)c(the)h(history)
+f(list,)h(a)f(line)i(at)e(a)g(time.)24 b(If)17 b Fj(\014lename)j
+Fo(is)d Fn(NULL)p Fo(,)120 2155 y(then)f(read)f(from)f(`)p
+Fn(~/.history)p Fo('.)k(Returns)e(0)e(if)i(successful,)g(or)f(errno)g(if)h
+(not.)1725 2344 y(F)l(unction)-1899 b Fh(int)20 b Fg(read)p
+211 2344 V 20 w(history)p 406 2344 V 20 w(range)i Ff(\()p Fn(char)15
+b(*filename,)e(int)i(from,)g(int)f(to)p Ff(\))120 2407 y Fo(Read)j(a)e(range)
+h(of)f(lines)j(from)d Fj(\014lename)p Fo(,)i(adding)f(them)g(to)f(the)h
+(history)g(list.)23 b(Start)15 b(reading)i(at)120 2469 y(line)f
+Fj(from)f Fo(and)g(end)g(at)f Fj(to)p Fo(.)19 b(If)d Fj(from)e
+Fo(is)h(zero,)f(start)g(at)g(the)h(b)q(eginning.)22 b(If)15
+b Fj(to)i Fo(is)e(less)g(than)g Fj(from)p Fo(,)120 2531 y(then)i(read)g(un)o
+(til)h(the)f(end)g(of)g(the)g(\014le.)25 b(If)17 b Fj(\014lename)k
+Fo(is)c Fn(NULL)p Fo(,)f(then)i(read)e(from)g(`)p Fn(~/.history)p
+Fo('.)120 2593 y(Returns)g(0)f(if)g(successful,)h(or)f Fn(errno)g
+Fo(if)g(not.)p eop
+%%Page: 10 12
+11 bop 0 -83 a Fo(10)1474 b(GNU)15 b(History)g(Library)1725
+158 y(F)l(unction)-1899 b Fh(int)20 b Fg(write)p 229 158 18
+3 v 22 w(history)i Ff(\()p Fn(char)15 b(*filename)p Ff(\))120
+221 y Fo(W)l(rite)20 b(the)g(curren)o(t)f(history)h(to)f Fj(\014lename)p
+Fo(,)i(o)o(v)o(erwriting)f Fj(\014lename)j Fo(if)d(necessary)l(.)34
+b(If)20 b Fj(\014lename)120 283 y Fo(is)d Fn(NULL)p Fo(,)g(then)g(write)g
+(the)g(history)g(list)h(to)e(`)p Fn(~/.history)p Fo('.)23 b(V)l(alues)18
+b(returned)g(are)e(as)h(in)h Fn(read_)120 345 y(history)c(\(\))p
+Fo(.)1725 504 y(F)l(unction)-1899 b Fh(int)20 b Fg(app)r(end)p
+285 504 V 19 w(history)j Ff(\()p Fn(int)14 b(nelements,)g(char)h(*filename)p
+Ff(\))120 566 y Fo(App)q(end)i(the)e(last)g Fj(nelemen)o(ts)j
+Fo(of)d(the)g(history)g(list)h(to)f Fj(\014lename)p Fo(.)1725
+724 y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p 276 724
+V 20 w(truncate)p 507 724 V 21 w(\014le)k Ff(\()p Fn(char)14
+b(*filename,)g(int)h(nlines)p Ff(\))120 787 y Fo(T)l(runcate)g(the)h(history)
+f(\014le)h Fj(\014lename)p Fo(,)g(lea)o(ving)g(only)g(the)f(last)g
+Fj(nlines)k Fo(lines.)0 988 y Fi(2.3.7)30 b(History)15 b(Expansion)62
+1125 y Fo(These)h(functions)g(implemen)o(t)g Fn(csh)p Fo(-lik)o(e)g(history)g
+(expansion.)1725 1283 y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p
+276 1283 V 20 w(expand)j Ff(\()p Fn(char)14 b(*string,)g(char)h(**output)p
+Ff(\))120 1345 y Fo(Expand)20 b Fj(string)p Fo(,)f(placing)i(the)e(result)h
+(in)o(to)f Fj(output)p Fo(,)h(a)f(p)q(oin)o(ter)h(to)e(a)h(string)h(\(see)f
+(Section)h(1.1)120 1408 y([History)15 b(In)o(teraction],)f(page)h(1\).)20
+b(Returns:)120 1555 y Fn(0)216 b Fo(If)21 b(no)g(expansions)h(to)q(ok)e
+(place)h(\(or,)g(if)h(the)f(only)g(c)o(hange)g(in)h(the)f(text)f(w)o(as)g
+(the)360 1618 y(de-slashifying)d(of)e(the)g(history)h(expansion)g(c)o
+(haracter\);)120 1701 y Fn(1)216 b Fo(if)16 b(expansions)g(did)g(tak)o(e)e
+(place;)120 1785 y Fn(-1)192 b Fo(if)16 b(there)f(w)o(as)f(an)h(error)g(in)h
+(expansion;)120 1869 y Fn(2)216 b Fo(if)14 b(the)f(returned)h(line)h(should)f
+(only)g(b)q(e)f(displa)o(y)o(ed,)i(but)e(not)g(executed,)h(as)f(with)h(the)
+360 1931 y Fn(:p)h Fo(mo)q(di\014er)h(\(see)f(Section)h(1.1.3)e([Mo)q
+(di\014ers],)h(page)g(2\).)120 2079 y(If)g(an)h(error)e(o)q(curred)i(in)g
+(expansion,)f(then)h Fj(output)g Fo(con)o(tains)f(a)g(descriptiv)o(e)i(error)
+d(message.)1725 2238 y(F)l(unction)-1899 b Fh(char)20 b(*)f
+Fg(history)p 347 2238 V 21 w(arg)p 449 2238 V 19 w(extract)24
+b Ff(\()p Fn(int)14 b(first,)h(int)g(last,)f(char)h(*string)p
+Ff(\))120 2300 y Fo(Extract)10 b(a)h(string)g(segmen)o(t)g(consisting)h(of)f
+(the)g Fj(\014rst)h Fo(through)f Fj(last)h Fo(argumen)o(ts)e(presen)o(t)h(in)
+h Fj(string)p Fo(.)120 2362 y(Argumen)o(ts)j(are)g(brok)o(en)g(up)g(as)g(in)h
+(Bash.)1725 2521 y(F)l(unction)-1899 b Fh(char)20 b(*)f Fg(get)p
+249 2521 V 21 w(history)p 445 2521 V 20 w(ev)n(en)n(t)25 b
+Ff(\()p Fn(char)14 b(*string,)g(int)h(*cindex,)f(int)h(qchar)p
+Ff(\))120 2583 y Fo(Returns)e(the)f(text)f(of)h(the)g(history)g(ev)o(en)o(t)f
+(b)q(eginning)k(at)c Fj(string)16 b Fn(+)c Fj(*cindex)p Fo(.)20
+b Fj(*cindex)c Fo(is)d(mo)q(di\014ed)120 2645 y(to)h(p)q(oin)o(t)h(to)f
+(after)h(the)f(ev)o(en)o(t)h(sp)q(eci\014er.)21 b(A)o(t)15
+b(function)g(en)o(try)l(,)f Fj(cindex)20 b Fo(p)q(oin)o(ts)15
+b(to)f(the)h(index)h(in)o(to)p eop
+%%Page: 11 13
+12 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1017
+b(11)120 158 y Fj(string)17 b Fo(where)d(the)f(history)h(ev)o(en)o(t)f(sp)q
+(eci\014cation)i(b)q(egins.)20 b Fj(qc)o(har)d Fo(is)c(a)g(c)o(haracter)g
+(that)g(is)h(allo)o(w)o(ed)120 221 y(to)h(end)g(the)h(ev)o(en)o(t)f(sp)q
+(eci\014cation)i(in)f(addition)g(to)f(the)g(\\normal")g(terminating)g(c)o
+(haracters.)1725 394 y(F)l(unction)-1899 b Fh(char)20 b(**)f
+Fg(history)p 373 394 18 3 v 21 w(tok)n(enize)25 b Ff(\()p Fn(char)14
+b(*string)p Ff(\))120 456 y Fo(Return)k(an)f(arra)o(y)f(of)h(tok)o(ens)f
+(parsed)i(out)e(of)h Fj(string)p Fo(,)g(m)o(uc)o(h)h(as)e(the)i(shell)g(migh)
+o(t.)26 b(The)17 b(tok)o(ens)120 519 y(are)c(split)h(on)f(white)g(space)h
+(and)f(on)g(the)g(c)o(haracters)f Fn(\(\)<>;&|$)p Fo(,)g(and)h(shell)i
+(quoting)e(con)o(v)o(en)o(tions)120 581 y(are)i(ob)q(ey)o(ed.)0
+840 y Fm(2.4)33 b(History)15 b(V)-6 b(ariables)62 981 y Fo(This)16
+b(section)g(describ)q(es)h(the)e(externally)h(visible)i(v)m(ariables)e(exp)q
+(orted)g(b)o(y)f(the)g(GNU)g(History)g(Library)l(.)1736 1155
+y(V)l(ariable)-1899 b Fh(int)20 b Fg(history)p 276 1155 V 20
+w(base)120 1217 y Fo(The)15 b(logical)i(o\013set)d(of)h(the)g(\014rst)g(en)o
+(try)g(in)h(the)f(history)g(list.)1736 1390 y(V)l(ariable)-1899
+b Fh(int)20 b Fg(history)p 276 1390 V 20 w(length)120 1453
+y Fo(The)15 b(n)o(um)o(b)q(er)h(of)f(en)o(tries)g(curren)o(tly)h(stored)f(in)
+h(the)f(history)g(list.)1736 1626 y(V)l(ariable)-1899 b Fh(int)20
+b Fg(max)p 208 1626 V 19 w(input)p 360 1626 V 21 w(history)120
+1689 y Fo(The)12 b(maxim)o(um)g(n)o(um)o(b)q(er)g(of)f(history)h(en)o(tries.)
+19 b(This)12 b(m)o(ust)f(b)q(e)h(c)o(hanged)g(using)h Fn(stifle_history)120
+1751 y(\(\))p Fo(.)1736 1924 y(V)l(ariable)-1899 b Fh(char)20
+b Fg(history)p 302 1924 V 20 w(expansion)p 569 1924 V 21 w(c)n(har)120
+1987 y Fo(The)15 b(c)o(haracter)g(that)f(starts)g(a)h(history)g(ev)o(en)o(t.)
+20 b(The)15 b(default)h(is)g(`)p Fn(!)p Fo('.)1736 2160 y(V)l(ariable)-1899
+b Fh(char)20 b Fg(history)p 302 2160 V 20 w(subst)p 454 2160
+V 20 w(c)n(har)120 2222 y Fo(The)13 b(c)o(haracter)e(that)h(in)o(v)o(ok)o(es)
+g(w)o(ord)g(substitution)h(if)g(found)g(at)e(the)i(start)e(of)h(a)g(line.)21
+b(The)12 b(default)120 2285 y(is)k(`)p Fn(^)p Fo('.)1736 2458
+y(V)l(ariable)-1899 b Fh(char)20 b Fg(history)p 302 2458 V
+20 w(commen)n(t)p 552 2458 V 19 w(c)n(har)120 2521 y Fo(During)12
+b(tok)o(enization,)h(if)f(this)h(c)o(haracter)e(is)i(seen)f(as)g(the)g
+(\014rst)f(c)o(haracter)g(of)h(a)g(w)o(ord,)f(then)i(it)f(and)120
+2583 y(all)19 b(subsequen)o(t)g(c)o(haracters)e(up)h(to)g(a)f(newline)j(are)e
+(ignored,)h(suppressing)g(history)f(expansion)120 2645 y(for)d(the)g
+(remainder)h(of)f(the)g(line.)21 b(This)16 b(is)g(disabled)h(b)o(y)e
+(default.)p eop
+%%Page: 12 14
+13 bop 0 -83 a Fo(12)1474 b(GNU)15 b(History)g(Library)1736
+158 y(V)l(ariable)-1899 b Fh(char)20 b(*)f Fg(history)p 347
+158 18 3 v 21 w(no)p 429 158 V 20 w(expand)p 629 158 V 20 w(c)n(hars)120
+221 y Fo(The)f(list)g(of)g(c)o(haracters)e(whic)o(h)j(inhibit)h(history)d
+(expansion)i(if)f(found)g(immediately)h(follo)o(wing)120 283
+y Fj(history)p 261 283 14 2 v 16 w(expansion)p 472 283 V 18
+w(c)o(har)p Fo(.)g(The)d(default)f(is)h(whitespace)g(and)g(`)p
+Fn(=)p Fo('.)0 575 y Fm(2.5)33 b(History)15 b(Programming)h(Example)62
+720 y Fo(The)g(follo)o(wing)g(program)e(demonstrates)g(simple)j(use)e(of)g
+(the)g(GNU)g(History)g(Library)l(.)120 852 y Fn(main)23 b(\(\))120
+902 y({)168 951 y(char)g(line[1024],)f(*t;)168 1001 y(int)h(len,)g(done)h(=)g
+(0;)168 1101 y(line[0])f(=)g(0;)168 1201 y(using_history)f(\(\);)168
+1250 y(while)h(\(!done\))215 1300 y({)263 1350 y(printf)g(\("history$)g("\);)
+263 1400 y(fflush)g(\(stdout\);)263 1450 y(t)h(=)g(fgets)f(\(line,)g(sizeof)g
+(\(line\))g(-)h(1,)f(stdin\);)263 1499 y(if)h(\(t)f(&&)h(*t\))311
+1549 y({)359 1599 y(len)f(=)h(strlen)f(\(t\);)359 1649 y(if)g(\(t[len)g(-)h
+(1])g(==)f('\\n'\))406 1699 y(t[len)h(-)f(1])h(=)g('\\0';)311
+1748 y(})263 1848 y(if)g(\(!t\))311 1898 y(strcpy)f(\(line,)g("quit"\);)263
+1998 y(if)h(\(line[0]\))311 2047 y({)359 2097 y(char)f(*expansion;)359
+2147 y(int)g(result;)359 2247 y(result)g(=)g(history_expand)f(\(line,)h
+(&expansion\);)359 2296 y(if)g(\(result\))406 2346 y(fprintf)g(\(stderr,)g
+("\045s\\n",)g(expansion\);)359 2446 y(if)g(\(result)g(<)h(0)g(||)f(result)g
+(==)h(2\))406 2496 y({)454 2545 y(free)f(\(expansion\);)454
+2595 y(continue;)406 2645 y(})p eop
+%%Page: 13 15
+14 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1017
+b(13)359 208 y Fn(add_history)22 b(\(expansion\);)359 258 y(strncpy)h
+(\(line,)g(expansion,)f(sizeof)h(\(line\))g(-)h(1\);)359 308
+y(free)f(\(expansion\);)311 358 y(})263 457 y(if)h(\(strcmp)f(\(line,)g
+("quit"\))g(==)g(0\))311 507 y(done)g(=)h(1;)263 557 y(else)f(if)h(\(strcmp)f
+(\(line,)g("save"\))g(==)h(0\))311 607 y(write_history)e(\("history_file"\);)
+263 656 y(else)h(if)h(\(strcmp)f(\(line,)g("read"\))g(==)h(0\))311
+706 y(read_history)e(\("history_file"\);)263 756 y(else)h(if)h(\(strcmp)f
+(\(line,)g("list"\))g(==)h(0\))311 806 y({)359 856 y(register)e(HIST_ENTRY)h
+(**the_list;)359 906 y(register)f(int)i(i;)359 1005 y(the_list)e(=)i
+(history_list)e(\(\);)359 1055 y(if)h(\(the_list\))406 1105
+y(for)h(\(i)f(=)h(0;)g(the_list[i];)e(i++\))454 1155 y(printf)h(\("\045d:)g
+(\045s\\n",)g(i)h(+)g(history_base,)e(the_list[i]->line\);)311
+1204 y(})263 1254 y(else)h(if)h(\(strncmp)f(\(line,)g("delete",)g(6\))g(==)h
+(0\))311 1304 y({)359 1354 y(int)f(which;)359 1404 y(if)g(\(\(sscanf)g
+(\(line)g(+)h(6,)f("\045d",)h(&which\)\))e(==)i(1\))406 1453
+y({)454 1503 y(HIST_ENTRY)f(*entry)g(=)g(remove_history)f(\(which\);)454
+1553 y(if)i(\(!entry\))502 1603 y(fprintf)f(\(stderr,)f("No)i(such)f(entry)g
+(\045d\\n",)g(which\);)454 1653 y(else)502 1703 y({)550 1752
+y(free)g(\(entry->line\);)550 1802 y(free)g(\(entry\);)502
+1852 y(})406 1902 y(})359 1952 y(else)406 2001 y({)454 2051
+y(fprintf)g(\(stderr,)g("non-numeric)f(arg)h(given)h(to)f(`delete'\\n"\);)406
+2101 y(})311 2151 y(})215 2201 y(})120 2250 y(})p eop
+%%Page: 14 16
+15 bop 0 -83 a Fo(14)1474 b(GNU)15 b(History)g(Library)p eop
+%%Page: 15 17
+16 bop 0 -83 a Fo(App)q(endix)17 b(A:)e(Concept)g(Index)1346
+b(15)0 158 y Fk(App)r(endix)13 b(A)41 b(Concept)15 b(Index)0
+405 y Fm(A)0 471 y Fe(anc)o(hored)f(searc)o(h)5 b Fd(:)i(:)f(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fe(8)0
+579 y Fm(E)0 646 y Fe(ev)o(en)o(t)13 b(designators)g Fd(:)6
+b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)23
+b Fe(1)1015 405 y(expansion)5 b Fd(:)k(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fe(1)1015
+521 y Fm(H)1015 587 y Fe(history)d(ev)o(en)o(ts)5 b Fd(:)i(:)f(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b
+Fe(1)1015 646 y(History)c(Searc)o(hing)7 b Fd(:)h(:)e(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fe(8)p eop
+%%Page: 16 18
+17 bop 0 -83 a Fo(16)1474 b(GNU)15 b(History)g(Library)p eop
+%%Page: 17 19
+18 bop 0 -83 a Fo(App)q(endix)17 b(B:)e(F)l(unction)h(and)g(V)l(ariable)g
+(Index)1069 b(17)0 158 y Fk(App)r(endix)13 b(B)41 b(F)-7 b(unction)15
+b(and)g(V)-7 b(ariable)14 b(Index)0 405 y Fm(A)0 471 y Fc(add)p
+62 471 12 2 v 13 w(history)8 b Fd(:)s(:)e(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20 b Fe(7)0 529 y Fc(append)p
+122 529 V 12 w(history)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)24 b Fe(10)0 654 y Fm(C)0 720 y Fc(current)p
+142 720 V 11 w(history)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)24 b Fe(8)0 845 y Fm(G)0 911 y Fc(get)p 62 911
+V 13 w(history)p 215 911 V 11 w(event)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)23 b Fe(10)0 1036 y Fm(H)0 1102 y Fc(history)p
+142 1102 V 11 w(arg)p 213 1102 V 13 w(extract)8 b Fd(:)t(:)e(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)21 b Fe(10)0 1160 y Fc(history)p 142 1160
+V 11 w(base)e Fd(:)6 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)20 b Fe(11)0 1218 y Fc(history)p 142 1218 V 11 w(comment)p
+293 1218 V 12 w(char)g Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)21
+b Fe(11)0 1276 y Fc(history)p 142 1276 V 11 w(expand)10 b Fd(:)c(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)24 b Fe(10)0
+1335 y Fc(history)p 142 1335 V 11 w(expansion)p 333 1335 V
+11 w(char)17 b Fd(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fe(11)0
+1393 y Fc(history)p 142 1393 V 11 w(get)8 b Fd(:)d(:)h(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20 b Fe(8)0
+1451 y Fc(history)p 142 1451 V 11 w(get)p 213 1451 V 13 w(history)p
+366 1451 V 12 w(state)t Fd(:)t(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fe(6)0
+1509 y Fc(history)p 142 1509 V 11 w(is)p 193 1509 V 14 w(stifled)7
+b Fd(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b
+Fe(7)0 1567 y Fc(history)p 142 1567 V 11 w(length)16 b Fd(:)6
+b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18
+b Fe(11)0 1625 y Fc(history)p 142 1625 V 11 w(list)7 b Fd(:)t(:)g(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)19
+b Fe(7)0 1683 y Fc(history)p 142 1683 V 11 w(no)p 193 1683
+V 14 w(expand)p 327 1683 V 12 w(chars)f Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20
+b Fe(12)0 1741 y Fc(history)p 142 1741 V 11 w(search)t Fd(:)t(:)6
+b(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17
+b Fe(9)0 1800 y Fc(history)p 142 1800 V 11 w(search)p 273 1800
+V 12 w(pos)9 b Fd(:)d(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23
+b Fe(9)0 1858 y Fc(history)p 142 1858 V 11 w(search)p 273 1858
+V 12 w(prefix)6 b Fd(:)t(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fe(9)0 1916 y Fc(history)p 142 1916 V 11 w(set)p 213 1916
+V 13 w(history)p 366 1916 V 12 w(state)t Fd(:)t(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17
+b Fe(6)0 1974 y Fc(history)p 142 1974 V 11 w(set)p 213 1974
+V 13 w(pos)5 b Fd(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)18 b Fe(8)0 2032 y Fc(history)p 142 2032 V 11 w(subst)p
+253 2032 V 13 w(char)k Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)24
+b Fe(11)1015 405 y Fc(history)p 1157 405 V 12 w(tokenize)9
+b Fd(:)s(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)22
+b Fe(11)1015 463 y Fc(history)p 1157 463 V 12 w(total)p 1269
+463 V 12 w(bytes)9 b Fd(:)t(:)d(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22
+b Fe(8)1015 521 y Fc(history)p 1157 521 V 12 w(truncate)p 1329
+521 V 11 w(file)5 b Fd(:)g(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fe(10)1015 629 y Fm(M)1015 695 y Fc(max)p 1077 695 V 13 w(input)p
+1190 695 V 13 w(history)14 b Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)17 b Fe(11)1015 803 y Fm(N)1015 870 y Fc(next)p 1097
+870 V 13 w(history)7 b Fd(:)s(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fe(8)1015 978 y Fm(P)1015 1044
+y Fc(previous)p 1177 1044 V 12 w(history)7 b Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b Fe(8)1015 1152 y Fm(R)1015
+1218 y Fc(read)p 1097 1218 V 13 w(history)7 b Fd(:)s(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fe(9)1015
+1276 y Fc(read)p 1097 1276 V 13 w(history)p 1250 1276 V 11
+w(range)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)23
+b Fe(9)1015 1335 y Fc(remove)p 1137 1335 V 12 w(history)t Fd(:)t(:)6
+b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)17
+b Fe(7)1015 1393 y Fc(replace)p 1157 1393 V 12 w(history)p
+1309 1393 V 11 w(entry)6 b Fd(:)f(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)19
+b Fe(7)1015 1501 y Fm(S)1015 1567 y Fc(stifle)p 1137 1567 V
+12 w(history)t Fd(:)t(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)17 b Fe(7)1015 1675 y Fm(U)1015 1741 y Fc(unstifle)p
+1177 1741 V 12 w(history)7 b Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)23 b Fe(7)1015 1800 y Fc(using)p 1117 1800 V
+13 w(history)5 b Fd(:)s(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)18 b Fe(6)1015 1907 y Fm(W)1015 1974 y Fc(where)p
+1117 1974 V 13 w(history)5 b Fd(:)s(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)18 b Fe(8)1015 2032 y Fc(write)p
+1117 2032 V 13 w(history)5 b Fd(:)s(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)18 b Fe(9)p eop
+%%Page: 18 20
+19 bop 0 -83 a Fo(18)1474 b(GNU)15 b(History)g(Library)p eop
+%%Page: -1 21
+20 bop 1937 -83 a Fo(i)0 158 y Fk(T)-7 b(able)15 b(of)g(Con)n(ten)n(ts)0
+333 y Fm(1)67 b(Using)22 b(History)h(In)n(teractiv)n(ely)9
+b Fb(:)k(:)d(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)31 b Fm(1)149 411 y Fo(1.1)45
+b(History)15 b(In)o(teraction)9 b Fa(:)f(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)23
+b Fo(1)299 473 y(1.1.1)44 b(Ev)o(en)o(t)14 b(Designators)6
+b Fa(:)h(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)20 b Fo(1)299 535 y(1.1.2)44 b(W)l(ord)15 b(Designators)9
+b Fa(:)d(:)h(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)23 b Fo(2)299 597 y(1.1.3)44 b(Mo)q(di\014ers)14
+b Fa(:)8 b(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)28 b Fo(2)0 722
+y Fm(2)67 b(Programming)23 b(with)g(GNU)f(History)13 b Fb(:)e(:)f(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)36 b
+Fm(5)149 800 y Fo(2.1)45 b(In)o(tro)q(duction)16 b(to)f(History)6
+b Fa(:)h(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)20 b Fo(5)149 862 y(2.2)45 b(History)15
+b(Storage)d Fa(:)7 b(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)27
+b Fo(5)149 924 y(2.3)45 b(History)15 b(F)l(unctions)c Fa(:)d(:)f(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)25 b Fo(6)299 986 y(2.3.1)44 b(Initializing)18
+b(History)d(and)h(State)e(Managemen)o(t)f Fa(:)7 b(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)27 b Fo(6)299 1049 y(2.3.2)44 b(History)15
+b(List)h(Managemen)o(t)c Fa(:)7 b(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)28 b Fo(7)299 1111 y(2.3.3)44 b(Information)15 b(Ab)q(out)g(the)h(History)
+f(List)5 b Fa(:)i(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)19 b Fo(7)299 1173 y(2.3.4)44 b(Mo)o(ving)15
+b(Around)g(the)g(History)g(List)6 b Fa(:)i(:)f(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)20
+b Fo(8)299 1236 y(2.3.5)44 b(Searc)o(hing)16 b(the)f(History)g(List)7
+b Fa(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)21 b
+Fo(8)299 1298 y(2.3.6)44 b(Managing)15 b(the)g(History)g(File)5
+b Fa(:)j(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)19 b
+Fo(9)299 1360 y(2.3.7)44 b(History)15 b(Expansion)d Fa(:)7
+b(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)26
+b Fo(10)149 1422 y(2.4)45 b(History)15 b(V)l(ariables)5 b Fa(:)k(:)e(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)20 b Fo(11)149 1485 y(2.5)45 b(History)15
+b(Programming)f(Example)8 b Fa(:)g(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)23 b Fo(12)0 1609 y Fm(App)r(endix)h(A)67 b(Concept)22
+b(Index)15 b Fb(:)c(:)f(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)37 b Fm(15)0 1749
+y(App)r(endix)24 b(B)67 b(F)-6 b(unction)25 b(and)e(V)-6 b(ariable)24
+b(Index)8 b Fb(:)j(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)31
+b Fm(17)p eop
+%%Page: -2 22
+21 bop 0 -83 a Fo(ii)1496 b(GNU)15 b(History)g(Library)p eop
+%%Trailer
+end
+userdict /end-hook known{end-hook}if
+%%EOF
diff --git a/lib/readline/doc/hstech.texinfo b/lib/readline/doc/hstech.texinfo
new file mode 100644 (file)
index 0000000..5f0f600
--- /dev/null
@@ -0,0 +1,489 @@
+@ignore
+This file documents the user interface to the GNU History library.
+
+Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+Authored by Brian Fox and Chet Ramey.
+
+Permission is granted to make and distribute verbatim copies of this manual
+provided the copyright notice and this permission notice are preserved on
+all copies.
+
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+GNU Copyright statement is available to the distributee, and provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ignore
+
+@node Programming with GNU History
+@chapter Programming with GNU History
+
+This chapter describes how to interface programs that you write
+with the GNU History Library.
+It should be considered a technical guide.
+For information on the interactive use of GNU History, @pxref{Using
+History Interactively}.
+
+@menu
+* Introduction to History::    What is the GNU History library for?
+* History Storage::            How information is stored.
+* History Functions::          Functions that you can use.
+* History Variables::          Variables that control behaviour.
+* History Programming Example::        Example of using the GNU History Library.
+@end menu
+
+@node Introduction to History
+@section Introduction to History
+
+Many programs read input from the user a line at a time.  The GNU History
+library is able to keep track of those lines, associate arbitrary data with
+each line, and utilize information from previous lines in composing new
+ones.
+
+The programmer using the History library has available functions
+for remembering lines on a history list, associating arbitrary data
+with a line, removing lines from the list, searching through the list
+for a line containing an arbitrary text string, and referencing any line
+in the list directly.  In addition, a history @dfn{expansion} function
+is available which provides for a consistent user interface across
+different programs.
+
+The user using programs written with the History library has the
+benefit of a consistent user interface with a set of well-known
+commands for manipulating the text of previous lines and using that text
+in new commands.  The basic history manipulation commands are similar to
+the history substitution provided by @code{csh}.
+
+If the programmer desires, he can use the Readline library, which
+includes some history manipulation by default, and has the added
+advantage of command line editing.
+
+@node History Storage
+@section History Storage
+
+The history list is an array of history entries.  A history entry is
+declared as follows:
+
+@example
+typedef struct _hist_entry @{
+  char *line;
+  char *data;
+@} HIST_ENTRY;
+@end example
+
+The history list itself might therefore be declared as
+
+@example
+HIST_ENTRY **the_history_list;
+@end example
+
+The state of the History library is encapsulated into a single structure:
+
+@example
+/* A structure used to pass the current state of the history stuff around. */
+typedef struct _hist_state @{
+  HIST_ENTRY **entries;         /* Pointer to the entries themselves. */
+  int offset;                   /* The location pointer within this array. */
+  int length;                   /* Number of elements within this array. */
+  int size;                     /* Number of slots allocated to this array. */
+  int flags;
+@} HISTORY_STATE;
+@end example
+
+If the flags member includes @code{HS_STIFLED}, the history has been
+stifled.
+
+@node History Functions
+@section History Functions
+
+This section describes the calling sequence for the various functions
+present in GNU History.
+
+@menu
+* Initializing History and State Management::  Functions to call when you
+                                               want to use history in a
+                                               program.
+* History List Management::            Functions used to manage the list
+                                       of history entries.
+* Information About the History List:: Functions returning information about
+                                       the history list.
+* Moving Around the History List::     Functions used to change the position
+                                       in the history list.
+* Searching the History List::         Functions to search the history list
+                                       for entries containing a string.
+* Managing the History File::          Functions that read and write a file
+                                       containing the history list.
+* History Expansion::                  Functions to perform csh-like history
+                                       expansion.
+@end menu
+
+@node Initializing History and State Management
+@subsection Initializing History and State Management
+
+This section describes functions used to initialize and manage
+the state of the History library when you want to use the history
+functions in your program.
+
+@deftypefun void using_history ()
+Begin a session in which the history functions might be used.  This
+initializes the interactive variables.
+@end deftypefun
+
+@deftypefun {HISTORY_STATE *} history_get_history_state ()
+Return a structure describing the current state of the input history.
+@end deftypefun
+
+@deftypefun void history_set_history_state (HISTORY_STATE *state)
+Set the state of the history list according to @var{state}.
+@end deftypefun
+
+@node History List Management
+@subsection History List Management
+
+These functions manage individual entries on the history list, or set
+parameters managing the list itself.
+
+@deftypefun void add_history (char *string)
+Place @var{string} at the end of the history list.  The associated data
+field (if any) is set to @code{NULL}.
+@end deftypefun
+
+@deftypefun {HIST_ENTRY *} remove_history (int which)
+Remove history entry at offset @var{which} from the history.  The
+removed element is returned so you can free the line, data,
+and containing structure.
+@end deftypefun
+
+@deftypefun {HIST_ENTRY *} replace_history_entry (int which, char *line, char *data)
+Make the history entry at offset @var{which} have @var{line} and @var{data}.
+This returns the old entry so you can dispose of the data.  In the case
+of an invalid @var{which}, a @code{NULL} pointer is returned.
+@end deftypefun
+
+@deftypefun void stifle_history (int max)
+Stifle the history list, remembering only the last @var{max} entries.
+@end deftypefun
+
+@deftypefun int unstifle_history ()
+Stop stifling the history.  This returns the previous amount the
+history was stifled.  The value is positive if the history was
+stifled, negative if it wasn't.
+@end deftypefun
+
+@deftypefun int history_is_stifled ()
+Returns non-zero if the history is stifled, zero if it is not.
+@end deftypefun
+
+@node Information About the History List
+@subsection Information About the History List
+
+These functions return information about the entire history list or
+individual list entries.
+
+@deftypefun {HIST_ENTRY **} history_list ()
+Return a @code{NULL} terminated array of @code{HIST_ENTRY} which is the
+current input history.  Element 0 of this list is the beginning of time.
+If there is no history, return @code{NULL}.
+@end deftypefun
+
+@deftypefun int where_history ()
+Returns the offset of the current history element.
+@end deftypefun
+
+@deftypefun {HIST_ENTRY *} current_history ()
+Return the history entry at the current position, as determined by
+@code{where_history ()}.  If there is no entry there, return a @code{NULL}
+pointer.
+@end deftypefun
+
+@deftypefun {HIST_ENTRY *} history_get (int offset)
+Return the history entry at position @var{offset}, starting from
+@code{history_base}.  If there is no entry there, or if @var{offset}
+is greater than the history length, return a @code{NULL} pointer.
+@end deftypefun
+
+@deftypefun int history_total_bytes ()
+Return the number of bytes that the primary history entries are using.
+This function returns the sum of the lengths of all the lines in the
+history.
+@end deftypefun
+
+@node Moving Around the History List
+@subsection Moving Around the History List
+
+These functions allow the current index into the history list to be
+set or changed.
+
+@deftypefun int history_set_pos (int pos)
+Set the position in the history list to @var{pos}, an absolute index
+into the list.
+@end deftypefun
+
+@deftypefun {HIST_ENTRY *} previous_history ()
+Back up the current history offset to the previous history entry, and
+return a pointer to that entry.  If there is no previous entry, return
+a @code{NULL} pointer.
+@end deftypefun
+
+@deftypefun {HIST_ENTRY *} next_history ()
+Move the current history offset forward to the next history entry, and
+return the a pointer to that entry.  If there is no next entry, return
+a @code{NULL} pointer.
+@end deftypefun
+
+@node Searching the History List
+@subsection Searching the History List
+@cindex History Searching
+
+These functions allow searching of the history list for entries containing
+a specific string.  Searching may be performed both forward and backward
+from the current history position.  The search may be @dfn{anchored},
+meaning that the string must match at the beginning of the history entry.
+@cindex anchored search
+
+@deftypefun int history_search (char *string, int direction)
+Search the history for @var{string}, starting at the current history
+offset.  If @var{direction} < 0, then the search is through previous entries,
+else through subsequent.  If @var{string} is found, then
+the current history index is set to that history entry, and the value
+returned is the offset in the line of the entry where
+@var{string} was found.  Otherwise, nothing is changed, and a -1 is
+returned.
+@end deftypefun
+
+@deftypefun int history_search_prefix (char *string, int direction)
+Search the history for @var{string}, starting at the current history
+offset.  The search is anchored: matching lines must begin with
+@var{string}.  If @var{direction} < 0, then the search is through previous
+entries, else through subsequent.  If @var{string} is found, then the
+current history index is set to that entry, and the return value is 0. 
+Otherwise, nothing is changed, and a -1 is returned. 
+@end deftypefun
+
+@deftypefun int history_search_pos (char *string, int direction, int pos)
+Search for @var{string} in the history list, starting at @var{pos}, an
+absolute index into the list.  If @var{direction} is negative, the search
+proceeds backward from @var{pos}, otherwise forward.  Returns the absolute
+index of the history element where @var{string} was found, or -1 otherwise.
+@end deftypefun
+
+@node Managing the History File
+@subsection Managing the History File
+
+The History library can read the history from and write it to a file.
+This section documents the functions for managing a history file.
+
+@deftypefun int read_history (char *filename)
+Add the contents of @var{filename} to the history list, a line at a
+time.  If @var{filename} is @code{NULL}, then read from
+@file{~/.history}.  Returns 0 if successful, or errno if not.
+@end deftypefun
+
+@deftypefun int read_history_range (char *filename, int from, int to)
+Read a range of lines from @var{filename}, adding them to the history list.
+Start reading at line @var{from} and end at @var{to}.  If
+@var{from} is zero, start at the beginning.  If @var{to} is less than
+@var{from}, then read until the end of the file.  If @var{filename} is
+@code{NULL}, then read from @file{~/.history}.  Returns 0 if successful,
+or @code{errno} if not.
+@end deftypefun
+
+@deftypefun int write_history (char *filename)
+Write the current history to @var{filename}, overwriting @var{filename}
+if necessary.  If @var{filename} is
+@code{NULL}, then write the history list to @file{~/.history}.  Values
+returned are as in @code{read_history ()}.
+@end deftypefun
+
+@deftypefun int append_history (int nelements, char *filename)
+Append the last @var{nelements} of the history list to @var{filename}.
+@end deftypefun
+
+@deftypefun int history_truncate_file (char *filename, int nlines)
+Truncate the history file @var{filename}, leaving only the last
+@var{nlines} lines.
+@end deftypefun
+
+@node History Expansion
+@subsection History Expansion
+
+These functions implement @code{csh}-like history expansion.
+
+@deftypefun int history_expand (char *string, char **output)
+Expand @var{string}, placing the result into @var{output}, a pointer
+to a string (@pxref{History Interaction}).  Returns:
+@table @code
+@item 0
+If no expansions took place (or, if the only change in
+the text was the de-slashifying of the history expansion
+character);
+@item 1
+if expansions did take place;
+@item -1
+if there was an error in expansion;
+@item 2
+if the returned line should only be displayed, but not executed,
+as with the @code{:p} modifier (@pxref{Modifiers}).
+@end table
+
+If an error ocurred in expansion, then @var{output} contains a descriptive
+error message.
+@end deftypefun
+
+@deftypefun {char *} history_arg_extract (int first, int last, char *string)
+Extract a string segment consisting of the @var{first} through @var{last}
+arguments present in @var{string}.  Arguments are broken up as in Bash.
+@end deftypefun
+
+@deftypefun {char *} get_history_event (char *string, int *cindex, int qchar)
+Returns the text of the history event beginning at @var{string} +
+@var{*cindex}.  @var{*cindex} is modified to point to after the event
+specifier.  At function entry, @var{cindex} points to the index into
+@var{string} where the history event specification begins.  @var{qchar}
+is a character that is allowed to end the event specification in addition
+to the ``normal'' terminating characters.
+@end deftypefun
+
+@deftypefun {char **} history_tokenize (char *string)
+Return an array of tokens parsed out of @var{string}, much as the
+shell might.  The tokens are split on white space and on the
+characters @code{()<>;&|$}, and shell quoting conventions are
+obeyed.
+@end deftypefun
+
+@node History Variables
+@section History Variables
+
+This section describes the externally visible variables exported by
+the GNU History Library.
+
+@deftypevar int history_base
+The logical offset of the first entry in the history list.
+@end deftypevar
+
+@deftypevar int history_length
+The number of entries currently stored in the history list.
+@end deftypevar
+
+@deftypevar int max_input_history
+The maximum number of history entries.  This must be changed using
+@code{stifle_history ()}.
+@end deftypevar
+
+@deftypevar char history_expansion_char
+The character that starts a history event.  The default is @samp{!}.
+@end deftypevar
+
+@deftypevar char history_subst_char
+The character that invokes word substitution if found at the start of
+a line.  The default is @samp{^}.
+@end deftypevar
+
+@deftypevar char history_comment_char
+During tokenization, if this character is seen as the first character
+of a word, then it and all subsequent characters up to a newline are
+ignored, suppressing history expansion for the remainder of the line.
+This is disabled by default.
+@end deftypevar
+
+@deftypevar {char *} history_no_expand_chars
+The list of characters which inhibit history expansion if found immediately
+following @var{history_expansion_char}.  The default is whitespace and
+@samp{=}.
+@end deftypevar
+
+@node History Programming Example
+@section History Programming Example
+
+The following program demonstrates simple use of the GNU History Library.
+
+@smallexample
+main ()
+@{
+  char line[1024], *t;
+  int len, done = 0;
+
+  line[0] = 0;
+
+  using_history ();
+  while (!done)
+    @{
+      printf ("history$ ");
+      fflush (stdout);
+      t = fgets (line, sizeof (line) - 1, stdin);
+      if (t && *t)
+        @{
+          len = strlen (t);
+          if (t[len - 1] == '\n')
+            t[len - 1] = '\0';
+        @}
+
+      if (!t)
+        strcpy (line, "quit");
+
+      if (line[0])
+        @{
+          char *expansion;
+          int result;
+
+          result = history_expand (line, &expansion);
+          if (result)
+            fprintf (stderr, "%s\n", expansion);
+
+          if (result < 0 || result == 2)
+            @{
+              free (expansion);
+              continue;
+            @}
+
+          add_history (expansion);
+          strncpy (line, expansion, sizeof (line) - 1);
+          free (expansion);
+        @}
+
+      if (strcmp (line, "quit") == 0)
+        done = 1;
+      else if (strcmp (line, "save") == 0)
+        write_history ("history_file");
+      else if (strcmp (line, "read") == 0)
+        read_history ("history_file");
+      else if (strcmp (line, "list") == 0)
+        @{
+          register HIST_ENTRY **the_list;
+          register int i;
+
+          the_list = history_list ();
+          if (the_list)
+            for (i = 0; the_list[i]; i++)
+              printf ("%d: %s\n", i + history_base, the_list[i]->line);
+        @}
+      else if (strncmp (line, "delete", 6) == 0)
+        @{
+          int which;
+          if ((sscanf (line + 6, "%d", &which)) == 1)
+            @{
+              HIST_ENTRY *entry = remove_history (which);
+              if (!entry)
+                fprintf (stderr, "No such entry %d\n", which);
+              else
+                @{
+                  free (entry->line);
+                  free (entry);
+                @}
+            @}
+          else
+            @{
+              fprintf (stderr, "non-numeric arg given to `delete'\n");
+            @}
+        @}
+    @}
+@}
+@end smallexample
diff --git a/lib/readline/doc/hsuser.texinfo b/lib/readline/doc/hsuser.texinfo
new file mode 100644 (file)
index 0000000..51327a3
--- /dev/null
@@ -0,0 +1,198 @@
+@ignore
+This file documents the user interface to the GNU History library.
+
+Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+Authored by Brian Fox and Chet Ramey.
+
+Permission is granted to make and distribute verbatim copies of this manual
+provided the copyright notice and this permission notice are preserved on
+all copies.
+
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+GNU Copyright statement is available to the distributee, and provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ignore
+
+@node Using History Interactively
+@chapter Using History Interactively
+
+@ifset BashFeatures
+This chapter describes how to use the GNU History Library interactively,
+from a user's standpoint.  It should be considered a user's guide.  For
+information on using the GNU History Library in your own programs,
+see the GNU Readline Library Manual.
+@end ifset
+@ifclear BashFeatures
+This chapter describes how to use the GNU History Library interactively,
+from a user's standpoint.  It should be considered a user's guide.  For
+information on using the GNU History Library in your own programs,
+@pxref{Programming with GNU History}.
+@end ifclear
+
+@menu
+* History Interaction::                What it feels like using History as a user.
+@end menu
+
+@node History Interaction
+@section History Interaction
+@cindex expansion
+
+The History library provides a history expansion feature that is similar
+to the history expansion provided by @code{csh}.  The following text
+describes the syntax used to manipulate the history information.
+
+History expansion takes place in two parts.  The first is to determine
+which line from the previous history should be used during substitution.
+The second is to select portions of that line for inclusion into the
+current one.  The line selected from the previous history is called the
+@dfn{event}, and the portions of that line that are acted upon are
+called @dfn{words}.  The line is broken into words in the same fashion
+that Bash does, so that several English (or Unix) words
+surrounded by quotes are considered as one word.
+
+@menu
+* Event Designators::  How to specify which history line to use.
+* Word Designators::   Specifying which words are of interest.
+* Modifiers::          Modifying the results of substitution.
+@end menu
+
+@node Event Designators
+@subsection Event Designators
+@cindex event designators
+
+An event designator is a reference to a command line entry in the
+history list.
+@cindex history events
+
+@table @asis
+
+@item @code{!}
+Start a history substitution, except when followed by a space, tab,
+the end of the line, @key{=} or @key{(}.
+
+@item @code{!!}
+Refer to the previous command.  This is a synonym for @code{!-1}.
+
+@item @code{!n}
+Refer to command line @var{n}.
+
+@item @code{!-n}
+Refer to the command @var{n} lines back.
+
+@item @code{!string}
+Refer to the most recent command starting with @var{string}.
+
+@item @code{!?string}[@code{?}]
+Refer to the most recent command containing @var{string}.
+
+@item @code{!#}
+The entire command line typed so far.
+
+@item @code{^string1^string2^}
+Quick Substitution.  Repeat the last command, replacing @var{string1}
+with @var{string2}.  Equivalent to
+@code{!!:s/string1/string2/}.
+
+@end table
+
+@node Word Designators
+@subsection Word Designators
+
+A @key{:} separates the event specification from the word designator.  It
+can be omitted if the word designator begins with a @key{^}, @key{$},
+@key{*} or @key{%}.  Words are numbered from the beginning of the line,
+with the first word being denoted by a 0 (zero).
+
+@table @code
+
+@item 0 (zero)
+The @code{0}th word.  For many applications, this is the command word.
+
+@item n
+The @var{n}th word.
+
+@item ^
+The first argument;  that is, word 1.
+
+@item $
+The last argument.
+
+@item %
+The word matched by the most recent @code{?string?} search.
+
+@item x-y
+A range of words; @code{-@var{y}} abbreviates @code{0-@var{y}}.
+
+@item *
+All of the words, except the @code{0}th.  This is a synonym for @code{1-$}.
+It is not an error to use @key{*} if there is just one word in the event;
+the empty string is returned in that case.
+
+@item x*
+Abbreviates @code{x-$}
+
+@item x-
+Abbreviates @code{x-$} like @code{x*}, but omits the last word.
+
+@end table
+
+@node Modifiers
+@subsection Modifiers
+
+After the optional word designator, you can add a sequence of one or more
+of the following modifiers, each preceded by a @key{:}.
+
+@table @code
+
+@item h
+Remove a trailing pathname component, leaving only the head.
+
+@item r
+Remove a trailing suffix of the form @samp{.}@var{suffix}, leaving the basename.
+
+@item e
+Remove all but the trailing suffix.
+
+@item t
+Remove all leading  pathname  components, leaving the tail.
+
+@item p
+Print the new command but do not execute it.
+
+@ifset BashFeatures
+@item q
+Quote the substituted words, escaping further substitutions.
+
+@item x
+Quote the substituted words as with @code{q},         
+but break into words at spaces, tabs, and newlines.
+@end ifset
+
+@item s/old/new/
+Substitute @var{new} for the first occurrence of @var{old} in the
+event line.  Any delimiter may be used in place of @key{/}.
+The delimiter may be quoted in @var{old} and @var{new}
+with a single backslash.  If @key{&} appears in @var{new},
+it is replaced by @var{old}.  A single backslash will quote
+the @key{&}.  The final delimiter is optional if it is the last
+character on the input line.
+
+@item &
+Repeat the previous substitution.
+
+@item g
+Cause changes to be applied over the entire event line.  Used in
+conjunction with @code{s}, as in @code{gs/old/new/}, or with
+@code{&}.
+
+@end table
diff --git a/lib/readline/doc/readline.dvi b/lib/readline/doc/readline.dvi
new file mode 100644 (file)
index 0000000..aea321a
Binary files /dev/null and b/lib/readline/doc/readline.dvi differ
diff --git a/lib/readline/doc/readline.info b/lib/readline/doc/readline.info
new file mode 100644 (file)
index 0000000..6df0bd9
--- /dev/null
@@ -0,0 +1,744 @@
+This is Info file history.info, produced by Makeinfo-1.55 from the
+input file hist.texinfo.
+
+   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, 1991 Free Software Foundation, Inc.
+
+   Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice pare
+preserved on all copies.
+
+   Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+   Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+\1f
+File: history.info,  Node: Top,  Next: Using History Interactively,  Prev: (DIR),  Up: (DIR)
+
+GNU History Library
+*******************
+
+   This document describes the GNU History library, a programming tool
+that provides a consistent user interface for recalling lines of
+previously typed input.
+
+* Menu:
+
+* Using History Interactively::          GNU History User's Manual.
+* Programming with GNU History::  GNU History Programmer's Manual.
+* Concept Index::                Index of concepts described in this manual.
+* Function and Variable Index::          Index of externally visible functions
+                                 and variables.
+
+\1f
+File: history.info,  Node: Using History Interactively,  Next: Programming with GNU History,  Prev: Top,  Up: Top
+
+Using History Interactively
+***************************
+
+   This chapter describes how to use the GNU History Library
+interactively, from a user's standpoint.  It should be considered a
+user's guide.  For information on using the GNU History Library in your
+own programs, *note Programming with GNU History::..
+
+* Menu:
+
+* History Interaction::                What it feels like using History as a user.
+
+\1f
+File: history.info,  Node: History Interaction,  Up: Using History Interactively
+
+History Interaction
+===================
+
+   The History library provides a history expansion feature that is
+similar to the history expansion provided by `csh'.  The following text
+describes the syntax used to manipulate the history information.
+
+   History expansion takes place in two parts.  The first is to
+determine which line from the previous history should be used during
+substitution.  The second is to select portions of that line for
+inclusion into the current one.  The line selected from the previous
+history is called the "event", and the portions of that line that are
+acted upon are called "words".  The line is broken into words in the
+same fashion that Bash does, so that several English (or Unix) words
+surrounded by quotes are considered as one word.
+
+* Menu:
+
+* Event Designators::  How to specify which history line to use.
+* Word Designators::   Specifying which words are of interest.
+* Modifiers::          Modifying the results of substitution.
+
+\1f
+File: history.info,  Node: Event Designators,  Next: Word Designators,  Up: History Interaction
+
+Event Designators
+-----------------
+
+   An event designator is a reference to a command line entry in the
+history list.
+
+`!'
+     Start a history substitution, except when followed by a space, tab,
+     the end of the line, = or (.
+
+`!!'
+     Refer to the previous command.  This is a synonym for `!-1'.
+
+`!n'
+     Refer to command line N.
+
+`!-n'
+     Refer to the command N lines back.
+
+`!string'
+     Refer to the most recent command starting with STRING.
+
+`!?string'[`?']
+     Refer to the most recent command containing STRING.
+
+`!#'
+     The entire command line typed so far.
+
+`^string1^string2^'
+     Quick Substitution.  Repeat the last command, replacing STRING1
+     with STRING2.  Equivalent to `!!:s/string1/string2/'.
+
+\1f
+File: history.info,  Node: Word Designators,  Next: Modifiers,  Prev: Event Designators,  Up: History Interaction
+
+Word Designators
+----------------
+
+   A : separates the event specification from the word designator.  It
+can be omitted if the word designator begins with a ^, $, * or %.
+Words are numbered from the beginning of the line, with the first word
+being denoted by a 0 (zero).
+
+`0 (zero)'
+     The `0'th word.  For many applications, this is the command word.
+
+`n'
+     The Nth word.
+
+`^'
+     The first argument;  that is, word 1.
+
+`$'
+     The last argument.
+
+`%'
+     The word matched by the most recent `?string?' search.
+
+`x-y'
+     A range of words; `-Y' abbreviates `0-Y'.
+
+`*'
+     All of the words, except the `0'th.  This is a synonym for `1-$'.
+     It is not an error to use * if there is just one word in the event;
+     the empty string is returned in that case.
+
+`x*'
+     Abbreviates `x-$'
+
+`x-'
+     Abbreviates `x-$' like `x*', but omits the last word.
+
+\1f
+File: history.info,  Node: Modifiers,  Prev: Word Designators,  Up: History Interaction
+
+Modifiers
+---------
+
+   After the optional word designator, you can add a sequence of one or
+more of the following modifiers, each preceded by a :.
+
+`h'
+     Remove a trailing pathname component, leaving only the head.
+
+`r'
+     Remove a trailing suffix of the form `.'SUFFIX, leaving the
+     basename.
+
+`e'
+     Remove all but the trailing suffix.
+
+`t'
+     Remove all leading  pathname  components, leaving the tail.
+
+`p'
+     Print the new command but do not execute it.
+
+`s/old/new/'
+     Substitute NEW for the first occurrence of OLD in the event line.
+     Any delimiter may be used in place of /.  The delimiter may be
+     quoted in OLD and NEW with a single backslash.  If & appears in
+     NEW, it is replaced by OLD.  A single backslash will quote the &.
+     The final delimiter is optional if it is the last character on the
+     input line.
+
+`&'
+     Repeat the previous substitution.
+
+`g'
+     Cause changes to be applied over the entire event line.  Used in
+     conjunction with `s', as in `gs/old/new/', or with `&'.
+
+\1f
+File: history.info,  Node: Programming with GNU History,  Next: Concept Index,  Prev: Using History Interactively,  Up: Top
+
+Programming with GNU History
+****************************
+
+   This chapter describes how to interface programs that you write with
+the GNU History Library.  It should be considered a technical guide.
+For information on the interactive use of GNU History, *note Using
+History Interactively::..
+
+* Menu:
+
+* Introduction to History::    What is the GNU History library for?
+* History Storage::            How information is stored.
+* History Functions::          Functions that you can use.
+* History Variables::          Variables that control behaviour.
+* History Programming Example::        Example of using the GNU History Library.
+
+\1f
+File: history.info,  Node: Introduction to History,  Next: History Storage,  Up: Programming with GNU History
+
+Introduction to History
+=======================
+
+   Many programs read input from the user a line at a time.  The GNU
+History library is able to keep track of those lines, associate
+arbitrary data with each line, and utilize information from previous
+lines in composing new ones.
+
+   The programmer using the History library has available functions for
+remembering lines on a history list, associating arbitrary data with a
+line, removing lines from the list, searching through the list for a
+line containing an arbitrary text string, and referencing any line in
+the list directly.  In addition, a history "expansion" function is
+available which provides for a consistent user interface across
+different programs.
+
+   The user using programs written with the History library has the
+benefit of a consistent user interface with a set of well-known
+commands for manipulating the text of previous lines and using that text
+in new commands.  The basic history manipulation commands are similar to
+the history substitution provided by `csh'.
+
+   If the programmer desires, he can use the Readline library, which
+includes some history manipulation by default, and has the added
+advantage of command line editing.
+
+\1f
+File: history.info,  Node: History Storage,  Next: History Functions,  Prev: Introduction to History,  Up: Programming with GNU History
+
+History Storage
+===============
+
+   The history list is an array of history entries.  A history entry is
+declared as follows:
+
+     typedef struct _hist_entry {
+       char *line;
+       char *data;
+     } HIST_ENTRY;
+
+   The history list itself might therefore be declared as
+
+     HIST_ENTRY **the_history_list;
+
+   The state of the History library is encapsulated into a single
+structure:
+
+     /* A structure used to pass the current state of the history stuff around. */
+     typedef struct _hist_state {
+       HIST_ENTRY **entries;         /* Pointer to the entries themselves. */
+       int offset;                   /* The location pointer within this array. */
+       int length;                   /* Number of elements within this array. */
+       int size;                     /* Number of slots allocated to this array. */
+       int flags;
+     } HISTORY_STATE;
+
+   If the flags member includes `HS_STIFLED', the history has been
+stifled.
+
+\1f
+File: history.info,  Node: History Functions,  Next: History Variables,  Prev: History Storage,  Up: Programming with GNU History
+
+History Functions
+=================
+
+   This section describes the calling sequence for the various functions
+present in GNU History.
+
+* Menu:
+
+* Initializing History and State Management::  Functions to call when you
+                                               want to use history in a
+                                               program.
+* History List Management::            Functions used to manage the list
+                                       of history entries.
+* Information About the History List:: Functions returning information about
+                                       the history list.
+* Moving Around the History List::     Functions used to change the position
+                                       in the history list.
+* Searching the History List::         Functions to search the history list
+                                       for entries containing a string.
+* Managing the History File::          Functions that read and write a file
+                                       containing the history list.
+* History Expansion::                  Functions to perform csh-like history
+                                       expansion.
+
+\1f
+File: history.info,  Node: Initializing History and State Management,  Next: History List Management,  Up: History Functions
+
+Initializing History and State Management
+-----------------------------------------
+
+   This section describes functions used to initialize and manage the
+state of the History library when you want to use the history functions
+in your program.
+
+ - Function: void using_history ()
+     Begin a session in which the history functions might be used.  This
+     initializes the interactive variables.
+
+ - Function: HISTORY_STATE * history_get_history_state ()
+     Return a structure describing the current state of the input
+     history.
+
+ - Function: void history_set_history_state (HISTORY_STATE *state)
+     Set the state of the history list according to STATE.
+
+\1f
+File: history.info,  Node: History List Management,  Next: Information About the History List,  Prev: Initializing History and State Management,  Up: History Functions
+
+History List Management
+-----------------------
+
+   These functions manage individual entries on the history list, or set
+parameters managing the list itself.
+
+ - Function: void add_history (char *string)
+     Place STRING at the end of the history list.  The associated data
+     field (if any) is set to `NULL'.
+
+ - Function: HIST_ENTRY * remove_history (int which)
+     Remove history entry at offset WHICH from the history.  The
+     removed element is returned so you can free the line, data, and
+     containing structure.
+
+ - Function: HIST_ENTRY * replace_history_entry (int which, char *line,
+          char *data)
+     Make the history entry at offset WHICH have LINE and DATA.  This
+     returns the old entry so you can dispose of the data.  In the case
+     of an invalid WHICH, a `NULL' pointer is returned.
+
+ - Function: void stifle_history (int max)
+     Stifle the history list, remembering only the last MAX entries.
+
+ - Function: int unstifle_history ()
+     Stop stifling the history.  This returns the previous amount the
+     history was stifled.  The value is positive if the history was
+     stifled, negative if it wasn't.
+
+ - Function: int history_is_stifled ()
+     Returns non-zero if the history is stifled, zero if it is not.
+
+\1f
+File: history.info,  Node: Information About the History List,  Next: Moving Around the History List,  Prev: History List Management,  Up: History Functions
+
+Information About the History List
+----------------------------------
+
+   These functions return information about the entire history list or
+individual list entries.
+
+ - Function: HIST_ENTRY ** history_list ()
+     Return a `NULL' terminated array of `HIST_ENTRY' which is the
+     current input history.  Element 0 of this list is the beginning of
+     time.  If there is no history, return `NULL'.
+
+ - Function: int where_history ()
+     Returns the offset of the current history element.
+
+ - Function: HIST_ENTRY * current_history ()
+     Return the history entry at the current position, as determined by
+     `where_history ()'.  If there is no entry there, return a `NULL'
+     pointer.
+
+ - Function: HIST_ENTRY * history_get (int offset)
+     Return the history entry at position OFFSET, starting from
+     `history_base'.  If there is no entry there, or if OFFSET is
+     greater than the history length, return a `NULL' pointer.
+
+ - Function: int history_total_bytes ()
+     Return the number of bytes that the primary history entries are
+     using.  This function returns the sum of the lengths of all the
+     lines in the history.
+
+\1f
+File: history.info,  Node: Moving Around the History List,  Next: Searching the History List,  Prev: Information About the History List,  Up: History Functions
+
+Moving Around the History List
+------------------------------
+
+   These functions allow the current index into the history list to be
+set or changed.
+
+ - Function: int history_set_pos (int pos)
+     Set the position in the history list to POS, an absolute index
+     into the list.
+
+ - Function: HIST_ENTRY * previous_history ()
+     Back up the current history offset to the previous history entry,
+     and return a pointer to that entry.  If there is no previous
+     entry, return a `NULL' pointer.
+
+ - Function: HIST_ENTRY * next_history ()
+     Move the current history offset forward to the next history entry,
+     and return the a pointer to that entry.  If there is no next
+     entry, return a `NULL' pointer.
+
+\1f
+File: history.info,  Node: Searching the History List,  Next: Managing the History File,  Prev: Moving Around the History List,  Up: History Functions
+
+Searching the History List
+--------------------------
+
+   These functions allow searching of the history list for entries
+containing a specific string.  Searching may be performed both forward
+and backward from the current history position.  The search may be
+"anchored", meaning that the string must match at the beginning of the
+history entry.
+
+ - Function: int history_search (char *string, int direction)
+     Search the history for STRING, starting at the current history
+     offset.  If DIRECTION < 0, then the search is through previous
+     entries, else through subsequent.  If STRING is found, then the
+     current history index is set to that history entry, and the value
+     returned is the offset in the line of the entry where STRING was
+     found.  Otherwise, nothing is changed, and a -1 is returned.
+
+ - Function: int history_search_prefix (char *string, int direction)
+     Search the history for STRING, starting at the current history
+     offset.  The search is anchored: matching lines must begin with
+     STRING.  If DIRECTION < 0, then the search is through previous
+     entries, else through subsequent.  If STRING is found, then the
+     current history index is set to that entry, and the return value
+     is 0.  Otherwise, nothing is changed, and a -1 is returned.
+
+ - Function: int history_search_pos (char *string, int direction, int
+          pos)
+     Search for STRING in the history list, starting at POS, an
+     absolute index into the list.  If DIRECTION is negative, the search
+     proceeds backward from POS, otherwise forward.  Returns the
+     absolute index of the history element where STRING was found, or
+     -1 otherwise.
+
+\1f
+File: history.info,  Node: Managing the History File,  Next: History Expansion,  Prev: Searching the History List,  Up: History Functions
+
+Managing the History File
+-------------------------
+
+   The History library can read the history from and write it to a file.
+This section documents the functions for managing a history file.
+
+ - Function: int read_history (char *filename)
+     Add the contents of FILENAME to the history list, a line at a
+     time.  If FILENAME is `NULL', then read from `~/.history'.
+     Returns 0 if successful, or errno if not.
+
+ - Function: int read_history_range (char *filename, int from, int to)
+     Read a range of lines from FILENAME, adding them to the history
+     list.  Start reading at line FROM and end at TO.  If FROM is zero,
+     start at the beginning.  If TO is less than FROM, then read until
+     the end of the file.  If FILENAME is `NULL', then read from
+     `~/.history'.  Returns 0 if successful, or `errno' if not.
+
+ - Function: int write_history (char *filename)
+     Write the current history to FILENAME, overwriting FILENAME if
+     necessary.  If FILENAME is `NULL', then write the history list to
+     `~/.history'.  Values returned are as in `read_history ()'.
+
+ - Function: int append_history (int nelements, char *filename)
+     Append the last NELEMENTS of the history list to FILENAME.
+
+ - Function: int history_truncate_file (char *filename, int nlines)
+     Truncate the history file FILENAME, leaving only the last NLINES
+     lines.
+
+\1f
+File: history.info,  Node: History Expansion,  Prev: Managing the History File,  Up: History Functions
+
+History Expansion
+-----------------
+
+   These functions implement `csh'-like history expansion.
+
+ - Function: int history_expand (char *string, char **output)
+     Expand STRING, placing the result into OUTPUT, a pointer to a
+     string (*note History Interaction::.).  Returns:
+    `0'
+          If no expansions took place (or, if the only change in the
+          text was the de-slashifying of the history expansion
+          character);
+
+    `1'
+          if expansions did take place;
+
+    `-1'
+          if there was an error in expansion;
+
+    `2'
+          if the returned line should only be displayed, but not
+          executed, as with the `:p' modifier (*note Modifiers::.).
+
+     If an error ocurred in expansion, then OUTPUT contains a
+     descriptive error message.
+
+ - Function: char * history_arg_extract (int first, int last, char
+          *string)
+     Extract a string segment consisting of the FIRST through LAST
+     arguments present in STRING.  Arguments are broken up as in Bash.
+
+ - Function: char * get_history_event (char *string, int *cindex, int
+          qchar)
+     Returns the text of the history event beginning at STRING +
+     *CINDEX.  *CINDEX is modified to point to after the event
+     specifier.  At function entry, CINDEX points to the index into
+     STRING where the history event specification begins.  QCHAR is a
+     character that is allowed to end the event specification in
+     addition to the "normal" terminating characters.
+
+ - Function: char ** history_tokenize (char *string)
+     Return an array of tokens parsed out of STRING, much as the shell
+     might.  The tokens are split on white space and on the characters
+     `()<>;&|$', and shell quoting conventions are obeyed.
+
+\1f
+File: history.info,  Node: History Variables,  Next: History Programming Example,  Prev: History Functions,  Up: Programming with GNU History
+
+History Variables
+=================
+
+   This section describes the externally visible variables exported by
+the GNU History Library.
+
+ - Variable: int history_base
+     The logical offset of the first entry in the history list.
+
+ - Variable: int history_length
+     The number of entries currently stored in the history list.
+
+ - Variable: int max_input_history
+     The maximum number of history entries.  This must be changed using
+     `stifle_history ()'.
+
+ - Variable: char history_expansion_char
+     The character that starts a history event.  The default is `!'.
+
+ - Variable: char history_subst_char
+     The character that invokes word substitution if found at the start
+     of a line.  The default is `^'.
+
+ - Variable: char history_comment_char
+     During tokenization, if this character is seen as the first
+     character of a word, then it and all subsequent characters up to a
+     newline are ignored, suppressing history expansion for the
+     remainder of the line.  This is disabled by default.
+
+ - Variable: char * history_no_expand_chars
+     The list of characters which inhibit history expansion if found
+     immediately following HISTORY_EXPANSION_CHAR.  The default is
+     whitespace and `='.
+
+\1f
+File: history.info,  Node: History Programming Example,  Prev: History Variables,  Up: Programming with GNU History
+
+History Programming Example
+===========================
+
+   The following program demonstrates simple use of the GNU History
+Library.
+
+     main ()
+     {
+       char line[1024], *t;
+       int len, done = 0;
+     
+       line[0] = 0;
+     
+       using_history ();
+       while (!done)
+         {
+           printf ("history$ ");
+           fflush (stdout);
+           t = fgets (line, sizeof (line) - 1, stdin);
+           if (t && *t)
+             {
+               len = strlen (t);
+               if (t[len - 1] == '\n')
+                 t[len - 1] = '\0';
+             }
+     
+           if (!t)
+             strcpy (line, "quit");
+     
+           if (line[0])
+             {
+               char *expansion;
+               int result;
+     
+               result = history_expand (line, &expansion);
+               if (result)
+                 fprintf (stderr, "%s\n", expansion);
+     
+               if (result < 0 || result == 2)
+                 {
+                   free (expansion);
+                   continue;
+                 }
+     
+               add_history (expansion);
+               strncpy (line, expansion, sizeof (line) - 1);
+               free (expansion);
+             }
+     
+           if (strcmp (line, "quit") == 0)
+             done = 1;
+           else if (strcmp (line, "save") == 0)
+             write_history ("history_file");
+           else if (strcmp (line, "read") == 0)
+             read_history ("history_file");
+           else if (strcmp (line, "list") == 0)
+             {
+               register HIST_ENTRY **the_list;
+               register int i;
+     
+               the_list = history_list ();
+               if (the_list)
+                 for (i = 0; the_list[i]; i++)
+                   printf ("%d: %s\n", i + history_base, the_list[i]->line);
+             }
+           else if (strncmp (line, "delete", 6) == 0)
+             {
+               int which;
+               if ((sscanf (line + 6, "%d", &which)) == 1)
+                 {
+                   HIST_ENTRY *entry = remove_history (which);
+                   if (!entry)
+                     fprintf (stderr, "No such entry %d\n", which);
+                   else
+                     {
+                       free (entry->line);
+                       free (entry);
+                     }
+                 }
+               else
+                 {
+                   fprintf (stderr, "non-numeric arg given to `delete'\n");
+                 }
+             }
+         }
+     }
+
+\1f
+File: history.info,  Node: Concept Index,  Next: Function and Variable Index,  Prev: Programming with GNU History,  Up: Top
+
+Concept Index
+*************
+
+* Menu:
+
+* anchored search:                      Searching the History List.
+* event designators:                    Event Designators.
+* expansion:                            History Interaction.
+* history events:                       Event Designators.
+* History Searching:                    Searching the History List.
+
+\1f
+File: history.info,  Node: Function and Variable Index,  Prev: Concept Index,  Up: Top
+
+Function and Variable Index
+***************************
+
+* Menu:
+
+* add_history:                          History List Management.
+* append_history:                       Managing the History File.
+* current_history:                      Information About the History List.
+* get_history_event:                    History Expansion.
+* history_arg_extract:                  History Expansion.
+* history_base:                         History Variables.
+* history_comment_char:                 History Variables.
+* history_expand:                       History Expansion.
+* history_expansion_char:               History Variables.
+* history_get:                          Information About the History List.
+* history_get_history_state:            Initializing History and State Management.
+* history_is_stifled:                   History List Management.
+* history_length:                       History Variables.
+* history_list:                         Information About the History List.
+* history_no_expand_chars:              History Variables.
+* history_search:                       Searching the History List.
+* history_search_pos:                   Searching the History List.
+* history_search_prefix:                Searching the History List.
+* history_set_history_state:            Initializing History and State Management.
+* history_set_pos:                      Moving Around the History List.
+* history_subst_char:                   History Variables.
+* history_tokenize:                     History Expansion.
+* history_total_bytes:                  Information About the History List.
+* history_truncate_file:                Managing the History File.
+* max_input_history:                    History Variables.
+* next_history:                         Moving Around the History List.
+* previous_history:                     Moving Around the History List.
+* read_history:                         Managing the History File.
+* read_history_range:                   Managing the History File.
+* remove_history:                       History List Management.
+* replace_history_entry:                History List Management.
+* stifle_history:                       History List Management.
+* unstifle_history:                     History List Management.
+* using_history:                        Initializing History and State Management.
+* where_history:                        Information About the History List.
+* write_history:                        Managing the History File.
+
+
+\1f
+Tag Table:
+Node: Top\7f975
+Node: Using History Interactively\7f1569
+Node: History Interaction\7f2077
+Node: Event Designators\7f3122
+Node: Word Designators\7f3952
+Node: Modifiers\7f4936
+Node: Programming with GNU History\7f6065
+Node: Introduction to History\7f6791
+Node: History Storage\7f8112
+Node: History Functions\7f9205
+Node: Initializing History and State Management\7f10176
+Node: History List Management\7f10968
+Node: Information About the History List\7f12396
+Node: Moving Around the History List\7f13702
+Node: Searching the History List\7f14587
+Node: Managing the History File\7f16419
+Node: History Expansion\7f17925
+Node: History Variables\7f19769
+Node: History Programming Example\7f21138
+Node: Concept Index\7f23742
+Node: Function and Variable Index\7f24223
+\1f
+End Tag Table
diff --git a/lib/readline/doc/readline.ps b/lib/readline/doc/readline.ps
new file mode 100644 (file)
index 0000000..839598f
--- /dev/null
@@ -0,0 +1,2037 @@
+%!PS-Adobe-2.0
+%%Creator: dvipsk 5.490s Copyright 1986, 1992 Radical Eye Software
+%%Title: history.dvi
+%%Pages: 22 1
+%%BoundingBox: 0 0 612 792
+%%EndComments
+%DVIPSCommandLine: dvips -D 300 -o history.ps history.dvi
+%%BeginProcSet: tex.pro
+%!
+/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N /X{S N}
+B /TR{translate}N /isls false N /vsize 11 72 mul N /@rigin{isls{[0 -1 1 0 0 0]
+concat}if 72 Resolution div 72 VResolution div neg scale isls{Resolution hsize
+-72 div mul 0 TR}if Resolution VResolution vsize -72 div 1 add mul TR matrix
+currentmatrix dup dup 4 get round 4 exch put dup dup 5 get round 5 exch put
+setmatrix}N /@landscape{/isls true N}B /@manualfeed{statusdict /manualfeed
+true put}B /@copies{/#copies X}B /FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N
+/IE 0 N /ctr 0 N /df-tail{/nn 8 dict N nn begin /FontType 3 N /FontMatrix
+fntrx N /FontBBox FBB N string /base X array /BitMaps X /BuildChar{
+CharBuilder}N /Encoding IE N end dup{/foo setfont}2 array copy cvx N load 0 nn
+put /ctr 0 N[}B /df{/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0
+0 sf neg 0 0]N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data
+dup length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{128
+ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub get 127
+sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data dup type
+/stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N /rc 0 N /gp 0 N
+/cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup /base get 2 index get
+S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx 0 ch-xoff ch-yoff ch-height
+sub ch-xoff ch-width add ch-yoff setcachedevice ch-width ch-height true[1 0 0
+-1 -.1 ch-xoff sub ch-yoff .1 add]{ch-image}imagemask restore}B /D{/cc X dup
+type /stringtype ne{]}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1
+ne{dup dup length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}
+B /I{cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin
+0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul add
+.99 lt{/FV}{/RV}ifelse load def pop}N /eop{SI restore showpage userdict
+/eop-hook known{eop-hook}if}N /@start{userdict /start-hook known{start-hook}
+if /VResolution X /Resolution X 1000 div /DVImag X /IE 256 array N 0 1 255{IE
+S 1 string dup 0 3 index put cvn put}for 65781.76 div /vsize X 65781.76 div
+/hsize X}N /p{show}N /RMat[1 0 0 -1 0 0]N /BDot 260 string N /rulex 0 N /ruley
+0 N /v{/ruley X /rulex X V}B /V{}B /RV statusdict begin /product where{pop
+product dup length 7 ge{0 7 getinterval dup(Display)eq exch 0 4 getinterval
+(NeXT)eq or}{pop false}ifelse}{false}ifelse end{{gsave TR -.1 -.1 TR 1 1 scale
+rulex ruley false RMat{BDot}imagemask grestore}}{{gsave TR -.1 -.1 TR rulex
+ruley scale 1 1 false RMat{BDot}imagemask grestore}}ifelse B /FV{gsave
+transform round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg
+rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail{dup
+/delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M}B /d{-3 M}
+B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{4 M}B /w{0
+rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{p 1 w}B /r{p 2 w}
+B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p a}B /bos{/SS save N}B
+/eos{SS restore}B end
+%%EndProcSet
+TeXDict begin 40258431 52099146 1000 300 300 @start /Fa 1 59
+df<70F8F8F87005057C840D>58 D E /Fb 1 59 df<78FCFCFCFC7806067B8510>58
+D E /Fc 24 123 df<1FC0007FF000707800201800001C00001C0007FC001FFC003C1C00701C00
+E01C00E01C00E01C00707C003FFF800F8F8011107E8F14>97 D<FC0000FC00001C00001C00001C
+00001C00001C00001CF8001DFE001F07001E03001C03801C01C01C01C01C01C01C01C01C01C01C
+01C01C03801E03001F0E001DFC000CF8001217809614>I<03F80FFC1C1C380870006000E000E0
+00E000E00060007000380E1C1E0FFC03F00F107E8F14>I<007E00007E00000E00000E00000E00
+000E00000E0007CE000FFE001C3E00301E00700E00E00E00E00E00E00E00E00E00E00E00E00E00
+700E00301E00383E001FEFC007CFC012177F9614>I<07E00FF01C38301C700CE00EE00EFFFEFF
+FEE00060007000380E1C1E0FFC03F00F107E8F14>I<007C00FE01CE03840380038003807FFEFF
+FE0380038003800380038003800380038003800380038003807FFC7FFC0F177F9614>I<07CF00
+1FFF80383B80301800701C00701C00701C003018003838003FF00037C0007000007000003FF800
+1FFC003FFE00700F00E00380E00380E00380E003807007003C1E001FFC0007F00011197F8F14>
+I<FC0000FC00001C00001C00001C00001C00001C00001C78001DFE001F86001E07001C07001C07
+001C07001C07001C07001C07001C07001C07001C07001C0700FF8FE0FF8FE01317809614>I<03
+0007800780030000000000000000007F807F800380038003800380038003800380038003800380
+03800380FFFCFFFC0E187D9714>I<FC0000FC00001C00001C00001C00001C00001C00001DFF80
+1DFF801C3C001C78001CF0001DE0001FC0001FC0001FE0001EF0001C70001C38001C38001C1C00
+FE3F80FE3F8011177F9614>107 D<FF80FF800380038003800380038003800380038003800380
+038003800380038003800380038003800380FFFEFFFE0F177E9614>I<FB8E00FFDF003CF3803C
+F38038E38038E38038E38038E38038E38038E38038E38038E38038E38038E380FEFBE0FE79E013
+10808F14>I<FC7800FDFE001F86001E07001C07001C07001C07001C07001C07001C07001C0700
+1C07001C07001C0700FF8FE0FF8FE01310808F14>I<07C01FF03C78701C701CE00EE00EE00EE0
+0EE00EE00E701C783C3C781FF007C00F107E8F14>I<FCF800FDFE001F07001E03001C03801C01
+C01C01C01C01C01C01C01C01C01C01C01C03801E03001F0E001DFC001CF8001C00001C00001C00
+001C00001C00001C0000FF8000FF80001218808F14>I<FE1F00FE7F800EE3800F81000F00000F
+00000E00000E00000E00000E00000E00000E00000E00000E0000FFF000FFF00011107F8F14>
+114 D<0FD83FF86038C038C038F0007F803FF007F8001C6006E006F006F81CFFF8CFE00F107E8F
+14>I<030007000700070007007FFCFFFC07000700070007000700070007000700070E070E070E
+070C03FC00F00F157F9414>I<FC3F00FC3F001C07001C07001C07001C07001C07001C07001C07
+001C07001C07001C07001C07001C1F000FFFE003E7E01310808F14>I<FE3F80FE3F801C1C001C
+1C001C1C001C1C000E38000E38000E380006300007700007700007700003E00003E00003E00011
+107F8F14>I<FF7F80FF7F80380E00380E00380E00380E0039CE0039CE0019CC001B6C001B6C00
+1A6C001A6C001E7C000E78000E780011107F8F14>I<7E3F007E3F001E38000E780007700007E0
+0003E00001C00003C00003E0000770000E78000E38001C1C00FE3F80FE3F8011107F8F14>I<FE
+3F80FE3F801C1C001C1C001C1C000E1C000E38000E380007380007300007300003700003700001
+E00001E00001E00001C00001C00001C0000380007380007700007E00003C000011187F8F14>I<
+3FFF7FFF700E701C7038007000E001C0038007000E001C0738077007FFFFFFFF10107F8F14>I
+E /Fd 1 59 df<60F0F06004047D830B>58 D E /Fe 25 122 df<078018603030303060186018
+E01CE01CE01CE01CE01CE01CE01CE01CE01CE01CE01CE01C6018601870383030186007800E187E
+9713>48 D<03000700FF0007000700070007000700070007000700070007000700070007000700
+070007000700070007000700FFF00C187D9713>I<0F80106020304038803CC01CE01C401C003C
+003800380070006000C001800100020004040804100430083FF87FF8FFF80E187E9713>I<01E0
+06100C1818383038300070006000E000E7C0E860F030F018E018E01CE01CE01C601C601C701830
+183030186007C00E187E9713>54 D<40007FFE7FFC7FFC40088010801080200040004000800180
+01800100030003000300030007000700070007000700070002000F197E9813>I<078018603030
+201860186018601870103C303E600F8007C019F030F86038401CC00CC00CC00CC00C6008201018
+600FC00E187E9713>I<07801860303070306018E018E018E01CE01CE01C601C603C303C185C0F
+9C001C00180018003870307060604021801F000E187E9713>I<FFE7FF0E00700E00700E00700E
+00700E00700E00700E00700E00700E00700E00700E00700FFFF00E00700E00700E00700E00700E
+00700E00700E00700E00700E00700E00700E00700E0070FFE7FF181A7E991D>72
+D<0FC21836200E6006C006C002C002C002E00070007E003FE01FF807FC003E000E000700038003
+80038003C002C006E004D81887E0101A7E9915>83 D<3F8070C070E020700070007007F01C7030
+707070E070E071E071E0F171FB1E3C10107E8F13>97 D<07F80C1C381C30087000E000E000E000
+E000E000E0007000300438080C1807E00E107F8F11>99 D<007E00000E00000E00000E00000E00
+000E00000E00000E00000E00000E0003CE000C3E00380E00300E00700E00E00E00E00E00E00E00
+E00E00E00E00E00E00600E00700E00381E001C2E0007CFC0121A7F9915>I<07C01C3030187018
+600CE00CFFFCE000E000E000E0006000300438080C1807E00E107F8F11>I<0FCE187330307038
+703870387038303018602FC02000600070003FF03FFC1FFE600FC003C003C003C0036006381C07
+E010187F8F13>103 D<FC00001C00001C00001C00001C00001C00001C00001C00001C00001C00
+001CF8001D0C001E0E001E0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E
+001C0E001C0E00FF9FC0121A7F9915>I<18003C003C001800000000000000000000000000FC00
+1C001C001C001C001C001C001C001C001C001C001C001C001C001C00FF80091A80990A>I<FCF8
+001D0C001E0E001E0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E
+001C0E00FF9FC012107F8F15>110 D<07E01C38300C700E6006E007E007E007E007E007E00760
+06700E381C1C3807E010107F8F13>I<FCF8001F0E001E07001C03801C03801C01C01C01C01C01
+C01C01C01C01C01C01C01C03801C03001E07001F0C001CF0001C00001C00001C00001C00001C00
+001C0000FF800012177F8F15>I<FCE01D701E701E201C001C001C001C001C001C001C001C001C
+001C001C00FFC00C107F8F0F>114 D<1F2060E04020C020C020F0007F003FC01FE000F0807080
+30C030C020F0408F800C107F8F0F>I<0400040004000C000C001C003C00FFC01C001C001C001C
+001C001C001C001C001C201C201C201C201C200E4003800B177F960F>I<FF1F803C06001C0400
+1C04001E0C000E08000E080007100007100007900003A00003A00001C00001C00001C000008000
+11107F8F14>118 D<FF3F803C1C001C18000E100007200007600003C00001C00001E00003E000
+027000043800083800181C00381E00FC3FC012107F8F14>120 D<FF1F803C06001C04001C0400
+1E0C000E08000E080007100007100007900003A00003A00001C00001C00001C000008000008000
+010000010000E10000E20000E4000078000011177F8F14>I E /Ff 2 42
+df<007000E001C00380078007000E001E001E003C003C003C0078007800780078007000F000F0
+00F000F000F000F000F000F000F000F000F000F000700078007800780078003C003C003C001E00
+1E000E0007000780038001C000E000700C2E7EA112>40 D<E000700038001C001E000E00070007
+80078003C003C003C001E001E001E001E000E000F000F000F000F000F000F000F000F000F000F0
+00F000F000E001E001E001E001E003C003C003C00780078007000E001E001C0038007000E0000C
+2E7DA112>I E /Fg 25 123 df<0007F800007FFC0001FC0E0003F01F0007E03F000FC03F000F
+C03F000FC03F000FC01E000FC00C000FC000000FC000000FC0FF80FFFFFF80FFFFFF800FC01F80
+0FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F
+800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F807FF8FFF07FF8FFF01C23
+7FA220>12 D<000FFF80007FFF8001FC1F8003F03F8007E03F800FC03F800FC01F800FC01F800F
+C01F800FC01F800FC01F800FC01F800FC01F80FFFFFF80FFFFFF800FC01F800FC01F800FC01F80
+0FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F
+800FC01F800FC01F800FC01F800FC01F800FC01F807FF8FFF07FF8FFF01C237FA220>I<07FE00
+001FFF80003F07E0003F03F0003F01F0003F01F8001E01F8000001F8000001F800003FF80003FD
+F8001F81F8003E01F8007C01F800F801F800F801F800F801F800F801F8007C02F8007E0CF8001F
+F87F8007E03F8019167E951C>97 D<FF800000FF8000001F8000001F8000001F8000001F800000
+1F8000001F8000001F8000001F8000001F8000001F8000001F8000001F87F0001FBFFC001FF03E
+001FC01F001F800F801F800FC01F8007C01F8007E01F8007E01F8007E01F8007E01F8007E01F80
+07E01F8007E01F8007C01F8007C01F800FC01F800F801FC01F001E707E001C3FFC00180FE0001B
+237EA220>I<00FF8007FFE00F83F01F03F03E03F07E03F07C01E07C0000FC0000FC0000FC0000
+FC0000FC0000FC00007C00007E00007E00003F00301F00600FC0E007FF8000FE0014167E9519>
+I<0001FF000001FF0000003F0000003F0000003F0000003F0000003F0000003F0000003F000000
+3F0000003F0000003F0000003F0000FE3F0007FFBF000FC1FF001F007F003E003F007E003F007C
+003F007C003F00FC003F00FC003F00FC003F00FC003F00FC003F00FC003F00FC003F007C003F00
+7E003F003E003F001F007F000F81FF0007FF3FE001FC3FE01B237EA220>I<00FE0007FF800F83
+C01F01E03E00F07E00F07C00F87C0078FC0078FFFFF8FFFFF8FC0000FC0000FC00007C00007C00
+003E00183E00181F00300F80E003FFC000FF0015167E951A>I<00FE0F8003FF9FC00F83E3C01F
+01F3C01E00F0003E00F8003E00F8003E00F8003E00F8003E00F8001E00F0001F01F0000F83E000
+0BFF800008FE000018000000180000001C0000001FFFE0001FFFFC000FFFFF0007FFFF001FFFFF
+807C001FC078000FC0F80007C0F80007C0F80007C07C000F803E001F001F807E000FFFFC0001FF
+E0001A217F951D>103 D<FF800000FF8000001F8000001F8000001F8000001F8000001F800000
+1F8000001F8000001F8000001F8000001F8000001F8000001F83F0001F8FFC001F987E001FA03E
+001FC03F001FC03F001F803F001F803F001F803F001F803F001F803F001F803F001F803F001F80
+3F001F803F001F803F001F803F001F803F001F803F001F803F00FFF1FFE0FFF1FFE01B237DA220
+>I<1E003F007F807F807F807F803F001E00000000000000000000000000FF80FF801F801F801F
+801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F80FFF0FFF00C247EA3
+0F>I<FF800000FF8000001F8000001F8000001F8000001F8000001F8000001F8000001F800000
+1F8000001F8000001F8000001F8000001F80FF801F80FF801F803C001F8030001F80E0001F81C0
+001F8300001F8600001F9E00001FBE00001FFF00001FDF80001F8FC0001F07C0001F07E0001F03
+F0001F01F8001F00F8001F00FC001F007E00FFE1FFC0FFE1FFC01A237EA21E>107
+D<FF80FF801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F80
+1F801F801F801F801F801F801F801F801F801F801F801F801F801F80FFF0FFF00C237EA20F>I<
+FF03F803F800FF0FFE0FFE001F183F183F001F201F201F001F401FC01F801F401FC01F801F801F
+801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F80
+1F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F
+801F80FFF0FFF0FFF0FFF0FFF0FFF02C167D9531>I<FF03F000FF0FFC001F187E001F203E001F
+403F001F403F001F803F001F803F001F803F001F803F001F803F001F803F001F803F001F803F00
+1F803F001F803F001F803F001F803F001F803F001F803F00FFF1FFE0FFF1FFE01B167D9520>I<
+00FF0007FFE00F81F01F00F83E007C7C003E7C003E7C003EFC003FFC003FFC003FFC003FFC003F
+FC003FFC003F7C003E7E007E3E007C1F00F80F81F007FFE000FF0018167E951D>I<FF87F000FF
+BFFC001FF07E001FC01F001F800F801F800FC01F800FC01F8007E01F8007E01F8007E01F8007E0
+1F8007E01F8007E01F8007E01F8007C01F800FC01F800FC01F801F801FC01F001FF07E001FBFFC
+001F8FE0001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F800000FFF0
+0000FFF000001B207E9520>I<FF0F80FF1FE01F33F01F63F01F43F01F43F01FC1E01F80001F80
+001F80001F80001F80001F80001F80001F80001F80001F80001F80001F80001F8000FFF800FFF8
+0014167E9518>114 D<07F9801FFF80380780700380F00180F00180F80000FF0000FFF8007FFE
+003FFF001FFF8007FF80003FC0C007C0C003C0E003C0E003C0F00380FC0F00EFFE00C3F8001216
+7E9517>I<00C00000C00000C00000C00001C00001C00003C00007C0000FC0001FC000FFFF00FF
+FF000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC1800F
+C1800FC1800FC1800FC18007C18007E30003FE0000FC0011207F9F16>I<FF81FF00FF81FF001F
+803F001F803F001F803F001F803F001F803F001F803F001F803F001F803F001F803F001F803F00
+1F803F001F803F001F803F001F803F001F803F001F807F001F80FF000FC1BF0007FF3FE001FC3F
+E01B167D9520>I<FFF01FE0FFF01FE00FC007000FC006000FE00E0007E00C0007F01C0003F018
+0003F8180001F8300001F8300000FC600000FC6000007EC000007EC000007FC000003F8000003F
+8000001F0000001F0000000E0000000E00001B167F951E>I<FFF3FF87FCFFF3FF87FC1F807C00
+E00FC07C00C00FC07E00C00FE03E01C007E03F018007E07F018003F07F030003F0CF830001F8CF
+860001F8CFC60001FD87C60000FD87CC0000FF03EC00007F03F800007F03F800007E01F800003E
+01F000003C00F000001C00E000001800600026167F9529>I<FFF0FFC0FFF0FFC00FC01C0007E0
+380007F0700003F0E00001F8C00000FD8000007F0000007F0000003F0000001F8000003FC00000
+37E0000067F00000C3F00001C1F8000380FC000700FE000E007E00FFC1FFE0FFC1FFE01B167F95
+1E>I<FFF01FE0FFF01FE00FC007000FC006000FE00E0007E00C0007F01C0003F0180003F81800
+01F8300001F8300000FC600000FC6000007EC000007EC000007FC000003F8000003F8000001F00
+00001F0000000E0000000E0000000C0000000C00000018000078180000FC380000FC300000FC60
+000069E000007F8000001F0000001B207F951E>I<7FFFE07FFFE0780FC0701FC0601F80E03F00
+C07F00C07E00C0FC0001FC0001F80003F00007F03007E0300FC0301FC0701F80703F00607F00E0
+7E03E0FFFFE0FFFFE014167E9519>I E /Fh 22 119 df<00E00000E00000E00000E00040E040
+F0E1E0F8E3E07EEFC01FFF0007FC0003F80007FC001FFF007EEFC0F8E3E0F0E1E040E04000E000
+00E00000E00000E00013157D991A>42 D<003800007C00007C00006C0000EE0000EE0000EE0000
+EE0000C60001C70001C70001C70001C7000383800383800383800383800783C00701C007FFC007
+FFC007FFC00E00E00E00E00E00E00E00E01C00707F83FCFF83FE7F83FC171E7F9D1A>65
+D<7FFFFCFFFFFC7FFFFC0E001C0E001C0E001C0E001C0E001C0E00000E00000E07000E07000E07
+000FFF000FFF000FFF000E07000E07000E07000E00000E00000E00000E000E0E000E0E000E0E00
+0E0E000E7FFFFEFFFFFE7FFFFE171E7F9D1A>69 D<FF8FF8FF8FF8FF8FF81C01C01C01C01C01C0
+1C01C01C01C01C01C01C01C01C01C01C01C01C01C01FFFC01FFFC01FFFC01C01C01C01C01C01C0
+1C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C0FF8FF8FF8FF8FF8FF8151E7E9D1A>
+72 D<FFFF80FFFF80FFFF8001C00001C00001C00001C00001C00001C00001C00001C00001C000
+01C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C000
+01C00001C000FFFF80FFFF80FFFF80111E7C9D1A>I<FE0FF8FF0FF8FF0FF81D81C01D81C01D81
+C01D81C01DC1C01CC1C01CC1C01CE1C01CE1C01C61C01C61C01C71C01C71C01C31C01C31C01C39
+C01C39C01C19C01C19C01C1DC01C0DC01C0DC01C0DC01C0DC0FF87C0FF87C0FF83C0151E7E9D1A
+>78 D<0FFE003FFF807FFFC07C07C07001C0F001E0E000E0E000E0E000E0E000E0E000E0E000E0
+E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0F001E0F001E0
+7001C07C07C07FFFC03FFF800FFE00131E7D9D1A>I<FFF000FFFC00FFFF001C0F801C07801C03
+C01C01C01C01C01C01C01C01C01C03C01C07801C0F801FFF001FFC001FFE001C0F001C07001C03
+801C03801C03801C03801C03801C03841C038E1C038E1C038EFF81FCFF81FCFF8070171E7E9D1A
+>82 D<03F1C00FFDC03FFFC07C0FC07003C0E003C0E001C0E001C0E001C0E00000700000780000
+3F00001FF00007FE0000FF00000F800003C00001C00000E00000E06000E0E000E0E000E0E001C0
+F001C0FC0780FFFF80EFFE00E3F800131E7D9D1A>I<7FFFFEFFFFFEFFFFFEE0380EE0380EE038
+0EE0380EE0380E0038000038000038000038000038000038000038000038000038000038000038
+0000380000380000380000380000380000380000380000380003FF8007FFC003FF80171E7F9D1A
+>I<FF01FEFF83FEFF01FE1E00F00E00E00E00E00701C00701C003838003838003C78001C70001
+C70000EE0000EE00007C00007C0000380000380000380000380000380000380000380000380000
+380000380001FF0001FF0001FF00171E7F9D1A>89 D<7FFFC0FFFFE0FFFFE07FFFC013047D7E1A
+>95 D<1FF0003FFC007FFE00780F00300700000380000380007F8007FF801FFF803F8380780380
+700380E00380E00380E00380700780780F803FFFFC1FFDFC07F0FC16157D941A>97
+D<00FF8003FFC00FFFE01F01E03C00C0780000700000700000E00000E00000E00000E00000E000
+007000007000007800703C00701F01F00FFFE003FFC000FE0014157D941A>99
+D<001FC0001FC0001FC00001C00001C00001C00001C00001C00001C001F1C007FDC00FFFC01E0F
+C03C07C07803C07001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C07003C07003C03807
+C03E0FC01FFFFC07FDFC01F1FC161E7E9D1A>I<FE0000FE0000FE00000E00000E00000E00000E
+00000E00000E00000E3E000EFF800FFFC00FC1C00F80E00F00E00E00E00E00E00E00E00E00E00E
+00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E0FFE3FEFFE3FEFFE3FE171E7F9D1A>
+104 D<01C00003E00003E00003E00001C0000000000000000000000000000000007FE000FFE000
+7FE00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E000
+00E00000E00000E000FFFFC0FFFFC0FFFFC0121F7C9E1A>I<FE3E00FEFF80FFFFC00FC1C00F80
+E00F00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00
+E0FFE3FEFFE3FEFFE3FE17157F941A>110 D<01F00007FC001FFF003E0F803C07807803C07001
+C0E000E0E000E0E000E0E000E0E000E0E000E0F001E07001C07803C03C07803E0F801FFF0007FC
+0001F00013157D941A>I<FF83F0FF8FF8FFBFFC03FC3C03F01803E00003C00003C00003800003
+8000038000038000038000038000038000038000038000038000FFFF00FFFF80FFFF0016157E94
+1A>114 D<00C00001C00001C00001C00001C00001C00001C0007FFFE0FFFFE0FFFFE001C00001
+C00001C00001C00001C00001C00001C00001C00001C00001C00001C07001C07001C07001C07000
+E0E000FFE0007FC0001F00141C7F9B1A>116 D<7FC7FCFFC7FE7FC7FC0E00E00E00E00F01E007
+01C00701C00783C003838003838003838001C70001C70001C70000EE0000EE0000EE00007C0000
+7C0000380017157F941A>118 D E /Fi 41 123 df<0003FC00003FFE00007E070001F80F8003
+F01F8003E01F8007E01F8007E01F8007E01F8007E0060007E0000007E0000007E0000007E0FFC0
+FFFFFFC0FFFFFFC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00F
+C007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E0
+0FC007E00FC007E00FC07FFC7FFC7FFC7FFC1E267FA522>12 D<3C7EFFFFFFFF7E3C08087C8711
+>46 D<001C00003C0000FC00FFFC00FFFC0000FC0000FC0000FC0000FC0000FC0000FC0000FC00
+00FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC00
+00FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC007FFFFC7FFFFC16237CA21F>49
+D<01FF0007FFC01E07F03803F86001FC7C00FEFE00FEFE00FFFE007FFE007F7C007F3800FF0000
+FF0000FE0000FE0001FC0001F80003F00007E0000780000F00001E00003C0000700000E00301C0
+030380070700060600060FFFFE1FFFFE3FFFFE7FFFFCFFFFFCFFFFFC18237DA21F>I<01FF0007
+FFE01E03F03801F83C01FC7E00FE7E00FE7E00FE3E00FE1C01FE0001FC0001FC0003F80007F000
+0FC001FF0001FF000007E00001F00001F80000FC0000FE0000FF0000FF1000FF7C00FFFE00FFFE
+00FFFE00FEFE00FE7C01FC7001F83E07F00FFFC001FF0018237DA21F>I<000038000000780000
+0078000000F8000001F8000003F8000007F8000006F800000CF800001CF8000038F8000030F800
+0060F80000E0F80001C0F8000180F8000300F8000700F8000E00F8001C00F8001800F8003000F8
+007000F800E000F800FFFFFFC0FFFFFFC00001F8000001F8000001F8000001F8000001F8000001
+F8000001F800007FFFC0007FFFC01A237EA21F>I<18000C1F007C1FFFF81FFFF01FFFE01FFFC0
+1FFF801FFE0018000018000018000018000018000018FF001BFFE01F01F01C00F80800FC00007E
+00007E00007E00007F00007F78007FFC007FFC007FFC007FFC007EF8007E6000FC7000FC3801F8
+1E07E007FFC001FE0018237DA21F>I<001FC0007FF001F83803E00C07803E0F807E1F007E3F00
+7E3F007E7E003C7E00007E00007E0000FE3FC0FE7FF0FE80F8FF80FCFF007CFF007EFE007EFE00
+7FFE007FFE007FFE007F7E007F7E007F7E007F7E007F3E007E3F007E1F007C0F80F807C1F003FF
+C0007F0018237DA21F>I<300000003C0000003FFFFFC03FFFFFC03FFFFF807FFFFF007FFFFE00
+7FFFFC006000180060001800E0003000C0006000C000C000000180000001800000030000000700
+0000060000000E0000001E0000001E0000001E0000003C0000003C0000007C0000007C0000007C
+0000007C000000FC000000FC000000FC000000FC000000FC000000FC000000FC00000078000000
+3000001A257DA41F>I<00001C00000000001C00000000003E00000000003E00000000003E0000
+0000007F00000000007F0000000000FF8000000000FF8000000000FF80000000019FC000000001
+9FC0000000031FE0000000030FE0000000030FE00000000607F00000000607F00000000C07F800
+00000C03F80000001C03FC0000001801FC0000001801FC0000003001FE0000003000FE0000007F
+FFFF0000007FFFFF00000060007F000000C0007F800000C0003F800001C0003FC0000180001FC0
+000180001FC0000300000FE0000300000FE0000780000FF000FFF801FFFF80FFF801FFFF802925
+7EA42E>65 D<FFFFFFE00000FFFFFFFC000003F800FF000003F8001FC00003F80007E00003F800
+03F00003F80001F80003F80001FC0003F80000FC0003F80000FE0003F80000FE0003F800007F00
+03F800007F0003F800007F0003F800007F8003F800007F8003F800007F8003F800007F8003F800
+007F8003F800007F8003F800007F8003F800007F8003F800007F8003F800007F8003F800007F00
+03F800007F0003F800007F0003F80000FE0003F80000FE0003F80001FC0003F80001F80003F800
+03F00003F80007E00003F8001FC00003F800FF8000FFFFFFFE0000FFFFFFE0000029257EA42F>
+68 D<FFFFFFFF00FFFFFFFF0003F8007F0003F8000F8003F800078003F800038003F800038003
+F800018003F800018003F800018003F80000C003F80600C003F80600C003F806000003F8060000
+03F80E000003F81E000003FFFE000003FFFE000003F81E000003F80E000003F806000003F80600
+0003F806006003F806006003F800006003F80000C003F80000C003F80000C003F80000C003F800
+01C003F80003C003F80003C003F8000F8003F8003F80FFFFFFFF80FFFFFFFF8023257EA428>I<
+FFFFFFFE00FFFFFFFE0003F800FE0003F8001F0003F8000F0003F800070003F800070003F80003
+0003F800030003F800030003F800018003F806018003F806018003F806000003F806000003F80E
+000003F81E000003FFFE000003FFFE000003F81E000003F80E000003F806000003F806000003F8
+06000003F806000003F800000003F800000003F800000003F800000003F800000003F800000003
+F800000003F800000003F800000003F8000000FFFFF00000FFFFF0000021257EA427>I<FFFFE0
+FFFFE0FFFFE0FFFFE003F80003F80003F80003F80003F80003F80003F80003F80003F80003F800
+03F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F800
+03F80003F80003F80003F80003F80003F80003F80003FFFFFFF80003FFFFFFF80003F80003F800
+03F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F800
+03F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F800
+03F80003F80003F80003F800FFFFE0FFFFE0FFFFE0FFFFE02B257EA430>72
+D<FFFFE0FFFFE003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F8
+0003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F8
+0003F80003F80003F80003F80003F80003F80003F80003F80003F800FFFFE0FFFFE013257EA417
+>I<FFFFF000FFFFF00003F8000003F8000003F8000003F8000003F8000003F8000003F8000003
+F8000003F8000003F8000003F8000003F8000003F8000003F8000003F8000003F8000003F80000
+03F8000003F8000003F8000003F8000003F8000603F8000603F8000603F8000C03F8000C03F800
+0C03F8001C03F8001C03F8003C03F8007C03F800F803F803F8FFFFFFF8FFFFFFF81F257EA425>
+76 D<FFF8000000FFF8FFFC000001FFF803FC000001FE00037E0000037E00037E0000037E0003
+7E0000037E00033F0000067E00033F0000067E00031F80000C7E00031F80000C7E00030FC00018
+7E00030FC000187E000307E000307E000307E000307E000307E000307E000303F000607E000303
+F000607E000301F800C07E000301F800C07E000300FC01807E000300FC01807E0003007E03007E
+0003007E03007E0003007E03007E0003003F06007E0003003F06007E0003001F8C007E0003001F
+8C007E0003000FD8007E0003000FD8007E00030007F0007E00030007F0007E00030007F0007E00
+030003E0007E00078003E0007E00FFFC01C01FFFF8FFFC01C01FFFF835257EA43A>I<00FF0080
+07FFE3800F80F7801E001F803C000F807800078078000380F8000380F8000180F8000180FC0001
+80FC000000FF0000007FE000007FFF00003FFFE0003FFFF8001FFFFE0007FFFF0003FFFF80007F
+FF800003FFC000003FC000000FE0000007E0000007E0C00003E0C00003E0C00003E0C00003C0E0
+0003C0F00007C0F8000780FC000F00FFC03E00E3FFF800803FE0001B257DA422>83
+D<FFFF83FFFE01FFF0FFFF83FFFE01FFF007F0001FC0000F0007F0001FC000060003F8000FE000
+0C0003F8000FE0000C0003FC000FF0001C0001FC0007F000180001FC0007F000180000FE000FF8
+00300000FE000FF800300000FE000FFC003000007F0019FC006000007F0019FC006000007F8039
+FE00E000003F8030FE00C000003F8030FE00C000001FC0607F018000001FC0607F018000001FE0
+607F818000000FE0C03F830000000FE0C03F830000000FF1C03FC700000007F1801FC600000007
+F1801FC600000003FB000FEC00000003FB000FEC00000003FF000FFC00000001FE0007F8000000
+01FE0007F800000001FE0007F800000000FC0003F000000000FC0003F000000000780001E00000
+0000780001E000000000780001E000000000300000C000003C257FA43F>87
+D<07FF00001FFFC0003E03E0003F01F0003F01F8003F00FC001E00FC000000FC000000FC000000
+FC00003FFC0003FCFC000FC0FC003F00FC007E00FC007E00FC00FC00FC00FC00FC00FC00FC00FC
+017C007E017C003F067C001FFC3FE007F01FE01B187E971E>97 D<FFC00000FFC000000FC00000
+0FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000
+000FC000000FC3F8000FCFFE000FF81F800FE00FC00FC007E00FC007E00FC003F00FC003F00FC0
+03F80FC003F80FC003F80FC003F80FC003F80FC003F80FC003F80FC003F80FC003F00FC003F00F
+C007E00FC007C00FE00FC00F383F000E1FFE000C07F0001D267EA522>I<007FE003FFF807C07C
+1F80FC1F00FC3F00FC7E00787E0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000
+7E00007F00003F000C1F800C1FC01807E07003FFE0007F0016187E971B>I<0001FF800001FF80
+00001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F
+8000001F8000001F80007F1F8003FFDF8007E0FF801F803F803F001F803F001F807E001F807E00
+1F80FE001F80FE001F80FE001F80FE001F80FE001F80FE001F80FE001F80FE001F807E001F807E
+001F803F001F803F003F801F807F800FC0FF8003FF9FF800FE1FF81D267EA522>I<007F0003FF
+C007C1F00F80F81F00F83F007C7E007C7E007EFE007EFE007EFFFFFEFFFFFEFE0000FE0000FE00
+007E00007E00007E00063F00061F000C0F801807E07003FFE0007F8017187E971C>I<000FC000
+7FF000F8F001F1F803F1F803E1F807E0F007E00007E00007E00007E00007E00007E00007E000FF
+FF00FFFF0007E00007E00007E00007E00007E00007E00007E00007E00007E00007E00007E00007
+E00007E00007E00007E00007E00007E00007E00007E00007E0007FFF007FFF0015267EA513>I<
+01FF07C007FFDFE00F83F1E01F01F1E03E00F8007E00FC007E00FC007E00FC007E00FC007E00FC
+007E00FC003E00F8001F01F0000F83E0000FFFC00011FF00003000000030000000380000003C00
+00003FFFE0001FFFFC001FFFFE000FFFFF001FFFFF803C003F8078000FC0F80007C0F80007C0F8
+0007C0F80007C07C000F803E001F001F807E0007FFF80000FFC0001B247E971F>I<FFC00000FF
+C000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC00000
+0FC000000FC000000FC000000FC1F8000FC7FE000FCC3F000FD01F000FF01F800FE01F800FE01F
+800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC0
+1F800FC01F800FC01F800FC01F800FC01F800FC01F80FFFCFFF8FFFCFFF81D267DA522>I<0F00
+1F803FC03FC03FC03FC01F800F000000000000000000000000000000FFC0FFC00FC00FC00FC00F
+C00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0FFF8FFF80D27
+7EA611>I<FFC0FFC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0
+0FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0FF
+FCFFFC0E267EA511>108 D<FF81FC01FC00FF87FF07FF000F8C1F8C1F800F980F980F800FB00F
+F00FC00FA00FE00FC00FA00FE00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0
+0FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00F
+C00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0FFFCFFFCFFFCFFFCFFFCFFFC
+2E187D9733>I<FF81F800FF87FE000F8C3F000F901F000FB01F800FA01F800FA01F800FC01F80
+0FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F
+800FC01F800FC01F800FC01F800FC01F80FFFCFFF8FFFCFFF81D187D9722>I<007F800003FFF0
+0007C0F8001F807E003F003F003F003F007E001F807E001F80FE001FC0FE001FC0FE001FC0FE00
+1FC0FE001FC0FE001FC0FE001FC0FE001FC07E001F807E001F803F003F003F003F001F807E000F
+C0FC0003FFF000007F80001A187E971F>I<FFC3F800FFCFFE000FF83F800FE00FC00FC00FE00F
+C007E00FC007F00FC003F00FC003F80FC003F80FC003F80FC003F80FC003F80FC003F80FC003F8
+0FC003F80FC007F00FC007F00FC007E00FC00FC00FE01FC00FF83F000FDFFE000FC7F0000FC000
+000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC00000FFFC0000FFFC
+00001D237E9722>I<FF87C0FF8FF00F98F80FB1F80FA1F80FA1F80FE0F00FC0000FC0000FC000
+0FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC000FFFE00
+FFFE0015187E9719>114 D<07F9801FFF803C0F80700380F00180F00180F00180FC0000FF8000
+7FFC007FFE003FFF800FFFC003FFC0001FE00003E0C001E0C001E0E001E0E001C0F003C0FC0780
+EFFF00C3FC0013187E9718>I<00600000600000600000600000E00000E00001E00001E00003E0
+0007E0001FE000FFFFC0FFFFC007E00007E00007E00007E00007E00007E00007E00007E00007E0
+0007E00007E00007E00007E06007E06007E06007E06007E06007E06003E0C003F0C001FF80007E
+0013237FA218>I<FFC1FF80FFC1FF800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F
+800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC0
+1F800FC03F800FC03F8007C07F8007E0DF8003FF9FF800FE1FF81D187D9722>I<FFF80FF8FFF8
+0FF80FC003C00FE0018007E0030007E0030003F0060003F0060003F80E0001F80C0001FC1C0000
+FC180000FE1800007E3000007E3000003F6000003F6000001FC000001FC000001FC000000F8000
+000F800000070000000700001D187F9720>I<FFF83FF0FFF83FF00FC00F0007E00C0003F01C00
+03F8380001FC700000FCE000007EC000003F8000003F8000001F8000000FC000001FE000001FF0
+000033F8000071F80000E0FC0001C07E0003807F0003003F000F001F80FFC07FF8FFC07FF81D18
+7F9720>120 D<FFF80FF8FFF80FF80FC003C00FE0018007E0030007E0030003F0060003F00600
+03F80E0001F80C0001FC1C0000FC180000FE1800007E3000007E3000003F6000003F6000001FC0
+00001FC000001FC000000F8000000F800000070000000700000006000000060000000C0000300C
+0000781C0000FC180000FC380000FC70000078E000007FC000001F0000001D237F9720>I<3FFF
+F83FFFF83E03F03807F0300FE0700FC0701F80603F80603F00607E0000FE0000FC0001F80003F8
+1803F01807E0180FE0180FC0381F80303F80707F00707E01F0FFFFF0FFFFF015187E971B>I
+E /Fj 29 122 df<0003F07C001E0DC600380F0F00701E0F00E01E0E00E00C0001C01C0001C01C
+0001C01C0001C01C0001C01C00038038007FFFFFC0038038000380380003803800038038000700
+700007007000070070000700700007007000070070000E00E0000E00E0000E00E0000E00E0000E
+00E0000E00E0001C01C0001E01E000FF8FFE0020207E9F1B>11 D<0003E0001C1800381800703C
+00E03C00E03801C00001C00001C00001C00001C0000380007FFFF0038070038070038070038070
+0700E00700E00700E00700E00700E00700E00E01C00E01C00E01C00E01C00E01C00E01C01C0380
+1E03C0FF0FF816207E9F19>I<0003F03F00001E09E08000380F80C000701F01E000E03E01E000
+E01E01C001C01C000001C01C000001C01C000001C01C000001C01C000003803800007FFFFFFF80
+038038038003803803800380380380038038038007007007000700700700070070070007007007
+00070070070007007007000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E0
+0E001C01C01C001E01E01E00FF8FF8FFC023207E9F26>14 D<0020000060000060000060000060
+007061C03843800E4E0007580001E00001E00006B8001C9C00708700E083800180000180000180
+0001800001000012147AA117>42 D<FFC0FFC00A027D8A0F>45 D<000C001C00FC0F3800380038
+00380038003800700070007000700070007000E000E000E000E000E000E001C001C001C001C001
+C001C0038003C0FFFE0F1E7C9D17>49 D<003F8000C1E00100F00200780400780400780F007C0F
+807C0F807C0F00780600780000F80000F00001E00001C0000380000700000E00001C0000380000
+600000C0000180000300200600200800401000403FFFC07FFF80FFFF80161E7E9D17>I<07F800
+0C0C001E06001E07001C070000070000070000070000FF0007C7001E07003C0E00780E00F00E10
+F00E10F00E10F01E10F02E20784F401F878014147D9317>97 D<01FC07060E0F1C0F380E780070
+00F000F000F000F000E000E000E000E000F0027004300818300FC010147C9314>99
+D<0000700003F00000F00000700000700000E00000E00000E00000E00000E00000E00001C000F9
+C00305C00E03C01C03C03801C0780380700380F00380F00380F00380F00380E00700E00700E007
+00E00700E00700700F00301E00186F000F8FE014207C9F19>I<00F800070E000E07001C070038
+0380780380700380F00380F00380FFFF80F00000E00000E00000E00000E00000F0010070020030
+04001C180007E00011147D9314>I<0007800018C00031E00061E000E1C000C00001C00001C000
+01C00001C00001C0000380007FF800038000038000038000038000070000070000070000070000
+0700000700000E00000E00000E00000E00000E00000E00001C00001E0000FFE00013207E9F0E>
+I<00000E003E1100E1A301C1C20381E00780E00701E00F01E00F01E00F01E00703C00703800787
+0004FC000800000800001800001C00000FFF000FFFC007FFE01800F0300030600030C00030C000
+30C000306000603000C01C070007FC00181F809417>I<00E00007E00001E00000E00000E00001
+C00001C00001C00001C00001C00001C000038000038F800390E003A0E003C0600380600780E007
+00E00700E00700E00700E00700E00E01C00E01C00E01C00E01C00E01C00E01C01C03801E03C0FF
+CFF815207E9F19>I<01C003E003E003C0018000000000000000000000000003801F8007800380
+03800700070007000700070007000E000E000E000E000E000E001C001E00FF800B1F7F9E0C>I<
+00E007E001E000E000E001C001C001C001C001C001C00380038003800380038003800700070007
+000700070007000E000E000E000E000E000E001C001E00FFC00B207F9F0C>108
+D<0387C07C001F9861860007A072070003C0340300038038030007807807000700700700070070
+07000700700700070070070007007007000E00E00E000E00E00E000E00E00E000E00E00E000E00
+E00E000E00E00E001C01C01C001E01E01E00FFCFFCFFC022147E9326>I<038F801F90E007A0E0
+03C0600380600780E00700E00700E00700E00700E00700E00E01C00E01C00E01C00E01C00E01C0
+0E01C01C03801E03C0FFCFF815147E9319>I<00FC000387000E01801C00C03800E03800E07000
+F0F000F0F000F0F000F0F000F0E001E0E001E0E001C0E003C0F00380700700380E001C1C0007E0
+0014147D9317>I<00E3E007EC3800F01C00E01E00E00E01C00E01C00F01C00F01C00F01C00F01
+C00F03801E03801E03801C03803C0380380380700740E00721C0071F000700000700000700000E
+00000E00000E00000E00001E0000FFC000181D809319>I<00F040038CC00E04C01C03C03C03C0
+780380780380F00380F00380F00380F00380E00700E00700E00700F00700F00F00700F00301E00
+186E000F8E00000E00000E00000E00001C00001C00001C00001C00003C0001FF80121D7C9318>
+I<038E001FB38007C78003C7800383000780000700000700000700000700000700000E00000E00
+000E00000E00000E00000E00001C00001E0000FFE00011147E9312>I<01F2060E080618061802
+380438001E001FE00FF003F8003C401C400C400C600C6018E010D0608FC00F147E9312>I<0080
+010001000100030007000F001E00FFF80E000E000E000E001C001C001C001C001C001C00380038
+203820382038203840384018800F000D1C7C9B12>I<1C0380FC1F803C07801C03801C03803807
+00380700380700380700380700380700700E00700E00700E00700E00701E00701E00703C00305E
+001F9FC012147B9319>I<FF83F81E00E01C00C01C00800E00800E01000E02000E02000F040007
+040007080007080007100003900003A00003E00003C00003800001800001000015147C9318>I<
+FF9FE1FC3E0780701C0300601C0300401C0380401C0380800E0780800E0581000E0981000E09C2
+000E11C2000731C4000721C4000760C8000740C8000780F0000780F0000300E000030060000200
+40001E147C9321>I<1FF0FF03C07801C06001C04000E08000E180007300007600003C00003C00
+001C00002E00004E000087000107000203800603800C01C03E03E0FF07FC18147F9318>I<0FF8
+3F8001E00E0001C00C0001C0080000E0180000E0100000E0200000E0200000F040000070400000
+708000007080000071000000390000003A0000003E0000003C0000003800000018000000100000
+0010000000200000002000000040000070C00000F0800000F1000000E20000007C000000191D80
+9318>I E /Fk 36 122 df<0001C0000003C000000FC000007FC0001FFFC000FFFFC000FFBFC0
+00E03FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003F
+C000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC00000
+3FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000
+003FC000003FC000003FC000003FC000003FC000003FC000003FC0007FFFFFE07FFFFFE07FFFFF
+E01B2E7AAD28>49 D<003FE00001FFFE0007FFFF800F80FFC01E003FE038001FF07C000FF87E00
+07FCFF0007FCFF8007FEFF8007FEFF8003FEFF8003FE7F0003FE3E0007FE000007FE000007FC00
+0007FC00000FF800000FF800000FF000001FE000001FC000003F8000007F0000007E000000F800
+0001F0000003E0000007C000000F0000001E000E003C000E0038000E0070001E00E0001C01C000
+1C0300003C07FFFFFC0FFFFFFC1FFFFFFC3FFFFFFC7FFFFFF8FFFFFFF8FFFFFFF8FFFFFFF81F2E
+7CAD28>I<0000007800000000000078000000000000FC000000000000FC000000000000FC0000
+00000001FE000000000001FE000000000003FF000000000003FF000000000007FF800000000007
+FF800000000007FF80000000000FFFC0000000000E7FC0000000001E7FE0000000001C3FE00000
+00001C3FE000000000383FF000000000381FF000000000781FF800000000700FF800000000700F
+F800000000E00FFC00000000E007FC00000001E007FE00000001C003FE00000001C003FE000000
+038003FF000000038001FF000000078001FF800000070000FF800000070000FF8000000FFFFFFF
+C000000FFFFFFFC000001FFFFFFFE000001C00003FE000003C00003FF000003800001FF0000038
+00001FF000007000001FF800007000000FF80000F000000FFC0000E0000007FC0000E0000007FC
+0001C0000007FE0003E0000003FE00FFFF8001FFFFFCFFFF8001FFFFFCFFFF8001FFFFFC36317D
+B03D>65 D<FFFFFFFFE00000FFFFFFFFFE0000FFFFFFFFFF800000FF0000FFC00000FF00003FF0
+0000FF00001FF80000FF00000FF80000FF000007FC0000FF000007FC0000FF000007FE0000FF00
+0003FE0000FF000003FE0000FF000003FE0000FF000003FE0000FF000007FE0000FF000007FE00
+00FF000007FC0000FF000007FC0000FF00000FF80000FF00001FF00000FF00003FE00000FF0000
+FF800000FF000FFF000000FFFFFFFE000000FFFFFFFFC00000FF00001FF00000FF000007F80000
+FF000003FE0000FF000003FE0000FF000001FF0000FF000001FF8000FF000000FF8000FF000000
+FFC000FF000000FFC000FF000000FFC000FF000000FFC000FF000000FFC000FF000000FFC000FF
+000000FFC000FF000000FF8000FF000001FF8000FF000001FF0000FF000003FF0000FF000007FE
+0000FF00000FFC0000FF00007FF800FFFFFFFFFFE000FFFFFFFFFF8000FFFFFFFFFC000032317E
+B039>I<000003FF80018000003FFFF003800001FFFFFC07800007FF003F0F80001FF800079F80
+003FC00001FF8000FF800000FF8001FE0000007F8003FC0000003F8007FC0000001F8007F80000
+000F800FF00000000F801FF000000007801FF000000007803FE000000007803FE000000003807F
+E000000003807FE000000003807FC000000000007FC00000000000FFC00000000000FFC0000000
+0000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC0
+0000000000FFC000000000007FC000000000007FC000000000007FE000000000007FE000000003
+803FE000000003803FE000000003801FF000000003801FF000000007800FF0000000070007F800
+0000070007FC0000000E0003FC0000001E0001FE0000001C0000FF8000007800003FC00000F000
+001FF80003E0000007FF003F80000001FFFFFE000000003FFFF80000000003FF80000031317CB0
+3A>I<FFFFFFFFFFE0FFFFFFFFFFE0FFFFFFFFFFE000FF80007FE000FF80000FF000FF800003F0
+00FF800001F000FF800001F000FF800000F000FF800000F000FF8000007000FF8000007000FF80
+00007000FF8000003800FF8000003800FF8007003800FF8007003800FF8007000000FF80070000
+00FF8007000000FF800F000000FF801F000000FF803F000000FFFFFF000000FFFFFF000000FFFF
+FF000000FF803F000000FF801F000000FF800F000000FF8007000000FF8007000000FF80070000
+00FF8007000000FF8007000000FF8000000000FF8000000000FF8000000000FF8000000000FF80
+00000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF80000000
+00FF80000000FFFFFFE00000FFFFFFE00000FFFFFFE000002D317EB033>70
+D<000003FF00030000007FFFF007000001FFFFFC0F000007FF007E1F00001FF0000FBF00007FC0
+0003FF0000FF800001FF0001FE0000007F0003FC0000007F0007FC0000003F000FF80000001F00
+0FF00000001F001FF00000000F001FF00000000F003FE000000007003FE000000007007FE00000
+0007007FE000000007007FC00000000000FFC00000000000FFC00000000000FFC00000000000FF
+C00000000000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC0000000
+0000FFC00000000000FFC00007FFFFFC7FC00007FFFFFC7FE00007FFFFFC7FE0000001FF003FE0
+000001FF003FE0000001FF001FF0000001FF001FF0000001FF000FF0000001FF000FF8000001FF
+0007FC000001FF0003FC000001FF0001FE000001FF0000FF800001FF00007FC00003FF00001FF8
+00077F000007FF003E3F000001FFFFFC1F0000007FFFF00F00000003FF80030036317CB03F>I<
+FFFFFF807FFFFFC0FFFFFF807FFFFFC0FFFFFF807FFFFFC000FF8000007FC00000FF8000007FC0
+0000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007F
+C00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF800000
+7FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000
+007FC00000FF8000007FC00000FF8000007FC00000FFFFFFFFFFC00000FFFFFFFFFFC00000FFFF
+FFFFFFC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF
+8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000
+FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC000
+00FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC0
+0000FF8000007FC00000FF8000007FC000FFFFFF807FFFFFC0FFFFFF807FFFFFC0FFFFFF807FFF
+FFC03A317EB03F>I<FFFFFF80FFFFFF80FFFFFF8000FF800000FF800000FF800000FF800000FF
+800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000
+FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF8000
+00FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF80
+0000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF800000FF8000FFFF
+FF80FFFFFF80FFFFFF8019317EB01E>I<FFFF800001FFFFC0FFFFC00001FFFFC0FFFFE00001FF
+FFC000FFF0000003E00000FFF8000001C00000EFFC000001C00000E7FC000001C00000E7FE0000
+01C00000E3FF000001C00000E1FF800001C00000E0FFC00001C00000E07FE00001C00000E03FE0
+0001C00000E03FF00001C00000E01FF80001C00000E00FFC0001C00000E007FE0001C00000E003
+FE0001C00000E001FF0001C00000E001FF8001C00000E000FFC001C00000E0007FE001C00000E0
+003FF001C00000E0001FF001C00000E0001FF801C00000E0000FFC01C00000E00007FE01C00000
+E00003FF01C00000E00001FF81C00000E00000FF81C00000E00000FFC1C00000E000007FE1C000
+00E000003FF1C00000E000001FF9C00000E000000FFDC00000E0000007FDC00000E0000007FFC0
+0000E0000003FFC00000E0000001FFC00000E0000000FFC00000E00000007FC00000E00000003F
+C00000E00000003FC00000E00000001FC00000E00000000FC00001F000000007C000FFFFE00000
+03C000FFFFE0000001C000FFFFE0000001C0003A317EB03F>78 D<FFFFFFFFE000FFFFFFFFFE00
+FFFFFFFFFF8000FF8000FFE000FF80003FF000FF80000FF800FF800007FC00FF800007FC00FF80
+0003FE00FF800003FE00FF800003FF00FF800003FF00FF800003FF00FF800003FF00FF800003FF
+00FF800003FF00FF800003FF00FF800003FE00FF800003FE00FF800007FC00FF800007F800FF80
+000FF800FF80003FE000FF8000FFC000FFFFFFFF0000FFFFFFF80000FF8000000000FF80000000
+00FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF80
+00000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF80000000
+00FF8000000000FF8000000000FF8000000000FF8000000000FF80000000FFFFFF800000FFFFFF
+800000FFFFFF80000030317EB037>80 D<7FFFFFFFFFFF007FFFFFFFFFFF007FFFFFFFFFFF007F
+C00FF801FF007E000FF8003F007C000FF8001F0078000FF8000F0078000FF8000F0070000FF800
+0700F0000FF8000780F0000FF8000780F0000FF8000780E0000FF8000380E0000FF8000380E000
+0FF8000380E0000FF8000380E0000FF800038000000FF800000000000FF800000000000FF80000
+0000000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000000F
+F800000000000FF800000000000FF800000000000FF800000000000FF800000000000FF8000000
+00000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000000FF8
+00000000000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000
+000FF800000000000FF800000000000FF8000000007FFFFFFF0000007FFFFFFF0000007FFFFFFF
+000031307DAF38>84 D<FFFFFF8003FFFF80FFFFFF8003FFFF80FFFFFF8003FFFF8000FF800000
+07C00000FF80000003800000FF80000003800000FF80000003800000FF80000003800000FF8000
+0003800000FF80000003800000FF80000003800000FF80000003800000FF80000003800000FF80
+000003800000FF80000003800000FF80000003800000FF80000003800000FF80000003800000FF
+80000003800000FF80000003800000FF80000003800000FF80000003800000FF80000003800000
+FF80000003800000FF80000003800000FF80000003800000FF80000003800000FF800000038000
+00FF80000003800000FF80000003800000FF80000003800000FF80000003800000FF8000000380
+0000FF80000003800000FF80000003800000FF800000038000007F800000038000007F80000007
+0000007FC00000070000003FC000000E0000003FC000000E0000001FE000001C0000000FF00000
+3800000007F800007000000003FC0001E000000000FF801FC0000000003FFFFF80000000000FFF
+FE000000000000FFE000000039317EB03E>I<FFFFFC0000FFFFFFFFFC0000FFFFFFFFFC0000FF
+FF03FF00000003C001FF000000038001FF800000078000FF800000070000FFC000000700007FC0
+00000E00007FC000000E00007FE000001E00003FE000001C00003FF000003C00001FF000003800
+001FF800003800000FF800007000000FFC000070000007FC0000E0000007FC0000E0000007FE00
+01E0000003FE0001C0000003FF0003C0000001FF000380000001FF800380000000FF8007000000
+00FFC00700000000FFC00F000000007FC00E000000007FE01E000000003FE01C000000003FF03C
+000000001FF038000000001FF838000000000FF870000000000FF870000000000FFCF000000000
+07FCE00000000007FFE00000000003FFC00000000003FFC00000000001FF800000000001FF8000
+00000000FF000000000000FF000000000000FF0000000000007E0000000000007E000000000000
+3C0000000000003C00000038317EB03D>I<00FFF0000003FFFE00000F803F80000FC00FE0001F
+E007F0001FE007F0001FE003F8000FC003FC00078003FC00000003FC00000003FC00000003FC00
+000003FC000000FFFC00001FFFFC0000FFE3FC0003FC03FC000FF003FC001FC003FC003FC003FC
+007F8003FC007F8003FC00FF0003FC00FF0003FC00FF0003FC00FF0007FC00FF0007FC007F800D
+FC003FC019FE001FE070FFF007FFE07FF000FF803FF024207E9F27>97 D<01F8000000FFF80000
+00FFF8000000FFF80000000FF800000007F800000007F800000007F800000007F800000007F800
+000007F800000007F800000007F800000007F800000007F800000007F800000007F800000007F8
+00000007F83FE00007F8FFFC0007FBE07F0007FF001F8007FE000FC007FC000FE007F80007F007
+F80007F807F80007F807F80003FC07F80003FC07F80003FC07F80003FE07F80003FE07F80003FE
+07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FC07F80003FC07F80003
+FC07F80007F807F80007F807F80007F007FC000FE007FE000FC007E7003F8007C3C0FE000780FF
+F80007003FC00027327EB12D>I<000FFF00007FFFC001FC01F003F003F007E007F80FE007F81F
+C007F83FC003F03FC001E07F8000007F8000007F800000FF800000FF800000FF800000FF800000
+FF800000FF800000FF800000FF8000007F8000007F8000007F8000003FC0001C3FC0001C1FC000
+380FE0003807E0007003F001E001FC07C0007FFF00000FF8001E207D9F24>I<0000000FC00000
+07FFC0000007FFC0000007FFC00000007FC00000003FC00000003FC00000003FC00000003FC000
+00003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC0
+0000003FC00007F83FC0003FFF3FC000FE07BFC003F801FFC007E0007FC00FE0007FC01FC0003F
+C03FC0003FC03FC0003FC07F80003FC07F80003FC07F80003FC0FF80003FC0FF80003FC0FF8000
+3FC0FF80003FC0FF80003FC0FF80003FC0FF80003FC0FF80003FC07F80003FC07F80003FC07F80
+003FC03FC0003FC03FC0003FC01FC0003FC00FE0007FC007E000FFC003F003FFE001FC0F3FFE00
+7FFE3FFE000FF03FFE27327DB12D>I<000FFC00007FFF8001FC0FC003F003E007E001F00FE001
+F81FC000FC3FC000FE3FC000FE7F80007E7F80007F7F80007FFF80007FFF80007FFFFFFFFFFFFF
+FFFFFF800000FF800000FF800000FF8000007F8000007F8000007F8000003FC000071FC000071F
+C0000E0FE0000E07F0001C03F8007800FE03E0003FFFC00007FE0020207E9F25>I<0001FE0000
+0FFF80001FC3C0007F07E000FE0FF001FE0FF001FC0FF003FC0FF003FC07E003FC018003FC0000
+03FC000003FC000003FC000003FC000003FC000003FC000003FC0000FFFFFC00FFFFFC00FFFFFC
+0003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC
+000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003
+FC000003FC000003FC000003FC000003FC000003FC000003FC00007FFFF0007FFFF0007FFFF000
+1C327EB119>I<001FF007C000FFFE3FE001F83F79F007E00FC3F00FE00FE1F00FC007E0E01FC0
+07F0001FC007F0003FC007F8003FC007F8003FC007F8003FC007F8003FC007F8001FC007F0001F
+C007F0000FC007E0000FE00FE00007E00FC00003F83F000006FFFE00000E1FF000000E00000000
+1E000000001E000000001F000000001F800000001FFFFF80000FFFFFF0000FFFFFFC0007FFFFFE
+0003FFFFFF0003FFFFFF800FFFFFFFC01F00007FC07E00001FE07C00000FE0FC000007E0FC0000
+07E0FC000007E0FC000007E07E00000FC03E00000F803F00001F800FC0007E0007F803FC0001FF
+FFF000001FFF0000242F7E9F28>I<01F8000000FFF8000000FFF8000000FFF80000000FF80000
+0007F800000007F800000007F800000007F800000007F800000007F800000007F800000007F800
+000007F800000007F800000007F800000007F800000007F800000007F807F80007F83FFE0007F8
+783F0007F8C03F8007F9801FC007FB001FC007FE001FE007FC001FE007FC001FE007FC001FE007
+F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE0
+07F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001F
+E007F8001FE007F8001FE007F8001FE0FFFFC3FFFFFFFFC3FFFFFFFFC3FFFF28327DB12D>I<03
+C00007E0000FF0001FF8001FF8001FF8001FF8000FF00007E00003C00000000000000000000000
+000000000000000000000000000000000001F800FFF800FFF800FFF8000FF80007F80007F80007
+F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007
+F80007F80007F80007F80007F80007F80007F80007F80007F800FFFF80FFFF80FFFF8011337DB2
+17>I<01F800FFF800FFF800FFF8000FF80007F80007F80007F80007F80007F80007F80007F800
+07F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F800
+07F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F800
+07F80007F80007F80007F80007F80007F80007F80007F80007F800FFFFC0FFFFC0FFFFC012327D
+B117>108 D<03F007F8001FE000FFF03FFE00FFF800FFF0783F01E0FC00FFF0C03F8300FE000F
+F1801FC6007F0007F3001FCC007F0007F6001FF8007F8007FC001FF0007F8007FC001FF0007F80
+07FC001FF0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F
+8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE000
+7F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0
+007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001F
+E0007F80FFFFC3FFFF0FFFFCFFFFC3FFFF0FFFFCFFFFC3FFFF0FFFFC3E207D9F43>I<03F007F8
+00FFF03FFE00FFF0783F00FFF0C03F800FF1801FC007F3001FC007F6001FE007FC001FE007FC00
+1FE007FC001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8
+001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007
+F8001FE007F8001FE007F8001FE007F8001FE007F8001FE0FFFFC3FFFFFFFFC3FFFFFFFFC3FFFF
+28207D9F2D>I<0007FC0000007FFFC00001FC07F00003F001F80007E000FC000FC0007E001FC0
+007F003FC0007F803F80003F807F80003FC07F80003FC07F80003FC0FF80003FE0FF80003FE0FF
+80003FE0FF80003FE0FF80003FE0FF80003FE0FF80003FE0FF80003FE07F80003FC07F80003FC0
+7F80003FC03FC0007F803FC0007F801FC0007F000FE000FE0007E000FC0003F803F80001FE0FF0
+00007FFFC0000007FC000023207E9F28>I<01F83FE000FFF8FFFC00FFFBE07F00FFFF003F8007
+FE001FC007FC000FE007F8000FF007F80007F807F80007F807F80007FC07F80003FC07F80003FC
+07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003
+FE07F80003FC07F80007FC07F80007FC07F80007F807F80007F807F8000FF007FC000FE007FE00
+1FC007FF003F8007FBC0FE0007F8FFF80007F83FC00007F800000007F800000007F800000007F8
+00000007F800000007F800000007F800000007F800000007F800000007F800000007F8000000FF
+FFC00000FFFFC00000FFFFC00000272E7E9F2D>I<03F03F00FFF07FC0FFF1C3E0FFF187E00FF3
+0FF007F60FF007F60FF007FC07E007FC03C007FC000007FC000007F8000007F8000007F8000007
+F8000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F80000
+07F8000007F8000007F8000007F8000007F80000FFFFE000FFFFE000FFFFE0001C207E9F21>
+114 D<01FF860007FFFE001F00FE003C003E0078001E0078000E00F8000E00F8000E00F8000E00
+FC000000FF800000FFFC00007FFFC0007FFFF0003FFFF8001FFFFC0007FFFE0001FFFF00003FFF
+000000FF8000003F8060001F80E0000F80E0000F80F0000F80F0000F00F8000F00FC001E00FE00
+1C00FF807800F3FFF000C07F800019207D9F20>I<001C0000001C0000001C0000001C0000001C
+0000003C0000003C0000003C0000007C0000007C000000FC000001FC000003FC000007FC00001F
+FFFE00FFFFFE00FFFFFE0003FC000003FC000003FC000003FC000003FC000003FC000003FC0000
+03FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC03
+8003FC038003FC038003FC038003FC038003FC038003FC038001FC038001FC070000FE0700007F
+0E00003FFC000007F000192E7FAD1F>I<01F80007E0FFF803FFE0FFF803FFE0FFF803FFE00FF8
+003FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007
+F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE0
+07F8001FE007F8001FE007F8001FE007F8001FE007F8003FE007F8003FE003F8007FE003F8007F
+E001FC00DFF000FE039FFF007FFF1FFF000FFC1FFF28207D9F2D>I<FFFF801FFCFFFF801FFCFF
+FF801FFC0FF80003C007F800038007FC00078003FC00070003FE000F0001FE000E0001FF000E00
+00FF001C0000FF001C00007F803800007F803800007FC07800003FC07000003FE0F000001FE0E0
+00001FF1E000000FF1C000000FF9C0000007FB80000007FB80000003FF00000003FF00000003FF
+00000001FE00000001FE00000000FC00000000FC00000000780000000078000026207E9F2B>I<
+FFFF1FFFE07FF8FFFF1FFFE07FF8FFFF1FFFE07FF80FF000FE0007800FF800FE00078007F800FE
+00070007F8007F00070003FC007F000E0003FC00FF800E0003FE00FF801E0001FE00FF801C0001
+FE01DFC01C0001FF01DFC03C0000FF03DFE0380000FF838FE07800007F838FE07000007F8707F0
+7000007FC707F0F000003FCF07F8E000003FCE03F8E000001FEE03F9C000001FFC01FDC000001F
+FC01FFC000000FFC01FF8000000FF800FF80000007F800FF00000007F0007F00000007F0007F00
+000003F0007E00000003E0003E00000001E0003C00000001C0001C000035207E9F3A>I<7FFF80
+7FFC7FFF807FFC7FFF807FFC03FE000F0001FE001E0000FF003C0000FF807800007FC07800003F
+E0F000001FE1E000000FF3C000000FFF80000007FF00000003FE00000001FE00000000FF000000
+00FF80000000FFC0000001FFC0000003DFE00000078FF00000078FF800000F07FC00001E03FC00
+003C01FE00007800FF0000F000FF8000E0007FC001E0003FC0FFFC01FFFFFFFC01FFFFFFFC01FF
+FF28207F9F2B>I<FFFF801FFCFFFF801FFCFFFF801FFC0FF80003C007F800038007FC00078003
+FC00070003FE000F0001FE000E0001FF000E0000FF001C0000FF001C00007F803800007F803800
+007FC07800003FC07000003FE0F000001FE0E000001FF1E000000FF1C000000FF9C0000007FB80
+000007FB80000003FF00000003FF00000003FF00000001FE00000001FE00000000FC00000000FC
+000000007800000000780000000070000000007000000000F000000000E000000001E000007C01
+C00000FE03C00000FE03800000FE07800000FE0F000000FC1E000000787C0000003FF00000000F
+C0000000262E7E9F2B>I E /Fl 1 14 df<0001FE00000007FF8000001E01E000007800780000
+E0001C000180000600030000030006000001800C000000C00C000000C018000000603000000030
+30000000303000000030600000001860000000186000000018C00000000CC00000000CC0000000
+0CC00000000CC00000000CC00000000CC00000000CC00000000CC00000000C6000000018600000
+0018600000001830000000303000000030300000003018000000600C000000C00C000000C00600
+0001800300000300018000060000E0001C000078007800001E01E0000007FF80000001FE000026
+2B7DA02D>13 D E /Fm 46 122 df<3C007F00FF80FF80FFC0FFC0FFC07FC03EC000C000C00180
+018001800300030006000E001C00380030000A157B8813>44 D<1C007F007F00FF80FF80FF807F
+007F001C0009097B8813>46 D<000E00001E00007E0007FE00FFFE00FFFE00F8FE0000FE0000FE
+0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE
+0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE
+0000FE007FFFFE7FFFFE7FFFFE17277BA622>49 D<00FF800007FFF0000FFFFC001E03FE003800
+FF807C003F80FE003FC0FF001FC0FF001FE0FF000FE0FF000FE07E000FE03C001FE000001FE000
+001FC000001FC000003F8000003F0000007E000000FC000000F8000001F0000003E00000078000
+000F0000001E0000003C00E0007000E000E000E001C001C0038001C0060001C00FFFFFC01FFFFF
+C03FFFFFC07FFFFFC0FFFFFF80FFFFFF80FFFFFF801B277DA622>I<007F800003FFF00007FFFC
+000F80FE001F007F003F807F003F803F803F803F803F803F801F803F801F003F8000007F000000
+7F0000007E000000FC000001F8000007F00000FFC00000FFC0000001F80000007E0000003F0000
+003F8000001FC000001FC000001FE000001FE03C001FE07E001FE0FF001FE0FF001FE0FF001FC0
+FF003FC0FE003F807C007F003F00FE001FFFFC0007FFF00000FF80001B277DA622>I<00000E00
+00001E0000003E0000007E000000FE000000FE000001FE000003FE0000077E00000E7E00000E7E
+00001C7E0000387E0000707E0000E07E0000E07E0001C07E0003807E0007007E000E007E000E00
+7E001C007E0038007E0070007E00E0007E00FFFFFFF8FFFFFFF8FFFFFFF80000FE000000FE0000
+00FE000000FE000000FE000000FE000000FE000000FE00007FFFF8007FFFF8007FFFF81D277EA6
+22>I<180003001F801F001FFFFE001FFFFC001FFFF8001FFFF0001FFFC0001FFF00001C000000
+1C0000001C0000001C0000001C0000001C0000001C0000001C7FC0001DFFF8001F80FC001E003F
+0008003F0000001F8000001FC000001FC000001FE000001FE018001FE07C001FE0FE001FE0FE00
+1FE0FE001FE0FE001FC0FC001FC078003F8078003F803C007F001F01FE000FFFFC0003FFF00000
+FF80001B277DA622>I<380000003E0000003FFFFFF03FFFFFF03FFFFFF07FFFFFE07FFFFFC07F
+FFFF807FFFFF0070000E0070000E0070001C00E0003800E0007000E000E0000001E0000001C000
+000380000007800000070000000F0000001F0000001E0000003E0000003E0000007E0000007C00
+00007C000000FC000000FC000000FC000000FC000001FC000001FC000001FC000001FC000001FC
+000001FC000001FC000000F80000007000001C297CA822>55 D<00000780000000000780000000
+000FC0000000000FC0000000000FC0000000001FE0000000001FE0000000003FF0000000003FF0
+000000003FF00000000077F80000000077F800000000F7FC00000000E3FC00000000E3FC000000
+01C1FE00000001C1FE00000003C1FF0000000380FF0000000380FF00000007007F80000007007F
+8000000F007FC000000E003FC000000E003FC000001C001FE000001C001FE000003FFFFFF00000
+3FFFFFF000003FFFFFF00000700007F80000700007F80000F00007FC0000E00003FC0000E00003
+FC0001C00001FE0001C00001FE0003C00001FF00FFFE003FFFFCFFFE003FFFFCFFFE003FFFFC2E
+297EA833>65 D<FFFFFFF800FFFFFFFF00FFFFFFFFC003F8001FE003F8000FF003F80007F803F8
+0003F803F80003FC03F80003FC03F80001FC03F80001FC03F80001FC03F80003FC03F80003F803
+F80003F803F80007F003F8000FF003F8001FC003F800FF8003FFFFFE0003FFFFFFC003F8000FF0
+03F80003F803F80001FC03F80001FE03F80000FE03F80000FE03F80000FF03F80000FF03F80000
+FF03F80000FF03F80000FF03F80000FF03F80000FE03F80001FE03F80003FC03F80007FC03F800
+1FF8FFFFFFFFE0FFFFFFFFC0FFFFFFFE0028297DA830>I<00007FE0030007FFFC07001FFFFF0F
+007FF00F9F00FF0001FF01FC0000FF03F800007F07F000003F0FE000001F1FC000001F1FC00000
+0F3F8000000F3F800000077F800000077F800000077F00000000FF00000000FF00000000FF0000
+0000FF00000000FF00000000FF00000000FF00000000FF00000000FF000000007F000000007F80
+0000007F800000073F800000073F800000071FC00000071FC000000E0FE000000E07F000001C03
+F800003C01FC00007800FF0001F0007FF007C0001FFFFF800007FFFE0000007FF00028297CA831
+>I<FFFFFFFFE0FFFFFFFFE0FFFFFFFFE003FC001FE003FC0007F003FC0001F003FC0001F003FC
+0000F003FC00007003FC00007003FC00007003FC01C07803FC01C03803FC01C03803FC01C03803
+FC03C00003FC03C00003FC0FC00003FFFFC00003FFFFC00003FFFFC00003FC0FC00003FC03C000
+03FC03C00003FC01C00E03FC01C00E03FC01C00E03FC01C01C03FC00001C03FC00001C03FC0000
+1C03FC00003C03FC00003803FC00007803FC0000F803FC0001F803FC0003F803FC001FF8FFFFFF
+FFF0FFFFFFFFF0FFFFFFFFF027297EA82C>69 D<FFFFFFFFC0FFFFFFFFC0FFFFFFFFC003FC003F
+C003FC000FE003FC0003E003FC0001E003FC0001E003FC0000E003FC0000E003FC0000E003FC00
+00F003FC01C07003FC01C07003FC01C07003FC01C00003FC03C00003FC03C00003FC0FC00003FF
+FFC00003FFFFC00003FFFFC00003FC0FC00003FC03C00003FC03C00003FC01C00003FC01C00003
+FC01C00003FC01C00003FC00000003FC00000003FC00000003FC00000003FC00000003FC000000
+03FC00000003FC00000003FC000000FFFFFC0000FFFFFC0000FFFFFC000024297EA82A>I<0000
+7FE003000007FFFC0700001FFFFF0F00007FF00F9F0000FF0001FF0001FC0000FF0003F800007F
+0007F000003F000FE000001F001FC000001F001FC000000F003F8000000F003F80000007007F80
+000007007F80000007007F0000000000FF0000000000FF0000000000FF0000000000FF00000000
+00FF0000000000FF0000000000FF0000000000FF0000000000FF0000FFFFF87F0000FFFFF87F80
+00FFFFF87F800000FF003F800000FF003F800000FF001FC00000FF001FC00000FF000FE00000FF
+0007F00000FF0003F80000FF0001FC0000FF0000FF0001FF00007FF007FF00001FFFFF9F000007
+FFFE0F0000007FF003002D297CA835>I<FFFFF00FFFFFFFFFF00FFFFFFFFFF00FFFFF03FC0000
+3FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003
+FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC0000
+3FC003FC00003FC003FFFFFFFFC003FFFFFFFFC003FFFFFFFFC003FC00003FC003FC00003FC003
+FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC0000
+3FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003FC00003FC003
+FC00003FC003FC00003FC0FFFFF00FFFFFFFFFF00FFFFFFFFFF00FFFFF30297EA835>I<FFFFFC
+FFFFFCFFFFFC01FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE00
+01FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE00
+01FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE0001FE00FFFFFCFFFFFC
+FFFFFC16297FA819>I<FFFE0000003FFF80FFFE0000003FFF80FFFF0000007FFF8003FF000000
+7FE00003FF0000007FE00003BF800000EFE00003BF800000EFE000039FC00001CFE000039FC000
+01CFE000038FE000038FE000038FE000038FE000038FE000038FE0000387F000070FE0000387F0
+00070FE0000383F8000E0FE0000383F8000E0FE0000381FC001C0FE0000381FC001C0FE0000381
+FC001C0FE0000380FE00380FE0000380FE00380FE00003807F00700FE00003807F00700FE00003
+803F80E00FE00003803F80E00FE00003803F80E00FE00003801FC1C00FE00003801FC1C00FE000
+03800FE3800FE00003800FE3800FE000038007F7000FE000038007F7000FE000038007F7000FE0
+00038003FE000FE000038003FE000FE000038001FC000FE000038001FC000FE000038000F8000F
+E000FFFE00F803FFFF80FFFE00F803FFFF80FFFE007003FFFF8039297DA840>77
+D<FFFC00007FFFFFFE00007FFFFFFF00007FFF03FF800001C003FFC00001C003BFE00001C0039F
+E00001C0039FF00001C0038FF80001C00387FC0001C00383FE0001C00381FF0001C00380FF8001
+C003807F8001C003807FC001C003803FE001C003801FF001C003800FF801C0038007FC01C00380
+03FC01C0038003FE01C0038001FF01C0038000FF81C00380007FC1C00380003FE1C00380001FF1
+C00380000FF1C00380000FF9C003800007FDC003800003FFC003800001FFC003800000FFC00380
+00007FC0038000007FC0038000003FC0038000001FC0038000000FC00380000007C0FFFE000003
+C0FFFE000001C0FFFE000001C030297EA835>I<FFFFFFF800FFFFFFFF00FFFFFFFFC003FC003F
+E003FC0007F003FC0003F803FC0003FC03FC0001FC03FC0001FE03FC0001FE03FC0001FE03FC00
+01FE03FC0001FE03FC0001FE03FC0001FE03FC0001FC03FC0003FC03FC0003F803FC0007F003FC
+003FE003FFFFFF8003FFFFFE0003FC00000003FC00000003FC00000003FC00000003FC00000003
+FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC000000
+03FC00000003FC00000003FC000000FFFFF00000FFFFF00000FFFFF0000027297EA82E>80
+D<FFFFFFE00000FFFFFFFE0000FFFFFFFF800003FC003FE00003FC000FF00003FC0007F80003FC
+0003FC0003FC0001FC0003FC0001FE0003FC0001FE0003FC0001FE0003FC0001FE0003FC0001FE
+0003FC0001FE0003FC0001FC0003FC0003F80003FC0007F80003FC000FE00003FC003FC00003FF
+FFFE000003FFFFFE000003FC00FF800003FC003FC00003FC001FE00003FC000FF00003FC0007F8
+0003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC
+0007F80003FC0007F80003FC0007F80E03FC0007F80E03FC0003F80E03FC0001FC1CFFFFF000FE
+1CFFFFF0007FF8FFFFF0000FE02F297EA832>82 D<00FF00C003FFE1C00FFFF9C01F80FFC03F00
+3FC03E000FC07C0007C07C0007C0FC0003C0FC0003C0FC0001C0FE0001C0FE0001C0FF000000FF
+C000007FFC00007FFFE0003FFFF8001FFFFE001FFFFF0007FFFF8003FFFFC000FFFFC0000FFFE0
+00007FE000001FF000000FF0000007F0E00003F0E00003F0E00003F0E00003F0F00003E0F00003
+E0F80007E0FC0007C0FF000F80FFE01F80E3FFFF00E1FFFC00C01FF0001C297CA825>I<FFFFF0
+00FFFEFFFFF000FFFEFFFFF000FFFE03FC0000038003FC0000038003FC0000038003FC00000380
+03FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC00
+00038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC00000380
+03FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC00
+00038003FC0000038003FC0000038003FC0000038003FC0000038001FC0000070001FE00000700
+00FE00000E00007F00000E00003F00003C00001FC0007800000FF003F0000007FFFFE0000000FF
+FF800000001FFC00002F297EA834>85 D<FFFFF0007FFFFFFFF0007FFFFFFFF0007FFF03FE0000
+01C001FE0000038001FE0000038000FF0000070000FF0000070000FF80000F00007F80000E0000
+7FC0000E00003FC0001C00003FE0001C00001FE0003800001FE0003800001FF0007800000FF000
+7000000FF800F0000007F800E0000007FC00E0000003FC01C0000003FC01C0000003FE03C00000
+01FE0380000001FF0780000000FF0700000000FF87000000007F8E000000007F8E000000007FDE
+000000003FDC000000003FFC000000001FF8000000001FF8000000000FF0000000000FF0000000
+000FF00000000007E00000000007E00000000003C00000000003C0000030297FA833>I<FFFFE0
+FFFFE01FFFC0FFFFE0FFFFE01FFFC0FFFFE0FFFFE01FFFC003FC0003FC0000700003FC0003FC00
+00700003FE0003FE0000F00001FE0001FE0000E00001FE0001FE0000E00001FF0001FF0001E000
+00FF0001FF0001C00000FF0001FF0001C000007F8003FF80038000007F8003FF80038000007FC0
+07FFC0078000003FC0073FC0070000003FC0073FC0070000003FE00F3FE00F0000001FE00E1FE0
+0E0000001FE00E1FE00E0000000FF01C0FF01C0000000FF01C0FF01C0000000FF01C0FF81C0000
+0007F83807F83800000007F83807F83800000007FC7807FC7800000003FC7003FC7000000003FC
+7003FC7000000003FEF003FEF000000001FEE001FEE000000001FEE001FEE000000000FFC000FF
+C000000000FFC000FFC000000000FFC000FFC0000000007F80007F80000000007F80007F800000
+00007F80007F80000000003F00003F00000000003F00003F00000000003F00003F00000000001E
+00001E00000000001E00001E00000042297FA845>I<03FF80000FFFF0001F01FC003F80FE003F
+807F003F803F003F803F801F003F8000003F8000003F8000003F8000003F80003FFF8001FC3F80
+0FE03F801F803F803F003F807E003F80FC003F80FC003F80FC003F80FC003F80FC005F807E00DF
+803F839FFC1FFE0FFC03F803FC1E1B7E9A21>97 D<FFE00000FFE00000FFE000000FE000000FE0
+00000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000F
+E000000FE1FE000FE7FF800FFE07E00FF803F00FF001F80FE000FC0FE000FC0FE0007E0FE0007E
+0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007E0FE000
+7E0FE0007E0FE000FC0FE000FC0FF001F80FF803F00F9C0FE00F0FFF800E01FC00202A7EA925>
+I<003FF00001FFFC0003F03E000FC07F001F807F003F007F003F007F007F003E007E0000007E00
+0000FE000000FE000000FE000000FE000000FE000000FE000000FE0000007E0000007E0000007F
+0000003F0003803F8003801F8007000FE00E0003F83C0001FFF800003FC000191B7E9A1E>I<00
+007FF000007FF000007FF0000007F0000007F0000007F0000007F0000007F0000007F0000007F0
+000007F0000007F0000007F0000007F0000007F0003F87F001FFF7F007F03FF00FC00FF01F8007
+F03F0007F03F0007F07E0007F07E0007F07E0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE00
+07F0FE0007F0FE0007F0FE0007F07E0007F07E0007F03F0007F03F0007F01F800FF00FC01FF007
+E07FFF01FFE7FF007F87FF202A7EA925>I<003FC00001FFF00003E07C000F803E001F801F001F
+001F003F000F807E000F807E000FC07E000FC0FE0007C0FE0007C0FFFFFFC0FFFFFFC0FE000000
+FE000000FE0000007E0000007E0000007F0000003F0001C01F0001C00F80038007C0070003F01E
+0000FFFC00003FE0001A1B7E9A1F>I<0007F8003FFC007E3E01FC7F03F87F03F07F07F07F07F0
+3E07F00007F00007F00007F00007F00007F00007F000FFFFC0FFFFC0FFFFC007F00007F00007F0
+0007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F0
+0007F00007F00007F00007F00007F0007FFF807FFF807FFF80182A7EA915>I<007F80F001FFE3
+F807C0FE1C0F807C7C1F003E7C1F003E103F003F003F003F003F003F003F003F003F003F003F00
+3F001F003E001F003E000F807C0007C0F80005FFE0000C7F8000180000001C0000001C0000001E
+0000001FFFF8001FFFFF000FFFFFC007FFFFE003FFFFF00FFFFFF03E0007F07C0001F8F80000F8
+F80000F8F80000F8F80000F87C0001F07C0001F03F0007E00FC01F8007FFFF00007FF0001E287E
+9A22>I<FFE00000FFE00000FFE000000FE000000FE000000FE000000FE000000FE000000FE000
+000FE000000FE000000FE000000FE000000FE000000FE000000FE07E000FE1FF800FE30FC00FE4
+0FE00FE807E00FF807F00FF007F00FF007F00FE007F00FE007F00FE007F00FE007F00FE007F00F
+E007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F0
+0FE007F0FFFE3FFFFFFE3FFFFFFE3FFF202A7DA925>I<07000F801FC03FE03FE03FE01FC00F80
+07000000000000000000000000000000FFE0FFE0FFE00FE00FE00FE00FE00FE00FE00FE00FE00F
+E00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE0FFFEFFFEFFFE0F2B7EAA12>I<FF
+E0FFE0FFE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE0
+0FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE0FF
+FEFFFEFFFE0F2A7EA912>108 D<FFC07F001FC000FFC1FFC07FF000FFC307E0C1F8000FC407F1
+01FC000FC803F200FC000FD803FE00FE000FD003FC00FE000FD003FC00FE000FE003F800FE000F
+E003F800FE000FE003F800FE000FE003F800FE000FE003F800FE000FE003F800FE000FE003F800
+FE000FE003F800FE000FE003F800FE000FE003F800FE000FE003F800FE000FE003F800FE000FE0
+03F800FE000FE003F800FE000FE003F800FE000FE003F800FE00FFFE3FFF8FFFE0FFFE3FFF8FFF
+E0FFFE3FFF8FFFE0331B7D9A38>I<FFC07E00FFC1FF80FFC30FC00FC40FE00FC807E00FD807F0
+0FD007F00FD007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007
+F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F0FFFE3FFFFFFE
+3FFFFFFE3FFF201B7D9A25>I<003FE00001FFFC0003F07E000FC01F801F800FC03F0007E03F00
+07E07E0003F07E0003F07E0003F0FE0003F8FE0003F8FE0003F8FE0003F8FE0003F8FE0003F8FE
+0003F8FE0003F87E0003F07E0003F03F0007E03F0007E01F800FC00FC01F8007F07F0001FFFC00
+003FE0001D1B7E9A22>I<FFE1FE00FFE7FF80FFFE0FE00FF803F00FF001F80FE001FC0FE000FC
+0FE000FE0FE000FE0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE000
+7F0FE0007E0FE000FE0FE000FE0FE000FC0FE001FC0FF001F80FF803F00FFC0FE00FEFFF800FE1
+FC000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE00000FF
+FE0000FFFE0000FFFE000020277E9A25>I<FFC3E0FFC7F8FFCC7C0FD8FE0FD0FE0FD0FE0FF0FE
+0FE07C0FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE000
+0FE0000FE0000FE0000FE000FFFF00FFFF00FFFF00171B7E9A1B>114 D<03FE300FFFF03E03F0
+7800F07000F0F00070F00070F80070FE0000FFE0007FFF007FFFC03FFFE01FFFF007FFF800FFF8
+0007FC0000FCE0007CE0003CF0003CF00038F80038FC0070FF01E0E7FFC0C1FF00161B7E9A1B>
+I<00700000700000700000700000F00000F00000F00001F00003F00003F00007F0001FFFE0FFFF
+E0FFFFE007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F0
+0007F00007F07007F07007F07007F07007F07007F07007F07003F0E001F8C000FFC0003F001426
+7FA51A>I<FFE07FF0FFE07FF0FFE07FF00FE007F00FE007F00FE007F00FE007F00FE007F00FE0
+07F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00FE007F00F
+E007F00FE007F00FE007F00FE00FF00FE00FF007E017F003F067FF01FFC7FF007F87FF201B7D9A
+25>I<FFFE07FFFFFE07FFFFFE07FF07F000E007F000E007F801E003F801C003F801C001FC0380
+01FC038001FE078000FE070000FF0F00007F0E00007F0E00003F9C00003F9C00003FFC00001FF8
+00001FF800000FF000000FF000000FF0000007E0000007E0000003C0000003C000201B7F9A23>
+I<FFFC7FFC1FFCFFFC7FFC1FFCFFFC7FFC1FFC0FE00FE001C007F007E0038007F007E0038007F8
+07F0078003F807F0070003F807F8070001FC0FF80E0001FC0FF80E0001FE1FFC1E0000FE1CFC1C
+0000FE1CFE1C0000FF387E3C00007F387E3800007F787F3800003FF03F7000003FF03F7000003F
+E01FF000001FE01FE000001FE01FE000000FC00FC000000FC00FC000000FC00FC0000007800780
+000007800780002E1B7F9A31>I<FFFC1FFEFFFC1FFEFFFC1FFE07F0078003F8070001FC0F0001
+FE1E0000FE3C00007F7800003FF800003FF000001FE000000FE0000007F0000007F800000FF800
+001FFC00003DFE000038FF0000787F0000F03F8001E03FC003C01FE003800FE0FFF03FFFFFF03F
+FFFFF03FFF201B7F9A23>I<FFFE07FFFFFE07FFFFFE07FF07F000E007F000E007F801E003F801
+C003F801C001FC038001FC038001FE078000FE070000FF0F00007F0E00007F0E00003F9C00003F
+9C00003FFC00001FF800001FF800000FF000000FF0000007F0000007E0000007E0000003C00000
+03C000000380000003800000078000380700007C070000FE0E0000FE0E0000FE1C0000FE380000
+7C7000003FE000000F80000020277F9A23>I E /Fn 75 127 df<70F8F8F8F8F8F8F8F8F8F8F8
+F8F8F8F8F870000000000070F8F8F870051C779B18>33 D<4010E038F078E038E038E038E038E0
+38E038E038E038E038E03860300D0E7B9C18>I<030600078F00078F00078F00078F00078F0007
+8F007FFFC0FFFFE0FFFFE07FFFC00F1E000F1E000F1E000F1E000F1E000F1E007FFFC0FFFFE0FF
+FFE07FFFC01E3C001E3C001E3C001E3C001E3C001E3C000C1800131C7E9B18>I<00C00001C000
+01C00001C00003F0000FFC003FFE007DCF0071C700E1C380E1C780E1C780E1C780F1C00079C000
+3DC0001FE0000FF80003FC0001DE0001CF0001C70061C380F1C380F1C380E1C380E1C70071C700
+79DE003FFE001FF80007E00001C00001C00001C00000C00011247D9F18>I<3803007C07807C07
+80EE0F80EE0F00EE0F00EE1F00EE1E00EE1E00EE3E007C3C007C3C00387C0000780000780000F8
+0000F00001F00001E00001E00003E00003C00003C00007C0000783800787C00F87C00F0EE00F0E
+E01F0EE01E0EE01E0EE03E0EE03C07C03C07C018038013247E9F18>I<01C00007E0000FF0000E
+70001C38001C38001C38001C38001C73F01C73F01CE3F00FE3800FC7000F87000F07001F0E003F
+0E007B8E0073DC00E1DC00E0F800E0F800E07070E0787070FC707FFFE03FCFE00F03C0141C7F9B
+18>I<387C7C7E3E0E0E0E1C1C38F8F0C0070E789B18>I<007000F001E003C007800F001E001C00
+380038007000700070007000E000E000E000E000E000E000E000E0007000700070007000380038
+001C001E000F00078003C001F000F000700C24799F18>I<6000F00078003C001E000F00078003
+8001C001C000E000E000E000E00070007000700070007000700070007000E000E000E000E001C0
+01C0038007800F001E003C007800F00060000C247C9F18>I<01C00001C00001C00001C000C1C1
+80F1C780F9CF807FFF001FFC0007F00007F0001FFC007FFF00F9CF80F1C780C1C18001C00001C0
+0001C00001C00011147D9718>I<00600000F00000F00000F00000F00000F00000F00000F0007F
+FFC0FFFFE0FFFFE07FFFC000F00000F00000F00000F00000F00000F00000F00000600013147E97
+18>I<1C3E7E7F3F1F070E1E7CF860080C788518>I<7FFF00FFFF80FFFF807FFF0011047D8F18>
+I<3078FCFC78300606778518>I<000300000780000780000F80000F00001F00001E00001E0000
+3E00003C00007C0000780000780000F80000F00001F00001E00003E00003C00003C00007C00007
+80000F80000F00000F00001F00001E00003E00003C00003C00007C0000780000F80000F00000F0
+000060000011247D9F18>I<01F00007FC000FFE001F1F001C07003803807803C07001C07001C0
+E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0F001E07001C07001C07803C0
+3803801C07001F1F000FFE0007FC0001F000131C7E9B18>I<01800380038007800F803F80FF80
+FB80438003800380038003800380038003800380038003800380038003800380038003807FFCFF
+FE7FFC0F1C7B9B18>I<03F0000FFE003FFF007C0F807003C0E001C0F000E0F000E06000E00000
+E00000E00001C00001C00003C0000780000F00001E00003C0000780000F00001E00007C0000F80
+001E00E03C00E07FFFE0FFFFE07FFFE0131C7E9B18>I<001F00003F0000770000770000E70001
+E70001C7000387000787000707000E07001E07003C0700380700780700F00700FFFFF8FFFFF8FF
+FFF8000700000700000700000700000700000700007FF000FFF8007FF0151C7F9B18>52
+D<007E0001FF0007FF800F83C01E03C01C03C0380180380000700000700000E1F800E7FE00FFFF
+00FE0780F803C0F001C0F000E0E000E0F000E07000E07000E07000E03801C03C03C01E07800FFF
+0007FE0001F800131C7E9B18>54 D<3078FCFC783000000000000000003078FCFC783006147793
+18>58 D<183C7E7E3C180000000000000000183C7E7E3E1E0E1C3C78F060071A789318>I<0003
+00000780001F80003F00007E0001FC0003F00007E0001FC0003F00007E0000FC0000FC00007E00
+003F00001FC00007E00003F00001FC00007E00003F00001F8000078000030011187D9918>I<7F
+FFC0FFFFE0FFFFE0FFFFE0000000000000000000000000FFFFE0FFFFE0FFFFE07FFFC0130C7E93
+18>I<600000F00000FC00007E00003F00001FC00007E00003F00001FC00007E00003F00001F80
+001F80003F00007E0001FC0003F00007E0001FC0003F00007E0000FC0000F0000060000011187D
+9918>I<0FF0003FFC007FFF00700F00F00380F00380600780000F00003E00007C0001F00001E0
+0003C00003C00003C00003C00003C00003800000000000000000000000000000000003800007C0
+0007C00007C000038000111C7D9B18>I<00700000F80000F80000D80000D80001DC0001DC0001
+DC00018C00038E00038E00038E00038E000306000707000707000707000707000FFF800FFF800F
+FF800E03800E03801C01C01C01C07F07F0FF8FF87F07F0151C7F9B18>65
+D<7FF800FFFE007FFF001C0F801C03C01C03C01C01E01C00E01C00E01C00F01C00701C00701C00
+701C00701C00701C00701C00701C00701C00F01C00E01C00E01C01E01C01C01C03C01C0F807FFF
+00FFFE007FF800141C7F9B18>68 D<FFFFF0FFFFF0FFFFF01C00701C00701C00701C00701C0000
+1C00001C0E001C0E001C0E001FFE001FFE001FFE001C0E001C0E001C0E001C00001C00001C0038
+1C00381C00381C00381C0038FFFFF8FFFFF8FFFFF8151C7F9B18>I<FFFFE0FFFFE0FFFFE01C00
+E01C00E01C00E01C00E01C00001C00001C1C001C1C001C1C001FFC001FFC001FFC001C1C001C1C
+001C1C001C00001C00001C00001C00001C00001C00001C0000FFC000FFC000FFC000131C7E9B18
+>I<7F07F0FF8FF87F07F01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01F
+FFC01FFFC01FFFC01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C07F
+07F0FF8FF87F07F0151C7F9B18>72 D<7FFF00FFFF807FFF0001C00001C00001C00001C00001C0
+0001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C0
+0001C00001C00001C00001C0007FFF00FFFF807FFF00111C7D9B18>I<7FE000FFE0007FE0000E
+00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E
+00000E00000E00000E00000E00700E00700E00700E00700E00707FFFF0FFFFF07FFFF0141C7F9B
+18>76 D<7E07F0FF0FF87F07F01D81C01D81C01D81C01DC1C01CC1C01CC1C01CE1C01CE1C01CE1
+C01C61C01C71C01C71C01C31C01C39C01C39C01C39C01C19C01C19C01C1DC01C0DC01C0DC01C0D
+C07F07C0FF87C07F03C0151C7F9B18>78 D<0FF8003FFE007FFF00780F00700700F00780E00380
+E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380
+E00380E00380F00780700700780F007FFF003FFE000FF800111C7D9B18>I<FFFE00FFFF80FFFF
+C01C03C01C01E01C00E01C00701C00701C00701C00701C00701C00E01C01E01C03C01FFFC01FFF
+801FFE001C00001C00001C00001C00001C00001C00001C00001C0000FF8000FF8000FF8000141C
+7F9B18>I<7FF800FFFE007FFF001C0F801C03801C03C01C01C01C01C01C01C01C03C01C03801C
+0F801FFF001FFE001FFE001C0F001C07001C03801C03801C03801C03801C03801C039C1C039C1C
+039C7F01F8FF81F87F00F0161C7F9B18>82 D<03F3801FFF803FFF807C0F80700780E00380E003
+80E00380E000007000007800003F00001FF00007FE0000FF00000F800003C00001C00000E00000
+E06000E0E000E0E001E0F001C0F80780FFFF80FFFE00E7F800131C7E9B18>I<7FFFF8FFFFF8FF
+FFF8E07038E07038E07038E0703800700000700000700000700000700000700000700000700000
+700000700000700000700000700000700000700000700000700000700007FF0007FF0007FF0015
+1C7F9B18>I<FF83FEFF83FEFF83FE1C00701C00701C00701C00701C00701C00701C00701C0070
+1C00701C00701C00701C00701C00701C00701C00701C00701C00701C00701C00700E00E00F01E0
+0783C003FF8001FF00007C00171C809B18>I<FF07F8FF07F8FF07F81C01C01E03C00E03800F07
+80070700070700038E00038E0001DC0001DC0001DC0000F80000F8000070000070000070000070
+0000700000700000700000700000700001FC0003FE0001FC00151C7F9B18>89
+D<FFF8FFF8FFF8E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000
+E000E000E000E000E000E000E000E000E000E000E000E000E000E000FFF8FFF8FFF80D24779F18
+>91 D<600000F00000F00000F800007800007C00003C00003C00003E00001E00001F00000F0000
+0F00000F800007800007C00003C00003C00003E00001E00001F00000F00000F800007800007800
+007C00003C00003E00001E00001E00001F00000F00000F8000078000078000030011247D9F18>
+I<FFF8FFF8FFF80038003800380038003800380038003800380038003800380038003800380038
+00380038003800380038003800380038003800380038003800380038FFF8FFF8FFF80D247F9F18
+>I<018007C01FF07EFCF83EE00E0F067C9B18>I<7FFF00FFFF80FFFF807FFF0011047D7F18>I<
+061E3E387070E0E0E0F8FC7C7C38070E789E18>I<1FE0003FF8007FFC00781E00300E00000700
+00070000FF0007FF001FFF007F0700780700E00700E00700E00700F00F00781F003FFFF01FFBF0
+07E1F014147D9318>I<7E0000FE00007E00000E00000E00000E00000E00000E00000E3E000EFF
+800FFFC00FC1E00F80E00F00700E00700E00380E00380E00380E00380E00380E00380F00700F00
+700F80E00FC1E00FFFC00EFF80063E00151C809B18>I<01FE0007FF001FFF803E078038030070
+0000700000E00000E00000E00000E00000E00000E000007000007001C03801C03E03C01FFF8007
+FF0001FC0012147D9318>I<001F80003F80001F8000038000038000038000038000038003E380
+0FFB801FFF803C1F80380F80700780700380E00380E00380E00380E00380E00380E00380700780
+700780380F803C1F801FFFF00FFBF803E3F0151C7E9B18>I<01F00007FC001FFE003E0F003807
+80700380700380E001C0E001C0FFFFC0FFFFC0FFFFC0E000007000007001C03801C03E03C01FFF
+8007FF0001FC0012147D9318>I<001F80007FC000FFE000E1E001C0C001C00001C00001C0007F
+FFC0FFFFC0FFFFC001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001
+C00001C00001C00001C0007FFF007FFF007FFF00131C7F9B18>I<01E1F007FFF80FFFF81E1E30
+1C0E003807003807003807003807003807001C0E001E1E001FFC001FF80039E0003800001C0000
+1FFE001FFFC03FFFE07801F0700070E00038E00038E00038E000387800F07E03F01FFFC00FFF80
+01FC00151F7F9318>I<7E0000FE00007E00000E00000E00000E00000E00000E00000E3E000EFF
+800FFFC00FC1C00F80E00F00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00
+E00E00E00E00E07FC3FCFFE7FE7FC3FC171C809B18>I<03800007C00007C00007C00003800000
+00000000000000000000007FC000FFC0007FC00001C00001C00001C00001C00001C00001C00001
+C00001C00001C00001C00001C00001C00001C00001C000FFFF00FFFF80FFFF00111D7C9C18>I<
+7FE000FFE0007FE00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E000
+00E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E0007FFFC0
+FFFFE07FFFC0131C7E9B18>108 D<7CE0E000FFFBF8007FFFF8001F1F1C001E1E1C001E1E1C00
+1C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C
+001C1C1C007F1F1F00FFBFBF807F1F1F001914819318>I<7E3E00FEFF807FFFC00FC1C00F80E0
+0F00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E07FC3FC
+FFE7FE7FC3FC1714809318>I<01F0000FFE001FFF003E0F803803807001C07001C0E000E0E000
+E0E000E0E000E0E000E0F001E07001C07803C03C07803E0F801FFF000FFE0001F00013147E9318
+>I<7E3E00FEFF807FFFC00FC1E00F80E00F00700E00700E00380E00380E00380E00380E00380E
+00380F00700F00700F80E00FC1E00FFFC00EFF800E3E000E00000E00000E00000E00000E00000E
+00000E00007FC000FFE0007FC000151E809318>I<01E38007FB801FFF803E1F80380F80700780
+700780E00380E00380E00380E00380E00380E00380700780700780380F803C1F801FFF800FFB80
+03E380000380000380000380000380000380000380000380003FF8003FF8003FF8151E7E9318>
+I<7F87E0FF9FF07FBFF803F87803F03003E00003C00003C0000380000380000380000380000380
+000380000380000380000380007FFE00FFFF007FFE0015147F9318>I<07F7003FFF007FFF0078
+0F00E00700E00700E007007C00007FE0001FFC0003FE00001F00600780E00380E00380F00380F8
+0F00FFFF00FFFC00E7F00011147D9318>I<0180000380000380000380000380007FFFC0FFFFC0
+FFFFC00380000380000380000380000380000380000380000380000380000380400380E00380E0
+0380E001C1C001FFC000FF80003E0013197F9818>I<7E07E0FE0FE07E07E00E00E00E00E00E00
+E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E01E00F03E007FFFC03FF
+FE01FCFC1714809318>I<7F8FF0FF8FF87F8FF01E03C00E03800E03800E038007070007070007
+0700038E00038E00038E00038E0001DC0001DC0001DC0000F80000F80000700015147F9318>I<
+FF8FF8FF8FF8FF8FF83800E03800E03800E01C01C01C01C01C71C01CF9C01CF9C01CD9C01CD9C0
+0DDD800DDD800DDD800D8D800F8F800F8F8007070015147F9318>I<7F8FF07F9FF07F8FF00707
+00078E00039E0001DC0001F80000F80000700000F00000F80001DC00039E00038E000707000F07
+807F8FF0FF8FF87F8FF015147F9318>I<7F8FF0FF8FF87F8FF00E01C00E03800E038007038007
+0700070700038700038600038E0001CE0001CE0000CC0000CC0000DC0000780000780000780000
+700000700000700000F00000E00079E0007BC0007F80003F00001E0000151E7F9318>I<3FFFF0
+7FFFF07FFFF07001E07003C0700780000F00001E00003C0000F80001F00003C0000780000F0070
+1E00703C0070780070FFFFF0FFFFF0FFFFF014147F9318>I<0007E0001FE0007FE000780000E0
+0000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00001E0007FC000FF80
+00FF80007FC00001E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E0
+0000E000007800007FE0001FE00007E013247E9F18>I<60F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0
+F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0600424769F18>I<7C0000FF0000FFC00003C000
+00E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000F000007FC0
+003FE0003FE0007FC000F00000E00000E00000E00000E00000E00000E00000E00000E00000E000
+00E00000E00003C000FFC000FF00007C000013247E9F18>I<060C1F1E3FBEFBF8F1F060C00F06
+7C9B18>I E /Fo 75 123 df<001F83E000F06E3001C078780380F8780300F030070070000700
+70000700700007007000070070000700700007007000FFFFFF8007007000070070000700700007
+007000070070000700700007007000070070000700700007007000070070000700700007007000
+07007000070070000700700007007000070070007FE3FF001D20809F1B>11
+D<003F0000E0C001C0C00381E00701E00701E0070000070000070000070000070000070000FFFF
+E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700
+E00700E00700E00700E00700E00700E07FC3FE1720809F19>I<003FE000E0E001C1E00381E007
+00E00700E00700E00700E00700E00700E00700E00700E0FFFFE00700E00700E00700E00700E007
+00E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E007
+00E07FE7FE1720809F19>I<001F81F80000F04F040001C07C06000380F80F000300F00F000700
+F00F00070070000007007000000700700000070070000007007000000700700000FFFFFFFF0007
+007007000700700700070070070007007007000700700700070070070007007007000700700700
+070070070007007007000700700700070070070007007007000700700700070070070007007007
+00070070070007007007007FE3FE3FF02420809F26>I<7038F87CFC7EFC7E743A040204020402
+0804080410081008201040200F0E7E9F17>34 D<70F8FCFC74040404080810102040060E7C9F0D
+>39 D<0020004000800100020006000C000C00180018003000300030007000600060006000E000
+E000E000E000E000E000E000E000E000E000E000E0006000600060007000300030003000180018
+000C000C000600020001000080004000200B2E7DA112>I<800040002000100008000C00060006
+000300030001800180018001C000C000C000C000E000E000E000E000E000E000E000E000E000E0
+00E000E000C000C000C001C001800180018003000300060006000C00080010002000400080000B
+2E7DA112>I<70F8FCFC74040404080810102040060E7C840D>44 D<FFC0FFC00A027F8A0F>I<70
+F8F8F87005057C840D>I<03F0000E1C001C0E00180600380700700380700380700380700380F0
+03C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C070
+03807003807003807807803807001806001C0E000E1C0003F000121F7E9D17>48
+D<018003800F80F380038003800380038003800380038003800380038003800380038003800380
+03800380038003800380038003800380038007C0FFFE0F1E7C9D17>I<03F0000C1C00100E0020
+0700400780800780F007C0F803C0F803C0F803C02007C00007C0000780000780000F00000E0000
+1C0000380000700000600000C0000180000300000600400C00401800401000803FFF807FFF80FF
+FF80121E7E9D17>I<03F0000C1C00100E00200F00780F80780780780780380F80000F80000F00
+000F00000E00001C0000380003F000003C00000E00000F000007800007800007C02007C0F807C0
+F807C0F807C0F00780400780400F00200E001C3C0003F000121F7E9D17>I<000600000600000E
+00000E00001E00002E00002E00004E00008E00008E00010E00020E00020E00040E00080E00080E
+00100E00200E00200E00400E00C00E00FFFFF0000E00000E00000E00000E00000E00000E00000E
+0000FFE0141E7F9D17>I<1803001FFE001FFC001FF8001FE00010000010000010000010000010
+000010000011F000161C00180E001007001007800003800003800003C00003C00003C07003C0F0
+03C0F003C0E00380400380400700200600100E000C380003E000121F7E9D17>I<007C00018200
+0701000E03800C07801C0780380300380000780000700000700000F1F000F21C00F40600F80700
+F80380F80380F003C0F003C0F003C0F003C0F003C07003C07003C0700380380380380700180700
+0C0E00061C0001F000121F7E9D17>I<4000007FFFC07FFF807FFF804001008002008002008004
+0000080000080000100000200000200000400000400000C00000C00001C0000180000380000380
+00038000038000078000078000078000078000078000078000078000030000121F7D9D17>I<03
+F0000C0C001006003003002001806001806001806001807001807803003E03003F06001FC8000F
+F00003F80007FC000C7E00103F00300F806003804001C0C001C0C000C0C000C0C000C0C0008060
+01802001001002000C0C0003F000121F7E9D17>I<03F0000E18001C0C00380600380700700700
+700380F00380F00380F003C0F003C0F003C0F003C0F003C07007C07007C03807C0180BC00E13C0
+03E3C0000380000380000380000700300700780600780E00700C002018001070000FC000121F7E
+9D17>I<70F8F8F8700000000000000000000070F8F8F87005147C930D>I<70F8F8F87000000000
+00000000000070F0F8F878080808101010202040051D7C930D>I<000100000003800000038000
+000380000007C0000007C0000007C0000009E0000009E0000009E0000010F0000010F0000010F0
+0000207800002078000020780000403C0000403C0000403C0000801E0000801E0000FFFE000100
+0F0001000F0001000F00020007800200078002000780040003C00E0003C01F0007E0FFC03FFE1F
+207F9F22>65 D<FFFFE0000F80380007801E0007801F0007800F0007800F8007800F8007800F80
+07800F8007800F8007800F0007801F0007801E0007803C0007FFF00007803C0007801E0007800F
+0007800F8007800780078007C0078007C0078007C0078007C0078007C00780078007800F800780
+0F0007801F000F803C00FFFFF0001A1F7E9E20>I<000FC040007030C001C009C0038005C00700
+03C00E0001C01E0000C01C0000C03C0000C07C0000407C00004078000040F8000000F8000000F8
+000000F8000000F8000000F8000000F8000000F8000000F8000000780000007C0000407C000040
+3C0000401C0000401E0000800E000080070001000380020001C0040000703800000FC0001A217D
+9F21>I<FFFFE0000F803C0007801E000780070007800380078003C0078001E0078001E0078001
+F0078000F0078000F0078000F8078000F8078000F8078000F8078000F8078000F8078000F80780
+00F8078000F8078000F0078000F0078000F0078001E0078001E0078003C0078003800780070007
+800E000F803C00FFFFE0001D1F7E9E23>I<FFFFFF000F800F0007800300078003000780010007
+800180078000800780008007800080078080800780800007808000078080000781800007FF8000
+078180000780800007808000078080000780800007800020078000200780002007800040078000
+4007800040078000C0078000C0078001800F800F80FFFFFF801B1F7E9E1F>I<FFFFFF000F800F
+000780030007800300078001000780018007800080078000800780008007800080078080000780
+800007808000078080000781800007FF8000078180000780800007808000078080000780800007
+800000078000000780000007800000078000000780000007800000078000000FC00000FFFE0000
+191F7E9E1E>I<000FE0200078186000E004E0038002E0070001E00F0000E01E0000601E000060
+3C0000603C0000207C00002078000020F8000000F8000000F8000000F8000000F8000000F80000
+00F8000000F8007FFCF80003E0780001E07C0001E03C0001E03C0001E01E0001E01E0001E00F00
+01E0070001E0038002E000E0046000781820000FE0001E217D9F24>I<FFF8FFF80F800F800780
+0F0007800F0007800F0007800F0007800F0007800F0007800F0007800F0007800F0007800F0007
+800F0007800F0007FFFF0007800F0007800F0007800F0007800F0007800F0007800F0007800F00
+07800F0007800F0007800F0007800F0007800F0007800F0007800F000F800F80FFF8FFF81D1F7E
+9E22>I<FFFC0FC007800780078007800780078007800780078007800780078007800780078007
+80078007800780078007800780078007800780078007800FC0FFFC0E1F7F9E10>I<0FFFC0007C
+00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C
+00003C00003C00003C00003C00003C00003C00003C00003C00203C00F83C00F83C00F83C00F038
+0040780040700030E0000F800012207E9E17>I<FFFE000FC00007800007800007800007800007
+800007800007800007800007800007800007800007800007800007800007800007800007800007
+800007800207800207800207800207800607800407800407800C07801C0F807CFFFFFC171F7E9E
+1C>76 D<FF80001FF80F80001F800780001F0005C0002F0005C0002F0005C0002F0004E0004F00
+04E0004F000470008F000470008F000470008F000438010F000438010F000438010F00041C020F
+00041C020F00041C020F00040E040F00040E040F00040E040F000407080F000407080F00040708
+0F000403900F000403900F000401E00F000401E00F000401E00F000E00C00F001F00C01F80FFE0
+C1FFF8251F7E9E2A>I<FF803FF807C007C007C0038005E0010005E0010004F001000478010004
+780100043C0100043C0100041E0100040F0100040F010004078100040781000403C1000401E100
+0401E1000400F1000400F1000400790004003D0004003D0004001F0004001F0004000F00040007
+00040007000E0003001F000300FFE001001D1F7E9E22>I<001F800000F0F00001C0380007801E
+000F000F000E0007001E0007803C0003C03C0003C07C0003E0780001E0780001E0F80001F0F800
+01F0F80001F0F80001F0F80001F0F80001F0F80001F0F80001F0F80001F0780001E07C0003E07C
+0003E03C0003C03C0003C01E0007800E0007000F000F0007801E0001C0380000F0F000001F8000
+1C217D9F23>I<FFFFE0000F80780007801C0007801E0007800F0007800F8007800F8007800F80
+07800F8007800F8007800F8007800F0007801E0007801C000780780007FFE00007800000078000
+000780000007800000078000000780000007800000078000000780000007800000078000000780
+0000078000000FC00000FFFC0000191F7E9E1F>I<001F800000F0F00001C0380007801E000F00
+0F000E0007001E0007803C0003C03C0003C07C0003E07C0003E0780001E0F80001F0F80001F0F8
+0001F0F80001F0F80001F0F80001F0F80001F0F80001F0F80001F0780001E0780001E07C0003E0
+3C0003C03C0F03C01E1087800E2047000F204F0007A03E0001E0380000F0F010001FB010000030
+10000038300000387000003FF000001FE000001FE000000FC0000007801C297D9F23>I<FFFF80
+000F80F0000780780007803C0007801E0007801E0007801F0007801F0007801F0007801F000780
+1E0007801E0007803C00078078000780F00007FF80000781C0000780E0000780F0000780700007
+807800078078000780780007807C0007807C0007807C0007807C0407807E0407803E040FC01E08
+FFFC0F10000003E01E207E9E21>I<07E0800C1980100780300380600180600180E00180E00080
+E00080E00080F00000F000007800007F00003FF0001FFC000FFE0003FF00001F800007800003C0
+0003C00001C08001C08001C08001C08001C0C00180C00380E00300F00600CE0C0081F80012217D
+9F19>I<7FFFFFE0780F01E0600F0060400F0020400F0020C00F0030800F0010800F0010800F00
+10800F0010000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F
+0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F000000
+0F0000001F800007FFFE001C1F7E9E21>I<FFFC3FF80FC007C007800380078001000780010007
+800100078001000780010007800100078001000780010007800100078001000780010007800100
+078001000780010007800100078001000780010007800100078001000780010007800100038002
+000380020001C0020001C0040000E008000070180000382000000FC0001D207E9E22>I<FFF003
+FE1F8000F80F0000600F800060078000400780004003C0008003C0008003C0008001E0010001E0
+010001F0010000F0020000F0020000F806000078040000780400003C0800003C0800003C080000
+1E1000001E1000001F3000000F2000000F20000007C0000007C0000007C0000003800000038000
+00038000000100001F207F9E22>I<FFF07FF81FF01F800FC007C00F00078003800F0007800100
+0F0007C00100078007C00200078007C00200078007C0020003C009E0040003C009E0040003C009
+E0040003E010F00C0001E010F0080001E010F0080001F02078080000F02078100000F020781000
+00F0403C10000078403C20000078403C20000078C03E2000003C801E4000003C801E4000003C80
+1E4000001F000F8000001F000F8000001F000F8000001E00078000000E00070000000E00070000
+000C000300000004000200002C207F9E2F>I<FEFEC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0
+C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0FEFE072D7CA10D>91
+D<080410082010201040204020804080408040B85CFC7EFC7E7C3E381C0F0E7B9F17>I<FEFE06
+060606060606060606060606060606060606060606060606060606060606060606060606060606
+06FEFE072D7FA10D>I<081020204040808080B8FCFC7C38060E7D9F0D>96
+D<1FE000303000781800781C00300E00000E00000E00000E0000FE00078E001E0E00380E00780E
+00F00E10F00E10F00E10F01E10781E103867200F83C014147E9317>I<0E0000FE00000E00000E
+00000E00000E00000E00000E00000E00000E00000E00000E00000E3E000EC3800F01C00F00E00E
+00E00E00700E00700E00780E00780E00780E00780E00780E00780E00700E00700E00E00F00E00D
+01C00CC300083E0015207F9F19>I<03F80E0C1C1E381E380C70007000F000F000F000F000F000
+F00070007000380138011C020E0C03F010147E9314>I<000380003F8000038000038000038000
+038000038000038000038000038000038000038003E380061B801C078038038038038070038070
+0380F00380F00380F00380F00380F00380F003807003807003803803803807801C07800E1B8003
+E3F815207E9F19>I<03F0000E1C001C0E00380700380700700700700380F00380F00380FFFF80
+F00000F00000F000007000007000003800801800800C010007060001F80011147F9314>I<007C
+00C6018F038F07060700070007000700070007000700FFF0070007000700070007000700070007
+0007000700070007000700070007000700070007007FF01020809F0E>I<0000E003E3300E3C30
+1C1C30380E00780F00780F00780F00780F00780F00380E001C1C001E380033E000200000200000
+3000003000003FFE001FFF800FFFC03001E0600070C00030C00030C00030C000306000603000C0
+1C038003FC00141F7F9417>I<0E0000FE00000E00000E00000E00000E00000E00000E00000E00
+000E00000E00000E00000E3E000E43000E81800F01C00F01C00E01C00E01C00E01C00E01C00E01
+C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C0FFE7FC16207F9F19>I<1C
+003E003E003E001C000000000000000000000000000E007E000E000E000E000E000E000E000E00
+0E000E000E000E000E000E000E000E000E000E00FFC00A1F809E0C>I<00E001F001F001F000E0
+000000000000000000000000007007F000F0007000700070007000700070007000700070007000
+7000700070007000700070007000700070007000706070F060F0C061803F000C28829E0E>I<0E
+0000FE00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E0FF00E
+03C00E03000E02000E04000E08000E10000E30000E70000EF8000F38000E1C000E1E000E0E000E
+07000E07800E03800E03C00E03E0FFCFF815207F9F18>I<0E00FE000E000E000E000E000E000E
+000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E00
+0E000E000E000E00FFE00B20809F0C>I<0E1F01F000FE618618000E81C81C000F00F00E000F00
+F00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E
+00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E00FFE7FE7FE0
+23147F9326>I<0E3E00FE43000E81800F01C00F01C00E01C00E01C00E01C00E01C00E01C00E01
+C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C0FFE7FC16147F9319>I<01F80007
+0E001C03803801C03801C07000E07000E0F000F0F000F0F000F0F000F0F000F0F000F07000E070
+00E03801C03801C01C0380070E0001F80014147F9317>I<0E3E00FEC3800F01C00F00E00E00E0
+0E00F00E00700E00780E00780E00780E00780E00780E00780E00700E00F00E00E00F01E00F01C0
+0EC3000E3E000E00000E00000E00000E00000E00000E00000E00000E0000FFE000151D7F9319>
+I<03E0800619801C05803C0780380380780380700380F00380F00380F00380F00380F00380F003
+807003807803803803803807801C0B800E138003E3800003800003800003800003800003800003
+80000380000380003FF8151D7E9318>I<0E78FE8C0F1E0F1E0F0C0E000E000E000E000E000E00
+0E000E000E000E000E000E000E000E00FFE00F147F9312>I<1F9030704030C010C010C010E000
+78007F803FE00FF00070803880188018C018C018E030D0608F800D147E9312>I<020002000200
+060006000E000E003E00FFF80E000E000E000E000E000E000E000E000E000E000E000E080E080E
+080E080E080610031001E00D1C7F9B12>I<0E01C0FE1FC00E01C00E01C00E01C00E01C00E01C0
+0E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E03C00603C0030DC001F1FC
+16147F9319>I<FF83F81E01E01C00C00E00800E00800E00800701000701000382000382000382
+0001C40001C40001EC0000E80000E80000700000700000700000200015147F9318>I<FF9FE1FC
+3C0780701C0300601C0380200E0380400E0380400E03C0400707C0800704C0800704E080038861
+000388710003C8730001D0320001D03A0000F03C0000E01C0000E01C0000601800004008001E14
+7F9321>I<7FC3FC0F01E00701C007018003810001C20000E40000EC00007800003800003C0000
+7C00004E000087000107000303800201C00601E01E01E0FF07FE1714809318>I<FF83F81E01E0
+1C00C00E00800E00800E008007010007010003820003820003820001C40001C40001EC0000E800
+00E800007000007000007000002000002000004000004000004000F08000F08000F10000620000
+3C0000151D7F9318>I<3FFF380E200E201C40384078407000E001E001C00380078007010E011E
+011C0338027006700EFFFE10147F9314>I E /Fp 13 122 df<0000001FFC0000C000000003FF
+FFC001C00000001FFFFFF003C00000007FFFFFFC07C0000001FFFC00FE0FC0000007FFC0001F9F
+C000000FFE000007FFC000003FF8000003FFC000007FF0000000FFC00000FFE00000007FC00001
+FFC00000007FC00001FF800000003FC00003FF000000001FC00007FE000000001FC0000FFE0000
+00000FC0000FFC000000000FC0001FFC0000000007C0001FFC0000000007C0003FF80000000007
+C0003FF80000000003C0003FF80000000003C0007FF80000000003C0007FF80000000003C0007F
+F0000000000000007FF000000000000000FFF000000000000000FFF000000000000000FFF00000
+0000000000FFF000000000000000FFF000000000000000FFF000000000000000FFF00000000000
+0000FFF000000000000000FFF000000000000000FFF000000000000000FFF000001FFFFFFF807F
+F000001FFFFFFF807FF000001FFFFFFF807FF800001FFFFFFF807FF800000001FFC0003FF80000
+0001FFC0003FF800000001FFC0003FF800000001FFC0001FFC00000001FFC0001FFC00000001FF
+C0000FFE00000001FFC0000FFE00000001FFC00007FF00000001FFC00003FF00000001FFC00001
+FF80000001FFC00001FFC0000001FFC00000FFE0000001FFC000007FF0000003FFC000003FFC00
+0003FFC000000FFF000007FFC0000007FFC0001FBFC0000001FFFC00FF1FC00000007FFFFFFE0F
+C00000001FFFFFF803C000000003FFFFE000C0000000001FFE00000000413D7BBB4C>71
+D<FFFFFFF803FFFFFFE0FFFFFFF803FFFFFFE0FFFFFFF803FFFFFFE0FFFFFFF803FFFFFFE0007F
+F0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF00000
+01FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC0
+00007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007F
+F0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF00000
+01FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC0
+00007FFFFFFFFFFFC000007FFFFFFFFFFFC000007FFFFFFFFFFFC000007FFFFFFFFFFFC000007F
+F0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF00000
+01FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC0
+00007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007F
+F0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF00000
+01FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000007FF0000001FFC0
+00007FF0000001FFC000007FF0000001FFC000007FF0000001FFC000FFFFFFF803FFFFFFE0FFFF
+FFF803FFFFFFE0FFFFFFF803FFFFFFE0FFFFFFF803FFFFFFE0433B7CBA4C>I<FFFFFFFE000000
+FFFFFFFE000000FFFFFFFE000000FFFFFFFE000000007FF000000000007FF000000000007FF000
+000000007FF000000000007FF000000000007FF000000000007FF000000000007FF00000000000
+7FF000000000007FF000000000007FF000000000007FF000000000007FF000000000007FF00000
+0000007FF000000000007FF000000000007FF000000000007FF000000000007FF000000000007F
+F000000000007FF000000000007FF000000000007FF000000000007FF000000000007FF0000000
+00007FF000000000007FF000000000007FF000000000007FF000000000007FF000000000007FF0
+00000000007FF000000780007FF000000780007FF000000780007FF000000780007FF000000780
+007FF000000F80007FF000000F00007FF000000F00007FF000000F00007FF000001F00007FF000
+001F00007FF000001F00007FF000003F00007FF000003F00007FF000007F00007FF00000FF0000
+7FF00001FF00007FF00003FF00007FF0000FFE00007FF0007FFE00FFFFFFFFFFFE00FFFFFFFFFF
+FE00FFFFFFFFFFFE00FFFFFFFFFFFE00313B7CBA3A>76 D<FFFFF0000007FFFFE0FFFFF8000007
+FFFFE0FFFFFC000007FFFFE0FFFFFE000007FFFFE0007FFE00000007E000007FFF00000003C000
+007FFF80000003C000007BFFC0000003C000007BFFE0000003C0000079FFE0000003C0000078FF
+F0000003C00000787FF8000003C00000783FFC000003C00000783FFE000003C00000781FFE0000
+03C00000780FFF000003C000007807FF800003C000007803FFC00003C000007803FFE00003C000
+007801FFE00003C000007800FFF00003C0000078007FF80003C0000078003FFC0003C000007800
+3FFE0003C0000078001FFF0003C0000078000FFF0003C00000780007FF8003C00000780003FFC0
+03C00000780003FFE003C00000780001FFF003C00000780000FFF003C000007800007FF803C000
+007800003FFC03C000007800003FFE03C000007800001FFF03C000007800000FFF03C000007800
+0007FF83C0000078000003FFC3C0000078000003FFE3C0000078000001FFF3C0000078000000FF
+F3C00000780000007FFBC00000780000003FFFC00000780000003FFFC00000780000001FFFC000
+00780000000FFFC000007800000007FFC000007800000003FFC000007800000003FFC000007800
+000001FFC000007800000000FFC0000078000000007FC0000078000000003FC000007800000000
+3FC00000FC000000001FC000FFFFFC0000000FC000FFFFFC00000007C000FFFFFC00000003C000
+FFFFFC00000003C000433B7CBA4C>78 D<FFFFFFF8001FFFFF80FFFFFFF8001FFFFF80FFFFFFF8
+001FFFFF80FFFFFFF8001FFFFF80007FF00000001F8000007FF00000000F0000007FF00000000F
+0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F000000
+7FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF000
+00000F0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F
+0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F000000
+7FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF000
+00000F0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F
+0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F000000
+7FF00000000F0000007FF00000000F0000007FF00000000F0000007FF00000000F0000007FF000
+00000F0000007FF00000000F0000007FF00000000F0000003FF00000001E0000003FF00000001E
+0000003FF80000001E0000001FF80000003C0000001FF80000003C0000000FFC00000078000000
+07FC000000F800000007FE000001F000000003FF000003F000000001FF800007E000000000FFE0
+001FC0000000003FFC01FF80000000001FFFFFFE000000000007FFFFF8000000000000FFFFE000
+00000000000FFE00000000413C7CBA4A>85 D<003FFE00000001FFFFE0000007FFFFF800000FE0
+07FC00000FF001FE00001FF800FF00001FF8007F80001FF8007FC0001FF8003FC0000FF0003FE0
+0007E0003FE00003C0003FE0000000003FE0000000003FE0000000003FE0000000003FE0000000
+FFFFE000001FFFFFE000007FF83FE00003FF803FE00007FC003FE0000FF0003FE0001FE0003FE0
+003FE0003FE0007FC0003FE0007FC0003FE000FF80003FE000FF80003FE000FF80003FE000FF80
+003FE000FF80007FE0007FC0007FE0007FC000DFE0003FE0039FF0001FF80F0FFFE007FFFE0FFF
+E001FFF807FFE0003FE000FFE02B267DA52F>97 D<00FE00000000FFFE00000000FFFE00000000
+FFFE00000000FFFE0000000007FE0000000003FE0000000003FE0000000003FE0000000003FE00
+00000003FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE00000000
+03FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE01
+FF000003FE1FFFF00003FE7FFFFC0003FEFC03FE0003FFF000FF0003FFC0003F8003FF00001FC0
+03FE00001FE003FE00000FF003FE00000FF803FE00000FF803FE000007FC03FE000007FC03FE00
+0007FC03FE000007FE03FE000007FE03FE000007FE03FE000007FE03FE000007FE03FE000007FE
+03FE000007FE03FE000007FE03FE000007FE03FE000007FC03FE000007FC03FE000007FC03FE00
+000FFC03FE00000FF803FE00000FF003FE00001FF003FF00001FE003FF80003FC003FFC0007F80
+03F9E000FF0003F0FC07FE0003F07FFFF80003E01FFFE00003C003FE00002F3C7DBB36>I<01E0
+0007F8000FFC000FFC001FFE001FFE001FFE001FFE000FFC000FFC0007F80001E0000000000000
+0000000000000000000000000000000000000000000000000000000000FE00FFFE00FFFE00FFFE
+00FFFE0007FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE
+0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE
+0003FE0003FE0003FE0003FE00FFFFF0FFFFF0FFFFF0FFFFF0143D7DBC1A>105
+D<0001FFC00000000FFFF80000007FFFFF000000FF80FF800003FE003FE00007F8000FF0000FF0
+0007F8000FF00007F8001FE00003FC003FE00003FE003FE00003FE007FC00001FF007FC00001FF
+007FC00001FF007FC00001FF00FFC00001FF80FFC00001FF80FFC00001FF80FFC00001FF80FFC0
+0001FF80FFC00001FF80FFC00001FF80FFC00001FF80FFC00001FF807FC00001FF007FC00001FF
+007FC00001FF003FE00003FE003FE00003FE001FE00003FC001FF00007FC000FF00007F80007F8
+000FF00003FE003FE00000FF80FF8000007FFFFF0000000FFFF800000001FFC0000029267DA530
+>111 D<01FC03F000FFFC0FFC00FFFC1FFF00FFFC3C3F80FFFC707F8007FCE0FFC003FCC0FFC0
+03FD80FFC003FD80FFC003FF807F8003FF003F0003FF001E0003FF00000003FE00000003FE0000
+0003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00
+000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE
+00000003FE00000003FE00000003FE000000FFFFFC0000FFFFFC0000FFFFFC0000FFFFFC000022
+267DA528>114 D<003FF07003FFFEF007FFFFF01FC01FF03F0003F03E0001F07C0001F07C0000
+F0FC0000F0FC0000F0FE0000F0FF000000FFC00000FFFC00007FFFF0003FFFFE003FFFFF801FFF
+FFC00FFFFFE003FFFFF000FFFFF8001FFFFC00007FFC000007FE700001FEF00000FEF000007EF8
+00007EF800007EFC00007EFC00007CFE0000FCFF0000F8FF8001F0FFF00FE0F9FFFFC0F07FFF00
+C01FF8001F267DA526>I<000F0000000F0000000F0000000F0000000F0000001F0000001F0000
+001F0000001F0000003F0000003F0000007F0000007F000000FF000001FF000003FF000007FF00
+001FFFFFF0FFFFFFF0FFFFFFF0FFFFFFF001FF000001FF000001FF000001FF000001FF000001FF
+000001FF000001FF000001FF000001FF000001FF000001FF000001FF000001FF000001FF000001
+FF000001FF000001FF000001FF000001FF003C01FF003C01FF003C01FF003C01FF003C01FF003C
+01FF003C01FF003C00FF007800FF8078007F80F0003FC1E0001FFFC0000FFF800001FE001E377E
+B626>I<FFFFF001FFFCFFFFF001FFFCFFFFF001FFFCFFFFF001FFFC03FE00001F8003FF00001F
+0001FF00001E0001FF80003E0000FF80003C0000FF80003C00007FC0007800007FC0007800007F
+E000F800003FE000F000003FF001F000001FF001E000001FF803E000000FF803C000000FFC03C0
+000007FC0780000007FC0780000007FE0F80000003FE0F00000003FF1F00000001FF1E00000001
+FFBE00000000FFBC00000000FFFC000000007FF8000000007FF8000000007FF8000000003FF000
+0000003FF0000000001FE0000000001FE0000000000FC0000000000FC000000000078000000000
+0780000000000F80000000000F00000000001F00000000001E00000008003E0000007F003C0000
+007F007C000000FF8078000000FF80F8000000FF80F0000000FF81E00000007F07C00000007C1F
+800000003FFF000000001FFE0000000007F0000000002E377EA533>121
+D E end
+%%EndProlog
+%%BeginSetup
+%%Feature: *Resolution 300dpi
+TeXDict begin
+
+%%EndSetup
+%%Page: 1 1
+0 bop 0 1152 a Fp(GNU)33 b(History)f(Library)p 0 1201 1950
+17 v 1035 1250 a Fo(Edition)16 b(2.0,)e(for)h Fn(History)f(Library)g
+Fo(V)l(ersion)i(2.0.)1759 1304 y(July)g(1994)0 2443 y Fm(Brian)23
+b(F)-6 b(o)n(x,)23 b(F)-6 b(ree)23 b(Soft)n(w)n(are)f(F)-6
+b(oundation)0 2509 y(Chet)22 b(Ramey)-6 b(,)23 b(Case)e(W)-6
+b(estern)23 b(Reserv)n(e)f(Univ)n(ersit)n(y)p 0 2545 1950 9
+v eop
+%%Page: 2 2
+1 bop 0 295 a Fo(This)16 b(do)q(cumen)o(t)g(describ)q(es)h(the)f(GNU)f
+(History)g(library)l(,)h(a)g(programming)e(to)q(ol)i(that)f(pro)o(vides)h(a)f
+(consisten)o(t)0 358 y(user)g(in)o(terface)h(for)e(recalling)j(lines)g(of)e
+(previously)h(t)o(yp)q(ed)g(input.)0 495 y(Published)h(b)o(y)f(the)f(F)l(ree)
+g(Soft)o(w)o(are)f(F)l(oundation)0 557 y(675)g(Massac)o(h)o(usetts)g(Av)o(en)
+o(ue,)0 619 y(Cam)o(bridge,)h(MA)g(02139)f(USA)0 756 y(P)o(ermission)f(is)g
+(gran)o(ted)f(to)f(mak)o(e)h(and)h(distribute)h(v)o(erbatim)e(copies)h(of)f
+(this)h(man)o(ual)g(pro)o(vided)g(the)f(cop)o(yrigh)o(t)0 818
+y(notice)k(and)f(this)h(p)q(ermission)h(notice)e(are)g(preserv)o(ed)h(on)f
+(all)h(copies.)0 955 y(P)o(ermission)f(is)f(gran)o(ted)f(to)h(cop)o(y)g(and)g
+(distribute)h(mo)q(di\014ed)h(v)o(ersions)e(of)f(this)i(man)o(ual)f(under)h
+(the)f(conditions)0 1018 y(for)e(v)o(erbatim)g(cop)o(ying,)h(pro)o(vided)h
+(that)d(the)i(en)o(tire)g(resulting)h(deriv)o(ed)f(w)o(ork)f(is)h
+(distributed)h(under)f(the)g(terms)0 1080 y(of)i(a)g(p)q(ermission)h(notice)g
+(iden)o(tical)h(to)e(this)g(one.)0 1217 y(P)o(ermission)20
+b(is)g(gran)o(ted)f(to)g(cop)o(y)h(and)f(distribute)i(translations)f(of)f
+(this)h(man)o(ual)f(in)o(to)h(another)f(language,)0 1279 y(under)c(the)f(ab)q
+(o)o(v)o(e)g(conditions)h(for)e(mo)q(di\014ed)j(v)o(ersions,)e(except)g(that)
+g(this)g(p)q(ermission)i(notice)e(ma)o(y)g(b)q(e)h(stated)0
+1341 y(in)h(a)f(translation)g(appro)o(v)o(ed)g(b)o(y)g(the)g(F)l(oundation.)0
+2636 y(Cop)o(yrigh)o(t)226 2635 y(c)214 2636 y Fl(\015)g Fo(1989,)f(1991)g(F)
+l(ree)h(Soft)o(w)o(are)f(F)l(oundation,)h(Inc.)p eop
+%%Page: 1 3
+2 bop 0 -83 a Fo(Chapter)15 b(1:)k(Using)d(History)f(In)o(teractiv)o(ely)1157
+b(1)0 158 y Fk(1)41 b(Using)14 b(History)h(In)n(teractiv)n(ely)62
+330 y Fo(This)i(c)o(hapter)e(describ)q(es)j(ho)o(w)d(to)h(use)g(the)g(GNU)g
+(History)f(Library)i(in)o(teractiv)o(ely)l(,)g(from)e(a)g(user's)h(stand-)0
+392 y(p)q(oin)o(t.)23 b(It)16 b(should)h(b)q(e)f(considered)i(a)d(user's)h
+(guide.)23 b(F)l(or)15 b(information)h(on)g(using)h(the)f(GNU)g(History)f
+(Library)0 454 y(in)h(y)o(our)f(o)o(wn)f(programs,)g(see)i(Chapter)e(2)h
+([Programming)f(with)i(GNU)f(History],)f(page)h(5.)0 663 y
+Fm(1.1)33 b(History)15 b(In)n(teraction)62 800 y Fo(The)j(History)g(library)g
+(pro)o(vides)h(a)e(history)h(expansion)h(feature)e(that)g(is)i(similar)g(to)e
+(the)h(history)f(expan-)0 862 y(sion)k(pro)o(vided)h(b)o(y)f
+Fn(csh)p Fo(.)36 b(The)22 b(follo)o(wing)f(text)g(describ)q(es)h(the)f(syn)o
+(tax)f(used)i(to)e(manipulate)i(the)f(history)0 924 y(information.)62
+1061 y(History)11 b(expansion)i(tak)o(es)d(place)i(in)h(t)o(w)o(o)d(parts.)18
+b(The)11 b(\014rst)g(is)h(to)f(determine)h(whic)o(h)g(line)h(from)e(the)g
+(previous)0 1124 y(history)h(should)h(b)q(e)f(used)h(during)f(substitution.)
+20 b(The)12 b(second)g(is)h(to)e(select)h(p)q(ortions)g(of)g(that)f(line)i
+(for)f(inclusion)0 1186 y(in)o(to)f(the)h(curren)o(t)f(one.)18
+b(The)12 b(line)h(selected)f(from)f(the)g(previous)h(history)g(is)f(called)i
+(the)e Fj(ev)o(en)o(t)p Fo(,)h(and)f(the)h(p)q(ortions)0 1248
+y(of)h(that)g(line)i(that)e(are)g(acted)g(up)q(on)h(are)g(called)h
+Fj(w)o(ords)p Fo(.)j(The)c(line)h(is)f(brok)o(en)f(in)o(to)h(w)o(ords)f(in)h
+(the)f(same)h(fashion)0 1310 y(that)j(Bash)h(do)q(es,)h(so)e(that)g(sev)o
+(eral)h(English)i(\(or)d(Unix\))h(w)o(ords)f(surrounded)i(b)o(y)f(quotes)f
+(are)h(considered)h(as)0 1373 y(one)c(w)o(ord.)0 1565 y Fi(1.1.1)30
+b(Ev)n(en)n(t)16 b(Designators)62 1702 y Fo(An)g(ev)o(en)o(t)f(designator)g
+(is)g(a)g(reference)h(to)f(a)g(command)g(line)i(en)o(try)d(in)i(the)g
+(history)f(list.)0 1847 y Fn(!)216 b Fo(Start)14 b(a)g(history)h
+(substitution,)g(except)h(when)f(follo)o(w)o(ed)g(b)o(y)g(a)f(space,)h(tab,)f
+(the)h(end)g(of)g(the)g(line,)240 1909 y Fn(=)g Fo(or)g Fn(\()p
+Fo(.)0 1989 y Fn(!!)192 b Fo(Refer)16 b(to)e(the)i(previous)f(command.)20
+b(This)c(is)g(a)f(synon)o(ym)g(for)f Fn(!-1)p Fo(.)0 2068 y
+Fn(!n)192 b Fo(Refer)16 b(to)e(command)h(line)i Fj(n)p Fo(.)0
+2148 y Fn(!-n)168 b Fo(Refer)16 b(to)e(the)i(command)f Fj(n)g
+Fo(lines)i(bac)o(k.)0 2227 y Fn(!string)72 b Fo(Refer)16 b(to)e(the)i(most)e
+(recen)o(t)h(command)g(starting)g(with)g Fj(string)p Fo(.)0
+2298 y Fn(!?string)p Fo([)p Fn(?)p Fo(])240 2360 y(Refer)h(to)e(the)i(most)e
+(recen)o(t)h(command)g(con)o(taining)h Fj(string)p Fo(.)0 2440
+y Fn(!#)192 b Fo(The)15 b(en)o(tire)h(command)f(line)i(t)o(yp)q(ed)f(so)e
+(far.)0 2510 y Fn(^string1^string2^)240 2573 y Fo(Quic)o(k)j(Substitution.)22
+b(Rep)q(eat)16 b(the)g(last)f(command,)h(replacing)h Fj(string1)h
+Fo(with)e Fj(string2)p Fo(.)21 b(Equiv-)240 2635 y(alen)o(t)15
+b(to)g Fn(!!:s/string1/string2/)p Fo(.)p eop
+%%Page: 2 4
+3 bop 0 -83 a Fo(2)1497 b(GNU)15 b(History)g(Library)0 158
+y Fi(1.1.2)30 b(W)-5 b(ord)15 b(Designators)62 295 y Fo(A)i
+Fn(:)g Fo(separates)f(the)h(ev)o(en)o(t)f(sp)q(eci\014cation)j(from)d(the)g
+(w)o(ord)g(designator.)25 b(It)17 b(can)g(b)q(e)g(omitted)g(if)g(the)g(w)o
+(ord)0 358 y(designator)d(b)q(egins)h(with)f(a)f Fn(^)p Fo(,)h
+Fn($)p Fo(,)f Fn(*)h Fo(or)f Fn(\045)p Fo(.)20 b(W)l(ords)13
+b(are)h(n)o(um)o(b)q(ered)g(from)f(the)h(b)q(eginning)i(of)d(the)h(line,)i
+(with)e(the)0 420 y(\014rst)h(w)o(ord)f(b)q(eing)j(denoted)f(b)o(y)f(a)g(0)f
+(\(zero\).)0 569 y Fn(0)h(\(zero\))57 b Fo(The)15 b Fn(0)p
+Fo(th)g(w)o(ord.)20 b(F)l(or)14 b(man)o(y)h(applications,)h(this)g(is)g(the)f
+(command)g(w)o(ord.)0 656 y Fn(n)216 b Fo(The)15 b Fj(n)p Fo(th)h(w)o(ord.)0
+744 y Fn(^)216 b Fo(The)15 b(\014rst)g(argumen)o(t;)f(that)h(is,)g(w)o(ord)g
+(1.)0 831 y Fn($)216 b Fo(The)15 b(last)h(argumen)o(t.)0 918
+y Fn(\045)216 b Fo(The)15 b(w)o(ord)g(matc)o(hed)g(b)o(y)g(the)g(most)g
+(recen)o(t)g Fn(?string?)f Fo(searc)o(h.)0 1005 y Fn(x-y)168
+b Fo(A)15 b(range)g(of)g(w)o(ords;)f Fn(-)p Fj(y)19 b Fo(abbreviates)c
+Fn(0-)p Fj(y)t Fo(.)0 1092 y Fn(*)216 b Fo(All)17 b(of)f(the)g(w)o(ords,)f
+(except)i(the)f Fn(0)p Fo(th.)22 b(This)17 b(is)f(a)g(synon)o(ym)g(for)f
+Fn(1-$)p Fo(.)22 b(It)17 b(is)f(not)g(an)g(error)f(to)h(use)240
+1155 y Fn(*)f Fo(if)h(there)f(is)h(just)f(one)g(w)o(ord)f(in)i(the)g(ev)o(en)
+o(t;)e(the)i(empt)o(y)e(string)i(is)f(returned)h(in)g(that)e(case.)0
+1242 y Fn(x*)192 b Fo(Abbreviates)16 b Fn(x-$)0 1329 y(x-)192
+b Fo(Abbreviates)16 b Fn(x-$)f Fo(lik)o(e)h Fn(x*)p Fo(,)e(but)i(omits)f(the)
+g(last)g(w)o(ord.)0 1537 y Fi(1.1.3)30 b(Mo)r(di\014ers)62
+1674 y Fo(After)20 b(the)f(optional)i(w)o(ord)e(designator,)h(y)o(ou)f(can)h
+(add)g(a)g(sequence)h(of)e(one)h(or)f(more)g(of)g(the)h(follo)o(wing)0
+1736 y(mo)q(di\014ers,)c(eac)o(h)f(preceded)i(b)o(y)e(a)g Fn(:)p
+Fo(.)0 1885 y Fn(h)216 b Fo(Remo)o(v)o(e)15 b(a)g(trailing)h(pathname)f(comp)
+q(onen)o(t,)g(lea)o(ving)h(only)g(the)f(head.)0 1973 y Fn(r)216
+b Fo(Remo)o(v)o(e)15 b(a)g(trailing)h(su\016x)f(of)g(the)g(form)g(`)p
+Fn(.)p Fo(')p Fj(su\016x)p Fo(,)f(lea)o(ving)i(the)f(basename.)0
+2060 y Fn(e)216 b Fo(Remo)o(v)o(e)15 b(all)h(but)g(the)f(trailing)h(su\016x.)
+0 2147 y Fn(t)216 b Fo(Remo)o(v)o(e)15 b(all)h(leading)h(pathname)e(comp)q
+(onen)o(ts,)g(lea)o(ving)h(the)f(tail.)0 2234 y Fn(p)216 b
+Fo(Prin)o(t)15 b(the)g(new)h(command)f(but)g(do)g(not)g(execute)h(it.)0
+2309 y Fn(s/old/new/)240 2371 y Fo(Substitute)g Fj(new)k Fo(for)15
+b(the)h(\014rst)f(o)q(ccurrence)h(of)g Fj(old)h Fo(in)g(the)e(ev)o(en)o(t)h
+(line.)22 b(An)o(y)16 b(delimiter)h(ma)o(y)e(b)q(e)240 2433
+y(used)e(in)f(place)h(of)f Fn(/)p Fo(.)19 b(The)12 b(delimiter)i(ma)o(y)d(b)q
+(e)i(quoted)f(in)h Fj(old)h Fo(and)e Fj(new)17 b Fo(with)12
+b(a)g(single)h(bac)o(kslash.)240 2496 y(If)g Fn(&)h Fo(app)q(ears)f(in)h
+Fj(new)p Fo(,)f(it)h(is)g(replaced)g(b)o(y)f Fj(old)p Fo(.)20
+b(A)13 b(single)i(bac)o(kslash)e(will)i(quote)e(the)h Fn(&)p
+Fo(.)19 b(The)13 b(\014nal)240 2558 y(delimiter)k(is)f(optional)g(if)f(it)h
+(is)f(the)h(last)f(c)o(haracter)f(on)h(the)h(input)g(line.)0
+2645 y Fn(&)216 b Fo(Rep)q(eat)16 b(the)f(previous)h(substitution.)p
+eop
+%%Page: 3 5
+4 bop 0 -83 a Fo(Chapter)15 b(1:)k(Using)d(History)f(In)o(teractiv)o(ely)1157
+b(3)0 158 y Fn(g)216 b Fo(Cause)15 b(c)o(hanges)g(to)f(b)q(e)i(applied)h(o)o
+(v)o(er)d(the)h(en)o(tire)g(ev)o(en)o(t)g(line.)21 b(Used)16
+b(in)g(conjunction)g(with)f Fn(s)p Fo(,)f(as)240 221 y(in)i
+Fn(gs/old/new/)p Fo(,)d(or)i(with)h Fn(&)p Fo(.)p eop
+%%Page: 4 6
+5 bop 0 -83 a Fo(4)1497 b(GNU)15 b(History)g(Library)p eop
+%%Page: 5 7
+6 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1039
+b(5)0 158 y Fk(2)41 b(Programming)16 b(with)f(GNU)h(History)62
+347 y Fo(This)e(c)o(hapter)f(describ)q(es)i(ho)o(w)d(to)h(in)o(terface)g
+(programs)f(that)h(y)o(ou)g(write)g(with)g(the)h(GNU)f(History)g(Library)l(.)
+0 409 y(It)j(should)g(b)q(e)g(considered)h(a)f(tec)o(hnical)h(guide.)22
+b(F)l(or)15 b(information)h(on)f(the)h(in)o(teractiv)o(e)g(use)g(of)f(GNU)g
+(History)l(,)0 471 y(see)g(Chapter)g(1)g([Using)h(History)f(In)o(teractiv)o
+(ely],)g(page)g(1.)0 698 y Fm(2.1)33 b(In)n(tro)r(duction)17
+b(to)e(History)62 835 y Fo(Man)o(y)j(programs)g(read)h(input)h(from)e(the)g
+(user)h(a)g(line)h(at)f(a)f(time.)31 b(The)19 b(GNU)g(History)f(library)i(is)
+f(able)0 897 y(to)e(k)o(eep)g(trac)o(k)f(of)h(those)g(lines,)i(asso)q(ciate)e
+(arbitrary)g(data)g(with)g(eac)o(h)g(line,)j(and)d(utilize)i(information)f
+(from)0 960 y(previous)e(lines)h(in)f(comp)q(osing)f(new)h(ones.)62
+1097 y(The)i(programmer)f(using)h(the)g(History)g(library)g(has)g(a)o(v)m
+(ailable)h(functions)g(for)e(remem)o(b)q(ering)h(lines)i(on)d(a)0
+1159 y(history)f(list,)g(asso)q(ciating)g(arbitrary)g(data)f(with)h(a)f
+(line,)j(remo)o(ving)d(lines)j(from)d(the)h(list,)g(searc)o(hing)g(through)0
+1221 y(the)h(list)h(for)e(a)h(line)h(con)o(taining)g(an)f(arbitrary)f(text)h
+(string,)g(and)g(referencing)h(an)o(y)f(line)h(in)g(the)f(list)h(directly)l
+(.)0 1284 y(In)d(addition,)h(a)e(history)h Fj(expansion)h Fo(function)g(is)f
+(a)o(v)m(ailable)h(whic)o(h)g(pro)o(vides)f(for)f(a)h(consisten)o(t)g(user)g
+(in)o(terface)0 1346 y(across)f(di\013eren)o(t)i(programs.)62
+1483 y(The)i(user)g(using)g(programs)f(written)g(with)h(the)g(History)f
+(library)i(has)e(the)h(b)q(ene\014t)h(of)e(a)g(consisten)o(t)h(user)0
+1545 y(in)o(terface)d(with)g(a)f(set)h(of)f(w)o(ell-kno)o(wn)h(commands)g
+(for)f(manipulating)i(the)f(text)f(of)g(previous)h(lines)h(and)f(using)0
+1608 y(that)g(text)g(in)i(new)e(commands.)22 b(The)15 b(basic)i(history)e
+(manipulation)j(commands)d(are)g(similar)i(to)e(the)h(history)0
+1670 y(substitution)g(pro)o(vided)g(b)o(y)f Fn(csh)p Fo(.)62
+1807 y(If)g(the)g(programmer)e(desires,)i(he)g(can)g(use)g(the)f(Readline)j
+(library)l(,)e(whic)o(h)h(includes)g(some)f(history)f(manip-)0
+1870 y(ulation)i(b)o(y)f(default,)h(and)f(has)g(the)g(added)h(adv)m(an)o
+(tage)f(of)g(command)g(line)h(editing.)0 2096 y Fm(2.2)33 b(History)15
+b(Storage)62 2234 y Fo(The)h(history)f(list)h(is)g(an)f(arra)o(y)f(of)g
+(history)i(en)o(tries.)k(A)15 b(history)g(en)o(try)g(is)h(declared)g(as)f
+(follo)o(ws:)120 2358 y Fn(typedef)23 b(struct)g(_hist_entry)f({)168
+2408 y(char)h(*line;)168 2458 y(char)g(*data;)120 2508 y(})h(HIST_ENTRY;)62
+2645 y Fo(The)16 b(history)f(list)h(itself)g(migh)o(t)f(therefore)g(b)q(e)h
+(declared)g(as)p eop
+%%Page: 6 8
+7 bop 0 -83 a Fo(6)1497 b(GNU)15 b(History)g(Library)120 158
+y Fn(HIST_ENTRY)22 b(**the_history_list;)62 302 y Fo(The)16
+b(state)e(of)h(the)g(History)g(library)h(is)g(encapsulated)g(in)o(to)f(a)g
+(single)i(structure:)120 434 y Fn(/*)24 b(A)f(structure)g(used)g(to)h(pass)f
+(the)h(current)f(state)g(of)g(the)h(history)f(stuff)g(around.)g(*/)120
+484 y(typedef)g(struct)g(_hist_state)f({)168 534 y(HIST_ENTRY)g(**entries;)
+214 b(/*)23 b(Pointer)g(to)h(the)f(entries)g(themselves.)f(*/)168
+584 y(int)h(offset;)453 b(/*)23 b(The)h(location)e(pointer)h(within)g(this)h
+(array.)f(*/)168 633 y(int)g(length;)453 b(/*)23 b(Number)g(of)h(elements)f
+(within)g(this)g(array.)g(*/)168 683 y(int)g(size;)501 b(/*)23
+b(Number)g(of)h(slots)f(allocated)g(to)g(this)h(array.)f(*/)168
+733 y(int)g(flags;)120 783 y(})h(HISTORY_STATE;)62 927 y Fo(If)16
+b(the)f(\015ags)g(mem)o(b)q(er)g(includes)j Fn(HS_STIFLED)p
+Fo(,)13 b(the)i(history)h(has)f(b)q(een)h(sti\015ed.)0 1215
+y Fm(2.3)33 b(History)15 b(F)-6 b(unctions)62 1359 y Fo(This)16
+b(section)g(describ)q(es)h(the)e(calling)i(sequence)f(for)f(the)g(v)m(arious)
+h(functions)g(presen)o(t)f(in)h(GNU)f(History)l(.)0 1631 y
+Fi(2.3.1)30 b(Initializing)15 b(History)g(and)g(State)g(Managemen)n(t)62
+1775 y Fo(This)j(section)g(describ)q(es)h(functions)f(used)g(to)e(initialize)
+21 b(and)c(manage)g(the)g(state)g(of)g(the)g(History)g(library)0
+1837 y(when)f(y)o(ou)f(w)o(an)o(t)f(to)g(use)i(the)f(history)g(functions)h
+(in)g(y)o(our)f(program.)1725 2021 y(F)l(unction)-1899 b Fh(void)20
+b Fg(using)p 258 2021 18 3 v 20 w(history)j Ff(\(\))120 2083
+y Fo(Begin)g(a)f(session)g(in)h(whic)o(h)g(the)f(history)g(functions)g(migh)o
+(t)g(b)q(e)h(used.)40 b(This)23 b(initializes)i(the)120 2145
+y(in)o(teractiv)o(e)16 b(v)m(ariables.)1725 2328 y(F)l(unction)-1899
+b Fh(HISTORY_STATE)21 b(*)e Fg(history)p 582 2328 V 21 w(get)p
+680 2328 V 21 w(history)p 876 2328 V 21 w(state)j Ff(\(\))120
+2391 y Fo(Return)16 b(a)f(structure)g(describing)i(the)e(curren)o(t)g(state)f
+(of)h(the)g(input)i(history)l(.)1725 2574 y(F)l(unction)-1899
+b Fh(void)20 b Fg(history)p 302 2574 V 20 w(set)p 393 2574
+V 21 w(history)p 589 2574 V 21 w(state)j Ff(\()p Fn(HISTORY_STATE)13
+b(*state)p Ff(\))120 2636 y Fo(Set)i(the)h(state)e(of)h(the)g(history)g(list)
+h(according)g(to)e Fj(state)p Fo(.)p eop
+%%Page: 7 9
+8 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1039
+b(7)0 158 y Fi(2.3.2)30 b(History)15 b(List)g(Managemen)n(t)62
+295 y Fo(These)i(functions)h(manage)e(individual)k(en)o(tries)d(on)f(the)h
+(history)g(list,)g(or)f(set)h(parameters)e(managing)i(the)0
+358 y(list)f(itself.)1725 520 y(F)l(unction)-1899 b Fh(void)20
+b Fg(add)p 219 520 18 3 v 20 w(history)j Ff(\()p Fn(char)14
+b(*string)p Ff(\))120 582 y Fo(Place)j Fj(string)k Fo(at)16
+b(the)g(end)i(of)e(the)g(history)h(list.)25 b(The)17 b(asso)q(ciated)g(data)f
+(\014eld)h(\(if)g(an)o(y\))f(is)h(set)g(to)120 644 y Fn(NULL)p
+Fo(.)1725 806 y(F)l(unction)-1899 b Fh(HIST_ENTRY)21 b(*)e
+Fg(remo)n(v)n(e)p 509 806 V 20 w(history)k Ff(\()p Fn(int)14
+b(which)p Ff(\))120 868 y Fo(Remo)o(v)o(e)d(history)g(en)o(try)g(at)g
+(o\013set)f Fj(whic)o(h)i Fo(from)f(the)g(history)l(.)19 b(The)11
+b(remo)o(v)o(ed)g(elemen)o(t)h(is)g(returned)120 930 y(so)j(y)o(ou)g(can)g
+(free)g(the)h(line,)g(data,)e(and)i(con)o(taining)g(structure.)1725
+1092 y(F)l(unction)-1899 b Fh(HIST_ENTRY)21 b(*)e Fg(replace)p
+505 1092 V 22 w(history)p 702 1092 V 20 w(en)n(try)24 b Ff(\()p
+Fn(int)14 b(which,)g(char)h(*line,)f(char)208 1155 y(*data)p
+Ff(\))120 1217 y Fo(Mak)o(e)d(the)i(history)f(en)o(try)g(at)f(o\013set)h
+Fj(whic)o(h)h Fo(ha)o(v)o(e)e Fj(line)17 b Fo(and)12 b Fj(data)p
+Fo(.)19 b(This)12 b(returns)g(the)h(old)g(en)o(try)e(so)120
+1279 y(y)o(ou)i(can)g(disp)q(ose)h(of)e(the)h(data.)19 b(In)13
+b(the)g(case)g(of)f(an)h(in)o(v)m(alid)i Fj(whic)o(h)p Fo(,)f(a)f
+Fn(NULL)f Fo(p)q(oin)o(ter)i(is)f(returned.)1725 1441 y(F)l(unction)-1899
+b Fh(void)20 b Fg(sti\015e)p 245 1441 V 21 w(history)j Ff(\()p
+Fn(int)14 b(max)p Ff(\))120 1503 y Fo(Sti\015e)i(the)f(history)h(list,)f
+(remem)o(b)q(ering)h(only)g(the)f(last)g Fj(max)j Fo(en)o(tries.)1725
+1665 y(F)l(unction)-1899 b Fh(int)20 b Fg(unsti\015e)p 283
+1665 V 21 w(history)i Ff(\(\))120 1728 y Fo(Stop)13 b(sti\015ing)h(the)f
+(history)l(.)19 b(This)14 b(returns)f(the)g(previous)h(amoun)o(t)e(the)h
+(history)g(w)o(as)g(sti\015ed.)20 b(The)120 1790 y(v)m(alue)c(is)g(p)q
+(ositiv)o(e)g(if)g(the)f(history)g(w)o(as)g(sti\015ed,)h(negativ)o(e)f(if)g
+(it)h(w)o(asn't.)1725 1952 y(F)l(unction)-1899 b Fh(int)20
+b Fg(history)p 276 1952 V 20 w(is)p 334 1952 V 21 w(sti\015ed)k
+Ff(\(\))120 2014 y Fo(Returns)16 b(non-zero)f(if)h(the)f(history)g(is)h
+(sti\015ed,)g(zero)f(if)g(it)h(is)g(not.)0 2222 y Fi(2.3.3)30
+b(Information)14 b(Ab)r(out)h(the)g(History)g(List)62 2359
+y Fo(These)h(functions)g(return)f(information)g(ab)q(out)g(the)h(en)o(tire)f
+(history)g(list)h(or)f(individual)j(list)f(en)o(tries.)1725
+2521 y(F)l(unction)-1899 b Fh(HIST_ENTRY)21 b(**)e Fg(history)p
+530 2521 V 21 w(list)24 b Ff(\(\))120 2583 y Fo(Return)e(a)e
+Fn(NULL)h Fo(terminated)g(arra)o(y)f(of)g Fn(HIST_ENTRY)g Fo(whic)o(h)i(is)f
+(the)g(curren)o(t)g(input)h(history)l(.)120 2645 y(Elemen)o(t)16
+b(0)f(of)f(this)i(list)g(is)g(the)f(b)q(eginning)i(of)e(time.)20
+b(If)c(there)f(is)h(no)f(history)l(,)g(return)g Fn(NULL)p Fo(.)p
+eop
+%%Page: 8 10
+9 bop 0 -83 a Fo(8)1497 b(GNU)15 b(History)g(Library)1725 158
+y(F)l(unction)-1899 b Fh(int)20 b Fg(where)p 250 158 18 3 v
+20 w(history)j Ff(\(\))120 221 y Fo(Returns)16 b(the)f(o\013set)f(of)h(the)g
+(curren)o(t)g(history)g(elemen)o(t.)1725 378 y(F)l(unction)-1899
+b Fh(HIST_ENTRY)21 b(*)e Fg(curren)n(t)p 512 378 V 21 w(history)k
+Ff(\(\))120 440 y Fo(Return)14 b(the)g(history)g(en)o(try)f(at)h(the)g
+(curren)o(t)f(p)q(osition,)i(as)e(determined)j(b)o(y)d Fn(where_history)h
+(\(\))p Fo(.)120 502 y(If)h(there)h(is)f(no)h(en)o(try)e(there,)h(return)g(a)
+g Fn(NULL)g Fo(p)q(oin)o(ter.)1725 660 y(F)l(unction)-1899
+b Fh(HIST_ENTRY)21 b(*)e Fg(history)p 504 660 V 21 w(get)j
+Ff(\()p Fn(int)15 b(offset)p Ff(\))120 722 y Fo(Return)g(the)g(history)f(en)o
+(try)g(at)g(p)q(osition)i Fj(o\013set)p Fo(,)d(starting)h(from)g
+Fn(history_base)p Fo(.)k(If)c(there)h(is)g(no)120 784 y(en)o(try)g(there,)g
+(or)f(if)i Fj(o\013set)f Fo(is)h(greater)e(than)h(the)h(history)f(length,)g
+(return)g(a)g Fn(NULL)g Fo(p)q(oin)o(ter.)1725 942 y(F)l(unction)-1899
+b Fh(int)20 b Fg(history)p 276 942 V 20 w(total)p 412 942 V
+22 w(b)n(ytes)j Ff(\(\))120 1004 y Fo(Return)17 b(the)f(n)o(um)o(b)q(er)g(of)
+g(b)o(ytes)g(that)f(the)h(primary)g(history)g(en)o(tries)h(are)e(using.)23
+b(This)17 b(function)120 1066 y(returns)e(the)g(sum)h(of)e(the)i(lengths)f
+(of)g(all)h(the)g(lines)g(in)g(the)g(history)l(.)0 1265 y Fi(2.3.4)30
+b(Mo)n(ving)15 b(Around)h(the)f(History)g(List)62 1402 y Fo(These)h
+(functions)g(allo)o(w)f(the)g(curren)o(t)h(index)g(in)o(to)f(the)h(history)f
+(list)h(to)e(b)q(e)i(set)f(or)g(c)o(hanged.)1725 1559 y(F)l(unction)-1899
+b Fh(int)20 b Fg(history)p 276 1559 V 20 w(set)p 367 1559 V
+21 w(p)r(os)h Ff(\()p Fn(int)15 b(pos)p Ff(\))120 1621 y Fo(Set)g(the)h(p)q
+(osition)g(in)g(the)f(history)g(list)h(to)f Fj(p)q(os)p Fo(,)g(an)g(absolute)
+g(index)i(in)o(to)e(the)g(list.)1725 1779 y(F)l(unction)-1899
+b Fh(HIST_ENTRY)21 b(*)e Fg(previous)p 540 1779 V 20 w(history)k
+Ff(\(\))120 1841 y Fo(Bac)o(k)16 b(up)h(the)g(curren)o(t)f(history)h
+(o\013set)e(to)h(the)h(previous)g(history)g(en)o(try)l(,)f(and)h(return)f(a)g
+(p)q(oin)o(ter)120 1903 y(to)f(that)f(en)o(try)l(.)20 b(If)15
+b(there)g(is)h(no)f(previous)h(en)o(try)l(,)f(return)g(a)g
+Fn(NULL)g Fo(p)q(oin)o(ter.)1725 2061 y(F)l(unction)-1899 b
+Fh(HIST_ENTRY)21 b(*)e Fg(next)p 439 2061 V 21 w(history)k
+Ff(\(\))120 2123 y Fo(Mo)o(v)o(e)c(the)h(curren)o(t)g(history)f(o\013set)g
+(forw)o(ard)g(to)g(the)h(next)g(history)g(en)o(try)l(,)g(and)g(return)g(the)g
+(a)120 2185 y(p)q(oin)o(ter)c(to)e(that)h(en)o(try)l(.)k(If)d(there)f(is)h
+(no)f(next)g(en)o(try)l(,)g(return)g(a)g Fn(NULL)g Fo(p)q(oin)o(ter.)0
+2384 y Fi(2.3.5)30 b(Searc)n(hing)15 b(the)h(History)f(List)62
+2521 y Fo(These)e(functions)g(allo)o(w)f(searc)o(hing)h(of)f(the)g(history)g
+(list)h(for)f(en)o(tries)h(con)o(taining)g(a)f(sp)q(eci\014c)i(string.)19
+b(Searc)o(h-)0 2583 y(ing)e(ma)o(y)g(b)q(e)g(p)q(erformed)g(b)q(oth)g(forw)o
+(ard)f(and)h(bac)o(kw)o(ard)f(from)g(the)h(curren)o(t)f(history)h(p)q
+(osition.)26 b(The)17 b(searc)o(h)0 2645 y(ma)o(y)d(b)q(e)i
+Fj(anc)o(hored)p Fo(,)f(meaning)h(that)f(the)g(string)g(m)o(ust)g(matc)o(h)f
+(at)h(the)g(b)q(eginning)i(of)e(the)h(history)f(en)o(try)l(.)p
+eop
+%%Page: 9 11
+10 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1039
+b(9)1725 158 y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p
+276 158 18 3 v 20 w(searc)n(h)j Ff(\()p Fn(char)14 b(*string,)g(int)h
+(direction)p Ff(\))120 221 y Fo(Searc)o(h)k(the)g(history)g(for)f
+Fj(string)p Fo(,)i(starting)e(at)g(the)h(curren)o(t)g(history)g(o\013set.)30
+b(If)19 b Fj(direction)h Fn(<)f Fo(0,)120 283 y(then)14 b(the)f(searc)o(h)g
+(is)h(through)e(previous)i(en)o(tries,)g(else)g(through)f(subsequen)o(t.)20
+b(If)13 b Fj(string)k Fo(is)d(found,)120 345 y(then)f(the)g(curren)o(t)g
+(history)g(index)i(is)e(set)g(to)f(that)h(history)g(en)o(try)l(,)f(and)i(the)
+f(v)m(alue)h(returned)f(is)h(the)120 407 y(o\013set)h(in)i(the)f(line)i(of)d
+(the)h(en)o(try)g(where)g Fj(string)k Fo(w)o(as)c(found.)22
+b(Otherwise,)17 b(nothing)f(is)h(c)o(hanged,)120 470 y(and)e(a)g(-1)g(is)h
+(returned.)1725 659 y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p
+276 659 V 20 w(searc)n(h)p 452 659 V 21 w(pre\014x)i Ff(\()p
+Fn(char)15 b(*string,)f(int)g(direction)p Ff(\))120 721 y Fo(Searc)o(h)22
+b(the)h(history)f(for)f Fj(string)p Fo(,)j(starting)e(at)f(the)i(curren)o(t)f
+(history)g(o\013set.)40 b(The)22 b(searc)o(h)g(is)120 783 y(anc)o(hored:)i
+(matc)o(hing)18 b(lines)h(m)o(ust)d(b)q(egin)j(with)f Fj(string)p
+Fo(.)26 b(If)17 b Fj(direction)i Fn(<)e Fo(0,)g(then)h(the)f(searc)o(h)g(is)
+120 845 y(through)e(previous)h(en)o(tries,)f(else)i(through)d(subsequen)o(t.)
+21 b(If)16 b Fj(string)j Fo(is)d(found,)f(then)h(the)f(curren)o(t)120
+908 y(history)20 b(index)i(is)e(set)g(to)g(that)f(en)o(try)l(,)i(and)f(the)g
+(return)h(v)m(alue)g(is)g(0.)34 b(Otherwise,)22 b(nothing)e(is)120
+970 y(c)o(hanged,)15 b(and)h(a)e(-1)h(is)h(returned.)1725 1159
+y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p 276 1159 V 20
+w(searc)n(h)p 452 1159 V 21 w(p)r(os)h Ff(\()p Fn(char)15 b(*string,)f(int)g
+(direction,)g(int)h(pos)p Ff(\))120 1221 y Fo(Searc)o(h)d(for)f
+Fj(string)k Fo(in)d(the)g(history)f(list,)i(starting)e(at)g
+Fj(p)q(os)p Fo(,)h(an)f(absolute)h(index)h(in)o(to)e(the)h(list.)19
+b(If)12 b Fj(di-)120 1283 y(rection)g Fo(is)h(negativ)o(e,)f(the)g(searc)o(h)
+g(pro)q(ceeds)h(bac)o(kw)o(ard)e(from)g Fj(p)q(os)p Fo(,)i(otherwise)f(forw)o
+(ard.)17 b(Returns)120 1345 y(the)e(absolute)h(index)g(of)f(the)g(history)h
+(elemen)o(t)f(where)h Fj(string)j Fo(w)o(as)14 b(found,)h(or)g(-1)g
+(otherwise.)0 1634 y Fi(2.3.6)30 b(Managing)14 b(the)i(History)f(File)62
+1780 y Fo(The)f(History)g(library)h(can)f(read)g(the)g(history)g(from)f(and)i
+(write)f(it)g(to)f(a)h(\014le.)20 b(This)15 b(section)g(do)q(cumen)o(ts)f
+(the)0 1842 y(functions)i(for)f(managing)g(a)f(history)i(\014le.)1725
+2031 y(F)l(unction)-1899 b Fh(int)20 b Fg(read)p 211 2031 V
+20 w(history)i Ff(\()p Fn(char)15 b(*filename)p Ff(\))120 2093
+y Fo(Add)i(the)f(con)o(ten)o(ts)g(of)g Fj(\014lename)k Fo(to)c(the)h(history)
+f(list,)h(a)f(line)i(at)e(a)g(time.)24 b(If)17 b Fj(\014lename)j
+Fo(is)d Fn(NULL)p Fo(,)120 2155 y(then)f(read)f(from)f(`)p
+Fn(~/.history)p Fo('.)k(Returns)e(0)e(if)i(successful,)g(or)f(errno)g(if)h
+(not.)1725 2344 y(F)l(unction)-1899 b Fh(int)20 b Fg(read)p
+211 2344 V 20 w(history)p 406 2344 V 20 w(range)i Ff(\()p Fn(char)15
+b(*filename,)e(int)i(from,)g(int)f(to)p Ff(\))120 2407 y Fo(Read)j(a)e(range)
+h(of)f(lines)j(from)d Fj(\014lename)p Fo(,)i(adding)f(them)g(to)f(the)h
+(history)g(list.)23 b(Start)15 b(reading)i(at)120 2469 y(line)f
+Fj(from)f Fo(and)g(end)g(at)f Fj(to)p Fo(.)19 b(If)d Fj(from)e
+Fo(is)h(zero,)f(start)g(at)g(the)h(b)q(eginning.)22 b(If)15
+b Fj(to)i Fo(is)e(less)g(than)g Fj(from)p Fo(,)120 2531 y(then)i(read)g(un)o
+(til)h(the)f(end)g(of)g(the)g(\014le.)25 b(If)17 b Fj(\014lename)k
+Fo(is)c Fn(NULL)p Fo(,)f(then)i(read)e(from)g(`)p Fn(~/.history)p
+Fo('.)120 2593 y(Returns)g(0)f(if)g(successful,)h(or)f Fn(errno)g
+Fo(if)g(not.)p eop
+%%Page: 10 12
+11 bop 0 -83 a Fo(10)1474 b(GNU)15 b(History)g(Library)1725
+158 y(F)l(unction)-1899 b Fh(int)20 b Fg(write)p 229 158 18
+3 v 22 w(history)i Ff(\()p Fn(char)15 b(*filename)p Ff(\))120
+221 y Fo(W)l(rite)20 b(the)g(curren)o(t)f(history)h(to)f Fj(\014lename)p
+Fo(,)i(o)o(v)o(erwriting)f Fj(\014lename)j Fo(if)d(necessary)l(.)34
+b(If)20 b Fj(\014lename)120 283 y Fo(is)d Fn(NULL)p Fo(,)g(then)g(write)g
+(the)g(history)g(list)h(to)e(`)p Fn(~/.history)p Fo('.)23 b(V)l(alues)18
+b(returned)g(are)e(as)h(in)h Fn(read_)120 345 y(history)c(\(\))p
+Fo(.)1725 504 y(F)l(unction)-1899 b Fh(int)20 b Fg(app)r(end)p
+285 504 V 19 w(history)j Ff(\()p Fn(int)14 b(nelements,)g(char)h(*filename)p
+Ff(\))120 566 y Fo(App)q(end)i(the)e(last)g Fj(nelemen)o(ts)j
+Fo(of)d(the)g(history)g(list)h(to)f Fj(\014lename)p Fo(.)1725
+724 y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p 276 724
+V 20 w(truncate)p 507 724 V 21 w(\014le)k Ff(\()p Fn(char)14
+b(*filename,)g(int)h(nlines)p Ff(\))120 787 y Fo(T)l(runcate)g(the)h(history)
+f(\014le)h Fj(\014lename)p Fo(,)g(lea)o(ving)g(only)g(the)f(last)g
+Fj(nlines)k Fo(lines.)0 988 y Fi(2.3.7)30 b(History)15 b(Expansion)62
+1125 y Fo(These)h(functions)g(implemen)o(t)g Fn(csh)p Fo(-lik)o(e)g(history)g
+(expansion.)1725 1283 y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p
+276 1283 V 20 w(expand)j Ff(\()p Fn(char)14 b(*string,)g(char)h(**output)p
+Ff(\))120 1345 y Fo(Expand)20 b Fj(string)p Fo(,)f(placing)i(the)e(result)h
+(in)o(to)f Fj(output)p Fo(,)h(a)f(p)q(oin)o(ter)h(to)e(a)h(string)h(\(see)f
+(Section)h(1.1)120 1408 y([History)15 b(In)o(teraction],)f(page)h(1\).)20
+b(Returns:)120 1555 y Fn(0)216 b Fo(If)21 b(no)g(expansions)h(to)q(ok)e
+(place)h(\(or,)g(if)h(the)f(only)g(c)o(hange)g(in)h(the)f(text)f(w)o(as)g
+(the)360 1618 y(de-slashifying)d(of)e(the)g(history)h(expansion)g(c)o
+(haracter\);)120 1701 y Fn(1)216 b Fo(if)16 b(expansions)g(did)g(tak)o(e)e
+(place;)120 1785 y Fn(-1)192 b Fo(if)16 b(there)f(w)o(as)f(an)h(error)g(in)h
+(expansion;)120 1869 y Fn(2)216 b Fo(if)14 b(the)f(returned)h(line)h(should)f
+(only)g(b)q(e)f(displa)o(y)o(ed,)i(but)e(not)g(executed,)h(as)f(with)h(the)
+360 1931 y Fn(:p)h Fo(mo)q(di\014er)h(\(see)f(Section)h(1.1.3)e([Mo)q
+(di\014ers],)h(page)g(2\).)120 2079 y(If)g(an)h(error)e(o)q(curred)i(in)g
+(expansion,)f(then)h Fj(output)g Fo(con)o(tains)f(a)g(descriptiv)o(e)i(error)
+d(message.)1725 2238 y(F)l(unction)-1899 b Fh(char)20 b(*)f
+Fg(history)p 347 2238 V 21 w(arg)p 449 2238 V 19 w(extract)24
+b Ff(\()p Fn(int)14 b(first,)h(int)g(last,)f(char)h(*string)p
+Ff(\))120 2300 y Fo(Extract)10 b(a)h(string)g(segmen)o(t)g(consisting)h(of)f
+(the)g Fj(\014rst)h Fo(through)f Fj(last)h Fo(argumen)o(ts)e(presen)o(t)h(in)
+h Fj(string)p Fo(.)120 2362 y(Argumen)o(ts)j(are)g(brok)o(en)g(up)g(as)g(in)h
+(Bash.)1725 2521 y(F)l(unction)-1899 b Fh(char)20 b(*)f Fg(get)p
+249 2521 V 21 w(history)p 445 2521 V 20 w(ev)n(en)n(t)25 b
+Ff(\()p Fn(char)14 b(*string,)g(int)h(*cindex,)f(int)h(qchar)p
+Ff(\))120 2583 y Fo(Returns)e(the)f(text)f(of)h(the)g(history)g(ev)o(en)o(t)f
+(b)q(eginning)k(at)c Fj(string)16 b Fn(+)c Fj(*cindex)p Fo(.)20
+b Fj(*cindex)c Fo(is)d(mo)q(di\014ed)120 2645 y(to)h(p)q(oin)o(t)h(to)f
+(after)h(the)f(ev)o(en)o(t)h(sp)q(eci\014er.)21 b(A)o(t)15
+b(function)g(en)o(try)l(,)f Fj(cindex)20 b Fo(p)q(oin)o(ts)15
+b(to)f(the)h(index)h(in)o(to)p eop
+%%Page: 11 13
+12 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1017
+b(11)120 158 y Fj(string)17 b Fo(where)d(the)f(history)h(ev)o(en)o(t)f(sp)q
+(eci\014cation)i(b)q(egins.)20 b Fj(qc)o(har)d Fo(is)c(a)g(c)o(haracter)g
+(that)g(is)h(allo)o(w)o(ed)120 221 y(to)h(end)g(the)h(ev)o(en)o(t)f(sp)q
+(eci\014cation)i(in)f(addition)g(to)f(the)g(\\normal")g(terminating)g(c)o
+(haracters.)1725 394 y(F)l(unction)-1899 b Fh(char)20 b(**)f
+Fg(history)p 373 394 18 3 v 21 w(tok)n(enize)25 b Ff(\()p Fn(char)14
+b(*string)p Ff(\))120 456 y Fo(Return)k(an)f(arra)o(y)f(of)h(tok)o(ens)f
+(parsed)i(out)e(of)h Fj(string)p Fo(,)g(m)o(uc)o(h)h(as)e(the)i(shell)g(migh)
+o(t.)26 b(The)17 b(tok)o(ens)120 519 y(are)c(split)h(on)f(white)g(space)h
+(and)f(on)g(the)g(c)o(haracters)f Fn(\(\)<>;&|$)p Fo(,)g(and)h(shell)i
+(quoting)e(con)o(v)o(en)o(tions)120 581 y(are)i(ob)q(ey)o(ed.)0
+840 y Fm(2.4)33 b(History)15 b(V)-6 b(ariables)62 981 y Fo(This)16
+b(section)g(describ)q(es)h(the)e(externally)h(visible)i(v)m(ariables)e(exp)q
+(orted)g(b)o(y)f(the)g(GNU)g(History)g(Library)l(.)1736 1155
+y(V)l(ariable)-1899 b Fh(int)20 b Fg(history)p 276 1155 V 20
+w(base)120 1217 y Fo(The)15 b(logical)i(o\013set)d(of)h(the)g(\014rst)g(en)o
+(try)g(in)h(the)f(history)g(list.)1736 1390 y(V)l(ariable)-1899
+b Fh(int)20 b Fg(history)p 276 1390 V 20 w(length)120 1453
+y Fo(The)15 b(n)o(um)o(b)q(er)h(of)f(en)o(tries)g(curren)o(tly)h(stored)f(in)
+h(the)f(history)g(list.)1736 1626 y(V)l(ariable)-1899 b Fh(int)20
+b Fg(max)p 208 1626 V 19 w(input)p 360 1626 V 21 w(history)120
+1689 y Fo(The)12 b(maxim)o(um)g(n)o(um)o(b)q(er)g(of)f(history)h(en)o(tries.)
+19 b(This)12 b(m)o(ust)f(b)q(e)h(c)o(hanged)g(using)h Fn(stifle_history)120
+1751 y(\(\))p Fo(.)1736 1924 y(V)l(ariable)-1899 b Fh(char)20
+b Fg(history)p 302 1924 V 20 w(expansion)p 569 1924 V 21 w(c)n(har)120
+1987 y Fo(The)15 b(c)o(haracter)g(that)f(starts)g(a)h(history)g(ev)o(en)o(t.)
+20 b(The)15 b(default)h(is)g(`)p Fn(!)p Fo('.)1736 2160 y(V)l(ariable)-1899
+b Fh(char)20 b Fg(history)p 302 2160 V 20 w(subst)p 454 2160
+V 20 w(c)n(har)120 2222 y Fo(The)13 b(c)o(haracter)e(that)h(in)o(v)o(ok)o(es)
+g(w)o(ord)g(substitution)h(if)g(found)g(at)e(the)i(start)e(of)h(a)g(line.)21
+b(The)12 b(default)120 2285 y(is)k(`)p Fn(^)p Fo('.)1736 2458
+y(V)l(ariable)-1899 b Fh(char)20 b Fg(history)p 302 2458 V
+20 w(commen)n(t)p 552 2458 V 19 w(c)n(har)120 2521 y Fo(During)12
+b(tok)o(enization,)h(if)f(this)h(c)o(haracter)e(is)i(seen)f(as)g(the)g
+(\014rst)f(c)o(haracter)g(of)h(a)g(w)o(ord,)f(then)i(it)f(and)120
+2583 y(all)19 b(subsequen)o(t)g(c)o(haracters)e(up)h(to)g(a)f(newline)j(are)e
+(ignored,)h(suppressing)g(history)f(expansion)120 2645 y(for)d(the)g
+(remainder)h(of)f(the)g(line.)21 b(This)16 b(is)g(disabled)h(b)o(y)e
+(default.)p eop
+%%Page: 12 14
+13 bop 0 -83 a Fo(12)1474 b(GNU)15 b(History)g(Library)1736
+158 y(V)l(ariable)-1899 b Fh(char)20 b(*)f Fg(history)p 347
+158 18 3 v 21 w(no)p 429 158 V 20 w(expand)p 629 158 V 20 w(c)n(hars)120
+221 y Fo(The)f(list)g(of)g(c)o(haracters)e(whic)o(h)j(inhibit)h(history)d
+(expansion)i(if)f(found)g(immediately)h(follo)o(wing)120 283
+y Fj(history)p 261 283 14 2 v 16 w(expansion)p 472 283 V 18
+w(c)o(har)p Fo(.)g(The)d(default)f(is)h(whitespace)g(and)g(`)p
+Fn(=)p Fo('.)0 575 y Fm(2.5)33 b(History)15 b(Programming)h(Example)62
+720 y Fo(The)g(follo)o(wing)g(program)e(demonstrates)g(simple)j(use)e(of)g
+(the)g(GNU)g(History)g(Library)l(.)120 852 y Fn(main)23 b(\(\))120
+902 y({)168 951 y(char)g(line[1024],)f(*t;)168 1001 y(int)h(len,)g(done)h(=)g
+(0;)168 1101 y(line[0])f(=)g(0;)168 1201 y(using_history)f(\(\);)168
+1250 y(while)h(\(!done\))215 1300 y({)263 1350 y(printf)g(\("history$)g("\);)
+263 1400 y(fflush)g(\(stdout\);)263 1450 y(t)h(=)g(fgets)f(\(line,)g(sizeof)g
+(\(line\))g(-)h(1,)f(stdin\);)263 1499 y(if)h(\(t)f(&&)h(*t\))311
+1549 y({)359 1599 y(len)f(=)h(strlen)f(\(t\);)359 1649 y(if)g(\(t[len)g(-)h
+(1])g(==)f('\\n'\))406 1699 y(t[len)h(-)f(1])h(=)g('\\0';)311
+1748 y(})263 1848 y(if)g(\(!t\))311 1898 y(strcpy)f(\(line,)g("quit"\);)263
+1998 y(if)h(\(line[0]\))311 2047 y({)359 2097 y(char)f(*expansion;)359
+2147 y(int)g(result;)359 2247 y(result)g(=)g(history_expand)f(\(line,)h
+(&expansion\);)359 2296 y(if)g(\(result\))406 2346 y(fprintf)g(\(stderr,)g
+("\045s\\n",)g(expansion\);)359 2446 y(if)g(\(result)g(<)h(0)g(||)f(result)g
+(==)h(2\))406 2496 y({)454 2545 y(free)f(\(expansion\);)454
+2595 y(continue;)406 2645 y(})p eop
+%%Page: 13 15
+14 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1017
+b(13)359 208 y Fn(add_history)22 b(\(expansion\);)359 258 y(strncpy)h
+(\(line,)g(expansion,)f(sizeof)h(\(line\))g(-)h(1\);)359 308
+y(free)f(\(expansion\);)311 358 y(})263 457 y(if)h(\(strcmp)f(\(line,)g
+("quit"\))g(==)g(0\))311 507 y(done)g(=)h(1;)263 557 y(else)f(if)h(\(strcmp)f
+(\(line,)g("save"\))g(==)h(0\))311 607 y(write_history)e(\("history_file"\);)
+263 656 y(else)h(if)h(\(strcmp)f(\(line,)g("read"\))g(==)h(0\))311
+706 y(read_history)e(\("history_file"\);)263 756 y(else)h(if)h(\(strcmp)f
+(\(line,)g("list"\))g(==)h(0\))311 806 y({)359 856 y(register)e(HIST_ENTRY)h
+(**the_list;)359 906 y(register)f(int)i(i;)359 1005 y(the_list)e(=)i
+(history_list)e(\(\);)359 1055 y(if)h(\(the_list\))406 1105
+y(for)h(\(i)f(=)h(0;)g(the_list[i];)e(i++\))454 1155 y(printf)h(\("\045d:)g
+(\045s\\n",)g(i)h(+)g(history_base,)e(the_list[i]->line\);)311
+1204 y(})263 1254 y(else)h(if)h(\(strncmp)f(\(line,)g("delete",)g(6\))g(==)h
+(0\))311 1304 y({)359 1354 y(int)f(which;)359 1404 y(if)g(\(\(sscanf)g
+(\(line)g(+)h(6,)f("\045d",)h(&which\)\))e(==)i(1\))406 1453
+y({)454 1503 y(HIST_ENTRY)f(*entry)g(=)g(remove_history)f(\(which\);)454
+1553 y(if)i(\(!entry\))502 1603 y(fprintf)f(\(stderr,)f("No)i(such)f(entry)g
+(\045d\\n",)g(which\);)454 1653 y(else)502 1703 y({)550 1752
+y(free)g(\(entry->line\);)550 1802 y(free)g(\(entry\);)502
+1852 y(})406 1902 y(})359 1952 y(else)406 2001 y({)454 2051
+y(fprintf)g(\(stderr,)g("non-numeric)f(arg)h(given)h(to)f(`delete'\\n"\);)406
+2101 y(})311 2151 y(})215 2201 y(})120 2250 y(})p eop
+%%Page: 14 16
+15 bop 0 -83 a Fo(14)1474 b(GNU)15 b(History)g(Library)p eop
+%%Page: 15 17
+16 bop 0 -83 a Fo(App)q(endix)17 b(A:)e(Concept)g(Index)1346
+b(15)0 158 y Fk(App)r(endix)13 b(A)41 b(Concept)15 b(Index)0
+405 y Fm(A)0 471 y Fe(anc)o(hored)f(searc)o(h)5 b Fd(:)i(:)f(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fe(8)0
+579 y Fm(E)0 646 y Fe(ev)o(en)o(t)13 b(designators)g Fd(:)6
+b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)23
+b Fe(1)1015 405 y(expansion)5 b Fd(:)k(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fe(1)1015
+521 y Fm(H)1015 587 y Fe(history)d(ev)o(en)o(ts)5 b Fd(:)i(:)f(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b
+Fe(1)1015 646 y(History)c(Searc)o(hing)7 b Fd(:)h(:)e(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fe(8)p eop
+%%Page: 16 18
+17 bop 0 -83 a Fo(16)1474 b(GNU)15 b(History)g(Library)p eop
+%%Page: 17 19
+18 bop 0 -83 a Fo(App)q(endix)17 b(B:)e(F)l(unction)h(and)g(V)l(ariable)g
+(Index)1069 b(17)0 158 y Fk(App)r(endix)13 b(B)41 b(F)-7 b(unction)15
+b(and)g(V)-7 b(ariable)14 b(Index)0 405 y Fm(A)0 471 y Fc(add)p
+62 471 12 2 v 13 w(history)8 b Fd(:)s(:)e(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20 b Fe(7)0 529 y Fc(append)p
+122 529 V 12 w(history)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)24 b Fe(10)0 654 y Fm(C)0 720 y Fc(current)p
+142 720 V 11 w(history)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)24 b Fe(8)0 845 y Fm(G)0 911 y Fc(get)p 62 911
+V 13 w(history)p 215 911 V 11 w(event)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)23 b Fe(10)0 1036 y Fm(H)0 1102 y Fc(history)p
+142 1102 V 11 w(arg)p 213 1102 V 13 w(extract)8 b Fd(:)t(:)e(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)21 b Fe(10)0 1160 y Fc(history)p 142 1160
+V 11 w(base)e Fd(:)6 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)
+g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)20 b Fe(11)0 1218 y Fc(history)p 142 1218 V 11 w(comment)p
+293 1218 V 12 w(char)g Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)21
+b Fe(11)0 1276 y Fc(history)p 142 1276 V 11 w(expand)10 b Fd(:)c(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)24 b Fe(10)0
+1335 y Fc(history)p 142 1335 V 11 w(expansion)p 333 1335 V
+11 w(char)17 b Fd(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fe(11)0
+1393 y Fc(history)p 142 1393 V 11 w(get)8 b Fd(:)d(:)h(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20 b Fe(8)0
+1451 y Fc(history)p 142 1451 V 11 w(get)p 213 1451 V 13 w(history)p
+366 1451 V 12 w(state)t Fd(:)t(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fe(6)0
+1509 y Fc(history)p 142 1509 V 11 w(is)p 193 1509 V 14 w(stifled)7
+b Fd(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b
+Fe(7)0 1567 y Fc(history)p 142 1567 V 11 w(length)16 b Fd(:)6
+b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18
+b Fe(11)0 1625 y Fc(history)p 142 1625 V 11 w(list)7 b Fd(:)t(:)g(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)19
+b Fe(7)0 1683 y Fc(history)p 142 1683 V 11 w(no)p 193 1683
+V 14 w(expand)p 327 1683 V 12 w(chars)f Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20
+b Fe(12)0 1741 y Fc(history)p 142 1741 V 11 w(search)t Fd(:)t(:)6
+b(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17
+b Fe(9)0 1800 y Fc(history)p 142 1800 V 11 w(search)p 273 1800
+V 12 w(pos)9 b Fd(:)d(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23
+b Fe(9)0 1858 y Fc(history)p 142 1858 V 11 w(search)p 273 1858
+V 12 w(prefix)6 b Fd(:)t(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fe(9)0 1916 y Fc(history)p 142 1916 V 11 w(set)p 213 1916
+V 13 w(history)p 366 1916 V 12 w(state)t Fd(:)t(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17
+b Fe(6)0 1974 y Fc(history)p 142 1974 V 11 w(set)p 213 1974
+V 13 w(pos)5 b Fd(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)18 b Fe(8)0 2032 y Fc(history)p 142 2032 V 11 w(subst)p
+253 2032 V 13 w(char)k Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)24
+b Fe(11)1015 405 y Fc(history)p 1157 405 V 12 w(tokenize)9
+b Fd(:)s(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)22
+b Fe(11)1015 463 y Fc(history)p 1157 463 V 12 w(total)p 1269
+463 V 12 w(bytes)9 b Fd(:)t(:)d(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22
+b Fe(8)1015 521 y Fc(history)p 1157 521 V 12 w(truncate)p 1329
+521 V 11 w(file)5 b Fd(:)g(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)
+f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19
+b Fe(10)1015 629 y Fm(M)1015 695 y Fc(max)p 1077 695 V 13 w(input)p
+1190 695 V 13 w(history)14 b Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)17 b Fe(11)1015 803 y Fm(N)1015 870 y Fc(next)p 1097
+870 V 13 w(history)7 b Fd(:)s(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fe(8)1015 978 y Fm(P)1015 1044
+y Fc(previous)p 1177 1044 V 12 w(history)7 b Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b Fe(8)1015 1152 y Fm(R)1015
+1218 y Fc(read)p 1097 1218 V 13 w(history)7 b Fd(:)s(:)f(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fe(9)1015
+1276 y Fc(read)p 1097 1276 V 13 w(history)p 1250 1276 V 11
+w(range)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)23
+b Fe(9)1015 1335 y Fc(remove)p 1137 1335 V 12 w(history)t Fd(:)t(:)6
+b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)17
+b Fe(7)1015 1393 y Fc(replace)p 1157 1393 V 12 w(history)p
+1309 1393 V 11 w(entry)6 b Fd(:)f(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)19
+b Fe(7)1015 1501 y Fm(S)1015 1567 y Fc(stifle)p 1137 1567 V
+12 w(history)t Fd(:)t(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)g(:)g(:)17 b Fe(7)1015 1675 y Fm(U)1015 1741 y Fc(unstifle)p
+1177 1741 V 12 w(history)7 b Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)g(:)g(:)g(:)23 b Fe(7)1015 1800 y Fc(using)p 1117 1800 V
+13 w(history)5 b Fd(:)s(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)h(:)f(:)g(:)18 b Fe(6)1015 1907 y Fm(W)1015 1974 y Fc(where)p
+1117 1974 V 13 w(history)5 b Fd(:)s(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)18 b Fe(8)1015 2032 y Fc(write)p
+1117 2032 V 13 w(history)5 b Fd(:)s(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g
+(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)18 b Fe(9)p eop
+%%Page: 18 20
+19 bop 0 -83 a Fo(18)1474 b(GNU)15 b(History)g(Library)p eop
+%%Page: -1 21
+20 bop 1937 -83 a Fo(i)0 158 y Fk(T)-7 b(able)15 b(of)g(Con)n(ten)n(ts)0
+333 y Fm(1)67 b(Using)22 b(History)h(In)n(teractiv)n(ely)9
+b Fb(:)k(:)d(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)31 b Fm(1)149 411 y Fo(1.1)45
+b(History)15 b(In)o(teraction)9 b Fa(:)f(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)23
+b Fo(1)299 473 y(1.1.1)44 b(Ev)o(en)o(t)14 b(Designators)6
+b Fa(:)h(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)20 b Fo(1)299 535 y(1.1.2)44 b(W)l(ord)15 b(Designators)9
+b Fa(:)d(:)h(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)23 b Fo(2)299 597 y(1.1.3)44 b(Mo)q(di\014ers)14
+b Fa(:)8 b(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)28 b Fo(2)0 722
+y Fm(2)67 b(Programming)23 b(with)g(GNU)f(History)13 b Fb(:)e(:)f(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)36 b
+Fm(5)149 800 y Fo(2.1)45 b(In)o(tro)q(duction)16 b(to)f(History)6
+b Fa(:)h(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)20 b Fo(5)149 862 y(2.2)45 b(History)15
+b(Storage)d Fa(:)7 b(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)27
+b Fo(5)149 924 y(2.3)45 b(History)15 b(F)l(unctions)c Fa(:)d(:)f(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)25 b Fo(6)299 986 y(2.3.1)44 b(Initializing)18
+b(History)d(and)h(State)e(Managemen)o(t)f Fa(:)7 b(:)g(:)g(:)h(:)f(:)g(:)g(:)
+g(:)h(:)f(:)g(:)g(:)g(:)h(:)27 b Fo(6)299 1049 y(2.3.2)44 b(History)15
+b(List)h(Managemen)o(t)c Fa(:)7 b(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h
+(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)28 b Fo(7)299 1111 y(2.3.3)44 b(Information)15 b(Ab)q(out)g(the)h(History)
+f(List)5 b Fa(:)i(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)19 b Fo(7)299 1173 y(2.3.4)44 b(Mo)o(ving)15
+b(Around)g(the)g(History)g(List)6 b Fa(:)i(:)f(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)20
+b Fo(8)299 1236 y(2.3.5)44 b(Searc)o(hing)16 b(the)f(History)g(List)7
+b Fa(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)21 b
+Fo(8)299 1298 y(2.3.6)44 b(Managing)15 b(the)g(History)g(File)5
+b Fa(:)j(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)19 b
+Fo(9)299 1360 y(2.3.7)44 b(History)15 b(Expansion)d Fa(:)7
+b(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)26
+b Fo(10)149 1422 y(2.4)45 b(History)15 b(V)l(ariables)5 b Fa(:)k(:)e(:)g(:)g
+(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g
+(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)h(:)f(:)g(:)20 b Fo(11)149 1485 y(2.5)45 b(History)15
+b(Programming)f(Example)8 b Fa(:)g(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)
+g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f
+(:)g(:)g(:)g(:)23 b Fo(12)0 1609 y Fm(App)r(endix)h(A)67 b(Concept)22
+b(Index)15 b Fb(:)c(:)f(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g
+(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)37 b Fm(15)0 1749
+y(App)r(endix)24 b(B)67 b(F)-6 b(unction)25 b(and)e(V)-6 b(ariable)24
+b(Index)8 b Fb(:)j(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)31
+b Fm(17)p eop
+%%Page: -2 22
+21 bop 0 -83 a Fo(ii)1496 b(GNU)15 b(History)g(Library)p eop
+%%Trailer
+end
+userdict /end-hook known{end-hook}if
+%%EOF
diff --git a/lib/readline/doc/rlman.texinfo b/lib/readline/doc/rlman.texinfo
new file mode 100644 (file)
index 0000000..ec14066
--- /dev/null
@@ -0,0 +1,111 @@
+\input texinfo    @c -*-texinfo-*-
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename readline.info
+@settitle GNU Readline Library
+@comment %**end of header (This is for running Texinfo on a region.)
+@synindex vr fn
+@setchapternewpage odd
+
+@ignore
+last change: Thu Jul 21 16:02:40 EDT 1994
+@end ignore
+
+@set EDITION 2.0
+@set VERSION 2.0
+@set UPDATED 21 July 1994
+@set UPDATE-MONTH July 1994
+
+@ifinfo
+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, 1991 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+pare preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@titlepage  
+@sp 10
+@title GNU Readline Library
+@subtitle Edition @value{EDITION}, for @code{Readline Library} Version @value{VERSION}.
+@subtitle @value{UPDATE-MONTH}
+@author Brian Fox, Free Software Foundation
+@author Chet Ramey, Case Western Reserve University
+
+@page
+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.
+
+Published by the Free Software Foundation @*
+675 Massachusetts Avenue, @*
+Cambridge, MA 02139 USA
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
+@end titlepage
+
+@ifinfo
+@node Top
+@top GNU Readline Library
+
+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.
+
+@menu
+* Command Line Editing::          GNU Readline User's Manual.
+* Programming with GNU Readline::  GNU Readline Programmer's Manual.
+* Concept Index::                 Index of concepts described in this manual.
+* Function and Variable Index::           Index of externally visible functions
+                                  and variables.
+@end menu
+@end ifinfo
+
+@include rluser.texinfo
+@include rltech.texinfo
+
+@node Concept Index
+@unnumbered Concept Index
+@printindex cp
+
+@node Function and Variable Index
+@unnumbered Function and Variable Index
+@printindex fn
+
+@contents
+@bye
diff --git a/lib/readline/doc/rltech.texinfo b/lib/readline/doc/rltech.texinfo
new file mode 100644 (file)
index 0000000..636c923
--- /dev/null
@@ -0,0 +1,1406 @@
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename rltech.info
+@comment %**end of header (This is for running Texinfo on a region.)
+@setchapternewpage odd
+
+@ifinfo
+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, 1994 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+pare preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@node Programming with GNU Readline
+@chapter Programming with GNU Readline
+
+This chapter describes the interface between the GNU Readline Library and
+other programs.  If you are a programmer, and you wish to include the
+features found in GNU Readline
+such as completion, line editing, and interactive history manipulation
+in your own programs, this section is for you.
+
+@menu
+* Basic Behavior::     Using the default behavior of Readline.
+* Custom Functions::   Adding your own functions to Readline.
+* Readline Variables::                 Variables accessible to custom
+                                       functions.
+* Readline Convenience Functions::     Functions which Readline supplies to
+                                       aid in writing your own
+* Custom Completers::  Supplanting or supplementing Readline's
+                       completion functions.
+@end menu
+
+@node Basic Behavior
+@section Basic Behavior
+
+Many programs provide a command line interface, such as @code{mail},
+@code{ftp}, and @code{sh}.  For such programs, the default behaviour of
+Readline is sufficient.  This section describes how to use Readline in
+the simplest way possible, perhaps to replace calls in your code to
+@code{gets()} or @code{fgets ()}.
+
+@findex readline
+@cindex readline, function
+The function @code{readline ()} prints a prompt and then reads and returns
+a single line of text from the user.  The line @code{readline}
+returns is allocated with @code{malloc ()}; you should @code{free ()}
+the line when you are done with it.  The declaration for @code{readline}
+in ANSI C is
+
+@example
+@code{char *readline (char *@var{prompt});}
+@end example
+
+@noindent
+So, one might say
+@example
+@code{char *line = readline ("Enter a line: ");}
+@end example
+@noindent
+in order to read a line of text from the user.
+The line returned has the final newline removed, so only the
+text remains.
+
+If @code{readline} encounters an @code{EOF} while reading the line, and the
+line is empty at that point, then @code{(char *)NULL} is returned.
+Otherwise, the line is ended just as if a newline had been typed.
+
+If you want the user to be able to get at the line later, (with
+@key{C-p} for example), you must call @code{add_history ()} to save the
+line away in a @dfn{history} list of such lines.
+
+@example
+@code{add_history (line)};
+@end example
+
+@noindent
+For full details on the GNU History Library, see the associated manual.
+
+It is preferable to avoid saving empty lines on the history list, since
+users rarely have a burning need to reuse a blank line.  Here is
+a function which usefully replaces the standard @code{gets ()} library
+function, and has the advantage of no static buffer to overflow:
+
+@example
+/* A static variable for holding the line. */
+static char *line_read = (char *)NULL;
+
+/* Read a string, and return a pointer to it.  Returns NULL on EOF. */
+char *
+rl_gets ()
+@{
+  /* If the buffer has already been allocated, return the memory
+     to the free pool. */
+  if (line_read)
+    @{
+      free (line_read);
+      line_read = (char *)NULL;
+    @}
+
+  /* Get a line from the user. */
+  line_read = readline ("");
+
+  /* If the line has any text in it, save it on the history. */
+  if (line_read && *line_read)
+    add_history (line_read);
+
+  return (line_read);
+@}
+@end example
+
+This function gives the user the default behaviour of @key{TAB}
+completion: completion on file names.  If you do not want Readline to
+complete on filenames, you can change the binding of the @key{TAB} key
+with @code{rl_bind_key ()}.
+
+@example
+@code{int rl_bind_key (int @var{key}, int (*@var{function})());}
+@end example
+
+@code{rl_bind_key ()} takes two arguments: @var{key} is the character that
+you want to bind, and @var{function} is the address of the function to
+call when @var{key} is pressed.  Binding @key{TAB} to @code{rl_insert ()}
+makes @key{TAB} insert itself.
+@code{rl_bind_key ()} returns non-zero if @var{key} is not a valid
+ASCII character code (between 0 and 255).
+
+Thus, to disable the default @key{TAB} behavior, the following suffices:
+@example
+@code{rl_bind_key ('\t', rl_insert);}
+@end example
+
+This code should be executed once at the start of your program; you
+might write a function called @code{initialize_readline ()} which
+performs this and other desired initializations, such as installing
+custom completers (@pxref{Custom Completers}).
+
+@node Custom Functions
+@section Custom Functions
+
+Readline provides many functions for manipulating the text of
+the line, but it isn't possible to anticipate the needs of all
+programs.  This section describes the various functions and variables
+defined within the Readline library which allow a user program to add
+customized functionality to Readline.
+
+@menu
+* The Function Type::  C declarations to make code readable.
+* Function Writing::   Variables and calling conventions.
+@end menu
+
+@node The Function Type
+@subsection The Function Type
+
+For readabilty, we declare a new type of object, called
+@dfn{Function}.  A @code{Function} is a C function which
+returns an @code{int}.  The type declaration for @code{Function} is:
+
+@noindent
+@code{typedef int Function ();}
+
+The reason for declaring this new type is to make it easier to write
+code describing pointers to C functions.  Let us say we had a variable
+called @var{func} which was a pointer to a function.  Instead of the
+classic C declaration
+
+@code{int (*)()func;}
+
+@noindent
+we may write
+
+@code{Function *func;}
+
+@noindent
+Similarly, there are
+
+@example
+typedef void VFunction ();
+typedef char *CPFunction (); @r{and}
+typedef char **CPPFunction ();
+@end example
+
+@noindent
+for functions returning no value, @code{pointer to char}, and
+@code{pointer to pointer to char}, respectively.
+
+@node Function Writing
+@subsection Writing a New Function
+
+In order to write new functions for Readline, you need to know the
+calling conventions for keyboard-invoked functions, and the names of the
+variables that describe the current state of the line read so far.
+
+The calling sequence for a command @code{foo} looks like
+
+@example
+@code{foo (int count, int key)}
+@end example
+
+@noindent
+where @var{count} is the numeric argument (or 1 if defaulted) and
+@var{key} is the key that invoked this function.
+
+It is completely up to the function as to what should be done with the
+numeric argument.  Some functions use it as a repeat count, some
+as a flag, and others to choose alternate behavior (refreshing the current
+line as opposed to refreshing the screen, for example).  Some choose to
+ignore it.  In general, if a
+function uses the numeric argument as a repeat count, it should be able
+to do something useful with both negative and positive arguments.
+At the very least, it should be aware that it can be passed a
+negative argument.
+
+@node Readline Variables
+@section Readline Variables
+
+These variables are available to function writers.
+
+@deftypevar {char *} rl_line_buffer
+This is the line gathered so far.  You are welcome to modify the
+contents of the line, but see @ref{Allowing Undoing}.
+@end deftypevar
+
+@deftypevar int rl_point
+The offset of the current cursor position in @code{rl_line_buffer}
+(the @emph{point}).
+@end deftypevar
+
+@deftypevar int rl_end
+The number of characters present in @code{rl_line_buffer}.  When
+@code{rl_point} is at the end of the line, @code{rl_point} and
+@code{rl_end} are equal.
+@end deftypevar
+
+@deftypevar int rl_mark
+The mark (saved position) in the current line.  If set, the mark
+and point define a @emph{region}.
+@end deftypevar
+
+@deftypevar int rl_done
+Setting this to a non-zero value causes Readline to return the current
+line immediately.
+@end deftypevar
+
+@deftypevar int rl_pending_input
+Setting this to a value makes it the next keystroke read.  This is a
+way to stuff a single character into the input stream.
+@end deftypevar
+
+@deftypevar {char *} rl_prompt
+The prompt Readline uses.  This is set from the argument to
+@code{readline ()}, and should not be assigned to directly.
+@end deftypevar
+
+@deftypevar {char *} rl_terminal_name
+The terminal type, used for initialization.
+@end deftypevar
+
+@deftypevar {char *} rl_readline_name
+This variable is set to a unique name by each application using Readline.
+The value allows conditional parsing of the inputrc file
+(@pxref{Conditional Init Constructs}).
+@end deftypevar
+
+@deftypevar {FILE *} rl_instream
+The stdio stream from which Readline reads input.
+@end deftypevar
+
+@deftypevar {FILE *} rl_outstream
+The stdio stream to which Readline performs output.
+@end deftypevar
+
+@deftypevar {Function *} rl_startup_hook
+If non-zero, this is the address of a function to call just
+before @code{readline} prints the first prompt.
+@end deftypevar
+
+@deftypevar {Function *} rl_event_hook
+If non-zero, this is the address of a function to call periodically
+when readline is waiting for terminal input.
+@end deftypevar
+
+@node Readline Convenience Functions
+@section Readline Convenience Functions
+
+@menu
+* Function Naming::    How to give a function you write a name.
+* Keymaps::            Making keymaps.
+* Binding Keys::       Changing Keymaps.
+* Associating Function Names and Bindings::    Translate function names to
+                                               key sequences.
+* Allowing Undoing::   How to make your functions undoable.
+* Redisplay::          Functions to control line display.
+* Modifying Text::     Functions to modify @code{rl_line_buffer}.
+* Utility Functions::  Generally useful functions and hooks.
+@end menu
+
+@node Function Naming
+@subsection Naming a Function
+
+The user can dynamically change the bindings of keys while using
+Readline.  This is done by representing the function with a descriptive
+name.  The user is able to type the descriptive name when referring to
+the function.  Thus, in an init file, one might find
+
+@example
+Meta-Rubout:   backward-kill-word
+@end example
+
+This binds the keystroke @key{Meta-Rubout} to the function
+@emph{descriptively} named @code{backward-kill-word}.  You, as the
+programmer, should bind the functions you write to descriptive names as
+well.  Readline provides a function for doing that:
+
+@deftypefun int rl_add_defun (char *name, Function *function, int key)
+Add @var{name} to the list of named functions.  Make @var{function} be
+the function that gets called.  If @var{key} is not -1, then bind it to
+@var{function} using @code{rl_bind_key ()}.
+@end deftypefun
+
+Using this function alone is sufficient for most applications.  It is
+the recommended way to add a few functions to the default functions that
+Readline has built in.  If you need to do something other
+than adding a function to Readline, you may need to use the
+underlying functions described below.
+
+@node Keymaps
+@subsection Selecting a Keymap
+
+Key bindings take place on a @dfn{keymap}.  The keymap is the
+association between the keys that the user types and the functions that
+get run.  You can make your own keymaps, copy existing keymaps, and tell
+Readline which keymap to use.
+
+@deftypefun Keymap rl_make_bare_keymap ()
+Returns a new, empty keymap.  The space for the keymap is allocated with
+@code{malloc ()}; you should @code{free ()} it when you are done.
+@end deftypefun
+
+@deftypefun Keymap rl_copy_keymap (Keymap map)
+Return a new keymap which is a copy of @var{map}.
+@end deftypefun
+
+@deftypefun Keymap rl_make_keymap ()
+Return a new keymap with the printing characters bound to rl_insert,
+the lowercase Meta characters bound to run their equivalents, and
+the Meta digits bound to produce numeric arguments.
+@end deftypefun
+
+@deftypefun void rl_discard_keymap (Keymap keymap)
+Free the storage associated with @var{keymap}.
+@end deftypefun
+
+Readline has several internal keymaps.  These functions allow you to
+change which keymap is active.
+
+@deftypefun Keymap rl_get_keymap ()
+Returns the currently active keymap.
+@end deftypefun
+
+@deftypefun void rl_set_keymap (Keymap keymap)
+Makes @var{keymap} the currently active keymap.
+@end deftypefun
+
+@deftypefun Keymap rl_get_keymap_by_name (char *name)
+Return the keymap matching @var{name}.  @var{name} is one which would
+be supplied in a @code{set keymap} inputrc line (@pxref{Readline Init File}).
+@end deftypefun
+
+@node Binding Keys
+@subsection Binding Keys
+
+You associate keys with functions through the keymap.  Readline has
+several internal keymaps: @code{emacs_standard_keymap},
+@code{emacs_meta_keymap}, @code{emacs_ctlx_keymap},
+@code{vi_movement_keymap}, and @code{vi_insertion_keymap}.
+@code{emacs_standard_keymap} is the default, and the examples in
+this manual assume that.
+
+These functions manage key bindings.
+
+@deftypefun int rl_bind_key (int key, Function *function)
+Binds @var{key} to @var{function} in the currently active keymap.
+Returns non-zero in the case of an invalid @var{key}.
+@end deftypefun
+
+@deftypefun int rl_bind_key_in_map (int key, Function *function, Keymap map)
+Bind @var{key} to @var{function} in @var{map}.  Returns non-zero in the case
+of an invalid @var{key}.
+@end deftypefun
+
+@deftypefun int rl_unbind_key (int key)
+Bind @var{key} to the null function in the currently active keymap.
+Returns non-zero in case of error.
+@end deftypefun
+
+@deftypefun int rl_unbind_key_in_map (int key, Keymap map)
+Bind @var{key} to the null function in @var{map}.
+Returns non-zero in case of error.
+@end deftypefun
+
+@deftypefun int rl_generic_bind (int type, char *keyseq, char *data, Keymap map)
+Bind the key sequence represented by the string @var{keyseq} to the arbitrary
+pointer @var{data}.  @var{type} says what kind of data is pointed to by
+@var{data}; this can be a function (@code{ISFUNC}), a macro
+(@code{ISMACR}), or a keymap (@code{ISKMAP}).  This makes new keymaps as
+necessary.  The initial keymap in which to do bindings is @var{map}.
+@end deftypefun
+
+@deftypefun int rl_parse_and_bind (char *line)
+Parse @var{line} as if it had been read from the @code{inputrc} file and
+perform any key bindings and variable assignments found
+(@pxref{Readline Init File}).
+@end deftypefun
+
+@deftypefun int rl_read_init_file (char *filename)
+Read keybindings and variable assignments from @var{filename}
+(@pxref{Readline Init File}).
+@end deftypefun
+
+@node Associating Function Names and Bindings
+@subsection Associating Function Names and Bindings
+
+These functions allow you to find out what keys invoke named functions
+and the functions invoked by a particular key sequence.
+
+@deftypefun {Function *} rl_named_function (char *name)
+Return the function with name @var{name}.
+@end deftypefun
+
+@deftypefun {Function *} rl_function_of_keyseq (char *keyseq, Keymap map, int *type)
+Return the function invoked by @var{keyseq} in keymap @var{map}.
+If @var{map} is NULL, the current keymap is used.  If @var{type} is
+not NULL, the type of the object is returned in it (one of @code{ISFUNC},
+@code{ISKMAP}, or @code{ISMACR}).
+@end deftypefun
+
+@deftypefun {char **} rl_invoking_keyseqs (Function *function)
+Return an array of strings representing the key sequences used to
+invoke @var{function} in the current keymap.
+@end deftypefun
+
+@deftypefun {char **} rl_invoking_keyseqs_in_map (Function *function, Keymap map)
+Return an array of strings representing the key sequences used to
+invoke @var{function} in the keymap @var{map}.
+@end deftypefun
+
+@deftypefun void rl_function_dumper (int readable)
+Print the readline function names and the key sequences currently
+bound to them to @code{rl_outstream}.  If @var{readable} is non-zero,
+the list is formatted in such a way that it can be made part of an
+@code{inputrc} file and re-read.
+@end deftypefun
+
+@deftypefun void rl_list_funmap_names ()
+Print the names of all bindable Readline functions to @code{rl_outstream}.
+@end deftypefun
+
+@node Allowing Undoing
+@subsection Allowing Undoing
+
+Supporting the undo command is a painless thing, and makes your
+functions much more useful.  It is certainly easy to try
+something if you know you can undo it.  I could use an undo function for
+the stock market.
+
+If your function simply inserts text once, or deletes text once, and
+uses @code{rl_insert_text ()} or @code{rl_delete_text ()} to do it, then
+undoing is already done for you automatically.
+
+If you do multiple insertions or multiple deletions, or any combination
+of these operations, you should group them together into one operation.
+This is done with @code{rl_begin_undo_group ()} and
+@code{rl_end_undo_group ()}.
+
+The types of events that can be undone are:
+
+@example
+enum undo_code @{ UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END @}; 
+@end example
+
+Notice that @code{UNDO_DELETE} means to insert some text, and
+@code{UNDO_INSERT} means to delete some text.  That is, the undo code
+tells undo what to undo, not how to undo it.  @code{UNDO_BEGIN} and
+@code{UNDO_END} are tags added by @code{rl_begin_undo_group ()} and
+@code{rl_end_undo_group ()}.
+
+@deftypefun int rl_begin_undo_group ()
+Begins saving undo information in a group construct.  The undo
+information usually comes from calls to @code{rl_insert_text ()} and
+@code{rl_delete_text ()}, but could be the result of calls to
+@code{rl_add_undo ()}.
+@end deftypefun
+
+@deftypefun int rl_end_undo_group ()
+Closes the current undo group started with @code{rl_begin_undo_group
+()}.  There should be one call to @code{rl_end_undo_group ()}
+for each call to @code{rl_begin_undo_group ()}.
+@end deftypefun
+
+@deftypefun void rl_add_undo (enum undo_code what, int start, int end, char *text)
+Remember how to undo an event (according to @var{what}).  The affected
+text runs from @var{start} to @var{end}, and encompasses @var{text}.
+@end deftypefun
+
+@deftypefun void free_undo_list ()
+Free the existing undo list.
+@end deftypefun
+
+@deftypefun int rl_do_undo ()
+Undo the first thing on the undo list.  Returns @code{0} if there was
+nothing to undo, non-zero if something was undone.
+@end deftypefun
+
+Finally, if you neither insert nor delete text, but directly modify the
+existing text (e.g., change its case), call @code{rl_modifying ()}
+once, just before you modify the text.  You must supply the indices of
+the text range that you are going to modify.
+
+@deftypefun int rl_modifying (int start, int end)
+Tell Readline to save the text between @var{start} and @var{end} as a
+single undo unit.  It is assumed that you will subsequently modify
+that text.
+@end deftypefun
+
+@node Redisplay
+@subsection Redisplay
+
+@deftypefun int rl_redisplay ()
+Change what's displayed on the screen to reflect the current contents
+of @code{rl_line_buffer}.
+@end deftypefun
+
+@deftypefun int rl_forced_update_display ()
+Force the line to be updated and redisplayed, whether or not
+Readline thinks the screen display is correct.
+@end deftypefun
+
+@deftypefun int rl_on_new_line ()
+Tell the update routines that we have moved onto a new (empty) line,
+usually after ouputting a newline.
+@end deftypefun
+
+@deftypefun int rl_reset_line_state ()
+Reset the display state to a clean state and redisplay the current line
+starting on a new line.
+@end deftypefun
+
+@deftypefun int rl_message (va_alist)
+The arguments are a string as would be supplied to @code{printf}.  The
+resulting string is displayed in the @dfn{echo area}.  The echo area
+is also used to display numeric arguments and search strings.
+@end deftypefun
+
+@deftypefun int rl_clear_message ()
+Clear the message in the echo area.
+@end deftypefun
+
+@node Modifying Text
+@subsection Modifying Text
+
+@deftypefun int rl_insert_text (char *text)
+Insert @var{text} into the line at the current cursor position.
+@end deftypefun
+
+@deftypefun int rl_delete_text (int start, int end)
+Delete the text between @var{start} and @var{end} in the current line.
+@end deftypefun
+
+@deftypefun {char *} rl_copy_text (int start, int end)
+Return a copy of the text between @var{start} and @var{end} in
+the current line.
+@end deftypefun
+
+@deftypefun int rl_kill_text (int start, int end)
+Copy the text between @var{start} and @var{end} in the current line
+to the kill ring, appending or prepending to the last kill if the
+last command was a kill command.  The text is deleted.
+If @var{start} is less than @var{end},
+the text is appended, otherwise prepended.  If the last command was
+not a kill, a new kill ring slot is used.
+@end deftypefun
+
+@node Utility Functions
+@subsection Utility Functions
+
+@deftypefun int rl_read_key ()
+Return the next character available.  This handles input inserted into
+the input stream via @var{pending input} (@pxref{Readline Variables})
+and @code{rl_stuff_char ()}, macros, and characters read from the keyboard.
+@end deftypefun
+
+@deftypefun int rl_stuff_char (int c)
+Insert @var{c} into the Readline input stream.  It will be "read"
+before Readline attempts to read characters from the terminal with
+@code{rl_read_key ()}.
+@end deftypefun
+
+@deftypefun int rl_initialize ()
+Initialize or re-initialize Readline's internal state.
+@end deftypefun
+
+@deftypefun int rl_reset_terminal (char *terminal_name)
+Reinitialize Readline's idea of the terminal settings using
+@var{terminal_name} as the terminal type (e.g., @code{vt100}).
+@end deftypefun
+
+@deftypefun int alphabetic (int c)
+Return 1 if @var{c} is an alphabetic character.
+@end deftypefun
+
+@deftypefun int numeric (int c)
+Return 1 if @var{c} is a numeric character.
+@end deftypefun
+
+@deftypefun int ding ()
+Ring the terminal bell, obeying the setting of @code{bell-style}.
+@end deftypefun
+
+The following are implemented as macros, defined in @code{chartypes.h}.
+
+@deftypefun int uppercase_p (int c)
+Return 1 if @var{c} is an uppercase alphabetic character.
+@end deftypefun
+
+@deftypefun int lowercase_p (int c)
+Return 1 if @var{c} is a lowercase alphabetic character.
+@end deftypefun
+
+@deftypefun int digit_p (int c)
+Return 1 if @var{c} is a numeric character.
+@end deftypefun
+
+@deftypefun int to_upper (int c)
+If @var{c} is a lowercase alphabetic character, return the corresponding
+uppercase character.
+@end deftypefun
+
+@deftypefun int to_lower (int c)
+If @var{c} is an uppercase alphabetic character, return the corresponding
+lowercase character.
+@end deftypefun
+
+@deftypefun int digit_value (int c)
+If @var{c} is a number, return the value it represents.
+@end deftypefun
+
+@subsection An Example
+
+Here is a function which changes lowercase characters to their uppercase
+equivalents, and uppercase characters to lowercase.  If
+this function was bound to @samp{M-c}, then typing @samp{M-c} would
+change the case of the character under point.  Typing @samp{M-1 0 M-c}
+would change the case of the following 10 characters, leaving the cursor on
+the last character changed.
+
+@example
+/* Invert the case of the COUNT following characters. */
+int
+invert_case_line (count, key)
+     int count, key;
+@{
+  register int start, end, i;
+
+  start = rl_point;
+
+  if (rl_point >= rl_end)
+    return (0);
+
+  if (count < 0)
+    @{
+      direction = -1;
+      count = -count;
+    @}
+  else
+    direction = 1;
+      
+  /* Find the end of the range to modify. */
+  end = start + (count * direction);
+
+  /* Force it to be within range. */
+  if (end > rl_end)
+    end = rl_end;
+  else if (end < 0)
+    end = 0;
+
+  if (start == end)
+    return (0);
+
+  if (start > end)
+    @{
+      int temp = start;
+      start = end;
+      end = temp;
+    @}
+
+  /* Tell readline that we are modifying the line, so it will save
+     the undo information. */
+  rl_modifying (start, end);
+
+  for (i = start; i != end; i++)
+    @{
+      if (uppercase_p (rl_line_buffer[i]))
+        rl_line_buffer[i] = to_lower (rl_line_buffer[i]);
+      else if (lowercase_p (rl_line_buffer[i]))
+        rl_line_buffer[i] = to_upper (rl_line_buffer[i]);
+    @}
+  /* Move point to on top of the last character changed. */
+  rl_point = (direction == 1) ? end - 1 : start;
+  return (0);
+@}
+@end example
+
+@node Custom Completers
+@section Custom Completers
+
+Typically, a program that reads commands from the user has a way of
+disambiguating commands and data.  If your program is one of these, then
+it can provide completion for commands, data, or both.
+The following sections describe how your program and Readline
+cooperate to provide this service.
+
+@menu
+* How Completing Works::       The logic used to do completion.
+* Completion Functions::       Functions provided by Readline.
+* Completion Variables::       Variables which control completion.
+* A Short Completion Example:: An example of writing completer subroutines.
+@end menu
+
+@node How Completing Works
+@subsection How Completing Works
+
+In order to complete some text, the full list of possible completions
+must be available.  That is, it is not possible to accurately
+expand a partial word without knowing all of the possible words
+which make sense in that context.  The Readline library provides
+the user interface to completion, and two of the most common
+completion functions:  filename and username.  For completing other types
+of text, you must write your own completion function.  This section
+describes exactly what such functions must do, and provides an example.
+
+There are three major functions used to perform completion:
+
+@enumerate
+@item
+The user-interface function @code{rl_complete ()}.  This function is
+called with the same arguments as other Readline
+functions intended for interactive use:  @var{count} and
+@var{invoking_key}.  It isolates the word to be completed and calls
+@code{completion_matches ()} to generate a list of possible completions.
+It then either lists the possible completions, inserts the possible
+completions, or actually performs the
+completion, depending on which behavior is desired.
+
+@item
+The internal function @code{completion_matches ()} uses your
+@dfn{generator} function to generate the list of possible matches, and
+then returns the array of these matches.  You should place the address
+of your generator function in @code{rl_completion_entry_function}.
+
+@item
+The generator function is called repeatedly from
+@code{completion_matches ()}, returning a string each time.  The
+arguments to the generator function are @var{text} and @var{state}.
+@var{text} is the partial word to be completed.  @var{state} is zero the
+first time the function is called, allowing the generator to perform
+any necessary initialization, and a positive non-zero integer for
+each subsequent call.  When the generator function returns
+@code{(char *)NULL} this signals @code{completion_matches ()} that there are
+no more possibilities left.  Usually the generator function computes the
+list of possible completions when @var{state} is zero, and returns them
+one at a time on subsequent calls.  Each string the generator function
+returns as a match must be allocated with @code{malloc()}; Readline
+frees the strings when it has finished with them.
+
+@end enumerate
+
+@deftypefun int rl_complete (int ignore, int invoking_key)
+Complete the word at or before point.  You have supplied the function
+that does the initial simple matching selection algorithm (see
+@code{completion_matches ()}).  The default is to do filename completion.
+@end deftypefun
+
+@deftypevar {Function *} rl_completion_entry_function
+This is a pointer to the generator function for @code{completion_matches
+()}.  If the value of @code{rl_completion_entry_function} is
+@code{(Function *)NULL} then the default filename generator function,
+@code{filename_entry_function ()}, is used.
+@end deftypevar
+
+@node Completion Functions
+@subsection Completion Functions
+
+Here is the complete list of callable completion functions present in
+Readline.
+
+@deftypefun int rl_complete_internal (int what_to_do)
+Complete the word at or before point.  @var{what_to_do} says what to do
+with the completion.  A value of @samp{?} means list the possible
+completions.  @samp{TAB} means do standard completion.  @samp{*} means
+insert all of the possible completions.  @samp{!} means to display
+all of the possible completions, if there is more than one, as well as
+performing partial completion.
+@end deftypefun
+
+@deftypefun int rl_complete (int ignore, int invoking_key)
+Complete the word at or before point.  You have supplied the function
+that does the initial simple matching selection algorithm (see
+@code{completion_matches ()} and @code{rl_completion_entry_function}).
+The default is to do filename
+completion.  This calls @code{rl_complete_internal ()} with an
+argument depending on @var{invoking_key}.
+@end deftypefun
+
+@deftypefun int rl_possible_completions (int count, int invoking_key))
+List the possible completions.  See description of @code{rl_complete
+()}.  This calls @code{rl_complete_internal ()} with an argument of
+@samp{?}.
+@end deftypefun
+
+@deftypefun int rl_insert_completions (int count, int invoking_key))
+Insert the list of possible completions into the line, deleting the
+partially-completed word.  See description of @code{rl_complete ()}.
+This calls @code{rl_complete_internal ()} with an argument of @samp{*}.
+@end deftypefun
+
+@deftypefun {char **} completion_matches (char *text, CPFunction *entry_func)
+Returns an array of @code{(char *)} which is a list of completions for
+@var{text}.  If there are no completions, returns @code{(char **)NULL}.
+The first entry in the returned array is the substitution for @var{text}.
+The remaining entries are the possible completions.  The array is
+terminated with a @code{NULL} pointer.
+
+@var{entry_func} is a function of two args, and returns a
+@code{(char *)}.  The first argument is @var{text}.  The second is a
+state argument; it is zero on the first call, and non-zero on subsequent
+calls.  @var{entry_func} returns a @code{NULL}  pointer to the caller
+when there are no more matches.
+@end deftypefun
+
+@deftypefun {char *} filename_completion_function (char *text, int state)
+A generator function for filename completion in the general case.  Note
+that completion in Bash is a little different because of all
+the pathnames that must be followed when looking up completions for a
+command.  The Bash source is a useful reference for writing custom
+completion functions.
+@end deftypefun
+
+@deftypefun {char *} username_completion_function (char *text, int state)
+A completion generator for usernames.  @var{text} contains a partial
+username preceded by a random character (usually @samp{~}).  As with all
+completion generators, @var{state} is zero on the first call and non-zero
+for subsequent calls.
+@end deftypefun
+
+@node Completion Variables
+@subsection Completion Variables
+
+@deftypevar {Function *} rl_completion_entry_function
+A pointer to the generator function for @code{completion_matches ()}.
+@code{NULL} means to use @code{filename_entry_function ()}, the default
+filename completer.
+@end deftypevar
+
+@deftypevar {CPPFunction *} rl_attempted_completion_function
+A pointer to an alternative function to create matches.
+The function is called with @var{text}, @var{start}, and @var{end}.
+@var{start} and @var{end} are indices in @code{rl_line_buffer} saying
+what the boundaries of @var{text} are.  If this function exists and
+returns @code{NULL}, or if this variable is set to @code{NULL}, then
+@code{rl_complete ()} will call the value of
+@code{rl_completion_entry_function} to generate matches, otherwise the
+array of strings returned will be used.
+@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 {char *} rl_basic_word_break_characters
+The basic list of characters that signal a break between words for the
+completer routine.  The default value of this variable is the characters
+which break words for completion in Bash, i.e.,
+@code{" \t\n\"\\'`@@$><=;|&@{("}.
+@end deftypevar
+
+@deftypevar {char *} rl_completer_word_break_characters
+The list of characters that signal a break between words for
+@code{rl_complete_internal ()}.  The default list is the value of
+@code{rl_basic_word_break_characters}.
+@end deftypevar
+
+@deftypevar {char *} rl_completer_quote_characters
+List of characters which can be used to quote a substring of the line.
+Completion occurs on the entire substring, and within the substring
+@code{rl_completer_word_break_characters} are treated as any other character,
+unless they also appear within this list.
+@end deftypevar
+
+@deftypevar {char *} rl_special_prefixes
+The list of characters that are word break characters, but should be
+left in @var{text} when it is passed to the completion function.
+Programs can use this to help determine what kind of completing to do.
+For instance, Bash sets this variable to "$@@" so that it can complete
+shell variables and hostnames.
+@end deftypevar
+
+@deftypevar int rl_ignore_completion_duplicates
+If non-zero, then disallow duplicates in the matches.  Default is 1.
+@end deftypevar
+
+@deftypevar int rl_filename_completion_desired
+Non-zero means that the results of the matches are to be treated as
+filenames.  This is @emph{always} zero on entry, and can only be changed
+within a completion entry generator function.  If it is set to a non-zero
+value, directory names have a slash appended and Readline attempts to
+quote completed filenames if they contain any embedded word break
+characters.
+@end deftypevar
+
+@deftypevar int rl_filename_quoting_desired
+Non-zero means that the results of the matches are to be quoted using
+double quotes (or an application-specific quoting mechanism) if the
+completed filename contains any characters in
+@code{rl_completer_word_break_chars}.  This is @emph{always} non-zero
+on entry, and can only be changed within a completion entry generator
+function.
+@end deftypevar
+
+@deftypevar {Function *} 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 {Function *} 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.  It could be used
+to expand symbolic links or shell variables in pathnames.
+@end deftypevar
+
+@node A Short Completion Example
+@subsection A Short Completion Example
+
+Here is a small application demonstrating the use of the GNU Readline
+library.  It is called @code{fileman}, and the source code resides in
+@file{examples/fileman.c}.  This sample application provides
+completion of command names, line editing features, and access to the
+history list.
+
+@page
+@smallexample
+/* fileman.c -- A tiny application which demonstrates how to use the
+   GNU Readline library.  This application interactively allows users
+   to manipulate files and their modes. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+extern char *getwd ();
+extern char *xmalloc ();
+
+/* The names of functions that actually do the manipulation. */
+int com_list (), com_view (), com_rename (), com_stat (), com_pwd ();
+int com_delete (), com_help (), com_cd (), com_quit ();
+
+/* A structure which contains information on the commands this program
+   can understand. */
+
+typedef struct @{
+  char *name;                  /* User printable name of the function. */
+  Function *func;              /* Function to call to do the job. */
+  char *doc;                   /* Documentation for this function.  */
+@} COMMAND;
+
+COMMAND commands[] = @{
+  @{ "cd", com_cd, "Change to directory DIR" @},
+  @{ "delete", com_delete, "Delete FILE" @},
+  @{ "help", com_help, "Display this text" @},
+  @{ "?", com_help, "Synonym for `help'" @},
+  @{ "list", com_list, "List files in DIR" @},
+  @{ "ls", com_list, "Synonym for `list'" @},
+  @{ "pwd", com_pwd, "Print the current working directory" @},
+  @{ "quit", com_quit, "Quit using Fileman" @},
+  @{ "rename", com_rename, "Rename FILE to NEWNAME" @},
+  @{ "stat", com_stat, "Print out statistics on FILE" @},
+  @{ "view", com_view, "View the contents of FILE" @},
+  @{ (char *)NULL, (Function *)NULL, (char *)NULL @}
+@};
+
+/* Forward declarations. */
+char *stripwhite ();
+COMMAND *find_command ();
+
+/* The name of this program, as taken from argv[0]. */
+char *progname;
+
+/* When non-zero, this global means the user is done using this program. */
+int done;
+
+char *
+dupstr (s)
+     int s;
+@{
+  char *r;
+
+  r = xmalloc (strlen (s) + 1);
+  strcpy (r, s);
+  return (r);
+@}
+
+main (argc, argv)
+     int argc;
+     char **argv;
+@{
+  char *line, *s;
+
+  progname = argv[0];
+
+  initialize_readline ();      /* Bind our completer. */
+
+  /* Loop reading and executing lines until the user quits. */
+  for ( ; done == 0; )
+    @{
+      line = readline ("FileMan: ");
+
+      if (!line)
+        break;
+
+      /* Remove leading and trailing whitespace from the line.
+         Then, if there is anything left, add it to the history list
+         and execute it. */
+      s = stripwhite (line);
+
+      if (*s)
+        @{
+          add_history (s);
+          execute_line (s);
+        @}
+
+      free (line);
+    @}
+  exit (0);
+@}
+
+/* Execute a command line. */
+int
+execute_line (line)
+     char *line;
+@{
+  register int i;
+  COMMAND *command;
+  char *word;
+
+  /* Isolate the command word. */
+  i = 0;
+  while (line[i] && whitespace (line[i]))
+    i++;
+  word = line + i;
+
+  while (line[i] && !whitespace (line[i]))
+    i++;
+
+  if (line[i])
+    line[i++] = '\0';
+
+  command = find_command (word);
+
+  if (!command)
+    @{
+      fprintf (stderr, "%s: No such command for FileMan.\n", word);
+      return (-1);
+    @}
+
+  /* Get argument to command, if any. */
+  while (whitespace (line[i]))
+    i++;
+
+  word = line + i;
+
+  /* Call the function. */
+  return ((*(command->func)) (word));
+@}
+
+/* Look up NAME as the name of a command, and return a pointer to that
+   command.  Return a NULL pointer if NAME isn't a command name. */
+COMMAND *
+find_command (name)
+     char *name;
+@{
+  register int i;
+
+  for (i = 0; commands[i].name; i++)
+    if (strcmp (name, commands[i].name) == 0)
+      return (&commands[i]);
+
+  return ((COMMAND *)NULL);
+@}
+
+/* Strip whitespace from the start and end of STRING.  Return a pointer
+   into STRING. */
+char *
+stripwhite (string)
+     char *string;
+@{
+  register char *s, *t;
+
+  for (s = string; whitespace (*s); s++)
+    ;
+    
+  if (*s == 0)
+    return (s);
+
+  t = s + strlen (s) - 1;
+  while (t > s && whitespace (*t))
+    t--;
+  *++t = '\0';
+
+  return s;
+@}
+
+/* **************************************************************** */
+/*                                                                  */
+/*                  Interface to Readline Completion                */
+/*                                                                  */
+/* **************************************************************** */
+
+char *command_generator ();
+char **fileman_completion ();
+
+/* Tell the GNU Readline library how to complete.  We want to try to complete
+   on command names if this is the first word in the line, or on filenames
+   if not. */
+initialize_readline ()
+@{
+  /* Allow conditional parsing of the ~/.inputrc file. */
+  rl_readline_name = "FileMan";
+
+  /* Tell the completer that we want a crack first. */
+  rl_attempted_completion_function = (CPPFunction *)fileman_completion;
+@}
+
+/* Attempt to complete on the contents of TEXT.  START and END show the
+   region of TEXT that contains the word to complete.  We can use the
+   entire line in case we want to do some simple parsing.  Return the
+   array of matches, or NULL if there aren't any. */
+char **
+fileman_completion (text, start, end)
+     char *text;
+     int start, end;
+@{
+  char **matches;
+
+  matches = (char **)NULL;
+
+  /* If this word is at the start of the line, then it is a command
+     to complete.  Otherwise it is the name of a file in the current
+     directory. */
+  if (start == 0)
+    matches = completion_matches (text, command_generator);
+
+  return (matches);
+@}
+
+/* Generator function for command completion.  STATE lets us know whether
+   to start from scratch; without any state (i.e. STATE == 0), then we
+   start at the top of the list. */
+char *
+command_generator (text, state)
+     char *text;
+     int state;
+@{
+  static int list_index, len;
+  char *name;
+
+  /* If this is a new word to complete, initialize now.  This includes
+     saving the length of TEXT for efficiency, and initializing the index
+     variable to 0. */
+  if (!state)
+    @{
+      list_index = 0;
+      len = strlen (text);
+    @}
+
+  /* Return the next name which partially matches from the command list. */
+  while (name = commands[list_index].name)
+    @{
+      list_index++;
+
+      if (strncmp (name, text, len) == 0)
+        return (dupstr(name));
+    @}
+
+  /* If no names matched, then return NULL. */
+  return ((char *)NULL);
+@}
+
+/* **************************************************************** */
+/*                                                                  */
+/*                       FileMan Commands                           */
+/*                                                                  */
+/* **************************************************************** */
+
+/* String to pass to system ().  This is for the LIST, VIEW and RENAME
+   commands. */
+static char syscom[1024];
+
+/* List the file(s) named in arg. */
+com_list (arg)
+     char *arg;
+@{
+  if (!arg)
+    arg = "";
+
+  sprintf (syscom, "ls -FClg %s", arg);
+  return (system (syscom));
+@}
+
+com_view (arg)
+     char *arg;
+@{
+  if (!valid_argument ("view", arg))
+    return 1;
+
+  sprintf (syscom, "more %s", arg);
+  return (system (syscom));
+@}
+
+com_rename (arg)
+     char *arg;
+@{
+  too_dangerous ("rename");
+  return (1);
+@}
+
+com_stat (arg)
+     char *arg;
+@{
+  struct stat finfo;
+
+  if (!valid_argument ("stat", arg))
+    return (1);
+
+  if (stat (arg, &finfo) == -1)
+    @{
+      perror (arg);
+      return (1);
+    @}
+
+  printf ("Statistics for `%s':\n", arg);
+
+  printf ("%s has %d link%s, and is %d byte%s in length.\n", arg,
+          finfo.st_nlink,
+          (finfo.st_nlink == 1) ? "" : "s",
+          finfo.st_size,
+          (finfo.st_size == 1) ? "" : "s");
+  printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime));
+  printf ("      Last access at: %s", ctime (&finfo.st_atime));
+  printf ("    Last modified at: %s", ctime (&finfo.st_mtime));
+  return (0);
+@}
+
+com_delete (arg)
+     char *arg;
+@{
+  too_dangerous ("delete");
+  return (1);
+@}
+
+/* Print out help for ARG, or for all of the commands if ARG is
+   not present. */
+com_help (arg)
+     char *arg;
+@{
+  register int i;
+  int printed = 0;
+
+  for (i = 0; commands[i].name; i++)
+    @{
+      if (!*arg || (strcmp (arg, commands[i].name) == 0))
+        @{
+          printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
+          printed++;
+        @}
+    @}
+
+  if (!printed)
+    @{
+      printf ("No commands match `%s'.  Possibilties are:\n", arg);
+
+      for (i = 0; commands[i].name; i++)
+        @{
+          /* Print in six columns. */
+          if (printed == 6)
+            @{
+              printed = 0;
+              printf ("\n");
+            @}
+
+          printf ("%s\t", commands[i].name);
+          printed++;
+        @}
+
+      if (printed)
+        printf ("\n");
+    @}
+  return (0);
+@}
+
+/* Change to the directory ARG. */
+com_cd (arg)
+     char *arg;
+@{
+  if (chdir (arg) == -1)
+    @{
+      perror (arg);
+      return 1;
+    @}
+
+  com_pwd ("");
+  return (0);
+@}
+
+/* Print out the current working directory. */
+com_pwd (ignore)
+     char *ignore;
+@{
+  char dir[1024], *s;
+
+  s = getwd (dir);
+  if (s == 0)
+    @{
+      printf ("Error getting pwd: %s\n", dir);
+      return 1;
+    @}
+
+  printf ("Current directory is %s\n", dir);
+  return 0;
+@}
+
+/* The user wishes to quit using this program.  Just set DONE non-zero. */
+com_quit (arg)
+     char *arg;
+@{
+  done = 1;
+  return (0);
+@}
+
+/* Function which tells you that you can't do this. */
+too_dangerous (caller)
+     char *caller;
+@{
+  fprintf (stderr,
+           "%s: Too dangerous for me to distribute.  Write it yourself.\n",
+           caller);
+@}
+
+/* Return non-zero if ARG is a valid argument for CALLER, else print
+   an error message and return zero. */
+int
+valid_argument (caller, arg)
+     char *caller, *arg;
+@{
+  if (!arg || !*arg)
+    @{
+      fprintf (stderr, "%s: Argument required.\n", caller);
+      return (0);
+    @}
+
+  return (1);
+@}
+@end smallexample
diff --git a/lib/readline/doc/rluser.texinfo b/lib/readline/doc/rluser.texinfo
new file mode 100644 (file)
index 0000000..3567549
--- /dev/null
@@ -0,0 +1,875 @@
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename rluser.info
+@comment %**end of header (This is for running Texinfo on a region.)
+@setchapternewpage odd
+
+@ignore
+This file documents the end user interface to the GNU command line
+editing features.  It is to be an appendix to manuals for programs which
+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 Free Software Foundation, Inc.
+
+Authored by Brian Fox and Chet Ramey.
+
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+Permission is granted to make and distribute verbatim copies of this manual
+provided the copyright notice and this permission notice are preserved on
+all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+GNU Copyright statement is available to the distributee, and provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ignore
+
+@comment If you are including this manual as an appendix, then set the
+@comment variable readline-appendix.
+
+@node Command Line Editing
+@chapter Command Line Editing
+
+This chapter describes the basic features of the GNU
+command line editing interface.
+
+@menu
+* Introduction and Notation::  Notation used in this text.
+* Readline Interaction::       The minimum set of commands for editing a line.
+* Readline Init File::         Customizing Readline from a user's view.
+* Bindable Readline Commands:: A description of most of the Readline commands
+                               available for binding
+* Readline vi Mode::           A short description of how to make Readline
+                               behave like the vi editor.
+@end menu
+
+@node Introduction and Notation
+@section Introduction to Line Editing
+
+The following paragraphs describe the notation used to represent
+keystrokes.
+
+The text @key{C-k} is read as `Control-K' and describes the character
+produced when the Control key is depressed and the @key{k} key is struck.
+
+The text @key{M-k} is read as `Meta-K' and describes the character
+produced when the meta key (if you have one) is depressed, and the @key{k}
+key is struck.  If you do not have a meta key, the identical keystroke
+can be generated by typing @key{ESC} @i{first}, and then typing @key{k}.
+Either process is known as @dfn{metafying} the @key{k} key.
+
+The text @key{M-C-k} is read as `Meta-Control-k' and describes the
+character produced by @dfn{metafying} @key{C-k}.
+
+In addition, several keys have their own names.  Specifically,
+@key{DEL}, @key{ESC}, @key{LFD}, @key{SPC}, @key{RET}, and @key{TAB} all
+stand for themselves when seen in this text, or in an init file
+(@pxref{Readline Init File}, for more info).
+
+@node Readline Interaction
+@section Readline Interaction
+@cindex interaction, readline
+
+Often during an interactive session you type in a long line of text,
+only to notice that the first word on the line is misspelled.  The
+Readline library gives you a set of commands for manipulating the text
+as you type it in, allowing you to just fix your typo, and not forcing
+you to retype the majority of the line.  Using these editing commands,
+you move the cursor to the place that needs correction, and delete or
+insert the text of the corrections.  Then, when you are satisfied with
+the line, you simply press @key{RETURN}.  You do not have to be at the
+end of the line to press @key{RETURN}; the entire line is accepted
+regardless of the location of the cursor within the line.
+
+@menu
+* Readline Bare Essentials::   The least you need to know about Readline.
+* Readline Movement Commands:: Moving about the input line.
+* Readline Killing Commands::  How to delete text, and how to get it back!
+* Readline Arguments::         Giving numeric arguments to commands.
+@end menu
+
+@node Readline Bare Essentials
+@subsection Readline Bare Essentials
+
+In order to enter characters into the line, simply type them.  The typed
+character appears where the cursor was, and then the cursor moves one
+space to the right.  If you mistype a character, you can use your
+erase character to back up and delete the mistyped character.
+
+Sometimes you may miss typing a character that you wanted to type, and
+not notice your error until you have typed several other characters.  In
+that case, you can type @key{C-b} to move the cursor to the left, and then
+correct your mistake.  Afterwards, you can move the cursor to the right
+with @key{C-f}.
+
+When you add text in the middle of a line, you will notice that characters
+to the right of the cursor are `pushed over' to make room for the text
+that you have inserted.  Likewise, when you delete text behind the cursor,
+characters to the right of the cursor are `pulled back' to fill in the
+blank space created by the removal of the text.  A list of the basic bare
+essentials for editing the text of an input line follows.
+
+@table @asis
+@item @key{C-b}
+Move back one character.
+@item @key{C-f}
+Move forward one character.
+@item @key{DEL}
+Delete the character to the left of the cursor.
+@item @key{C-d}
+Delete the character underneath the cursor.
+@item @w{Printing characters}
+Insert the character into the line at the cursor.
+@item @key{C-_}
+Undo the last thing that you did.  You can undo all the way back to an
+empty line.
+@end table
+
+@node Readline Movement Commands
+@subsection Readline Movement Commands
+
+
+The above table describes the most basic possible keystrokes that you need
+in order to do editing of the input line.  For your convenience, many
+other commands have been added in addition to @key{C-b}, @key{C-f},
+@key{C-d}, and @key{DEL}.  Here are some commands for moving more rapidly
+about the line.
+
+@table @key
+@item C-a
+Move to the start of the line.
+@item C-e
+Move to the end of the line.
+@item M-f
+Move forward a word.
+@item M-b
+Move backward a word.
+@item C-l
+Clear the screen, reprinting the current line at the top.
+@end table
+
+Notice how @key{C-f} moves forward a character, while @key{M-f} moves
+forward a word.  It is a loose convention that control keystrokes
+operate on characters while meta keystrokes operate on words.
+
+@node Readline Killing Commands
+@subsection Readline Killing Commands
+
+@cindex Killing text
+@cindex Yanking text
+
+@dfn{Killing} text means to delete the text from the line, but to save
+it away for later use, usually by @dfn{yanking} (re-inserting)
+it back into the line.
+If the description for a command says that it `kills' text, then you can
+be sure that you can get the text back in a different (or the same)
+place later.
+
+When you use a kill command, the text is saved in a @dfn{kill-ring}.
+Any number of consecutive kills save all of the killed text together, so
+that when you yank it back, you get it all.  The kill
+ring is not line specific; the text that you killed on a previously
+typed line is available to be yanked back later, when you are typing
+another line.
+@cindex Kill ring
+
+Here is the list of commands for killing text.
+
+@table @key
+@item C-k
+Kill the text from the current cursor position to the end of the line.
+
+@item M-d
+Kill from the cursor to the end of the current word, or if between
+words, to the end of the next word.
+
+@item M-DEL
+Kill from the cursor the start of the previous word, or if between
+words, to the start of the previous word.
+
+@item C-w
+Kill from the cursor to the previous whitespace.  This is different than
+@key{M-DEL} because the word boundaries differ.
+
+@end table
+
+And, here is how to @dfn{yank} the text back into the line.  Yanking
+means to copy the most-recently-killed text from the kill buffer.
+
+@table @key
+@item C-y
+Yank the most recently killed text back into the buffer at the cursor.
+
+@item M-y
+Rotate the kill-ring, and yank the new top.  You can only do this if
+the prior command is @key{C-y} or @key{M-y}.
+@end table
+
+@node Readline Arguments
+@subsection Readline Arguments
+
+You can pass numeric arguments to Readline commands.  Sometimes the
+argument acts as a repeat count, other times it is the @i{sign} of the
+argument that is significant.  If you pass a negative argument to a
+command which normally acts in a forward direction, that command will
+act in a backward direction.  For example, to kill text back to the
+start of the line, you might type @key{M--} @key{C-k}.
+
+The general way to pass numeric arguments to a command is to type meta
+digits before the command.  If the first `digit' you type is a minus
+sign (@key{-}), then the sign of the argument will be negative.  Once
+you have typed one meta digit to get the argument started, you can type
+the remainder of the digits, and then the command.  For example, to give
+the @key{C-d} command an argument of 10, you could type @key{M-1 0 C-d}.
+
+
+@node Readline Init File
+@section Readline Init File
+
+Although the Readline library comes with a set of Emacs-like
+keybindings installed by default,
+it is possible that you would like to use a different set
+of keybindings.  You can customize programs that use Readline by putting
+commands in an @dfn{init} file in your home directory.  The name of this
+@ifset BashFeatures
+file is taken from the value of the shell variable @code{INPUTRC}.  If
+@end ifset
+@ifclear BashFeatures
+file is taken from the value of the environment variable @code{INPUTRC}.  If
+@end ifclear
+that variable is unset, the default is @file{~/.inputrc}.
+
+When a program which uses the Readline library starts up, the
+init file is read, and the key bindings are set.
+
+In addition, the @code{C-x C-r} command re-reads this init file, thus
+incorporating any changes that you might have made to it.
+
+@menu
+* Readline Init Syntax::       Syntax for the commands in the inputrc file.
+* Conditional Init Constructs::        Conditional key bindings in the inputrc file.
+@end menu
+
+@node Readline Init Syntax
+@subsection Readline Init Syntax
+
+There are only a few basic constructs allowed in the
+Readline init file.  Blank lines are ignored.
+Lines beginning with a @key{#} are comments.
+Lines beginning with a @key{$} indicate conditional
+constructs (@pxref{Conditional Init Constructs}).  Other lines
+denote variable settings and key bindings.
+
+@table @asis
+@item Variable Settings
+You can change the state of a few variables in Readline by
+using the @code{set} command within the init file.  Here is how you
+would specify that you wish to use @code{vi} line editing commands:
+
+@example
+set editing-mode vi
+@end example
+
+Right now, there are only a few variables which can be set;
+so few, in fact, that we just list them here:
+
+@table @code
+
+@item editing-mode
+@vindex editing-mode
+The @code{editing-mode} variable controls which editing mode you are
+using.  By default, Readline starts up in Emacs editing mode, where
+the keystrokes are most similar to Emacs.  This variable can be
+set to either @code{emacs} or @code{vi}.
+
+@item horizontal-scroll-mode
+@vindex horizontal-scroll-mode
+This variable can be set to either @code{On} or @code{Off}.  Setting it
+to @code{On} means that the text of the lines that you edit will scroll
+horizontally on a single screen line when they are longer than the width
+of the screen, instead of wrapping onto a new screen line.  By default,
+this variable is set to @code{Off}.
+
+@item mark-modified-lines
+@vindex mark-modified-lines
+This variable, when set to @code{On}, says to display an asterisk
+(@samp{*}) at the start of history lines which have been modified.
+This variable is @code{off} by default.
+
+@item bell-style
+@vindex bell-style
+Controls what happens when Readline wants to ring the terminal bell.
+If set to @code{none}, Readline never rings the bell.  If set to
+@code{visible}, Readline uses a visible bell if one is available.
+If set to @code{audible} (the default), Readline attempts to ring
+the terminal's bell.
+
+@item comment-begin
+@vindex comment-begin
+The string to insert at the beginning of the line when the
+@code{vi-comment} command is executed.  The default value
+is @code{"#"}.
+
+@item meta-flag
+@vindex meta-flag
+If set to @code{on}, Readline will enable eight-bit input (it
+will not strip the eighth bit from the characters it reads),
+regardless of what the terminal claims it can support.  The
+default value is @code{off}.
+
+@item convert-meta
+@vindex convert-meta
+If set to @code{on}, Readline will convert characters with the
+eigth bit set to an ASCII key sequence by stripping the eigth
+bit and prepending an @key{ESC} character, converting them to a
+meta-prefixed key sequence.  The default value is @code{on}.
+
+@item output-meta
+@vindex output-meta
+If set to @code{on}, Readline will display characters with the
+eighth bit set directly rather than as a meta-prefixed escape
+sequence.  The default is @code{off}.
+
+@item completion-query-items
+@vindex completion-query-items
+The number of possible completions that determines when the user is
+asked whether he wants to see the list of possibilities.  If the
+number of possible completions is greater than this value,
+Readline will ask the user whether or not he wishes to view
+them; otherwise, they are simply listed.  The default limit is
+@code{100}.
+
+@item keymap
+@vindex keymap
+Sets Readline's idea of the current keymap for key binding commands.
+Acceptable @code{keymap} names are
+@code{emacs},
+@code{emacs-standard},
+@code{emacs-meta},
+@code{emacs-ctlx},
+@code{vi},
+@code{vi-move},
+@code{vi-command}, and
+@code{vi-insert}.
+@code{vi} is equivalent to @code{vi-command}; @code{emacs} is
+equivalent to @code{emacs-standard}.  The default value is @code{emacs}.
+The value of the @code{editing-mode} variable also affects the
+default keymap.
+
+@item show-all-if-ambiguous
+@vindex show-all-if-ambiguous
+This alters the default behavior of the completion functions.  If
+set to @code{on}, 
+words which have more than one possible completion cause the
+matches to be listed immediately instead of ringing the bell.
+The default value is @code{off}.
+
+@item expand-tilde
+@vindex expand-tilde
+If set to @code{on}, tilde expansion is performed when Readline
+attempts word completion.  The default is @code{off}.
+
+@end table
+
+@item Key Bindings
+The syntax for controlling key bindings in the init file is
+simple.  First you have to know the name of the command that you
+want to change.  The following pages contain tables of the command name,
+the default keybinding, and a short description of what the command
+does.
+
+Once you know the name of the command, simply place the name of the key
+you wish to bind the command to, a colon, and then the name of the
+command on a line in the init file.  The name of the key
+can be expressed in different ways, depending on which is most
+comfortable for you.
+
+@table @asis
+@item @w{@var{keyname}: @var{function-name} or @var{macro}}
+@var{keyname} is the name of a key spelled out in English.  For example:
+@example
+Control-u: universal-argument
+Meta-Rubout: backward-kill-word
+Control-o: ">&output"
+@end example
+
+In the above example, @samp{C-u} is bound to the function
+@code{universal-argument}, and @samp{C-o} is bound to run the macro
+expressed on the right hand side (that is, to insert the text
+@samp{>&output} into the line).
+
+@item @w{"@var{keyseq}": @var{function-name} or @var{macro}}
+@var{keyseq} differs from @var{keyname} above in that strings
+denoting an entire key sequence can be specified, by placing
+the key sequence in double quotes.  Some GNU Emacs style key
+escapes can be used, as in the following example, but the
+special character names are not recognized.
+
+@example
+"\C-u": universal-argument
+"\C-x\C-r": re-read-init-file
+"\e[11~": "Function Key 1"
+@end example
+
+In the above example, @samp{C-u} is bound to the function
+@code{universal-argument} (just as it was in the first example),
+@samp{C-x C-r} is bound to the function @code{re-read-init-file}, and
+@samp{ESC [ 1 1 ~} is bound to insert the text @samp{Function Key 1}.
+The following escape sequences are available when specifying key
+sequences:
+
+@table @code
+@item @kbd{\C-}
+control prefix
+@item @kbd{\M-}
+meta prefix
+@item @kbd{\e}
+an escape character
+@item @kbd{\\}
+backslash
+@item @kbd{\"}
+@key{"}
+@item @kbd{\'}
+@key{'}
+@end table
+
+When entering the text of a macro, single or double quotes should
+be used to indicate a macro definition.  Unquoted text
+is assumed to be a function name.  Backslash
+will quote any character in the macro text, including @key{"}
+and @key{'}.
+For example, the following binding will make @kbd{C-x \}
+insert a single @key{\} into the line:
+@example
+"\C-x\\": "\\"
+@end example
+
+@end table
+@end table
+
+@node Conditional Init Constructs
+@subsection Conditional Init Constructs
+
+Readline implements a facility similar in spirit to the conditional
+compilation features of the C preprocessor which allows key
+bindings and variable settings to be performed as the result
+of tests.  There are three parser directives used.
+
+@ftable @code
+@item $if
+The @code{$if} construct allows bindings to be made based on the
+editing mode, the terminal being used, or the application using
+Readline.  The text of the test extends to the end of the line;
+no characters are required to isolate it.
+
+@table @code
+@item mode
+The @code{mode=} form of the @code{$if} directive is used to test
+whether Readline is in @code{emacs} or @code{vi} mode.
+This may be used in conjunction
+with the @samp{set keymap} command, for instance, to set bindings in
+the @code{emacs-standard} and @code{emacs-ctlx} keymaps only if
+Readline is starting out in @code{emacs} mode.
+
+@item term
+The @code{term=} form may be used to include terminal-specific
+key bindings, perhaps to bind the key sequences output by the
+terminal's function keys.  The word on the right side of the
+@samp{=} is tested against the full name of the terminal and the
+portion of the terminal name before the first @samp{-}.  This
+allows @var{sun} to match both @var{sun} and @var{sun-cmd},
+for instance.
+
+@item application
+The @var{application} construct is used to include
+application-specific settings.  Each program using the Readline
+library sets the @var{application name}, and you can test for it. 
+This could be used to bind key sequences to functions useful for
+a specific program.  For instance, the following command adds a
+key sequence that quotes the current or previous word in Bash:
+@example
+$if bash
+# Quote the current or previous word
+"\C-xq": "\eb\"\ef\""
+$endif
+@end example
+@end table
+
+@item $endif
+This command, as you saw in the previous example, terminates an
+@code{$if} command.
+
+@item $else
+Commands in this branch of the @code{$if} directive are executed if
+the test fails.
+@end ftable
+
+@node Bindable Readline Commands
+@section Bindable Readline Commands
+
+@menu
+* Commands For Moving::                Moving about the line.
+* Commands For History::       Getting at previous lines.
+* Commands For Text::          Commands for changing text.
+* Commands For Killing::       Commands for killing and yanking.
+* Numeric Arguments::          Specifying numeric arguments, repeat counts.
+* Commands For Completion::    Getting Readline to do the typing for you.
+* Keyboard Macros::            Saving and re-executing typed characters
+* Miscellaneous Commands::     Other miscellaneous commands.
+@end menu
+
+@node Commands For Moving
+@subsection Commands For Moving
+@ftable @code
+@item beginning-of-line (C-a)
+Move to the start of the current line.
+
+@item end-of-line (C-e)
+Move to the end of the line.
+
+@item forward-char (C-f)
+Move forward a character.
+
+@item backward-char (C-b)
+Move back a character.
+
+@item forward-word (M-f)
+Move forward to the end of the next word.  Words are composed of
+letters and digits.
+
+@item backward-word (M-b)
+Move back to the start of this, or the previous, word.  Words are
+composed of letters and digits.
+
+@item clear-screen (C-l)
+Clear the screen and redraw the current line,
+leaving the current line at the top of the screen.
+
+@item redraw-current-line ()
+Refresh the current line.  By default, this is unbound.
+
+@end ftable
+
+@node Commands For History
+@subsection Commands For Manipulating The History
+
+@ftable @code
+@item accept-line (Newline, Return)
+@ifset BashFeatures
+Accept the line regardless of where the cursor is.  If this line is
+non-empty, add it to the history list according to the setting of
+the @code{HISTCONTROL} variable.  If this line was a history
+line, then restore the history line to its original state.
+@end ifset
+@ifclear BashFeatures
+Accept the line regardless of where the cursor is.  If this line is
+non-empty, add it to the history list.  If this line was a history
+line, then restore the history line to its original state.
+@end ifclear
+
+@item previous-history (C-p)
+Move `up' through the history list.
+
+@item next-history (C-n)
+Move `down' through the history list.
+
+@item beginning-of-history (M-<)
+Move to the first line in the history.
+
+@item end-of-history (M->)
+Move to the end of the input history, i.e., the line you are entering.
+
+@item reverse-search-history (C-r)
+Search backward starting at the current line and moving `up' through
+the history as necessary.  This is an incremental search.
+
+@item forward-search-history (C-s)
+Search forward starting at the current line and moving `down' through
+the the history as necessary.  This is an incremental search.
+
+@item non-incremental-reverse-search-history (M-p)
+Search backward starting at the current line and moving `up'
+through the history as necessary using a non-incremental search
+for a string supplied by the user.
+
+@item non-incremental-forward-search-history (M-n)
+Search forward starting at the current line and moving `down'
+through the the history as necessary using a non-incremental search
+for a string supplied by the user.
+
+@item history-search-forward ()
+Search forward through the history for the string of characters
+between the start of the current line and the current point.  This
+is a non-incremental search.  By default, this command is unbound.
+
+@item history-search-backward ()
+Search backward through the history for the string of characters
+between the start of the current line and the current point.  This
+is a non-incremental search.  By default, this command is unbound.
+
+@item yank-nth-arg (M-C-y)
+Insert the first argument to the previous command (usually
+the second word on the previous line).  With an argument @var{n},
+insert the @var{n}th word from the previous command (the words
+in the previous command begin with word 0).  A negative argument
+inserts the @var{n}th word from the end of the previous command.
+
+@item yank-last-arg (M-., M-_)
+Insert last argument to the previous command (the last word on the
+previous line).  With an
+argument, behave exactly like @code{yank-nth-arg}.
+
+@end ftable
+
+@node Commands For Text
+@subsection Commands For Changing Text
+
+@ftable @code
+@item delete-char (C-d)
+Delete the character under the cursor.  If the cursor is at the
+beginning of the line, there are no characters in the line, and
+the last character typed was not C-d, then return EOF.
+
+@item backward-delete-char (Rubout)
+Delete the character behind the cursor.  A numeric arg says to kill
+the characters instead of deleting them.
+
+@item quoted-insert (C-q, C-v)
+Add the next character that you type to the line verbatim.  This is
+how to insert key sequences like @key{C-q}, for example.
+
+@item tab-insert (M-TAB)
+Insert a tab character.
+
+@item self-insert (a, b, A, 1, !, ...)
+Insert yourself.
+
+@item transpose-chars (C-t)
+Drag the character before the cursor forward over
+the character at the cursor, moving the
+cursor forward as well.  If the insertion point
+is at the end of the line, then this
+transposes the last two characters of the line.
+Negative argumentss don't work.
+
+@item transpose-words (M-t)
+Drag the word behind the cursor past the word in front of the cursor
+moving the cursor over that word as well.
+
+@item upcase-word (M-u)
+Uppercase the current (or following) word.  With a negative argument,
+do the previous word, but do not move the cursor.
+
+@item downcase-word (M-l)
+Lowercase the current (or following) word.  With a negative argument,
+do the previous word, but do not move the cursor.
+
+@item capitalize-word (M-c)
+Capitalize the current (or following) word.  With a negative argument,
+do the previous word, but do not move the cursor.
+
+@end ftable
+
+@node Commands For Killing
+@subsection Killing And Yanking
+
+@ftable @code
+
+@item kill-line (C-k)
+Kill the text from the current cursor position to the end of the line.
+
+@item backward-kill-line (C-x Rubout)
+Kill backward to the beginning of the line.
+
+@item unix-line-discard (C-u)
+Kill backward from the cursor to the beginning of the current line.
+Save the killed text on the kill-ring.
+
+@item kill-whole-line ()
+Kill all characters on the current line, no matter where the
+cursor is.  By default, this is unbound.
+
+@item kill-word (M-d)
+Kill from the cursor to the end of the current word, or if between
+words, to the end of the next word.  Word boundaries are the same
+as @code{forward-word}.
+
+@item backward-kill-word (M-DEL)
+Kill the word behind the cursor.  Word boundaries are the same
+as @code{backward-word}.
+
+@item unix-word-rubout (C-w)
+Kill the word behind the cursor, using white space as a word
+boundary.  The killed text is saved on the kill-ring.
+
+@item delete-horizontal-space ()
+Delete all spaces and tabs around point.  By default, this is unbound.
+
+@item yank (C-y)
+Yank the top of the kill ring into the buffer at the current
+cursor position.
+
+@item yank-pop (M-y)
+Rotate the kill-ring, and yank the new top.  You can only do this if
+the prior command is yank or yank-pop.
+@end ftable
+
+@node Numeric Arguments
+@subsection Specifying Numeric Arguments
+@ftable @code
+
+@item digit-argument (M-0, M-1, ... M--)
+Add this digit to the argument already accumulating, or start a new
+argument.  M-- starts a negative argument.
+
+@item universal-argument ()
+Each time this is executed, the argument count is multiplied by four.
+The argument count is initially one, so executing this function the
+first time makes the argument count four.  By default, this is not
+bound to a key.
+@end ftable
+
+@node Commands For Completion
+@subsection Letting Readline Type For You
+
+@ftable @code
+@item complete (TAB)
+Attempt to do completion on the text before the cursor.  This is
+application-specific.  Generally, if you are typing a filename
+argument, you can do filename completion; if you are typing a command,
+you can do command completion, if you are typing in a symbol to GDB, you
+can do symbol name completion, if you are typing in a variable to Bash,
+you can do variable name completion, and so on.
+@ifset BashFeatures
+See the Bash manual page for a complete list of available completion
+functions.
+@end ifset
+
+@item possible-completions (M-?)
+List the possible completions of the text before the cursor.
+
+@item insert-completions ()
+Insert all completions of the text before point that would have
+been generated by @code{possible-completions}.  By default, this
+is not bound to a key.
+
+@end ftable
+
+@node Keyboard Macros
+@subsection Keyboard Macros
+@ftable @code
+
+@item start-kbd-macro (C-x ()
+Begin saving the characters typed into the current keyboard macro.
+
+@item end-kbd-macro (C-x ))
+Stop saving the characters typed into the current keyboard macro
+and save the definition.
+
+@item call-last-kbd-macro (C-x e)
+Re-execute the last keyboard macro defined, by making the characters
+in the macro appear as if typed at the keyboard.
+
+@end ftable
+
+@node Miscellaneous Commands
+@subsection Some Miscellaneous Commands
+@ftable @code
+
+@item re-read-init-file (C-x C-r)
+Read in the contents of your init file, and incorporate
+any bindings or variable assignments found there.
+
+@item abort (C-g)
+Abort the current editing command and
+ring the terminal's bell (subject to the setting of
+@code{bell-style}).
+
+@item do-uppercase-version (M-a, M-b, ...)
+Run the command that is bound to the corresoponding uppercase
+character.
+
+@item prefix-meta (ESC)
+Make the next character that you type be metafied.  This is for people
+without a meta key.  Typing @samp{ESC f} is equivalent to typing
+@samp{M-f}.
+
+@item undo (C-_, C-x C-u)
+Incremental undo, separately remembered for each line.
+
+@item revert-line (M-r)
+Undo all changes made to this line.  This is like typing the @code{undo}
+command enough times to get back to the beginning.
+
+@item tilde-expand (M-~)
+Perform tilde expansion on the current word.
+
+@item dump-functions ()
+Print all of the functions and their key bindings to the
+readline output stream.  If a numeric argument is supplied,
+the output is formatted in such a way that it can be made part
+of an @var{inputrc} file.
+
+@ifset BashFeatures
+@item display-shell-version (C-x C-v)
+Display version information about the current instance of Bash.
+
+@item shell-expand-line (M-C-e)
+Expand the line the way the shell does when it reads it.  This
+performs alias and history expansion as well as all of the shell
+word expansions.
+
+@item history-expand-line (M-^)
+Perform history expansion on the current line.
+
+@item insert-last-argument (M-., M-_)
+A synonym for @code{yank-last-arg}.
+
+@item operate-and-get-next (C-o)
+Accept the current line for execution and fetch the next line
+relative to the current line from the history for editing.  Any
+argument is ignored.
+
+@item emacs-editing-mode (C-e)
+When in @code{vi} editing mode, this causes a switch back to
+emacs editing mode, as if the command @code{set -o emacs} had
+been executed.
+
+@end ifset
+
+@end ftable
+
+@node Readline vi Mode
+@section Readline vi Mode
+
+While the Readline library does not have a full set of @code{vi}
+editing functions, it does contain enough to allow simple editing
+of the line.  The Readline @code{vi} mode behaves as specified in
+the Posix 1003.2 standard.
+
+@ifset BashFeatures
+In order to switch interactively between @code{Emacs} and @code{Vi}
+editing modes, use the @code{set -o emacs} and @code{set -o vi}
+commands (@pxref{The Set Builtin}).
+@end ifset
+@ifclear BashFeatures
+In order to switch interactively between @code{Emacs} and @code{Vi}
+editing modes, use the command M-C-j (toggle-editing-mode).
+@end ifclear
+The Readline default is @code{emacs} mode.
+
+When you enter a line in @code{vi} mode, you are already placed in
+`insertion' mode, as if you had typed an @samp{i}.  Pressing @key{ESC}
+switches you into `command' mode, where you can edit the text of the
+line with the standard @code{vi} movement keys, move to previous
+history lines with @samp{k}, and following lines with @samp{j}, and
+so forth.
diff --git a/lib/readline/doc/texindex.c b/lib/readline/doc/texindex.c
new file mode 100644 (file)
index 0000000..9233bab
--- /dev/null
@@ -0,0 +1,1666 @@
+/* Prepare TeX index dribble output into an actual index.
+
+   Version 1.45
+
+   Copyright (C) 1987, 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+\f
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include "getopt.h"
+#include "bashansi.h"
+
+#if !defined (errno)
+extern int errno;
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#else /* !HAVE_UNISTD_H */
+extern long lseek ();
+#endif /* !HAVE_UNISTD_H */
+
+extern char *mktemp ();
+
+#if !defined (HAVE_STRERROR)
+extern int sys_nerr;
+extern char *sys_errlist[];
+#endif
+
+#include <sys/types.h>
+
+#if defined (_AIX) || !defined (_POSIX_VERSION)
+#  include <sys/file.h>
+#endif
+
+#include <fcntl.h>
+
+#define TI_NO_ERROR 0
+#define TI_FATAL_ERROR 1
+
+#if !defined (SEEK_SET)
+#  define SEEK_SET 0
+#  define SEEK_CUR 1
+#  define SEEK_END 2
+#endif /* !SEEK_SET */
+
+/* When sorting in core, this structure describes one line
+   and the position and length of its first keyfield.  */
+struct lineinfo
+{
+  char *text;          /* The actual text of the line. */
+  union {
+    char *text;                /* The start of the key (for textual comparison). */
+    long number;       /* The numeric value (for numeric comparison). */
+  } key;
+  long keylen;         /* Length of KEY field. */
+};
+
+/* This structure describes a field to use as a sort key. */
+struct keyfield
+{
+  int startwords;      /* Number of words to skip. */
+  int startchars;      /* Number of additional chars to skip. */
+  int endwords;                /* Number of words to ignore at end. */
+  int endchars;                /* Ditto for characters of last word. */
+  char ignore_blanks;  /* Non-zero means ignore spaces and tabs. */
+  char fold_case;      /* Non-zero means case doesn't matter. */
+  char reverse;                /* Non-zero means compare in reverse order. */
+  char numeric;                /* Non-zeros means field is ASCII numeric. */
+  char positional;     /* Sort according to file position. */
+  char braced;         /* Count balanced-braced groupings as fields. */
+};
+
+/* Vector of keyfields to use. */
+struct keyfield keyfields[3];
+
+/* Number of keyfields stored in that vector.  */
+int num_keyfields = 3;
+
+/* Vector of input file names, terminated with a null pointer. */
+char **infiles;
+
+/* Vector of corresponding output file names, or NULL, meaning default it
+   (add an `s' to the end). */
+char **outfiles;
+
+/* Length of `infiles'. */
+int num_infiles;
+
+/* Pointer to the array of pointers to lines being sorted. */
+char **linearray;
+
+/* The allocated length of `linearray'. */
+long nlines;
+
+/* Directory to use for temporary files.  On Unix, it ends with a slash.  */
+char *tempdir;
+
+/* Start of filename to use for temporary files.  */
+char *tempbase;
+
+/* Number of last temporary file.  */
+int tempcount;
+
+/* Number of last temporary file already deleted.
+   Temporary files are deleted by `flush_tempfiles' in order of creation.  */
+int last_deleted_tempcount;
+
+/* During in-core sort, this points to the base of the data block
+   which contains all the lines of data.  */
+char *text_base;
+
+/* Additional command switches .*/
+
+/* Nonzero means do not delete tempfiles -- for debugging. */
+int keep_tempfiles;
+
+/* The name this program was run with. */
+char *program_name;
+
+/* Forward declarations of functions in this file. */
+
+void decode_command ();
+void sort_in_core ();
+void sort_offline ();
+char **parsefile ();
+char *find_field ();
+char *find_pos ();
+long find_value ();
+char *find_braced_pos ();
+char *find_braced_end ();
+void writelines ();
+int compare_field ();
+int compare_full ();
+long readline ();
+int merge_files ();
+int merge_direct ();
+void pfatal_with_name ();
+void fatal ();
+void error ();
+void *xmalloc (), *xrealloc ();
+char *concat ();
+char *maketempname ();
+void flush_tempfiles ();
+char *tempcopy ();
+\f
+#define MAX_IN_CORE_SORT 500000
+
+void
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int i;
+
+  tempcount = 0;
+  last_deleted_tempcount = 0;
+  program_name = argv[0];
+
+  /* Describe the kind of sorting to do. */
+  /* The first keyfield uses the first braced field and folds case. */
+  keyfields[0].braced = 1;
+  keyfields[0].fold_case = 1;
+  keyfields[0].endwords = -1;
+  keyfields[0].endchars = -1;
+
+  /* The second keyfield uses the second braced field, numerically. */
+  keyfields[1].braced = 1;
+  keyfields[1].numeric = 1;
+  keyfields[1].startwords = 1;
+  keyfields[1].endwords = -1;
+  keyfields[1].endchars = -1;
+
+  /* The third keyfield (which is ignored while discarding duplicates)
+     compares the whole line. */
+  keyfields[2].endwords = -1;
+  keyfields[2].endchars = -1;
+
+  decode_command (argc, argv);
+
+  tempbase = mktemp (concat ("txiXXXXXX", "", ""));
+
+  /* Process input files completely, one by one.  */
+
+  for (i = 0; i < num_infiles; i++)
+    {
+      int desc;
+      long ptr;
+      char *outfile;
+
+      desc = open (infiles[i], O_RDONLY, 0);
+      if (desc < 0)
+       pfatal_with_name (infiles[i]);
+      lseek (desc, 0L, SEEK_END);
+      ptr = lseek (desc, 0L, SEEK_CUR);
+
+      close (desc);
+
+      outfile = outfiles[i];
+      if (!outfile)
+       {
+         outfile = concat (infiles[i], "s", "");
+       }
+
+      if (ptr < MAX_IN_CORE_SORT)
+       /* Sort a small amount of data. */
+       sort_in_core (infiles[i], ptr, outfile);
+      else
+       sort_offline (infiles[i], ptr, outfile);
+    }
+
+  flush_tempfiles (tempcount);
+  exit (TI_NO_ERROR);
+}
+\f
+void
+usage ()
+{
+  fprintf (stderr, "\
+Usage: %s [-k] infile [-o outfile] ...\n", program_name);
+  exit (1);
+}
+
+/* Decode the command line arguments to set the parameter variables
+   and set up the vector of keyfields and the vector of input files. */
+
+void
+decode_command (argc, argv)
+     int argc;
+     char **argv;
+{
+  int optc;
+  char **ip;
+  char **op;
+
+  /* Store default values into parameter variables. */
+
+  tempdir = getenv ("TMPDIR");
+  if (tempdir == NULL)
+    tempdir = "/tmp/";
+  else
+    tempdir = concat (tempdir, "/", "");
+
+  keep_tempfiles = 0;
+
+  /* Allocate ARGC input files, which must be enough.  */
+
+  infiles = (char **) xmalloc (argc * sizeof (char *));
+  outfiles = (char **) xmalloc (argc * sizeof (char *));
+  ip = infiles;
+  op = outfiles;
+
+  while ((optc = getopt (argc, argv, "-ko:")) != EOF)
+    {
+      switch (optc)
+       {
+       case 1:         /* Non-option filename. */
+         *ip++ = optarg;
+         *op++ = NULL;
+         break;
+
+       case 'k':
+         keep_tempfiles = 1;
+         break;
+
+       case 'o':
+         if (op > outfiles)
+           *(op - 1) = optarg;
+         break;
+
+       default:
+         usage ();
+       }
+    }
+
+  /* Record number of keyfields and terminate list of filenames. */
+  num_infiles = ip - infiles;
+  *ip = 0;
+  if (num_infiles == 0)
+    usage ();
+}
+\f
+/* Return a name for a temporary file. */
+
+char *
+maketempname (count)
+     int count;
+{
+  char tempsuffix[10];
+  sprintf (tempsuffix, "%d", count);
+  return concat (tempdir, tempbase, tempsuffix);
+}
+
+/* Delete all temporary files up to TO_COUNT. */
+
+void
+flush_tempfiles (to_count)
+     int to_count;
+{
+  if (keep_tempfiles)
+    return;
+  while (last_deleted_tempcount < to_count)
+    unlink (maketempname (++last_deleted_tempcount));
+}
+
+/* Copy the input file open on IDESC into a temporary file
+   and return the temporary file name. */
+
+#define BUFSIZE 1024
+
+char *
+tempcopy (idesc)
+     int idesc;
+{
+  char *outfile = maketempname (++tempcount);
+  int odesc;
+  char buffer[BUFSIZE];
+
+  odesc = open (outfile, O_WRONLY | O_CREAT, 0666);
+
+  if (odesc < 0)
+    pfatal_with_name (outfile);
+
+  while (1)
+    {
+      int nread = read (idesc, buffer, BUFSIZE);
+      write (odesc, buffer, nread);
+      if (!nread)
+       break;
+    }
+
+  close (odesc);
+
+  return outfile;
+}
+\f
+/* Compare LINE1 and LINE2 according to the specified set of keyfields. */
+
+int
+compare_full (line1, line2)
+     char **line1, **line2;
+{
+  int i;
+
+  /* Compare using the first keyfield;
+     if that does not distinguish the lines, try the second keyfield;
+     and so on. */
+
+  for (i = 0; i < num_keyfields; i++)
+    {
+      long length1, length2;
+      char *start1 = find_field (&keyfields[i], *line1, &length1);
+      char *start2 = find_field (&keyfields[i], *line2, &length2);
+      int tem = compare_field (&keyfields[i], start1, length1, *line1 - text_base,
+                              start2, length2, *line2 - text_base);
+      if (tem)
+       {
+         if (keyfields[i].reverse)
+           return -tem;
+         return tem;
+       }
+    }
+
+  return 0;                    /* Lines match exactly. */
+}
+
+/* Compare LINE1 and LINE2, described by structures
+   in which the first keyfield is identified in advance.
+   For positional sorting, assumes that the order of the lines in core
+   reflects their nominal order.  */
+
+int
+compare_prepared (line1, line2)
+     struct lineinfo *line1, *line2;
+{
+  int i;
+  int tem;
+  char *text1, *text2;
+
+  /* Compare using the first keyfield, which has been found for us already. */
+  if (keyfields->positional)
+    {
+      if (line1->text - text_base > line2->text - text_base)
+       tem = 1;
+      else
+       tem = -1;
+    }
+  else if (keyfields->numeric)
+    tem = line1->key.number - line2->key.number;
+  else
+    tem = compare_field (keyfields, line1->key.text, line1->keylen, 0,
+                        line2->key.text, line2->keylen, 0);
+  if (tem)
+    {
+      if (keyfields->reverse)
+       return -tem;
+      return tem;
+    }
+
+  text1 = line1->text;
+  text2 = line2->text;
+
+  /* Compare using the second keyfield;
+     if that does not distinguish the lines, try the third keyfield;
+     and so on. */
+
+  for (i = 1; i < num_keyfields; i++)
+    {
+      long length1, length2;
+      char *start1 = find_field (&keyfields[i], text1, &length1);
+      char *start2 = find_field (&keyfields[i], text2, &length2);
+      int tem = compare_field (&keyfields[i], start1, length1, text1 - text_base,
+                              start2, length2, text2 - text_base);
+      if (tem)
+       {
+         if (keyfields[i].reverse)
+           return -tem;
+         return tem;
+       }
+    }
+
+  return 0;                    /* Lines match exactly. */
+}
+
+/* Like compare_full but more general.
+   You can pass any strings, and you can say how many keyfields to use.
+   POS1 and POS2 should indicate the nominal positional ordering of
+   the two lines in the input.  */
+
+int
+compare_general (str1, str2, pos1, pos2, use_keyfields)
+     char *str1, *str2;
+     long pos1, pos2;
+     int use_keyfields;
+{
+  int i;
+
+  /* Compare using the first keyfield;
+     if that does not distinguish the lines, try the second keyfield;
+     and so on. */
+
+  for (i = 0; i < use_keyfields; i++)
+    {
+      long length1, length2;
+      char *start1 = find_field (&keyfields[i], str1, &length1);
+      char *start2 = find_field (&keyfields[i], str2, &length2);
+      int tem = compare_field (&keyfields[i], start1, length1, pos1,
+                              start2, length2, pos2);
+      if (tem)
+       {
+         if (keyfields[i].reverse)
+           return -tem;
+         return tem;
+       }
+    }
+
+  return 0;                    /* Lines match exactly. */
+}
+
+/* Find the start and length of a field in STR according to KEYFIELD.
+   A pointer to the starting character is returned, and the length
+   is stored into the int that LENGTHPTR points to.  */
+
+char *
+find_field (keyfield, str, lengthptr)
+     struct keyfield *keyfield;
+     char *str;
+     long *lengthptr;
+{
+  char *start;
+  char *end;
+  char *(*fun) ();
+
+  if (keyfield->braced)
+    fun = find_braced_pos;
+  else
+    fun = find_pos;
+
+  start = (*fun) (str, keyfield->startwords, keyfield->startchars,
+                 keyfield->ignore_blanks);
+  if (keyfield->endwords < 0)
+    {
+      if (keyfield->braced)
+       end = find_braced_end (start);
+      else
+       {
+         end = start;
+         while (*end && *end != '\n')
+           end++;
+       }
+    }
+  else
+    {
+      end = (*fun) (str, keyfield->endwords, keyfield->endchars, 0);
+      if (end - str < start - str)
+       end = start;
+    }
+  *lengthptr = end - start;
+  return start;
+}
+
+/* Return a pointer to a specified place within STR,
+   skipping (from the beginning) WORDS words and then CHARS chars.
+   If IGNORE_BLANKS is nonzero, we skip all blanks
+   after finding the specified word.  */
+
+char *
+find_pos (str, words, chars, ignore_blanks)
+     char *str;
+     int words, chars;
+     int ignore_blanks;
+{
+  int i;
+  char *p = str;
+
+  for (i = 0; i < words; i++)
+    {
+      char c;
+      /* Find next bunch of nonblanks and skip them. */
+      while ((c = *p) == ' ' || c == '\t')
+       p++;
+      while ((c = *p) && c != '\n' && !(c == ' ' || c == '\t'))
+       p++;
+      if (!*p || *p == '\n')
+       return p;
+    }
+
+  while (*p == ' ' || *p == '\t')
+    p++;
+
+  for (i = 0; i < chars; i++)
+    {
+      if (!*p || *p == '\n')
+       break;
+      p++;
+    }
+  return p;
+}
+
+/* Like find_pos but assumes that each field is surrounded by braces
+   and that braces within fields are balanced. */
+
+char *
+find_braced_pos (str, words, chars, ignore_blanks)
+     char *str;
+     int words, chars;
+     int ignore_blanks;
+{
+  int i;
+  int bracelevel;
+  char *p = str;
+  char c;
+
+  for (i = 0; i < words; i++)
+    {
+      bracelevel = 1;
+      while ((c = *p++) != '{' && c != '\n' && c)
+       /* Do nothing. */ ;
+      if (c != '{')
+       return p - 1;
+      while (bracelevel)
+       {
+         c = *p++;
+         if (c == '{')
+           bracelevel++;
+         if (c == '}')
+           bracelevel--;
+         if (c == 0 || c == '\n')
+           return p - 1;
+       }
+    }
+
+  while ((c = *p++) != '{' && c != '\n' && c)
+    /* Do nothing. */ ;
+
+  if (c != '{')
+    return p - 1;
+
+  if (ignore_blanks)
+    while ((c = *p) == ' ' || c == '\t')
+      p++;
+
+  for (i = 0; i < chars; i++)
+    {
+      if (!*p || *p == '\n')
+       break;
+      p++;
+    }
+  return p;
+}
+
+/* Find the end of the balanced-brace field which starts at STR.
+   The position returned is just before the closing brace. */
+
+char *
+find_braced_end (str)
+     char *str;
+{
+  int bracelevel;
+  char *p = str;
+  char c;
+
+  bracelevel = 1;
+  while (bracelevel)
+    {
+      c = *p++;
+      if (c == '{')
+       bracelevel++;
+      if (c == '}')
+       bracelevel--;
+      if (c == 0 || c == '\n')
+       return p - 1;
+    }
+  return p - 1;
+}
+
+long
+find_value (start, length)
+     char *start;
+     long length;
+{
+  while (length != 0L)
+    {
+      if (isdigit (*start))
+       return atol (start);
+      length--;
+      start++;
+    }
+  return 0l;
+}
+
+/* Vector used to translate characters for comparison.
+   This is how we make all alphanumerics follow all else,
+   and ignore case in the first sorting.  */
+int char_order[256];
+
+void
+init_char_order ()
+{
+  int i;
+  for (i = 1; i < 256; i++)
+    char_order[i] = i;
+
+  for (i = '0'; i <= '9'; i++)
+    char_order[i] += 512;
+
+  for (i = 'a'; i <= 'z'; i++)
+    {
+      char_order[i] = 512 + i;
+      char_order[i + 'A' - 'a'] = 512 + i;
+    }
+}
+
+/* Compare two fields (each specified as a start pointer and a character count)
+   according to KEYFIELD.
+   The sign of the value reports the relation between the fields. */
+
+int
+compare_field (keyfield, start1, length1, pos1, start2, length2, pos2)
+     struct keyfield *keyfield;
+     char *start1;
+     long length1;
+     long pos1;
+     char *start2;
+     long length2;
+     long pos2;
+{
+  if (keyfields->positional)
+    {
+      if (pos1 > pos2)
+       return 1;
+      else
+       return -1;
+    }
+  if (keyfield->numeric)
+    {
+      long value = find_value (start1, length1) - find_value (start2, length2);
+      if (value > 0)
+       return 1;
+      if (value < 0)
+       return -1;
+      return 0;
+    }
+  else
+    {
+      char *p1 = start1;
+      char *p2 = start2;
+      char *e1 = start1 + length1;
+      char *e2 = start2 + length2;
+
+      while (1)
+       {
+         int c1, c2;
+
+         if (p1 == e1)
+           c1 = 0;
+         else
+           c1 = *p1++;
+         if (p2 == e2)
+           c2 = 0;
+         else
+           c2 = *p2++;
+
+         if (char_order[c1] != char_order[c2])
+           return char_order[c1] - char_order[c2];
+         if (!c1)
+           break;
+       }
+
+      /* Strings are equal except possibly for case.  */
+      p1 = start1;
+      p2 = start2;
+      while (1)
+       {
+         int c1, c2;
+
+         if (p1 == e1)
+           c1 = 0;
+         else
+           c1 = *p1++;
+         if (p2 == e2)
+           c2 = 0;
+         else
+           c2 = *p2++;
+
+         if (c1 != c2)
+           /* Reverse sign here so upper case comes out last.  */
+           return c2 - c1;
+         if (!c1)
+           break;
+       }
+
+      return 0;
+    }
+}
+\f
+/* A `struct linebuffer' is a structure which holds a line of text.
+   `readline' reads a line from a stream into a linebuffer
+   and works regardless of the length of the line.  */
+
+struct linebuffer
+{
+  long size;
+  char *buffer;
+};
+
+/* Initialize LINEBUFFER for use. */
+
+void
+initbuffer (linebuffer)
+     struct linebuffer *linebuffer;
+{
+  linebuffer->size = 200;
+  linebuffer->buffer = (char *) xmalloc (200);
+}
+
+/* Read a line of text from STREAM into LINEBUFFER.
+   Return the length of the line.  */
+
+long
+readline (linebuffer, stream)
+     struct linebuffer *linebuffer;
+     FILE *stream;
+{
+  char *buffer = linebuffer->buffer;
+  char *p = linebuffer->buffer;
+  char *end = p + linebuffer->size;
+
+  while (1)
+    {
+      int c = getc (stream);
+      if (p == end)
+       {
+         buffer = (char *) xrealloc (buffer, linebuffer->size *= 2);
+         p += buffer - linebuffer->buffer;
+         end += buffer - linebuffer->buffer;
+         linebuffer->buffer = buffer;
+       }
+      if (c < 0 || c == '\n')
+       {
+         *p = 0;
+         break;
+       }
+      *p++ = c;
+    }
+
+  return p - buffer;
+}
+\f
+/* Sort an input file too big to sort in core.  */
+
+void
+sort_offline (infile, nfiles, total, outfile)
+     char *infile;
+     int nfiles;
+     long total;
+     char *outfile;
+{
+  /* More than enough. */
+  int ntemps = 2 * (total + MAX_IN_CORE_SORT - 1) / MAX_IN_CORE_SORT;
+  char **tempfiles = (char **) xmalloc (ntemps * sizeof (char *));
+  FILE *istream = fopen (infile, "r");
+  int i;
+  struct linebuffer lb;
+  long linelength;
+  int failure = 0;
+
+  initbuffer (&lb);
+
+  /* Read in one line of input data.  */
+
+  linelength = readline (&lb, istream);
+
+  if (lb.buffer[0] != '\\' && lb.buffer[0] != '@')
+    {
+      error ("%s: not a texinfo index file", infile);
+      return;
+    }
+
+  /* Split up the input into `ntemps' temporary files, or maybe fewer,
+     and put the new files' names into `tempfiles' */
+
+  for (i = 0; i < ntemps; i++)
+    {
+      char *outname = maketempname (++tempcount);
+      FILE *ostream = fopen (outname, "w");
+      long tempsize = 0;
+
+      if (!ostream)
+       pfatal_with_name (outname);
+      tempfiles[i] = outname;
+
+      /* Copy lines into this temp file as long as it does not make file
+        "too big" or until there are no more lines.  */
+
+      while (tempsize + linelength + 1 <= MAX_IN_CORE_SORT)
+       {
+         tempsize += linelength + 1;
+         fputs (lb.buffer, ostream);
+         putc ('\n', ostream);
+
+         /* Read another line of input data.  */
+
+         linelength = readline (&lb, istream);
+         if (!linelength && feof (istream))
+           break;
+
+         if (lb.buffer[0] != '\\' && lb.buffer[0] != '@')
+           {
+             error ("%s: not a texinfo index file", infile);
+             failure = 1;
+             goto fail;
+           }
+       }
+      fclose (ostream);
+      if (feof (istream))
+       break;
+    }
+
+  free (lb.buffer);
+
+fail:
+  /* Record number of temp files we actually needed.  */
+
+  ntemps = i;
+
+  /* Sort each tempfile into another tempfile.
+    Delete the first set of tempfiles and put the names of the second
+    into `tempfiles'. */
+
+  for (i = 0; i < ntemps; i++)
+    {
+      char *newtemp = maketempname (++tempcount);
+      sort_in_core (&tempfiles[i], MAX_IN_CORE_SORT, newtemp);
+      if (!keep_tempfiles)
+       unlink (tempfiles[i]);
+      tempfiles[i] = newtemp;
+    }
+
+  if (failure)
+    return;
+
+  /* Merge the tempfiles together and indexify. */
+
+  merge_files (tempfiles, ntemps, outfile);
+}
+\f
+/* Sort INFILE, whose size is TOTAL,
+   assuming that is small enough to be done in-core,
+   then indexify it and send the output to OUTFILE (or to stdout).  */
+
+void
+sort_in_core (infile, total, outfile)
+     char *infile;
+     long total;
+     char *outfile;
+{
+  char **nextline;
+  char *data = (char *) xmalloc (total + 1);
+  char *file_data;
+  long file_size;
+  int i;
+  FILE *ostream = stdout;
+  struct lineinfo *lineinfo;
+
+  /* Read the contents of the file into the moby array `data'. */
+
+  int desc = open (infile, O_RDONLY, 0);
+
+  if (desc < 0)
+    fatal ("failure reopening %s", infile);
+  for (file_size = 0;;)
+    {
+      i = read (desc, data + file_size, total - file_size);
+      if (i <= 0)
+       break;
+      file_size += i;
+    }
+  file_data = data;
+  data[file_size] = 0;
+
+  close (desc);
+
+  if (file_size > 0 && data[0] != '\\' && data[0] != '@')
+    {
+      error ("%s: not a texinfo index file", infile);
+      return;
+    }
+
+  init_char_order ();
+
+  /* Sort routines want to know this address. */
+
+  text_base = data;
+
+  /* Create the array of pointers to lines, with a default size
+     frequently enough.  */
+
+  nlines = total / 50;
+  if (!nlines)
+    nlines = 2;
+  linearray = (char **) xmalloc (nlines * sizeof (char *));
+
+  /* `nextline' points to the next free slot in this array.
+     `nlines' is the allocated size.  */
+
+  nextline = linearray;
+
+  /* Parse the input file's data, and make entries for the lines.  */
+
+  nextline = parsefile (infile, nextline, file_data, file_size);
+  if (nextline == 0)
+    {
+      error ("%s: not a texinfo index file", infile);
+      return;
+    }
+
+  /* Sort the lines. */
+
+  /* If we have enough space, find the first keyfield of each line in advance.
+     Make a `struct lineinfo' for each line, which records the keyfield
+     as well as the line, and sort them.  */
+
+  lineinfo = (struct lineinfo *) malloc ((nextline - linearray) * sizeof (struct lineinfo));
+
+  if (lineinfo)
+    {
+      struct lineinfo *lp;
+      char **p;
+
+      for (lp = lineinfo, p = linearray; p != nextline; lp++, p++)
+       {
+         lp->text = *p;
+         lp->key.text = find_field (keyfields, *p, &lp->keylen);
+         if (keyfields->numeric)
+           lp->key.number = find_value (lp->key.text, lp->keylen);
+       }
+
+      qsort (lineinfo, nextline - linearray, sizeof (struct lineinfo), compare_prepared);
+
+      for (lp = lineinfo, p = linearray; p != nextline; lp++, p++)
+       *p = lp->text;
+
+      free (lineinfo);
+    }
+  else
+    qsort (linearray, nextline - linearray, sizeof (char *), compare_full);
+
+  /* Open the output file. */
+
+  if (outfile)
+    {
+      ostream = fopen (outfile, "w");
+      if (!ostream)
+       pfatal_with_name (outfile);
+    }
+
+  writelines (linearray, nextline - linearray, ostream);
+  if (outfile)
+    fclose (ostream);
+
+  free (linearray);
+  free (data);
+}
+\f
+/* Parse an input string in core into lines.
+   DATA is the input string, and SIZE is its length.
+   Data goes in LINEARRAY starting at NEXTLINE.
+   The value returned is the first entry in LINEARRAY still unused.
+   Value 0 means input file contents are invalid.  */
+
+char **
+parsefile (filename, nextline, data, size)
+     char *filename;
+     char **nextline;
+     char *data;
+     long size;
+{
+  char *p, *end;
+  char **line = nextline;
+
+  p = data;
+  end = p + size;
+  *end = 0;
+
+  while (p != end)
+    {
+      if (p[0] != '\\' && p[0] != '@')
+       return 0;
+
+      *line = p;
+      while (*p && *p != '\n')
+       p++;
+      if (p != end)
+       p++;
+
+      line++;
+      if (line == linearray + nlines)
+       {
+         char **old = linearray;
+         linearray = (char **) xrealloc (linearray, sizeof (char *) * (nlines *= 4));
+         line += linearray - old;
+       }
+    }
+
+  return line;
+}
+\f
+/* Indexification is a filter applied to the sorted lines
+   as they are being written to the output file.
+   Multiple entries for the same name, with different page numbers,
+   get combined into a single entry with multiple page numbers.
+   The first braced field, which is used for sorting, is discarded.
+   However, its first character is examined, folded to lower case,
+   and if it is different from that in the previous line fed to us
+   a \initial line is written with one argument, the new initial.
+
+   If an entry has four braced fields, then the second and third
+   constitute primary and secondary names.
+   In this case, each change of primary name
+   generates a \primary line which contains only the primary name,
+   and in between these are \secondary lines which contain
+   just a secondary name and page numbers. */
+
+/* The last primary name we wrote a \primary entry for.
+   If only one level of indexing is being done, this is the last name seen. */
+char *lastprimary;
+/* Length of storage allocated for lastprimary. */
+int lastprimarylength;
+
+/* Similar, for the secondary name. */
+char *lastsecondary;
+int lastsecondarylength;
+
+/* Zero if we are not in the middle of writing an entry.
+   One if we have written the beginning of an entry but have not
+   yet written any page numbers into it.
+   Greater than one if we have written the beginning of an entry
+   plus at least one page number. */
+int pending;
+
+/* The initial (for sorting purposes) of the last primary entry written.
+   When this changes, a \initial {c} line is written */
+
+char *lastinitial;
+
+int lastinitiallength;
+
+/* When we need a string of length 1 for the value of lastinitial,
+   store it here.  */
+
+char lastinitial1[2];
+
+/* Initialize static storage for writing an index. */
+
+static void
+xbzero(s, n)
+     char *s;
+     int n;
+{
+  register char *p;
+  for (p = s; n--; )
+    *p++ = '\0';
+}
+
+void
+init_index ()
+{
+  pending = 0;
+  lastinitial = lastinitial1;
+  lastinitial1[0] = 0;
+  lastinitial1[1] = 0;
+  lastinitiallength = 0;
+  lastprimarylength = 100;
+  lastprimary = (char *) xmalloc (lastprimarylength + 1);
+  xbzero (lastprimary, lastprimarylength + 1);
+  lastsecondarylength = 100;
+  lastsecondary = (char *) xmalloc (lastsecondarylength + 1);
+  xbzero (lastsecondary, lastsecondarylength + 1);
+}
+
+/* Indexify.  Merge entries for the same name,
+   insert headers for each initial character, etc.  */
+
+void
+indexify (line, ostream)
+     char *line;
+     FILE *ostream;
+{
+  char *primary, *secondary, *pagenumber;
+  int primarylength, secondarylength = 0, pagelength;
+  int nosecondary;
+  int initiallength;
+  char *initial;
+  char initial1[2];
+  register char *p;
+
+  /* First, analyze the parts of the entry fed to us this time. */
+
+  p = find_braced_pos (line, 0, 0, 0);
+  if (*p == '{')
+    {
+      initial = p;
+      /* Get length of inner pair of braces starting at `p',
+        including that inner pair of braces.  */
+      initiallength = find_braced_end (p + 1) + 1 - p;
+    }
+  else
+    {
+      initial = initial1;
+      initial1[0] = *p;
+      initial1[1] = 0;
+      initiallength = 1;
+
+      if (initial1[0] >= 'a' && initial1[0] <= 'z')
+       initial1[0] -= 040;
+    }
+
+  pagenumber = find_braced_pos (line, 1, 0, 0);
+  pagelength = find_braced_end (pagenumber) - pagenumber;
+  if (pagelength == 0)
+    abort ();
+
+  primary = find_braced_pos (line, 2, 0, 0);
+  primarylength = find_braced_end (primary) - primary;
+
+  secondary = find_braced_pos (line, 3, 0, 0);
+  nosecondary = !*secondary;
+  if (!nosecondary)
+    secondarylength = find_braced_end (secondary) - secondary;
+
+  /* If the primary is different from before, make a new primary entry. */
+  if (strncmp (primary, lastprimary, primarylength))
+    {
+      /* Close off current secondary entry first, if one is open. */
+      if (pending)
+       {
+         fputs ("}\n", ostream);
+         pending = 0;
+       }
+
+      /* If this primary has a different initial, include an entry for
+        the initial. */
+      if (initiallength != lastinitiallength ||
+         strncmp (initial, lastinitial, initiallength))
+       {
+         fprintf (ostream, "\\initial {");
+         fwrite (initial, 1, initiallength, ostream);
+         fprintf (ostream, "}\n", initial);
+         if (initial == initial1)
+           {
+             lastinitial = lastinitial1;
+             *lastinitial1 = *initial1;
+           }
+         else
+           {
+             lastinitial = initial;
+           }
+         lastinitiallength = initiallength;
+       }
+
+      /* Make the entry for the primary.  */
+      if (nosecondary)
+       fputs ("\\entry {", ostream);
+      else
+       fputs ("\\primary {", ostream);
+      fwrite (primary, primarylength, 1, ostream);
+      if (nosecondary)
+       {
+         fputs ("}{", ostream);
+         pending = 1;
+       }
+      else
+       fputs ("}\n", ostream);
+
+      /* Record name of most recent primary. */
+      if (lastprimarylength < primarylength)
+       {
+         lastprimarylength = primarylength + 100;
+         lastprimary = (char *) xrealloc (lastprimary,
+                                          1 + lastprimarylength);
+       }
+      strncpy (lastprimary, primary, primarylength);
+      lastprimary[primarylength] = 0;
+
+      /* There is no current secondary within this primary, now. */
+      lastsecondary[0] = 0;
+    }
+
+  /* Should not have an entry with no subtopic following one with a subtopic. */
+
+  if (nosecondary && *lastsecondary)
+    error ("entry %s follows an entry with a secondary name", line);
+
+  /* Start a new secondary entry if necessary. */
+  if (!nosecondary && strncmp (secondary, lastsecondary, secondarylength))
+    {
+      if (pending)
+       {
+         fputs ("}\n", ostream);
+         pending = 0;
+       }
+
+      /* Write the entry for the secondary.  */
+      fputs ("\\secondary {", ostream);
+      fwrite (secondary, secondarylength, 1, ostream);
+      fputs ("}{", ostream);
+      pending = 1;
+
+      /* Record name of most recent secondary. */
+      if (lastsecondarylength < secondarylength)
+       {
+         lastsecondarylength = secondarylength + 100;
+         lastsecondary = (char *) xrealloc (lastsecondary,
+                                            1 + lastsecondarylength);
+       }
+      strncpy (lastsecondary, secondary, secondarylength);
+      lastsecondary[secondarylength] = 0;
+    }
+
+  /* Here to add one more page number to the current entry. */
+  if (pending++ != 1)
+    fputs (", ", ostream);     /* Punctuate first, if this is not the first. */
+  fwrite (pagenumber, pagelength, 1, ostream);
+}
+
+/* Close out any unfinished output entry. */
+
+void
+finish_index (ostream)
+     FILE *ostream;
+{
+  if (pending)
+    fputs ("}\n", ostream);
+  free (lastprimary);
+  free (lastsecondary);
+}
+\f
+/* Copy the lines in the sorted order.
+   Each line is copied out of the input file it was found in. */
+
+void
+writelines (linearray, nlines, ostream)
+     char **linearray;
+     int nlines;
+     FILE *ostream;
+{
+  char **stop_line = linearray + nlines;
+  char **next_line;
+
+  init_index ();
+
+  /* Output the text of the lines, and free the buffer space. */
+
+  for (next_line = linearray; next_line != stop_line; next_line++)
+    {
+      /* If -u was specified, output the line only if distinct from previous one.  */
+      if (next_line == linearray
+      /* Compare previous line with this one, using only the
+         explicitly specd keyfields. */
+         || compare_general (*(next_line - 1), *next_line, 0L, 0L, num_keyfields - 1))
+       {
+         char *p = *next_line;
+         char c;
+
+         while ((c = *p++) && c != '\n')
+           /* Do nothing. */ ;
+         *(p - 1) = 0;
+         indexify (*next_line, ostream);
+       }
+    }
+
+  finish_index (ostream);
+}
+\f
+/* Assume (and optionally verify) that each input file is sorted;
+   merge them and output the result.
+   Returns nonzero if any input file fails to be sorted.
+
+   This is the high-level interface that can handle an unlimited
+   number of files.  */
+
+#define MAX_DIRECT_MERGE 10
+
+int
+merge_files (infiles, nfiles, outfile)
+     char **infiles;
+     int nfiles;
+     char *outfile;
+{
+  char **tempfiles;
+  int ntemps;
+  int i;
+  int value = 0;
+  int start_tempcount = tempcount;
+
+  if (nfiles <= MAX_DIRECT_MERGE)
+    return merge_direct (infiles, nfiles, outfile);
+
+  /* Merge groups of MAX_DIRECT_MERGE input files at a time,
+     making a temporary file to hold each group's result.  */
+
+  ntemps = (nfiles + MAX_DIRECT_MERGE - 1) / MAX_DIRECT_MERGE;
+  tempfiles = (char **) xmalloc (ntemps * sizeof (char *));
+  for (i = 0; i < ntemps; i++)
+    {
+      int nf = MAX_DIRECT_MERGE;
+      if (i + 1 == ntemps)
+       nf = nfiles - i * MAX_DIRECT_MERGE;
+      tempfiles[i] = maketempname (++tempcount);
+      value |= merge_direct (&infiles[i * MAX_DIRECT_MERGE], nf, tempfiles[i]);
+    }
+
+  /* All temporary files that existed before are no longer needed
+     since their contents have been merged into our new tempfiles.
+     So delete them.  */
+  flush_tempfiles (start_tempcount);
+
+  /* Now merge the temporary files we created.  */
+
+  merge_files (tempfiles, ntemps, outfile);
+
+  free (tempfiles);
+
+  return value;
+}
+\f
+/* Assume (and optionally verify) that each input file is sorted;
+   merge them and output the result.
+   Returns nonzero if any input file fails to be sorted.
+
+   This version of merging will not work if the number of
+   input files gets too high.  Higher level functions
+   use it only with a bounded number of input files.  */
+
+int
+merge_direct (infiles, nfiles, outfile)
+     char **infiles;
+     int nfiles;
+     char *outfile;
+{
+  struct linebuffer *lb1, *lb2;
+  struct linebuffer **thisline, **prevline;
+  FILE **streams;
+  int i;
+  int nleft;
+  int lossage = 0;
+  int *file_lossage;
+  struct linebuffer *prev_out = 0;
+  FILE *ostream = stdout;
+
+  if (outfile)
+    {
+      ostream = fopen (outfile, "w");
+    }
+  if (!ostream)
+    pfatal_with_name (outfile);
+
+  init_index ();
+
+  if (nfiles == 0)
+    {
+      if (outfile)
+       fclose (ostream);
+      return 0;
+    }
+
+  /* For each file, make two line buffers.
+     Also, for each file, there is an element of `thisline'
+     which points at any time to one of the file's two buffers,
+     and an element of `prevline' which points to the other buffer.
+     `thisline' is supposed to point to the next available line from the file,
+     while `prevline' holds the last file line used,
+     which is remembered so that we can verify that the file is properly sorted. */
+
+  /* lb1 and lb2 contain one buffer each per file. */
+  lb1 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer));
+  lb2 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer));
+
+  /* thisline[i] points to the linebuffer holding the next available line in file i,
+     or is zero if there are no lines left in that file.  */
+  thisline = (struct linebuffer **)
+    xmalloc (nfiles * sizeof (struct linebuffer *));
+  /* prevline[i] points to the linebuffer holding the last used line
+     from file i.  This is just for verifying that file i is properly
+     sorted.  */
+  prevline = (struct linebuffer **)
+    xmalloc (nfiles * sizeof (struct linebuffer *));
+  /* streams[i] holds the input stream for file i.  */
+  streams = (FILE **) xmalloc (nfiles * sizeof (FILE *));
+  /* file_lossage[i] is nonzero if we already know file i is not
+     properly sorted.  */
+  file_lossage = (int *) xmalloc (nfiles * sizeof (int));
+
+  /* Allocate and initialize all that storage. */
+
+  for (i = 0; i < nfiles; i++)
+    {
+      initbuffer (&lb1[i]);
+      initbuffer (&lb2[i]);
+      thisline[i] = &lb1[i];
+      prevline[i] = &lb2[i];
+      file_lossage[i] = 0;
+      streams[i] = fopen (infiles[i], "r");
+      if (!streams[i])
+       pfatal_with_name (infiles[i]);
+
+      readline (thisline[i], streams[i]);
+    }
+
+  /* Keep count of number of files not at eof. */
+  nleft = nfiles;
+
+  while (nleft)
+    {
+      struct linebuffer *best = 0;
+      struct linebuffer *exch;
+      int bestfile = -1;
+      int i;
+
+      /* Look at the next avail line of each file; choose the least one.  */
+
+      for (i = 0; i < nfiles; i++)
+       {
+         if (thisline[i] &&
+             (!best ||
+              0 < compare_general (best->buffer, thisline[i]->buffer,
+                                (long) bestfile, (long) i, num_keyfields)))
+           {
+             best = thisline[i];
+             bestfile = i;
+           }
+       }
+
+      /* Output that line, unless it matches the previous one and we
+        don't want duplicates. */
+
+      if (!(prev_out &&
+           !compare_general (prev_out->buffer,
+                             best->buffer, 0L, 1L, num_keyfields - 1)))
+       indexify (best->buffer, ostream);
+      prev_out = best;
+
+      /* Now make the line the previous of its file, and fetch a new
+        line from that file.  */
+
+      exch = prevline[bestfile];
+      prevline[bestfile] = thisline[bestfile];
+      thisline[bestfile] = exch;
+
+      while (1)
+       {
+         /* If the file has no more, mark it empty. */
+
+         if (feof (streams[bestfile]))
+           {
+             thisline[bestfile] = 0;
+             /* Update the number of files still not empty. */
+             nleft--;
+             break;
+           }
+         readline (thisline[bestfile], streams[bestfile]);
+         if (thisline[bestfile]->buffer[0] || !feof (streams[bestfile]))
+           break;
+       }
+    }
+
+  finish_index (ostream);
+
+  /* Free all storage and close all input streams. */
+
+  for (i = 0; i < nfiles; i++)
+    {
+      fclose (streams[i]);
+      free (lb1[i].buffer);
+      free (lb2[i].buffer);
+    }
+  free (file_lossage);
+  free (lb1);
+  free (lb2);
+  free (thisline);
+  free (prevline);
+  free (streams);
+
+  if (outfile)
+    fclose (ostream);
+
+  return lossage;
+}
+\f
+/* Print error message and exit.  */
+
+void
+fatal (s1, s2)
+     char *s1, *s2;
+{
+  error (s1, s2);
+  exit (TI_FATAL_ERROR);
+}
+
+/* Print error message.  S1 is printf control string, S2 is arg for it. */
+
+void
+error (s1, s2)
+     char *s1, *s2;
+{
+  printf ("%s: ", program_name);
+  printf (s1, s2);
+  printf ("\n");
+}
+
+#if !defined (HAVE_STRERROR)
+static char *
+strerror (n)
+     int n;
+{
+  static char ebuf[40];
+
+  if (n < sys_nerr)
+    return sys_errlist[n];
+  else
+    {
+      sprintf (ebuf, "Unknown error %d", n);
+      return ebuf;
+    }
+}
+#endif
+
+void
+perror_with_name (name)
+     char *name;
+{
+  char *s;
+
+  s = concat ("", strerror (errno), " for %s");
+  error (s, name);
+}
+
+void
+pfatal_with_name (name)
+     char *name;
+{
+  char *s;
+
+  s = concat ("", strerror (errno), " for %s");
+  fatal (s, name);
+}
+
+/* Return a newly-allocated string whose contents concatenate those of
+   S1, S2, S3.  */
+
+char *
+concat (s1, s2, s3)
+     char *s1, *s2, *s3;
+{
+  int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+  char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+  strcpy (result, s1);
+  strcpy (result + len1, s2);
+  strcpy (result + len1 + len2, s3);
+  *(result + len1 + len2 + len3) = 0;
+
+  return result;
+}
+
+/* Just like malloc, but kills the program in case of fatal error. */
+void *
+xmalloc (nbytes)
+     int nbytes;
+{
+  void *temp = (void *) malloc (nbytes);
+
+  if (nbytes && temp == (void *)NULL)
+    memory_error ("xmalloc", nbytes);
+
+  return (temp);
+}
+
+/* Like realloc (), but barfs if there isn't enough memory. */
+void *
+xrealloc (pointer, nbytes)
+     void *pointer;
+     int nbytes;
+{
+  void *temp;
+
+  if (!pointer)
+    temp = (void *)xmalloc (nbytes);
+  else
+    temp = (void *)realloc (pointer, nbytes);
+
+  if (nbytes && !temp)
+    memory_error ("xrealloc", nbytes);
+
+  return (temp);
+}
+
+memory_error (callers_name, bytes_wanted)
+     char *callers_name;
+     int bytes_wanted;
+{
+  char printable_string[80];
+
+  sprintf (printable_string,
+          "Virtual memory exhausted in %s ()!  Needed %d bytes.",
+          callers_name, bytes_wanted);
+
+  error (printable_string, "");
+  abort ();
+}
diff --git a/lib/readline/emacs_keymap.c b/lib/readline/emacs_keymap.c
new file mode 100644 (file)
index 0000000..849d85f
--- /dev/null
@@ -0,0 +1,885 @@
+/* emacs_keymap.c -- the keymap for emacs_mode in readline (). */
+
+/* Copyright (C) 1987, 1989, 1992 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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (BUFSIZ)
+#include <stdio.h>
+#endif /* !BUFSIZ */
+
+#include "readline.h"
+
+/* An array of function pointers, one for each possible key.
+   If the type byte is ISKMAP, then the pointer is the address of
+   a keymap. */
+
+KEYMAP_ENTRY_ARRAY emacs_standard_keymap = {
+
+  /* Control keys. */
+  { ISFUNC, (Function *)0x0 },         /* Control-@ */
+  { ISFUNC, rl_beg_of_line },          /* Control-a */
+  { ISFUNC, rl_backward },             /* Control-b */
+  { ISFUNC, (Function *)0x0 },         /* Control-c */
+  { ISFUNC, rl_delete },               /* Control-d */
+  { ISFUNC, rl_end_of_line },          /* Control-e */
+  { ISFUNC, rl_forward },              /* Control-f */
+  { ISFUNC, rl_abort },                        /* Control-g */
+  { ISFUNC, rl_rubout },               /* Control-h */
+  { ISFUNC, rl_complete },             /* Control-i */
+  { ISFUNC, rl_newline },              /* Control-j */
+  { ISFUNC, rl_kill_line },            /* Control-k */
+  { ISFUNC, rl_clear_screen },         /* Control-l */
+  { ISFUNC, rl_newline },              /* Control-m */
+  { ISFUNC, rl_get_next_history },     /* Control-n */
+  { ISFUNC, (Function *)0x0 },         /* Control-o */
+  { ISFUNC, rl_get_previous_history }, /* Control-p */
+  { ISFUNC, rl_quoted_insert },                /* Control-q */
+  { ISFUNC, rl_reverse_search_history }, /* Control-r */
+  { ISFUNC, rl_forward_search_history }, /* Control-s */
+  { ISFUNC, rl_transpose_chars },      /* Control-t */
+  { ISFUNC, rl_unix_line_discard },    /* Control-u */
+  { ISFUNC, rl_quoted_insert },                /* Control-v */
+  { ISFUNC, rl_unix_word_rubout },     /* Control-w */
+  { ISKMAP, (Function *)emacs_ctlx_keymap },   /* Control-x */
+  { ISFUNC, rl_yank },                 /* Control-y */
+  { ISFUNC, (Function *)0x0 },         /* Control-z */
+  { ISKMAP, (Function *)emacs_meta_keymap }, /* Control-[ */
+  { ISFUNC, (Function *)0x0 },         /* Control-\ */
+  { ISFUNC, (Function *)0x0 },         /* Control-] */
+  { ISFUNC, (Function *)0x0 },         /* Control-^ */
+  { ISFUNC, rl_undo_command },         /* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, rl_insert },       /* SPACE */
+  { ISFUNC, rl_insert },       /* ! */
+  { ISFUNC, rl_insert },       /* " */
+  { ISFUNC, rl_insert },       /* # */
+  { ISFUNC, rl_insert },       /* $ */
+  { ISFUNC, rl_insert },       /* % */
+  { ISFUNC, rl_insert },       /* & */
+  { ISFUNC, rl_insert },       /* ' */
+  { ISFUNC, rl_insert },       /* ( */
+#if defined (PAREN_MATCHING)
+  { ISFUNC, rl_insert_close }, /* ) */
+#else
+  { ISFUNC, rl_insert },       /* ) */
+#endif /* !PAREN_MATCHING */
+  { ISFUNC, rl_insert },       /* * */
+  { ISFUNC, rl_insert },       /* + */
+  { ISFUNC, rl_insert },       /* , */
+  { ISFUNC, rl_insert },       /* - */
+  { ISFUNC, rl_insert },       /* . */
+  { ISFUNC, rl_insert },       /* / */
+
+  /* Regular digits. */
+  { ISFUNC, rl_insert },       /* 0 */
+  { ISFUNC, rl_insert },       /* 1 */
+  { ISFUNC, rl_insert },       /* 2 */
+  { ISFUNC, rl_insert },       /* 3 */
+  { ISFUNC, rl_insert },       /* 4 */
+  { ISFUNC, rl_insert },       /* 5 */
+  { ISFUNC, rl_insert },       /* 6 */
+  { ISFUNC, rl_insert },       /* 7 */
+  { ISFUNC, rl_insert },       /* 8 */
+  { ISFUNC, rl_insert },       /* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, rl_insert },       /* : */
+  { ISFUNC, rl_insert },       /* ; */
+  { ISFUNC, rl_insert },       /* < */
+  { ISFUNC, rl_insert },       /* = */
+  { ISFUNC, rl_insert },       /* > */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_insert },       /* A */
+  { ISFUNC, rl_insert },       /* B */
+  { ISFUNC, rl_insert },       /* C */
+  { ISFUNC, rl_insert },       /* D */
+  { ISFUNC, rl_insert },       /* E */
+  { ISFUNC, rl_insert },       /* F */
+  { ISFUNC, rl_insert },       /* G */
+  { ISFUNC, rl_insert },       /* H */
+  { ISFUNC, rl_insert },       /* I */
+  { ISFUNC, rl_insert },       /* J */
+  { ISFUNC, rl_insert },       /* K */
+  { ISFUNC, rl_insert },       /* L */
+  { ISFUNC, rl_insert },       /* M */
+  { ISFUNC, rl_insert },       /* N */
+  { ISFUNC, rl_insert },       /* O */
+  { ISFUNC, rl_insert },       /* P */
+  { ISFUNC, rl_insert },       /* Q */
+  { ISFUNC, rl_insert },       /* R */
+  { ISFUNC, rl_insert },       /* S */
+  { ISFUNC, rl_insert },       /* T */
+  { ISFUNC, rl_insert },       /* U */
+  { ISFUNC, rl_insert },       /* V */
+  { ISFUNC, rl_insert },       /* W */
+  { ISFUNC, rl_insert },       /* X */
+  { ISFUNC, rl_insert },       /* Y */
+  { ISFUNC, rl_insert },       /* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, rl_insert },       /* [ */
+  { ISFUNC, rl_insert },       /* \ */
+#if defined (PAREN_MATCHING)
+  { ISFUNC, rl_insert_close }, /* ] */
+#else
+  { ISFUNC, rl_insert },       /* ] */
+#endif /* !PAREN_MATCHING */
+  { ISFUNC, rl_insert },       /* ^ */
+  { ISFUNC, rl_insert },       /* _ */
+  { ISFUNC, rl_insert },       /* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, rl_insert },       /* a */
+  { ISFUNC, rl_insert },       /* b */
+  { ISFUNC, rl_insert },       /* c */
+  { ISFUNC, rl_insert },       /* d */
+  { ISFUNC, rl_insert },       /* e */
+  { ISFUNC, rl_insert },       /* f */
+  { ISFUNC, rl_insert },       /* g */
+  { ISFUNC, rl_insert },       /* h */
+  { ISFUNC, rl_insert },       /* i */
+  { ISFUNC, rl_insert },       /* j */
+  { ISFUNC, rl_insert },       /* k */
+  { ISFUNC, rl_insert },       /* l */
+  { ISFUNC, rl_insert },       /* m */
+  { ISFUNC, rl_insert },       /* n */
+  { ISFUNC, rl_insert },       /* o */
+  { ISFUNC, rl_insert },       /* p */
+  { ISFUNC, rl_insert },       /* q */
+  { ISFUNC, rl_insert },       /* r */
+  { ISFUNC, rl_insert },       /* s */
+  { ISFUNC, rl_insert },       /* t */
+  { ISFUNC, rl_insert },       /* u */
+  { ISFUNC, rl_insert },       /* v */
+  { ISFUNC, rl_insert },       /* w */
+  { ISFUNC, rl_insert },       /* x */
+  { ISFUNC, rl_insert },       /* y */
+  { ISFUNC, rl_insert },       /* z */
+
+  /* Final punctuation. */
+  { ISFUNC, rl_insert },       /* { */
+  { ISFUNC, rl_insert },       /* | */
+#if defined (PAREN_MATCHING)
+  { ISFUNC, rl_insert_close }, /* } */
+#else
+  { ISFUNC, rl_insert },       /* } */
+#endif /* !PAREN_MATCHING */
+  { ISFUNC, rl_insert },       /* ~ */
+  { ISFUNC, rl_rubout },       /* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+  /* Pure 8-bit characters (128 - 159).
+     These might be used in some
+     character sets. */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+
+  /* ISO Latin-1 characters (160 - 255) */
+  { ISFUNC, rl_insert },       /* No-break space */
+  { ISFUNC, rl_insert },       /* Inverted exclamation mark */
+  { ISFUNC, rl_insert },       /* Cent sign */
+  { ISFUNC, rl_insert },       /* Pound sign */
+  { ISFUNC, rl_insert },       /* Currency sign */
+  { ISFUNC, rl_insert },       /* Yen sign */
+  { ISFUNC, rl_insert },       /* Broken bar */
+  { ISFUNC, rl_insert },       /* Section sign */
+  { ISFUNC, rl_insert },       /* Diaeresis */
+  { ISFUNC, rl_insert },       /* Copyright sign */
+  { ISFUNC, rl_insert },       /* Feminine ordinal indicator */
+  { ISFUNC, rl_insert },       /* Left pointing double angle quotation mark */
+  { ISFUNC, rl_insert },       /* Not sign */
+  { ISFUNC, rl_insert },       /* Soft hyphen */
+  { ISFUNC, rl_insert },       /* Registered sign */
+  { ISFUNC, rl_insert },       /* Macron */
+  { ISFUNC, rl_insert },       /* Degree sign */
+  { ISFUNC, rl_insert },       /* Plus-minus sign */
+  { ISFUNC, rl_insert },       /* Superscript two */
+  { ISFUNC, rl_insert },       /* Superscript three */
+  { ISFUNC, rl_insert },       /* Acute accent */
+  { ISFUNC, rl_insert },       /* Micro sign */
+  { ISFUNC, rl_insert },       /* Pilcrow sign */
+  { ISFUNC, rl_insert },       /* Middle dot */
+  { ISFUNC, rl_insert },       /* Cedilla */
+  { ISFUNC, rl_insert },       /* Superscript one */
+  { ISFUNC, rl_insert },       /* Masculine ordinal indicator */
+  { ISFUNC, rl_insert },       /* Right pointing double angle quotation mark */
+  { ISFUNC, rl_insert },       /* Vulgar fraction one quarter */
+  { ISFUNC, rl_insert },       /* Vulgar fraction one half */
+  { ISFUNC, rl_insert },       /* Vulgar fraction three quarters */
+  { ISFUNC, rl_insert },       /* Inverted questionk mark */
+  { ISFUNC, rl_insert },       /* Latin capital letter a with grave */
+  { ISFUNC, rl_insert },       /* Latin capital letter a with acute */
+  { ISFUNC, rl_insert },       /* Latin capital letter a with circumflex */
+  { ISFUNC, rl_insert },       /* Latin capital letter a with tilde */
+  { ISFUNC, rl_insert },       /* Latin capital letter a with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin capital letter a with ring above */
+  { ISFUNC, rl_insert },       /* Latin capital letter ae */
+  { ISFUNC, rl_insert },       /* Latin capital letter c with cedilla */
+  { ISFUNC, rl_insert },       /* Latin capital letter e with grave */
+  { ISFUNC, rl_insert },       /* Latin capital letter e with acute */
+  { ISFUNC, rl_insert },       /* Latin capital letter e with circumflex */
+  { ISFUNC, rl_insert },       /* Latin capital letter e with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin capital letter i with grave */
+  { ISFUNC, rl_insert },       /* Latin capital letter i with acute */
+  { ISFUNC, rl_insert },       /* Latin capital letter i with circumflex */
+  { ISFUNC, rl_insert },       /* Latin capital letter i with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin capital letter eth (Icelandic) */
+  { ISFUNC, rl_insert },       /* Latin capital letter n with tilde */
+  { ISFUNC, rl_insert },       /* Latin capital letter o with grave */
+  { ISFUNC, rl_insert },       /* Latin capital letter o with acute */
+  { ISFUNC, rl_insert },       /* Latin capital letter o with circumflex */
+  { ISFUNC, rl_insert },       /* Latin capital letter o with tilde */
+  { ISFUNC, rl_insert },       /* Latin capital letter o with diaeresis */
+  { ISFUNC, rl_insert },       /* Multiplication sign */
+  { ISFUNC, rl_insert },       /* Latin capital letter o with stroke */
+  { ISFUNC, rl_insert },       /* Latin capital letter u with grave */
+  { ISFUNC, rl_insert },       /* Latin capital letter u with acute */
+  { ISFUNC, rl_insert },       /* Latin capital letter u with circumflex */
+  { ISFUNC, rl_insert },       /* Latin capital letter u with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin capital letter Y with acute */
+  { ISFUNC, rl_insert },       /* Latin capital letter thorn (Icelandic) */
+  { ISFUNC, rl_insert },       /* Latin small letter sharp s (German) */
+  { ISFUNC, rl_insert },       /* Latin small letter a with grave */
+  { ISFUNC, rl_insert },       /* Latin small letter a with acute */
+  { ISFUNC, rl_insert },       /* Latin small letter a with circumflex */
+  { ISFUNC, rl_insert },       /* Latin small letter a with tilde */
+  { ISFUNC, rl_insert },       /* Latin small letter a with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin small letter a with ring above */
+  { ISFUNC, rl_insert },       /* Latin small letter ae */
+  { ISFUNC, rl_insert },       /* Latin small letter c with cedilla */
+  { ISFUNC, rl_insert },       /* Latin small letter e with grave */
+  { ISFUNC, rl_insert },       /* Latin small letter e with acute */
+  { ISFUNC, rl_insert },       /* Latin small letter e with circumflex */
+  { ISFUNC, rl_insert },       /* Latin small letter e with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin small letter i with grave */
+  { ISFUNC, rl_insert },       /* Latin small letter i with acute */
+  { ISFUNC, rl_insert },       /* Latin small letter i with circumflex */
+  { ISFUNC, rl_insert },       /* Latin small letter i with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin small letter eth (Icelandic) */
+  { ISFUNC, rl_insert },       /* Latin small letter n with tilde */
+  { ISFUNC, rl_insert },       /* Latin small letter o with grave */
+  { ISFUNC, rl_insert },       /* Latin small letter o with acute */
+  { ISFUNC, rl_insert },       /* Latin small letter o with circumflex */
+  { ISFUNC, rl_insert },       /* Latin small letter o with tilde */
+  { ISFUNC, rl_insert },       /* Latin small letter o with diaeresis */
+  { ISFUNC, rl_insert },       /* Division sign */
+  { ISFUNC, rl_insert },       /* Latin small letter o with stroke */
+  { ISFUNC, rl_insert },       /* Latin small letter u with grave */
+  { ISFUNC, rl_insert },       /* Latin small letter u with acute */
+  { ISFUNC, rl_insert },       /* Latin small letter u with circumflex */
+  { ISFUNC, rl_insert },       /* Latin small letter u with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin small letter y with acute */
+  { ISFUNC, rl_insert },       /* Latin small letter thorn (Icelandic) */
+  { ISFUNC, rl_insert }                /* Latin small letter y with diaeresis */
+#endif /* KEYMAP_SIZE > 128 */
+};
+
+KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
+
+  /* Meta keys.  Just like above, but the high bit is set. */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-@ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-a */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-b */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-c */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-d */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-e */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-f */
+  { ISFUNC, rl_abort },                /* Meta-Control-g */
+  { ISFUNC, rl_backward_kill_word },   /* Meta-Control-h */
+  { ISFUNC, rl_tab_insert },   /* Meta-Control-i */
+  { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-j */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-k */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-l */
+  { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-m */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-n */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-o */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-p */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-q */
+  { ISFUNC, rl_revert_line },  /* Meta-Control-r */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-s */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-t */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-u */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-v */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-w */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-x */
+  { ISFUNC, rl_yank_nth_arg }, /* Meta-Control-y */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-z */
+
+  { ISFUNC, rl_complete },     /* Meta-Control-[ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-\ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-] */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-^ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, (Function *)0x0 }, /* Meta-SPACE */
+  { ISFUNC, (Function *)0x0 }, /* Meta-! */
+  { ISFUNC, (Function *)0x0 }, /* Meta-" */
+  { ISFUNC, (Function *)0x0 }, /* Meta-# */
+  { ISFUNC, (Function *)0x0 }, /* Meta-$ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-% */
+  { ISFUNC, rl_tilde_expand }, /* Meta-& */
+  { ISFUNC, (Function *)0x0 }, /* Meta-' */
+  { ISFUNC, (Function *)0x0 }, /* Meta-( */
+  { ISFUNC, (Function *)0x0 }, /* Meta-) */
+  { ISFUNC, (Function *)0x0 }, /* Meta-* */
+  { ISFUNC, (Function *)0x0 }, /* Meta-+ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-, */
+  { ISFUNC, rl_digit_argument }, /* Meta-- */
+  { ISFUNC, rl_yank_last_arg}, /* Meta-. */
+  { ISFUNC, (Function *)0x0 }, /* Meta-/ */
+
+  /* Regular digits. */
+  { ISFUNC, rl_digit_argument }, /* Meta-0 */
+  { ISFUNC, rl_digit_argument }, /* Meta-1 */
+  { ISFUNC, rl_digit_argument }, /* Meta-2 */
+  { ISFUNC, rl_digit_argument }, /* Meta-3 */
+  { ISFUNC, rl_digit_argument }, /* Meta-4 */
+  { ISFUNC, rl_digit_argument }, /* Meta-5 */
+  { ISFUNC, rl_digit_argument }, /* Meta-6 */
+  { ISFUNC, rl_digit_argument }, /* Meta-7 */
+  { ISFUNC, rl_digit_argument }, /* Meta-8 */
+  { ISFUNC, rl_digit_argument }, /* Meta-9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* Meta-: */
+  { ISFUNC, (Function *)0x0 },         /* Meta-; */
+  { ISFUNC, rl_beginning_of_history }, /* Meta-< */
+  { ISFUNC, (Function *)0x0 },         /* Meta-= */
+  { ISFUNC, rl_end_of_history },       /* Meta-> */
+  { ISFUNC, rl_possible_completions }, /* Meta-? */
+  { ISFUNC, (Function *)0x0 },         /* Meta-@ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-A */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-B */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-C */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-D */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-E */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-F */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-G */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-H */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-I */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-J */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-K */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-L */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-M */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-N */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-O */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-P */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-Q */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-R */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-S */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-T */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-U */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-V */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-W */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-X */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-Y */
+  { ISFUNC, rl_do_lowercase_version }, /* Meta-Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* Meta-[ */    /* was rl_arrow_keys */
+  { ISFUNC, rl_delete_horizontal_space },      /* Meta-\ */
+  { ISFUNC, (Function *)0x0 },         /* Meta-] */
+  { ISFUNC, (Function *)0x0 },         /* Meta-^ */
+  { ISFUNC, rl_yank_last_arg },                /* Meta-_ */
+  { ISFUNC, (Function *)0x0 },         /* Meta-` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, (Function *)0x0 }, /* Meta-a */
+  { ISFUNC, rl_backward_word },        /* Meta-b */
+  { ISFUNC, rl_capitalize_word }, /* Meta-c */
+  { ISFUNC, rl_kill_word },    /* Meta-d */
+  { ISFUNC, (Function *)0x0 }, /* Meta-e */
+  { ISFUNC, rl_forward_word }, /* Meta-f */
+  { ISFUNC, (Function *)0x0 }, /* Meta-g */
+  { ISFUNC, (Function *)0x0 }, /* Meta-h */
+  { ISFUNC, (Function *)0x0 }, /* Meta-i */
+  { ISFUNC, (Function *)0x0 }, /* Meta-j */
+  { ISFUNC, (Function *)0x0 }, /* Meta-k */
+  { ISFUNC, rl_downcase_word },        /* Meta-l */
+  { ISFUNC, (Function *)0x0 }, /* Meta-m */
+  { ISFUNC, rl_noninc_forward_search },        /* Meta-n */
+  { ISFUNC, (Function *)0x0 }, /* Meta-o */    /* was rl_arrow_keys */
+  { ISFUNC, rl_noninc_reverse_search },        /* Meta-p */
+  { ISFUNC, (Function *)0x0 }, /* Meta-q */
+  { ISFUNC, rl_revert_line },  /* Meta-r */
+  { ISFUNC, (Function *)0x0 }, /* Meta-s */
+  { ISFUNC, rl_transpose_words }, /* Meta-t */
+  { ISFUNC, rl_upcase_word },  /* Meta-u */
+  { ISFUNC, (Function *)0x0 }, /* Meta-v */
+  { ISFUNC, (Function *)0x0 }, /* Meta-w */
+  { ISFUNC, (Function *)0x0 }, /* Meta-x */
+  { ISFUNC, rl_yank_pop },     /* Meta-y */
+  { ISFUNC, (Function *)0x0 }, /* Meta-z */
+
+  /* Final punctuation. */
+  { ISFUNC, (Function *)0x0 }, /* Meta-{ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-| */
+  { ISFUNC, (Function *)0x0 }, /* Meta-} */
+  { ISFUNC, rl_tilde_expand }, /* Meta-~ */
+  { ISFUNC, rl_backward_kill_word }, /* Meta-rubout */
+
+#if KEYMAP_SIZE > 128
+  /* Undefined keys. */
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 }
+#endif /* KEYMAP_SIZE > 128 */
+};
+
+KEYMAP_ENTRY_ARRAY emacs_ctlx_keymap = {
+
+  /* Control keys. */
+  { ISFUNC, (Function *)0x0 },         /* Control-@ */
+  { ISFUNC, (Function *)0x0 },         /* Control-a */
+  { ISFUNC, (Function *)0x0 },         /* Control-b */
+  { ISFUNC, (Function *)0x0 },         /* Control-c */
+  { ISFUNC, (Function *)0x0 },         /* Control-d */
+  { ISFUNC, (Function *)0x0 },         /* Control-e */
+  { ISFUNC, (Function *)0x0 },         /* Control-f */
+  { ISFUNC, rl_abort },                        /* Control-g */
+  { ISFUNC, (Function *)0x0 },         /* Control-h */
+  { ISFUNC, (Function *)0x0 },         /* Control-i */
+  { ISFUNC, (Function *)0x0 },         /* Control-j */
+  { ISFUNC, (Function *)0x0 },         /* Control-k */
+  { ISFUNC, (Function *)0x0 },         /* Control-l */
+  { ISFUNC, (Function *)0x0 },         /* Control-m */
+  { ISFUNC, (Function *)0x0 },         /* Control-n */
+  { ISFUNC, (Function *)0x0 },         /* Control-o */
+  { ISFUNC, (Function *)0x0 },         /* Control-p */
+  { ISFUNC, (Function *)0x0 },         /* Control-q */
+  { ISFUNC, rl_re_read_init_file },    /* Control-r */
+  { ISFUNC, (Function *)0x0 },         /* Control-s */
+  { ISFUNC, (Function *)0x0 },         /* Control-t */
+  { ISFUNC, rl_undo_command },         /* Control-u */
+  { ISFUNC, (Function *)0x0 },         /* Control-v */
+  { ISFUNC, (Function *)0x0 },         /* Control-w */
+  { ISFUNC, (Function *)0x0 },         /* Control-x */
+  { ISFUNC, (Function *)0x0 },         /* Control-y */
+  { ISFUNC, (Function *)0x0 },         /* Control-z */
+  { ISFUNC, (Function *)0x0 },         /* Control-[ */
+  { ISFUNC, (Function *)0x0 },         /* Control-\ */
+  { ISFUNC, (Function *)0x0 },         /* Control-] */
+  { ISFUNC, (Function *)0x0 },         /* Control-^ */
+  { ISFUNC, (Function *)0x0 },         /* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, (Function *)0x0 },         /* SPACE */
+  { ISFUNC, (Function *)0x0 },         /* ! */
+  { ISFUNC, (Function *)0x0 },         /* " */
+  { ISFUNC, (Function *)0x0 },         /* # */
+  { ISFUNC, (Function *)0x0 },         /* $ */
+  { ISFUNC, (Function *)0x0 },         /* % */
+  { ISFUNC, (Function *)0x0 },         /* & */
+  { ISFUNC, (Function *)0x0 },         /* ' */
+  { ISFUNC, rl_start_kbd_macro },      /* ( */
+  { ISFUNC, rl_end_kbd_macro  },       /* ) */
+  { ISFUNC, (Function *)0x0 },         /* * */
+  { ISFUNC, (Function *)0x0 },         /* + */
+  { ISFUNC, (Function *)0x0 },         /* , */
+  { ISFUNC, (Function *)0x0 },         /* - */
+  { ISFUNC, (Function *)0x0 },         /* . */
+  { ISFUNC, (Function *)0x0 },         /* / */
+
+  /* Regular digits. */
+  { ISFUNC, (Function *)0x0 },         /* 0 */
+  { ISFUNC, (Function *)0x0 },         /* 1 */
+  { ISFUNC, (Function *)0x0 },         /* 2 */
+  { ISFUNC, (Function *)0x0 },         /* 3 */
+  { ISFUNC, (Function *)0x0 },         /* 4 */
+  { ISFUNC, (Function *)0x0 },         /* 5 */
+  { ISFUNC, (Function *)0x0 },         /* 6 */
+  { ISFUNC, (Function *)0x0 },         /* 7 */
+  { ISFUNC, (Function *)0x0 },         /* 8 */
+  { ISFUNC, (Function *)0x0 },         /* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, (Function *)0x0 }, /* : */
+  { ISFUNC, (Function *)0x0 }, /* ; */
+  { ISFUNC, (Function *)0x0 }, /* < */
+  { ISFUNC, (Function *)0x0 }, /* = */
+  { ISFUNC, (Function *)0x0 }, /* > */
+  { ISFUNC, (Function *)0x0 }, /* ? */
+  { ISFUNC, (Function *)0x0 }, /* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_do_lowercase_version }, /* A */
+  { ISFUNC, rl_do_lowercase_version }, /* B */
+  { ISFUNC, rl_do_lowercase_version }, /* C */
+  { ISFUNC, rl_do_lowercase_version }, /* D */
+  { ISFUNC, rl_do_lowercase_version }, /* E */
+  { ISFUNC, rl_do_lowercase_version }, /* F */
+  { ISFUNC, rl_do_lowercase_version }, /* G */
+  { ISFUNC, rl_do_lowercase_version }, /* H */
+  { ISFUNC, rl_do_lowercase_version }, /* I */
+  { ISFUNC, rl_do_lowercase_version }, /* J */
+  { ISFUNC, rl_do_lowercase_version }, /* K */
+  { ISFUNC, rl_do_lowercase_version }, /* L */
+  { ISFUNC, rl_do_lowercase_version }, /* M */
+  { ISFUNC, rl_do_lowercase_version }, /* N */
+  { ISFUNC, rl_do_lowercase_version }, /* O */
+  { ISFUNC, rl_do_lowercase_version }, /* P */
+  { ISFUNC, rl_do_lowercase_version }, /* Q */
+  { ISFUNC, rl_do_lowercase_version }, /* R */
+  { ISFUNC, rl_do_lowercase_version }, /* S */
+  { ISFUNC, rl_do_lowercase_version }, /* T */
+  { ISFUNC, rl_do_lowercase_version }, /* U */
+  { ISFUNC, rl_do_lowercase_version }, /* V */
+  { ISFUNC, rl_do_lowercase_version }, /* W */
+  { ISFUNC, rl_do_lowercase_version }, /* X */
+  { ISFUNC, rl_do_lowercase_version }, /* Y */
+  { ISFUNC, rl_do_lowercase_version }, /* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* [ */
+  { ISFUNC, (Function *)0x0 },         /* \ */
+  { ISFUNC, (Function *)0x0 },         /* ] */
+  { ISFUNC, (Function *)0x0 },         /* ^ */
+  { ISFUNC, (Function *)0x0 },         /* _ */
+  { ISFUNC, (Function *)0x0 },         /* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, (Function *)0x0 },         /* a */
+  { ISFUNC, (Function *)0x0 },         /* b */
+  { ISFUNC, (Function *)0x0 },         /* c */
+  { ISFUNC, (Function *)0x0 },         /* d */
+  { ISFUNC, rl_call_last_kbd_macro },  /* e */
+  { ISFUNC, (Function *)0x0 },         /* f */
+  { ISFUNC, (Function *)0x0 },         /* g */
+  { ISFUNC, (Function *)0x0 },         /* h */
+  { ISFUNC, (Function *)0x0 },         /* i */
+  { ISFUNC, (Function *)0x0 },         /* j */
+  { ISFUNC, (Function *)0x0 },         /* k */
+  { ISFUNC, (Function *)0x0 },         /* l */
+  { ISFUNC, (Function *)0x0 },         /* m */
+  { ISFUNC, (Function *)0x0 },         /* n */
+  { ISFUNC, (Function *)0x0 },         /* o */
+  { ISFUNC, (Function *)0x0 },         /* p */
+  { ISFUNC, (Function *)0x0 },         /* q */
+  { ISFUNC, (Function *)0x0 },         /* r */
+  { ISFUNC, (Function *)0x0 },         /* s */
+  { ISFUNC, (Function *)0x0 },         /* t */
+  { ISFUNC, (Function *)0x0 },         /* u */
+  { ISFUNC, (Function *)0x0 },         /* v */
+  { ISFUNC, (Function *)0x0 },         /* w */
+  { ISFUNC, (Function *)0x0 },         /* x */
+  { ISFUNC, (Function *)0x0 },         /* y */
+  { ISFUNC, (Function *)0x0 },         /* z */
+
+  /* Final punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* { */
+  { ISFUNC, (Function *)0x0 },         /* | */
+  { ISFUNC, (Function *)0x0 },         /* } */
+  { ISFUNC, (Function *)0x0 },         /* ~ */
+  { ISFUNC, rl_backward_kill_line },   /* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+  /* Undefined keys. */
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 }
+#endif /* KEYMAP_SIZE > 128 */
+};
diff --git a/lib/readline/examples/Inputrc b/lib/readline/examples/Inputrc
new file mode 100644 (file)
index 0000000..5b71bd7
--- /dev/null
@@ -0,0 +1,65 @@
+# My ~/.inputrc file is in -*- text -*- for easy editing with Emacs.
+#
+# Notice the various bindings which are conditionalized depending
+# on which program is running, or what terminal is active.
+#
+
+# In all programs, all terminals, make sure this is bound.
+"\C-x\C-r": re-read-init-file
+
+# Hp terminals (and some others) have ugly default behaviour for C-h.
+"\C-h": backward-delete-char
+"\e\C-h": backward-kill-word
+"\C-xd": dump-functions
+
+# In xterm windows, make the arrow keys do the right thing.
+$if TERM=xterm
+"\e[A": previous-history
+"\e[B": next-history
+"\e[C": forward-char
+"\e[D": backward-char
+
+# alternate arrow key prefix
+"\eOA": previous-history
+"\eOB": next-history
+"\eOC": forward-char
+"\eOD": backward-char
+
+# Under Xterm in Bash, we bind local Function keys to do something useful.
+$if Bash
+"\e[11~": "Function Key 1"
+"\e[12~": "Function Key 2"
+"\e[13~": "Function Key 3"
+"\e[14~": "Function Key 4"
+"\e[15~": "Function Key 5"
+
+# I know the following escape sequence numbers are 1 greater than
+# the function key.  Don't ask me why, I didn't design the xterm terminal.
+"\e[17~": "Function Key 6"
+"\e[18~": "Function Key 7"
+"\e[19~": "Function Key 8"
+"\e[20~": "Function Key 9"
+"\e[21~": "Function Key 10"
+$endif
+$endif
+
+# For Bash, all terminals, add some Bash specific hacks.
+$if Bash
+"\C-xv": show-bash-version
+"\C-x\C-e": shell-expand-line
+
+# Here is one for editing my path.
+"\C-xp": "$PATH\C-x\C-e\C-e\"\C-aPATH=\":\C-b"
+
+# Make C-x r read my mail in emacs.
+# "\C-xr": "emacs -f rmail\C-j"
+$endif
+
+# For FTP, different hacks:
+$if Ftp
+"\C-xg": "get \M-?"
+"\C-xt": "put \M-?"
+"\M-.": yank-last-arg
+$endif
+
+" ": self-insert
diff --git a/lib/readline/examples/Makefile b/lib/readline/examples/Makefile
new file mode 100644 (file)
index 0000000..3d1fc52
--- /dev/null
@@ -0,0 +1,12 @@
+# This is the Makefile for the examples subdirectory of readline. -*- text -*-
+#
+
+EXECUTABLES = fileman
+CFLAGS  = -g -I../..
+LDFLAGS = -g -L..
+
+fileman: fileman.o
+       $(CC) $(LDFLAGS) -o fileman fileman.o -lreadline -ltermcap
+
+fileman.o: fileman.c
+  
diff --git a/lib/readline/examples/fileman.c b/lib/readline/examples/fileman.c
new file mode 100644 (file)
index 0000000..3ecb9f1
--- /dev/null
@@ -0,0 +1,425 @@
+/* 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. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+extern char *getwd ();
+extern char *xmalloc ();
+
+/* The names of functions that actually do the manipulation. */
+int com_list (), com_view (), com_rename (), com_stat (), com_pwd ();
+int com_delete (), com_help (), com_cd (), com_quit ();
+
+/* A structure which contains information on the commands this program
+   can understand. */
+
+typedef struct {
+  char *name;                  /* User printable name of the function. */
+  Function *func;              /* Function to call to do the job. */
+  char *doc;                   /* Documentation for this function.  */
+} COMMAND;
+
+COMMAND commands[] = {
+  { "cd", com_cd, "Change to directory DIR" },
+  { "delete", com_delete, "Delete FILE" },
+  { "help", com_help, "Display this text" },
+  { "?", com_help, "Synonym for `help'" },
+  { "list", com_list, "List files in DIR" },
+  { "ls", com_list, "Synonym for `list'" },
+  { "pwd", com_pwd, "Print the current working directory" },
+  { "quit", com_quit, "Quit using Fileman" },
+  { "rename", com_rename, "Rename FILE to NEWNAME" },
+  { "stat", com_stat, "Print out statistics on FILE" },
+  { "view", com_view, "View the contents of FILE" },
+  { (char *)NULL, (Function *)NULL, (char *)NULL }
+};
+
+/* Forward declarations. */
+char *stripwhite ();
+COMMAND *find_command ();
+
+/* The name of this program, as taken from argv[0]. */
+char *progname;
+
+/* When non-zero, this global means the user is done using this program. */
+int done;
+
+char *
+dupstr (s)
+     int s;
+{
+  char *r;
+
+  r = xmalloc (strlen (s) + 1);
+  strcpy (r, s);
+  return (r);
+}
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char *line, *s;
+
+  progname = argv[0];
+
+  initialize_readline ();      /* Bind our completer. */
+
+  /* Loop reading and executing lines until the user quits. */
+  for ( ; done == 0; )
+    {
+      line = readline ("FileMan: ");
+
+      if (!line)
+        break;
+
+      /* Remove leading and trailing whitespace from the line.
+         Then, if there is anything left, add it to the history list
+         and execute it. */
+      s = stripwhite (line);
+
+      if (*s)
+        {
+          add_history (s);
+          execute_line (s);
+        }
+
+      free (line);
+    }
+  exit (0);
+}
+
+/* Execute a command line. */
+int
+execute_line (line)
+     char *line;
+{
+  register int i;
+  COMMAND *command;
+  char *word;
+
+  /* Isolate the command word. */
+  i = 0;
+  while (line[i] && whitespace (line[i]))
+    i++;
+  word = line + i;
+
+  while (line[i] && !whitespace (line[i]))
+    i++;
+
+  if (line[i])
+    line[i++] = '\0';
+
+  command = find_command (word);
+
+  if (!command)
+    {
+      fprintf (stderr, "%s: No such command for FileMan.\n", word);
+      return (-1);
+    }
+
+  /* Get argument to command, if any. */
+  while (whitespace (line[i]))
+    i++;
+
+  word = line + i;
+
+  /* Call the function. */
+  return ((*(command->func)) (word));
+}
+
+/* Look up NAME as the name of a command, and return a pointer to that
+   command.  Return a NULL pointer if NAME isn't a command name. */
+COMMAND *
+find_command (name)
+     char *name;
+{
+  register int i;
+
+  for (i = 0; commands[i].name; i++)
+    if (strcmp (name, commands[i].name) == 0)
+      return (&commands[i]);
+
+  return ((COMMAND *)NULL);
+}
+
+/* Strip whitespace from the start and end of STRING.  Return a pointer
+   into STRING. */
+char *
+stripwhite (string)
+     char *string;
+{
+  register char *s, *t;
+
+  for (s = string; whitespace (*s); s++)
+    ;
+    
+  if (*s == 0)
+    return (s);
+
+  t = s + strlen (s) - 1;
+  while (t > s && whitespace (*t))
+    t--;
+  *++t = '\0';
+
+  return s;
+}
+
+/* **************************************************************** */
+/*                                                                  */
+/*                  Interface to Readline Completion                */
+/*                                                                  */
+/* **************************************************************** */
+
+char *command_generator ();
+char **fileman_completion ();
+
+/* Tell the GNU Readline library how to complete.  We want to try to complete
+   on command names if this is the first word in the line, or on filenames
+   if not. */
+initialize_readline ()
+{
+  /* Allow conditional parsing of the ~/.inputrc file. */
+  rl_readline_name = "FileMan";
+
+  /* Tell the completer that we want a crack first. */
+  rl_attempted_completion_function = (CPPFunction *)fileman_completion;
+}
+
+/* Attempt to complete on the contents of TEXT.  START and END show the
+   region of TEXT that contains the word to complete.  We can use the
+   entire line in case we want to do some simple parsing.  Return the
+   array of matches, or NULL if there aren't any. */
+char **
+fileman_completion (text, start, end)
+     char *text;
+     int start, end;
+{
+  char **matches;
+
+  matches = (char **)NULL;
+
+  /* If this word is at the start of the line, then it is a command
+     to complete.  Otherwise it is the name of a file in the current
+     directory. */
+  if (start == 0)
+    matches = completion_matches (text, command_generator);
+
+  return (matches);
+}
+
+/* Generator function for command completion.  STATE lets us know whether
+   to start from scratch; without any state (i.e. STATE == 0), then we
+   start at the top of the list. */
+char *
+command_generator (text, state)
+     char *text;
+     int state;
+{
+  static int list_index, len;
+  char *name;
+
+  /* If this is a new word to complete, initialize now.  This includes
+     saving the length of TEXT for efficiency, and initializing the index
+     variable to 0. */
+  if (!state)
+    {
+      list_index = 0;
+      len = strlen (text);
+    }
+
+  /* Return the next name which partially matches from the command list. */
+  while (name = commands[list_index].name)
+    {
+      list_index++;
+
+      if (strncmp (name, text, len) == 0)
+        return (dupstr(name));
+    }
+
+  /* If no names matched, then return NULL. */
+  return ((char *)NULL);
+}
+
+/* **************************************************************** */
+/*                                                                  */
+/*                       FileMan Commands                           */
+/*                                                                  */
+/* **************************************************************** */
+
+/* String to pass to system ().  This is for the LIST, VIEW and RENAME
+   commands. */
+static char syscom[1024];
+
+/* List the file(s) named in arg. */
+com_list (arg)
+     char *arg;
+{
+  if (!arg)
+    arg = "";
+
+  sprintf (syscom, "ls -FClg %s", arg);
+  return (system (syscom));
+}
+
+com_view (arg)
+     char *arg;
+{
+  if (!valid_argument ("view", arg))
+    return 1;
+
+  sprintf (syscom, "more %s", arg);
+  return (system (syscom));
+}
+
+com_rename (arg)
+     char *arg;
+{
+  too_dangerous ("rename");
+  return (1);
+}
+
+com_stat (arg)
+     char *arg;
+{
+  struct stat finfo;
+
+  if (!valid_argument ("stat", arg))
+    return (1);
+
+  if (stat (arg, &finfo) == -1)
+    {
+      perror (arg);
+      return (1);
+    }
+
+  printf ("Statistics for `%s':\n", arg);
+
+  printf ("%s has %d link%s, and is %d byte%s in length.\n", arg,
+          finfo.st_nlink,
+          (finfo.st_nlink == 1) ? "" : "s",
+          finfo.st_size,
+          (finfo.st_size == 1) ? "" : "s");
+  printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime));
+  printf ("      Last access at: %s", ctime (&finfo.st_atime));
+  printf ("    Last modified at: %s", ctime (&finfo.st_mtime));
+  return (0);
+}
+
+com_delete (arg)
+     char *arg;
+{
+  too_dangerous ("delete");
+  return (1);
+}
+
+/* Print out help for ARG, or for all of the commands if ARG is
+   not present. */
+com_help (arg)
+     char *arg;
+{
+  register int i;
+  int printed = 0;
+
+  for (i = 0; commands[i].name; i++)
+    {
+      if (!*arg || (strcmp (arg, commands[i].name) == 0))
+        {
+          printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
+          printed++;
+        }
+    }
+
+  if (!printed)
+    {
+      printf ("No commands match `%s'.  Possibilties are:\n", arg);
+
+      for (i = 0; commands[i].name; i++)
+        {
+          /* Print in six columns. */
+          if (printed == 6)
+            {
+              printed = 0;
+              printf ("\n");
+            }
+
+          printf ("%s\t", commands[i].name);
+          printed++;
+        }
+
+      if (printed)
+        printf ("\n");
+    }
+  return (0);
+}
+
+/* Change to the directory ARG. */
+com_cd (arg)
+     char *arg;
+{
+  if (chdir (arg) == -1)
+    {
+      perror (arg);
+      return 1;
+    }
+
+  com_pwd ("");
+  return (0);
+}
+
+/* Print out the current working directory. */
+com_pwd (ignore)
+     char *ignore;
+{
+  char dir[1024], *s;
+
+  s = getwd (dir);
+  if (s == 0)
+    {
+      printf ("Error getting pwd: %s\n", dir);
+      return 1;
+    }
+
+  printf ("Current directory is %s\n", dir);
+  return 0;
+}
+
+/* The user wishes to quit using this program.  Just set DONE non-zero. */
+com_quit (arg)
+     char *arg;
+{
+  done = 1;
+  return (0);
+}
+
+/* Function which tells you that you can't do this. */
+too_dangerous (caller)
+     char *caller;
+{
+  fprintf (stderr,
+           "%s: Too dangerous for me to distribute.  Write it yourself.\n",
+           caller);
+}
+
+/* Return non-zero if ARG is a valid argument for CALLER, else print
+   an error message and return zero. */
+int
+valid_argument (caller, arg)
+     char *caller, *arg;
+{
+  if (!arg || !*arg)
+    {
+      fprintf (stderr, "%s: Argument required.\n", caller);
+      return (0);
+    }
+
+  return (1);
+}
diff --git a/lib/readline/examples/histexamp.c b/lib/readline/examples/histexamp.c
new file mode 100644 (file)
index 0000000..eceb66d
--- /dev/null
@@ -0,0 +1,82 @@
+main ()
+{
+  char line[1024], *t;
+  int len, done = 0;
+
+  line[0] = 0;
+
+  using_history ();
+  while (!done)
+    {
+      printf ("history$ ");
+      fflush (stdout);
+      t = fgets (line, sizeof (line) - 1, stdin);
+      if (t && *t)
+        {
+          len = strlen (t);
+          if (t[len - 1] == '\n')
+            t[len - 1] = '\0';
+        }
+
+      if (!t)
+        strcpy (line, "quit");
+
+      if (line[0])
+        {
+          char *expansion;
+          int result;
+
+          using_history ();
+
+          result = history_expand (line, &expansion);
+          if (result)
+            fprintf (stderr, "%s\n", expansion);
+
+          if (result < 0 || result == 2)
+            {
+              free (expansion);
+              continue;
+            }
+
+          add_history (expansion);
+          strncpy (line, expansion, sizeof (line) - 1);
+          free (expansion);
+        }
+
+      if (strcmp (line, "quit") == 0)
+        done = 1;
+      else if (strcmp (line, "save") == 0)
+        write_history ("history_file");
+      else if (strcmp (line, "read") == 0)
+        read_history ("history_file");
+      else if (strcmp (line, "list") == 0)
+        {
+          register HIST_ENTRY **the_list;
+          register int i;
+
+          the_list = history_list ();
+          if (the_list)
+            for (i = 0; the_list[i]; i++)
+              printf ("%d: %s\n", i + history_base, the_list[i]->line);
+        }
+      else if (strncmp (line, "delete", 6) == 0)
+        {
+          int which;
+          if ((sscanf (line + 6, "%d", &which)) == 1)
+            {
+              HIST_ENTRY *entry = remove_history (which);
+              if (!entry)
+                fprintf (stderr, "No such entry %d\n", which);
+              else
+                {
+                  free (entry->line);
+                  free (entry);
+                }
+            }
+          else
+            {
+              fprintf (stderr, "non-numeric arg given to `delete'\n");
+            }
+        }
+    }
+}
diff --git a/lib/readline/examples/manexamp.c b/lib/readline/examples/manexamp.c
new file mode 100644 (file)
index 0000000..3496efa
--- /dev/null
@@ -0,0 +1,94 @@
+/* manexamp.c -- The examples which appear in the documentation are here. */
+
+#include <stdio.h>
+#include <readline/readline.h>
+
+
+/* **************************************************************** */
+/*                                                                  */
+*                      How to Emulate gets ()                      */
+/*                                                                  */
+/* **************************************************************** */
+
+/* A static variable for holding the line. */
+static char *line_read = (char *)NULL;
+
+/* Read a string, and return a pointer to it.  Returns NULL on EOF. */
+char *
+rl_gets ()
+{
+  /* If the buffer has already been allocated, return the memory
+     to the free pool. */
+  if (line_read)
+    {
+      free (line_read);
+      line_read = (char *)NULL;
+    }
+
+  /* Get a line from the user. */
+  line_read = readline ("");
+
+  /* If the line has any text in it, save it on the history. */
+  if (line_read && *line_read)
+    add_history (line_read);
+
+  return (line_read);
+}
+
+/* **************************************************************** */
+/*                                                                  */
+/*        Writing a Function to be Called by Readline.              */
+/*                                                                  */
+/* **************************************************************** */
+
+/* Invert the case of the COUNT following characters. */
+invert_case_line (count, key)
+     int count, key;
+{
+  register int start, end;
+
+  start = rl_point;
+
+  if (count < 0)
+    {
+      direction = -1;
+      count = -count;
+    }
+  else
+    direction = 1;
+      
+  /* Find the end of the range to modify. */
+  end = start + (count * direction);
+
+  /* Force it to be within range. */
+  if (end > rl_end)
+    end = rl_end;
+  else if (end < 0)
+    end = -1;
+
+  if (start > end)
+    {
+      int temp = start;
+      start = end;
+      end = temp;
+    }
+
+  if (start == end)
+    return;
+
+  /* Tell readline that we are modifying the line, so save the undo
+     information. */
+  rl_modifying (start, end);
+
+  for (; start != end; start += direction)
+    {
+      if (uppercase_p (rl_line_buffer[start]))
+       rl_line_buffer[start] = to_lower (rl_line_buffer[start]);
+      else if (lowercase_p (rl_line_buffer[start]))
+       rl_line_buffer[start] = to_upper (rl_line_buffer[start]);
+    }
+
+  /* Move point to on top of the last character changed. */
+  rl_point = end - direction;
+}
+
diff --git a/lib/readline/funmap.c b/lib/readline/funmap.c
new file mode 100644 (file)
index 0000000..9255974
--- /dev/null
@@ -0,0 +1,299 @@
+/* funmap.c -- attach names to functions. */
+
+/* Copyright (C) 1987, 1989, 1992 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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+#if !defined (BUFSIZ)
+#include <stdio.h>
+#endif /* BUFSIZ */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "rlconf.h"
+#include "readline.h"
+
+static int qsort_string_compare ();
+
+FUNMAP **funmap = (FUNMAP **)NULL;
+static int funmap_size = 0;
+static int funmap_entry = 0;
+
+/* After initializing the function map, this is the index of the first
+   program specific function. */
+int funmap_program_specific_entry_start;
+
+static FUNMAP default_funmap[] = {
+
+  { "abort", rl_abort },
+  { "accept-line", rl_newline },
+  { "arrow-key-prefix", rl_arrow_keys },
+  { "backward-char", rl_backward },
+  { "backward-delete-char", rl_rubout },
+  { "backward-kill-line", rl_backward_kill_line },
+  { "backward-kill-word", rl_backward_kill_word },
+  { "backward-word", rl_backward_word },
+  { "beginning-of-history", rl_beginning_of_history },
+  { "beginning-of-line", rl_beg_of_line },
+  { "call-last-kbd-macro", rl_call_last_kbd_macro },
+  { "capitalize-word", rl_capitalize_word },
+  { "clear-screen", rl_clear_screen },
+  { "complete", rl_complete },
+  { "delete-char", rl_delete },
+  { "delete-horizontal-space", rl_delete_horizontal_space },
+  { "digit-argument", rl_digit_argument },
+  { "do-lowercase-version", rl_do_lowercase_version },
+  { "downcase-word", rl_downcase_word },
+  { "dump-functions", rl_dump_functions },
+  { "emacs-editing-mode", rl_emacs_editing_mode },
+  { "end-kbd-macro", rl_end_kbd_macro },
+  { "end-of-history", rl_end_of_history },
+  { "end-of-line", rl_end_of_line },
+  { "forward-char", rl_forward },
+  { "forward-search-history", rl_forward_search_history },
+  { "forward-word", rl_forward_word },
+  { "history-search-backward", rl_history_search_backward },
+  { "history-search-forward", rl_history_search_forward },
+  { "insert-completions", rl_insert_completions },
+  { "kill-whole-line", rl_kill_full_line },
+  { "kill-line", rl_kill_line },
+  { "kill-word", rl_kill_word },
+  { "next-history", rl_get_next_history },
+  { "non-incremental-forward-search-history", rl_noninc_forward_search },
+  { "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 },
+  { "possible-completions", rl_possible_completions },
+  { "previous-history", rl_get_previous_history },
+  { "quoted-insert", rl_quoted_insert },
+  { "re-read-init-file", rl_re_read_init_file },
+  { "redraw-current-line", rl_refresh_line},
+  { "reverse-search-history", rl_reverse_search_history },
+  { "revert-line", rl_revert_line },
+  { "self-insert", rl_insert },
+  { "start-kbd-macro", rl_start_kbd_macro },
+  { "tab-insert", rl_tab_insert },
+  { "tilde-expand", rl_tilde_expand },
+  { "transpose-chars", rl_transpose_chars },
+  { "transpose-words", rl_transpose_words },
+  { "tty-status", rl_tty_status },
+  { "undo", rl_undo_command },
+  { "universal-argument", rl_universal_argument },
+  { "unix-line-discard", rl_unix_line_discard },
+  { "unix-word-rubout", rl_unix_word_rubout },
+  { "upcase-word", rl_upcase_word },
+  { "yank", rl_yank },
+  { "yank-last-arg", rl_yank_last_arg },
+  { "yank-nth-arg", rl_yank_nth_arg },
+  { "yank-pop", rl_yank_pop },
+
+#if defined (VI_MODE)
+  { "vi-append-eol", rl_vi_append_eol },
+  { "vi-append-mode", rl_vi_append_mode },
+  { "vi-arg-digit", rl_vi_arg_digit },
+  { "vi-bWord", rl_vi_bWord },
+  { "vi-bracktype", rl_vi_bracktype },
+  { "vi-bword", rl_vi_bword },
+  { "vi-change-case", rl_vi_change_case },
+  { "vi-change-char", rl_vi_change_char },
+  { "vi-change-to", rl_vi_change_to },
+  { "vi-char-search", rl_vi_char_search },
+  { "vi-column", rl_vi_column },
+  { "vi-comment", rl_vi_comment },
+  { "vi-complete", rl_vi_complete },
+  { "vi-delete", rl_vi_delete },
+  { "vi-delete-to", rl_vi_delete_to },
+  { "vi-eWord", rl_vi_eWord },
+  { "vi-editing-mode", rl_vi_editing_mode },
+  { "vi-end-word", rl_vi_end_word },
+  { "vi-eof-maybe", rl_vi_eof_maybe },
+  { "vi-eword", rl_vi_eword },
+  { "vi-fWord", rl_vi_fWord },
+  { "vi-first-print", rl_vi_first_print },
+  { "vi-fword", rl_vi_fword },
+  { "vi-insert-beg", rl_vi_insert_beg },
+  { "vi-insertion-mode", rl_vi_insertion_mode },
+  { "vi-match", rl_vi_match },
+  { "vi-movement-mode", rl_vi_movement_mode },
+  { "vi-next-word", rl_vi_next_word },
+  { "vi-overstrike", rl_vi_overstrike },
+  { "vi-overstrike-delete", rl_vi_overstrike_delete },
+  { "vi-prev-word", rl_vi_prev_word },
+  { "vi-put", rl_vi_put },
+  { "vi-redo", rl_vi_redo },
+  { "vi-replace", rl_vi_replace },
+  { "vi-search", rl_vi_search },
+  { "vi-search-again", rl_vi_search_again },
+  { "vi-subst", rl_vi_subst },
+  { "vi-tilde-expand", rl_vi_tilde_expand },
+  { "vi-yank-arg", rl_vi_yank_arg },
+  { "vi-yank-to", rl_vi_yank_to },
+#endif /* VI_MODE */
+
+ {(char *)NULL, (Function *)NULL }
+};
+
+rl_add_funmap_entry (name, function)
+     char *name;
+     Function *function;
+{
+  if (funmap_entry + 2 >= funmap_size)
+    if (!funmap)
+      funmap = (FUNMAP **)xmalloc ((funmap_size = 80) * sizeof (FUNMAP *));
+    else
+      funmap =
+       (FUNMAP **)xrealloc (funmap, (funmap_size += 80) * sizeof (FUNMAP *));
+  
+  funmap[funmap_entry] = (FUNMAP *)xmalloc (sizeof (FUNMAP));
+  funmap[funmap_entry]->name = name;
+  funmap[funmap_entry]->function = function;
+
+  funmap[++funmap_entry] = (FUNMAP *)NULL;
+  return funmap_entry;
+}
+
+static int funmap_initialized = 0;
+
+/* Make the funmap contain all of the default entries. */
+void
+rl_initialize_funmap ()
+{
+  register int i;
+
+  if (funmap_initialized)
+    return;
+
+  for (i = 0; default_funmap[i].name; i++)
+    rl_add_funmap_entry (default_funmap[i].name, default_funmap[i].function);
+
+  funmap_initialized = 1;
+  funmap_program_specific_entry_start = i;
+}
+
+/* Produce a NULL terminated array of known function names.  The array
+   is sorted.  The array itself is allocated, but not the strings inside.
+   You should free () the array when you done, but not the pointrs. */
+char **
+rl_funmap_names ()
+{
+  char **result = (char **)NULL;
+  int result_size, result_index;
+
+  result_size = result_index = 0;
+
+  /* Make sure that the function map has been initialized. */
+  rl_initialize_funmap ();
+
+  for (result_index = 0; funmap[result_index]; result_index++)
+    {
+      if (result_index + 2 > result_size)
+       {
+         if (!result)
+           result = (char **)xmalloc ((result_size = 20) * sizeof (char *));
+         else
+           result = (char **)
+             xrealloc (result, (result_size += 20) * sizeof (char *));
+       }
+
+      result[result_index] = funmap[result_index]->name;
+      result[result_index + 1] = (char *)NULL;
+    }
+
+  qsort (result, result_index, sizeof (char *), qsort_string_compare);
+  return (result);
+}
+
+/* Stupid comparison routine for qsort () ing strings. */
+static int
+qsort_string_compare (s1, s2)
+     register char **s1, **s2;
+{
+  int r;
+
+  r = **s1 - **s2;
+  if (r == 0)
+    r = strcmp (*s1, *s2);
+  return r;
+}
+
+/* Things that mean `Control'. */
+char *possible_control_prefixes[] = {
+  "Control-", "C-", "CTRL-", (char *)NULL
+};
+
+char *possible_meta_prefixes[] = {
+  "Meta", "M-", (char *)NULL
+};
+
+#if defined (STATIC_MALLOC)
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "history: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
diff --git a/lib/readline/history.c b/lib/readline/history.c
new file mode 100644 (file)
index 0000000..9172755
--- /dev/null
@@ -0,0 +1,2218 @@
+/* History.c -- standalone history library */
+
+/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+
+   This file contains the GNU History Library (the Library), a set of
+   routines for managing the text of previously typed lines.
+
+   The 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 1, or (at your option)
+   any later version.
+
+   The 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* The goal is to make the implementation transparent, so that you
+   don't have to know what data types are used, just what functions
+   you can call.  I think I have done that. */
+#define READLINE_LIBRARY
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+#include <errno.h>
+
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "memalloc.h"
+#include "history.h"
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+#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))
+
+#ifndef savestring
+#  ifndef strcpy
+extern char *strcpy ();
+#  endif
+#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
+#endif
+
+#ifndef whitespace
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#endif
+
+#ifndef digit_p
+#define digit_p(c)  ((c) >= '0' && (c) <= '9')
+#endif
+
+#ifndef digit_value
+#define digit_value(c) ((c) - '0')
+#endif
+
+#ifndef member
+#  ifndef strchr
+extern char *strchr ();
+#  endif
+#define member(c, s) ((c) ? ((char *)strchr ((s), (c)) != (char *)NULL) : 0)
+#endif
+
+/* Possible history errors passed to hist_error. */
+#define EVENT_NOT_FOUND 0
+#define BAD_WORD_SPEC  1
+#define SUBST_FAILED   2
+#define BAD_MODIFIER   3
+
+static char error_pointer;
+
+static char *subst_lhs;
+static char *subst_rhs;
+static int subst_lhs_len = 0;
+static int subst_rhs_len = 0;
+
+static char *get_history_word_specifier ();
+static char *history_find_word ();
+
+#if defined (SHELL)
+extern char *single_quote ();
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Functions                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* An array of HIST_ENTRY.  This is where we store the history. */
+static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
+
+/* Non-zero means that we have enforced a limit on the amount of
+   history that we save. */
+static int history_stifled = 0;
+
+/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
+   entries to remember. */
+int max_input_history;
+
+/* The current location of the interactive history pointer.  Just makes
+   life easier for outside callers. */
+static int history_offset = 0;
+
+/* The number of strings currently stored in the input_history list. */
+int history_length = 0;
+
+/* The current number of slots allocated to the input_history. */
+static int history_size = 0;
+
+/* The number of slots to increase the_history by. */
+#define DEFAULT_HISTORY_GROW_SIZE 50
+
+/* The character that represents the start of a history expansion
+   request.  This is usually `!'. */
+char history_expansion_char = '!';
+
+/* The character that invokes word substitution if found at the start of
+   a line.  This is usually `^'. */
+char history_subst_char = '^';
+
+/* During tokenization, if this character is seen as the first character
+   of a word, then it, and all subsequent characters upto a newline are
+   ignored.  For a Bourne shell, this should be '#'.  Bash special cases
+   the interactive comment character to not be a comment delimiter. */
+char history_comment_char = '\0';
+
+/* The list of characters which inhibit the expansion of text if found
+   immediately following history_expansion_char. */
+char *history_no_expand_chars = " \t\n\r=";
+
+/* The logical `base' of the history array.  It defaults to 1. */
+int history_base = 1;
+
+/* Return the current HISTORY_STATE of the history. */
+HISTORY_STATE *
+history_get_history_state ()
+{
+  HISTORY_STATE *state;
+
+  state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
+  state->entries = the_history;
+  state->offset = history_offset;
+  state->length = history_length;
+  state->size = history_size;
+  state->flags = 0;
+  if (history_stifled)
+    state->flags |= HS_STIFLED;
+
+  return (state);
+}
+
+/* Set the state of the current history array to STATE. */
+void
+history_set_history_state (state)
+     HISTORY_STATE *state;
+{
+  the_history = state->entries;
+  history_offset = state->offset;
+  history_length = state->length;
+  history_size = state->size;
+  if (state->flags & HS_STIFLED)
+    history_stifled = 1;
+}
+
+/* Begin a session in which the history functions might be used.  This
+   initializes interactive variables. */
+void
+using_history ()
+{
+  history_offset = history_length;
+}
+
+/* Return the number of bytes that the primary history entries are using.
+   This just adds up the lengths of the_history->lines. */
+int
+history_total_bytes ()
+{
+  register int i, result;
+
+  result = 0;
+
+  for (i = 0; the_history && the_history[i]; i++)
+    result += strlen (the_history[i]->line);
+
+  return (result);
+}
+
+/* Place STRING at the end of the history list.  The data field
+   is  set to NULL. */
+void
+add_history (string)
+     char *string;
+{
+  HIST_ENTRY *temp;
+
+  if (history_stifled && (history_length == max_input_history))
+    {
+      register int i;
+
+      /* If the history is stifled, and history_length is zero,
+        and it equals max_input_history, we don't save items. */
+      if (history_length == 0)
+       return;
+
+      /* If there is something in the slot, then remove it. */
+      if (the_history[0])
+       {
+         free (the_history[0]->line);
+         free (the_history[0]);
+       }
+
+      /* Copy the rest of the entries, moving down one slot. */
+      for (i = 0; i < history_length; i++)
+       the_history[i] = the_history[i + 1];
+
+      history_base++;
+
+    }
+  else
+    {
+      if (!history_size)
+       {
+         history_size = DEFAULT_HISTORY_GROW_SIZE;
+         the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
+         history_length = 1;
+
+       }
+      else
+       {
+         if (history_length == (history_size - 1))
+           {
+             history_size += DEFAULT_HISTORY_GROW_SIZE;
+             the_history = (HIST_ENTRY **)
+               xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
+           }
+         history_length++;
+       }
+    }
+
+  temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+  temp->line = savestring (string);
+  temp->data = (char *)NULL;
+
+  the_history[history_length] = (HIST_ENTRY *)NULL;
+  the_history[history_length - 1] = temp;
+}
+
+/* Make the history entry at WHICH have LINE and DATA.  This returns
+   the old entry so you can dispose of the data.  In the case of an
+   invalid WHICH, a NULL pointer is returned. */
+HIST_ENTRY *
+replace_history_entry (which, line, data)
+     int which;
+     char *line;
+     char *data;
+{
+  HIST_ENTRY *temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+  HIST_ENTRY *old_value;
+
+  if (which >= history_length)
+    return ((HIST_ENTRY *)NULL);
+
+  old_value = the_history[which];
+
+  temp->line = savestring (line);
+  temp->data = data;
+  the_history[which] = temp;
+
+  return (old_value);
+}
+
+/* Returns the magic number which says what history element we are
+   looking at now.  In this implementation, it returns history_offset. */
+int
+where_history ()
+{
+  return (history_offset);
+}
+
+/* Search the history for STRING, starting at history_offset.
+   If DIRECTION < 0, then the search is through previous entries, else
+   through subsequent.  If ANCHORED is non-zero, the string must
+   appear at the beginning of a history line, otherwise, the string
+   may appear anywhere in the line.  If the string is found, then
+   current_history () is the history entry, and the value of this
+   function is the offset in the line of that history entry that the
+   string was found in.  Otherwise, nothing is changed, and a -1 is
+   returned. */
+
+#define ANCHORED_SEARCH 1
+#define NON_ANCHORED_SEARCH 0
+
+static int
+history_search_internal (string, direction, anchored)
+     char *string;
+     int direction, anchored;
+{
+  register int i, reverse;
+  register char *line;
+  register int line_index;
+  int string_len;
+
+  i = history_offset;
+  reverse = (direction < 0);
+
+  /* Take care of trivial cases first. */
+  if (string == 0 || *string == '\0')
+    return (-1);
+
+  if (!history_length || ((i == history_length) && !reverse))
+    return (-1);
+
+  if (reverse && (i == history_length))
+    i--;
+
+#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0)
+
+  string_len = strlen (string);
+  while (1)
+    {
+      /* Search each line in the history list for STRING. */
+
+      /* At limit for direction? */
+      if ((reverse && i < 0) || (!reverse && i == history_length))
+       return (-1);
+
+      line = the_history[i]->line;
+      line_index = strlen (line);
+
+      /* If STRING is longer than line, no match. */
+      if (string_len > line_index)
+       {
+         NEXT_LINE ();
+         continue;
+       }
+
+      /* Handle anchored searches first. */
+      if (anchored == ANCHORED_SEARCH)
+       {
+         if (STREQN (string, line, string_len))
+           {
+             history_offset = i;
+             return (0);
+           }
+
+         NEXT_LINE ();
+         continue;
+       }
+
+      /* Do substring search. */
+      if (reverse)
+       {
+         line_index -= string_len;
+
+         while (line_index >= 0)
+           {
+             if (STREQN (string, line + line_index, string_len))
+               {
+                 history_offset = i;
+                 return (line_index);
+               }
+             line_index--;
+           }
+       }
+      else
+       {
+         register int limit = line_index - string_len + 1;
+         line_index = 0;
+
+         while (line_index < limit)
+           {
+             if (STREQN (string, line + line_index, string_len))
+               {
+                 history_offset = i;
+                 return (line_index);
+               }
+             line_index++;
+           }
+       }
+      NEXT_LINE ();
+    }
+}
+
+/* Do a non-anchored search for STRING through the history in DIRECTION. */
+int
+history_search (string, direction)
+     char *string;
+     int direction;
+{
+  return (history_search_internal (string, direction, NON_ANCHORED_SEARCH));
+}
+
+/* Do an anchored search for string through the history in DIRECTION. */
+int
+history_search_prefix (string, direction)
+     char *string;
+     int direction;
+{
+  return (history_search_internal (string, direction, ANCHORED_SEARCH));
+}
+
+/* Remove history element WHICH from the history.  The removed
+   element is returned to you so you can free the line, data,
+   and containing structure. */
+HIST_ENTRY *
+remove_history (which)
+     int which;
+{
+  HIST_ENTRY *return_value;
+
+  if (which >= history_length || !history_length)
+    return_value = (HIST_ENTRY *)NULL;
+  else
+    {
+      register int i;
+      return_value = the_history[which];
+
+      for (i = which; i < history_length; i++)
+       the_history[i] = the_history[i + 1];
+
+      history_length--;
+    }
+
+  return (return_value);
+}
+
+/* Stifle the history list, remembering only MAX number of lines. */
+void
+stifle_history (max)
+     int max;
+{
+  if (max < 0)
+    max = 0;
+
+  if (history_length > max)
+    {
+      register int i, j;
+
+      /* This loses because we cannot free the data. */
+      for (i = 0; i < (history_length - max); i++)
+       {
+         free (the_history[i]->line);
+         free (the_history[i]);
+       }
+
+      history_base = i;
+      for (j = 0, i = history_length - max; j < max; i++, j++)
+       the_history[j] = the_history[i];
+      the_history[j] = (HIST_ENTRY *)NULL;
+      history_length = j;
+    }
+
+  history_stifled = 1;
+  max_input_history = 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. */
+int
+unstifle_history ()
+{
+  int result = max_input_history;
+
+  if (history_stifled)
+    {
+      result = -result;
+      history_stifled = 0;
+    }
+
+  return (result);
+}
+
+int
+history_is_stifled ()
+{
+  return (history_stifled);
+}
+
+/* Return the string that should be used in the place of this
+   filename.  This only matters when you don't specify the
+   filename to read_history (), or write_history (). */
+static char *
+history_filename (filename)
+     char *filename;
+{
+  char *return_val = filename ? savestring (filename) : (char *)NULL;
+
+  if (!return_val)
+    {
+      char *home;
+      int home_len;
+
+      home = getenv ("HOME");
+
+      if (!home)
+       home = ".";
+
+      home_len = strlen (home);
+      /* strlen(".history") == 8 */
+      return_val = xmalloc (2 + home_len + 8);
+
+      strcpy (return_val, home);
+      return_val[home_len] = '/';
+      strcpy (return_val + home_len + 1, ".history");
+    }
+
+  return (return_val);
+}
+
+/* Add the contents of FILENAME to the history list, a line at a time.
+   If FILENAME is NULL, then read from ~/.history.  Returns 0 if
+   successful, or errno if not. */
+int
+read_history (filename)
+     char *filename;
+{
+  return (read_history_range (filename, 0, -1));
+}
+
+/* Read a range of lines from FILENAME, adding them to the history list.
+   Start reading at the FROM'th line and end at the TO'th.  If FROM
+   is zero, start at the beginning.  If TO is less than FROM, read
+   until the end of the file.  If FILENAME is NULL, then read from
+   ~/.history.  Returns 0 if successful, or errno if not. */
+int
+read_history_range (filename, from, to)
+     char *filename;
+     int from, to;
+{
+  register int line_start, line_end;
+  char *input, *buffer = (char *)NULL;
+  int file, current_line;
+  struct stat finfo;
+
+  input = history_filename (filename);
+  file = open (input, O_RDONLY, 0666);
+
+  if ((file < 0) || (fstat (file, &finfo) == -1))
+    goto error_and_exit;
+
+  buffer = xmalloc ((int)finfo.st_size + 1);
+
+  if (read (file, buffer, finfo.st_size) != finfo.st_size)
+    {
+  error_and_exit:
+      if (file >= 0)
+       close (file);
+
+      if (input)
+       free (input);
+
+      if (buffer)
+       free (buffer);
+
+      return (errno);
+    }
+
+  close (file);
+
+  /* Set TO to larger than end of file if negative. */
+  if (to < 0)
+    to = finfo.st_size;
+
+  /* Start at beginning of file, work to end. */
+  line_start = line_end = current_line = 0;
+
+  /* Skip lines until we are at FROM. */
+  while (line_start < finfo.st_size && current_line < from)
+    {
+      for (line_end = line_start; line_end < finfo.st_size; line_end++)
+       if (buffer[line_end] == '\n')
+         {
+           current_line++;
+           line_start = line_end + 1;
+           if (current_line == from)
+             break;
+         }
+    }
+
+  /* If there are lines left to gobble, then gobble them now. */
+  for (line_end = line_start; line_end < finfo.st_size; line_end++)
+    if (buffer[line_end] == '\n')
+      {
+       buffer[line_end] = '\0';
+
+       if (buffer[line_start])
+         add_history (buffer + line_start);
+
+       current_line++;
+
+       if (current_line >= to)
+         break;
+
+       line_start = line_end + 1;
+      }
+
+  if (input)
+    free (input);
+
+  if (buffer)
+    free (buffer);
+
+  return (0);
+}
+
+/* Truncate the history file FNAME, leaving only LINES trailing lines.
+   If FNAME is NULL, then use ~/.history. */
+int
+history_truncate_file (fname, lines)
+     char *fname;
+     register int lines;
+{
+  register int i;
+  int file, chars_read;
+  char *buffer = (char *)NULL, *filename;
+  struct stat finfo;
+
+  filename = history_filename (fname);
+  file = open (filename, O_RDONLY, 0666);
+
+  if (file == -1 || fstat (file, &finfo) == -1)
+    goto truncate_exit;
+
+  buffer = xmalloc ((int)finfo.st_size + 1);
+  chars_read = read (file, buffer, finfo.st_size);
+  close (file);
+
+  if (chars_read <= 0)
+    goto truncate_exit;
+
+  /* Count backwards from the end of buffer until we have passed
+     LINES lines. */
+  for (i = chars_read - 1; lines && i; i--)
+    {
+      if (buffer[i] == '\n')
+       lines--;
+    }
+
+  /* If this is the first line, then the file contains exactly the
+     number of lines we want to truncate to, so we don't need to do
+     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')
+      {
+       i++;
+       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, 0666)) != -1))
+    {
+      write (file, buffer + i, finfo.st_size - i);
+      close (file);
+    }
+
+ truncate_exit:
+  if (buffer)
+    free (buffer);
+
+  free (filename);
+  return 0;
+}
+
+#define HISTORY_APPEND 0
+#define HISTORY_OVERWRITE 1
+
+/* Workhorse function for writing history.  Writes NELEMENT entries
+   from the history list to FILENAME.  OVERWRITE is non-zero if you
+   wish to replace FILENAME with the entries. */
+static int
+history_do_write (filename, nelements, overwrite)
+     char *filename;
+     int nelements, overwrite;
+{
+  register int i;
+  char *output = history_filename (filename);
+  int file, mode;
+
+  mode = overwrite ? O_WRONLY | O_CREAT | O_TRUNC : O_WRONLY | O_APPEND;
+
+  if ((file = open (output, mode, 0666)) == -1)
+    {
+      if (output)
+       free (output);
+
+      return (errno);
+    }
+
+  if (nelements > history_length)
+    nelements = history_length;
+
+  /* Build a buffer of all the lines to write, and write them in one syscall.
+     Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
+  {
+    register int j = 0;
+    int buffer_size = 0;
+    char *buffer;
+
+    /* Calculate the total number of bytes to write. */
+    for (i = history_length - nelements; i < history_length; i++)
+      buffer_size += 1 + strlen (the_history[i]->line);
+
+    /* Allocate the buffer, and fill it. */
+    buffer = xmalloc (buffer_size);
+
+    for (i = history_length - nelements; i < history_length; i++)
+      {
+       strcpy (buffer + j, the_history[i]->line);
+       j += strlen (the_history[i]->line);
+       buffer[j++] = '\n';
+      }
+
+    write (file, buffer, buffer_size);
+    free (buffer);
+  }
+
+  close (file);
+
+  if (output)
+    free (output);
+
+  return (0);
+}
+
+/* Append NELEMENT entries to FILENAME.  The entries appended are from
+   the end of the list minus NELEMENTs up to the end of the list. */
+int
+append_history (nelements, filename)
+     int nelements;
+     char *filename;
+{
+  return (history_do_write (filename, nelements, HISTORY_APPEND));
+}
+
+/* Overwrite FILENAME with the current history.  If FILENAME is NULL,
+   then write the history list to ~/.history.  Values returned
+   are as in read_history ().*/
+int
+write_history (filename)
+     char *filename;
+{
+  return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
+}
+
+/* Return the history entry at the current position, as determined by
+   history_offset.  If there is no entry there, return a NULL pointer. */
+HIST_ENTRY *
+current_history ()
+{
+  if ((history_offset == history_length) || !the_history)
+    return ((HIST_ENTRY *)NULL);
+  else
+    return (the_history[history_offset]);
+}
+
+/* Back up history_offset to the previous history entry, and return
+   a pointer to that entry.  If there is no previous entry then return
+   a NULL pointer. */
+HIST_ENTRY *
+previous_history ()
+{
+  if (!history_offset)
+    return ((HIST_ENTRY *)NULL);
+  else
+    return (the_history[--history_offset]);
+}
+
+/* Move history_offset forward to the next history entry, and return
+   a pointer to that entry.  If there is no next entry then return a
+   NULL pointer. */
+HIST_ENTRY *
+next_history ()
+{
+  if (history_offset == history_length)
+    return ((HIST_ENTRY *)NULL);
+  else
+    return (the_history[++history_offset]);
+}
+
+/* Return the current history array.  The caller has to be carefull, since this
+   is the actual array of data, and could be bashed or made corrupt easily.
+   The array is terminated with a NULL pointer. */
+HIST_ENTRY **
+history_list ()
+{
+  return (the_history);
+}
+
+/* Return the history entry which is logically at OFFSET in the history array.
+   OFFSET is relative to history_base. */
+HIST_ENTRY *
+history_get (offset)
+     int offset;
+{
+  int local_index = offset - history_base;
+
+  if (local_index >= history_length ||
+      local_index < 0 ||
+      !the_history)
+    return ((HIST_ENTRY *)NULL);
+  return (the_history[local_index]);
+}
+
+/* Search for STRING in the history list.  DIR is < 0 for searching
+   backwards.  POS is an absolute index into the history list at
+   which point to begin searching. */
+int
+history_search_pos (string, dir, pos)
+     char *string;
+     int dir, pos;
+{
+  int ret, old = where_history ();
+  history_set_pos (pos);
+  if (history_search (string, dir) == -1)
+    {
+      history_set_pos (old);
+      return (-1);
+    }
+  ret = where_history ();
+  history_set_pos (old);
+  return ret;
+}
+
+/* Make the current history item be the one at POS, an absolute index.
+   Returns zero if POS is out of range, else non-zero. */
+int
+history_set_pos (pos)
+     int pos;
+{
+  if (pos > history_length || pos < 0 || !the_history)
+    return (0);
+  history_offset = pos;
+  return (1);
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Expansion                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Hairy history expansion on text, not tokens.  This is of general
+   use, and thus belongs in this library. */
+
+/* The last string searched for in a !?string? search. */
+static char *search_string = (char *)NULL;
+
+/* The last string matched by a !?string? search. */
+static char *search_match = (char *)NULL;
+
+/* Return the event specified at TEXT + OFFSET modifying OFFSET to
+   point to after the event specifier.  Just a pointer to the history
+   line is returned; NULL is returned in the event of a bad specifier.
+   You pass STRING with *INDEX equal to the history_expansion_char that
+   begins this specification.
+   DELIMITING_QUOTE is a character that is allowed to end the string
+   specification for what to search for in addition to the normal
+   characters `:', ` ', `\t', `\n', and sometimes `?'.
+   So you might call this function like:
+   line = get_history_event ("!echo:p", &index, 0);  */
+char *
+get_history_event (string, caller_index, delimiting_quote)
+     char *string;
+     int *caller_index;
+     int delimiting_quote;
+{
+  register int i = *caller_index;
+  register char c;
+  HIST_ENTRY *entry;
+  int which, sign = 1;
+  int local_index, search_mode, substring_okay = 0;
+  char *temp;
+
+  /* The event can be specified in a number of ways.
+
+     !!   the previous command
+     !n   command line N
+     !-n  current command-line minus N
+     !str the most recent command starting with STR
+     !?str[?]
+         the most recent command containing STR
+
+     All values N are determined via HISTORY_BASE. */
+
+  if (string[i] != history_expansion_char)
+    return ((char *)NULL);
+
+  /* Move on to the specification. */
+  i++;
+
+#define RETURN_ENTRY(e, w) \
+       return ((e = history_get (w)) ? e->line : (char *)NULL)
+
+  /* Handle !! case. */
+  if (string[i] == history_expansion_char)
+    {
+      i++;
+      which = history_base + (history_length - 1);
+      *caller_index = i;
+      RETURN_ENTRY (entry, which);
+    }
+
+  /* Hack case of numeric line specification. */
+  if (string[i] == '-')
+    {
+      sign = -1;
+      i++;
+    }
+
+  if (digit_p (string[i]))
+    {
+      /* Get the extent of the digits and compute the value. */
+      for (which = 0; digit_p (string[i]); i++)
+       which = (which * 10) + digit_value (string[i]);
+
+      *caller_index = i;
+
+      if (sign < 0)
+       which = (history_length + history_base) - which;
+
+      RETURN_ENTRY (entry, which);
+    }
+
+  /* This must be something to search for.  If the spec begins with
+     a '?', then the string may be anywhere on the line.  Otherwise,
+     the string must be found at the start of a line. */
+  if (string[i] == '?')
+    {
+      substring_okay++;
+      i++;
+    }
+
+  /* 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 == ':' ||
+#if defined (SHELL)
+         member (c, ";&()|<>") ||
+#endif /* SHELL */
+         string[i] == delimiting_quote)) ||
+       string[i] == '\n' ||
+       (substring_okay && string[i] == '?'))
+      break;
+
+  temp = xmalloc (1 + (i - local_index));
+  strncpy (temp, &string[local_index], (i - local_index));
+  temp[i - local_index] = '\0';
+
+  if (substring_okay && string[i] == '?')
+    i++;
+
+  *caller_index = i;
+
+#define FAIL_SEARCH() \
+  do { history_offset = history_length; free (temp) ; return (char *)NULL; } while (0)
+
+  search_mode = substring_okay ? NON_ANCHORED_SEARCH : ANCHORED_SEARCH;
+  while (1)
+    {
+      local_index = history_search_internal (temp, -1, search_mode);
+
+      if (local_index < 0)
+       FAIL_SEARCH ();
+
+      if (local_index == 0 || substring_okay)
+       {
+         entry = current_history ();
+         history_offset = history_length;
+       
+         /* If this was a substring search, then remember the
+            string that we matched for word substitution. */
+         if (substring_okay)
+           {
+             if (search_string)
+               free (search_string);
+             search_string = temp;
+
+             if (search_match)
+               free (search_match);
+             search_match = history_find_word (entry->line, local_index);
+           }
+         else
+           free (temp);
+         return (entry->line);
+       }
+
+      if (history_offset)
+       history_offset--;
+      else
+       FAIL_SEARCH ();
+    }
+#undef FAIL_SEARCH
+#undef RETURN_ENTRY
+}
+#if defined (SHELL)
+/* Function for extracting single-quoted strings.  Used for inhibiting
+   history expansion within single quotes. */
+
+/* Extract the contents of STRING as if it is enclosed in single quotes.
+   SINDEX, when passed in, is the offset of the character immediately
+   following the opening single quote; on exit, SINDEX is left pointing
+   to the closing single quote. */
+static void
+rl_string_extract_single_quoted (string, sindex)
+     char *string;
+     int *sindex;
+{
+  register int i = *sindex;
+
+  while (string[i] && string[i] != '\'')
+    i++;
+
+  *sindex = i;
+}
+
+static char *
+quote_breaks (s)
+     char *s;
+{
+  register char *p, *r;
+  char *ret;
+  int len = 3;
+
+  for (p = s; p && *p; p++, len++)
+    {
+      if (*p == '\'')
+       len += 3;
+      else if (whitespace (*p) || *p == '\n')
+       len += 2;
+    }
+
+  r = ret = xmalloc (len);
+  *r++ = '\'';
+  for (p = s; p && *p; )
+    {
+      if (*p == '\'')
+       {
+         *r++ = '\'';
+         *r++ = '\\';
+         *r++ = '\'';
+         *r++ = '\'';
+         p++;
+       }
+      else if (whitespace (*p) || *p == '\n')
+       {
+         *r++ = '\'';
+         *r++ = *p++;
+         *r++ = '\'';
+       }
+      else
+       *r++ = *p++;
+    }
+  *r++ = '\'';
+  *r = '\0';
+  return ret;
+}
+#endif /* SHELL */
+
+static char *
+hist_error(s, start, current, errtype)
+      char *s;
+      int start, current, errtype;
+{
+  char *temp, *emsg;
+  int ll, elen;
+
+  ll = current - start;
+
+  switch (errtype)
+    {
+    case EVENT_NOT_FOUND:
+      emsg = "event not found";
+      elen = 15;
+      break;
+    case BAD_WORD_SPEC:
+      emsg = "bad word specifier";
+      elen = 18;
+      break;
+    case SUBST_FAILED:
+      emsg = "substitution failed";
+      elen = 19;
+      break;
+    case BAD_MODIFIER:
+      emsg = "unrecognized history modifier";
+      elen = 29;
+      break;
+    default:
+      emsg = "unknown expansion error";
+      elen = 23;
+      break;
+    }
+
+  temp = xmalloc (ll + elen + 3);
+  strncpy (temp, s + start, ll);
+  temp[ll] = ':';
+  temp[ll + 1] = ' ';
+  strcpy (temp + ll + 2, emsg);
+  return (temp);
+}
+
+/* Get a history substitution string from STR starting at *IPTR
+   and return it.  The length is returned in LENPTR.
+
+   A backslash can quote the delimiter.  If the string is the
+   empty string, the previous pattern is used.  If there is
+   no previous pattern for the lhs, the last history search
+   string is used.
+
+   If IS_RHS is 1, we ignore empty strings and set the pattern
+   to "" anyway.  subst_lhs is not changed if the lhs is empty;
+   subst_rhs is allowed to be set to the empty string. */
+
+static char *
+get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr)
+     char *str;
+     int *iptr, delimiter, is_rhs, *lenptr;
+{
+  register int si, i, j, k;
+  char *s = (char *) NULL;
+
+  i = *iptr;
+
+  for (si = i; str[si] && str[si] != delimiter; si++)
+    if (str[si] == '\\' && str[si + 1] == delimiter)
+      si++;
+
+  if (si > i || is_rhs)
+    {
+      s = xmalloc (si - i + 1);
+      for (j = 0, k = i; k < si; j++, k++)
+       {
+         /* Remove a backslash quoting the search string delimiter. */
+         if (str[k] == '\\' && str[k + 1] == delimiter)
+           k++;
+         s[j] = str[k];
+       }
+      s[j] = '\0';
+      if (lenptr)
+        *lenptr = j;
+    }
+
+  i = si;
+  if (str[i])
+    i++;
+  *iptr = i;
+
+  return s;
+}
+
+static void
+postproc_subst_rhs ()
+{
+  char *new;
+  int i, j, new_size;
+
+  new = xmalloc (new_size = subst_rhs_len + subst_lhs_len);
+  for (i = j = 0; i < subst_rhs_len; i++)
+    {
+      if (subst_rhs[i] == '&')
+       {
+         if (j + subst_lhs_len >= new_size)
+           new = xrealloc (new, (new_size = new_size * 2 + subst_lhs_len));
+         strcpy (new + j, subst_lhs);
+         j += subst_lhs_len;
+       }
+      else
+       {
+         /* a single backslash protects the `&' from lhs interpolation */
+         if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&')
+           i++;
+         if (j >= new_size)
+           new = xrealloc (new, new_size *= 2);
+         new[j++] = subst_rhs[i];
+       }
+    }
+  new[j] = '\0';
+  free (subst_rhs);
+  subst_rhs = new;
+  subst_rhs_len = j;
+}
+
+/* Expand the bulk of a history specifier starting at STRING[START].
+   Returns 0 if everything is OK, -1 if an error occurred, and 1
+   if the `p' modifier was supplied and the caller should just print
+   the returned string.  Returns the new index into string in
+   *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
+static int
+history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
+     char *string;
+     int start, *end_index_ptr;
+     char **ret_string;
+     char *current_line;       /* for !# */
+{
+  int i, n, starting_index;
+  int substitute_globally, want_quotes, print_only;
+  char *event, *temp, *result, *tstr, *t, c, *word_spec;
+  int result_len;
+
+  result = xmalloc (result_len = 128);
+
+  i = start;
+
+  /* If it is followed by something that starts a word specifier,
+     then !! is implied as the event specifier. */
+
+  if (member (string[i + 1], ":$*%^"))
+    {
+      char fake_s[3];
+      int fake_i = 0;
+      i++;
+      fake_s[0] = fake_s[1] = history_expansion_char;
+      fake_s[2] = '\0';
+      event = get_history_event (fake_s, &fake_i, 0);
+    }
+  else if (string[i + 1] == '#')
+    {
+      i += 2;
+      event = current_line;
+    }
+  else
+    {
+      int quoted_search_delimiter = 0;
+
+      /* If the character before this `!' is a double or single
+        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];
+      event = get_history_event (string, &i, quoted_search_delimiter);
+    }
+         
+  if (!event)
+    {
+      *ret_string = hist_error (string, start, i, EVENT_NOT_FOUND);
+      free (result);
+      return (-1);
+    }
+
+  /* If a word specifier is found, then do what that requires. */
+  starting_index = i;
+  word_spec = get_history_word_specifier (string, event, &i);
+
+  /* There is no such thing as a `malformed word specifier'.  However,
+     it is possible for a specifier that has no match.  In that case,
+     we complain. */
+  if (word_spec == (char *)&error_pointer)
+    {
+      *ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC);
+      free (result);
+      return (-1);
+    }
+
+  /* If no word specifier, than the thing of interest was the event. */
+  if (!word_spec)
+    temp = savestring (event);
+  else
+    {
+      temp = savestring (word_spec);
+      free (word_spec);
+    }
+
+  /* Perhaps there are other modifiers involved.  Do what they say. */
+  want_quotes = substitute_globally = print_only = 0;
+  starting_index = i;
+
+  while (string[i] == ':')
+    {
+      c = string[i + 1];
+
+      if (c == 'g')
+       {
+         substitute_globally = 1;
+         i++;
+         c = string[i + 1];
+       }
+
+      switch (c)
+       {
+       default:
+         *ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER);
+         free (result);
+         free (temp);
+         return -1;
+
+#if defined (SHELL)
+       case 'q':
+         want_quotes = 'q';
+         break;
+
+       case 'x':
+         want_quotes = 'x';
+         break;
+#endif /* SHELL */
+
+         /* :p means make this the last executed line.  So we
+            return an error state after adding this line to the
+            history. */
+       case 'p':
+         print_only++;
+         break;
+
+         /* :t discards all but the last part of the pathname. */
+       case 't':
+         tstr = strrchr (temp, '/');
+         if (tstr)
+           {
+             tstr++;
+             t = savestring (tstr);
+             free (temp);
+             temp = t;
+           }
+         break;
+
+         /* :h discards the last part of a pathname. */
+       case 'h':
+         tstr = strrchr (temp, '/');
+         if (tstr)
+           *tstr = '\0';
+         break;
+
+         /* :r discards the suffix. */
+       case 'r':
+         tstr = strrchr (temp, '.');
+         if (tstr)
+           *tstr = '\0';
+         break;
+
+         /* :e discards everything but the suffix. */
+       case 'e':
+         tstr = strrchr (temp, '.');
+         if (tstr)
+           {
+             t = savestring (tstr);
+             free (temp);
+             temp = t;
+           }
+         break;
+
+       /* :s/this/that substitutes `that' for the first
+          occurrence of `this'.  :gs/this/that substitutes `that'
+          for each occurrence of `this'.  :& repeats the last
+          substitution.  :g& repeats the last substitution
+          globally. */
+
+       case '&':
+       case 's':
+         {
+           char *new_event, *t;
+           int delimiter, failed, si, l_temp;
+
+           if (c == 's')
+             {
+               if (i + 2 < (int)strlen (string))
+                 delimiter = string[i + 2];
+               else
+                 break;        /* no search delimiter */
+
+               i += 3;
+
+               t = get_subst_pattern (string, &i, delimiter, 0, &subst_lhs_len);
+               /* An empty substitution lhs with no previous substitution
+                  uses the last search string as the lhs. */
+               if (t)
+                 {
+                   if (subst_lhs)
+                     free (subst_lhs);
+                   subst_lhs = t;
+                 }
+               else if (!subst_lhs)
+                 {
+                   if (search_string && *search_string)
+                     {
+                       subst_lhs = savestring (search_string);
+                       subst_lhs_len = strlen (subst_lhs);
+                     }
+                   else
+                     {
+                       subst_lhs = (char *) NULL;
+                       subst_lhs_len = 0;
+                     }
+                 }
+
+               /* If there is no lhs, the substitution can't succeed. */
+               if (subst_lhs_len == 0)
+                 {
+                   *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
+                   free (result);
+                   free (temp);
+                   return -1;
+                 }
+
+               if (subst_rhs)
+                 free (subst_rhs);
+               subst_rhs = get_subst_pattern (string, &i, delimiter, 1, &subst_rhs_len);
+
+               /* If `&' appears in the rhs, it's supposed to be replaced
+                  with the lhs. */
+               if (member ('&', subst_rhs))
+                 postproc_subst_rhs ();
+             }
+           else
+             i += 2;
+
+           l_temp = strlen (temp);
+           /* Ignore impossible cases. */
+           if (subst_lhs_len > l_temp)
+             {
+               *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
+               free (result);
+               free (temp);
+               return (-1);
+             }
+
+           /* Find the first occurrence of THIS in TEMP. */
+           si = 0;
+           for (failed = 1; (si + subst_lhs_len) <= l_temp; si++)
+             if (STREQN (temp+si, subst_lhs, subst_lhs_len))
+               {
+                 int len = subst_rhs_len - subst_lhs_len + l_temp;
+                 new_event = xmalloc (1 + len);
+                 strncpy (new_event, temp, si);
+                 strncpy (new_event + si, subst_rhs, subst_rhs_len);
+                 strncpy (new_event + si + subst_rhs_len,
+                          temp + si + subst_lhs_len,
+                          l_temp - (si + subst_lhs_len));
+                 new_event[len] = '\0';
+                 free (temp);
+                 temp = new_event;
+
+                 failed = 0;
+
+                 if (substitute_globally)
+                   {
+                     si += subst_rhs_len;
+                     l_temp = strlen (temp);
+                     substitute_globally++;
+                     continue;
+                   }
+                 else
+                   break;
+               }
+
+           if (substitute_globally > 1)
+             {
+               substitute_globally = 0;
+               continue;       /* don't want to increment i */
+             }
+
+           if (failed == 0)
+             continue;         /* don't want to increment i */
+
+           *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
+           free (result);
+           free (temp);
+           return (-1);
+         }
+       }
+      i += 2;
+    }
+  /* Done with modfiers. */
+  /* Believe it or not, we have to back the pointer up by one. */
+  --i;
+
+#if defined (SHELL)
+  if (want_quotes)
+    {
+      char *x;
+
+      if (want_quotes == 'q')
+       x = single_quote (temp);
+      else if (want_quotes == 'x')
+       x = quote_breaks (temp);
+      else
+       x = savestring (temp);
+
+      free (temp);
+      temp = x;
+    }
+#endif /* SHELL */
+
+  n = strlen (temp);
+  if (n > result_len)
+    result = xrealloc (result, n + 2);
+  strcpy (result, temp);
+  free (temp);
+
+  *end_index_ptr = i;
+  *ret_string = result;
+  return (print_only);
+}
+
+/* Expand the string STRING, placing the result into OUTPUT, a pointer
+   to a string.  Returns:
+
+  -1) If there was an error in expansion.
+   0) If no expansions took place (or, if the only change in
+      the text was the de-slashifying of the history expansion
+      character)
+   1) If expansions did take place
+   2) If the `p' modifier was given and the caller should print the result
+
+  If an error ocurred in expansion, then OUTPUT contains a descriptive
+  error message. */
+
+#define ADD_STRING(s) \
+       do \
+         { \
+           int sl = strlen (s); \
+           j += sl; \
+           if (j >= result_len) \
+             { \
+               while (j >= result_len) \
+                 result_len += 128; \
+               result = xrealloc (result, result_len); \
+             } \
+           strcpy (result + j - sl, s); \
+         } \
+       while (0)
+
+#define ADD_CHAR(c) \
+       do \
+         { \
+           if (j >= result_len - 1) \
+             result = xrealloc (result, result_len += 64); \
+           result[j++] = c; \
+           result[j] = '\0'; \
+         } \
+       while (0)
+
+int
+history_expand (hstring, output)
+     char *hstring;
+     char **output;
+{
+  register int j;
+  int i, r, l, passc, cc, modified, eindex, only_printing;
+  char *string;
+
+  /* The output string, and its length. */
+  int result_len;
+  char *result;
+
+  /* Used when adding the string. */
+  char *temp;
+
+  /* Setting the history expansion character to 0 inhibits all
+     history expansion. */
+  if (history_expansion_char == 0)
+    {
+      *output = savestring (hstring);
+      return (0);
+    }
+    
+  /* Prepare the buffer for printing error messages. */
+  result = xmalloc (result_len = 256);
+  result[0] = '\0';
+
+  only_printing = modified = 0;
+  l = strlen (hstring);
+
+  /* Grovel the string.  Only backslash can quote the history escape
+     character.  We also handle arg specifiers. */
+
+  /* Before we grovel forever, see if the history_expansion_char appears
+     anywhere within the text. */
+
+  /* The quick substitution character is a history expansion all right.  That
+     is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
+     that is the substitution that we do. */
+  if (hstring[0] == history_subst_char)
+    {
+      string = xmalloc (l + 5);
+
+      string[0] = string[1] = history_expansion_char;
+      string[2] = ':';
+      string[3] = 's';
+      strcpy (string + 4, hstring);
+      l += 4;
+    }
+  else
+    {
+      string = hstring;
+      /* If not quick substitution, still maybe have to do expansion. */
+
+      /* `!' followed by one of the characters in history_no_expand_chars
+        is NOT an expansion. */
+      for (i = 0; string[i]; i++)
+       {
+         cc = string[i + 1];
+          if (string[i] == history_expansion_char)
+           {
+             if (!cc || member (cc, history_no_expand_chars))
+               continue;
+#if defined (SHELL)
+             /* The shell uses ! as a pattern negation character
+                in globbing [...] expressions, so let those pass
+                without expansion. */
+             else if (i > 0 && (string[i - 1] == '[') &&
+                      member (']', string + i + 1))
+               continue;
+#endif /* SHELL */
+             else
+               break;
+           }
+#if defined (SHELL)
+         else if (string[i] == '\'')
+           {
+             /* If this is bash, single quotes inhibit history expansion. */
+             i++;
+             rl_string_extract_single_quoted (string, &i);
+           }
+         else if (string[i] == '\\')
+           {
+             /* If this is bash, allow backslashes to quote single
+                quotes and
+                the history expansion character. */
+             if (cc == '\'' || cc == history_expansion_char)
+               i++;
+           }
+#endif /* SHELL */
+       }
+         
+      if (string[i] != history_expansion_char)
+       {
+         free (result);
+         *output = savestring (string);
+         return (0);
+       }
+    }
+
+  /* Extract and perform the substitution. */
+  for (passc = i = j = 0; i < l; i++)
+    {
+      int tchar = string[i];
+
+      if (passc)
+       {
+         passc = 0;
+         ADD_CHAR (tchar);
+         continue;
+       }
+
+      if (tchar == history_expansion_char)
+       tchar = -3;
+
+      switch (tchar)
+       {
+       default:
+         ADD_CHAR (string[i]);
+         break;
+
+       case '\\':
+         passc++;
+         ADD_CHAR (tchar);
+         break;
+
+#if defined (SHELL)
+       case '\'':
+         {
+           /* If this is bash, single quotes inhibit history expansion. */
+           int quote, slen;
+
+           quote = i++;
+           rl_string_extract_single_quoted (string, &i);
+
+           slen = i - quote + 2;
+           temp = xmalloc (slen);
+           strncpy (temp, string + quote, slen);
+           temp[slen - 1] = '\0';
+           ADD_STRING (temp);
+           free (temp);
+           break;
+         }
+#endif /* SHELL */
+
+       case -3:                /* history_expansion_char */
+         cc = string[i + 1];
+
+         /* If the history_expansion_char is followed by one of the
+            characters in history_no_expand_chars, then it is not a
+            candidate for expansion of any kind. */
+         if (member (cc, history_no_expand_chars))
+           {
+             ADD_CHAR (string[i]);
+             break;
+           }
+
+#if defined (NO_BANG_HASH_MODIFIERS)
+         /* There is something that is listed as a `word specifier' in csh
+            documentation which means `the expanded text to this point'.
+            That is not a word specifier, it is an event specifier.  If we
+            don't want to allow modifiers with `!#', just stick the current
+            output line in again. */
+         if (cc == '#')
+           {
+             if (result)
+               {
+                 temp = xmalloc (1 + strlen (result));
+                 strcpy (temp, result);
+                 ADD_STRING (temp);
+                 free (temp);
+               }
+             i++;
+             break;
+           }
+#endif
+
+         r = history_expand_internal (string, i, &eindex, &temp, result);
+         if (r < 0)
+           {
+             *output = temp;
+             free (result);
+             if (string != hstring)
+               free (string);
+             return -1;
+           }
+         else
+           {
+             if (temp)
+               {
+                 modified++;
+                 if (*temp)
+                   ADD_STRING (temp);
+                 free (temp);
+               }
+             only_printing = r == 1;
+             i = eindex;
+           }
+         break;
+       }
+    }
+
+  *output = result;
+  if (string != hstring)
+    free (string);
+
+  if (only_printing)
+    {
+      add_history (result);
+      return (2);
+    }
+
+  return (modified != 0);
+}
+
+/* Return a consed string which is the word specified in SPEC, and found
+   in FROM.  NULL is returned if there is no spec.  The address of
+   ERROR_POINTER is returned if the word specified cannot be found.
+   CALLER_INDEX is the offset in SPEC to start looking; it is updated
+   to point to just after the last character parsed. */
+static char *
+get_history_word_specifier (spec, from, caller_index)
+     char *spec, *from;
+     int *caller_index;
+{
+  register int i = *caller_index;
+  int first, last;
+  int expecting_word_spec = 0;
+  char *result;
+
+  /* The range of words to return doesn't exist yet. */
+  first = last = 0;
+  result = (char *)NULL;
+
+  /* If we found a colon, then this *must* be a word specification.  If
+     it isn't, then it is an error. */
+  if (spec[i] == ':')
+    {
+      i++;
+      expecting_word_spec++;
+    }
+
+  /* Handle special cases first. */
+
+  /* `%' is the word last searched for. */
+  if (spec[i] == '%')
+    {
+      *caller_index = i + 1;
+      return (search_match ? savestring (search_match) : savestring (""));
+    }
+
+  /* `*' matches all of the arguments, but not the command. */
+  if (spec[i] == '*')
+    {
+      *caller_index = i + 1;
+      result = history_arg_extract (1, '$', from);
+      return (result ? result : savestring (""));
+    }
+
+  /* `$' is last arg. */
+  if (spec[i] == '$')
+    {
+      *caller_index = i + 1;
+      return (history_arg_extract ('$', '$', from));
+    }
+
+  /* Try to get FIRST and LAST figured out. */
+
+  if (spec[i] == '-')
+    first = 0;
+  else if (spec[i] == '^')
+    first = 1;
+  else if (digit_p (spec[i]) && expecting_word_spec)
+    {
+      for (first = 0; digit_p (spec[i]); i++)
+       first = (first * 10) + digit_value (spec[i]);
+    }
+  else
+    return ((char *)NULL);     /* no valid `first' for word specifier */
+
+  if (spec[i] == '^' || spec[i] == '*')
+    {
+      last = (spec[i] == '^') ? 1 : '$';       /* x* abbreviates x-$ */
+      i++;
+    }
+  else if (spec[i] != '-')
+    last = first;
+  else
+    {
+      i++;
+
+      if (digit_p (spec[i]))
+       {
+         for (last = 0; digit_p (spec[i]); i++)
+           last = (last * 10) + digit_value (spec[i]);
+       }
+      else if (spec[i] == '$')
+       {
+         i++;
+         last = '$';
+       }
+      else if (!spec[i] || spec[i] == ':')  /* could be modifier separator */
+       last = -1;              /* x- abbreviates x-$ omitting word `$' */
+    }
+
+  *caller_index = i;
+
+  if (last >= first || last == '$' || last < 0)
+    result = history_arg_extract (first, last, from);
+
+  return (result ? result : (char *)&error_pointer);
+}
+
+/* Extract the args specified, starting at FIRST, and ending at LAST.
+   The args are taken from STRING.  If either FIRST or LAST is < 0,
+   then make that arg count from the right (subtract from the number of
+   tokens, so that FIRST = -1 means the next to last token on the line).
+   If LAST is `$' the last arg from STRING is used. */
+char *
+history_arg_extract (first, last, string)
+     int first, last;
+     char *string;
+{
+  register int i, len;
+  char *result = (char *)NULL;
+  int size = 0, offset = 0;
+  char **list;
+
+  /* XXX - think about making history_tokenize return a struct array,
+     each struct in array being a string and a length to avoid the
+     calls to strlen below. */
+  if ((list = history_tokenize (string)) == NULL)
+    return ((char *)NULL);
+
+  for (len = 0; list[len]; len++)
+    ;
+
+  if (last < 0)
+    last = len + last - 1;
+
+  if (first < 0)
+    first = len + first - 1;
+
+  if (last == '$')
+    last = len - 1;
+
+  if (first == '$')
+    first = len - 1;
+
+  last++;
+
+  if (first >= len || last > len || first < 0 || last < 0 || first > last)
+    result = ((char *)NULL);
+  else
+    {
+      for (size = 0, i = first; i < last; i++)
+       size += strlen (list[i]) + 1;
+      result = xmalloc (size + 1);
+      result[0] = '\0';
+
+      for (i = first; i < last; i++)
+       {
+         strcpy (result + offset, list[i]);
+         offset += strlen (list[i]);
+         if (i + 1 < last)
+           {
+             result[offset++] = ' ';
+             result[offset] = 0;
+           }
+       }
+    }
+
+  for (i = 0; i < len; i++)
+    free (list[i]);
+  free (list);
+
+  return (result);
+}
+
+#define slashify_in_quotes "\\`\"$"
+
+/* Parse STRING into tokens and return an array of strings.  If WIND is
+   not -1 and INDP is not null, we also want the word surrounding index
+   WIND.  The position in the returned array of strings is returned in
+   *INDP. */
+static char **
+history_tokenize_internal (string, wind, indp)
+     char *string;
+     int wind, *indp;
+{
+  char **result = (char **)NULL;
+  register int i, start, result_index, size;
+  int len;
+
+  i = result_index = size = 0;
+
+  /* Get a token, and stuff it into RESULT.  The tokens are split
+     exactly where the shell would split them. */
+  while (string[i])
+    {
+      int delimiter = 0;
+
+      /* Skip leading whitespace. */
+      for (; string[i] && whitespace (string[i]); i++)
+       ;
+      if (!string[i] || string[i] == history_comment_char)
+       return (result);
+
+      start = i;
+      
+      if (member (string[i], "()\n"))
+       {
+         i++;
+         goto got_token;
+       }
+
+      if (member (string[i], "<>;&|$"))
+       {
+         int peek = string[i + 1];
+
+         if (peek == string[i] && peek != '$')
+           {
+             if (peek == '<' && string[i + 2] == '-')
+               i++;
+             i += 2;
+             goto got_token;
+           }
+         else
+           {
+             if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
+                 ((peek == '>') && (string[i] == '&')) ||
+                 ((peek == '(') && (string[i] == '$')))
+               {
+                 i += 2;
+                 goto got_token;
+               }
+           }
+         if (string[i] != '$')
+           {
+             i++;
+             goto got_token;
+           }
+       }
+
+      /* Get word from string + i; */
+
+      if (member (string[i], "\"'`"))
+       delimiter = string[i++];
+
+      for (; string[i]; i++)
+       {
+         if (string[i] == '\\' && string[i + 1] == '\n')
+           {
+             i++;
+             continue;
+           }
+
+         if (string[i] == '\\' && delimiter != '\'' &&
+             (delimiter != '"' || member (string[i], slashify_in_quotes)))
+           {
+             i++;
+             continue;
+           }
+
+         if (delimiter && string[i] == delimiter)
+           {
+             delimiter = 0;
+             continue;
+           }
+
+         if (!delimiter && (member (string[i], " \t\n;&()|<>")))
+           break;
+
+         if (!delimiter && member (string[i], "\"'`"))
+           delimiter = string[i];
+       }
+    got_token:
+
+      /* If we are looking for the word in which the character at a
+        particular index falls, remember it. */
+      if (indp && wind >= 0 && wind >= start && wind < i)
+        *indp = result_index;
+
+      len = i - start;
+      if (result_index + 2 >= size)
+       result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));
+      result[result_index] = xmalloc (1 + len);
+      strncpy (result[result_index], string + start, len);
+      result[result_index][len] = '\0';
+      result[++result_index] = (char *)NULL;
+    }
+
+  return (result);
+}
+
+/* Return an array of tokens, much as the shell might.  The tokens are
+   parsed out of STRING. */
+char **
+history_tokenize (string)
+     char *string;
+{
+  return (history_tokenize_internal (string, -1, (int *)NULL));
+}
+
+/* Find and return the word which contains the character at index IND
+   in the history line LINE.  Used to save the word matched by the
+   last history !?string? search. */
+static char *
+history_find_word (line, ind)
+     char *line;
+     int ind;
+{
+  char **words, *s;
+  int i, wind;
+
+  words = history_tokenize_internal (line, ind, &wind);
+  if (wind == -1)
+    return ((char *)NULL);
+  s = words[wind];
+  for (i = 0; i < wind; i++)
+    free (words[i]);
+  for (i = wind + 1; words[i]; i++)
+    free (words[i]);
+  free (words);
+  return s;
+}
+
+#if defined (STATIC_MALLOC)
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)xmalloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "history: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                             Test Code                           */
+/*                                                                 */
+/* **************************************************************** */
+#ifdef TEST
+main ()
+{
+  char line[1024], *t;
+  int done = 0;
+
+  line[0] = 0;
+
+  while (!done)
+    {
+      fprintf (stdout, "history%% ");
+      t = gets (line);
+
+      if (!t)
+       strcpy (line, "quit");
+
+      if (line[0])
+       {
+         char *expansion;
+         int result;
+
+         using_history ();
+
+         result = history_expand (line, &expansion);
+         strcpy (line, expansion);
+         free (expansion);
+         if (result)
+           fprintf (stderr, "%s\n", line);
+
+         if (result < 0)
+           continue;
+
+         add_history (line);
+       }
+
+      if (strcmp (line, "quit") == 0) done = 1;
+      if (strcmp (line, "save") == 0) write_history (0);
+      if (strcmp (line, "read") == 0) read_history (0);
+      if (strcmp (line, "list") == 0)
+       {
+         register HIST_ENTRY **the_list = history_list ();
+         register int i;
+
+         if (the_list)
+           for (i = 0; the_list[i]; i++)
+             fprintf (stdout, "%d: %s\n", i + history_base, the_list[i]->line);
+       }
+      if (strncmp (line, "delete", strlen ("delete")) == 0)
+       {
+         int which;
+         if ((sscanf (line + strlen ("delete"), "%d", &which)) == 1)
+           {
+             HIST_ENTRY *entry = remove_history (which);
+             if (!entry)
+               fprintf (stderr, "No such entry %d\n", which);
+             else
+               {
+                 free (entry->line);
+                 free (entry);
+               }
+           }
+         else
+           {
+             fprintf (stderr, "non-numeric arg given to `delete'\n");
+           }
+       }
+    }
+}
+
+#endif /* TEST */
+\f
+/*
+* Local variables:
+* compile-command: "gcc -g -DTEST -o history history.c"
+* end:
+*/
diff --git a/lib/readline/history.h b/lib/readline/history.h
new file mode 100644 (file)
index 0000000..6935efd
--- /dev/null
@@ -0,0 +1,181 @@
+/* History.h -- the names of functions that you can call in history. */
+
+/* The structure used to store a history entry. */
+typedef struct _hist_entry {
+  char *line;
+  char *data;
+} HIST_ENTRY;
+
+/* A structure used to pass the current state of the history stuff around. */
+typedef struct _hist_state {
+  HIST_ENTRY **entries;                /* Pointer to the entries themselves. */
+  int offset;                  /* The location pointer within this array. */
+  int length;                  /* Number of elements within this array. */
+  int size;                    /* Number of slots allocated to this array. */
+  int flags;
+} HISTORY_STATE;
+
+/* Flag values for the `flags' member of HISTORY_STATE. */
+#define HS_STIFLED     0x01
+
+/* Initialization and state management. */
+
+/* Begin a session in which the history functions might be used.  This
+   just initializes the interactive variables. */
+extern void using_history ();
+
+/* Return the current HISTORY_STATE of the history. */
+extern HISTORY_STATE *history_get_history_state ();
+
+/* Set the state of the current history array to STATE. */
+extern void history_set_history_state ();
+
+/* Manage the history list. */
+
+/* Place STRING at the end of the history list.
+   The associated data field (if any) is set to NULL. */
+extern void add_history ();
+
+/* A reasonably useless function, only here for completeness.  WHICH
+   is the magic number that tells us which element to delete.  The
+   elements are numbered from 0. */
+extern HIST_ENTRY *remove_history ();
+
+/* Make the history entry at WHICH have LINE and DATA.  This returns
+   the old entry so you can dispose of the data.  In the case of an
+   invalid WHICH, a NULL pointer is returned. */
+extern HIST_ENTRY *replace_history_entry ();
+
+/* Stifle the history list, remembering only MAX number of entries. */
+extern void stifle_history ();
+
+/* 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. */
+extern int unstifle_history ();
+
+/* Return 1 if the history is stifled, 0 if it is not. */
+extern int history_is_stifled ();
+
+/* Information about the history list. */
+
+/* Return a NULL terminated array of HIST_ENTRY which is the current input
+   history.  Element 0 of this list is the beginning of time.  If there
+   is no history, return NULL. */
+extern HIST_ENTRY **history_list ();
+
+/* Returns the number which says what history element we are now
+   looking at.  */
+extern int where_history ();
+  
+/* Return the history entry at the current position, as determined by
+   history_offset.  If there is no entry there, return a NULL pointer. */
+HIST_ENTRY *current_history ();
+
+/* Return the history entry which is logically at OFFSET in the history
+   array.  OFFSET is relative to history_base. */
+extern HIST_ENTRY *history_get ();
+
+/* Return the number of bytes that the primary history entries are using.
+   This just adds up the lengths of the_history->lines. */
+extern int history_total_bytes ();
+
+/* Moving around the history list. */
+
+/* Set the position in the history list to POS. */
+int history_set_pos ();
+
+/* Back up history_offset to the previous history entry, and return
+   a pointer to that entry.  If there is no previous entry, return
+   a NULL pointer. */
+extern HIST_ENTRY *previous_history ();
+
+/* Move history_offset forward to the next item in the input_history,
+   and return the a pointer to that entry.  If there is no next entry,
+   return a NULL pointer. */
+extern HIST_ENTRY *next_history ();
+
+/* Searching the history list. */
+
+/* Search the history for STRING, starting at history_offset.
+   If DIRECTION < 0, then the search is through previous entries,
+   else through subsequent.  If the string is found, then
+   current_history () is the history entry, and the value of this function
+   is the offset in the line of that history entry that the string was
+   found in.  Otherwise, nothing is changed, and a -1 is returned. */
+extern int history_search ();
+
+/* Search the history for STRING, starting at history_offset.
+   The search is anchored: matching lines must begin with string. */
+extern int history_search_prefix ();
+
+/* Search for STRING in the history list, starting at POS, an
+   absolute index into the list.  DIR, if negative, says to search
+   backwards from POS, else forwards.
+   Returns the absolute index of the history element where STRING
+   was found, or -1 otherwise. */
+extern int history_search_pos ();
+
+/* Managing the history file. */
+
+/* Add the contents of FILENAME to the history list, a line at a time.
+   If FILENAME is NULL, then read from ~/.history.  Returns 0 if
+   successful, or errno if not. */
+extern int read_history ();
+
+/* Read a range of lines from FILENAME, adding them to the history list.
+   Start reading at the FROM'th line and end at the TO'th.  If FROM
+   is zero, start at the beginning.  If TO is less than FROM, read
+   until the end of the file.  If FILENAME is NULL, then read from
+   ~/.history.  Returns 0 if successful, or errno if not. */
+extern int read_history_range ();
+
+/* Write the current history to FILENAME.  If FILENAME is NULL,
+   then write the history list to ~/.history.  Values returned
+   are as in read_history ().  */
+extern int write_history ();
+
+/* Append NELEMENT entries to FILENAME.  The entries appended are from
+   the end of the list minus NELEMENTs up to the end of the list. */
+int append_history ();
+
+/* Truncate the history file, leaving only the last NLINES lines. */
+extern int history_truncate_file ();
+
+/* History expansion. */
+
+/* Expand the string STRING, placing the result into OUTPUT, a pointer
+   to a string.  Returns:
+
+   0) If no expansions took place (or, if the only change in
+      the text was the de-slashifying of the history expansion
+      character)
+   1) If expansions did take place
+  -1) If there was an error in expansion.
+   2) If the returned line should just be printed.
+
+  If an error ocurred in expansion, then OUTPUT contains a descriptive
+  error message. */
+extern int history_expand ();
+
+/* Extract a string segment consisting of the FIRST through LAST
+   arguments present in STRING.  Arguments are broken up as in
+   the shell. */
+extern char *history_arg_extract ();
+
+/* Return the text of the history event beginning at the current
+   offset into STRING. */
+extern char *get_history_event ();
+
+/* Return an array of tokens, much as the shell might.  The tokens are
+   parsed out of STRING. */
+extern char **history_tokenize ();
+
+/* Exported history variables. */
+extern int history_base;
+extern int history_length;
+extern int max_input_history;
+extern char history_expansion_char;
+extern char history_subst_char;
+extern char history_comment_char;
+extern char *history_no_expand_chars;
diff --git a/lib/readline/isearch.c b/lib/readline/isearch.c
new file mode 100644 (file)
index 0000000..1a0193f
--- /dev/null
@@ -0,0 +1,378 @@
+/* **************************************************************** */
+/*                                                                 */
+/*                     I-Search and Searching                      */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Copyright (C) 1987,1989 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
+   for it.
+
+   The 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 1, or (at your option)
+   any later version.
+
+   The 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include "memalloc.h"
+#include "readline.h"
+#include "history.h"
+
+#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))
+
+/* Variables imported from other files in the readline library. */
+extern Keymap _rl_keymap;
+extern HIST_ENTRY *saved_line_for_history;
+extern int rl_line_buffer_len;
+extern int rl_point, rl_end;
+extern char *rl_line_buffer;
+
+extern char *xmalloc (), *xrealloc ();
+
+static int rl_search_history ();
+
+/* Last line found by the current incremental search, so we don't `find'
+   identical lines many times in a row. */
+static char *prev_line_found;
+
+/* Search backwards through the history looking for a string which is typed
+   interactively.  Start with the current line. */
+rl_reverse_search_history (sign, key)
+     int sign;
+     int key;
+{
+  return (rl_search_history (-sign, key));
+}
+
+/* Search forwards through the history looking for a string which is typed
+   interactively.  Start with the current line. */
+rl_forward_search_history (sign, key)
+     int sign;
+     int key;
+{
+  return (rl_search_history (sign, key));
+}
+
+/* Display the current state of the search in the echo-area.
+   SEARCH_STRING contains the string that is being searched for,
+   DIRECTION is zero for forward, or 1 for reverse,
+   WHERE is the history list number of the current line.  If it is
+   -1, then this line is the starting one. */
+static void
+rl_display_search (search_string, reverse_p, where)
+     char *search_string;
+     int reverse_p, where;
+{
+  char *message;
+
+  message = xmalloc (1 + (search_string ? strlen (search_string) : 0) + 30);
+  *message = '\0';
+
+#if defined (NOTDEF)
+  if (where != -1)
+    sprintf (message, "[%d]", where + history_base);
+#endif /* NOTDEF */
+
+  strcat (message, "(");
+
+  if (reverse_p)
+    strcat (message, "reverse-");
+
+  strcat (message, "i-search)`");
+
+  if (search_string)
+    strcat (message, search_string);
+
+  strcat (message, "': ");
+  rl_message ("%s", message, 0);
+  free (message);
+  rl_redisplay ();
+}
+
+/* Search through the history looking for an interactively typed string.
+   This is analogous to i-search.  We start the search in the current line.
+   DIRECTION is which direction to search; >= 0 means forward, < 0 means
+   backwards. */
+static int
+rl_search_history (direction, invoking_key)
+     int direction;
+     int invoking_key;
+{
+  /* The string that the user types in to search for. */
+  char *search_string;
+
+  /* The current length of SEARCH_STRING. */
+  int search_string_index;
+
+  /* The amount of space that SEARCH_STRING has allocated to it. */
+  int search_string_size;
+
+  /* The list of lines to search through. */
+  char **lines, *allocated_line = (char *)NULL;
+
+  /* The length of LINES. */
+  int hlen;
+
+  /* Where we get LINES from. */
+  HIST_ENTRY **hlist = history_list ();
+
+  register int i = 0;
+  int orig_point = rl_point;
+  int orig_line = where_history ();
+  int last_found_line = orig_line;
+  int c, done = 0, found, failed, sline_len;
+
+  /* The line currently being searched. */
+  char *sline;
+
+  /* Offset in that line. */
+  int line_index;
+
+  /* Non-zero if we are doing a reverse search. */
+  int reverse = (direction < 0);
+
+  /* Create an arrary of pointers to the lines that we want to search. */
+  maybe_replace_line ();
+  if (hlist)
+    for (i = 0; hlist[i]; i++);
+
+  /* Allocate space for this many lines, +1 for the current input line,
+     and remember those lines. */
+  lines = (char **)xmalloc ((1 + (hlen = i)) * sizeof (char *));
+  for (i = 0; i < hlen; i++)
+    lines[i] = hlist[i]->line;
+
+  if (saved_line_for_history)
+    lines[i] = saved_line_for_history->line;
+  else
+    {
+      /* Keep track of this so we can free it. */
+      allocated_line = xmalloc (1 + strlen (rl_line_buffer));
+      strcpy (allocated_line, &rl_line_buffer[0]);
+      lines[i] = allocated_line;
+    }
+
+  hlen++;
+
+  /* The line where we start the search. */
+  i = orig_line;
+
+  /* Initialize search parameters. */
+  search_string = xmalloc (search_string_size = 128);
+  *search_string = '\0';
+  search_string_index = 0;
+  prev_line_found = (char *)0;         /* XXX */
+
+  /* Normalize DIRECTION into 1 or -1. */
+  direction = (direction >= 0) ? 1 : -1;
+
+  rl_display_search (search_string, reverse, -1);
+
+  sline = rl_line_buffer;
+  sline_len = strlen (sline);
+  line_index = rl_point;
+
+  found = failed = 0;
+  while (!done)
+    {
+      Function *f = (Function *)NULL;
+
+      /* Read a key and decide how to proceed. */
+      c = rl_read_key ();
+
+      /* Hack C to Do What I Mean. */
+      if (_rl_keymap[c].type == ISFUNC)
+       {
+         f = _rl_keymap[c].function;
+
+         if (f == rl_reverse_search_history)
+           c = reverse ? -1 : -2;
+         else if (f == rl_forward_search_history)
+           c =  !reverse ? -1 : -2;
+       }
+
+      switch (c)
+       {
+       case ESC:
+         done = 1;
+         continue;
+
+       case -1:
+         if (!search_string_index)
+           continue;
+         else
+           {
+             if (reverse)
+               --line_index;
+             else
+               {
+                 if (line_index != sline_len)
+                   ++line_index;
+                 else
+                   ding ();
+               }
+           }
+         break;
+
+         /* switch directions */
+       case -2:
+         direction = -direction;
+         reverse = (direction < 0);
+         break;
+
+       case CTRL ('G'):
+         strcpy (rl_line_buffer, lines[orig_line]);
+         rl_point = orig_point;
+         rl_end = strlen (rl_line_buffer);
+         rl_clear_message ();
+         free (allocated_line);
+         free (lines);
+         return 0;
+
+       default:
+         if (CTRL_CHAR (c) || META_CHAR (c) || c == RUBOUT)
+           {
+             rl_execute_next (c);
+             done = 1;
+             continue;
+           }
+         else
+           {
+             /* Add character to search string and continue search. */
+             if (search_string_index + 2 >= search_string_size)
+               {
+                 search_string_size += 128;
+                 search_string = xrealloc (search_string, search_string_size);
+               }
+             search_string[search_string_index++] = c;
+             search_string[search_string_index] = '\0';
+             break;
+           }
+       }
+
+      found = failed = 0;
+      while (1)
+       {
+         int limit = sline_len - search_string_index + 1;
+
+         /* Search the current line. */
+         while (reverse ? (line_index >= 0) : (line_index < limit))
+           {
+             if (STREQN(search_string, sline + line_index, search_string_index))
+                 {
+                   found++;
+                   break;
+                 }
+             else
+               line_index += direction;
+           }
+         if (found)
+           break;
+
+         /* Move to the next line, but skip new copies of the line
+            we just found and lines shorter than the string we're
+            searching for. */
+         do
+           {
+             /* Move to the next line. */
+             i += direction;
+
+             /* At limit for direction? */
+             if (reverse ? (i < 0) : (i == hlen))
+               {
+                 failed++;
+                 break;
+               }
+
+             /* We will need these later. */
+             sline = lines[i];
+             sline_len = strlen (sline);
+           }
+         while ((prev_line_found && STREQ (prev_line_found, lines[i])) ||
+                (search_string_index > sline_len));
+
+         if (failed)
+           break;
+
+         /* Now set up the line for searching... */
+         if (reverse)
+           line_index = sline_len - search_string_index;
+         else
+           line_index = 0;
+       }
+
+      if (failed)
+       {
+         /* We cannot find the search string.  Ding the bell. */
+         ding ();
+         i = last_found_line;
+         continue;             /* XXX - was break */
+       }
+
+      /* We have found the search string.  Just display it.  But don't
+        actually move there in the history list until the user accepts
+        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_point = line_index;
+         rl_end = line_len;
+         last_found_line = i;
+         rl_display_search (search_string, reverse, (i == orig_line) ? -1 : i);
+       }
+    }
+
+  /* The searching is over.  The user may have found the string that she
+     was looking for, or else she may have exited a failing search.  If
+     LINE_INDEX is -1, then that shows that the string searched for was
+     not found.  We use this to determine where to place rl_point. */
+
+  /* First put back the original state. */
+  strcpy (rl_line_buffer, lines[orig_line]);
+
+  /* Free the search string. */
+  free (search_string);
+
+  if (last_found_line < orig_line)
+    rl_get_previous_history (orig_line - last_found_line);
+  else
+    rl_get_next_history (last_found_line - orig_line);
+
+  /* If the string was not found, put point at the end of the line. */
+  if (line_index < 0)
+    line_index = strlen (rl_line_buffer);
+  rl_point = line_index;
+  rl_clear_message ();
+
+  free (allocated_line);
+  free (lines);
+
+  return 0;
+}
diff --git a/lib/readline/keymaps.c b/lib/readline/keymaps.c
new file mode 100644 (file)
index 0000000..e1be552
--- /dev/null
@@ -0,0 +1,200 @@
+/* keymaps.c -- Functions and keymaps for the GNU Readline library. */
+
+/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+   This file is part of GNU Readline, a library for reading lines
+   of text with interactive input and history editing.
+
+   Readline is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 1, or (at your option) any
+   later version.
+
+   Readline is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "rlconf.h"
+#include "keymaps.h"
+#include "emacs_keymap.c"
+
+#if defined (VI_MODE)
+#include "vi_keymap.c"
+#endif
+
+extern int rl_do_lowercase_version ();
+extern int rl_rubout (), rl_insert ();
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                   Functions for manipulating Keymaps.           */
+/*                                                                 */
+/* **************************************************************** */
+
+
+/* Return a new, empty keymap.
+   Free it with free() when you are done. */
+Keymap
+rl_make_bare_keymap ()
+{
+  register int i;
+  Keymap keymap = (Keymap)xmalloc (KEYMAP_SIZE * sizeof (KEYMAP_ENTRY));
+
+  for (i = 0; i < KEYMAP_SIZE; i++)
+    {
+      keymap[i].type = ISFUNC;
+      keymap[i].function = (Function *)NULL;
+    }
+
+  for (i = 'A'; i < ('Z' + 1); i++)
+    {
+      keymap[i].type = ISFUNC;
+      keymap[i].function = rl_do_lowercase_version;
+    }
+
+  return (keymap);
+}
+
+/* Return a new keymap which is a copy of MAP. */
+Keymap
+rl_copy_keymap (map)
+     Keymap map;
+{
+  register int i;
+  Keymap temp = rl_make_bare_keymap ();
+
+  for (i = 0; i < KEYMAP_SIZE; i++)
+    {
+      temp[i].type = map[i].type;
+      temp[i].function = map[i].function;
+    }
+  return (temp);
+}
+
+/* Return a new keymap with the printing characters bound to rl_insert,
+   the uppercase Meta characters bound to run their lowercase equivalents,
+   and the Meta digits bound to produce numeric arguments. */
+Keymap
+rl_make_keymap ()
+{
+  register int i;
+  Keymap newmap;
+
+  newmap = rl_make_bare_keymap ();
+
+  /* All ASCII printing characters are self-inserting. */
+  for (i = ' '; i < 127; i++)
+    newmap[i].function = rl_insert;
+
+  newmap[TAB].function = rl_insert;
+  newmap[RUBOUT].function = rl_rubout;
+  newmap[CTRL('H')].function = rl_rubout;
+
+#if KEYMAP_SIZE > 128
+  /* Printing characters in some 8-bit character sets. */
+  for (i = 128; i < 160; i++)
+    newmap[i].function = rl_insert;
+
+  /* ISO Latin-1 printing characters should self-insert. */
+  for (i = 160; i < 256; i++)
+    newmap[i].function = rl_insert;
+#endif /* KEYMAP_SIZE > 128 */
+
+  return (newmap);
+}
+
+/* Free the storage associated with MAP. */
+void
+rl_discard_keymap (map)
+     Keymap (map);
+{
+  int i;
+
+  if (!map)
+    return;
+
+  for (i = 0; i < KEYMAP_SIZE; i++)
+    {
+      switch (map[i].type)
+       {
+       case ISFUNC:
+         break;
+
+       case ISKMAP:
+         rl_discard_keymap ((Keymap)map[i].function);
+         break;
+
+       case ISMACR:
+         free ((char *)map[i].function);
+         break;
+       }
+    }
+}
+
+#if defined (STATIC_MALLOC)
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
diff --git a/lib/readline/keymaps.h b/lib/readline/keymaps.h
new file mode 100644 (file)
index 0000000..f0eda3d
--- /dev/null
@@ -0,0 +1,95 @@
+/* keymaps.h -- Manipulation of readline keymaps. */
+
+/* Copyright (C) 1987, 1989, 1992 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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _KEYMAPS_H_
+#define _KEYMAPS_H_
+
+#if defined (READLINE_LIBRARY)
+#  include "chardefs.h"
+#else
+#  include <readline/chardefs.h>
+#endif
+
+#if !defined (__FUNCTION_DEF)
+#  define __FUNCTION_DEF
+typedef int Function ();
+typedef void VFunction ();
+typedef char *CPFunction ();
+typedef char **CPPFunction ();
+#endif
+
+/* A keymap contains one entry for each key in the ASCII set.
+   Each entry consists of a type and a pointer.
+   POINTER is the address of a function to run, or the
+   address of a keymap to indirect through.
+   TYPE says which kind of thing POINTER is. */
+typedef struct _keymap_entry {
+  char type;
+  Function *function;
+} 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
+
+/* I wanted to make the above structure contain a union of:
+   union { Function *function; struct _keymap_entry *keymap; } value;
+   but this made it impossible for me to create a static array.
+   Maybe I need C lessons. */
+
+typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE];
+typedef KEYMAP_ENTRY *Keymap;
+
+/* The values that TYPE can have in a keymap entry. */
+#define ISFUNC 0
+#define ISKMAP 1
+#define ISMACR 2
+
+extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_meta_keymap, emacs_ctlx_keymap;
+extern KEYMAP_ENTRY_ARRAY vi_insertion_keymap, vi_movement_keymap;
+
+/* Return a new, empty keymap.
+   Free it with free() when you are done. */
+extern Keymap rl_make_bare_keymap ();
+
+/* Return a new keymap which is a copy of MAP. */
+extern Keymap rl_copy_keymap ();
+
+/* Return a new keymap with the printing characters bound to rl_insert,
+   the lowercase Meta characters bound to run their equivalents, and
+   the Meta digits bound to produce numeric arguments. */
+extern Keymap rl_make_keymap ();
+
+extern void rl_discard_keymap ();
+
+/* Return the keymap corresponding to a given name.  Names look like
+   `emacs' or `emacs-meta' or `vi-insert'. */
+extern Keymap rl_get_keymap_by_name ();
+
+/* Return the current keymap. */
+extern Keymap rl_get_keymap ();
+
+/* Set the current keymap to MAP. */
+extern void rl_set_keymap ();
+
+#endif /* _KEYMAPS_H_ */
diff --git a/lib/readline/memalloc.h b/lib/readline/memalloc.h
new file mode 100644 (file)
index 0000000..750d53d
--- /dev/null
@@ -0,0 +1,56 @@
+/* memalloc.h -- consolidate code for including alloca.h or malloc.h and
+   defining alloca. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (__MEMALLOC_H__)
+#  define __MEMALLOC_H__
+
+#if defined (sparc) && defined (sun) && !defined (HAVE_ALLOCA_H)
+#  define HAVE_ALLOCA_H
+#endif
+
+#if defined (__GNUC__) && !defined (HAVE_ALLOCA)
+#  define HAVE_ALLOCA
+#endif
+
+#if defined (HAVE_ALLOCA_H) && !defined (HAVE_ALLOCA)
+#  define HAVE_ALLOCA
+#endif /* HAVE_ALLOCA_H && !HAVE_ALLOCA */
+
+#if !defined (BUILDING_MAKEFILE)
+
+#if defined (__GNUC__)
+#  undef alloca
+#  define alloca __builtin_alloca
+#else /* !__GNUC__ */
+#  if defined (HAVE_ALLOCA_H)
+#    if defined (IBMESA)
+#      include <malloc.h>
+#    else /* !IBMESA */
+#      include <alloca.h>
+#    endif /* !IBMESA */
+#  else
+extern char *alloca ();
+#  endif /* !HAVE_ALLOCA_H */
+#endif /* !__GNUC__ */
+
+#endif /* !BUILDING_MAKEFILE */
+
+#endif /* __MEMALLOC_H__ */
diff --git a/lib/readline/parens.c b/lib/readline/parens.c
new file mode 100644 (file)
index 0000000..57a9777
--- /dev/null
@@ -0,0 +1,130 @@
+/* parens.c -- Implemenation of matching parenthesis feature. */
+
+/* Copyright (C) 1987, 1989, 1992 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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#include "rlconf.h"
+
+#if !defined (PAREN_MATCHING)
+
+rl_insert_close (count, invoking_key)
+     int count, invoking_key;
+{
+  return (rl_insert (count, invoking_key));
+}
+
+#else /* PAREN_MATCHING */
+
+#include <stdio.h>
+#include <sys/types.h>
+#if defined (FD_SET)
+#  include <sys/time.h>
+#endif /* FD_SET */
+#include "readline.h"
+
+extern int rl_explicit_arg;
+
+/* Non-zero means try to blink the matching open parenthesis when the
+   close parenthesis is inserted. */
+#if defined (FD_SET)
+int rl_blink_matching_paren = 1;
+#else /* !FD_SET */
+int rl_blink_matching_paren = 0;
+#endif /* !FD_SET */
+
+static int find_matching_open ();
+
+rl_insert_close (count, invoking_key)
+     int count, invoking_key;
+{
+  if (rl_explicit_arg || !rl_blink_matching_paren)
+    rl_insert (count, invoking_key);
+  else
+    {
+#if defined (FD_SET)
+      int orig_point, match_point, ready;
+      struct timeval timer;
+      fd_set readfds;
+
+      rl_insert (1, invoking_key);
+      rl_redisplay ();
+      match_point =
+       find_matching_open (rl_line_buffer, rl_point - 2, invoking_key);
+
+      /* Emacs might message or ring the bell here, but I don't. */
+      if (match_point < 0)
+       return -1;
+
+      FD_ZERO (&readfds);
+      FD_SET (fileno (rl_instream), &readfds);
+      timer.tv_sec = 1;
+      timer.tv_usec = 500;
+
+      orig_point = rl_point;
+      rl_point = match_point;
+      rl_redisplay ();
+      ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer);
+      rl_point = orig_point;
+#else /* !FD_SET */
+      rl_insert (count, invoking_key);
+#endif /* !FD_SET */
+    }
+  return 0;
+}
+
+static int
+find_matching_open (string, from, closer)
+     char *string;
+     int from, closer;
+{
+  register int i;
+  int opener, level, delimiter;
+
+  switch (closer)
+    {
+    case ']': opener = '['; break;
+    case '}': opener = '{'; break;
+    case ')': opener = '('; break;
+    default:
+      return (-1);
+    }
+
+  level = 1;                   /* The closer passed in counts as 1. */
+  delimiter = 0;               /* Delimited state unknown. */
+
+  for (i = from; i > -1; i--)
+    {
+      if (delimiter && (string[i] == delimiter))
+       delimiter = 0;
+      else if ((string[i] == '\'') || (string[i] == '"'))
+       delimiter = rl_line_buffer[i];
+      else if (!delimiter && (string[i] == closer))
+       level++;
+      else if (!delimiter && (string[i] == opener))
+       level--;
+
+      if (!level)
+       break;
+    }
+  return (i);
+}
+
+#endif /* PAREN_MATCHING */
diff --git a/lib/readline/posixstat.h b/lib/readline/posixstat.h
new file mode 100644 (file)
index 0000000..7d1cece
--- /dev/null
@@ -0,0 +1,149 @@
+/* posixstat.h -- Posix stat(2) definitions for systems that
+   don't have them. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This file should be included instead of <sys/stat.h>.
+   It relies on the local sys/stat.h to work though. */
+#if !defined (_POSIXSTAT_H)
+#define _POSIXSTAT_H
+
+#include <sys/stat.h>
+
+#if defined (isc386)
+#  if !defined (S_IFDIR)
+#    define S_IFDIR 0040000
+#  endif /* !S_IFDIR */
+#  if !defined (S_IFMT)
+#    define S_IFMT  0170000
+#  endif /* !S_IFMT */
+#endif /* isc386 */
+
+/* This text is taken directly from the Cadmus I was trying to
+   compile on:
+    the following MACROs are defined for X/OPEN compatibility
+    however, is the param correct ??
+   #define S_ISBLK(s) ((s.st_mode & S_IFMT) == S_IFBLK)
+
+  Well, the answer is no.  Thus... */
+#if defined (BrainDeath)
+#  undef S_ISBLK
+#  undef S_ISCHR
+#  undef S_ISDIR
+#  undef S_ISFIFO
+#  undef S_ISREG
+#endif /* BrainDeath */
+
+/* Posix 1003.1 5.6.1.1 <sys/stat.h> file types */
+
+/* Some Posix-wannabe systems define _S_IF* macros instead of S_IF*, but
+   do not provide the S_IS* macros that Posix requires. */
+
+#if defined (_S_IFMT) && !defined (S_IFMT)
+#define S_IFMT _S_IFMT
+#endif
+#if defined (_S_IFIFO) && !defined (S_IFIFO)
+#define S_IFIFO _S_IFIFO
+#endif
+#if defined (_S_IFCHR) && !defined (S_IFCHR)
+#define S_IFCHR _S_IFCHR
+#endif
+#if defined (_S_IFDIR) && !defined (S_IFDIR)
+#define S_IFDIR _S_IFDIR
+#endif
+#if defined (_S_IFBLK) && !defined (S_IFBLK)
+#define S_IFBLK _S_IFBLK
+#endif
+#if defined (_S_IFREG) && !defined (S_IFREG)
+#define S_IFREG _S_IFREG
+#endif
+#if defined (_S_IFLNK) && !defined (S_IFLNK)
+#define S_IFLNK _S_IFLNK
+#endif
+#if defined (_S_IFSOCK) && !defined (S_IFSOCK)
+#define S_IFSOCK _S_IFSOCK
+#endif
+
+/* Test for each symbol individually and define the ones necessary (some
+   systems claiming Posix compatibility define some but not all). */
+
+#if defined (S_IFBLK) && !defined (S_ISBLK)
+#define        S_ISBLK(m)      (((m)&S_IFMT) == S_IFBLK)       /* block device */
+#endif
+
+#if defined (S_IFCHR) && !defined (S_ISCHR)
+#define        S_ISCHR(m)      (((m)&S_IFMT) == S_IFCHR)       /* character device */
+#endif
+
+#if defined (S_IFDIR) && !defined (S_ISDIR)
+#define        S_ISDIR(m)      (((m)&S_IFMT) == S_IFDIR)       /* directory */
+#endif
+
+#if defined (S_IFREG) && !defined (S_ISREG)
+#define        S_ISREG(m)      (((m)&S_IFMT) == S_IFREG)       /* file */
+#endif
+
+#if defined (S_IFIFO) && !defined (S_ISFIFO)
+#define        S_ISFIFO(m)     (((m)&S_IFMT) == S_IFIFO)       /* fifo - named pipe */
+#endif
+
+#if defined (S_IFLNK) && !defined (S_ISLNK)
+#define        S_ISLNK(m)      (((m)&S_IFMT) == S_IFLNK)       /* symbolic link */
+#endif
+
+#if defined (S_IFSOCK) && !defined (S_ISSOCK)
+#define        S_ISSOCK(m)     (((m)&S_IFMT) == S_IFSOCK)      /* socket */
+#endif
+
+/*
+ * POSIX 1003.1 5.6.1.2 <sys/stat.h> File Modes
+ */
+#if !defined (S_IRWXU)
+#  if !defined (S_IREAD)
+#    define S_IREAD    00400
+#    define S_IWRITE   00200
+#    define S_IEXEC    00100
+#  endif /* S_IREAD */
+
+#  if !defined (S_IRUSR)
+#    define S_IRUSR    S_IREAD                 /* read, owner */
+#    define S_IWUSR    S_IWRITE                /* write, owner */
+#    define S_IXUSR    S_IEXEC                 /* execute, owner */
+
+#    define S_IRGRP    (S_IREAD  >> 3)         /* read, group */
+#    define S_IWGRP    (S_IWRITE >> 3)         /* write, group */
+#    define S_IXGRP    (S_IEXEC  >> 3)         /* execute, group */
+
+#    define S_IROTH    (S_IREAD  >> 6)         /* read, other */
+#    define S_IWOTH    (S_IWRITE >> 6)         /* write, other */
+#    define S_IXOTH    (S_IEXEC  >> 6)         /* execute, other */
+#  endif /* !S_IRUSR */
+
+#  define S_IRWXU      (S_IRUSR | S_IWUSR | S_IXUSR)
+#  define S_IRWXG      (S_IRGRP | S_IWGRP | S_IXGRP)
+#  define S_IRWXO      (S_IROTH | S_IWOTH | S_IXOTH)
+#endif /* !S_IRWXU */
+
+/* These are non-standard, but are used in builtins.c$symbolic_umask() */
+#define S_IRUGO                (S_IRUSR | S_IRGRP | S_IROTH)
+#define S_IWUGO                (S_IWUSR | S_IWGRP | S_IWOTH)
+#define S_IXUGO                (S_IXUSR | S_IXGRP | S_IXOTH)
+
+#endif /* _POSIXSTAT_H */
diff --git a/lib/readline/readline.c b/lib/readline/readline.c
new file mode 100644 (file)
index 0000000..6040cbb
--- /dev/null
@@ -0,0 +1,3539 @@
+/* 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.
+
+   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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#if !defined (NO_SYS_FILE)
+#  include <sys/file.h>
+#endif /* !NO_SYS_FILE */
+#include <signal.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <errno.h>
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include <setjmp.h>
+
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+#if defined (GWINSZ_IN_SYS_IOCTL) || (defined (VSTATUS) && !defined (SunOS4))
+#  include <sys/ioctl.h>
+#endif /* GWINSZ_IN_SYS_IOCTL || VSTATUS */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+/* NOTE: Functions and variables prefixed with `_rl_' are
+   pseudo-global: they are global so they can be shared
+   between files in the readline library, but are not intended
+   to be visible to readline callers. */
+
+/* Functions imported from other files in the library. */
+extern char *tgetstr ();
+extern void rl_prep_terminal (), rl_deprep_terminal ();
+
+extern void _rl_bind_if_unbound ();
+
+/* External redisplay functions and variables from display.c */
+extern void _rl_move_vert ();
+extern void _rl_update_final ();
+
+extern void _rl_erase_at_end_of_line ();
+extern void _rl_move_cursor_relative ();
+
+extern int _rl_vis_botlin;
+extern int _rl_last_c_pos;
+extern int _rl_horizontal_scroll_mode;
+extern int rl_display_fixed;
+extern char *rl_display_prompt;
+
+/* Variables imported from complete.c. */
+extern char *rl_completer_word_break_characters;
+extern char *rl_basic_word_break_characters;
+extern int rl_completion_query_items;
+extern int rl_complete_with_tilde_expansion;
+
+#if defined (VI_MODE)
+extern void _rl_vi_set_last ();
+extern void _rl_vi_reset_last ();
+extern void _rl_vi_done_inserting ();
+#endif /* VI_MODE */
+
+/* Forward declarations used in this file. */
+void _rl_free_history_entry ();
+
+int _rl_dispatch ();
+void _rl_set_screen_size ();
+int _rl_output_character_function ();
+
+static char *readline_internal ();
+static void readline_initialize_everything ();
+static int init_terminal_io ();
+static void start_using_history ();
+static void bind_arrow_keys ();
+
+#if !defined (__GO32__)
+static void readline_default_bindings ();
+#endif /* !__GO32__ */
+
+#if defined (__GO32__)
+#  include <sys/pc.h>
+#  undef HANDLE_SIGNALS
+#endif /* __GO32__ */
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Line editing input utility                  */
+/*                                                                 */
+/* **************************************************************** */
+
+static char *LibraryVersion = "2.0";
+
+/* A pointer to the keymap that is currently in use.
+   By default, it is the standard emacs keymap. */
+Keymap _rl_keymap = emacs_standard_keymap;
+
+/* The current style of editing. */
+int rl_editing_mode = emacs_mode;
+
+/* Non-zero if the previous command was a kill command. */
+static int last_command_was_kill = 0;
+
+/* The current value of the numeric argument specified by the user. */
+int rl_numeric_arg = 1;
+
+/* Non-zero if an argument was typed. */
+int rl_explicit_arg = 0;
+
+/* Temporary value used while generating the argument. */
+int rl_arg_sign = 1;
+
+/* Non-zero means we have been called at least once before. */
+static int rl_initialized = 0;
+
+/* If non-zero, this program is running in an EMACS buffer. */
+static int running_in_emacs = 0;
+
+/* The current offset in the current input line. */
+int rl_point;
+
+/* Mark in the current input line. */
+int rl_mark;
+
+/* Length of the current input line. */
+int rl_end;
+
+/* Make this non-zero to return the current input_line. */
+int rl_done;
+
+/* The last function executed by readline. */
+Function *rl_last_func = (Function *)NULL;
+
+/* Top level environment for readline_internal (). */
+static jmp_buf readline_top_level;
+
+/* The streams we interact with. */
+static FILE *in_stream, *out_stream;
+
+/* The names of the streams that we do input and output to. */
+FILE *rl_instream = (FILE *)NULL;
+FILE *rl_outstream = (FILE *)NULL;
+
+/* Non-zero means echo characters as they are read. */
+int readline_echoing_p = 1;
+
+/* Current prompt. */
+char *rl_prompt;
+int rl_visible_prompt_length = 0;
+
+/* The number of characters read in order to type this complete command. */
+int rl_key_sequence_length = 0;
+
+/* If non-zero, then this is the address of a function to call just
+   before readline_internal () prints the first prompt. */
+Function *rl_startup_hook = (Function *)NULL;
+
+/* What we use internally.  You should always refer to RL_LINE_BUFFER. */
+static char *the_line;
+
+/* The character that can generate an EOF.  Really read from
+   the terminal driver... just defaulted here. */
+int _rl_eof_char = CTRL ('D');
+
+/* Non-zero makes this the next keystroke to read. */
+int rl_pending_input = 0;
+
+/* Pointer to a useful terminal name. */
+char *rl_terminal_name = (char *)NULL;
+
+/* Non-zero means to always use horizontal scrolling in line display. */
+int _rl_horizontal_scroll_mode = 0;
+
+/* Non-zero means to display an asterisk at the starts of history lines
+   which have been modified. */
+int _rl_mark_modified_lines = 0;  
+
+/* The style of `bell' notification preferred.  This can be set to NO_BELL,
+   AUDIBLE_BELL, or VISIBLE_BELL. */
+int _rl_bell_preference = AUDIBLE_BELL;
+     
+/* Line buffer and maintenence. */
+char *rl_line_buffer = (char *)NULL;
+int rl_line_buffer_len = 0;
+#define DEFAULT_BUFFER_SIZE 256
+
+/* Forward declarations used by the display and termcap code. */
+int term_xn;
+int screenwidth, screenheight, screenchars;
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     `Forward' declarations                      */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero means do not parse any lines other than comments and
+   parser directives. */
+unsigned char _rl_parsing_conditionalized_out = 0;
+
+/* Non-zero means to save keys that we dispatch on in a kbd macro. */
+static int defining_kbd_macro = 0;
+
+/* Non-zero means to convert characters with the meta bit set to
+   escape-prefixed characters so we can indirect through
+   emacs_meta_keymap or vi_escape_keymap. */
+int _rl_convert_meta_chars_to_ascii = 1;
+
+/* Non-zero means to output characters with the meta bit set directly
+   rather than as a meta-prefixed escape sequence. */
+int _rl_output_meta_chars = 0;
+
+/* Non-zero tells rl_delete_text and rl_insert_text to not add to
+   the undo list. */
+static int doing_an_undo = 0;
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Top Level Functions                         */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero means treat 0200 bit in terminal input as Meta bit. */
+int _rl_meta_flag = 0; /* Forward declaration */
+
+/* Read a line of input.  Prompt with PROMPT.  A NULL PROMPT means
+   none.  A return value of NULL means that EOF was encountered. */
+char *
+readline (prompt)
+     char *prompt;
+{
+  char *value;
+
+  rl_prompt = prompt;
+
+  /* If we are at EOF return a NULL string. */
+  if (rl_pending_input == EOF)
+    {
+      rl_pending_input = 0;
+      return ((char *)NULL);
+    }
+
+  rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
+
+  rl_initialize ();
+  rl_prep_terminal (_rl_meta_flag);
+
+#if defined (HANDLE_SIGNALS)
+  rl_set_signals ();
+#endif
+
+  value = readline_internal ();
+  rl_deprep_terminal ();
+
+#if defined (HANDLE_SIGNALS)
+  rl_clear_signals ();
+#endif
+
+  return (value);
+}
+
+/* Read a line of input from the global rl_instream, doing output on
+   the global rl_outstream.
+   If rl_prompt is non-null, then that is our prompt. */
+static char *
+readline_internal ()
+{
+  int lastc, c, eof_found;
+
+  in_stream  = rl_instream;
+  out_stream = rl_outstream;
+
+  lastc = -1;
+  eof_found = 0;
+
+  if (rl_startup_hook)
+    (*rl_startup_hook) ();
+
+  if (!readline_echoing_p)
+    {
+      if (rl_prompt)
+       {
+         fprintf (out_stream, "%s", rl_prompt);
+         fflush (out_stream);
+       }
+    }
+  else
+    {
+      rl_on_new_line ();
+      rl_redisplay ();
+#if defined (VI_MODE)
+      if (rl_editing_mode == vi_mode)
+       rl_vi_insertion_mode ();
+#endif /* VI_MODE */
+    }
+
+  while (!rl_done)
+    {
+      int lk = last_command_was_kill;
+      int code;
+
+      code = setjmp (readline_top_level);
+
+      if (code)
+       rl_redisplay ();
+
+      if (!rl_pending_input)
+       {
+         /* Then initialize the argument and number of keys read. */
+         rl_init_argument ();
+         rl_key_sequence_length = 0;
+       }
+
+      c = rl_read_key ();
+
+      /* EOF typed to a non-blank line is a <NL>. */
+      if (c == EOF && rl_end)
+       c = NEWLINE;
+
+      /* The character _rl_eof_char typed to blank line, and not as the
+        previous character is interpreted as EOF. */
+      if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end)
+       {
+         eof_found = 1;
+         break;
+       }
+
+      lastc = c;
+      _rl_dispatch (c, _rl_keymap);
+
+      /* If there was no change in last_command_was_kill, then no kill
+        has taken place.  Note that if input is pending we are reading
+        a prefix command, so nothing has changed yet. */
+      if (!rl_pending_input)
+       {
+         if (lk == last_command_was_kill)
+           last_command_was_kill = 0;
+       }
+
+#if defined (VI_MODE)
+      /* In vi mode, when you exit insert mode, the cursor moves back
+        over the previous character.  We explicitly check for that here. */
+      if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap)
+       rl_vi_check ();
+#endif /* VI_MODE */
+
+      if (!rl_done)
+       rl_redisplay ();
+    }
+
+  /* Restore the original of this history line, iff the line that we
+     are editing was originally in the history, AND the line has changed. */
+  {
+    HIST_ENTRY *entry = current_history ();
+
+    if (entry && rl_undo_list)
+      {
+       char *temp = savestring (the_line);
+       rl_revert_line ();
+       entry = replace_history_entry (where_history (), the_line,
+                                      (HIST_ENTRY *)NULL);
+       _rl_free_history_entry (entry);
+
+       strcpy (the_line, temp);
+       free (temp);
+      }
+  }
+
+  /* At any rate, it is highly likely that this line has an undo list.  Get
+     rid of it now. */
+  if (rl_undo_list)
+    free_undo_list ();
+
+  if (eof_found)
+    return (char *)NULL;
+  else
+    return (savestring (the_line));
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Character Input Buffering                   */
+/*                                                                 */
+/* **************************************************************** */
+
+static int pop_index = 0, push_index = 0, ibuffer_len = 511;
+static unsigned char ibuffer[512];
+
+/* Non-null means it is a pointer to a function to run while waiting for
+   character input. */
+Function *rl_event_hook = (Function *)NULL;
+
+#define any_typein (push_index != pop_index)
+
+/* Add KEY to the buffer of characters to be read. */
+rl_stuff_char (key)
+     int key;
+{
+  if (key == EOF)
+    {
+      key = NEWLINE;
+      rl_pending_input = EOF;
+    }
+  ibuffer[push_index++] = key;
+  if (push_index >= ibuffer_len)
+    push_index = 0;
+  return push_index;
+}
+
+/* Return the amount of space available in the
+   buffer for stuffing characters. */
+int
+ibuffer_space ()
+{
+  if (pop_index > push_index)
+    return (pop_index - push_index);
+  else
+    return (ibuffer_len - (push_index - pop_index));
+}
+
+/* Get a key from the buffer of characters to be read.
+   Return the key in KEY.
+   Result is KEY if there was a key, or 0 if there wasn't. */
+int
+rl_get_char (key)
+     int *key;
+{
+  if (push_index == pop_index)
+    return (0);
+
+  *key = ibuffer[pop_index++];
+
+  if (pop_index >= ibuffer_len)
+    pop_index = 0;
+
+  return (1);
+}
+
+/* Stuff KEY into the *front* of the input buffer.
+   Returns non-zero if successful, zero if there is
+   no space left in the buffer. */
+int
+rl_unget_char (key)
+     int key;
+{
+  if (ibuffer_space ())
+    {
+      pop_index--;
+      if (pop_index < 0)
+       pop_index = ibuffer_len - 1;
+      ibuffer[pop_index] = key;
+      return (1);
+    }
+  return (0);
+}
+
+/* If a character is available to be read, then read it
+   and stuff it into IBUFFER.  Otherwise, just return. */
+void
+rl_gather_tyi ()
+{
+#if defined (__GO32__)
+  char input;
+
+  if (isatty (0))
+    {
+      int i = rl_getc ();
+
+      if (i != EOF)
+       rl_stuff_char (i);
+    }
+  else if (kbhit () && ibuffer_space ())
+    rl_stuff_char (getkey ());
+#else /* !__GO32__ */
+
+  int tty = fileno (in_stream);
+  register int tem, result = -1;
+  int chars_avail;
+  char input;
+
+#if defined (FIONREAD)
+  result = ioctl (tty, FIONREAD, &chars_avail);
+#endif
+
+#if defined (O_NDELAY)
+  if (result == -1)
+    {
+      int flags;
+
+      flags = fcntl (tty, F_GETFL, 0);
+
+      fcntl (tty, F_SETFL, (flags | O_NDELAY));
+      chars_avail = read (tty, &input, 1);
+
+      fcntl (tty, F_SETFL, flags);
+      if (chars_avail == -1 && errno == EAGAIN)
+       return;
+    }
+#endif /* O_NDELAY */
+
+  /* If there's nothing available, don't waste time trying to read
+     something. */
+  if (chars_avail == 0)
+    return;
+
+  tem = ibuffer_space ();
+
+  if (chars_avail > tem)
+    chars_avail = tem;
+
+  /* One cannot read all of the available input.  I can only read a single
+     character at a time, or else programs which require input can be
+     thwarted.  If the buffer is larger than one character, I lose.
+     Damn! */
+  if (tem < ibuffer_len)
+    chars_avail = 0;
+
+  if (result != -1)
+    {
+      while (chars_avail--)
+       rl_stuff_char (rl_getc (in_stream));
+    }
+  else
+    {
+      if (chars_avail)
+       rl_stuff_char (input);
+    }
+#endif /* !__GO32__ */
+}
+
+static int next_macro_key ();
+/* Read a key, including pending input. */
+int
+rl_read_key ()
+{
+  int c;
+
+  rl_key_sequence_length++;
+
+  if (rl_pending_input)
+    {
+      c = rl_pending_input;
+      rl_pending_input = 0;
+    }
+  else
+    {
+      /* If input is coming from a macro, then use that. */
+      if (c = next_macro_key ())
+       return (c);
+
+      /* If the user has an event function, then call it periodically. */
+      if (rl_event_hook)
+       {
+         while (rl_event_hook && !rl_get_char (&c))
+           {
+             (*rl_event_hook) ();
+             rl_gather_tyi ();
+           }
+       }
+      else
+       {
+         if (!rl_get_char (&c))
+           c = rl_getc (in_stream);
+       }
+    }
+
+  return (c);
+}
+
+/* Found later in this file. */
+static void add_macro_char (), with_macro_input ();
+
+/* Do the command associated with KEY in MAP.
+   If the associated command is really a keymap, then read
+   another key, and dispatch into that map. */
+int
+_rl_dispatch (key, map)
+     register int key;
+     Keymap map;
+{
+  int r = 0;
+
+  if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
+    {
+      if (map[ESC].type == ISKMAP)
+       {
+         if (defining_kbd_macro)
+           add_macro_char (ESC);
+         map = FUNCTION_TO_KEYMAP (map, ESC);
+         key = UNMETA (key);
+         rl_key_sequence_length += 2;
+         return (_rl_dispatch (key, map));
+       }
+      else
+       ding ();
+      return 0;
+    }
+
+  if (defining_kbd_macro)
+    add_macro_char (key);
+
+  switch (map[key].type)
+    {
+    case ISFUNC:
+      {
+       Function *func = map[key].function;
+
+       if (func != (Function *)NULL)
+         {
+           /* Special case rl_do_lowercase_version (). */
+           if (func == rl_do_lowercase_version)
+             return (_rl_dispatch (to_lower (key), map));
+
+           r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key);
+
+           /* If we have input pending, then the last command was a prefix
+              command.  Don't change the state of rl_last_func.  Otherwise,
+              remember the last command executed in this variable. */
+           if (!rl_pending_input)
+             rl_last_func = map[key].function;
+         }
+       else
+         {
+           rl_abort ();
+           return -1;
+         }
+      }
+      break;
+
+    case ISKMAP:
+      if (map[key].function != (Function *)NULL)
+       {
+         int newkey;
+
+         rl_key_sequence_length++;
+         newkey = rl_read_key ();
+         r = _rl_dispatch (newkey, FUNCTION_TO_KEYMAP (map, key));
+       }
+      else
+       {
+         rl_abort ();
+         return -1;
+       }
+      break;
+
+    case ISMACR:
+      if (map[key].function != (Function *)NULL)
+       {
+         char *macro;
+
+         macro = savestring ((char *)map[key].function);
+         with_macro_input (macro);
+         return 0;
+       }
+      break;
+    }
+#if defined (VI_MODE)
+  if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap &&
+      rl_vi_textmod_command (key))
+    _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);
+#endif
+  return (r);
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Hacking Keyboard Macros                     */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The currently executing macro string.  If this is non-zero,
+   then it is a malloc ()'ed string where input is coming from. */
+static char *executing_macro = (char *)NULL;
+
+/* The offset in the above string to the next character to be read. */
+static int executing_macro_index = 0;
+
+/* The current macro string being built.  Characters get stuffed
+   in here by add_macro_char (). */
+static char *current_macro = (char *)NULL;
+
+/* The size of the buffer allocated to current_macro. */
+static int current_macro_size = 0;
+
+/* The index at which characters are being added to current_macro. */
+static int current_macro_index = 0;
+
+/* A structure used to save nested macro strings.
+   It is a linked list of string/index for each saved macro. */
+struct saved_macro {
+  struct saved_macro *next;
+  char *string;
+  int sindex;
+};
+
+/* The list of saved macros. */
+struct saved_macro *macro_list = (struct saved_macro *)NULL;
+
+/* Forward declarations of static functions.  Thank you C. */
+static void push_executing_macro (), pop_executing_macro ();
+
+/* This one has to be declared earlier in the file. */
+/* static void add_macro_char (); */
+
+/* Set up to read subsequent input from STRING.
+   STRING is free ()'ed when we are done with it. */
+static void
+with_macro_input (string)
+     char *string;
+{
+  push_executing_macro ();
+  executing_macro = string;
+  executing_macro_index = 0;
+}
+
+/* Return the next character available from a macro, or 0 if
+   there are no macro characters. */
+static int
+next_macro_key ()
+{
+  if (!executing_macro)
+    return (0);
+
+  if (!executing_macro[executing_macro_index])
+    {
+      pop_executing_macro ();
+      return (next_macro_key ());
+    }
+
+  return (executing_macro[executing_macro_index++]);
+}
+
+/* Save the currently executing macro on a stack of saved macros. */
+static void
+push_executing_macro ()
+{
+  struct saved_macro *saver;
+
+  saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro));
+  saver->next = macro_list;
+  saver->sindex = executing_macro_index;
+  saver->string = executing_macro;
+
+  macro_list = saver;
+}
+
+/* Discard the current macro, replacing it with the one
+   on the top of the stack of saved macros. */
+static void
+pop_executing_macro ()
+{
+  if (executing_macro)
+    free (executing_macro);
+
+  executing_macro = (char *)NULL;
+  executing_macro_index = 0;
+
+  if (macro_list)
+    {
+      struct saved_macro *disposer = macro_list;
+      executing_macro = macro_list->string;
+      executing_macro_index = macro_list->sindex;
+      macro_list = macro_list->next;
+      free (disposer);
+    }
+}
+
+/* Add a character to the macro being built. */
+static void
+add_macro_char (c)
+     int c;
+{
+  if (current_macro_index + 1 >= current_macro_size)
+    {
+      if (!current_macro)
+       current_macro = xmalloc (current_macro_size = 25);
+      else
+       current_macro = xrealloc (current_macro, current_macro_size += 25);
+    }
+
+  current_macro[current_macro_index++] = c;
+  current_macro[current_macro_index] = '\0';
+}
+
+/* Begin defining a keyboard macro.
+   Keystrokes are recorded as they are executed.
+   End the definition with rl_end_kbd_macro ().
+   If a numeric argument was explicitly typed, then append this
+   definition to the end of the existing macro, and start by
+   re-executing the existing macro. */
+rl_start_kbd_macro (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  if (defining_kbd_macro)
+    {
+      rl_abort ();
+      return -1;
+    }
+
+  if (rl_explicit_arg)
+    {
+      if (current_macro)
+       with_macro_input (savestring (current_macro));
+    }
+  else
+    current_macro_index = 0;
+
+  defining_kbd_macro = 1;
+  return 0;
+}
+
+/* Stop defining a keyboard macro.
+   A numeric argument says to execute the macro right now,
+   that many times, counting the definition as the first time. */
+rl_end_kbd_macro (count, ignore)
+     int count, ignore;
+{
+  if (!defining_kbd_macro)
+    {
+      rl_abort ();
+      return -1;
+    }
+
+  current_macro_index -= (rl_key_sequence_length - 1);
+  current_macro[current_macro_index] = '\0';
+
+  defining_kbd_macro = 0;
+
+  return (rl_call_last_kbd_macro (--count, 0));
+}
+
+/* Execute the most recently defined keyboard macro.
+   COUNT says how many times to execute it. */
+rl_call_last_kbd_macro (count, ignore)
+     int count, ignore;
+{
+  if (!current_macro)
+    rl_abort ();
+
+  if (defining_kbd_macro)
+    {
+      ding ();         /* no recursive macros */
+      current_macro[--current_macro_index] = '\0';     /* erase this char */
+      return 0;
+    }
+
+  while (count--)
+    with_macro_input (savestring (current_macro));
+  return 0;
+}
+
+void
+_rl_kill_kbd_macro ()
+{
+  if (current_macro)
+    {
+      free (current_macro);
+      current_macro = (char *) NULL;
+    }
+  current_macro_size = current_macro_index = 0;
+
+  if (executing_macro)
+    {
+      free (executing_macro);
+      executing_macro = (char *) NULL;
+    }
+  executing_macro_index = 0;
+
+  defining_kbd_macro = 0;
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Initializations                             */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Initliaze readline (and terminal if not already). */
+rl_initialize ()
+{
+  /* If we have never been called before, initialize the
+     terminal and data structures. */
+  if (!rl_initialized)
+    {
+      readline_initialize_everything ();
+      rl_initialized++;
+    }
+
+  /* Initalize the current line information. */
+  rl_point = rl_end = 0;
+  the_line = rl_line_buffer;
+  the_line[0] = 0;
+
+  /* We aren't done yet.  We haven't even gotten started yet! */
+  rl_done = 0;
+
+  /* Tell the history routines what is going on. */
+  start_using_history ();
+
+  /* Make the display buffer match the state of the line. */
+  rl_reset_line_state ();
+
+  /* No such function typed yet. */
+  rl_last_func = (Function *)NULL;
+
+  /* Parsing of key-bindings begins in an enabled state. */
+  _rl_parsing_conditionalized_out = 0;
+
+  return 0;
+}
+
+/* Initialize the entire state of the world. */
+static void
+readline_initialize_everything ()
+{
+  char *t;
+
+  /* Find out if we are running in Emacs. */
+  running_in_emacs = getenv ("EMACS") != (char *)0;
+
+  /* Set up input and output if they are not already set up. */
+  if (!rl_instream)
+    rl_instream = stdin;
+
+  if (!rl_outstream)
+    rl_outstream = stdout;
+
+  /* Bind in_stream and out_stream immediately.  These values may change,
+     but they may also be used before readline_internal () is called. */
+  in_stream = rl_instream;
+  out_stream = rl_outstream;
+
+  /* Allocate data structures. */
+  if (!rl_line_buffer)
+    rl_line_buffer = xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
+
+  /* Initialize the terminal interface. */
+  init_terminal_io ((char *)NULL);
+
+#if !defined (__GO32__)
+  /* Bind tty characters to readline functions. */
+  readline_default_bindings ();
+#endif /* !__GO32__ */
+
+  /* Initialize the function names. */
+  rl_initialize_funmap ();
+
+  /* Check for LC_CTYPE and use its value to decide the defaults for
+     8-bit character input and output. */
+  t = getenv ("LC_CTYPE");
+  if (t && (strcmp (t, "iso-8859-1") == 0 || strcmp (t, "iso_8859_1") == 0 ||
+           strcmp (t, "ISO-8859-1") == 0))
+    {
+      _rl_meta_flag = 1;
+      _rl_convert_meta_chars_to_ascii = 0;
+      _rl_output_meta_chars = 1;
+    }
+      
+  /* Read in the init file. */
+  rl_read_init_file ((char *)NULL);
+
+  /* XXX */
+  if (_rl_horizontal_scroll_mode && term_xn)
+    {
+      screenwidth--;
+      screenchars -= screenheight;
+    }
+
+  /* Override the effect of any `set keymap' assignments in the
+     inputrc file. */
+  rl_set_keymap_from_edit_mode ();
+
+  /* Try to bind a common arrow key prefix, if not already bound. */
+  bind_arrow_keys ();
+
+  /* If the completion parser's default word break characters haven't
+     been set yet, then do so now. */
+  if (rl_completer_word_break_characters == (char *)NULL)
+    rl_completer_word_break_characters = rl_basic_word_break_characters;
+}
+
+/* If this system allows us to look at the values of the regular
+   input editing characters, then bind them to their readline
+   equivalents, iff the characters are not bound to keymaps. */
+static void
+readline_default_bindings ()
+{
+  rltty_set_default_bindings (_rl_keymap);
+}
+
+static void
+bind_arrow_keys_internal ()
+{
+  Function *f;
+
+  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);
+    }
+}
+
+/* Try and bind the common arrow key prefix 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 ();
+
+#if defined (VI_MODE)
+  _rl_keymap = vi_movement_keymap;
+  bind_arrow_keys_internal ();
+#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;
+
+  while (1)
+    {
+      rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
+      key = c = rl_read_key ();
+
+      if (_rl_keymap[c].type == ISFUNC &&
+         _rl_keymap[c].function == rl_universal_argument)
+       {
+         rl_numeric_arg *= 4;
+         continue;
+       }
+      c = UNMETA (c);
+      if (digit_p (c))
+       {
+         if (rl_explicit_arg)
+           rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
+         else
+           rl_numeric_arg = (c - '0');
+         rl_explicit_arg = 1;
+       }
+      else
+       {
+         if (c == '-' && !rl_explicit_arg)
+           {
+             rl_numeric_arg = 1;
+             rl_arg_sign = -1;
+           }
+         else
+           {
+             rl_clear_message ();
+             return (_rl_dispatch (key, _rl_keymap));
+           }
+       }
+    }
+  return 0;
+}
+
+/* Add the current digit to the argument in progress. */
+rl_digit_argument (ignore, key)
+     int ignore, key;
+{
+  rl_pending_input = key;
+  return (rl_digit_loop ());
+}
+
+/* What to do when you abort reading an argument. */
+rl_discard_argument ()
+{
+  ding ();
+  rl_clear_message ();
+  rl_init_argument ();
+  return 0;
+}
+
+/* Create a default argument. */
+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. */
+rl_universal_argument ()
+{
+  rl_numeric_arg *= 4;
+  return (rl_digit_loop ());
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Terminal and Termcap                        */
+/*                                                                 */
+/* **************************************************************** */
+
+static char *term_buffer = (char *)NULL;
+static char *term_string_buffer = (char *)NULL;
+
+static int tcap_initialized = 0;
+
+/* Non-zero means this terminal can't really do anything. */
+int dumb_term = 0;
+/* On Solaris2, sys/types.h #includes sys/reg.h, which #defines PC.
+   Unfortunately, PC is a global variable used by the termcap library. */
+#undef PC
+
+#if !defined (__linux__)
+/* If this causes problems, add back the `extern'. */
+/*extern*/ char PC, *BC, *UP;
+#endif /* __linux__ */
+
+/* Some strings to control terminal actions.  These are output by tputs (). */
+char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace;
+char *term_pc;
+
+/* Non-zero if we determine that the terminal can do character insertion. */
+int terminal_can_insert = 0;
+
+/* How to insert characters. */
+char *term_im, *term_ei, *term_ic, *term_ip, *term_IC;
+
+/* How to delete characters. */
+char *term_dc, *term_DC;
+
+#if defined (HACK_TERMCAP_MOTION)
+char *term_forward_char;
+#endif  /* HACK_TERMCAP_MOTION */
+
+/* How to go up a line. */
+char *term_up;
+
+/* A visible bell, if the terminal can be made to flash the screen. */
+char *visible_bell;
+
+/* Non-zero means that this terminal has a meta key. */
+int term_has_meta;
+
+/* The string to write to turn on the meta key, if this term has one. */
+char *term_mm;
+
+/* The string to write to turn off the meta key, if this term has one. */
+char *term_mo;
+
+/* The key sequences output by the arrow keys, if this terminal has any. */
+char *term_ku, *term_kd, *term_kr, *term_kl;
+
+/* How to initialize and reset the arrow keys, if this terminal has any. */
+char *term_ks, *term_ke;
+
+/* Re-initialize the terminal considering that the TERM/TERMCAP variable
+   has changed. */
+rl_reset_terminal (terminal_name)
+     char *terminal_name;
+{
+  init_terminal_io (terminal_name);
+  return 0;
+}
+
+/* Set readline's idea of the screen size.  TTY is a file descriptor open
+   to the terminal.  If IGNORE_ENV is true, we do not pay attention to the
+   values of $LINES and $COLUMNS.  The tests for TERM_STRING_BUFFER being
+   non-null serve to check whether or not we have initialized termcap. */
+void
+_rl_set_screen_size (tty, ignore_env)
+     int tty, ignore_env;
+{
+#if defined (TIOCGWINSZ)
+  struct winsize window_size;
+#endif /* TIOCGWINSZ */
+
+#if defined (TIOCGWINSZ)
+  if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
+    {
+      screenwidth = (int) window_size.ws_col;
+      screenheight = (int) window_size.ws_row;
+    }
+#endif /* TIOCGWINSZ */
+
+  /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
+     is unset. */
+  if (screenwidth <= 0)
+    {
+      char *sw;
+
+      if (!ignore_env && (sw = getenv ("COLUMNS")))
+       screenwidth = atoi (sw);
+
+      if (screenwidth <= 0 && term_string_buffer)
+       screenwidth = tgetnum ("co");
+    }
+
+  /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
+     is unset. */
+  if (screenheight <= 0)
+    {
+      char *sh;
+
+      if (!ignore_env && (sh = getenv ("LINES")))
+       screenheight = atoi (sh);
+
+      if (screenheight <= 0 && term_string_buffer)
+       screenheight = tgetnum ("li");
+    }
+
+  /* If all else fails, default to 80x24 terminal. */
+  if (screenwidth <= 1)
+    screenwidth = 80;
+
+  if (screenheight <= 0)
+    screenheight = 24;
+
+#if defined (SHELL)
+  /* If we're being compiled as part of bash, set the environment
+     variables $LINES and $COLUMNS to new values. */
+  set_lines_and_columns (screenheight, screenwidth);
+#endif
+
+  if (!term_xn)
+    screenwidth--;
+
+  screenchars = screenwidth * screenheight;
+}
+
+struct _tc_string {
+     char *tc_var;
+     char **tc_value;
+};
+
+/* This should be kept sorted, just in case we decide to change the
+   search algorithm to something smarter. */
+static struct _tc_string tc_strings[] =
+{
+  "DC", &term_DC,
+  "IC", &term_IC,
+  "ce", &term_clreol,
+  "cl", &term_clrpag,
+  "cr", &term_cr,
+  "dc", &term_dc,
+  "ei", &term_ei,
+  "ic", &term_ic,
+  "im", &term_im,
+  "kd", &term_kd,
+  "kl", &term_kl,
+  "kr", &term_kr,
+  "ku", &term_ku,
+  "ks", &term_ks,
+  "ke", &term_ke,
+  "le", &term_backspace,
+  "mm", &term_mm,
+  "mo", &term_mo,
+#if defined (HACK_TERMCAP_MOTION)
+  "nd", &term_forward_char,
+#endif
+  "pc", &term_pc,
+  "up", &term_up,
+  "vb", &visible_bell,
+};
+
+#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
+
+/* Read the desired terminal capability strings into BP.  The capabilities
+   are described in the TC_STRINGS table. */
+static void
+get_term_capabilities (bp)
+     char **bp;
+{
+  register int i;
+
+  for (i = 0; i < NUM_TC_STRINGS; i++)
+    *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
+  tcap_initialized = 1;
+}
+
+static int
+init_terminal_io (terminal_name)
+     char *terminal_name;
+{
+#if defined (__GO32__)
+  screenwidth = ScreenCols ();
+  screenheight = ScreenRows ();
+  screenchars = screenwidth * screenheight;
+  term_cr = "\r";
+  term_im = term_ei = term_ic = term_IC = (char *)NULL;
+  term_up = term_dc = term_DC = visible_bell = (char *)NULL;
+
+  /* Does the __GO32__ have a meta key?  I don't know. */
+  term_has_meta = 0;
+  term_mm = term_mo = (char *)NULL;
+
+  /* It probably has arrow keys, but I don't know what they are. */
+  term_ku = term_kd = term_kr = term_kl = (char *)NULL;
+
+#if defined (HACK_TERMCAP_MOTION)
+  term_forward_char = (char *)NULL;
+#endif /* HACK_TERMCAP_MOTION */
+  terminal_can_insert = term_xn = 0;
+  return;
+#else /* !__GO32__ */
+
+  char *term, *buffer;
+  int tty;
+  Keymap xkeymap;
+
+  term = terminal_name ? terminal_name : getenv ("TERM");
+
+  if (!term_string_buffer)
+    term_string_buffer = xmalloc (2048);
+
+  if (!term_buffer)
+    term_buffer = xmalloc (2048);
+
+  buffer = term_string_buffer;
+
+  term_clrpag = term_cr = term_clreol = (char *)NULL;
+
+  if (!term)
+    term = "dumb";
+
+  if (tgetent (term_buffer, term) <= 0)
+    {
+      dumb_term = 1;
+      screenwidth = 79;
+      screenheight = 24;
+      screenchars = 79 * 24;
+      term_cr = "\r";
+      term_im = term_ei = term_ic = term_IC = (char *)NULL;
+      term_up = term_dc = term_DC = visible_bell = (char *)NULL;
+      term_ku = term_kd = term_kl = term_kr = (char *)NULL;
+#if defined (HACK_TERMCAP_MOTION)
+      term_forward_char = (char *)NULL;
+#endif
+      terminal_can_insert = 0;
+      return 0;
+    }
+
+  get_term_capabilities (&buffer);
+
+  /* Set up the variables that the termcap library expects the application
+     to provide. */
+  PC = term_pc ? *term_pc : 0;
+  BC = term_backspace;
+  UP = term_up;
+
+  if (!term_cr)
+    term_cr =  "\r";
+
+  if (rl_instream)
+    tty = fileno (rl_instream);
+  else
+    tty = 0;
+
+  screenwidth = screenheight = 0;
+
+  term_xn = tgetflag ("am") && tgetflag ("xn");
+
+  _rl_set_screen_size (tty, 0);
+
+  /* "An application program can assume that the terminal can do
+      character insertion if *any one of* the capabilities `IC',
+      `im', `ic' or `ip' is provided."  But we can't do anything if
+      only `ip' is provided, so... */
+  terminal_can_insert = (term_IC || term_im || term_ic);
+
+  /* Check to see if this terminal has a meta key and clear the capability
+     variables if there is none. */
+  term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
+  if (!term_has_meta)
+    {
+      term_mm = (char *)NULL;
+      term_mo = (char *)NULL;
+    }
+
+  /* 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 (term_ku, rl_get_previous_history);
+  _rl_bind_if_unbound (term_kd, rl_get_next_history);
+  _rl_bind_if_unbound (term_kr, rl_forward);
+  _rl_bind_if_unbound (term_kl, rl_backward);
+
+#if defined (VI_MODE)
+  _rl_keymap = vi_movement_keymap;
+  _rl_bind_if_unbound (term_ku, rl_get_previous_history);
+  _rl_bind_if_unbound (term_kd, rl_get_next_history);
+  _rl_bind_if_unbound (term_kr, rl_forward);
+  _rl_bind_if_unbound (term_kl, rl_backward);
+#endif /* VI_MODE */
+
+  _rl_keymap = xkeymap;
+
+#endif /* !__GO32__ */
+  return 0;
+}
+
+char *
+rl_get_termcap (cap)
+     char *cap;
+{
+  register int i;
+
+  if (tcap_initialized == 0)
+    return ((char *)NULL);
+  for (i = 0; i < NUM_TC_STRINGS; i++)
+    {
+      if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
+        return *(tc_strings[i].tc_value);
+    }
+  return ((char *)NULL);
+}
+
+/* A function for the use of tputs () */
+int
+_rl_output_character_function (c)
+     int c;
+{
+  return putc (c, out_stream);
+}
+
+/* Write COUNT characters from STRING to the output stream. */
+void
+_rl_output_some_chars (string, count)
+     char *string;
+     int count;
+{
+  fwrite (string, 1, count, out_stream);
+}
+
+/* Move the cursor back. */
+backspace (count)
+     int count;
+{
+  register int i;
+
+#if !defined (__GO32__)
+  if (term_backspace)
+    for (i = 0; i < count; i++)
+      tputs (term_backspace, 1, _rl_output_character_function);
+  else
+#endif /* !__GO32__ */
+    for (i = 0; i < count; i++)
+      putc ('\b', out_stream);
+  return 0;
+}
+
+/* Move to the start of the next line. */
+crlf ()
+{
+#if defined (NEW_TTY_DRIVER)
+  tputs (term_cr, 1, _rl_output_character_function);
+#endif /* NEW_TTY_DRIVER */
+  putc ('\n', out_stream);
+  return 0;
+}
+
+rl_tty_status (count, key)
+     int count, key;
+{
+#if defined (TIOCSTAT)
+  ioctl (1, TIOCSTAT, (char *)0);
+  rl_refresh_line ();
+#else
+  ding ();
+#endif
+  return 0;
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Utility Functions                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Return 0 if C is not a member of the class of characters that belong
+   in words, or 1 if it is. */
+
+int allow_pathname_alphabetic_chars = 0;
+char *pathname_alphabetic_chars = "/-_=~.#$";
+
+int
+alphabetic (c)
+     int c;
+{
+  if (pure_alphabetic (c) || (digit_p (c)))
+    return (1);
+
+  if (allow_pathname_alphabetic_chars)
+    return (strchr (pathname_alphabetic_chars, c) != NULL);
+  else
+    return (0);
+}
+
+/* Ring the terminal bell. */
+int
+ding ()
+{
+  if (readline_echoing_p)
+    {
+#if !defined (__GO32__)
+      switch (_rl_bell_preference)
+        {
+       case NO_BELL:
+       default:
+         break;
+       case VISIBLE_BELL:
+         if (visible_bell)
+           {
+             tputs (visible_bell, 1, _rl_output_character_function);
+             break;
+           }
+         /* FALLTHROUGH */
+       case AUDIBLE_BELL:
+         fprintf (stderr, "\007");
+         fflush (stderr);
+         break;
+        }
+#else /* __GO32__ */
+      fprintf (stderr, "\007");
+      fflush (stderr);
+#endif /* __GO32__ */
+      return (0);
+    }
+  return (-1);
+}
+
+/* How to abort things. */
+rl_abort (count, key)
+     int count, key;
+{
+  ding ();
+  rl_clear_message ();
+  rl_init_argument ();
+  rl_pending_input = 0;
+
+  defining_kbd_macro = 0;
+  while (executing_macro)
+    pop_executing_macro ();
+
+  rl_last_func = (Function *)NULL;
+  longjmp (readline_top_level, 1);
+}
+
+/* Return a copy of the string between FROM and TO.
+   FROM is inclusive, TO is not. */
+char *
+rl_copy_text (from, to)
+     int from, to;
+{
+  register int length;
+  char *copy;
+
+  /* Fix it if the caller is confused. */
+  if (from > to)
+    {
+      int t = from;
+      from = to;
+      to = t;
+    }
+
+  length = to - from;
+  copy = xmalloc (1 + length);
+  strncpy (copy, the_line + from, length);
+  copy[length] = '\0';
+  return (copy);
+}
+
+/* Increase the size of RL_LINE_BUFFER until it has enough space to hold
+   LEN characters. */
+void
+rl_extend_line_buffer (len)
+     int len;
+{
+  while (len >= rl_line_buffer_len)
+    {
+      rl_line_buffer_len += DEFAULT_BUFFER_SIZE;
+      rl_line_buffer = xrealloc (rl_line_buffer, rl_line_buffer_len);
+    }
+
+  the_line = rl_line_buffer;
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     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. */
+rl_insert_text (string)
+     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 (!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. */
+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)
+    {
+      int t = from;
+      from = to;
+      to = t;
+    }
+
+  if (to > rl_end)
+    to = rl_end;
+
+  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 (!doing_an_undo)
+    rl_add_undo (UNDO_DELETE, from, to, text);
+  else
+    free (text);
+
+  rl_end -= diff;
+  the_line[rl_end] = '\0';
+  return (diff);
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     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.
+*/
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     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 characters. */
+rl_forward (count, key)
+     int count, key;
+{
+  if (count < 0)
+    rl_backward (-count);
+  else if (count > 0)
+    {
+      int end = rl_point + count;
+#if defined (VI_MODE)
+      int lend = rl_end - (rl_editing_mode == vi_mode);
+#else
+      int lend = rl_end;
+#endif
+
+      if (end > lend)
+       {
+         rl_point = lend;
+         ding ();
+       }
+      else
+       rl_point = end;
+    }
+  return 0;
+}
+
+/* Move backward COUNT characters. */
+rl_backward (count, key)
+     int count, key;
+{
+  if (count < 0)
+    rl_forward (-count);
+  else if (count > 0)
+    {
+      if (rl_point < count)
+       {
+         rl_point = 0;
+         ding ();
+       }
+      else
+        rl_point -= count;
+    }
+  return 0;
+}
+
+/* Move to the beginning of the line. */
+rl_beg_of_line (count, key)
+     int count, key;
+{
+  rl_point = 0;
+  return 0;
+}
+
+/* Move to the end of the line. */
+rl_end_of_line (count, key)
+     int count, key;
+{
+  rl_point = rl_end;
+  return 0;
+}
+
+/* Move forward a word.  We do what Emacs does. */
+rl_forward_word (count, key)
+     int count, key;
+{
+  int c;
+
+  if (count < 0)
+    {
+      rl_backward_word (-count);
+      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 (!alphabetic (c))
+       {
+         while (++rl_point < rl_end)
+           {
+             c = the_line[rl_point];
+             if (alphabetic (c))
+               break;
+           }
+       }
+      if (rl_point == rl_end)
+       return 0;
+      while (++rl_point < rl_end)
+       {
+         c = the_line[rl_point];
+         if (!alphabetic (c))
+           break;
+       }
+      --count;
+    }
+  return 0;
+}
+
+/* Move backward a word.  We do what Emacs does. */
+rl_backward_word (count, key)
+     int count, key;
+{
+  int c;
+
+  if (count < 0)
+    {
+      rl_forward_word (-count);
+      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 (!alphabetic (c))
+       {
+         while (--rl_point)
+           {
+             c = the_line[rl_point - 1];
+             if (alphabetic (c))
+               break;
+           }
+       }
+
+      while (rl_point)
+       {
+         c = the_line[rl_point - 1];
+         if (!alphabetic (c))
+           break;
+         else
+           --rl_point;
+       }
+      --count;
+    }
+  return 0;
+}
+
+/* Clear the current line.  Numeric argument to C-l does this. */
+rl_refresh_line ()
+{
+  int curr_line, nleft;
+
+  /* Find out whether or not there might be invisible characters in the
+     editing buffer. */
+  if (rl_display_prompt == rl_prompt)
+    nleft = _rl_last_c_pos - screenwidth - rl_visible_prompt_length;
+  else
+    nleft = _rl_last_c_pos - screenwidth;
+
+  if (nleft > 0)
+    curr_line = 1 + nleft / screenwidth;
+  else
+    curr_line = 0;
+
+  _rl_move_vert (curr_line);
+  _rl_move_cursor_relative (0, the_line);   /* XXX is this right */
+
+#if defined (__GO32__)
+  {
+    int row, col, width, row_start;
+
+    ScreenGetCursor (&row, &col);
+    width = ScreenCols ();
+    row_start = ScreenPrimary + (row * width);
+    memset (row_start + col, 0, (width - col) * 2);
+  }
+#else /* !__GO32__ */
+  if (term_clreol)
+    tputs (term_clreol, 1, _rl_output_character_function);
+#endif /* !__GO32__ */
+
+  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. */
+rl_clear_screen (count, key)
+     int count, key;
+{
+  if (rl_explicit_arg)
+    {
+      rl_refresh_line ();
+      return 0;
+    }
+
+#if !defined (__GO32__)
+  if (term_clrpag)
+    tputs (term_clrpag, 1, _rl_output_character_function);
+  else
+#endif /* !__GO32__ */
+    crlf ();
+
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+rl_arrow_keys (count, c)
+     int count, c;
+{
+  int ch;
+
+  ch = rl_read_key ();
+
+  switch (to_upper (ch))
+    {
+    case 'A':
+      rl_get_previous_history (count);
+      break;
+
+    case 'B':
+      rl_get_next_history (count);
+      break;
+
+    case 'C':
+      rl_forward (count);
+      break;
+
+    case 'D':
+      rl_backward (count);
+      break;
+
+    default:
+      ding ();
+    }
+  return 0;
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Text commands                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Insert the character C at the current location, moving point forward. */
+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 = 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 (any_typein)
+    {
+      int key = 0, t;
+
+      i = 0;
+      string = xmalloc (ibuffer_len + 1);
+      string[i++] = c;
+
+      while ((t = rl_get_char (&key)) &&
+            (_rl_keymap[key].type == ISFUNC &&
+             _rl_keymap[key].function == rl_insert))
+       string[i++] = key;
+
+      if (t)
+       rl_unget_char (key);
+
+      string[i] = '\0';
+      rl_insert_text (string);
+      free (string);
+    }
+  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. */
+rl_quoted_insert (count, key)
+     int count, key;
+{
+  int c;
+
+  c = rl_read_key ();
+  return (rl_insert (count, c));  
+}
+
+/* Insert a tab character. */
+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. */
+rl_newline (count, key)
+     int count, key;
+{
+  rl_done = 1;
+
+#if defined (VI_MODE)
+  _rl_vi_done_inserting ();
+  _rl_vi_reset_last ();
+
+#endif /* VI_MODE */
+
+  if (readline_echoing_p)
+    _rl_update_final ();
+  return 0;
+}
+
+rl_clean_up_for_exit ()
+{
+  if (readline_echoing_p)
+    {
+      _rl_move_vert (_rl_vis_botlin);
+      _rl_vis_botlin = 0;
+      fflush (out_stream);
+      rl_restart_output ();
+    }
+  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. */
+rl_do_lowercase_version (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  return 0;
+}
+
+/* Rubout the character behind point. */
+rl_rubout (count, key)
+     int count, key;
+{
+  if (count < 0)
+    {
+      rl_delete (-count);
+      return 0;
+    }
+
+  if (!rl_point)
+    {
+      ding ();
+      return -1;
+    }
+
+  if (count > 1 || rl_explicit_arg)
+    {
+      int orig_point = rl_point;
+      rl_backward (count);
+      rl_kill_text (orig_point, rl_point);
+    }
+  else
+    {
+      int 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. */
+rl_delete (count, invoking_key)
+     int count, invoking_key;
+{
+  if (count < 0)
+    {
+      return (rl_rubout (-count));
+    }
+
+  if (rl_point == rl_end)
+    {
+      ding ();
+      return -1;
+    }
+
+  if (count > 1 || rl_explicit_arg)
+    {
+      int orig_point = rl_point;
+      rl_forward (count);
+      rl_kill_text (orig_point, rl_point);
+      rl_point = orig_point;
+      return 0;
+    }
+  else
+    return (rl_delete_text (rl_point, rl_point + 1));
+  
+}
+
+/* Delete all spaces and tabs around point. */
+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;
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Kill commands                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The next two functions mimic unix line editing behaviour, except they
+   save the deleted text on the kill ring.  This is safer than not saving
+   it, and since we have a ring, nobody should get screwed. */
+
+/* This does what C-w does in Unix.  We can't prevent people from
+   using behaviour that they expect. */
+rl_unix_word_rubout (count, key)
+     int count, key;
+{
+  if (!rl_point)
+    ding ();
+  else
+    {
+      int orig_point = rl_point;
+      if (count <= 0)
+       count = 1;
+
+      while (count--)
+       {
+         while (rl_point && whitespace (the_line[rl_point - 1]))
+           rl_point--;
+
+         while (rl_point && !whitespace (the_line[rl_point - 1]))
+           rl_point--;
+       }
+
+      rl_kill_text (orig_point, rl_point);
+    }
+  return 0;
+}
+
+/* Here is C-u doing what Unix does.  You don't *have* to use these
+   key-bindings.  We have a choice of killing the entire line, or
+   killing from where we are to the start of the line.  We choose the
+   latter, because if you are a Unix weenie, then you haven't backspaced
+   into the line at all, and if you aren't, then you know what you are
+   doing. */
+rl_unix_line_discard (count, key)
+     int count, key;
+{
+  if (!rl_point)
+    ding ();
+  else
+    {
+      rl_kill_text (rl_point, 0);
+      rl_point = 0;
+    }
+  return 0;
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Commands For Typos                          */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Random and interesting things in here.  */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Changing Case                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The three kinds of things that we know how to do. */
+#define UpCase 1
+#define DownCase 2
+#define CapCase 3
+
+static int rl_change_case ();
+
+/* Uppercase the word at point. */
+rl_upcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, UpCase));
+}
+
+/* Lowercase the word at point. */
+rl_downcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, DownCase));
+}
+
+/* Upcase the first letter, downcase the rest. */
+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 = rl_point, end;
+  int state = 0;
+
+  rl_forward_word (count);
+  end = rl_point;
+
+  if (count < 0)
+    {
+      int temp = start;
+      start = end;
+      end = temp;
+    }
+
+  /* We are going to modify some text, so let's prepare to undo it. */
+  rl_modifying (start, end);
+
+  for (; start < end; start++)
+    {
+      switch (op)
+       {
+       case UpCase:
+         the_line[start] = to_upper (the_line[start]);
+         break;
+
+       case DownCase:
+         the_line[start] = to_lower (the_line[start]);
+         break;
+
+       case CapCase:
+         if (state == 0)
+           {
+             the_line[start] = to_upper (the_line[start]);
+             state = 1;
+           }
+         else
+           {
+             the_line[start] = to_lower (the_line[start]);
+           }
+         if (!pure_alphabetic (the_line[start]))
+           state = 0;
+         break;
+
+       default:
+         ding ();
+         return -1;
+       }
+    }
+  rl_point = end;
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Transposition                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Transpose the words at point. */
+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);
+  w2_end = rl_point;
+  rl_backward_word (1);
+  w2_beg = rl_point;
+  rl_backward_word (count);
+  w1_beg = rl_point;
+  rl_forward_word (1);
+  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))
+    {
+      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. */
+rl_transpose_chars (count, key)
+     int count, key;
+{
+  char dummy[2];
+
+  if (!count)
+    return 0;
+
+  if (!rl_point || rl_end < 2)
+    {
+      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;
+  if (rl_point > rl_end)
+    rl_point = rl_end;
+  else if (rl_point < 0)
+    rl_point = 0;
+  rl_insert_text (dummy);
+
+  rl_end_undo_group ();
+  return 0;
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Undo, and Undoing                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The current undo list for THE_LINE. */
+UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
+
+/* Remember how to undo something.  Concatenate some undos if that
+   seems right. */
+void
+rl_add_undo (what, start, end, text)
+     enum undo_code what;
+     int start, end;
+     char *text;
+{
+  UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
+  temp->what = what;
+  temp->start = start;
+  temp->end = end;
+  temp->text = text;
+  temp->next = rl_undo_list;
+  rl_undo_list = temp;
+}
+
+/* Free the existing undo list. */
+void
+free_undo_list ()
+{
+  while (rl_undo_list)
+    {
+      UNDO_LIST *release = rl_undo_list;
+      rl_undo_list = rl_undo_list->next;
+
+      if (release->what == UNDO_DELETE)
+       free (release->text);
+
+      free (release);
+    }
+  rl_undo_list = (UNDO_LIST *)NULL;
+}
+
+/* Undo the next thing in the list.  Return 0 if there
+   is nothing to undo, or non-zero if there was. */
+int
+rl_do_undo ()
+{
+  UNDO_LIST *release;
+  int waiting_for_begin = 0;
+
+undo_thing:
+  if (!rl_undo_list)
+    return (0);
+
+  doing_an_undo = 1;
+
+  switch (rl_undo_list->what) {
+
+    /* Undoing deletes means inserting some text. */
+  case UNDO_DELETE:
+    rl_point = rl_undo_list->start;
+    rl_insert_text (rl_undo_list->text);
+    free (rl_undo_list->text);
+    break;
+
+    /* Undoing inserts means deleting some text. */
+  case UNDO_INSERT:
+    rl_delete_text (rl_undo_list->start, rl_undo_list->end);
+    rl_point = rl_undo_list->start;
+    break;
+
+    /* Undoing an END means undoing everything 'til we get to
+       a BEGIN. */
+  case UNDO_END:
+    waiting_for_begin++;
+    break;
+
+    /* Undoing a BEGIN means that we are done with this group. */
+  case UNDO_BEGIN:
+    if (waiting_for_begin)
+      waiting_for_begin--;
+    else
+      ding ();
+    break;
+  }
+
+  doing_an_undo = 0;
+
+  release = rl_undo_list;
+  rl_undo_list = rl_undo_list->next;
+  free (release);
+
+  if (waiting_for_begin)
+    goto undo_thing;
+
+  return (1);
+}
+
+/* Begin a group.  Subsequent undos are undone as an atomic operation. */
+int
+rl_begin_undo_group ()
+{
+  rl_add_undo (UNDO_BEGIN, 0, 0, 0);
+  return 0;
+}
+
+/* End an undo group started with rl_begin_undo_group (). */
+int
+rl_end_undo_group ()
+{
+  rl_add_undo (UNDO_END, 0, 0, 0);
+  return 0;
+}
+
+/* Save an undo entry for the text from START to END. */
+rl_modifying (start, end)
+     int start, end;
+{
+  if (start > end)
+    {
+      int t = start;
+      start = end;
+      end = t;
+    }
+
+  if (start != end)
+    {
+      char *temp = rl_copy_text (start, end);
+      rl_begin_undo_group ();
+      rl_add_undo (UNDO_DELETE, start, end, temp);
+      rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
+      rl_end_undo_group ();
+    }
+  return 0;
+}
+
+/* Revert the current line to its previous state. */
+int
+rl_revert_line (count, key)
+     int count, key;
+{
+  if (!rl_undo_list)
+    ding ();
+  else
+    {
+      while (rl_undo_list)
+       rl_do_undo ();
+    }
+  return 0;
+}
+
+/* Do some undoing of things that were done. */
+int
+rl_undo_command (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return 0;  /* Nothing to do. */
+
+  while (count)
+    {
+      if (rl_do_undo ())
+       count--;
+      else
+       {
+         ding ();
+         break;
+       }
+    }
+  return 0;
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Utilities                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* We already have a history library, and that is what we use to control
+   the history features of readline.  However, 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 *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 (saved_line_for_history)
+    _rl_free_history_entry (saved_line_for_history);
+
+  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)
+    return;
+  if (entry->line)
+    free (entry->line);
+  free (entry);
+}
+
+/* Perhaps put back the current line if it has changed. */
+maybe_replace_line ()
+{
+  HIST_ENTRY *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, rl_undo_list);
+      free (temp->line);
+      free (temp);
+    }
+  return 0;
+}
+
+/* Put back the saved_line_for_history if there is one. */
+maybe_unsave_line ()
+{
+  if (saved_line_for_history)
+    {
+      int line_len;
+
+      line_len = strlen (saved_line_for_history->line);
+
+      if (line_len >= rl_line_buffer_len)
+       rl_extend_line_buffer (line_len);
+
+      strcpy (the_line, saved_line_for_history->line);
+      rl_undo_list = (UNDO_LIST *)saved_line_for_history->data;
+      _rl_free_history_entry (saved_line_for_history);
+      saved_line_for_history = (HIST_ENTRY *)NULL;
+      rl_end = rl_point = strlen (the_line);
+    }
+  else
+    ding ();
+  return 0;
+}
+
+/* Save the current line in saved_line_for_history. */
+maybe_save_line ()
+{
+  if (!saved_line_for_history)
+    {
+      saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+      saved_line_for_history->line = savestring (the_line);
+      saved_line_for_history->data = (char *)rl_undo_list;
+    }
+  return 0;
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Commands                            */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Meta-< goes to the start of the history. */
+rl_beginning_of_history (count, key)
+     int count, key;
+{
+  return (rl_get_previous_history (1 + where_history ()));
+}
+
+/* Meta-> goes to the end of the history.  (The current line). */
+rl_end_of_history (count, key)
+     int count, key;
+{
+  maybe_replace_line ();
+  using_history ();
+  maybe_unsave_line ();
+  return 0;
+}
+
+/* Move down to the next history line. */
+rl_get_next_history (count, key)
+     int count, key;
+{
+  HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
+
+  if (count < 0)
+    return (rl_get_previous_history (-count));
+
+  if (!count)
+    return 0;
+
+  maybe_replace_line ();
+
+  while (count)
+    {
+      temp = next_history ();
+      if (!temp)
+       break;
+      --count;
+    }
+
+  if (!temp)
+    maybe_unsave_line ();
+  else
+    {
+      int line_len;
+
+      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 = rl_point = strlen (the_line);
+#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. */
+rl_get_previous_history (count, key)
+     int count, key;
+{
+  HIST_ENTRY *old_temp = (HIST_ENTRY *)NULL;
+  HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
+
+  if (count < 0)
+    return (rl_get_next_history (-count));
+
+  if (!count)
+    return 0;
+
+  /* If we don't have a line saved, then save this one. */
+  maybe_save_line ();
+
+  /* If the current line has changed, save the changes. */
+  maybe_replace_line ();
+
+  while (count)
+    {
+      temp = previous_history ();
+      if (!temp)
+       break;
+      else
+       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)
+    ding ();
+  else
+    {
+      int line_len;
+
+      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 = rl_point = line_len;
+
+#if defined (VI_MODE)
+      if (rl_editing_mode == vi_mode)
+       rl_point = 0;
+#endif /* VI_MODE */
+    }
+  return 0;
+}
+
+/* Make C be the next command to be executed. */
+rl_execute_next (c)
+     int c;
+{
+  rl_pending_input = c;
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                The Mark and the Region.                         */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Set the mark at POSITION. */
+rl_set_mark (position)
+     int position;
+{
+  if (position > rl_end)
+    return -1;
+
+  rl_mark = position;
+  return 0;
+}
+
+/* Exchange the position of mark and point. */
+rl_exchange_mark_and_point (count, key)
+     int count, key;
+{
+  if (rl_mark > rl_end)
+    rl_mark = -1;
+
+  if (rl_mark == -1)
+    {
+      ding ();
+      return -1;
+    }
+  else
+    {
+      int temp = rl_point;
+
+      rl_point = rl_mark;
+      rl_mark = temp;
+    }
+  return 0;
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Killing Mechanism                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* What we assume for a max number of kills. */
+#define DEFAULT_MAX_KILLS 10
+
+/* The real variable to look at to find out when to flush kills. */
+int rl_max_kills =  DEFAULT_MAX_KILLS;
+
+/* Where to store killed text. */
+char **rl_kill_ring = (char **)NULL;
+
+/* Where we are in the kill ring. */
+int rl_kill_index = 0;
+
+/* How many slots we have in the kill ring. */
+int rl_kill_ring_length = 0;
+
+/* How to say that you only want to save a certain amount
+   of kill material. */
+rl_set_retained_kills (num)
+     int num;
+{
+  return 0;
+}
+
+/* The way to kill something.  This appends or prepends to the last
+   kill, if the last command was a kill command.  if FROM is less
+   than TO, then the text is appended, otherwise prepended.  If the
+   last command was not a kill command, then a new slot is made for
+   this kill. */
+rl_kill_text (from, to)
+     int from, to;
+{
+  int slot;
+  char *text;
+
+  /* Is there anything to kill? */
+  if (from == to)
+    {
+      last_command_was_kill++;
+      return 0;
+    }
+
+  text = rl_copy_text (from, to);
+
+  /* Delete the copied text from the line. */
+  rl_delete_text (from, to);
+
+  /* First, find the slot to work with. */
+  if (!last_command_was_kill)
+    {
+      /* Get a new slot.  */
+      if (!rl_kill_ring)
+       {
+         /* If we don't have any defined, then make one. */
+         rl_kill_ring = (char **)
+           xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *));
+         rl_kill_ring[slot = 0] = (char *)NULL;
+       }
+      else
+       {
+         /* We have to add a new slot on the end, unless we have
+            exceeded the max limit for remembering kills. */
+         slot = rl_kill_ring_length;
+         if (slot == rl_max_kills)
+           {
+             register int i;
+             free (rl_kill_ring[0]);
+             for (i = 0; i < slot; i++)
+               rl_kill_ring[i] = rl_kill_ring[i + 1];
+           }
+         else
+           {
+             slot = rl_kill_ring_length += 1;
+             rl_kill_ring = (char **)xrealloc (rl_kill_ring, slot * sizeof (char *));
+           }
+         rl_kill_ring[--slot] = (char *)NULL;
+       }
+    }
+  else
+    slot = rl_kill_ring_length - 1;
+
+  /* If the last command was a kill, prepend or append. */
+  if (last_command_was_kill && rl_editing_mode != vi_mode)
+    {
+      char *old = rl_kill_ring[slot];
+      char *new = xmalloc (1 + strlen (old) + strlen (text));
+
+      if (from < to)
+       {
+         strcpy (new, old);
+         strcat (new, text);
+       }
+      else
+       {
+         strcpy (new, text);
+         strcat (new, old);
+       }
+      free (old);
+      free (text);
+      rl_kill_ring[slot] = new;
+    }
+  else
+    {
+      rl_kill_ring[slot] = text;
+    }
+  rl_kill_index = slot;
+  last_command_was_kill++;
+  return 0;
+}
+
+/* Now REMEMBER!  In order to do prepending or appending correctly, kill
+   commands always make rl_point's original position be the FROM argument,
+   and rl_point's extent be the TO argument. */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Killing Commands                            */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Delete the word at point, saving the text in the kill ring. */
+rl_kill_word (count, key)
+     int count, key;
+{
+  int orig_point = rl_point;
+
+  if (count < 0)
+    return (rl_backward_kill_word (-count));
+  else
+    {
+      rl_forward_word (count);
+
+      if (rl_point != orig_point)
+       rl_kill_text (orig_point, rl_point);
+
+      rl_point = orig_point;
+    }
+  return 0;
+}
+
+/* Rubout the word before point, placing it on the kill ring. */
+rl_backward_kill_word (count, ignore)
+     int count, ignore;
+{
+  int orig_point = rl_point;
+
+  if (count < 0)
+    return (rl_kill_word (-count));
+  else
+    {
+      rl_backward_word (count);
+
+      if (rl_point != orig_point)
+       rl_kill_text (orig_point, rl_point);
+    }
+  return 0;
+}
+
+/* Kill from here to the end of the line.  If DIRECTION is negative, kill
+   back to the line start instead. */
+rl_kill_line (direction, ignore)
+     int direction, ignore;
+{
+  int orig_point = rl_point;
+
+  if (direction < 0)
+    return (rl_backward_kill_line (1));
+  else
+    {
+      rl_end_of_line (1, ignore);
+      if (orig_point != rl_point)
+       rl_kill_text (orig_point, rl_point);
+      rl_point = orig_point;
+    }
+  return 0;
+}
+
+/* Kill backwards to the start of the line.  If DIRECTION is negative, kill
+   forwards to the line end instead. */
+rl_backward_kill_line (direction, ignore)
+     int direction, ignore;
+{
+  int orig_point = rl_point;
+
+  if (direction < 0)
+    return (rl_kill_line (1));
+  else
+    {
+      if (!rl_point)
+       ding ();
+      else
+       {
+         rl_beg_of_line (1, ignore);
+         rl_kill_text (orig_point, rl_point);
+       }
+    }
+  return 0;
+}
+
+/* Kill the whole line, no matter where point is. */
+rl_kill_full_line (count, ignore)
+     int count, ignore;
+{
+  rl_begin_undo_group ();
+  rl_point = 0;
+  rl_kill_text (rl_point, rl_end);
+  rl_end_undo_group ();
+  return 0;
+}
+
+/* Yank back the last killed text.  This ignores arguments. */
+rl_yank (count, ignore)
+     int count, ignore;
+{
+  if (!rl_kill_ring)
+    {
+      rl_abort (count, ignore);
+      return -1;
+    }
+
+  rl_set_mark (rl_point);
+  rl_insert_text (rl_kill_ring[rl_kill_index]);
+  return 0;
+}
+
+/* If the last command was yank, or yank_pop, and the text just
+   before point is identical to the current kill item, then
+   delete that text from the line, rotate the index down, and
+   yank back some other text. */
+rl_yank_pop (count, key)
+     int count, key;
+{
+  int l;
+
+  if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) ||
+      !rl_kill_ring)
+    {
+      rl_abort (1, key);
+      return -1;
+    }
+
+  l = strlen (rl_kill_ring[rl_kill_index]);
+  if (((rl_point - l) >= 0) &&
+      (strncmp (the_line + (rl_point - l),
+               rl_kill_ring[rl_kill_index], l) == 0))
+    {
+      rl_delete_text ((rl_point - l), rl_point);
+      rl_point -= l;
+      rl_kill_index--;
+      if (rl_kill_index < 0)
+       rl_kill_index = rl_kill_ring_length - 1;
+      rl_yank (1, 0);
+      return 0;
+    }
+  else
+    {
+      rl_abort (1, key);
+      return -1;
+    }
+}
+
+/* Yank the COUNTth argument from the previous history line. */
+rl_yank_nth_arg (count, ignore)
+     int count, ignore;
+{
+  register HIST_ENTRY *entry = previous_history ();
+  char *arg;
+
+  if (entry)
+    next_history ();
+  else
+    {
+      ding ();
+      return -1;
+    }
+
+  arg = history_arg_extract (count, count, entry->line);
+  if (!arg || !*arg)
+    {
+      ding ();
+      return -1;
+    }
+
+  rl_begin_undo_group ();
+
+#if defined (VI_MODE)
+  /* Vi mode always inserts a space before yanking the argument, and it
+     inserts it right *after* rl_point. */
+  if (rl_editing_mode == vi_mode)
+    {
+      rl_vi_append_mode ();
+      rl_insert_text (" ");
+    }
+#endif /* VI_MODE */
+
+  rl_insert_text (arg);
+  free (arg);
+
+  rl_end_undo_group ();
+  return 0;
+}
+
+/* Yank the last argument from the previous history line.  This `knows'
+   how rl_yank_nth_arg treats a count of `$'.  With an argument, this
+   behaves the same as rl_yank_nth_arg. */
+int
+rl_yank_last_arg (count, key)
+     int count, key;
+{
+  if (rl_explicit_arg)
+    return (rl_yank_nth_arg (count, key));
+  else
+    return (rl_yank_nth_arg ('$', key));
+}
+
+/* How to toggle back and forth between editing modes. */
+rl_vi_editing_mode (count, key)
+     int count, key;
+{
+#if defined (VI_MODE)
+  rl_editing_mode = vi_mode;
+  rl_vi_insertion_mode ();
+  return 0;
+#endif /* VI_MODE */
+}
+
+rl_emacs_editing_mode (count, key)
+     int count, key;
+{
+  rl_editing_mode = emacs_mode;
+  _rl_keymap = emacs_standard_keymap;
+  return 0;
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     USG (System V) Support                      */
+/*                                                                 */
+/* **************************************************************** */
+
+int
+rl_getc (stream)
+     FILE *stream;
+{
+  int result;
+  unsigned char c;
+
+#if defined (__GO32__)
+  if (isatty (0))
+    return (getkey () & 0x7F);
+#endif /* __GO32__ */
+
+  while (1)
+    {
+      result = read (fileno (stream), &c, sizeof (unsigned char));
+
+      if (result == sizeof (unsigned char))
+       return (c);
+
+      /* If zero characters are returned, then the file that we are
+        reading from is empty!  Return EOF in that case. */
+      if (result == 0)
+       return (EOF);
+
+#if defined (EWOULDBLOCK)
+      if (errno == EWOULDBLOCK)
+       {
+         int flags;
+
+         if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0)
+           return (EOF);
+         if (flags & O_NDELAY)
+           {
+             flags &= ~O_NDELAY;
+             fcntl (fileno (stream), F_SETFL, flags);
+             continue;
+           }
+         continue;
+       }
+#endif /* EWOULDBLOCK */
+
+#if defined (_POSIX_VERSION) && defined (EAGAIN) && defined (O_NONBLOCK)
+      if (errno == EAGAIN)
+       {
+         int flags;
+
+         if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0)
+           return (EOF);
+         if (flags & O_NONBLOCK)
+           {
+             flags &= ~O_NONBLOCK;
+             fcntl (fileno (stream), F_SETFL, flags);
+             continue;
+           }
+       }
+#endif /* _POSIX_VERSION && EAGAIN && O_NONBLOCK */
+
+#if !defined (__GO32__)
+      /* If the error that we received was SIGINT, then try again,
+        this is simply an interrupted system call to read ().
+        Otherwise, some error ocurred, also signifying EOF. */
+      if (errno != EINTR)
+       return (EOF);
+#endif /* !__GO32__ */
+    }
+}
+
+#if !defined (SHELL)
+#ifdef savestring
+#undef savestring
+#endif
+/* Backwards compatibilty, now that savestring has been removed from
+   all `public' readline header files. */
+char *
+savestring (s)
+     char *s;
+{
+  return ((char *)strcpy (xmalloc (1 + (int)strlen (s)), (s)));
+}
+#endif
+
+/* Function equivalents for the macros defined in chartypes.h. */
+#undef uppercase_p
+int
+uppercase_p (c)
+     int c;
+{
+  return (isupper (c));
+}
+
+#undef lowercase_p
+int
+lowercase_p (c)
+     int c;
+{
+  return (islower (c));
+}
+
+#undef pure_alphabetic
+int
+pure_alphabetic (c)
+     int c;
+{
+  return (isupper (c) || islower (c));
+}
+
+#undef digit_p
+int
+digit_p (c)
+     int c;
+{
+  return (isdigit (c));
+}
+
+#undef to_lower
+int
+to_lower (c)
+     int c;
+{
+  return (isupper (c) ? tolower (c) : c);
+}
+
+#undef to_upper
+int
+to_upper (c)
+     int c;
+{
+  return (islower (c) ? toupper (c) : c);
+}
+
+#undef digit_value
+int
+digit_value (c)
+     int c;
+{
+  return (isdigit (c) ? c - '0' : c);
+}
+
+#if defined (STATIC_MALLOC)
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Testing Readline                            */
+/*                                                                 */
+/* **************************************************************** */
+
+#if defined (TEST)
+
+main ()
+{
+  HIST_ENTRY **history_list ();
+  char *temp = (char *)NULL;
+  char *prompt = "readline% ";
+  int done = 0;
+
+  while (!done)
+    {
+      temp = readline (prompt);
+
+      /* Test for EOF. */
+      if (!temp)
+       exit (1);
+
+      /* If there is anything on the line, print it and remember it. */
+      if (*temp)
+       {
+         fprintf (stderr, "%s\r\n", temp);
+         add_history (temp);
+       }
+
+      /* Check for `command' that we handle. */
+      if (strcmp (temp, "quit") == 0)
+       done = 1;
+
+      if (strcmp (temp, "list") == 0)
+       {
+         HIST_ENTRY **list = history_list ();
+         register int i;
+         if (list)
+           {
+             for (i = 0; list[i]; i++)
+               {
+                 fprintf (stderr, "%d: %s\r\n", i, list[i]->line);
+                 free (list[i]->line);
+               }
+             free (list);
+           }
+       }
+      free (temp);
+    }
+}
+
+#endif /* TEST */
+
+\f
+/*
+ * Local variables:
+ * compile-command: "gcc -g -traditional -I. -I.. -DTEST -o readline readline.c keymaps.o funmap.o history.o -ltermcap"
+ * end:
+ */
diff --git a/lib/readline/readline.h b/lib/readline/readline.h
new file mode 100644 (file)
index 0000000..b397177
--- /dev/null
@@ -0,0 +1,289 @@
+/* Readline.h -- the names of functions callable from within readline. */
+
+/* Copyright (C) 1987, 1989, 1992 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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_READLINE_H_)
+#define _READLINE_H_
+
+#if defined (READLINE_LIBRARY)
+#  include "keymaps.h"
+#  include "tilde.h"
+#else
+#  include <readline/keymaps.h>
+#  include <readline/tilde.h>
+#endif
+
+/* The functions for manipulating the text of the line within readline.
+Most of these functions are bound to keys by default. */
+extern int
+  rl_tilde_expand (),
+  rl_beg_of_line (), rl_backward (), rl_delete (), rl_end_of_line (),
+  rl_forward (), ding (), rl_backward (), rl_newline (), rl_kill_line (),
+  rl_clear_screen (), rl_get_next_history (), rl_get_previous_history (),
+  rl_quoted_insert (), rl_reverse_search_history (), rl_transpose_chars (),
+  rl_unix_line_discard (), rl_quoted_insert (), rl_unix_word_rubout (),
+  rl_yank (), rl_rubout (), rl_backward_word (), rl_kill_word (),
+  rl_forward_word (), rl_tab_insert (), rl_yank_pop (), rl_yank_nth_arg (),
+  rl_backward_kill_word (), rl_backward_kill_line (), rl_transpose_words (),
+  rl_complete (), rl_possible_completions (), rl_insert_completions (),
+  rl_do_lowercase_version (), rl_kill_full_line (),
+  rl_digit_argument (), rl_universal_argument (), rl_abort (),
+  rl_undo_command (), rl_revert_line (), rl_beginning_of_history (),
+  rl_end_of_history (), rl_forward_search_history (), rl_insert (),
+  rl_upcase_word (), rl_downcase_word (), rl_capitalize_word (),
+  rl_restart_output (), rl_re_read_init_file (), rl_dump_functions (),
+  rl_delete_horizontal_space (), rl_history_search_forward (),
+  rl_history_search_backward (), rl_tty_status (), rl_yank_last_arg ();
+
+/* `Public' utility functions. */
+extern int rl_insert_text (), rl_delete_text (), rl_kill_text ();
+extern int rl_complete_internal ();
+extern int rl_expand_prompt ();
+extern int rl_initialize ();
+extern int rl_set_signals (), rl_clear_signals ();
+extern int rl_init_argument (), rl_digit_argument ();
+extern int rl_read_key (), rl_getc (), rl_stuff_char ();
+extern int maybe_save_line (), maybe_unsave_line (), maybe_replace_line ();
+extern int rl_modifying ();
+
+extern int rl_begin_undo_group (), rl_end_undo_group ();
+extern void rl_add_undo (), free_undo_list ();
+extern int rl_do_undo ();
+
+/* Not available unless readline is compiled -DPAREN_MATCHING. */
+extern int rl_insert_close ();
+
+/* These are *both* defined even when VI_MODE is not. */
+extern int rl_vi_editing_mode (), rl_emacs_editing_mode ();
+
+/* Non incremental history searching. */
+extern int
+  rl_noninc_forward_search (), rl_noninc_reverse_search (),
+  rl_noninc_forward_search_again (), rl_noninc_reverse_search_again ();
+
+/* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */
+extern int rl_vi_check (), rl_vi_textmod_command ();
+extern int
+  rl_vi_redo (), rl_vi_tilde_expand (),
+  rl_vi_movement_mode (), rl_vi_insertion_mode (), rl_vi_arg_digit (),
+  rl_vi_prev_word (), rl_vi_next_word (), rl_vi_char_search (),
+  rl_vi_eof_maybe (), rl_vi_append_mode (), rl_vi_put (),
+  rl_vi_append_eol (), rl_vi_insert_beg (), rl_vi_delete (), rl_vi_comment (),
+  rl_vi_first_print (), rl_vi_fword (), rl_vi_fWord (), rl_vi_bword (),
+  rl_vi_bWord (), rl_vi_eword (), rl_vi_eWord (), rl_vi_end_word (),
+  rl_vi_change_case (), rl_vi_match (), rl_vi_bracktype (),
+  rl_vi_change_char (), rl_vi_yank_arg (), rl_vi_search (),
+  rl_vi_search_again (),  rl_vi_subst (), rl_vi_overstrike (),
+  rl_vi_overstrike_delete (), rl_vi_replace(), rl_vi_column (),
+  rl_vi_delete_to (), rl_vi_change_to (), rl_vi_yank_to (),
+  rl_vi_complete (), rl_vi_fetch_history ();
+
+/* Keyboard macro commands. */
+extern int rl_start_kbd_macro (), rl_end_kbd_macro ();
+extern int rl_call_last_kbd_macro ();
+
+extern int rl_arrow_keys(), rl_refresh_line ();
+
+/* Maintaining the state of undo.  We remember individual deletes and inserts
+   on a chain of things to do. */
+
+/* The actions that undo knows how to undo.  Notice that UNDO_DELETE means
+   to insert some text, and UNDO_INSERT means to delete some text.   I.e.,
+   the code tells undo what to undo, not how to undo it. */
+enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END };
+
+/* What an element of THE_UNDO_LIST looks like. */
+typedef struct undo_list {
+  struct undo_list *next;
+  int start, end;              /* Where the change took place. */
+  char *text;                  /* The text to insert, if undoing a delete. */
+  enum undo_code what;         /* Delete, Insert, Begin, End. */
+} UNDO_LIST;
+
+/* The current undo list for RL_LINE_BUFFER. */
+extern UNDO_LIST *rl_undo_list;
+
+/* The data structure for mapping textual names to code addresses. */
+typedef struct {
+  char *name;
+  Function *function;
+} FUNMAP;
+
+extern FUNMAP **funmap;
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Well Published Variables                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The name of the calling program.  You should initialize this to
+   whatever was in argv[0].  It is used when parsing conditionals. */
+extern char *rl_readline_name;
+
+/* The line buffer that is in use. */
+extern char *rl_line_buffer;
+
+/* The location of point, and end. */
+extern int rl_point, rl_end;
+
+/* The name of the terminal to use. */
+extern char *rl_terminal_name;
+
+/* The input and output streams. */
+extern FILE *rl_instream, *rl_outstream;
+
+/* The basic list of characters that signal a break between words for the
+   completer routine.  The initial contents of this variable is what
+   breaks words in the shell, i.e. "n\"\\'`@$>". */
+extern char *rl_basic_word_break_characters;
+
+/* The list of characters that signal a break between words for
+   rl_complete_internal.  The default list is the contents of
+   rl_basic_word_break_characters.  */
+extern char *rl_completer_word_break_characters;
+
+/* List of characters which can be used to quote a substring of the line.
+   Completion occurs on the entire substring, and within the substring   
+   rl_completer_word_break_characters are treated as any other character,
+   unless they also appear within this list. */
+extern char *rl_completer_quote_characters;
+
+/* List of characters that are word break characters, but should be left
+   in TEXT when it is passed to the completion function.  The shell uses
+   this to help determine what kind of completing to do. */
+extern char *rl_special_prefixes;
+
+/* Pointer to the generator function for completion_matches ().
+   NULL means to use filename_entry_function (), the default filename
+   completer. */
+extern Function *rl_completion_entry_function;
+
+/* If rl_ignore_some_completions_function is non-NULL it is the address
+   of a function to call after all of the possible matches have been
+   generated, but before the actual completion is done to the input line.
+   The function is called with one argument; a NULL terminated array
+   of (char *).  If your function removes any of the elements, they
+   must be free()'ed. */
+extern Function *rl_ignore_some_completions_function;
+
+/* Pointer to alternative function to create matches.
+   Function is called with TEXT, START, and END.
+   START and END are indices in RL_LINE_BUFFER saying what the boundaries
+   of TEXT are.
+   If this function exists and returns NULL then call the value of
+   rl_completion_entry_function to try to match, otherwise use the
+   array of strings returned. */
+extern CPPFunction *rl_attempted_completion_function;
+
+/* If non-zero, then this is the address of a function to call just
+   before readline_internal () prints the first prompt. */
+extern Function *rl_startup_hook;
+
+/* If non-zero, then this is the address of a function to call when
+   completing on a directory name.  The function is called with
+   the address of a string (the current directory name) as an arg. */
+extern Function *rl_directory_completion_hook;
+
+/* Backwards compatibility with previous versions of readline. */
+#define rl_symbolic_link_hook rl_directory_completion_hook
+
+/* The address of a function to call periodically while Readline is
+   awaiting character input, or NULL, for no event handling. */
+extern Function *rl_event_hook;
+
+/* Non-zero means that modified history lines are preceded
+   with an asterisk. */
+extern int rl_show_star;
+
+/* Non-zero means that the results of the matches are to be treated
+   as filenames.  This is ALWAYS zero on entry, and can only be changed
+   within a completion entry finder function. */
+extern int rl_filename_completion_desired;
+
+/* Non-zero means that the results of the matches are to be quoted using
+   double quotes (or an application-specific quoting mechanism) if the
+   filename contains any characters in rl_word_break_chars.  This is
+   ALWAYS non-zero on entry, and can only be changed within a completion
+   entry finder function. */
+extern int rl_filename_quoting_desired;
+
+/* Non-zero means to suppress normal filename completion after the
+   user-specified completion function has been called. */
+extern int rl_attempted_completion_over;
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Well Published Functions                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Read a line of input.  Prompt with PROMPT.  A NULL PROMPT means none. */
+extern char *readline ();
+
+/* These functions are from complete.c. */
+/* Return an array of strings which are the result of repeatadly calling
+   FUNC with TEXT. */
+extern char **completion_matches ();
+extern char *username_completion_function ();
+extern char *filename_completion_function ();
+
+/* These functions are from bind.c. */
+/* rl_add_defun (char *name, Function *function, int key)
+   Add NAME to the list of named functions.  Make FUNCTION
+   be the function that gets called.
+   If KEY is not -1, then bind it. */
+extern int rl_add_defun ();
+extern int rl_bind_key (), rl_bind_key_in_map ();
+extern int rl_unbind_key (), rl_unbind_key_in_map ();
+extern int rl_set_key ();
+extern int rl_macro_bind (), rl_generic_bind (), rl_variable_bind ();
+extern int rl_translate_keyseq ();
+extern Function *rl_named_function (), *rl_function_of_keyseq ();
+extern int rl_parse_and_bind ();
+extern Keymap rl_get_keymap (), rl_get_keymap_by_name ();
+extern void rl_set_keymap ();
+extern char **rl_invoking_keyseqs (), **rl_invoking_keyseqs_in_map ();
+extern void rl_function_dumper ();
+extern int rl_read_init_file ();
+
+/* Functions in funmap.c */
+extern void rl_list_funmap_names ();
+extern void rl_initialize_funmap ();
+
+/* Functions in display.c */
+extern void rl_redisplay ();
+extern int rl_message (), rl_clear_message ();
+extern int rl_reset_line_state ();
+extern int rl_character_len ();
+extern int rl_show_char ();
+extern int crlf (), rl_on_new_line ();
+extern int rl_forced_update_display ();
+
+/* Definitions available for use by readline clients. */
+#define RL_PROMPT_START_IGNORE '\001'
+#define RL_PROMPT_END_IGNORE   '\002'
+
+#if !defined (savestring)
+extern char *savestring ();    /* XXX backwards compatibility */
+#endif
+
+#endif /* _READLINE_H_ */
diff --git a/lib/readline/rlconf.h b/lib/readline/rlconf.h
new file mode 100644 (file)
index 0000000..0035b93
--- /dev/null
@@ -0,0 +1,57 @@
+/* rlconf.h -- readline configuration definitions */
+
+/* Copyright (C) 1994 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
+   for it.
+
+   The 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 1, or (at your option)
+   any later version.
+
+   The 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_RLCONF_H_)
+#define _RLCONF_H_
+
+/* Define this if you want the vi-mode editing available. */
+#define VI_MODE
+
+/* Define this to get an indication of file type when listing completions. */
+#define VISIBLE_STATS
+
+/* If defined, readline shows opening parens and braces when closing
+   paren or brace entered. */
+/* #define PAREN_MATCHING */
+
+/* This definition is needed by readline.c, rltty.c, and signals.c. */
+/* If on, then readline handles signals in a way that doesn't screw. */
+#define HANDLE_SIGNALS
+
+/* Ugly but working hack for binding prefix meta. */
+#define PREFIX_META_HACK
+
+/* The final, last-ditch effort file name for an init file. */
+#define DEFAULT_INPUTRC "~/.inputrc"
+
+/* If defined, expand tabs to spaces. */
+#define DISPLAY_TABS
+
+/* If defined, use the terminal escape sequence to move the cursor forward
+   over a character when updating the line rather than rewriting it. */
+/* #define HACK_TERMCAP_MOTION */
+
+/* The string inserted by the vi-mode `insert comment' command. */
+#define VI_COMMENT_BEGIN_DEFAULT "#"
+
+#endif /* _RLCONF_H_ */
diff --git a/lib/readline/rldefs.h b/lib/readline/rldefs.h
new file mode 100644 (file)
index 0000000..683f8b5
--- /dev/null
@@ -0,0 +1,212 @@
+/* rldefs.h -- an attempt to isolate some of the system-specific defines
+   for readline.  This should be included after any files that define
+   system-specific constants like _POSIX_VERSION or USG. */
+
+/* Copyright (C) 1987,1989 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
+   for it.
+
+   The 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 1, or (at your option)
+   any later version.
+
+   The 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_RLDEFS_H)
+#define _RLDEFS_H
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#if !defined (PRAGMA_ALLOCA)
+#  include "memalloc.h"
+#endif
+
+#define NEW_TTY_DRIVER
+#define HAVE_BSD_SIGNALS
+/* #define USE_XON_XOFF */
+
+#if defined (__linux__) || defined (HAVE_TERMCAP_H)
+#  include <termcap.h>
+#endif /* __linux__ || HAVE_TERMCAP_H */
+
+/* Some USG machines have BSD signal handling (sigblock, sigsetmask, etc.) */
+#if defined (USG) && !defined (hpux)
+#  undef HAVE_BSD_SIGNALS
+#endif
+
+/* System V machines use termio. */
+#if !defined (_POSIX_VERSION)
+#  if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || \
+      defined (DGUX) || defined (HAVE_TERMIO_H)
+#    undef NEW_TTY_DRIVER
+#    define TERMIO_TTY_DRIVER
+#    include <termio.h>
+#    if !defined (TCOON)
+#      define TCOON 1
+#    endif
+#  endif /* USG || hpux || Xenix || sgi || DUGX || HAVE_TERMIO_H */
+#endif /* !_POSIX_VERSION */
+
+/* Posix systems use termios and the Posix signal functions. */
+#if defined (_POSIX_VERSION)
+#  if !defined (TERMIOS_MISSING)
+#    undef NEW_TTY_DRIVER
+#    define TERMIOS_TTY_DRIVER
+#    include <termios.h>
+#  endif /* !TERMIOS_MISSING */
+#  define HAVE_POSIX_SIGNALS
+#  if !defined (O_NDELAY)
+#    define O_NDELAY O_NONBLOCK        /* Posix-style non-blocking i/o */
+#  endif /* O_NDELAY */
+#endif /* _POSIX_VERSION */
+
+/* System V.3 machines have the old 4.1 BSD `reliable' signal interface. */
+#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
+#  if defined (USGr3) && !defined (XENIX_22)
+#    if !defined (HAVE_USG_SIGHOLD)
+#      define HAVE_USG_SIGHOLD
+#    endif /* !HAVE_USG_SIGHOLD */
+#  endif /* USGr3 && !XENIX_22 */
+#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
+
+/* Other (BSD) machines use sgtty. */
+#if defined (NEW_TTY_DRIVER)
+#  include <sgtty.h>
+#endif
+
+#if !defined (SHELL) && (defined (_POSIX_VERSION) || defined (USGr3))
+#  if !defined (HAVE_DIRENT_H)
+#    define HAVE_DIRENT_H
+#  endif /* !HAVE_DIRENT_H */
+#endif /* !SHELL && (_POSIX_VERSION || USGr3) */
+
+#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 (USG)
+#    if defined (Xenix)
+#      include <sys/ndir.h>
+#    else /* !Xenix (but USG...) */
+#      include "ndir.h"
+#    endif /* !Xenix */
+#  else /* !USG */
+#    include <sys/dir.h>
+#  endif /* !USG */
+#  if !defined (dirent)
+#    define dirent direct
+#  endif /* !dirent */
+#endif /* !HAVE_DIRENT_H */
+
+#if defined (USG) && defined (TIOCGWINSZ) && !defined (Linux)
+#  if defined (HAVE_SYS_STREAM_H)
+#    include <sys/stream.h>
+#  endif /* HAVE_SYS_STREAM_H */
+#  if defined (HAVE_SYS_PTEM_H)
+#    include <sys/ptem.h>
+#  endif /* HAVE_SYS_PTEM_H */
+#  if defined (HAVE_SYS_PTE_H)
+#    include <sys/pte.h>
+#  endif /* HAVE_SYS_PTE_H */
+#endif /* USG && TIOCGWINSZ && !Linux */
+
+/* Posix macro to check file in statbuf for directory-ness.
+   This requires that <sys/stat.h> be included before this test. */
+#if defined (S_IFDIR) && !defined (S_ISDIR)
+#  define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
+#endif
+
+/* Decide which flavor of the header file describing the C library
+   string functions to include and include it. */
+
+#if defined (USG) || defined (NeXT)
+#  if !defined (HAVE_STRING_H)
+#    define HAVE_STRING_H
+#  endif /* !HAVE_STRING_H */
+#endif /* USG || NeXT */
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+#if defined (HAVE_VARARGS_H)
+#  include <varargs.h>
+#endif /* HAVE_VARARGS_H */
+
+/* This is needed to include support for TIOCGWINSZ and window resizing. */
+#if defined (OSF1) || defined (BSD386) || defined (NetBSD) || \
+    defined (__BSD_4_4__) || defined (FreeBSD) || defined (_386BSD) || \
+    defined (AIX)
+#  define GWINSZ_IN_SYS_IOCTL
+#endif
+
+/* Define _POSIX_VDISABLE if we are not using the `new' tty driver and
+   it is not already defined.  It is used both to determine if a
+   special character is disabled and to disable certain special
+   characters.  Posix systems should set to 0, USG systems to -1. */
+#if !defined (NEW_TTY_DRIVER) && !defined (_POSIX_VDISABLE)
+#  if defined (_SVR4_VDISABLE)
+#    define _POSIX_VDISABLE _SVR4_VDISABLE
+#  else
+#    if defined (_POSIX_VERSION)
+#      define _POSIX_VDISABLE 0
+#    else /* !_POSIX_VERSION */
+#      define _POSIX_VDISABLE -1
+#    endif /* !_POSIX_VERSION */
+#  endif /* !_SVR4_VDISABLE */
+#endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */
+
+
+#if !defined (emacs_mode)
+#  define no_mode -1
+#  define vi_mode 0
+#  define emacs_mode 1
+#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
+   to functions and pointers to structs are different sizes).
+   This is not what is wanted. */
+#if defined (CRAY)
+#  define FUNCTION_TO_KEYMAP(map, key) (Keymap)((int)map[key].function)
+#  define KEYMAP_TO_FUNCTION(data)     (Function *)((int)(data))
+#else
+#  define FUNCTION_TO_KEYMAP(map, key) (Keymap)(map[key].function)
+#  define KEYMAP_TO_FUNCTION(data)     (Function *)(data)
+#endif
+
+#ifndef savestring
+extern char *xmalloc ();
+#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
+#endif
+
+/* Possible values for _rl_bell_preference. */
+#define NO_BELL 0
+#define AUDIBLE_BELL 1
+#define VISIBLE_BELL 2
+
+/* CONFIGURATION SECTION */
+#include "rlconf.h"
+
+#endif /* !_RLDEFS_H */
diff --git a/lib/readline/rltty.c b/lib/readline/rltty.c
new file mode 100644 (file)
index 0000000..02c036d
--- /dev/null
@@ -0,0 +1,705 @@
+/* rltty.c -- functions to prepare and restore the terminal for readline's
+   use. */
+
+/* Copyright (C) 1992 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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include "rldefs.h"
+#include "readline.h"
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+extern int readline_echoing_p;
+extern int _rl_eof_char;
+
+#if defined (__GO32__)
+#  include <sys/pc.h>
+#  undef HANDLE_SIGNALS
+#endif /* __GO32__ */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                        Signal Management                        */
+/*                                                                 */
+/* **************************************************************** */
+
+#if defined (HAVE_POSIX_SIGNALS)
+static sigset_t sigint_set, sigint_oset;
+#else /* !HAVE_POSIX_SIGNALS */
+#  if defined (HAVE_BSD_SIGNALS)
+static int sigint_oldmask;
+#  endif /* HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+static int sigint_blocked = 0;
+
+/* Cause SIGINT to not be delivered until the corresponding call to
+   release_sigint(). */
+static void
+block_sigint ()
+{
+  if (sigint_blocked)
+    return;
+
+#if defined (HAVE_POSIX_SIGNALS)
+  sigemptyset (&sigint_set);
+  sigemptyset (&sigint_oset);
+  sigaddset (&sigint_set, SIGINT);
+  sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
+#else /* !HAVE_POSIX_SIGNALS */
+#  if defined (HAVE_BSD_SIGNALS)
+  sigint_oldmask = sigblock (sigmask (SIGINT));
+#  else /* !HAVE_BSD_SIGNALS */
+#    if defined (HAVE_USG_SIGHOLD)
+  sighold (SIGINT);
+#    endif /* HAVE_USG_SIGHOLD */
+#  endif /* !HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+  sigint_blocked = 1;
+}
+
+/* Allow SIGINT to be delivered. */
+static void
+release_sigint ()
+{
+  if (!sigint_blocked)
+    return;
+
+#if defined (HAVE_POSIX_SIGNALS)
+  sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
+#else
+#  if defined (HAVE_BSD_SIGNALS)
+  sigsetmask (sigint_oldmask);
+#  else /* !HAVE_BSD_SIGNALS */
+#    if defined (HAVE_USG_SIGHOLD)
+  sigrelse (SIGINT);
+#    endif /* HAVE_USG_SIGHOLD */
+#  endif /* !HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+  sigint_blocked = 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*             Controlling the Meta Key and Keypad                 */
+/*                                                                 */
+/* **************************************************************** */
+
+extern int term_has_meta;
+extern char *term_mm;
+extern char *term_mo;
+
+extern char *term_ks;
+extern char *term_ke;
+
+static int
+outchar (c)
+     int c;
+{
+  return putc (c, rl_outstream);
+}
+
+/* Turn on/off the meta key depending on ON. */
+static void
+control_meta_key (on)
+     int on;
+{
+  if (term_has_meta)
+    {
+      if (on && term_mm)
+       tputs (term_mm, 1, outchar);
+      else if (!on && term_mo)
+       tputs (term_mo, 1, outchar);
+    }
+}
+
+#if 0
+static void
+control_keypad (on)
+     int on;
+{
+  if (on && term_ks)
+    tputs (term_ks, 1, outchar);
+  else if (!on && term_ke)
+    tputs (term_ke, 1, outchar);
+}
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*                   Saving and Restoring the TTY                  */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero means that the terminal is in a prepped state. */
+static int terminal_prepped = 0;
+
+/* If non-zero, means that this process has called tcflow(fd, TCOOFF)
+   and output is suspended. */
+#if defined (__ksr1__)
+static int ksrflow = 0;
+#endif
+#if defined (NEW_TTY_DRIVER)
+
+/* Values for the `flags' field of a struct bsdtty.  This tells which
+   elements of the struct bsdtty have been fetched from the system and
+   are valid. */
+#define SGTTY_SET      0x01
+#define LFLAG_SET      0x02
+#define TCHARS_SET     0x04
+#define LTCHARS_SET    0x08
+
+struct bsdtty {
+  struct sgttyb sgttyb;        /* Basic BSD tty driver information. */
+  int lflag;           /* Local mode flags, like LPASS8. */
+#if defined (TIOCGETC)
+  struct tchars tchars;        /* Terminal special characters, including ^S and ^Q. */
+#endif
+#if defined (TIOCGLTC)
+  struct ltchars ltchars; /* 4.2 BSD editing characters */
+#endif
+  int flags;           /* Bitmap saying which parts of the struct are valid. */
+};
+
+#define TIOTYPE struct bsdtty
+
+static TIOTYPE otio;
+
+static int
+get_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+#if !defined (SHELL) && defined (TIOCGWINSZ)
+  struct winsize w;
+
+  if (ioctl (tty, TIOCGWINSZ, &w) == 0)
+      (void) ioctl (tty, TIOCSWINSZ, &w);
+#endif
+
+  tiop->flags = tiop->lflag = 0;
+
+  ioctl (tty, TIOCGETP, &(tiop->sgttyb));
+  tiop->flags |= SGTTY_SET;
+
+#if defined (TIOCLGET)
+  ioctl (tty, TIOCLGET, &(tiop->lflag));
+  tiop->flags |= LFLAG_SET;
+#endif
+
+#if defined (TIOCGETC)
+  ioctl (tty, TIOCGETC, &(tiop->tchars));
+  tiop->flags |= TCHARS_SET;
+#endif
+
+#if defined (TIOCGLTC)
+  ioctl (tty, TIOCGLTC, &(tiop->ltchars));
+  tiop->flags |= LTCHARS_SET;
+#endif
+
+  return 0;
+}
+
+set_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+  if (tiop->flags & SGTTY_SET)
+    {
+      ioctl (tty, TIOCSETN, &(tiop->sgttyb));
+      tiop->flags &= ~SGTTY_SET;
+    }
+  readline_echoing_p = 1;
+
+#if defined (TIOCLSET)
+  if (tiop->flags & LFLAG_SET)
+    {
+      ioctl (tty, TIOCLSET, &(tiop->lflag));
+      tiop->flags &= ~LFLAG_SET;
+    }
+#endif
+
+#if defined (TIOCSETC)
+  if (tiop->flags & TCHARS_SET)
+    {
+      ioctl (tty, TIOCSETC, &(tiop->tchars));
+      tiop->flags &= ~TCHARS_SET;
+    }
+#endif
+
+#if defined (TIOCSLTC)
+  if (tiop->flags & LTCHARS_SET)
+    {
+      ioctl (tty, TIOCSLTC, &(tiop->ltchars));
+      tiop->flags &= ~LTCHARS_SET;
+    }
+#endif
+
+  return 0;
+}
+
+static void
+prepare_terminal_settings (meta_flag, otio, tiop)
+     int meta_flag;
+     TIOTYPE otio, *tiop;
+{
+#if !defined (__GO32__)
+  readline_echoing_p = (otio.sgttyb.sg_flags & ECHO);
+
+  /* Copy the original settings to the structure we're going to use for
+     our settings. */
+  tiop->sgttyb = otio.sgttyb;
+  tiop->lflag = otio.lflag;
+#if defined (TIOCGETC)
+  tiop->tchars = otio.tchars;
+#endif
+#if defined (TIOCGLTC)
+  tiop->ltchars = otio.ltchars;
+#endif
+  tiop->flags = otio.flags;
+
+  /* First, the basic settings to put us into character-at-a-time, no-echo
+     input mode. */
+  tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD);
+  tiop->sgttyb.sg_flags |= CBREAK;
+
+  /* If this terminal doesn't care how the 8th bit is used, then we can
+     use it for the meta-key.  If only one of even or odd parity is
+     specified, then the terminal is using parity, and we cannot. */
+#if !defined (ANYP)
+#  define ANYP (EVENP | ODDP)
+#endif
+  if (((otio.sgttyb.sg_flags & ANYP) == ANYP) ||
+      ((otio.sgttyb.sg_flags & ANYP) == 0))
+    {
+      tiop->sgttyb.sg_flags |= ANYP;
+
+      /* Hack on local mode flags if we can. */
+#if defined (TIOCLGET)
+#  if defined (LPASS8)
+      tiop->lflag |= LPASS8;
+#  endif /* LPASS8 */
+#endif /* TIOCLGET */
+    }
+
+#if defined (TIOCGETC)
+#  if defined (USE_XON_XOFF)
+  /* Get rid of terminal output start and stop characters. */
+  tiop->tchars.t_stopc = -1; /* C-s */
+  tiop->tchars.t_startc = -1; /* C-q */
+
+  /* If there is an XON character, bind it to restart the output. */
+  if (otio.tchars.t_startc != -1)
+    rl_bind_key (otio.tchars.t_startc, rl_restart_output);
+#  endif /* USE_XON_XOFF */
+
+  /* If there is an EOF char, bind _rl_eof_char to it. */
+  if (otio.tchars.t_eofc != -1)
+    _rl_eof_char = otio.tchars.t_eofc;
+
+#  if defined (NO_KILL_INTR)
+  /* Get rid of terminal-generated SIGQUIT and SIGINT. */
+  tiop->tchars.t_quitc = -1; /* C-\ */
+  tiop->tchars.t_intrc = -1; /* C-c */
+#  endif /* NO_KILL_INTR */
+#endif /* TIOCGETC */
+
+#if defined (TIOCGLTC)
+  /* Make the interrupt keys go away.  Just enough to make people happy. */
+  tiop->ltchars.t_dsuspc = -1; /* C-y */
+  tiop->ltchars.t_lnextc = -1; /* C-v */
+#endif /* TIOCGLTC */
+#endif /* !__GO32__ */
+}
+
+#else  /* !defined (NEW_TTY_DRIVER) */
+
+#if !defined (VMIN)
+#  define VMIN VEOF
+#endif
+
+#if !defined (VTIME)
+#  define VTIME VEOL
+#endif
+
+#if defined (TERMIOS_TTY_DRIVER)
+#  define TIOTYPE struct termios
+#  define DRAIN_OUTPUT(fd)     tcdrain (fd)
+#  define GETATTR(tty, tiop)   (tcgetattr (tty, tiop))
+#  define SETATTR(tty, tiop)   (tcsetattr (tty, TCSANOW, tiop))
+#else
+#  define TIOTYPE struct termio
+#  define DRAIN_OUTPUT(fd)
+#  define GETATTR(tty, tiop)   (ioctl (tty, TCGETA, tiop))
+#  define SETATTR(tty, tiop)   (ioctl (tty, TCSETA, tiop))
+#endif /* !TERMIOS_TTY_DRIVER */
+
+static TIOTYPE otio;
+
+#if defined (FLUSHO)
+#  define OUTPUT_BEING_FLUSHED(tp)  (tp->c_lflag & FLUSHO)
+#else
+#  define OUTPUT_BEING_FLUSHED(tp)  0
+#endif
+
+static int
+get_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+  int ioctl_ret;
+#if !defined (SHELL) && defined (TIOCGWINSZ)
+  struct winsize w;
+
+  if (ioctl (tty, TIOCGWINSZ, &w) == 0)
+      (void) ioctl (tty, TIOCSWINSZ, &w);
+#endif
+
+  /* Keep looping if output is being flushed after a ^O (or whatever
+     the flush character is). */
+  while ((ioctl_ret = GETATTR (tty, tiop)) < 0 || OUTPUT_BEING_FLUSHED (tiop))
+    {
+      if (ioctl_ret < 0 && errno != EINTR)
+       return -1;
+      if (OUTPUT_BEING_FLUSHED (tiop))
+        continue;
+      errno = 0;
+    }
+  return 0;
+}
+
+static int
+set_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+  while (SETATTR (tty, tiop) < 0)
+    {
+      if (errno != EINTR)
+       return -1;
+      errno = 0;
+    }
+
+#if 0
+
+#if defined (TERMIOS_TTY_DRIVER)
+#  if defined (__ksr1__)
+  if (ksrflow)
+    {
+      ksrflow = 0;
+      tcflow (tty, TCOON);
+    }
+#  else /* !ksr1 */
+  tcflow (tty, TCOON);         /* Simulate a ^Q. */
+#  endif /* !ksr1 */
+#else
+  ioctl (tty, TCXONC, 1);      /* Simulate a ^Q. */
+#endif /* !TERMIOS_TTY_DRIVER */
+
+#endif
+
+  return 0;
+}
+
+static void
+prepare_terminal_settings (meta_flag, otio, tiop)
+     int meta_flag;
+     TIOTYPE otio, *tiop;
+{
+  readline_echoing_p = (otio.c_lflag & ECHO);
+
+  tiop->c_lflag &= ~(ICANON | ECHO);
+
+  if ((unsigned char) otio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
+    _rl_eof_char = otio.c_cc[VEOF];
+
+#if defined (USE_XON_XOFF)
+#if defined (IXANY)
+  tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
+#else
+  /* `strict' Posix systems do not define IXANY. */
+  tiop->c_iflag &= ~(IXON | IXOFF);
+#endif /* IXANY */
+#endif /* USE_XON_XOFF */
+
+  /* Only turn this off if we are using all 8 bits. */
+  if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
+    tiop->c_iflag &= ~(ISTRIP | INPCK);
+
+  /* Make sure we differentiate between CR and NL on input. */
+  tiop->c_iflag &= ~(ICRNL | INLCR);
+
+#if !defined (HANDLE_SIGNALS)
+  tiop->c_lflag &= ~ISIG;
+#else
+  tiop->c_lflag |= ISIG;
+#endif
+
+  tiop->c_cc[VMIN] = 1;
+  tiop->c_cc[VTIME] = 0;
+
+#if defined (FLUSHO)
+  if (OUTPUT_BEING_FLUSHED (tiop))
+    {
+      tiop->c_lflag &= ~FLUSHO;
+      otio.c_lflag &= ~FLUSHO;
+    }
+#endif
+
+  /* Turn off characters that we need on Posix systems with job control,
+     just to be sure.  This includes ^Y and ^V.  This should not really
+     be necessary.  */
+#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE)
+
+#if defined (VLNEXT)
+  tiop->c_cc[VLNEXT] = _POSIX_VDISABLE;
+#endif
+
+#if defined (VDSUSP)
+  tiop->c_cc[VDSUSP] = _POSIX_VDISABLE;
+#endif
+
+#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */
+}
+#endif  /* NEW_TTY_DRIVER */
+
+/* Put the terminal in CBREAK mode so that we can detect key presses. */
+void
+rl_prep_terminal (meta_flag)
+     int meta_flag;
+{
+#if !defined (__GO32__)
+  int tty = fileno (rl_instream);
+  TIOTYPE tio;
+
+  if (terminal_prepped)
+    return;
+
+  /* Try to keep this function from being INTerrupted. */
+  block_sigint ();
+
+  if (get_tty_settings (tty, &tio) < 0)
+    {
+      release_sigint ();
+      return;
+    }
+
+  otio = tio;
+
+  prepare_terminal_settings (meta_flag, otio, &tio);
+
+  if (set_tty_settings (tty, &tio) < 0)
+    {
+      release_sigint ();
+      return;
+    }
+
+  control_meta_key (1);
+#if 0
+  control_keypad (1);
+#endif
+  fflush (rl_outstream);
+  terminal_prepped = 1;
+
+  release_sigint ();
+#endif /* !__GO32__ */
+}
+
+/* Restore the terminal's normal settings and modes. */
+void
+rl_deprep_terminal ()
+{
+#if !defined (__GO32__)
+  int tty = fileno (rl_instream);
+
+  if (!terminal_prepped)
+    return;
+
+  /* Try to keep this function from being INTerrupted. */
+  block_sigint ();
+
+  control_meta_key (0);
+#if 0
+  control_keypad (0);
+#endif
+  fflush (rl_outstream);
+
+  if (set_tty_settings (tty, &otio) < 0)
+    {
+      release_sigint ();
+      return;
+    }
+
+  terminal_prepped = 0;
+
+  release_sigint ();
+#endif /* !__GO32__ */
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Bogus Flow Control                          */
+/*                                                                 */
+/* **************************************************************** */
+
+rl_restart_output (count, key)
+     int count, key;
+{
+  int fildes = fileno (rl_outstream);
+#if defined (TIOCSTART)
+#if defined (apollo)
+  ioctl (&fildes, TIOCSTART, 0);
+#else
+  ioctl (fildes, TIOCSTART, 0);
+#endif /* apollo */
+
+#else /* !TIOCSTART */
+#  if defined (TERMIOS_TTY_DRIVER)
+#    if defined (__ksr1__)
+  if (ksrflow)
+    {
+      ksrflow = 0;
+      tcflow (fildes, TCOON);
+    }
+#    else /* !ksr1 */
+  tcflow (fildes, TCOON);              /* Simulate a ^Q. */
+#    endif /* !ksr1 */
+#  else /* !TERMIOS_TTY_DRIVER */
+#    if defined (TCXONC)
+  ioctl (fildes, TCXONC, TCOON);
+#    endif /* TCXONC */
+#  endif /* !TERMIOS_TTY_DRIVER */
+#endif /* !TIOCSTART */
+
+  return 0;
+}
+
+rl_stop_output (count, key)
+     int count, key;
+{
+  int fildes = fileno (rl_instream);
+
+#if defined (TIOCSTOP)
+# if defined (apollo)
+  ioctl (&fildes, TIOCSTOP, 0);
+# else
+  ioctl (fildes, TIOCSTOP, 0);
+# endif /* apollo */
+#else /* !TIOCSTOP */
+# if defined (TERMIOS_TTY_DRIVER)
+#  if defined (__ksr1__)
+  ksrflow = 1;
+#  endif /* ksr1 */
+  tcflow (fildes, TCOOFF);
+# else
+#   if defined (TCXONC)
+  ioctl (fildes, TCXONC, TCOON);
+#   endif /* TCXONC */
+# endif /* !TERMIOS_TTY_DRIVER */
+#endif /* !TIOCSTOP */
+
+  return 0;
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Default Key Bindings                        */
+/*                                                                 */
+/* **************************************************************** */
+void
+rltty_set_default_bindings (kmap)
+     Keymap kmap;
+{
+  TIOTYPE ttybuff;
+  int tty = fileno (rl_instream);
+
+#if defined (NEW_TTY_DRIVER)
+
+#define SET_SPECIAL(sc, func) \
+  do \
+    { \
+      int ic; \
+      ic = sc; \
+      if (ic != -1 && kmap[ic].type == ISFUNC) \
+       kmap[ic].function = func; \
+    } \
+  while (0)
+
+  if (get_tty_settings (tty, &ttybuff) == 0)
+    {
+      if (ttybuff.flags & SGTTY_SET)
+       {
+         SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
+         SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
+       }
+
+#  if defined (TIOCGLTC)
+      if (ttybuff.flags & LTCHARS_SET)
+       {
+         SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
+         SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
+       }
+#  endif /* TIOCGLTC */
+    }
+
+#else /* !NEW_TTY_DRIVER */
+
+#define SET_SPECIAL(sc, func) \
+  do \
+    { \
+      unsigned char uc; \
+      uc = ttybuff.c_cc[sc]; \
+      if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
+       kmap[uc].function = func; \
+    } \
+  while (0)
+
+  if (get_tty_settings (tty, &ttybuff) == 0)
+    {
+      SET_SPECIAL (VERASE, rl_rubout);
+      SET_SPECIAL (VKILL, rl_unix_line_discard);
+
+#  if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
+      SET_SPECIAL (VLNEXT, rl_quoted_insert);
+#  endif /* VLNEXT && TERMIOS_TTY_DRIVER */
+
+#  if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
+      SET_SPECIAL (VWERASE, rl_unix_word_rubout);
+#  endif /* VWERASE && TERMIOS_TTY_DRIVER */
+    }
+#endif /* !NEW_TTY_DRIVER */
+}
diff --git a/lib/readline/search.c b/lib/readline/search.c
new file mode 100644 (file)
index 0000000..d56e554
--- /dev/null
@@ -0,0 +1,370 @@
+/* search.c - code for non-incremental searching in emacs and vi modes. */
+
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+
+   This file is part of the Readline Library (the Library), a set of
+   routines for providing Emacs style line input to programs that ask
+   for it.
+
+   The 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 1, or (at your option)
+   any later version.
+
+   The 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#include <sys/types.h>
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include "rldefs.h"
+#include "readline.h"
+#include "history.h"
+
+#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))
+
+#define abs(x)         (((x) > 0) ? (x) : -(x))
+
+extern char *xmalloc (), *xrealloc ();
+
+/* Variables imported from readline.c */
+extern int rl_point, rl_end, rl_line_buffer_len;
+extern Keymap _rl_keymap;
+extern int rl_editing_mode;
+extern char *rl_prompt;
+extern char *rl_line_buffer;
+extern HIST_ENTRY *saved_line_for_history;
+extern Function *rl_last_func;
+
+/* Functions imported from the rest of the library. */
+extern int _rl_free_history_entry ();
+
+static char *noninc_search_string = (char *) NULL;
+static int noninc_history_pos = 0;
+static char *prev_line_found = (char *) NULL;
+
+/* Search the history list for STRING starting at absolute history position
+   POS.  If STRING begins with `^', the search must match STRING at the
+   beginning of a history line, otherwise a full substring match is performed
+   for STRING.  DIR < 0 means to search backwards through the history list,
+   DIR >= 0 means to search forward. */
+static int
+noninc_search_from_pos (string, pos, dir)
+     char *string;
+     int pos, dir;
+{
+  int ret, old;
+
+  old = where_history ();
+  history_set_pos (pos);
+
+  if (*string == '^')
+    ret = history_search_prefix (string + 1, dir);
+  else
+    ret = history_search (string, dir);
+
+  if (ret != -1)
+    ret = where_history ();
+
+  history_set_pos (old);
+  return (ret);
+}
+
+/* Search for a line in the history containing STRING.  If DIR is < 0, the
+   search is backwards through previous entries, else through subsequent
+   entries. */
+static void
+noninc_dosearch (string, dir)
+     char *string;
+     int dir;
+{
+  int oldpos, pos;
+  HIST_ENTRY *entry;
+
+  if (string == 0 || *string == '\0' || noninc_history_pos < 0)
+    {
+      ding ();
+      return;
+    }
+
+  pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
+  if (pos == -1)
+    {
+      /* Search failed, current history position unchanged. */
+      maybe_unsave_line ();
+      rl_clear_message ();
+      rl_point = 0;
+      ding ();
+      return;
+    }
+
+  noninc_history_pos = pos;
+
+  oldpos = where_history ();
+  history_set_pos (noninc_history_pos);
+  entry = current_history ();
+#if defined (VI_MODE)
+  if (rl_editing_mode != vi_mode)
+#endif
+  history_set_pos (oldpos);
+
+  {
+    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_undo_list = (UNDO_LIST *)entry->data;
+  rl_end = strlen (rl_line_buffer);
+  rl_point = 0;
+  rl_clear_message ();
+
+  if (saved_line_for_history)
+    _rl_free_history_entry (saved_line_for_history);
+  saved_line_for_history = (HIST_ENTRY *)NULL;
+}
+
+/* Search non-interactively through the history list.  DIR < 0 means to
+   search backwards through the history of previous commands; otherwise
+   the search is for commands subsequent to the current position in the
+   history list.  PCHAR is the character to use for prompting when reading
+   the search string; if not specified (0), it defaults to `:'. */
+static void
+noninc_search (dir, pchar)
+     int dir;
+     int pchar;
+{
+  int saved_point, c, pmtlen;
+  char *p;
+
+  maybe_save_line ();
+  saved_point = rl_point;
+
+  /* Use the line buffer to read the search string. */
+  rl_line_buffer[0] = 0;
+  rl_end = rl_point = 0;
+
+  /* XXX - this needs fixing to work with the prompt expansion stuff - XXX */
+  pmtlen = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
+  p = xmalloc (2 + pmtlen);
+  if (pmtlen)
+    strcpy (p, rl_prompt);
+  p[pmtlen] = pchar ? pchar : ':';
+  p[pmtlen + 1]  = '\0';
+
+  rl_message (p, 0, 0);
+  free (p);
+
+  /* Read the search string. */
+  while (c = rl_read_key ())
+    {
+      switch (c)
+       {
+       case CTRL('H'):
+       case RUBOUT:
+         if (rl_point == 0)
+           {
+             maybe_unsave_line ();
+             rl_clear_message ();
+             rl_point = saved_point;
+             return;
+           }
+         rl_rubout (1);
+         break;
+
+       case CTRL('W'):
+         rl_unix_word_rubout (1, c);
+         break;
+
+       case CTRL('U'):
+         rl_unix_line_discard (1, c);
+         break;
+
+       case RETURN:
+       case NEWLINE:
+         goto dosearch;
+         /* NOTREACHED */
+         break;
+
+       case CTRL('C'):
+       case CTRL('G'):
+         maybe_unsave_line ();
+         rl_clear_message ();
+         rl_point = saved_point;
+         ding ();
+         return;
+
+       default:
+         rl_insert (1, c);
+         break;
+       }
+      rl_redisplay ();
+    }
+
+ dosearch:
+  /* 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. */
+  if (rl_point == 0)
+    {
+      if (!noninc_search_string)
+       {
+         ding ();
+         return;
+       }
+    }
+  else
+    {
+      /* We want to start the search from the current history position. */
+      noninc_history_pos = where_history ();
+      if (noninc_search_string)
+       free (noninc_search_string);
+      noninc_search_string = savestring (rl_line_buffer);
+    }
+
+  noninc_dosearch (noninc_search_string, dir);
+}
+
+/* Search forward through the history list for a string.  If the vi-mode
+   code calls this, KEY will be `?'. */
+rl_noninc_forward_search (count, key)
+     int count, key;
+{
+  if (key == '?')
+    noninc_search (1, '?');
+  else
+    noninc_search (1, 0);
+  return 0;
+}
+
+/* Reverse search the history list for a string.  If the vi-mode code
+   calls this, KEY will be `/'. */
+rl_noninc_reverse_search (count, key)
+     int count, key;
+{
+  if (key == '/')
+    noninc_search (-1, '/');
+  else
+    noninc_search (-1, 0);
+  return 0;
+}
+
+/* Search forward through the history list for the last string searched
+   for.  If there is no saved search string, abort. */
+rl_noninc_forward_search_again (count, key)
+     int count, key;
+{
+  if (!noninc_search_string)
+    {
+      ding ();
+      return (-1);
+    }
+  noninc_dosearch (noninc_search_string, 1);
+  return 0;
+}
+
+/* Reverse search in the history list for the last string searched
+   for.  If there is no saved search string, abort. */
+rl_noninc_reverse_search_again (count, key)
+     int count, key;
+{
+  if (!noninc_search_string)
+    {
+      ding ();
+      return (-1);
+    }
+  noninc_dosearch (noninc_search_string, -1);
+  return 0;
+}
+
+static int
+rl_history_search_internal (count, direction)
+     int count, direction;
+{
+  HIST_ENTRY *temp, *old_temp;
+  int line_len;
+
+  maybe_save_line ();
+
+  temp = old_temp = (HIST_ENTRY *)NULL;
+  while (count)
+    {
+      temp = (direction < 0) ? previous_history () : next_history ();
+      if (!temp)
+        break;
+      if (STREQN (rl_line_buffer, temp->line, rl_point))
+       {
+         /* Don't find multiple instances of the same line. */
+         if (prev_line_found && STREQ (prev_line_found, temp->line))
+           continue;
+          if (direction < 0)
+            old_temp = temp;
+          prev_line_found = temp->line;
+          count--;
+       }
+    }
+
+  if (!temp)
+    {
+      if (direction < 0 && old_temp)
+       temp = old_temp;
+      else
+       {
+         maybe_unsave_line ();
+         ding ();
+         return 1;
+       }
+    }
+
+  line_len = strlen (temp->line);
+  if (line_len >= rl_line_buffer_len)
+    rl_extend_line_buffer (line_len);
+  strcpy (rl_line_buffer, temp->line);
+  rl_undo_list = (UNDO_LIST *)temp->data;
+  rl_end = line_len;
+  return 0;
+}
+
+/* Search forward in the history for the string of characters
+   from the start of the line to rl_point.  This is a non-incremental
+   search. */
+int
+rl_history_search_forward (count, ignore)
+     int count, ignore;
+{
+  if (count == 0)
+    return (0);
+  if (rl_last_func != rl_history_search_forward)
+    prev_line_found = (char *)NULL;
+  return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
+}
+
+/* Search backward through the history for the string of characters
+   from the start of the line to rl_point.  This is a non-incremental
+   search. */
+int
+rl_history_search_backward (count, ignore)
+     int count, ignore;
+{
+  if (count == 0)
+    return (0);
+  if (rl_last_func != rl_history_search_backward)
+    prev_line_found = (char *)NULL;
+  return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
+}
diff --git a/lib/readline/signals.c b/lib/readline/signals.c
new file mode 100644 (file)
index 0000000..e3d93a0
--- /dev/null
@@ -0,0 +1,287 @@
+/* signals.c -- signal handling support for readline. */
+
+/* Copyright (C) 1987, 1989, 1992 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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#if !defined (NO_SYS_FILE)
+#  include <sys/file.h>
+#endif /* !NO_SYS_FILE */
+#include <signal.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <errno.h>
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+#if defined (GWINSZ_IN_SYS_IOCTL)
+#  include <sys/ioctl.h>
+#endif /* GWINSZ_IN_SYS_IOCTL */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+extern int readline_echoing_p;
+extern int rl_pending_input;
+extern int _rl_meta_flag;
+
+extern void free_undo_list ();
+
+#if defined (VOID_SIGHANDLER)
+#  define sighandler void
+#else
+#  define sighandler int
+#endif /* VOID_SIGHANDLER */
+
+/* This typedef is equivalant to the one for Function; it allows us
+   to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
+typedef sighandler SigHandler ();
+
+#if defined (__GO32__)
+#  undef HANDLE_SIGNALS
+#endif /* __GO32__ */
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                        Signal Handling                          */
+/*                                                                 */
+/* **************************************************************** */
+
+#if defined (SIGWINCH)
+static SigHandler *old_sigwinch = (SigHandler *)NULL;
+
+static sighandler
+rl_handle_sigwinch (sig)
+     int sig;
+{
+  if (readline_echoing_p)
+    {
+      _rl_set_screen_size (fileno (rl_instream), 1);
+      _rl_redisplay_after_sigwinch ();
+    }
+
+  if (old_sigwinch &&
+      old_sigwinch != (SigHandler *)SIG_IGN &&
+      old_sigwinch != (SigHandler *)SIG_DFL)
+    (*old_sigwinch) (sig);
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* VOID_SIGHANDLER */
+}
+#endif  /* SIGWINCH */
+
+#if defined (HANDLE_SIGNALS)
+/* Interrupt handling. */
+static SigHandler
+  *old_int  = (SigHandler *)NULL,
+  *old_alrm = (SigHandler *)NULL;
+#if !defined (SHELL)
+static SigHandler
+  *old_tstp = (SigHandler *)NULL,
+  *old_ttou = (SigHandler *)NULL,
+  *old_ttin = (SigHandler *)NULL,
+  *old_cont = (SigHandler *)NULL;
+#endif /* !SHELL */
+
+/* Handle an interrupt character. */
+static sighandler
+rl_signal_handler (sig)
+     int sig;
+{
+#if defined (HAVE_POSIX_SIGNALS)
+  sigset_t set;
+#else /* !HAVE_POSIX_SIGNALS */
+#  if defined (HAVE_BSD_SIGNALS)
+  long omask;
+#  endif /* HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
+  /* Since the signal will not be blocked while we are in the signal
+     handler, ignore it until rl_clear_signals resets the catcher. */
+  if (sig == SIGINT)
+    signal (sig, SIG_IGN);
+#endif /* !HAVE_BSD_SIGNALS */
+
+  switch (sig)
+    {
+    case SIGINT:
+      {
+       register HIST_ENTRY *entry;
+
+       free_undo_list ();
+
+       entry = current_history ();
+       if (entry)
+         entry->data = (char *)NULL;
+      }
+      _rl_kill_kbd_macro ();
+      rl_clear_message ();
+      rl_init_argument ();
+
+#if defined (SIGTSTP)
+    case SIGTSTP:
+    case SIGTTOU:
+    case SIGTTIN:
+#endif /* SIGTSTP */
+    case SIGALRM:
+      rl_clean_up_for_exit ();
+      rl_deprep_terminal ();
+      rl_clear_signals ();
+      rl_pending_input = 0;
+
+#if defined (HAVE_POSIX_SIGNALS)
+      sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
+      sigdelset (&set, sig);
+#else /* !HAVE_POSIX_SIGNALS */
+#  if defined (HAVE_BSD_SIGNALS)
+      omask = sigblock (0);
+#  endif /* HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+      kill (getpid (), sig);
+
+      /* Let the signal that we just sent through.  */
+#if defined (HAVE_POSIX_SIGNALS)
+      sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
+#else /* !HAVE_POSIX_SIGNALS */
+#  if defined (HAVE_BSD_SIGNALS)
+      sigsetmask (omask & ~(sigmask (sig)));
+#  endif /* HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+      rl_prep_terminal (_rl_meta_flag);
+      rl_set_signals ();
+    }
+
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* !VOID_SIGHANDLER */
+}
+
+#if defined (HAVE_POSIX_SIGNALS)
+static SigHandler *
+rl_set_sighandler (sig, handler)
+     int sig;
+     SigHandler *handler;
+{
+  struct sigaction act, oact;
+
+  act.sa_handler = handler;
+  act.sa_flags = 0;
+  sigemptyset (&act.sa_mask);
+  sigemptyset (&oact.sa_mask);
+  sigaction (sig, &act, &oact);
+  return (oact.sa_handler);
+}
+
+#else /* !HAVE_POSIX_SIGNALS */
+#  define rl_set_sighandler(sig, handler) (SigHandler *)signal (sig, handler)
+#endif /* !HAVE_POSIX_SIGNALS */
+
+rl_set_signals ()
+{
+  old_int = (SigHandler *)rl_set_sighandler (SIGINT, rl_signal_handler);
+  if (old_int == (SigHandler *)SIG_IGN)
+    rl_set_sighandler (SIGINT, SIG_IGN);
+
+  old_alrm = (SigHandler *)rl_set_sighandler (SIGALRM, rl_signal_handler);
+  if (old_alrm == (SigHandler *)SIG_IGN)
+    rl_set_sighandler (SIGALRM, SIG_IGN);
+
+#if !defined (SHELL)
+
+#if defined (SIGTSTP)
+  old_tstp = (SigHandler *)rl_set_sighandler (SIGTSTP, rl_signal_handler);
+  if (old_tstp == (SigHandler *)SIG_IGN)
+    rl_set_sighandler (SIGTSTP, SIG_IGN);
+#endif /* SIGTSTP */
+#if defined (SIGTTOU)
+  old_ttou = (SigHandler *)rl_set_sighandler (SIGTTOU, rl_signal_handler);
+  old_ttin = (SigHandler *)rl_set_sighandler (SIGTTIN, rl_signal_handler);
+
+  if (old_tstp == (SigHandler *)SIG_IGN)
+    {
+      rl_set_sighandler (SIGTTOU, SIG_IGN);
+      rl_set_sighandler (SIGTTIN, SIG_IGN);
+    }
+#endif /* SIGTTOU */
+
+#endif /* !SHELL */
+
+#if defined (SIGWINCH)
+  old_sigwinch =
+    (SigHandler *) rl_set_sighandler (SIGWINCH, rl_handle_sigwinch);
+#endif /* SIGWINCH */
+  return 0;
+}
+
+rl_clear_signals ()
+{
+  rl_set_sighandler (SIGINT, old_int);
+  rl_set_sighandler (SIGALRM, old_alrm);
+
+#if !defined (SHELL)
+
+#if defined (SIGTSTP)
+  rl_set_sighandler (SIGTSTP, old_tstp);
+#endif
+
+#if defined (SIGTTOU)
+  rl_set_sighandler (SIGTTOU, old_ttou);
+  rl_set_sighandler (SIGTTIN, old_ttin);
+#endif /* SIGTTOU */
+
+#endif /* !SHELL */
+
+#if defined (SIGWINCH)
+  rl_set_sighandler (SIGWINCH, old_sigwinch);
+#endif
+
+  return 0;
+}
+#endif  /* HANDLE_SIGNALS */
diff --git a/lib/readline/tilde.c b/lib/readline/tilde.c
new file mode 100644 (file)
index 0000000..da75d95
--- /dev/null
@@ -0,0 +1,380 @@
+/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
+
+/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+   This file is part of GNU Readline, a library for reading lines
+   of text with interactive input and history editing.
+
+   Readline is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 1, or (at your option) any
+   later version.
+
+   Readline is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */  
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "tilde.h"
+#include <sys/types.h>
+#include <pwd.h>
+
+#if defined (USG) && !defined (HAVE_GETPW_DECLS)
+extern struct passwd *getpwuid (), *getpwnam ();
+#endif /* USG && !defined (HAVE_GETPW_DECLS) */
+
+#if !defined (savestring)
+extern char *xmalloc ();
+#  ifndef strcpy
+extern char *strcpy ();
+#  endif
+#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
+#endif /* !savestring */
+
+#if !defined (NULL)
+#  if defined (__STDC__)
+#    define NULL ((void *) 0)
+#  else
+#    define NULL 0x0
+#  endif /* !__STDC__ */
+#endif /* !NULL */
+
+#if defined (TEST) || defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* TEST || STATIC_MALLOC */
+
+/* The default value of tilde_additional_prefixes.  This is set to
+   whitespace preceding a tilde so that simple programs which do not
+   perform any word separation get desired behaviour. */
+static char *default_prefixes[] =
+  { " ~", "\t~", (char *)NULL };
+
+/* The default value of tilde_additional_suffixes.  This is set to
+   whitespace or newline so that simple programs which do not
+   perform any word separation get desired behaviour. */
+static char *default_suffixes[] =
+  { " ", "\n", (char *)NULL };
+
+/* If non-null, this contains the address of a function to call if the
+   standard meaning for expanding a tilde fails.  The function is called
+   with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
+   which is the expansion, or a NULL pointer if there is no expansion. */
+CPFunction *tilde_expansion_failure_hook = (CPFunction *)NULL;
+
+/* When non-null, this is a NULL terminated array of strings which
+   are duplicates for a tilde prefix.  Bash uses this to expand
+   `=~' and `:~'. */
+char **tilde_additional_prefixes = default_prefixes;
+
+/* When non-null, this is a NULL terminated array of strings which match
+   the end of a username, instead of just "/".  Bash sets this to
+   `:' and `=~'. */
+char **tilde_additional_suffixes = default_suffixes;
+
+/* Find the start of a tilde expansion in STRING, and return the index of
+   the tilde which starts the expansion.  Place the length of the text
+   which identified this tilde starter in LEN, excluding the tilde itself. */
+static int
+tilde_find_prefix (string, len)
+     char *string;
+     int *len;
+{
+  register int i, j, string_len;
+  register char **prefixes = tilde_additional_prefixes;
+
+  string_len = strlen (string);
+  *len = 0;
+
+  if (!*string || *string == '~')
+    return (0);
+
+  if (prefixes)
+    {
+      for (i = 0; i < string_len; i++)
+       {
+         for (j = 0; prefixes[j]; j++)
+           {
+             if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0)
+               {
+                 *len = strlen (prefixes[j]) - 1;
+                 return (i + *len);
+               }
+           }
+       }
+    }
+  return (string_len);
+}
+
+/* Find the end of a tilde expansion in STRING, and return the index of
+   the character which ends the tilde definition.  */
+static int
+tilde_find_suffix (string)
+     char *string;
+{
+  register int i, j, string_len;
+  register char **suffixes = tilde_additional_suffixes;
+
+  string_len = strlen (string);
+
+  for (i = 0; i < string_len; i++)
+    {
+      if (string[i] == '/' || !string[i])
+       break;
+
+      for (j = 0; suffixes && suffixes[j]; j++)
+       {
+         if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0)
+           return (i);
+       }
+    }
+  return (i);
+}
+
+/* Return a new string which is the result of tilde expanding STRING. */
+char *
+tilde_expand (string)
+     char *string;
+{
+  char *result, *tilde_expand_word ();
+  int result_size, result_index;
+
+  result_size = result_index = 0;
+  result = (char *)NULL;
+
+  /* Scan through STRING expanding tildes as we come to them. */
+  while (1)
+    {
+      register int start, end;
+      char *tilde_word, *expansion;
+      int len;
+
+      /* Make START point to the tilde which starts the expansion. */
+      start = tilde_find_prefix (string, &len);
+
+      /* Copy the skipped text into the result. */
+      if ((result_index + start + 1) > result_size)
+       result = (char *)xrealloc (result, 1 + (result_size += (start + 20)));
+
+      strncpy (result + result_index, string, start);
+      result_index += start;
+
+      /* Advance STRING to the starting tilde. */
+      string += start;
+
+      /* Make END be the index of one after the last character of the
+        username. */
+      end = tilde_find_suffix (string);
+
+      /* If both START and END are zero, we are all done. */
+      if (!start && !end)
+       break;
+
+      /* Expand the entire tilde word, and copy it into RESULT. */
+      tilde_word = (char *)xmalloc (1 + end);
+      strncpy (tilde_word, string, end);
+      tilde_word[end] = '\0';
+      string += end;
+
+      expansion = tilde_expand_word (tilde_word);
+      free (tilde_word);
+
+      len = strlen (expansion);
+      if ((result_index + len + 1) > result_size)
+       result = (char *)xrealloc (result, 1 + (result_size += (len + 20)));
+
+      strcpy (result + result_index, expansion);
+      result_index += len;
+      free (expansion);
+    }
+
+  result[result_index] = '\0';
+
+  return (result);
+}
+
+/* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
+   tilde.  If there is no expansion, call tilde_expansion_failure_hook. */
+char *
+tilde_expand_word (filename)
+     char *filename;
+{
+  char *dirname;
+
+  dirname = filename ? savestring (filename) : (char *)NULL;
+
+  if (dirname && *dirname == '~')
+    {
+      char *temp_name;
+      if (!dirname[1] || dirname[1] == '/')
+       {
+         /* Prepend $HOME to the rest of the string. */
+         char *temp_home = (char *)getenv ("HOME");
+
+         /* If there is no HOME variable, look up the directory in
+            the password database. */
+         if (!temp_home)
+           {
+             struct passwd *entry;
+
+             entry = getpwuid (getuid ());
+             if (entry)
+               temp_home = entry->pw_dir;
+           }
+
+         temp_name = xmalloc (1 + strlen (&dirname[1])
+                                + (temp_home ? strlen (temp_home) : 0));
+         temp_name[0] = '\0';
+         if (temp_home)
+           strcpy (temp_name, temp_home);
+         strcat (temp_name, dirname + 1);
+         free (dirname);
+         dirname = temp_name;
+       }
+      else
+       {
+         char *username;
+         struct passwd *user_entry;
+         int i;
+
+         username = xmalloc (strlen (dirname));
+         for (i = 1; dirname[i] && dirname[i] != '/'; i++)
+           username[i - 1] = dirname[i];
+         username[i - 1] = '\0';
+
+         if ((user_entry = getpwnam (username)) == 0)
+           {
+             /* If the calling program has a special syntax for
+                expanding tildes, and we couldn't find a standard
+                expansion, then let them try. */
+             if (tilde_expansion_failure_hook)
+               {
+                 char *expansion;
+
+                 expansion = (*tilde_expansion_failure_hook) (username);
+
+                 if (expansion)
+                   {
+                     temp_name = xmalloc (1 + strlen (expansion)
+                                                 + strlen (&dirname[i]));
+                     strcpy (temp_name, expansion);
+                     strcat (temp_name, &dirname[i]);
+                     free (expansion);
+                     free (dirname);
+                     dirname = temp_name;
+                   }
+               }
+             /* We shouldn't report errors. */
+           }
+         else
+           {
+             temp_name = xmalloc (1 + strlen (user_entry->pw_dir)
+                                    + strlen (&dirname[i]));
+             strcpy (temp_name, user_entry->pw_dir);
+             strcat (temp_name, &dirname[i]);
+             free (dirname);
+             dirname = temp_name;
+           }
+         endpwent ();
+         free (username);
+       }
+    }
+  return (dirname);
+}
+
+\f
+#if defined (TEST)
+#undef NULL
+#include <stdio.h>
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char *result, line[512];
+  int done = 0;
+
+  while (!done)
+    {
+      printf ("~expand: ");
+      fflush (stdout);
+
+      if (!gets (line))
+       strcpy (line, "done");
+
+      if ((strcmp (line, "done") == 0) ||
+         (strcmp (line, "quit") == 0) ||
+         (strcmp (line, "exit") == 0))
+       {
+         done = 1;
+         break;
+       }
+
+      result = tilde_expand (line);
+      printf ("  --> %s\n", result);
+      free (result);
+    }
+  exit (0);
+}
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+
+/*
+ * Local variables:
+ * compile-command: "gcc -g -DTEST -o tilde tilde.c"
+ * end:
+ */
+#endif /* TEST */
diff --git a/lib/readline/tilde.h b/lib/readline/tilde.h
new file mode 100644 (file)
index 0000000..726d081
--- /dev/null
@@ -0,0 +1,38 @@
+/* tilde.h: Externally available variables and function in libtilde.a. */
+
+#if !defined (__TILDE_H__)
+#  define __TILDE_H__
+
+/* Function pointers can be declared as (Function *)foo. */
+#if !defined (__FUNCTION_DEF)
+#  define __FUNCTION_DEF
+typedef int Function ();
+typedef void VFunction ();
+typedef char *CPFunction ();
+typedef char **CPPFunction ();
+#endif /* _FUNCTION_DEF */
+
+/* If non-null, this contains the address of a function to call if the
+   standard meaning for expanding a tilde fails.  The function is called
+   with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
+   which is the expansion, or a NULL pointer if there is no expansion. */
+extern CPFunction *tilde_expansion_failure_hook;
+
+/* When non-null, this is a NULL terminated array of strings which
+   are duplicates for a tilde prefix.  Bash uses this to expand
+   `=~' and `:~'. */
+extern char **tilde_additional_prefixes;
+
+/* When non-null, this is a NULL terminated array of strings which match
+   the end of a username, instead of just "/".  Bash sets this to
+   `:' and `=~'. */
+extern char **tilde_additional_suffixes;
+
+/* Return a new string which is the result of tilde expanding STRING. */
+extern char *tilde_expand ();
+
+/* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
+   tilde.  If there is no expansion, call tilde_expansion_failure_hook. */
+extern char *tilde_expand_word ();
+
+#endif /* __TILDE_H__ */
diff --git a/lib/readline/vi_keymap.c b/lib/readline/vi_keymap.c
new file mode 100644 (file)
index 0000000..b8b3123
--- /dev/null
@@ -0,0 +1,877 @@
+/* vi_keymap.c -- the keymap for vi_mode in readline (). */
+
+/* Copyright (C) 1987, 1989, 1992 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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (BUFSIZ)
+#include <stdio.h>
+#endif /* !BUFSIZ */
+
+#include "readline.h"
+
+#if 0
+extern KEYMAP_ENTRY_ARRAY vi_escape_keymap;
+#endif
+
+/* The keymap arrays for handling vi mode. */
+KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
+  /* The regular control keys come first. */
+  { ISFUNC, (Function *)0x0 },         /* Control-@ */
+  { ISFUNC, (Function *)0x0 },         /* Control-a */
+  { ISFUNC, (Function *)0x0 },         /* Control-b */
+  { ISFUNC, (Function *)0x0 },         /* Control-c */
+  { ISFUNC, rl_vi_eof_maybe },         /* Control-d */
+  { ISFUNC, rl_emacs_editing_mode },   /* Control-e */
+  { ISFUNC, (Function *)0x0 },         /* Control-f */
+  { ISFUNC, rl_abort },                        /* Control-g */
+  { ISFUNC, rl_backward },             /* Control-h */
+  { ISFUNC, (Function *)0x0 },         /* Control-i */
+  { ISFUNC, rl_newline },              /* Control-j */
+  { ISFUNC, rl_kill_line },            /* Control-k */
+  { ISFUNC, rl_clear_screen },         /* Control-l */
+  { ISFUNC, rl_newline },              /* Control-m */
+  { ISFUNC, rl_get_next_history },     /* Control-n */
+  { ISFUNC, (Function *)0x0 },         /* Control-o */
+  { ISFUNC, rl_get_previous_history }, /* Control-p */
+  { ISFUNC, rl_quoted_insert },                /* Control-q */
+  { ISFUNC, rl_reverse_search_history }, /* Control-r */
+  { ISFUNC, rl_forward_search_history }, /* Control-s */
+  { ISFUNC, rl_transpose_chars },      /* Control-t */
+  { ISFUNC, rl_unix_line_discard },    /* Control-u */
+  { ISFUNC, rl_quoted_insert },                /* Control-v */
+  { ISFUNC, rl_unix_word_rubout },     /* Control-w */
+  { ISFUNC, (Function *)0x0 },         /* Control-x */
+  { ISFUNC, rl_yank },                 /* Control-y */
+  { ISFUNC, (Function *)0x0 },         /* Control-z */
+
+  { ISFUNC, (Function *)0x0 },         /* Control-[ */ /* vi_escape_keymap */
+  { ISFUNC, (Function *)0x0 },         /* Control-\ */
+  { ISFUNC, (Function *)0x0 },         /* Control-] */
+  { ISFUNC, (Function *)0x0 },         /* Control-^ */
+  { ISFUNC, rl_undo_command },         /* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, rl_forward },              /* SPACE */
+  { ISFUNC, (Function *)0x0 },         /* ! */
+  { ISFUNC, (Function *)0x0 },         /* " */
+  { ISFUNC, rl_vi_comment },           /* # */
+  { ISFUNC, rl_end_of_line },          /* $ */
+  { ISFUNC, rl_vi_match },             /* % */
+  { ISFUNC, rl_vi_tilde_expand },      /* & */
+  { ISFUNC, (Function *)0x0 },         /* ' */
+  { ISFUNC, (Function *)0x0 },         /* ( */
+  { ISFUNC, (Function *)0x0 },         /* ) */
+  { ISFUNC, rl_vi_complete },          /* * */
+  { ISFUNC, rl_get_next_history},      /* + */
+  { ISFUNC, rl_vi_char_search },       /* , */
+  { ISFUNC, rl_get_previous_history }, /* - */
+  { ISFUNC, rl_vi_redo },              /* . */
+  { ISFUNC, rl_vi_search },            /* / */
+
+  /* Regular digits. */
+  { ISFUNC, rl_beg_of_line },          /* 0 */
+  { ISFUNC, rl_vi_arg_digit },         /* 1 */
+  { ISFUNC, rl_vi_arg_digit },         /* 2 */
+  { ISFUNC, rl_vi_arg_digit },         /* 3 */
+  { ISFUNC, rl_vi_arg_digit },         /* 4 */
+  { ISFUNC, rl_vi_arg_digit },         /* 5 */
+  { ISFUNC, rl_vi_arg_digit },         /* 6 */
+  { ISFUNC, rl_vi_arg_digit },         /* 7 */
+  { ISFUNC, rl_vi_arg_digit },         /* 8 */
+  { ISFUNC, rl_vi_arg_digit },         /* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* : */
+  { ISFUNC, rl_vi_char_search },       /* ; */
+  { ISFUNC, (Function *)0x0 },         /* < */
+  { ISFUNC, rl_vi_complete },          /* = */
+  { ISFUNC, (Function *)0x0 },         /* > */
+  { ISFUNC, rl_vi_search },            /* ? */
+  { ISFUNC, (Function *)0x0 },         /* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_vi_append_eol },                /* A */
+  { ISFUNC, rl_vi_prev_word},          /* B */
+  { ISFUNC, rl_vi_change_to },         /* C */
+  { ISFUNC, rl_vi_delete_to },         /* D */
+  { ISFUNC, rl_vi_end_word },          /* E */
+  { ISFUNC, rl_vi_char_search },       /* F */
+  { ISFUNC, rl_vi_fetch_history },     /* G */
+  { ISFUNC, (Function *)0x0 },         /* H */
+  { ISFUNC, rl_vi_insert_beg },                /* I */
+  { ISFUNC, (Function *)0x0 },         /* J */
+  { ISFUNC, (Function *)0x0 },         /* K */
+  { ISFUNC, (Function *)0x0 },         /* L */
+  { ISFUNC, (Function *)0x0 },         /* M */
+  { ISFUNC, rl_vi_search_again },      /* N */
+  { ISFUNC, (Function *)0x0 },         /* O */
+  { ISFUNC, rl_vi_put },               /* P */
+  { ISFUNC, (Function *)0x0 },         /* Q */
+  { ISFUNC, rl_vi_replace },           /* R */
+  { ISFUNC, rl_vi_subst },             /* S */
+  { ISFUNC, rl_vi_char_search },       /* T */
+  { ISFUNC, rl_revert_line },          /* U */
+  { ISFUNC, (Function *)0x0 },         /* V */
+  { ISFUNC, rl_vi_next_word },         /* W */
+  { ISFUNC, rl_rubout },               /* X */
+  { ISFUNC, rl_vi_yank_to },           /* Y */
+  { ISFUNC, (Function *)0x0 },         /* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* [ */
+  { ISFUNC, rl_vi_complete },          /* \ */
+  { ISFUNC, (Function *)0x0 },         /* ] */
+  { ISFUNC, rl_vi_first_print },       /* ^ */
+  { ISFUNC, rl_vi_yank_arg },          /* _ */
+  { ISFUNC, (Function *)0x0 },         /* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, rl_vi_append_mode },       /* a */
+  { ISFUNC, rl_vi_prev_word },         /* b */
+  { ISFUNC, rl_vi_change_to },         /* c */
+  { ISFUNC, rl_vi_delete_to },         /* d */
+  { ISFUNC, rl_vi_end_word },          /* e */
+  { ISFUNC, rl_vi_char_search },       /* f */
+  { ISFUNC, (Function *)0x0 },         /* g */
+  { ISFUNC, rl_backward },             /* h */
+  { ISFUNC, rl_vi_insertion_mode },    /* i */
+  { ISFUNC, rl_get_next_history },     /* j */
+  { ISFUNC, rl_get_previous_history }, /* k */
+  { ISFUNC, rl_forward },              /* l */
+  { ISFUNC, (Function *)0x0 },         /* m */
+  { ISFUNC, rl_vi_search_again },      /* n */
+  { ISFUNC, (Function *)0x0 },         /* o */
+  { ISFUNC, rl_vi_put },               /* p */
+  { ISFUNC, (Function *)0x0 },         /* q */
+  { ISFUNC, rl_vi_change_char },       /* r */
+  { ISFUNC, rl_vi_subst },             /* s */
+  { ISFUNC, rl_vi_char_search },       /* t */
+  { ISFUNC, rl_undo_command },         /* u */
+  { ISFUNC, (Function *)0x0 },         /* v */
+  { ISFUNC, rl_vi_next_word },         /* w */
+  { ISFUNC, rl_vi_delete },            /* x */
+  { ISFUNC, rl_vi_yank_to },           /* y */
+  { ISFUNC, (Function *)0x0 },         /* z */
+
+  /* Final punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* { */
+  { ISFUNC, rl_vi_column },            /* | */
+  { ISFUNC, (Function *)0x0 },         /* } */
+  { ISFUNC, rl_vi_change_case },       /* ~ */
+  { ISFUNC, (Function *)0x0 },         /* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+  /* Undefined keys. */
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 }
+#endif /* KEYMAP_SIZE > 128 */
+};
+
+
+KEYMAP_ENTRY_ARRAY vi_insertion_keymap = {
+  /* The regular control keys come first. */
+  { ISFUNC, (Function *)0x0 },         /* Control-@ */
+  { ISFUNC, rl_insert },               /* Control-a */
+  { ISFUNC, rl_insert },               /* Control-b */
+  { ISFUNC, rl_insert },               /* Control-c */
+  { ISFUNC, rl_vi_eof_maybe },         /* Control-d */
+  { ISFUNC, rl_insert },               /* Control-e */
+  { ISFUNC, rl_insert },               /* Control-f */
+  { ISFUNC, rl_insert },               /* Control-g */
+  { ISFUNC, rl_rubout },               /* Control-h */
+  { ISFUNC, rl_complete },             /* Control-i */
+  { ISFUNC, rl_newline },              /* Control-j */
+  { ISFUNC, rl_insert },               /* Control-k */
+  { ISFUNC, rl_insert },               /* Control-l */
+  { ISFUNC, rl_newline },              /* Control-m */
+  { ISFUNC, rl_insert },               /* Control-n */
+  { ISFUNC, rl_insert },               /* Control-o */
+  { ISFUNC, rl_insert },               /* Control-p */
+  { ISFUNC, rl_insert },               /* Control-q */
+  { ISFUNC, rl_reverse_search_history }, /* Control-r */
+  { ISFUNC, rl_forward_search_history }, /* Control-s */
+  { ISFUNC, rl_transpose_chars },      /* Control-t */
+  { ISFUNC, rl_unix_line_discard },    /* Control-u */
+  { ISFUNC, rl_quoted_insert },                /* Control-v */
+  { ISFUNC, rl_unix_word_rubout },     /* Control-w */
+  { ISFUNC, rl_insert },               /* Control-x */
+  { ISFUNC, rl_yank },                 /* Control-y */
+  { ISFUNC, rl_insert },               /* Control-z */
+
+  { ISFUNC, rl_vi_movement_mode },     /* Control-[ */
+  { ISFUNC, rl_insert },               /* Control-\ */
+  { ISFUNC, rl_insert },               /* Control-] */
+  { ISFUNC, rl_insert },               /* Control-^ */
+  { ISFUNC, rl_undo_command },         /* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, rl_insert },               /* SPACE */
+  { ISFUNC, rl_insert },               /* ! */
+  { ISFUNC, rl_insert },               /* " */
+  { ISFUNC, rl_insert },               /* # */
+  { ISFUNC, rl_insert },               /* $ */
+  { ISFUNC, rl_insert },               /* % */
+  { ISFUNC, rl_insert },               /* & */
+  { ISFUNC, rl_insert },               /* ' */
+  { ISFUNC, rl_insert },               /* ( */
+  { ISFUNC, rl_insert },               /* ) */
+  { ISFUNC, rl_insert },               /* * */
+  { ISFUNC, rl_insert },               /* + */
+  { ISFUNC, rl_insert },               /* , */
+  { ISFUNC, rl_insert },               /* - */
+  { ISFUNC, rl_insert },               /* . */
+  { ISFUNC, rl_insert },               /* / */
+
+  /* Regular digits. */
+  { ISFUNC, rl_insert },               /* 0 */
+  { ISFUNC, rl_insert },               /* 1 */
+  { ISFUNC, rl_insert },               /* 2 */
+  { ISFUNC, rl_insert },               /* 3 */
+  { ISFUNC, rl_insert },               /* 4 */
+  { ISFUNC, rl_insert },               /* 5 */
+  { ISFUNC, rl_insert },               /* 6 */
+  { ISFUNC, rl_insert },               /* 7 */
+  { ISFUNC, rl_insert },               /* 8 */
+  { ISFUNC, rl_insert },               /* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, rl_insert },               /* : */
+  { ISFUNC, rl_insert },               /* ; */
+  { ISFUNC, rl_insert },               /* < */
+  { ISFUNC, rl_insert },               /* = */
+  { ISFUNC, rl_insert },               /* > */
+  { ISFUNC, rl_insert },               /* ? */
+  { ISFUNC, rl_insert },               /* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_insert },               /* A */
+  { ISFUNC, rl_insert },               /* B */
+  { ISFUNC, rl_insert },               /* C */
+  { ISFUNC, rl_insert },               /* D */
+  { ISFUNC, rl_insert },               /* E */
+  { ISFUNC, rl_insert },               /* F */
+  { ISFUNC, rl_insert },               /* G */
+  { ISFUNC, rl_insert },               /* H */
+  { ISFUNC, rl_insert },               /* I */
+  { ISFUNC, rl_insert },               /* J */
+  { ISFUNC, rl_insert },               /* K */
+  { ISFUNC, rl_insert },               /* L */
+  { ISFUNC, rl_insert },               /* M */
+  { ISFUNC, rl_insert },               /* N */
+  { ISFUNC, rl_insert },               /* O */
+  { ISFUNC, rl_insert },               /* P */
+  { ISFUNC, rl_insert },               /* Q */
+  { ISFUNC, rl_insert },               /* R */
+  { ISFUNC, rl_insert },               /* S */
+  { ISFUNC, rl_insert },               /* T */
+  { ISFUNC, rl_insert },               /* U */
+  { ISFUNC, rl_insert },               /* V */
+  { ISFUNC, rl_insert },               /* W */
+  { ISFUNC, rl_insert },               /* X */
+  { ISFUNC, rl_insert },               /* Y */
+  { ISFUNC, rl_insert },               /* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, rl_insert },               /* [ */
+  { ISFUNC, rl_insert },               /* \ */
+  { ISFUNC, rl_insert },               /* ] */
+  { ISFUNC, rl_insert },               /* ^ */
+  { ISFUNC, rl_insert },               /* _ */
+  { ISFUNC, rl_insert },               /* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, rl_insert },               /* a */
+  { ISFUNC, rl_insert },               /* b */
+  { ISFUNC, rl_insert },               /* c */
+  { ISFUNC, rl_insert },               /* d */
+  { ISFUNC, rl_insert },               /* e */
+  { ISFUNC, rl_insert },               /* f */
+  { ISFUNC, rl_insert },               /* g */
+  { ISFUNC, rl_insert },               /* h */
+  { ISFUNC, rl_insert },               /* i */
+  { ISFUNC, rl_insert },               /* j */
+  { ISFUNC, rl_insert },               /* k */
+  { ISFUNC, rl_insert },               /* l */
+  { ISFUNC, rl_insert },               /* m */
+  { ISFUNC, rl_insert },               /* n */
+  { ISFUNC, rl_insert },               /* o */
+  { ISFUNC, rl_insert },               /* p */
+  { ISFUNC, rl_insert },               /* q */
+  { ISFUNC, rl_insert },               /* r */
+  { ISFUNC, rl_insert },               /* s */
+  { ISFUNC, rl_insert },               /* t */
+  { ISFUNC, rl_insert },               /* u */
+  { ISFUNC, rl_insert },               /* v */
+  { ISFUNC, rl_insert },               /* w */
+  { ISFUNC, rl_insert },               /* x */
+  { ISFUNC, rl_insert },               /* y */
+  { ISFUNC, rl_insert },               /* z */
+
+  /* Final punctuation. */
+  { ISFUNC, rl_insert },               /* { */
+  { ISFUNC, rl_insert },               /* | */
+  { ISFUNC, rl_insert },               /* } */
+  { ISFUNC, rl_insert },               /* ~ */
+  { ISFUNC, rl_rubout },               /* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+  /* Pure 8-bit characters (128 - 159).
+     These might be used in some
+     character sets. */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+  { ISFUNC, rl_insert },       /* ? */
+
+  /* ISO Latin-1 characters (160 - 255) */
+  { ISFUNC, rl_insert },       /* No-break space */
+  { ISFUNC, rl_insert },       /* Inverted exclamation mark */
+  { ISFUNC, rl_insert },       /* Cent sign */
+  { ISFUNC, rl_insert },       /* Pound sign */
+  { ISFUNC, rl_insert },       /* Currency sign */
+  { ISFUNC, rl_insert },       /* Yen sign */
+  { ISFUNC, rl_insert },       /* Broken bar */
+  { ISFUNC, rl_insert },       /* Section sign */
+  { ISFUNC, rl_insert },       /* Diaeresis */
+  { ISFUNC, rl_insert },       /* Copyright sign */
+  { ISFUNC, rl_insert },       /* Feminine ordinal indicator */
+  { ISFUNC, rl_insert },       /* Left pointing double angle quotation mark */
+  { ISFUNC, rl_insert },       /* Not sign */
+  { ISFUNC, rl_insert },       /* Soft hyphen */
+  { ISFUNC, rl_insert },       /* Registered sign */
+  { ISFUNC, rl_insert },       /* Macron */
+  { ISFUNC, rl_insert },       /* Degree sign */
+  { ISFUNC, rl_insert },       /* Plus-minus sign */
+  { ISFUNC, rl_insert },       /* Superscript two */
+  { ISFUNC, rl_insert },       /* Superscript three */
+  { ISFUNC, rl_insert },       /* Acute accent */
+  { ISFUNC, rl_insert },       /* Micro sign */
+  { ISFUNC, rl_insert },       /* Pilcrow sign */
+  { ISFUNC, rl_insert },       /* Middle dot */
+  { ISFUNC, rl_insert },       /* Cedilla */
+  { ISFUNC, rl_insert },       /* Superscript one */
+  { ISFUNC, rl_insert },       /* Masculine ordinal indicator */
+  { ISFUNC, rl_insert },       /* Right pointing double angle quotation mark */
+  { ISFUNC, rl_insert },       /* Vulgar fraction one quarter */
+  { ISFUNC, rl_insert },       /* Vulgar fraction one half */
+  { ISFUNC, rl_insert },       /* Vulgar fraction three quarters */
+  { ISFUNC, rl_insert },       /* Inverted questionk mark */
+  { ISFUNC, rl_insert },       /* Latin capital letter a with grave */
+  { ISFUNC, rl_insert },       /* Latin capital letter a with acute */
+  { ISFUNC, rl_insert },       /* Latin capital letter a with circumflex */
+  { ISFUNC, rl_insert },       /* Latin capital letter a with tilde */
+  { ISFUNC, rl_insert },       /* Latin capital letter a with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin capital letter a with ring above */
+  { ISFUNC, rl_insert },       /* Latin capital letter ae */
+  { ISFUNC, rl_insert },       /* Latin capital letter c with cedilla */
+  { ISFUNC, rl_insert },       /* Latin capital letter e with grave */
+  { ISFUNC, rl_insert },       /* Latin capital letter e with acute */
+  { ISFUNC, rl_insert },       /* Latin capital letter e with circumflex */
+  { ISFUNC, rl_insert },       /* Latin capital letter e with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin capital letter i with grave */
+  { ISFUNC, rl_insert },       /* Latin capital letter i with acute */
+  { ISFUNC, rl_insert },       /* Latin capital letter i with circumflex */
+  { ISFUNC, rl_insert },       /* Latin capital letter i with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin capital letter eth (Icelandic) */
+  { ISFUNC, rl_insert },       /* Latin capital letter n with tilde */
+  { ISFUNC, rl_insert },       /* Latin capital letter o with grave */
+  { ISFUNC, rl_insert },       /* Latin capital letter o with acute */
+  { ISFUNC, rl_insert },       /* Latin capital letter o with circumflex */
+  { ISFUNC, rl_insert },       /* Latin capital letter o with tilde */
+  { ISFUNC, rl_insert },       /* Latin capital letter o with diaeresis */
+  { ISFUNC, rl_insert },       /* Multiplication sign */
+  { ISFUNC, rl_insert },       /* Latin capital letter o with stroke */
+  { ISFUNC, rl_insert },       /* Latin capital letter u with grave */
+  { ISFUNC, rl_insert },       /* Latin capital letter u with acute */
+  { ISFUNC, rl_insert },       /* Latin capital letter u with circumflex */
+  { ISFUNC, rl_insert },       /* Latin capital letter u with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin capital letter Y with acute */
+  { ISFUNC, rl_insert },       /* Latin capital letter thorn (Icelandic) */
+  { ISFUNC, rl_insert },       /* Latin small letter sharp s (German) */
+  { ISFUNC, rl_insert },       /* Latin small letter a with grave */
+  { ISFUNC, rl_insert },       /* Latin small letter a with acute */
+  { ISFUNC, rl_insert },       /* Latin small letter a with circumflex */
+  { ISFUNC, rl_insert },       /* Latin small letter a with tilde */
+  { ISFUNC, rl_insert },       /* Latin small letter a with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin small letter a with ring above */
+  { ISFUNC, rl_insert },       /* Latin small letter ae */
+  { ISFUNC, rl_insert },       /* Latin small letter c with cedilla */
+  { ISFUNC, rl_insert },       /* Latin small letter e with grave */
+  { ISFUNC, rl_insert },       /* Latin small letter e with acute */
+  { ISFUNC, rl_insert },       /* Latin small letter e with circumflex */
+  { ISFUNC, rl_insert },       /* Latin small letter e with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin small letter i with grave */
+  { ISFUNC, rl_insert },       /* Latin small letter i with acute */
+  { ISFUNC, rl_insert },       /* Latin small letter i with circumflex */
+  { ISFUNC, rl_insert },       /* Latin small letter i with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin small letter eth (Icelandic) */
+  { ISFUNC, rl_insert },       /* Latin small letter n with tilde */
+  { ISFUNC, rl_insert },       /* Latin small letter o with grave */
+  { ISFUNC, rl_insert },       /* Latin small letter o with acute */
+  { ISFUNC, rl_insert },       /* Latin small letter o with circumflex */
+  { ISFUNC, rl_insert },       /* Latin small letter o with tilde */
+  { ISFUNC, rl_insert },       /* Latin small letter o with diaeresis */
+  { ISFUNC, rl_insert },       /* Division sign */
+  { ISFUNC, rl_insert },       /* Latin small letter o with stroke */
+  { ISFUNC, rl_insert },       /* Latin small letter u with grave */
+  { ISFUNC, rl_insert },       /* Latin small letter u with acute */
+  { ISFUNC, rl_insert },       /* Latin small letter u with circumflex */
+  { ISFUNC, rl_insert },       /* Latin small letter u with diaeresis */
+  { ISFUNC, rl_insert },       /* Latin small letter y with acute */
+  { ISFUNC, rl_insert },       /* Latin small letter thorn (Icelandic) */
+  { ISFUNC, rl_insert }                /* Latin small letter y with diaeresis */
+#endif /* KEYMAP_SIZE > 128 */
+};
+
+/* Unused for the time being. */
+#if 0
+KEYMAP_ENTRY_ARRAY vi_escape_keymap = {
+  /* The regular control keys come first. */
+  { ISFUNC, (Function *)0x0 },         /* Control-@ */
+  { ISFUNC, (Function *)0x0 },         /* Control-a */
+  { ISFUNC, (Function *)0x0 },         /* Control-b */
+  { ISFUNC, (Function *)0x0 },         /* Control-c */
+  { ISFUNC, (Function *)0x0 },         /* Control-d */
+  { ISFUNC, (Function *)0x0 },         /* Control-e */
+  { ISFUNC, (Function *)0x0 },         /* Control-f */
+  { ISFUNC, (Function *)0x0 },         /* Control-g */
+  { ISFUNC, (Function *)0x0 },         /* Control-h */
+  { ISFUNC, rl_tab_insert},            /* Control-i */
+  { ISFUNC, rl_emacs_editing_mode},    /* Control-j */
+  { ISFUNC, rl_kill_line },            /* Control-k */
+  { ISFUNC, (Function *)0x0 },         /* Control-l */
+  { ISFUNC, rl_emacs_editing_mode},    /* Control-m */
+  { ISFUNC, (Function *)0x0 },         /* Control-n */
+  { ISFUNC, (Function *)0x0 },         /* Control-o */
+  { ISFUNC, (Function *)0x0 },         /* Control-p */
+  { ISFUNC, (Function *)0x0 },         /* Control-q */
+  { ISFUNC, (Function *)0x0 },         /* Control-r */
+  { ISFUNC, (Function *)0x0 },         /* Control-s */
+  { ISFUNC, (Function *)0x0 },         /* Control-t */
+  { ISFUNC, (Function *)0x0 },         /* Control-u */
+  { ISFUNC, (Function *)0x0 },         /* Control-v */
+  { ISFUNC, (Function *)0x0 },         /* Control-w */
+  { ISFUNC, (Function *)0x0 },         /* Control-x */
+  { ISFUNC, (Function *)0x0 },         /* Control-y */
+  { ISFUNC, (Function *)0x0 },         /* Control-z */
+
+  { ISFUNC, rl_vi_movement_mode },     /* Control-[ */
+  { ISFUNC, (Function *)0x0 },         /* Control-\ */
+  { ISFUNC, (Function *)0x0 },         /* Control-] */
+  { ISFUNC, (Function *)0x0 },         /* Control-^ */
+  { ISFUNC, rl_undo_command },         /* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, (Function *)0x0 },         /* SPACE */
+  { ISFUNC, (Function *)0x0 },         /* ! */
+  { ISFUNC, (Function *)0x0 },         /* " */
+  { ISFUNC, (Function *)0x0 },         /* # */
+  { ISFUNC, (Function *)0x0 },         /* $ */
+  { ISFUNC, (Function *)0x0 },         /* % */
+  { ISFUNC, (Function *)0x0 },         /* & */
+  { ISFUNC, (Function *)0x0 },         /* ' */
+  { ISFUNC, (Function *)0x0 },         /* ( */
+  { ISFUNC, (Function *)0x0 },         /* ) */
+  { ISFUNC, (Function *)0x0 },         /* * */
+  { ISFUNC, (Function *)0x0 },         /* + */
+  { ISFUNC, (Function *)0x0 },         /* , */
+  { ISFUNC, (Function *)0x0 },         /* - */
+  { ISFUNC, (Function *)0x0 },         /* . */
+  { ISFUNC, (Function *)0x0 },         /* / */
+
+  /* Regular digits. */
+  { ISFUNC, rl_vi_arg_digit },         /* 0 */
+  { ISFUNC, rl_vi_arg_digit },         /* 1 */
+  { ISFUNC, rl_vi_arg_digit },         /* 2 */
+  { ISFUNC, rl_vi_arg_digit },         /* 3 */
+  { ISFUNC, rl_vi_arg_digit },         /* 4 */
+  { ISFUNC, rl_vi_arg_digit },         /* 5 */
+  { ISFUNC, rl_vi_arg_digit },         /* 6 */
+  { ISFUNC, rl_vi_arg_digit },         /* 7 */
+  { ISFUNC, rl_vi_arg_digit },         /* 8 */
+  { ISFUNC, rl_vi_arg_digit },         /* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* : */
+  { ISFUNC, (Function *)0x0 },         /* ; */
+  { ISFUNC, (Function *)0x0 },         /* < */
+  { ISFUNC, (Function *)0x0 },         /* = */
+  { ISFUNC, (Function *)0x0 },         /* > */
+  { ISFUNC, (Function *)0x0 },         /* ? */
+  { ISFUNC, (Function *)0x0 },         /* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_do_lowercase_version }, /* A */
+  { ISFUNC, rl_do_lowercase_version }, /* B */
+  { ISFUNC, rl_do_lowercase_version }, /* C */
+  { ISFUNC, rl_do_lowercase_version }, /* D */
+  { ISFUNC, rl_do_lowercase_version }, /* E */
+  { ISFUNC, rl_do_lowercase_version }, /* F */
+  { ISFUNC, rl_do_lowercase_version }, /* G */
+  { ISFUNC, rl_do_lowercase_version }, /* H */
+  { ISFUNC, rl_do_lowercase_version }, /* I */
+  { ISFUNC, rl_do_lowercase_version }, /* J */
+  { ISFUNC, rl_do_lowercase_version }, /* K */
+  { ISFUNC, rl_do_lowercase_version }, /* L */
+  { ISFUNC, rl_do_lowercase_version }, /* M */
+  { ISFUNC, rl_do_lowercase_version }, /* N */
+  { ISFUNC, rl_do_lowercase_version }, /* O */
+  { ISFUNC, rl_do_lowercase_version }, /* P */
+  { ISFUNC, rl_do_lowercase_version }, /* Q */
+  { ISFUNC, rl_do_lowercase_version }, /* R */
+  { ISFUNC, rl_do_lowercase_version }, /* S */
+  { ISFUNC, rl_do_lowercase_version }, /* T */
+  { ISFUNC, rl_do_lowercase_version }, /* U */
+  { ISFUNC, rl_do_lowercase_version }, /* V */
+  { ISFUNC, rl_do_lowercase_version }, /* W */
+  { ISFUNC, rl_do_lowercase_version }, /* X */
+  { ISFUNC, rl_do_lowercase_version }, /* Y */
+  { ISFUNC, rl_do_lowercase_version }, /* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, rl_arrow_keys },           /* [ */
+  { ISFUNC, (Function *)0x0 },         /* \ */
+  { ISFUNC, (Function *)0x0 },         /* ] */
+  { ISFUNC, (Function *)0x0 },         /* ^ */
+  { ISFUNC, (Function *)0x0 },         /* _ */
+  { ISFUNC, (Function *)0x0 },         /* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, (Function *)0x0 },         /* a */
+  { ISFUNC, (Function *)0x0 },         /* b */
+  { ISFUNC, (Function *)0x0 },         /* c */
+  { ISFUNC, (Function *)0x0 },         /* d */
+  { ISFUNC, (Function *)0x0 },         /* e */
+  { ISFUNC, (Function *)0x0 },         /* f */
+  { ISFUNC, (Function *)0x0 },         /* g */
+  { ISFUNC, (Function *)0x0 },         /* h */
+  { ISFUNC, (Function *)0x0 },         /* i */
+  { ISFUNC, (Function *)0x0 },         /* j */
+  { ISFUNC, (Function *)0x0 },         /* k */
+  { ISFUNC, (Function *)0x0 },         /* l */
+  { ISFUNC, (Function *)0x0 },         /* m */
+  { ISFUNC, (Function *)0x0 },         /* n */
+  { ISFUNC, rl_arrow_keys },           /* o */
+  { ISFUNC, (Function *)0x0 },         /* p */
+  { ISFUNC, (Function *)0x0 },         /* q */
+  { ISFUNC, (Function *)0x0 },         /* r */
+  { ISFUNC, (Function *)0x0 },         /* s */
+  { ISFUNC, (Function *)0x0 },         /* t */
+  { ISFUNC, (Function *)0x0 },         /* u */
+  { ISFUNC, (Function *)0x0 },         /* v */
+  { ISFUNC, (Function *)0x0 },         /* w */
+  { ISFUNC, (Function *)0x0 },         /* x */
+  { ISFUNC, (Function *)0x0 },         /* y */
+  { ISFUNC, (Function *)0x0 },         /* z */
+
+  /* Final punctuation. */
+  { ISFUNC, (Function *)0x0 },         /* { */
+  { ISFUNC, (Function *)0x0 },         /* | */
+  { ISFUNC, (Function *)0x0 },         /* } */
+  { ISFUNC, (Function *)0x0 },         /* ~ */
+  { ISFUNC, rl_backward_kill_word },   /* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+  /* Undefined keys. */
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 }
+#endif /* KEYMAP_SIZE > 128 */
+};
+#endif
diff --git a/lib/readline/vi_mode.c b/lib/readline/vi_mode.c
new file mode 100644 (file)
index 0000000..d0b9310
--- /dev/null
@@ -0,0 +1,1329 @@
+/* vi_mode.c -- A vi emulation mode for Bash.
+   Derived from code written by Jeff Sparkes (jsparkes@bnr.ca).  */
+
+/* Copyright (C) 1987, 1989, 1992 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 1, 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,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     VI Emulation Mode                           */
+/*                                                                 */
+/* **************************************************************** */
+#include "rlconf.h"
+
+#if defined (VI_MODE)
+
+#include <sys/types.h>
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include <stdio.h>
+
+/* Some standard library routines. */
+#include "rldefs.h"
+#include "readline.h"
+#include "history.h"
+
+#ifndef digit_p
+#define digit_p(c)  ((c) >= '0' && (c) <= '9')
+#endif
+
+#ifndef digit_value
+#define digit_value(c) ((c) - '0')
+#endif
+
+#ifndef member
+#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
+#endif
+
+#ifndef isident
+#define isident(c) ((pure_alphabetic (c) || digit_p (c) || c == '_'))
+#endif
+
+#ifndef exchange
+#define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0)
+#endif
+
+#ifndef VI_COMMENT_BEGIN_DEFAULT
+#define VI_COMMENT_BEGIN_DEFAULT "#"
+#endif
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+/* Variables imported from readline.c */
+extern int rl_point, rl_end, rl_mark, rl_done;
+extern FILE *rl_instream;
+extern int rl_line_buffer_len, rl_explicit_arg, rl_numeric_arg;
+extern Keymap _rl_keymap;
+extern char *rl_prompt;
+extern char *rl_line_buffer;
+extern int rl_arg_sign;
+
+extern void _rl_dispatch ();
+
+extern void rl_extend_line_buffer ();
+extern int rl_vi_check ();
+
+/* Non-zero means enter insertion mode. */
+static int _rl_vi_doing_insert = 0;
+
+/* String inserted into the line by rl_vi_comment (). */
+char *rl_vi_comment_begin = (char *)NULL;
+
+/* *** UNCLEAN *** */
+/* Command keys which do movement for xxx_to commands. */
+static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
+
+/* Keymap used for vi replace characters.  Created dynamically since
+   rarely used. */
+static Keymap vi_replace_map = (Keymap)NULL;
+
+/* The number of characters inserted in the last replace operation. */
+static int vi_replace_count = 0;
+
+/* If non-zero, we have text inserted after a c[motion] command that put
+   us implicitly into insert mode.  Some people want this text to be
+   attached to the command so that it is `redoable' with `.'. */
+static int vi_continued_command = 0;
+
+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 = 0;
+static int _rl_vi_last_search_char = 0;
+static int _rl_vi_last_replacement = 0;
+
+static int vi_redoing = 0;
+
+/* Text modification commands.  These are the `redoable' commands. */
+static char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
+
+static int rl_digit_loop1 ();
+
+void
+_rl_vi_reset_last ()
+{
+  _rl_vi_last_command = 'i';
+  _rl_vi_last_repeat = 1;
+  _rl_vi_last_arg_sign = 1;
+  _rl_vi_last_motion = 0;
+}
+
+void
+_rl_vi_set_last (key, repeat, sign)
+     int key, repeat, sign;
+{
+  _rl_vi_last_command = key;
+  _rl_vi_last_repeat = repeat;
+  _rl_vi_last_arg_sign = sign;
+}
+
+/* Is the command C a VI mode text modification command? */
+int
+rl_vi_textmod_command (c)
+     int c;
+{
+  return (member (c, vi_textmod));
+}
+
+/* Bound to `.'.  Called from command mode, so we know that we have to
+   redo a text modification command.  The default for _rl_vi_last_command
+   puts you back into insert mode. */
+rl_vi_redo (count, c)
+     int count, c;
+{
+  if (!rl_explicit_arg)
+    {
+      rl_numeric_arg = _rl_vi_last_repeat;
+      rl_arg_sign = _rl_vi_last_arg_sign;
+    }
+
+  vi_redoing = 1;
+  _rl_dispatch (_rl_vi_last_command, _rl_keymap);
+  vi_redoing = 0;
+
+  return (0);
+}
+    
+/* Yank the nth arg from the previous line into this line at point. */
+rl_vi_yank_arg (count, key)
+     int count, key;
+{
+  /* Readline thinks that the first word on a line is the 0th, while vi
+     thinks the first word on a line is the 1st.  Compensate. */
+  if (rl_explicit_arg)
+    rl_yank_nth_arg (count - 1, 0);
+  else
+    rl_yank_nth_arg ('$', 0);
+
+  return (0);
+}
+
+/* With an argument, move back that many history lines, else move to the
+   beginning of history. */
+rl_vi_fetch_history (count, c)
+     int count, c;
+{
+  int current = where_history ();
+
+  /* Giving an argument of n means we want the nth command in the history
+     file.  The command number is interpreted the same way that the bash
+     `history' command does it -- that is, giving an argument count of 450
+     to this command would get the command listed as number 450 in the
+     output of `history'. */
+  if (rl_explicit_arg)
+    {
+      int wanted = history_base + current - count;
+      if (wanted <= 0)
+        rl_beginning_of_history (0, 0);
+      else
+        rl_get_previous_history (wanted);
+    }
+  else
+    rl_beginning_of_history (count, 0);
+  return (0);
+}
+
+/* Search again for the last thing searched for. */
+rl_vi_search_again (count, key)
+     int count, key;
+{
+  switch (key)
+    {
+    case 'n':
+      rl_noninc_reverse_search_again (count, key);
+      break;
+
+    case 'N':
+      rl_noninc_forward_search_again (count, key);
+      break;
+    }
+  return (0);
+}
+
+/* Do a vi style search. */
+rl_vi_search (count, key)
+     int count, key;
+{
+  switch (key)
+    {
+    case '?':
+      rl_noninc_forward_search (count, key);
+      break;
+
+    case '/':
+      rl_noninc_reverse_search (count, key);
+      break;
+
+    default:
+      ding ();
+      break;
+    }
+  return (0);
+}
+
+/* Completion, from vi's point of view. */
+rl_vi_complete (ignore, key)
+     int ignore, key;
+{
+  if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
+    {
+      if (!whitespace (rl_line_buffer[rl_point + 1]))
+       rl_vi_end_word (1, 'E');
+      rl_point++;
+    }
+
+  if (key == '*')
+    rl_complete_internal ('*');        /* Expansion and replacement. */
+  else if (key == '=')
+    rl_complete_internal ('?');        /* List possible completions. */
+  else if (key == '\\')
+    rl_complete_internal (TAB);        /* Standard Readline completion. */
+  else
+    rl_complete (0, key);
+
+  if (key == '*' || key == '\\')
+    {
+      _rl_vi_set_last (key, 1, rl_arg_sign);
+      rl_vi_insertion_mode (1, key);
+    }
+  return (0);
+}
+
+/* Tilde expansion for vi mode. */
+rl_vi_tilde_expand (ignore, key)
+     int ignore, key;
+{
+  rl_tilde_expand (0, key);
+  _rl_vi_set_last (key, 1, rl_arg_sign);       /* XXX */
+  rl_vi_insertion_mode (1, key);
+  return (0);
+}
+
+/* Previous word in vi mode. */
+rl_vi_prev_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_vi_next_word (-count, key));
+
+  if (rl_point == 0)
+    {
+      ding ();
+      return (0);
+    }
+
+  if (uppercase_p (key))
+    rl_vi_bWord (count);
+  else
+    rl_vi_bword (count);
+
+  return (0);
+}
+
+/* Next word in vi mode. */
+rl_vi_next_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_vi_prev_word (-count, key));
+
+  if (rl_point >= (rl_end - 1))
+    {
+      ding ();
+      return (0);
+    }
+
+  if (uppercase_p (key))
+    rl_vi_fWord (count);
+  else
+    rl_vi_fword (count);
+  return (0);
+}
+
+/* Move to the end of the ?next? word. */
+rl_vi_end_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    {
+      ding ();
+      return -1;
+    }
+
+  if (uppercase_p (key))
+    rl_vi_eWord (count);
+  else
+    rl_vi_eword (count);
+  return (0);
+}
+
+/* Move forward a word the way that 'W' does. */
+rl_vi_fWord (count)
+     int count;
+{
+  while (count-- && rl_point < (rl_end - 1))
+    {
+      /* Skip until whitespace. */
+      while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+       rl_point++;
+
+      /* Now skip whitespace. */
+      while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+       rl_point++;
+    }
+  return (0);
+}
+
+rl_vi_bWord (count)
+     int count;
+{
+  while (count-- && rl_point > 0)
+    {
+      /* If we are at the start of a word, move back to whitespace so
+        we will go back to the start of the previous word. */
+      if (!whitespace (rl_line_buffer[rl_point]) &&
+         whitespace (rl_line_buffer[rl_point - 1]))
+       rl_point--;
+
+      while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
+       rl_point--;
+
+      if (rl_point > 0)
+       {
+         while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
+         rl_point++;
+       }
+    }
+  return (0);
+}
+
+rl_vi_eWord (count)
+     int count;
+{
+  while (count-- && rl_point < (rl_end - 1))
+    {
+      if (!whitespace (rl_line_buffer[rl_point]))
+       rl_point++;
+
+      /* Move to the next non-whitespace character (to the start of the
+        next word). */
+      while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point]));
+
+      if (rl_point && rl_point < rl_end)
+       {
+         /* Skip whitespace. */
+         while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+           rl_point++;
+
+         /* Skip until whitespace. */
+         while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
+           rl_point++;
+
+         /* Move back to the last character of the word. */
+         rl_point--;
+       }
+    }
+  return (0);
+}
+
+rl_vi_fword (count)
+     int count;
+{
+  while (count-- && rl_point < (rl_end - 1))
+    {
+      /* Move to white space (really non-identifer). */
+      if (isident (rl_line_buffer[rl_point]))
+       {
+         while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
+           rl_point++;
+       }
+      else /* if (!whitespace (rl_line_buffer[rl_point])) */
+       {
+         while (!isident (rl_line_buffer[rl_point]) &&
+                !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+           rl_point++;
+       }
+
+      /* Move past whitespace. */
+      while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+       rl_point++;
+    }
+  return (0);
+}
+
+rl_vi_bword (count)
+     int count;
+{
+  while (count-- && rl_point > 0)
+    {
+      int last_is_ident;
+
+      /* If we are at the start of a word, move back to whitespace
+        so we will go back to the start of the previous word. */
+      if (!whitespace (rl_line_buffer[rl_point]) &&
+         whitespace (rl_line_buffer[rl_point - 1]))
+       rl_point--;
+
+      /* If this character and the previous character are `opposite', move
+        back so we don't get messed up by the rl_point++ down there in
+        the while loop.  Without this code, words like `l;' screw up the
+        function. */
+      last_is_ident = isident (rl_line_buffer[rl_point - 1]);
+      if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
+         (!isident (rl_line_buffer[rl_point]) && last_is_ident))
+       rl_point--;
+
+      while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
+       rl_point--;
+
+      if (rl_point > 0)
+       {
+         if (isident (rl_line_buffer[rl_point]))
+           while (--rl_point >= 0 && isident (rl_line_buffer[rl_point]));
+         else
+           while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) &&
+                  !whitespace (rl_line_buffer[rl_point]));
+         rl_point++;
+       }
+    }
+  return (0);
+}
+
+rl_vi_eword (count)
+     int count;
+{
+  while (count-- && rl_point < rl_end - 1)
+    {
+      if (!whitespace (rl_line_buffer[rl_point]))
+       rl_point++;
+
+      while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+       rl_point++;
+
+      if (rl_point < rl_end)
+       {
+         if (isident (rl_line_buffer[rl_point]))
+           while (++rl_point < rl_end && isident (rl_line_buffer[rl_point]));
+         else
+           while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point])
+                  && !whitespace (rl_line_buffer[rl_point]));
+       }
+      rl_point--;
+    }
+  return (0);
+}
+
+rl_vi_insert_beg (count, key)
+     int count, key;
+{
+  rl_beg_of_line (1, key);
+  rl_vi_insertion_mode (1, key);
+  return (0);
+}
+
+rl_vi_append_mode (count, key)
+     int count, key;
+{
+  if (rl_point < rl_end)
+    rl_point++;
+  rl_vi_insertion_mode (1, key);
+  return (0);
+}
+
+rl_vi_append_eol (count, key)
+     int count, key;
+{
+  rl_end_of_line (1, key);
+  rl_vi_append_mode (1, key);
+  return (0);
+}
+
+/* What to do in the case of C-d. */
+rl_vi_eof_maybe (count, c)
+     int count, c;
+{
+  return (rl_newline (1, '\n'));
+}
+
+/* Insertion mode stuff. */
+
+/* Switching from one mode to the other really just involves
+   switching keymaps. */
+rl_vi_insertion_mode (count, key)
+     int count, key;
+{
+  _rl_keymap = vi_insertion_keymap;
+  return (0);
+}
+
+void
+_rl_vi_done_inserting ()
+{
+  if (_rl_vi_doing_insert)
+    {
+      rl_end_undo_group ();
+      /* Now, the text between rl_undo_list->next->start and
+        rl_undo_list->next->end is what was inserted while in insert
+        mode. */
+      _rl_vi_doing_insert = 0;
+      vi_continued_command = 1;
+    }
+  else
+    vi_continued_command = 0;
+}
+
+rl_vi_movement_mode (count, key)
+     int count, key;
+{
+  if (rl_point > 0)
+    rl_backward (1);
+
+#if 0
+  _rl_vi_reset_last ();
+#endif
+
+  _rl_keymap = vi_movement_keymap;
+  _rl_vi_done_inserting ();
+  return (0);
+}
+
+rl_vi_arg_digit (count, c)
+     int count, c;
+{
+  if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
+    return (rl_beg_of_line ());
+  else
+    return (rl_digit_argument (count, c));
+}
+
+rl_vi_change_case (count, ignore)
+     int count, ignore;
+{
+  char c = 0;
+
+  /* Don't try this on an empty line. */
+  if (rl_point >= rl_end)
+    return (0);
+
+  while (count-- && rl_point < rl_end)
+    {
+      if (uppercase_p (rl_line_buffer[rl_point]))
+       c = to_lower (rl_line_buffer[rl_point]);
+      else if (lowercase_p (rl_line_buffer[rl_point]))
+       c = to_upper (rl_line_buffer[rl_point]);
+      else
+       {
+         /* Just skip over characters neither upper nor lower case. */
+         rl_forward (1);
+         continue;
+       }
+
+      /* Vi is kind of strange here. */
+      if (c)
+       {
+         rl_begin_undo_group ();
+         rl_delete (1, c);
+         rl_insert (1, c);
+         rl_end_undo_group ();
+         rl_vi_check ();
+        }
+      else
+       rl_forward (1);
+    }
+  return (0);
+}
+
+rl_vi_put (count, key)
+     int count, key;
+{
+  if (!uppercase_p (key) && (rl_point + 1 <= rl_end))
+    rl_point++;
+
+  rl_yank ();
+  rl_backward (1);
+  return (0);
+}
+
+rl_vi_check ()
+{
+  if (rl_point && rl_point == rl_end)
+    rl_point--;
+  return (0);
+}
+
+rl_vi_column (count, key)
+     int count, key;
+{
+  if (count > rl_end)
+    rl_end_of_line ();
+  else
+    rl_point = count - 1;
+  return (0);
+}
+
+int
+rl_vi_domove (key, nextkey)
+     int key, *nextkey;
+{
+  int c, save;
+  int old_end;
+
+  rl_mark = rl_point;
+  c = rl_read_key ();
+  *nextkey = c;
+
+  if (!member (c, vi_motion))
+    {
+      if (digit_p (c))
+       {
+         save = rl_numeric_arg;
+         rl_numeric_arg = digit_value (c);
+         rl_digit_loop1 ();
+         rl_numeric_arg *= save;
+         c = rl_read_key ();   /* real command */
+         *nextkey = c;
+       }
+      else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
+       {
+         rl_mark = rl_end;
+         rl_beg_of_line ();
+         _rl_vi_last_motion = c;
+         return (0);
+       }
+      else
+       return (-1);
+    }
+
+  _rl_vi_last_motion = c;
+
+  /* Append a blank character temporarily so that the motion routines
+     work right at the end of the line. */
+  old_end = rl_end;
+  rl_line_buffer[rl_end++] = ' ';
+  rl_line_buffer[rl_end] = '\0';
+
+  _rl_dispatch (c, _rl_keymap);
+
+  /* Remove the blank that we added. */
+  rl_end = old_end;
+  rl_line_buffer[rl_end] = '\0';
+  if (rl_point > rl_end)
+    rl_point = rl_end;
+
+  /* No change in position means the command failed. */
+  if (rl_mark == rl_point)
+    return (-1);
+
+  /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
+     word.  If we are not at the end of the line, and we are on a
+     non-whitespace character, move back one (presumably to whitespace). */
+  if ((to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
+      !whitespace (rl_line_buffer[rl_point]))
+    rl_point--;
+
+  /* If cw or cW, back up to the end of a word, so the behaviour of ce
+     or cE is the actual result.  Brute-force, no subtlety. */
+  if (key == 'c' && rl_point >= rl_mark && (to_upper (c) == 'W'))
+    {
+      /* Don't move farther back than where we started. */
+      while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
+       rl_point--;
+
+      /* Posix.2 says that if cw or cW moves the cursor towards the end of
+        the line, the character under the cursor should be deleted. */
+      if (rl_point == rl_mark)
+        rl_point++;
+      else
+       {
+         /* Move past the end of the word so that the kill doesn't
+            remove the last letter of the previous word.  Only do this
+            if we are not at the end of the line. */
+         if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
+           rl_point++;
+       }
+    }
+
+  if (rl_mark < rl_point)
+    exchange (rl_point, rl_mark);
+
+  return (0);
+}
+
+/* A simplified loop for vi. Don't dispatch key at end.
+   Don't recognize minus sign? */
+static int
+rl_digit_loop1 ()
+{
+  int key, c;
+
+  while (1)
+    {
+      rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0);
+      key = c = rl_read_key ();
+
+      if (_rl_keymap[c].type == ISFUNC &&
+         _rl_keymap[c].function == rl_universal_argument)
+       {
+         rl_numeric_arg *= 4;
+         continue;
+       }
+
+      c = UNMETA (c);
+      if (digit_p (c))
+       {
+         if (rl_explicit_arg)
+           rl_numeric_arg = (rl_numeric_arg * 10) + digit_value (c);
+         else
+           rl_numeric_arg = digit_value (c);
+         rl_explicit_arg = 1;
+       }
+      else
+       {
+         rl_clear_message ();
+         rl_stuff_char (key);
+         break;
+       }
+    }
+  return (0);
+}
+
+rl_vi_delete_to (count, key)
+     int count, key;
+{
+  int c;
+
+  if (uppercase_p (key))
+    rl_stuff_char ('$');
+  else if (vi_redoing)
+    rl_stuff_char (_rl_vi_last_motion);
+
+  if (rl_vi_domove (key, &c))
+    {
+      ding ();
+      return -1;
+    }
+
+  /* These are the motion commands that do not require adjusting the
+     mark. */
+  if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end))
+    rl_mark++;
+
+  rl_kill_text (rl_point, rl_mark);
+  return (0);
+}
+
+rl_vi_change_to (count, key)
+     int count, key;
+{
+  int c, start_pos;
+
+  if (uppercase_p (key))
+    rl_stuff_char ('$');
+  else if (vi_redoing)
+    rl_stuff_char (_rl_vi_last_motion);
+
+  start_pos = rl_point;
+
+  if (rl_vi_domove (key, &c))
+    {
+      ding ();
+      return -1;
+    }
+
+  /* These are the motion commands that do not require adjusting the
+     mark.  c[wW] are handled by special-case code in rl_vi_domove(),
+     and already leave the mark at the correct location. */
+  if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end))
+    rl_mark++;
+
+  /* The cursor never moves with c[wW]. */
+  if ((to_upper (c) == 'W') && rl_point < start_pos)
+    rl_point = start_pos;
+
+  rl_kill_text (rl_point, rl_mark);
+
+  rl_begin_undo_group ();
+  _rl_vi_doing_insert = 1;
+  _rl_vi_set_last (key, count, rl_arg_sign);
+  rl_vi_insertion_mode (1, key);
+
+  return (0);
+}
+
+rl_vi_yank_to (count, key)
+     int count, key;
+{
+  int c, save = rl_point;
+
+  if (uppercase_p (key))
+    rl_stuff_char ('$');
+
+  if (rl_vi_domove (key, &c))
+    {
+      ding ();
+      return -1;
+    }
+
+  /* These are the motion commands that do not require adjusting the
+     mark. */
+  if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end))
+    rl_mark++;
+
+  rl_begin_undo_group ();
+  rl_kill_text (rl_point, rl_mark);
+  rl_end_undo_group ();
+  rl_do_undo ();
+  rl_point = save;
+
+  return (0);
+}
+
+rl_vi_delete (count, key)
+     int count, key;
+{
+  int end;
+
+  if (rl_end == 0)
+    {
+      ding ();
+      return -1;
+    }
+
+  end = rl_point + count;
+
+  if (end >= rl_end)
+    end = rl_end;
+
+  rl_kill_text (rl_point, end);
+  
+  if (rl_point > 0 && rl_point == rl_end)
+    rl_backward (1);
+  return (0);
+}
+
+/* Turn the current line into a comment in shell history.
+   A K*rn shell style function. */
+rl_vi_comment (count, key)
+     int count, key;
+{
+  rl_beg_of_line ();
+
+  if (rl_vi_comment_begin != (char *)NULL)
+    rl_insert_text (rl_vi_comment_begin);
+  else
+    rl_insert_text (VI_COMMENT_BEGIN_DEFAULT); /* Default. */
+
+  rl_redisplay ();
+  rl_newline (1, '\n');
+  return (0);
+}
+
+rl_vi_first_print (count, key)
+     int count, key;
+{
+  return (rl_back_to_indent ());
+}
+
+rl_back_to_indent (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  rl_beg_of_line ();
+  while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+    rl_point++;
+  return (0);
+}
+
+/* NOTE: it is necessary that opposite directions are inverses */
+#define        FTO      1              /* forward to */
+#define BTO    -1              /* backward to */
+#define FFIND   2              /* forward find */
+#define BFIND  -2              /* backward find */
+
+rl_vi_char_search (count, key)
+     int count, key;
+{
+  static char target;
+  static int orig_dir, dir;
+  int pos;
+
+  if (key == ';' || key == ',')
+    dir = (key == ';' ? orig_dir : -orig_dir);
+  else
+    {
+      if (vi_redoing)
+       target = _rl_vi_last_search_char;
+      else
+       _rl_vi_last_search_char = target = rl_getc (rl_instream);
+
+      switch (key)
+        {
+        case 't':
+          orig_dir = dir = FTO;
+          break;
+
+        case 'T':
+          orig_dir = dir = BTO;
+          break;
+
+        case 'f':
+          orig_dir = dir = FFIND;
+          break;
+
+        case 'F':
+          orig_dir = dir = BFIND;
+          break;
+        }
+    }
+
+  pos = rl_point;
+
+  while (count--)
+    {
+      if (dir < 0)
+       {
+         if (pos == 0)
+           {
+             ding ();
+             return -1;
+           }
+
+         pos--;
+         do
+           {
+             if (rl_line_buffer[pos] == target)
+               {
+                 if (dir == BTO)
+                   rl_point = pos + 1;
+                 else
+                   rl_point = pos;
+                 break;
+               }
+           }
+         while (pos--);
+
+         if (pos < 0)
+           {
+             ding ();
+             return -1;
+           }
+       }
+      else
+       {                       /* dir > 0 */
+         if (pos >= rl_end)
+           {
+             ding ();
+             return -1;
+           }
+
+         pos++;
+         do
+           {
+             if (rl_line_buffer[pos] == target)
+               {
+                 if (dir == FTO)
+                   rl_point = pos - 1;
+                 else
+                   rl_point = pos;
+                 break;
+               }
+           }
+         while (++pos < rl_end);
+
+         if (pos >= (rl_end - 1))
+           {
+             ding ();
+             return -1;
+           }
+       }
+    }
+  return (0);
+}
+
+/* Match brackets */
+rl_vi_match (ignore, key)
+     int ignore, key;
+{
+  int count = 1, brack, pos;
+
+  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);
+
+      if (brack <= 0)
+       {
+         rl_point = pos;
+         ding ();
+         return -1;
+       }
+    }
+
+  pos = rl_point;
+
+  if (brack < 0)
+    {
+      while (count)
+       {
+         if (--pos >= 0)
+           {
+             int b = rl_vi_bracktype (rl_line_buffer[pos]);
+             if (b == -brack)
+               count--;
+             else if (b == brack)
+               count++;
+           }
+         else
+           {
+             ding ();
+             return -1;
+           }
+       }
+    }
+  else
+    {                  /* brack > 0 */
+      while (count)
+       {
+         if (++pos < rl_end)
+           {
+             int b = rl_vi_bracktype (rl_line_buffer[pos]);
+             if (b == -brack)
+               count--;
+             else if (b == brack)
+               count++;
+           }
+         else
+           {
+             ding ();
+             return -1;
+           }
+       }
+    }
+  rl_point = pos;
+  return (0);
+}
+
+int
+rl_vi_bracktype (c)
+     int c;
+{
+  switch (c)
+    {
+    case '(': return  1;
+    case ')': return -1;
+    case '[': return  2;
+    case ']': return -2;
+    case '{': return  3;
+    case '}': return -3;
+    default:  return  0;
+    }
+}
+
+rl_vi_change_char (count, key)
+     int count, key;
+{
+  int c;
+
+  if (vi_redoing)
+    c = _rl_vi_last_replacement;
+  else
+    _rl_vi_last_replacement = c = rl_getc (rl_instream);
+
+  if (c == '\033' || c == CTRL ('C'))
+    return -1;
+
+  while (count-- && rl_point < rl_end)
+    {
+      rl_begin_undo_group ();
+
+      rl_delete (1, c);
+      rl_insert (1, c);
+      if (count == 0)
+       rl_backward (1);
+
+      rl_end_undo_group ();
+    }
+  return (0);
+}
+
+rl_vi_subst (count, key)
+     int count, key;
+{
+  rl_begin_undo_group ();
+
+  if (uppercase_p (key))
+    {
+      rl_beg_of_line ();
+      rl_kill_line (1);
+    }
+  else
+    rl_delete_text (rl_point, rl_point+count);
+
+  rl_end_undo_group ();
+
+  _rl_vi_set_last (key, count, rl_arg_sign);
+
+  rl_begin_undo_group ();
+  _rl_vi_doing_insert = 1;
+  rl_vi_insertion_mode (1, key);
+
+  return (0);
+}
+
+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++)
+    {
+      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 ();
+    }
+  return (0);
+}
+
+rl_vi_overstrike_delete (count)
+     int count;
+{
+  int i, s;
+
+  for (i = 0; i < count; i++)
+    {
+      if (vi_replace_count == 0)
+       {
+         ding ();
+         break;
+       }
+      s = rl_point;
+
+      if (rl_do_undo ())
+       vi_replace_count--;
+
+      if (rl_point == s)
+       rl_backward (1);
+    }
+
+  if (vi_replace_count == 0 && _rl_vi_doing_insert)
+    {
+      rl_end_undo_group ();
+      rl_do_undo ();
+      _rl_vi_doing_insert = 0;
+    }
+  return (0);
+}
+
+rl_vi_replace (count, key)
+     int count, key;
+{
+  int i;
+
+  vi_replace_count = 0;
+
+  if (!vi_replace_map)
+    {
+      vi_replace_map = rl_make_bare_keymap ();
+
+      for (i = ' '; i < KEYMAP_SIZE; i++)
+       vi_replace_map[i].function = rl_vi_overstrike;
+
+      vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
+      vi_replace_map[ESC].function = rl_vi_movement_mode;
+      vi_replace_map[RETURN].function = rl_newline;
+      vi_replace_map[NEWLINE].function = rl_newline;
+
+      /* If the normal vi insertion keymap has ^H bound to erase, do the
+         same here.  Probably should remove the assignment to RUBOUT up
+         there, but I don't think it will make a difference in real life. */
+      if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
+         vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
+       vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
+
+    }
+  _rl_keymap = vi_replace_map;
+  return (0);
+}
+
+#if 0
+/* Try to complete the word we are standing on or the word that ends with
+   the previous character.  A space matches everything.  Word delimiters are
+   space and ;. */
+rl_vi_possible_completions()
+{
+  int save_pos = rl_point;
+
+  if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
+    {
+      while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
+            rl_line_buffer[rl_point] != ';')
+       rl_point++;
+    }
+  else if (rl_line_buffer[rl_point - 1] == ';')
+    {
+      ding ();
+      return (0);
+    }
+
+  rl_possible_completions ();
+  rl_point = save_pos;
+
+  return (0);
+}
+#endif
+
+#if defined (STATIC_MALLOC)
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)xmalloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
+
+#endif /* VI_MODE */
diff --git a/lib/readline/xmalloc.c b/lib/readline/xmalloc.c
new file mode 100644 (file)
index 0000000..4f6dc76
--- /dev/null
@@ -0,0 +1,78 @@
+/* xmalloc.c -- safe versions of malloc and realloc */
+
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Readline, a library for reading lines
+   of text with interactive input and history editing.
+
+   Readline is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 1, or (at your option) any
+   later version.
+
+   Readline is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if defined (ALREADY_HAVE_XMALLOC)
+#else
+#include <stdio.h>
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+static void memory_error_and_abort ();
+
+/* **************************************************************** */
+/*                                                                 */
+/*                Memory Allocation and Deallocation.              */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Return a pointer to free()able block of memory large enough
+   to hold BYTES number of bytes.  If the memory cannot be allocated,
+   print an error message and abort. */
+char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ("xmalloc");
+  return (temp);
+}
+
+char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ("xrealloc");
+  return (temp);
+}
+
+static void
+memory_error_and_abort (fname)
+     char *fname;
+{
+  fprintf (stderr, "%s: Out of virtual memory!\n", fname);
+  abort ();
+}
+#endif /* !ALREADY_HAVE_XMALLOC */
diff --git a/lib/termcap/Makefile b/lib/termcap/Makefile
new file mode 100644 (file)
index 0000000..b87de8d
--- /dev/null
@@ -0,0 +1,67 @@
+## -*- text -*- ####################################################
+#                                                                 #
+# Makefile for termcap replacement libbrary.                      #
+#                                                                 #
+####################################################################
+
+# 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.
+.c.o:
+       $(CC) -c $(CFLAGS) $(LOCAL_INCLUDES) $(CPPFLAGS) $*.c
+
+# Destination installation directory.  The libraries are copied to DESTDIR
+# when you do a `make install'.
+DESTDIR = /usr/local/lib
+
+DEBUG_FLAGS = -g
+#OPTIMIZE_FLAGS = -O
+LDFLAGS = $(DEBUG_FLAGS) 
+CFLAGS = $(DEBUG_FLAGS) $(OPTIMIZE_FLAGS)
+
+SHELL = /bin/sh
+
+# A good alternative is gcc -traditional.
+#CC = gcc -traditional
+CC = cc
+RANLIB = ranlib
+AR = ar
+RM = rm
+CP = cp
+
+CSOURCES = termcap.c tparam.c
+
+SOURCES  = $(CSOURCES)
+
+OBJECTS = termcap.o tparam.o
+
+DOCUMENTATION = termcap.texinfo
+
+THINGS_TO_TAR = $(SOURCES) $(DOCUMENTATION)
+
+##########################################################################
+
+all: libtermcap.a
+
+libtermcap.a:  $(OBJECTS)
+               $(RM) -f $@
+               $(AR) clq $@ $(OBJECTS)
+               -[ -n "$(RANLIB)" ] && $(RANLIB) $@
+
+termcap.tar:   $(THINGS_TO_TAR)
+               tar -cf $@ $(THINGS_TO_TAR)
+
+termcap.tar.Z: termcap.tar
+               compress -f termcap.tar
+
+install:       $(DESTDIR)/libtermcap.a
+
+clean:
+               rm -f *.o *.a *.log *.cp *.tp *.vr *.fn *.aux *.pg *.toc
+
+maintainer-clean realclean mostlyclean distclean: clean
+
+
+$(DESTDIR)/libtermcap.a: libtermcap.a
+               -mv $(DESTDIR)/libtermcap.a $(DESTDIR)/libtermcap.old
+               cp libtermcap.a $@
+               -[ -n "$(RANLIB) ] && $(RANLIB) -t $@
diff --git a/lib/termcap/grot/COPYING b/lib/termcap/grot/COPYING
new file mode 100644 (file)
index 0000000..a43ea21
--- /dev/null
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/lib/termcap/grot/ChangeLog b/lib/termcap/grot/ChangeLog
new file mode 100644 (file)
index 0000000..3a8b844
--- /dev/null
@@ -0,0 +1,48 @@
+Thu Apr 15 12:45:10 1993  David J. MacKenzie  (djm@kropotkin.gnu.ai.mit.edu)
+
+       * Version 1.2.
+
+       * tparam.c [!emacs] (xmalloc, xrealloc, memory_out): New functions.
+       (tparam1): Use them.
+
+       * termcap.c, tparam.c: Use NULL or '\0' where appropriate
+       instead of 0.  Rename some vars.
+       * termcap.c (tgetent): If EOF is reached on termcap file,
+       free allocated resources before returning.
+
+       * termcap.c (tgetent): Use /etc/termcap if TERMCAP is an entry
+       for a term type other than TERM.
+       From pjr@jet.UK (Paul J Rippin).
+
+Sat Apr 10 23:55:12 1993  Richard Stallman  (rms@mole.gnu.ai.mit.edu)
+
+       * tparam.c (tparam1): Don't set the 0200 bit on a non-0 character code.
+       From junio@twinsun.COM (Junio Hamano).
+
+Tue Dec  8 22:02:15 1992  David J. MacKenzie  (djm@kropotkin.gnu.ai.mit.edu)
+
+       * termcap.c, tparam.c: Use HAVE_STRING_H instead of USG.
+
+Thu Dec  3 13:47:56 1992  David J. MacKenzie  (djm@nutrimat.gnu.ai.mit.edu)
+
+       * termcap.c, tparam.c [HAVE_CONFIG_H]: Include config.h.
+
+Fri Oct 23 12:35:29 1992  David J. MacKenzie  (djm@goldman.gnu.ai.mit.edu)
+
+       * termcap.h [__STDC__]: Add consts.  From Franc,ois Pinard.
+
+Tue Oct 13 15:52:21 1992  David J. MacKenzie  (djm@goldman.gnu.ai.mit.edu)
+
+       * Version 1.1.
+
+Tue Sep 29 21:04:39 1992  David J. MacKenzie  (djm@geech.gnu.ai.mit.edu)
+
+       * termcap.[ch], tparam.c: Fix some lint.
+
+       * version.c: New file.
+\f
+Local Variables:
+mode: indented-text
+left-margin: 8
+version-control: never
+End:
diff --git a/lib/termcap/grot/INSTALL b/lib/termcap/grot/INSTALL
new file mode 100644 (file)
index 0000000..014e0f7
--- /dev/null
@@ -0,0 +1,117 @@
+This is a generic INSTALL file for utilities distributions.
+If this package does not come with, e.g., installable documentation or
+data files, please ignore the references to them below.
+
+To compile this package:
+
+1.  Configure the package for your system.  In the directory that this
+file is in, type `./configure'.  If you're using `csh' on an old
+version of System V, you might need to type `sh configure' instead to
+prevent `csh' from trying to execute `configure' itself.
+
+The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation, and
+creates the Makefile(s) (one in each subdirectory of the source
+directory).  In some packages it creates a C header file containing
+system-dependent definitions.  It also creates a file `config.status'
+that you can run in the future to recreate the current configuration.
+
+Running `configure' takes a minute or two.  While it is running, it
+prints some messages that tell what it is doing.  If you don't want to
+see the messages, run `configure' with its standard output redirected
+to `/dev/null'; for example, `./configure >/dev/null'.
+
+To compile the package in a different directory from the one
+containing the source code, you must use a version of `make' that
+supports the VPATH variable, such as GNU `make'.  `cd' to the directory
+where you want the object files and executables to go and run
+`configure'.  `configure' automatically checks for the source code in
+the directory that `configure' is in and in `..'.  If for some reason
+`configure' is not in the source code directory that you are
+configuring, then it will report that it can't find the source code.
+In that case, run `configure' with the option `--srcdir=DIR', where
+DIR is the directory that contains the source code.
+
+By default, `make install' will install the package's files in
+/usr/local/bin, /usr/local/lib, /usr/local/man, etc.  You can specify
+an installation prefix other than /usr/local by giving `configure' the
+option `--prefix=PATH'.  Alternately, you can do so by giving a value
+for the `prefix' variable when you run `make', e.g.,
+       make prefix=/usr/gnu
+
+You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If
+you give `configure' the option `--exec-prefix=PATH' or set the
+`make' variable `exec_prefix' to PATH, the package will use PATH as
+the prefix for installing programs and libraries.  Data files and
+documentation will still use the regular prefix.  Normally, all files
+are installed using the regular prefix.
+
+Another `configure' option is useful mainly in `Makefile' rules for
+updating `config.status' and `Makefile'.  The `--no-create' option
+figures out the configuration for your system and records it in
+`config.status', without actually configuring the package (creating
+`Makefile's and perhaps a configuration header file).  Later, you can
+run `./config.status' to actually configure the package.  You can also
+give `config.status' the `--recheck' option, which makes it re-run
+`configure' with the same arguments you used before.  This option is
+useful if you change `configure'.
+
+Some packages pay attention to `--with-PACKAGE' options to `configure',
+where PACKAGE is something like `gnu-libc' or `x' (for the X Window System).
+The README should mention any --with- options that the package recognizes.
+
+`configure' ignores any other arguments that you give it.
+
+If your system requires unusual options for compilation or linking
+that `configure' doesn't know about, you can give `configure' initial
+values for some variables by setting them in the environment.  In
+Bourne-compatible shells, you can do that on the command line like
+this:
+       CC='gcc -traditional' DEFS=-D_POSIX_SOURCE ./configure
+
+The `make' variables that you might want to override with environment
+variables when running `configure' are:
+
+(For these variables, any value given in the environment overrides the
+value that `configure' would choose:)
+CC             C compiler program.
+               Default is `cc', or `gcc' if `gcc' is in your PATH.
+INSTALL                Program to use to install files.
+               Default is `install' if you have it, `cp' otherwise.
+
+(For these variables, any value given in the environment is added to
+the value that `configure' chooses:)
+DEFS           Configuration options, in the form `-Dfoo -Dbar ...'
+               Do not use this variable in packages that create a
+               configuration header file.
+LIBS           Libraries to link with, in the form `-lfoo -lbar ...'
+
+If you need to do unusual things to compile the package, we encourage
+you to figure out how `configure' could check whether to do them, and
+mail diffs or instructions to the address given in the README so we
+can include them in the next release.
+
+2.  Type `make' to compile the package.  If you want, you can override
+the `make' variables CFLAGS and LDFLAGS like this:
+
+       make CFLAGS=-O2 LDFLAGS=-s
+
+3.  If the package comes with self-tests and you want to run them,
+type `make check'.  If you're not sure whether there are any, try it;
+if `make' responds with something like
+       make: *** No way to make target `check'.  Stop.
+then the package does not come with self-tests.
+
+4.  Type `make install' to install programs, data files, and
+documentation.
+
+5.  You can remove the program binaries and object files from the
+source directory by typing `make clean'.  To also remove the
+Makefile(s), the header file containing system-dependent definitions
+(if the package uses one), and `config.status' (all the files that
+`configure' created), type `make distclean'.
+
+The file `configure.in' is used as a template to create `configure' by
+a program called `autoconf'.  You will only need it if you want to
+regenerate `configure' using a newer version of `autoconf'.
diff --git a/lib/termcap/grot/Makefile.in b/lib/termcap/grot/Makefile.in
new file mode 100644 (file)
index 0000000..309603d
--- /dev/null
@@ -0,0 +1,118 @@
+# Makefile for GNU termcap library.
+# Copyright (C) 1992, 1993 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+CC = @CC@
+
+# If you don't have a BSD or GNU install program, use cp.
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+
+MAKEINFO = makeinfo
+
+# Things you might add to DEFS:
+# -DHAVE_STRING_H      If you have memcpy instead of bcopy.
+# -DNO_ARG_ARRAY       If you can't take the address of the first of
+#                      a group of arguments and treat it as an array.
+#                      We always define this, because it's not a big loss
+#                      and can't be detected when cross-autoconfiguring.
+
+DEFS = @DEFS@ -DNO_ARG_ARRAY
+
+CFLAGS = -g
+
+prefix = /usr/local
+exec_prefix = $(prefix)
+
+# Directory in which to install libtermcap.a.
+libdir = $(exec_prefix)/lib
+
+# Directory in which to install termcap.h.
+includedir = $(prefix)/include
+
+# Directory in which to optionally also install termcap.h,
+# so compilers besides gcc can find it by default.
+# If it is empty or not defined, termcap.h will only be installed in
+# includedir. 
+oldincludedir = /usr/include
+
+# Directory in which to install the documentation info files.
+infodir = $(prefix)/info
+
+#### End of system configuration section. ####
+
+SHELL = /bin/sh
+
+SRCS = termcap.c tparam.c version.c
+OBJS = termcap.o tparam.o version.o
+HDRS = termcap.h
+DISTFILES = $(SRCS) $(HDRS) ChangeLog COPYING README INSTALL NEWS \
+termcap.texi termcap.info* \
+texinfo.tex Makefile.in configure configure.in
+
+all:   libtermcap.a termcap.info
+
+.c.o:
+       $(CC) -c $(CPPFLAGS) $(DEFS) -I$(srcdir) $(CFLAGS) $<
+
+install: all
+       $(INSTALL_DATA) libtermcap.a $(libdir)/libtermcap.a
+       -ranlib $(libdir)/libtermcap.a
+       test -d $(includedir) || mkdir $(includedir)
+       cd $(srcdir); $(INSTALL_DATA) termcap.h $(includedir)/termcap.h
+       -cd $(srcdir); test -z "$(oldincludedir)" || \
+         $(INSTALL_DATA) termcap.h $(oldincludedir)/termcap.h
+       cd $(srcdir); for f in termcap.info*; \
+       do $(INSTALL_DATA) $$f $(infodir)/$$f; done
+
+uninstall:
+       rm -f $(libdir)/libtermcap.a $(includedir)/termcap.h
+       test -z "$(oldincludedir)" || rm -f $(oldincludedir)/termcap.h
+       rm -f $(infodir)/termcap.info*
+
+libtermcap.a: $(OBJS)
+       ar rc $@ $(OBJS)
+       -ranlib $@
+
+termcap.info: termcap.texi
+       $(MAKEINFO) $(srcdir)/termcap.texi --output=$(srcdir)/termcap.info
+
+TAGS:  $(SRCS)
+       etags $(SRCS)
+
+clean:
+       rm -f *.a *.o core
+
+mostlyclean: clean
+
+distclean: clean
+       rm -f Makefile config.status
+
+realclean: distclean
+       rm -f TAGS *.info*
+
+dist: $(DISTFILES)
+       echo termcap-`sed -e '/version_string/!d' -e 's/[^0-9]*\([0-9a-z.]*\).*/\1/' -e q version.c` > .fname
+       rm -rf `cat .fname`
+       mkdir `cat .fname`
+       ln $(DISTFILES) `cat .fname`
+       tar chzf `cat .fname`.tar.z `cat .fname`
+       rm -rf `cat .fname` .fname
diff --git a/lib/termcap/grot/NEWS b/lib/termcap/grot/NEWS
new file mode 100644 (file)
index 0000000..c696fdf
--- /dev/null
@@ -0,0 +1,12 @@
+Major changes in release 1.2:
+
+For `%.', only set the high bit on NUL.
+Fix a file descriptor and memory leak.
+Add const in termcap.h prototypes.
+Configuration improvements.
+\f
+Major changes in release 1.1:
+
+Fix portability problems.
+Improve configuration and installation.
+Fix compiler warnings.
diff --git a/lib/termcap/grot/README b/lib/termcap/grot/README
new file mode 100644 (file)
index 0000000..9db9095
--- /dev/null
@@ -0,0 +1,14 @@
+This is the GNU termcap library -- a library of C functions that
+enable programs to send control strings to terminals in a way
+independent of the terminal type.  Most of this package is also
+distributed with GNU Emacs, but it is available in this separate
+distribution to make it easier to install as -ltermcap.
+
+The GNU termcap library does not place an arbitrary limit on the size
+of termcap entries, unlike most other termcap libraries.
+
+See the file INSTALL for compilation and installation instructions.
+
+Please report any bugs in this library to bug-gnu-emacs@prep.ai.mit.edu.
+You can check which version of the library you have by using the RCS
+`ident' command on libtermcap.a.
diff --git a/lib/termcap/grot/configure b/lib/termcap/grot/configure
new file mode 100755 (executable)
index 0000000..bc34d0a
--- /dev/null
@@ -0,0 +1,346 @@
+#!/bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf.
+# Copyright (C) 1991, 1992, 1993 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# Usage: configure [--srcdir=DIR] [--host=HOST] [--gas] [--nfp] [--no-create]
+#        [--prefix=PREFIX] [--exec-prefix=PREFIX] [--with-PACKAGE] [TARGET]
+# Ignores all args except --srcdir, --prefix, --exec-prefix, --no-create, and
+# --with-PACKAGE unless this script has special code to handle it.
+
+
+for arg
+do
+  # Handle --exec-prefix with a space before the argument.
+  if test x$next_exec_prefix = xyes; then exec_prefix=$arg; next_exec_prefix=
+  # Handle --host with a space before the argument.
+  elif test x$next_host = xyes; then next_host=
+  # Handle --prefix with a space before the argument.
+  elif test x$next_prefix = xyes; then prefix=$arg; next_prefix=
+  # Handle --srcdir with a space before the argument.
+  elif test x$next_srcdir = xyes; then srcdir=$arg; next_srcdir=
+  else
+    case $arg in
+     # For backward compatibility, also recognize exact --exec_prefix.
+     -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* | --exec=* | --exe=* | --ex=* | --e=*)
+       exec_prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;;
+     -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- | --exec | --exe | --ex | --e)
+       next_exec_prefix=yes ;;
+
+     -gas | --gas | --ga | --g) ;;
+
+     -host=* | --host=* | --hos=* | --ho=* | --h=*) ;;
+     -host | --host | --hos | --ho | --h)
+       next_host=yes ;;
+
+     -nfp | --nfp | --nf) ;;
+
+     -no-create | --no-create | --no-creat | --no-crea | --no-cre | --no-cr | --no-c | --no- | --no)
+        no_create=1 ;;
+
+     -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+       prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;;
+     -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+       next_prefix=yes ;;
+
+     -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=* | --s=*)
+       srcdir=`echo $arg | sed 's/[-a-z_]*=//'` ;;
+     -srcdir | --srcdir | --srcdi | --srcd | --src | --sr | --s)
+       next_srcdir=yes ;;
+
+     -with-* | --with-*)
+       package=`echo $arg|sed 's/-*with-//'`
+       # Delete all the valid chars; see if any are left.
+       if test -n "`echo $package|sed 's/[-a-zA-Z0-9_]*//g'`"; then
+         echo "configure: $package: invalid package name" >&2; exit 1
+       fi
+       eval "with_`echo $package|sed s/-/_/g`=1" ;;
+
+     -v | -verbose | --verbose | --verbos | --verbo | --verb | --ver | --ve | --v)
+       verbose=yes ;;
+
+     *) ;;
+    esac
+  fi
+done
+
+trap 'rm -f conftest* core; exit 1' 1 3 15
+
+rm -f conftest*
+compile='${CC-cc} $CFLAGS $DEFS conftest.c -o conftest $LIBS >/dev/null 2>&1'
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+unique_file=termcap.h
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  srcdirdefaulted=yes
+  # Try the directory containing this script, then `..'.
+  prog=$0
+  confdir=`echo $prog|sed 's%/[^/][^/]*$%%'`
+  test "X$confdir" = "X$prog" && confdir=.
+  srcdir=$confdir
+  if test ! -r $srcdir/$unique_file; then
+    srcdir=..
+  fi
+fi
+if test ! -r $srcdir/$unique_file; then
+  if test x$srcdirdefaulted = xyes; then
+    echo "configure: Can not find sources in \`${confdir}' or \`..'." 1>&2
+  else
+    echo "configure: Can not find sources in \`${srcdir}'." 1>&2
+  fi
+  exit 1
+fi
+# Preserve a srcdir of `.' to avoid automounter screwups with pwd.
+# But we can't avoid them for `..', to make subdirectories work.
+case $srcdir in
+  .|/*|~*) ;;
+  *) srcdir=`cd $srcdir; pwd` ;; # Make relative path absolute.
+esac
+
+if test -z "$CC"; then
+  echo checking for gcc
+  saveifs="$IFS"; IFS="${IFS}:"
+  for dir in $PATH; do
+    test -z "$dir" && dir=.
+    if test -f $dir/gcc; then
+      CC="gcc"
+      break
+    fi
+  done
+  IFS="$saveifs"
+fi
+test -z "$CC" && CC="cc"
+
+# Find out if we are using GNU C, under whatever name.
+cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes
+#endif
+EOF
+${CC-cc} -E conftest.c > conftest.out 2>&1
+if egrep yes conftest.out >/dev/null 2>&1; then
+  GCC=1 # For later tests.
+fi
+rm -f conftest*
+
+echo checking how to run the C preprocessor
+if test -z "$CPP"; then
+  CPP='${CC-cc} -E'
+  cat > conftest.c <<EOF
+#include <stdio.h>
+EOF
+err=`eval "($CPP $DEFS conftest.c >/dev/null) 2>&1"`
+if test -z "$err"; then
+  :
+else
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+
+# Make sure to not get the incompatible SysV /etc/install and
+# /usr/sbin/install, which might be in PATH before a BSD-like install,
+# or the SunOS /usr/etc/install directory, or the AIX /bin/install,
+# or the AFS install, which mishandles nonexistent args.  (Sigh.)
+if test -z "$INSTALL"; then
+  echo checking for install
+  saveifs="$IFS"; IFS="${IFS}:"
+  for dir in $PATH; do
+    test -z "$dir" && dir=.
+    case $dir in
+    /etc|/usr/sbin|/usr/etc|/usr/afsws/bin) ;;
+    *)
+      if test -f $dir/installbsd; then
+       INSTALL="$dir/installbsd -c" # OSF1
+       INSTALL_PROGRAM='$(INSTALL)'
+       INSTALL_DATA='$(INSTALL) -m 644'
+       break
+      fi
+      if test -f $dir/install; then
+       if grep dspmsg $dir/install >/dev/null 2>&1; then
+         : # AIX
+       else
+         INSTALL="$dir/install -c"
+         INSTALL_PROGRAM='$(INSTALL)'
+         INSTALL_DATA='$(INSTALL) -m 644'
+         break
+       fi
+      fi
+      ;;
+    esac
+  done
+  IFS="$saveifs"
+fi
+INSTALL=${INSTALL-cp}
+INSTALL_PROGRAM=${INSTALL_PROGRAM-'$(INSTALL)'}
+INSTALL_DATA=${INSTALL_DATA-'$(INSTALL)'}
+
+for hdr in string.h
+do
+trhdr=HAVE_`echo $hdr | tr '[a-z]./' '[A-Z]__'`
+echo checking for ${hdr}
+cat > conftest.c <<EOF
+#include <${hdr}>
+EOF
+err=`eval "($CPP $DEFS conftest.c >/dev/null) 2>&1"`
+if test -z "$err"; then
+  {
+test -n "$verbose" && \
+echo ' defining' ${trhdr}
+DEFS="$DEFS -D${trhdr}=1"
+}
+
+fi
+rm -f conftest*
+done
+
+echo checking for unistd.h
+cat > conftest.c <<EOF
+#include <unistd.h>
+EOF
+err=`eval "($CPP $DEFS conftest.c >/dev/null) 2>&1"`
+if test -z "$err"; then
+  {
+test -n "$verbose" && \
+echo ' defining' HAVE_UNISTD_H
+DEFS="$DEFS -DHAVE_UNISTD_H=1"
+}
+
+fi
+rm -f conftest*
+
+echo checking for ANSI C header files
+cat > conftest.c <<EOF
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+err=`eval "($CPP $DEFS conftest.c >/dev/null) 2>&1"`
+if test -z "$err"; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+echo '#include <string.h>' > conftest.c
+eval "$CPP $DEFS conftest.c > conftest.out 2>&1"
+if egrep "memchr" conftest.out >/dev/null 2>&1; then
+  # SGI's /bin/cc from Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+cat > conftest.c <<EOF
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e,f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+eval $compile
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+  {
+test -n "$verbose" && \
+echo ' defining' STDC_HEADERS
+DEFS="$DEFS -DSTDC_HEADERS=1"
+}
+
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+
+if test -n "$prefix"; then
+  test -z "$exec_prefix" && exec_prefix='${prefix}'
+  prsub="s%^prefix\\([         ]*\\)=\\([      ]*\\).*$%prefix\\1=\\2$prefix%"
+fi
+if test -n "$exec_prefix"; then
+  prsub="$prsub
+s%^exec_prefix\\([     ]*\\)=\\([      ]*\\).*$%\
+exec_prefix\\1=\\2$exec_prefix%"
+fi
+
+trap 'rm -f config.status; exit 1' 1 3 15
+echo creating config.status
+rm -f config.status
+cat > config.status <<EOF
+#!/bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $*
+
+for arg
+do
+  case "\$arg" in
+    -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    exec /bin/sh $0 $* ;;
+    *) echo "Usage: config.status --recheck" 2>&1; exit 1 ;;
+  esac
+done
+
+trap 'rm -f Makefile; exit 1' 1 3 15
+PROGS='$PROGS'
+CC='$CC'
+CPP='$CPP'
+INSTALL='$INSTALL'
+INSTALL_PROGRAM='$INSTALL_PROGRAM'
+INSTALL_DATA='$INSTALL_DATA'
+LIBS='$LIBS'
+srcdir='$srcdir'
+DEFS='$DEFS'
+prefix='$prefix'
+exec_prefix='$exec_prefix'
+prsub='$prsub'
+EOF
+cat >> config.status <<\EOF
+
+top_srcdir=$srcdir
+for file in .. Makefile; do if [ "x$file" != "x.." ]; then
+  srcdir=$top_srcdir
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  dir=`echo $file|sed 's%/[^/][^/]*$%%'`
+  if test "$dir" != "$file"; then
+    test "$top_srcdir" != . && srcdir=$top_srcdir/$dir
+    test ! -d $dir && mkdir $dir
+  fi
+  echo creating $file
+  rm -f $file
+  echo "# Generated automatically from `echo $file|sed 's|.*/||'`.in by configure." > $file
+  sed -e "
+$prsub
+s%@PROGS@%$PROGS%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@INSTALL@%$INSTALL%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@LIBS@%$LIBS%g
+s%@srcdir@%$srcdir%g
+s%@DEFS@%$DEFS%
+" $top_srcdir/${file}.in >> $file
+fi; done
+
+exit 0
+EOF
+chmod +x config.status
+test -n "$no_create" || ./config.status
+
diff --git a/lib/termcap/grot/configure.in b/lib/termcap/grot/configure.in
new file mode 100644 (file)
index 0000000..1c2aaf2
--- /dev/null
@@ -0,0 +1,10 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(termcap.h)
+AC_SUBST(PROGS)dnl
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_HAVE_HEADERS(string.h)
+AC_UNISTD_H
+AC_STDC_HEADERS
+AC_OUTPUT(Makefile)
diff --git a/lib/termcap/grot/termcap.info b/lib/termcap/grot/termcap.info
new file mode 100644 (file)
index 0000000..f8515f1
--- /dev/null
@@ -0,0 +1,80 @@
+This is Info file /home/gd/gnu/termcap/termcap.info, produced by
+Makeinfo-1.52 from the input file /home/gd/gnu/termcap/termcap.texi.
+
+   This file documents the termcap library of the GNU system.
+
+   Copyright (C) 1988 Free Software Foundation, Inc.
+
+   Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+   Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+   Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+\1f
+Indirect:
+termcap.info-1: 912
+termcap.info-2: 47539
+termcap.info-3: 90314
+termcap.info-4: 138449
+\1f
+Tag Table:
+(Indirect)
+Node: Top\7f912
+Node: Introduction\7f4143
+Node: Library\7f5870
+Node: Preparation\7f6889
+Node: Find\7f8072
+Node: Interrogate\7f11620
+Node: Initialize\7f16928
+Node: Padding\7f18568
+Node: Why Pad\7f19274
+Node: Not Enough\7f20896
+Node: Describe Padding\7f23464
+Node: Output Padding\7f24954
+Node: Parameters\7f28569
+Node: Encode Parameters\7f30229
+Node: Using Parameters\7f36313
+Node: tparam\7f36908
+Node: tgoto\7f38934
+Node: Data Base\7f41489
+Node: Format\7f42385
+Node: Capability Format\7f44474
+Node: Naming\7f47539
+Node: Inheriting\7f52108
+Node: Changing\7f54352
+Node: Capabilities\7f55516
+Node: Basic\7f58255
+Node: Screen Size\7f62308
+Node: Cursor Motion\7f64048
+Node: Wrapping\7f74190
+Node: Scrolling\7f77015
+Node: Windows\7f82904
+Node: Clearing\7f83638
+Node: Insdel Line\7f85402
+Node: Insdel Char\7f90314
+Node: Standout\7f100299
+Node: Underlining\7f109357
+Node: Cursor Visibility\7f111776
+Node: Bell\7f112524
+Node: Keypad\7f113073
+Node: Meta Key\7f117794
+Node: Initialization\7f118748
+Node: Pad Specs\7f121112
+Node: Status Line\7f123165
+Node: Half-Line\7f125049
+Node: Printer\7f125851
+Node: Summary\7f127530
+Node: Var Index\7f137736
+Node: Cap Index\7f138449
+Node: Index\7f145507
+\1f
+End Tag Table
diff --git a/lib/termcap/grot/termcap.info-1 b/lib/termcap/grot/termcap.info-1
new file mode 100644 (file)
index 0000000..8390359
--- /dev/null
@@ -0,0 +1,1115 @@
+This is Info file /home/gd/gnu/termcap/termcap.info, produced by
+Makeinfo-1.52 from the input file /home/gd/gnu/termcap/termcap.texi.
+
+   This file documents the termcap library of the GNU system.
+
+   Copyright (C) 1988 Free Software Foundation, Inc.
+
+   Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+   Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+   Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+\1f
+File: termcap.info,  Node: Top,  Next: Introduction,  Prev: (dir),  Up: (dir)
+
+* Menu:
+
+* Introduction::  What is termcap?  Why this manual?
+* Library::     The termcap library functions.
+* Data Base::   What terminal descriptions in `/etc/termcap' look like.
+* Capabilities::  Definitions of the individual terminal capabilities:
+                 how to write them in descriptions, and how to use
+                 their values to do display updating.
+* Summary::     Brief table of capability names and their meanings.
+* Var Index::   Index of C functions and variables.
+* Cap Index::   Index of termcap capabilities.
+* Index::       Concept index.
+
+ -- The Detailed Node Listing --
+
+The Termcap Library
+
+* Preparation::  Preparing to use the termcap library.
+* Find::        Finding the description of the terminal being used.
+* Interrogate::  Interrogating the description for particular capabilities.
+* Initialize::  Initialization for output using termcap.
+* Padding::     Outputting padding.
+* Parameters::  Encoding parameters such as cursor positions.
+
+Padding
+
+* Why Pad::     Explanation of padding.
+* Not Enough::  When there is not enough padding.
+* Describe Padding::  The data base says how much padding a terminal needs.
+* Output Padding::    Using `tputs' to output the needed padding.
+
+Filling In Parameters
+
+* Encode Parameters::  The language for encoding parameters.
+* Using Parameters::   Outputting a string command with parameters.
+
+Sending Display Commands with Parameters
+
+* tparam::      The general case, for GNU termcap only.
+* tgoto::       The special case of cursor motion.
+
+The Format of the Data Base
+
+* Format::      Overall format of a terminal description.
+* Capability Format::  Format of capabilities within a description.
+* Naming::      Naming conventions for terminal types.
+* Inheriting::  Inheriting part of a description from
+a related terminal type.
+* Changing::    When changes in the data base take effect.
+
+Definitions of the Terminal Capabilities
+
+* Basic::       Basic characteristics.
+* Screen Size::  Screen size, and what happens when it changes.
+* Cursor Motion::  Various ways to move the cursor.
+* Wrapping::    What happens if you write a character in the last column.
+* Scrolling::   Pushing text up and down on the screen.
+* Windows::     Limiting the part of the window that output affects.
+* Clearing::    Erasing one or many lines.
+* Insdel Line::  Making new blank lines in mid-screen; deleting lines.
+* Insdel Char::  Inserting and deleting characters within a line.
+* Standout::    Highlighting some of the text.
+* Underlining::  Underlining some of the text.
+* Cursor Visibility::  Making the cursor more or less easy to spot.
+* Bell::        Attracts user's attention; not localized on the screen.
+* Keypad::      Recognizing when function keys or arrows are typed.
+* Meta Key::    META acts like an extra shift key.
+* Initialization::  Commands used to initialize or reset the terminal.
+* Pad Specs::   Info for the kernel on how much padding is needed.
+* Status Line::  A status line displays "background" information.
+* Half-Line::   Moving by half-lines, for superscripts and subscripts.
+* Printer::     Controlling auxiliary printers of display terminals.
+
+\1f
+File: termcap.info,  Node: Introduction,  Next: Library,  Prev: Top,  Up: Top
+
+Introduction
+************
+
+   "Termcap" is a library and data base that enables programs to use
+display terminals in a terminal-independent manner.  It originated in
+Berkeley Unix.
+
+   The termcap data base describes the capabilities of hundreds of
+different display terminals in great detail.  Some examples of the
+information recorded for a terminal could include how many columns wide
+it is, what string to send to move the cursor to an arbitrary position
+(including how to encode the row and column numbers), how to scroll the
+screen up one or several lines, and how much padding is needed for such
+a scrolling operation.
+
+   The termcap library is provided for easy access this data base in
+programs that want to do terminal-independent character-based display
+output.
+
+   This manual describes the GNU version of the termcap library, which
+has some extensions over the Unix version.  All the extensions are
+identified as such, so this manual also tells you how to use the Unix
+termcap.
+
+   The GNU version of the termcap library is available free as source
+code, for use in free programs, and runs on Unix and VMS systems (at
+least).  You can find it in the GNU Emacs distribution in the files
+`termcap.c' and `tparam.c'.
+
+   This manual was written for the GNU project, whose goal is to
+develop a complete free operating system upward-compatible with Unix
+for user programs.  The project is approximately two thirds complete.
+For more information on the GNU project, including the GNU Emacs editor
+and the mostly-portable optimizing C compiler, send one dollar to
+
+     Free Software Foundation
+     675 Mass Ave
+     Cambridge, MA 02139
+
+\1f
+File: termcap.info,  Node: Library,  Next: Data Base,  Prev: Introduction,  Up: Top
+
+The Termcap Library
+*******************
+
+   The termcap library is the application programmer's interface to the
+termcap data base.  It contains functions for the following purposes:
+
+   * Finding the description of the user's terminal type (`tgetent').
+
+   * Interrogating the description for information on various topics
+     (`tgetnum', `tgetflag', `tgetstr').
+
+   * Computing and performing padding (`tputs').
+
+   * Encoding numeric parameters such as cursor positions into the
+     terminal-specific form required for display commands (`tparam',
+     `tgoto').
+
+* Menu:
+
+* Preparation::  Preparing to use the termcap library.
+* Find::        Finding the description of the terminal being used.
+* Interrogate::  Interrogating the description for particular capabilities.
+* Initialize::  Initialization for output using termcap.
+* Padding::     Outputting padding.
+* Parameters::  Encoding parameters such as cursor positions.
+
+\1f
+File: termcap.info,  Node: Preparation,  Next: Find,  Up: Library
+
+Preparing to Use the Termcap Library
+====================================
+
+   To use the termcap library in a program, you need two kinds of
+preparation:
+
+   * The compiler needs declarations of the functions and variables in
+     the library.
+
+     On GNU systems, it suffices to include the header file `termcap.h'
+     in each source file that uses these functions and variables.
+
+     On Unix systems, there is often no such header file.  Then you must
+     explictly declare the variables as external.  You can do likewise
+     for the functions, or let them be implicitly declared and cast
+     their values from type `int' to the appropriate type.
+
+     We illustrate the declarations of the individual termcap library
+     functions with ANSI C prototypes because they show how to pass the
+     arguments.  If you are not using the GNU C compiler, you probably
+     cannot use function prototypes, so omit the argument types and
+     names from your declarations.
+
+   * The linker needs to search the library.  Usually either
+     `-ltermcap' or `-ltermlib' as an argument when linking will do
+     this.
+
+\1f
+File: termcap.info,  Node: Find,  Next: Interrogate,  Prev: Preparation,  Up: Library
+
+Finding a Terminal Description: `tgetent'
+=========================================
+
+   An application program that is going to use termcap must first look
+up the description of the terminal type in use.  This is done by calling
+`tgetent', whose declaration in ANSI Standard C looks like:
+
+     int tgetent (char *BUFFER, char *TERMTYPE);
+
+This function finds the description and remembers it internally so that
+you can interrogate it about specific terminal capabilities (*note
+Interrogate::.).
+
+   The argument TERMTYPE is a string which is the name for the type of
+terminal to look up.  Usually you would obtain this from the environment
+variable `TERM' using `getenv ("TERM")'.
+
+   If you are using the GNU version of termcap, you can alternatively
+ask `tgetent' to allocate enough space.  Pass a null pointer for
+BUFFER, and `tgetent' itself allocates the storage using `malloc'.  In
+this case the returned value on success is the address of the storage,
+cast to `int'.  But normally there is no need for you to look at the
+address.  Do not free the storage yourself.
+
+   With the Unix version of termcap, you must allocate space for the
+description yourself and pass the address of the space as the argument
+BUFFER.  There is no way you can tell how much space is needed, so the
+convention is to allocate a buffer 2048 characters long and assume that
+is enough.  (Formerly the convention was to allocate 1024 characters and
+assume that was enough.  But one day, for one kind of terminal, that was
+not enough.)
+
+   No matter how the space to store the description has been obtained,
+termcap records its address internally for use when you later
+interrogate the description with `tgetnum', `tgetstr' or `tgetflag'.  If
+the buffer was allocated by termcap, it will be freed by termcap too if
+you call `tgetent' again.  If the buffer was provided by you, you must
+make sure that its contents remain unchanged for as long as you still
+plan to interrogate the description.
+
+   The return value of `tgetent' is -1 if there is some difficulty
+accessing the data base of terminal types, 0 if the data base is
+accessible but the specified type is not defined in it, and some other
+value otherwise.
+
+   Here is how you might use the function `tgetent':
+
+     #ifdef unix
+     static char term_buffer[2048];
+     #else
+     #define term_buffer 0
+     #endif
+     
+     init_terminal_data ()
+     {
+       char *termtype = getenv ("TERM");
+       int success;
+     
+       if (termtype == 0)
+         fatal ("Specify a terminal type with `setenv TERM <yourtype>'.\n");
+     
+       success = tgetent (term_buffer, termtype);
+       if (success < 0)
+         fatal ("Could not access the termcap data base.\n");
+       if (success == 0)
+         fatal ("Terminal type `%s' is not defined.\n", termtype);
+     }
+
+Here we assume the function `fatal' prints an error message and exits.
+
+   If the environment variable `TERMCAP' is defined, its value is used
+to override the terminal type data base.  The function `tgetent' checks
+the value of `TERMCAP' automatically.  If the value starts with `/'
+then it is taken as a file name to use as the data base file, instead
+of `/etc/termcap' which is the standard data base.  If the value does
+not start with `/' then it is itself used as the terminal description,
+provided that the terminal type TERMTYPE is among the types it claims
+to apply to.  *Note Data Base::, for information on the format of a
+terminal description.
+
+\1f
+File: termcap.info,  Node: Interrogate,  Next: Initialize,  Prev: Find,  Up: Library
+
+Interrogating the Terminal Description
+======================================
+
+   Each piece of information recorded in a terminal description is
+called a "capability".  Each defined terminal capability has a
+two-letter code name and a specific meaning.  For example, the number
+of columns is named `co'.  *Note Capabilities::, for definitions of all
+the standard capability names.
+
+   Once you have found the proper terminal description with `tgetent'
+(*note Find::.), your application program must "interrogate" it for
+various terminal capabilities.  You must specify the two-letter code of
+the capability whose value you seek.
+
+   Capability values can be numeric, boolean (capability is either
+present or absent) or strings.  Any particular capability always has
+the same value type; for example, `co' always has a numeric value,
+while `am' (automatic wrap at margin) is always a flag, and `cm'
+(cursor motion command) always has a string value.  The documentation
+of each capability says which type of value it has.
+
+   There are three functions to use to get the value of a capability,
+depending on the type of value the capability has.  Here are their
+declarations in ANSI C:
+
+     int tgetnum (char *NAME);
+     int tgetflag (char *NAME);
+     char *tgetstr (char *NAME, char **AREA);
+
+`tgetnum'
+     Use `tgetnum' to get a capability value that is numeric.  The
+     argument NAME is the two-letter code name of the capability.  If
+     the capability is present, `tgetnum' returns the numeric value
+     (which is nonnegative).  If the capability is not mentioned in the
+     terminal description, `tgetnum' returns -1.
+
+`tgetflag'
+     Use `tgetflag' to get a boolean value.  If the capability NAME is
+     present in the terminal description, `tgetflag' returns 1;
+     otherwise, it returns 0.
+
+`tgetstr'
+     Use `tgetstr' to get a string value.  It returns a pointer to a
+     string which is the capability value, or a null pointer if the
+     capability is not present in the terminal description.
+
+     There are two ways `tgetstr' can find space to store the string
+     value:
+
+        * You can ask `tgetstr' to allocate the space.  Pass a null
+          pointer for the argument AREA, and `tgetstr' will use
+          `malloc' to allocate storage big enough for the value.
+          Termcap will never free this storage or refer to it again; you
+          should free it when you are finished with it.
+
+          This method is more robust, since there is no need to guess
+          how much space is needed.  But it is supported only by the GNU
+          termcap library.
+
+        * You can provide the space.  Provide for the argument AREA the
+          address of a pointer variable of type `char *'.  Before
+          calling `tgetstr', initialize the variable to point at
+          available space.  Then `tgetstr' will store the string value
+          in that space and will increment the pointer variable to
+          point after the space that has been used.  You can use the
+          same pointer variable for many calls to `tgetstr'.
+
+          There is no way to determine how much space is needed for a
+          single string, and no way for you to prevent or handle
+          overflow of the area you have provided.  However, you can be
+          sure that the total size of all the string values you will
+          obtain from the terminal description is no greater than the
+          size of the description (unless you get the same capability
+          twice).  You can determine that size with `strlen' on the
+          buffer you provided to `tgetent'.  See below for an example.
+
+          Providing the space yourself is the only method supported by
+          the Unix version of termcap.
+
+   Note that you do not have to specify a terminal type or terminal
+description for the interrogation functions.  They automatically use the
+description found by the most recent call to `tgetent'.
+
+   Here is an example of interrogating a terminal description for
+various capabilities, with conditionals to select between the Unix and
+GNU methods of providing buffer space.
+
+     char *tgetstr ();
+     
+     char *cl_string, *cm_string;
+     int height;
+     int width;
+     int auto_wrap;
+     
+     char PC;   /* For tputs.  */
+     char *BC;  /* For tgoto.  */
+     char *UP;
+     
+     interrogate_terminal ()
+     {
+     #ifdef UNIX
+       /* Here we assume that an explicit term_buffer
+          was provided to tgetent.  */
+       char *buffer
+         = (char *) malloc (strlen (term_buffer));
+     #define BUFFADDR &buffer
+     #else
+     #define BUFFADDR 0
+     #endif
+     
+       char *temp;
+     
+       /* Extract information we will use.  */
+       cl_string = tgetstr ("cl", BUFFADDR);
+       cm_string = tgetstr ("cm", BUFFADDR);
+       auto_wrap = tgetflag ("am");
+       height = tgetnum ("li");
+       width = tgetnum ("co");
+     
+       /* Extract information that termcap functions use.  */
+       temp = tgetstr ("pc", BUFFADDR);
+       PC = temp ? *temp : 0;
+       BC = tgetstr ("le", BUFFADDR);
+       UP = tgetstr ("up", BUFFADDR);
+     }
+
+*Note Padding::, for information on the variable `PC'.  *Note Using
+Parameters::, for information on `UP' and `BC'.
+
+\1f
+File: termcap.info,  Node: Initialize,  Next: Padding,  Prev: Interrogate,  Up: Library
+
+Initialization for Use of Termcap
+=================================
+
+   Before starting to output commands to a terminal using termcap, an
+application program should do two things:
+
+   * Initialize various global variables which termcap library output
+     functions refer to.  These include `PC' and `ospeed' for padding
+     (*note Output Padding::.) and `UP' and `BC' for cursor motion
+     (*note tgoto::.).
+
+   * Tell the kernel to turn off alteration and padding of
+     horizontal-tab characters sent to the terminal.
+
+   To turn off output processing in Berkeley Unix you would use `ioctl'
+with code `TIOCLSET' to set the bit named `LLITOUT', and clear the bits
+`ANYDELAY' using `TIOCSETN'.  In POSIX or System V, you must clear the
+bit named `OPOST'.  Refer to the system documentation for details.
+
+   If you do not set the terminal flags properly, some older terminals
+will not work.  This is because their commands may contain the
+characters that normally signify newline, carriage return and
+horizontal tab--characters which the kernel thinks it ought to modify
+before output.
+
+   When you change the kernel's terminal flags, you must arrange to
+restore them to their normal state when your program exits.  This
+implies that the program must catch fatal signals such as `SIGQUIT' and
+`SIGINT' and restore the old terminal flags before actually terminating.
+
+   Modern terminals' commands do not use these special characters, so
+if you do not care about problems with old terminals, you can leave the
+kernel's terminal flags unaltered.
+
+\1f
+File: termcap.info,  Node: Padding,  Next: Parameters,  Prev: Initialize,  Up: Library
+
+Padding
+=======
+
+   "Padding" means outputting null characters following a terminal
+display command that takes a long time to execute.  The terminal
+description says which commands require padding and how much; the
+function `tputs', described below, outputs a terminal command while
+extracting from it the padding information, and then outputs the
+padding that is necessary.
+
+* Menu:
+
+* Why Pad::     Explanation of padding.
+* Not Enough::  When there is not enough padding.
+* Describe Padding::  The data base says how much padding a terminal needs.
+* Output Padding::  Using `tputs' to output the needed padding.
+
+\1f
+File: termcap.info,  Node: Why Pad,  Next: Not Enough,  Up: Padding
+
+Why Pad, and How
+----------------
+
+   Most types of terminal have commands that take longer to execute
+than they do to send over a high-speed line.  For example, clearing the
+screen may take 20msec once the entire command is received.  During
+that time, on a 9600 bps line, the terminal could receive about 20
+additional output characters while still busy clearing the screen.
+Every terminal has a certain amount of buffering capacity to remember
+output characters that cannot be processed yet, but too many slow
+commands in a row can cause the buffer to fill up.  Then any additional
+output that cannot be processed immediately will be lost.
+
+   To avoid this problem, we normally follow each display command with
+enough useless charaters (usually null characters) to fill up the time
+that the display command needs to execute.  This does the job if the
+terminal throws away null characters without using up space in the
+buffer (which most terminals do).  If enough padding is used, no output
+can ever be lost.  The right amount of padding avoids loss of output
+without slowing down operation, since the time used to transmit padding
+is time that nothing else could be done.
+
+   The number of padding characters needed for an operation depends on
+the line speed.  In fact, it is proportional to the line speed.  A 9600
+baud line transmits about one character per msec, so the clear screen
+command in the example above would need about 20 characters of padding.
+At 1200 baud, however, only about 3 characters of padding are needed
+to fill up 20msec.
+
+\1f
+File: termcap.info,  Node: Not Enough,  Next: Describe Padding,  Prev: Why Pad,  Up: Padding
+
+When There Is Not Enough Padding
+--------------------------------
+
+   There are several common manifestations of insufficient padding.
+
+   * Emacs displays `I-search: ^Q-' at the bottom of the screen.
+
+     This means that the terminal thought its buffer was getting full of
+     display commands, so it tried to tell the computer to stop sending
+     any.
+
+   * The screen is garbled intermittently, or the details of garbling
+     vary when you repeat the action.  (A garbled screen could be due
+     to a command which is simply incorrect, or to user option in the
+     terminal which doesn't match the assumptions of the terminal
+     description, but this usually leads to reproducible failure.)
+
+     This means that the buffer did get full, and some commands were
+     lost.  Many changeable factors can change which ones are lost.
+
+   * Screen is garbled at high output speeds but not at low speeds.
+     Padding problems nearly always go away at low speeds, usually even
+     at 1200 baud.
+
+     This means that a high enough speed permits commands to arrive
+     faster than they can be executed.
+
+   Although any obscure command on an obscure terminal might lack
+padding, in practice problems arise most often from the clearing
+commands `cl' and `cd' (*note Clearing::.), the scrolling commands `sf'
+and `sr' (*note Scrolling::.), and the line insert/delete commands `al'
+and `dl' (*note Insdel Line::.).
+
+   Occasionally the terminal description fails to define `sf' and some
+programs will use `do' instead, so you may get a problem with `do'.  If
+so, first define `sf' just like `do', then add some padding to `sf'.
+
+   The best strategy is to add a lot of padding at first, perhaps 200
+msec.  This is much more than enough; in fact, it should cause a
+visible slowdown.  (If you don't see a slowdown, the change has not
+taken effect; *note Changing::..)  If this makes the problem go away,
+you have found the right place to add padding; now reduce the amount
+until the problem comes back, then increase it again.  If the problem
+remains, either it is in some other capability or it is not a matter of
+padding at all.
+
+   Keep in mind that on many terminals the correct padding for
+insert/delete line or for scrolling is cursor-position dependent.  If
+you get problems from scrolling a large region of the screen but not
+from scrolling a small part (just a few lines moving), it may mean that
+fixed padding should be replaced with position-dependent padding.
+
+\1f
+File: termcap.info,  Node: Describe Padding,  Next: Output Padding,  Prev: Not Enough,  Up: Padding
+
+Specifying Padding in a Terminal Description
+--------------------------------------------
+
+   In the terminal description, the amount of padding required by each
+display command is recorded as a sequence of digits at the front of the
+command.  These digits specify the padding time in milliseconds (msec).
+They can be followed optionally by a decimal point and one more digit,
+which is a number of tenths of msec.
+
+   Sometimes the padding needed by a command depends on the cursor
+position.  For example, the time taken by an "insert line" command is
+usually proportional to the number of lines that need to be moved down
+or cleared.  An asterisk (`*') following the padding time says that the
+time should be multiplied by the number of screen lines affected by the
+command.
+
+     :al=1.3*\E[L:
+
+is used to describe the "insert line" command for a certain terminal.
+The padding required is 1.3 msec per line affected.  The command itself
+is `ESC [ L'.
+
+   The padding time specified in this way tells `tputs' how many pad
+characters to output.  *Note Output Padding::.
+
+   Two special capability values affect padding for all commands.
+These are the `pc' and `pb'.  The variable `pc' specifies the character
+to pad with, and `pb' the speed below which no padding is needed.  The
+defaults for these variables, a null character and 0, are correct for
+most terminals.  *Note Pad Specs::.
+
+\1f
+File: termcap.info,  Node: Output Padding,  Prev: Describe Padding,  Up: Padding
+
+Performing Padding with `tputs'
+-------------------------------
+
+   Use the termcap function `tputs' to output a string containing an
+optional padding spec of the form described above (*note Describe
+Padding::.).  The function `tputs' strips off and decodes the padding
+spec, outputs the rest of the string, and then outputs the appropriate
+padding.  Here is its declaration in ANSI C:
+
+     char PC;
+     short ospeed;
+     
+     int tputs (char *STRING, int NLINES, int (*OUTFUN) ());
+
+   Here STRING is the string (including padding spec) to be output;
+NLINES is the number of lines affected by the operation, which is used
+to multiply the amount of padding if the padding spec ends with a `*'.
+Finally, OUTFUN is a function (such as `fputchar') that is called to
+output each character.  When actually called, OUTFUN should expect one
+argument, a character.
+
+   The operation of `tputs' is controlled by two global variables,
+`ospeed' and `PC'.  The value of `ospeed' is supposed to be the
+terminal output speed, encoded as in the `ioctl' system call which gets
+the speed information.  This is needed to compute the number of padding
+characters.  The value of `PC' is the character used for padding.
+
+   You are responsible for storing suitable values into these variables
+before using `tputs'.  The value stored into the `PC' variable should be
+taken from the `pc' capability in the terminal description (*note Pad
+Specs::.).  Store zero in `PC' if there is no `pc' capability.
+
+   The argument NLINES requires some thought.  Normally, it should be
+the number of lines whose contents will be cleared or moved by the
+command.  For cursor motion commands, or commands that do editing
+within one line, use the value 1.  For most commands that affect
+multiple lines, such as `al' (insert a line) and `cd' (clear from the
+cursor to the end of the screen), NLINES should be the screen height
+minus the current vertical position (origin 0).  For multiple insert
+and scroll commands such as `AL' (insert multiple lines), that same
+value for NLINES is correct; the number of lines being inserted is not
+correct.
+
+   If a "scroll window" feature is used to reduce the number of lines
+affected by a command, the value of NLINES should take this into
+account.  This is because the delay time required depends on how much
+work the terminal has to do, and the scroll window feature reduces the
+work.  *Note Scrolling::.
+
+   Commands such as `ic' and `dc' (insert or delete characters) are
+problematical because the padding needed by these commands is
+proportional to the number of characters affected, which is the number
+of columns from the cursor to the end of the line.  It would be nice to
+have a way to specify such a dependence, and there is no need for
+dependence on vertical position in these commands, so it is an obvious
+idea to say that for these commands NLINES should really be the number
+of columns affected.  However, the definition of termcap clearly says
+that NLINES is always the number of lines affected, even in this case,
+where it is always 1.  It is not easy to change this rule now, because
+too many programs and terminal descriptions have been written to follow
+it.
+
+   Because NLINES is always 1 for the `ic' and `dc' strings, there is
+no reason for them to use `*', but some of them do.  These should be
+corrected by deleting the `*'.  If, some day, such entries have
+disappeared, it may be possible to change to a more useful convention
+for the NLINES argument for these operations without breaking any
+programs.
+
+\1f
+File: termcap.info,  Node: Parameters,  Prev: Padding,  Up: Library
+
+Filling In Parameters
+=====================
+
+   Some terminal control strings require numeric "parameters".  For
+example, when you move the cursor, you need to say what horizontal and
+vertical positions to move it to.  The value of the terminal's `cm'
+capability, which says how to move the cursor, cannot simply be a
+string of characters; it must say how to express the cursor position
+numbers and where to put them within the command.
+
+   The specifications of termcap include conventions as to which
+string-valued capabilities require parameters, how many parameters, and
+what the parameters mean; for example, it defines the `cm' string to
+take two parameters, the vertical and horizontal positions, with 0,0
+being the upper left corner.  These conventions are described where the
+individual commands are documented.
+
+   Termcap also defines a language used within the capability
+definition for specifying how and where to encode the parameters for
+output.  This language uses character sequences starting with `%'.
+(This is the same idea as `printf', but the details are different.)
+The language for parameter encoding is described in this section.
+
+   A program that is doing display output calls the functions `tparam'
+or `tgoto' to encode parameters according to the specifications.  These
+functions produce a string containing the actual commands to be output
+(as well a padding spec which must be processed with `tputs'; *note
+Padding::.).
+
+* Menu:
+
+* Encode Parameters::  The language for encoding parameters.
+* Using Parameters::  Outputting a string command with parameters.
+
+\1f
+File: termcap.info,  Node: Encode Parameters,  Next: Using Parameters,  Up: Parameters
+
+Describing the Encoding
+-----------------------
+
+   A terminal command string that requires parameters contains special
+character sequences starting with `%' to say how to encode the
+parameters.  These sequences control the actions of `tparam' and
+`tgoto'.
+
+   The parameters values passed to `tparam' or `tgoto' are considered
+to form a vector.  A pointer into this vector determines the next
+parameter to be processed.  Some of the `%'-sequences encode one
+parameter and advance the pointer to the next parameter.  Other
+`%'-sequences alter the pointer or alter the parameter values without
+generating output.
+
+   For example, the `cm' string for a standard ANSI terminal is written
+as `\E[%i%d;%dH'.  (`\E' stands for ESC.)  `cm' by convention always
+requires two parameters, the vertical and horizontal goal positions, so
+this string specifies the encoding of two parameters.  Here `%i'
+increments the two values supplied, and each `%d' encodes one of the
+values in decimal.  If the cursor position values 20,58 are encoded
+with this string, the result is `\E[21;59H'.
+
+   First, here are the `%'-sequences that generate output.  Except for
+`%%', each of them encodes one parameter and advances the pointer to
+the following parameter.
+
+`%%'
+     Output a single `%'.  This is the only way to represent a literal
+     `%' in a terminal command with parameters.  `%%' does not use up a
+     parameter.
+
+`%d'
+     As in `printf', output the next parameter in decimal.
+
+`%2'
+     Like `%02d' in `printf': output the next parameter in decimal, and
+     always use at least two digits.
+
+`%3'
+     Like `%03d' in `printf': output the next parameter in decimal, and
+     always use at least three digits.  Note that `%4' and so on are
+     *not* defined.
+
+`%.'
+     Output the next parameter as a single character whose ASCII code is
+     the parameter value.  Like `%c' in `printf'.
+
+`%+CHAR'
+     Add the next parameter to the character CHAR, and output the
+     resulting character.  For example, `%+ ' represents 0 as a space,
+     1 as `!', etc.
+
+   The following `%'-sequences specify alteration of the parameters
+(their values, or their order) rather than encoding a parameter for
+output.  They generate no output; they are used only for their side
+effects on the parameters.  Also, they do not advance the "next
+parameter" pointer except as explicitly stated.  Only `%i', `%r' and
+`%>' are defined in standard Unix termcap.  The others are GNU
+extensions.
+
+`%i'
+     Increment the next two parameters.  This is used for terminals that
+     expect cursor positions in origin 1.  For example, `%i%d,%d' would
+     output two parameters with `1' for 0, `2' for 1, etc.
+
+`%r'
+     Interchange the next two parameters.  This is used for terminals
+     whose cursor positioning command expects the horizontal position
+     first.
+
+`%s'
+     Skip the next parameter.  Do not output anything.
+
+`%b'
+     Back up one parameter.  The last parameter used will become once
+     again the next parameter to be output, and the next output command
+     will use it.  Using `%b' more than once, you can back up any
+     number of parameters, and you can refer to each parameter any
+     number of times.
+
+`%>C1C2'
+     Conditionally increment the next parameter.  Here C1 and C2 are
+     characters which stand for their ASCII codes as numbers.  If the
+     next parameter is greater than the ASCII code of C1, the ASCII
+     code of C2 is added to it.
+
+`%a OP TYPE POS'
+     Perform arithmetic on the next parameter, do not use it up, and do
+     not output anything.  Here OP specifies the arithmetic operation,
+     while TYPE and POS together specify the other operand.
+
+     Spaces are used above to separate the operands for clarity; the
+     spaces don't appear in the data base, where this sequence is
+     exactly five characters long.
+
+     The character OP says what kind of arithmetic operation to
+     perform.  It can be any of these characters:
+
+    `='
+          assign a value to the next parameter, ignoring its old value.
+          The new value comes from the other operand.
+
+    `+'
+          add the other operand to the next parameter.
+
+    `-'
+          subtract the other operand from the next parameter.
+
+    `*'
+          multiply the next parameter by the other operand.
+
+    `/'
+          divide the next parameter by the other operand.
+
+     The "other operand" may be another parameter's value or a constant;
+     the character TYPE says which.  It can be:
+
+    `p'
+          Use another parameter.  The character POS says which
+          parameter to use.  Subtract 64 from its ASCII code to get the
+          position of the desired parameter relative to this one.  Thus,
+          the character `A' as POS means the parameter after the next
+          one; the character `?' means the parameter before the next
+          one.
+
+    `c'
+          Use a constant value.  The character POS specifies the value
+          of the constant.  The 0200 bit is cleared out, so that 0200
+          can be used to represent zero.
+
+   The following `%'-sequences are special purpose hacks to compensate
+for the weird designs of obscure terminals.  They modify the next
+parameter or the next two parameters but do not generate output and do
+not use up any parameters.  `%m' is a GNU extension; the others are
+defined in standard Unix termcap.
+
+`%n'
+     Exclusive-or the next parameter with 0140, and likewise the
+     parameter after next.
+
+`%m'
+     Complement all the bits of the next parameter and the parameter
+     after next.
+
+`%B'
+     Encode the next parameter in BCD.  It alters the value of the
+     parameter by adding six times the quotient of the parameter by ten.
+     Here is a C statement that shows how the new value is computed:
+
+          PARM = (PARM / 10) * 16 + PARM % 10;
+
+`%D'
+     Transform the next parameter as needed by Delta Data terminals.
+     This involves subtracting twice the remainder of the parameter by
+     16.
+
+          PARM -= 2 * (PARM % 16);
+
+\1f
+File: termcap.info,  Node: Using Parameters,  Prev: Encode Parameters,  Up: Parameters
+
+Sending Display Commands with Parameters
+----------------------------------------
+
+   The termcap library functions `tparam' and `tgoto' serve as the
+analog of `printf' for terminal string parameters.  The newer function
+`tparam' is a GNU extension, more general but missing from Unix
+termcap.  The original parameter-encoding function is `tgoto', which is
+preferable for cursor motion.
+
+* Menu:
+
+* tparam::      The general case, for GNU termcap only.
+* tgoto::       The special case of cursor motion.
+
+\1f
+File: termcap.info,  Node: tparam,  Next: tgoto,  Up: Using Parameters
+
+`tparam'
+--------
+
+   The function `tparam' can encode display commands with any number of
+parameters and allows you to specify the buffer space.  It is the
+preferred function for encoding parameters for all but the `cm'
+capability.  Its ANSI C declaration is as follows:
+
+     char *tparam (char *CTLSTRING, char *BUFFER, int SIZE, int PARM1,...)
+
+   The arguments are a control string CTLSTRING (the value of a terminal
+capability, presumably), an output buffer BUFFER and SIZE, and any
+number of integer parameters to be encoded.  The effect of `tparam' is
+to copy the control string into the buffer, encoding parameters
+according to the `%' sequences in the control string.
+
+   You describe the output buffer by its address, BUFFER, and its size
+in bytes, SIZE.  If the buffer is not big enough for the data to be
+stored in it, `tparam' calls `malloc' to get a larger buffer.  In
+either case, `tparam' returns the address of the buffer it ultimately
+uses.  If the value equals BUFFER, your original buffer was used.
+Otherwise, a new buffer was allocated, and you must free it after you
+are done with printing the results.  If you pass zero for SIZE and
+BUFFER, `tparam' always allocates the space with `malloc'.
+
+   All capabilities that require parameters also have the ability to
+specify padding, so you should use `tputs' to output the string
+produced by `tparam'.  *Note Padding::.  Here is an example.
+
+     {
+     char *buf;
+     char buffer[40];
+     
+     buf = tparam (command, buffer, 40, parm);
+     tputs (buf, 1, fputchar);
+     if (buf != buffer)
+     free (buf);
+     }
+
+   If a parameter whose value is zero is encoded with `%.'-style
+encoding, the result is a null character, which will confuse `tputs'.
+This would be a serious problem, but luckily `%.' encoding is used only
+by a few old models of terminal, and only for the `cm' capability.  To
+solve the problem, use `tgoto' rather than `tparam' to encode the `cm'
+capability.
+
+\1f
+File: termcap.info,  Node: tgoto,  Prev: tparam,  Up: Using Parameters
+
+`tgoto'
+-------
+
+   The special case of cursor motion is handled by `tgoto'.  There are
+two reasons why you might choose to use `tgoto':
+
+   * For Unix compatibility, because Unix termcap does not have
+     `tparam'.
+
+   * For the `cm' capability, since `tgoto' has a special feature to
+     avoid problems with null characters, tabs and newlines on certain
+     old terminal types that use `%.' encoding for that capability.
+
+   Here is how `tgoto' might be declared in ANSI C:
+
+     char *tgoto (char *CSTRING, int HPOS, int VPOS)
+
+   There are three arguments, the terminal description's `cm' string and
+the two cursor position numbers; `tgoto' computes the parametrized
+string in an internal static buffer and returns the address of that
+buffer.  The next time you use `tgoto' the same buffer will be reused.
+
+   Parameters encoded with `%.' encoding can generate null characters,
+tabs or newlines.  These might cause trouble: the null character because
+`tputs' would think that was the end of the string, the tab because the
+kernel or other software might expand it into spaces, and the newline
+becaue the kernel might add a carriage-return, or padding characters
+normally used for a newline.  To prevent such problems, `tgoto' is
+careful to avoid these characters.  Here is how this works: if the
+target cursor position value is such as to cause a problem (that is to
+say, zero, nine or ten), `tgoto' increments it by one, then compensates
+by appending a string to move the cursor back or up one position.
+
+   The compensation strings to use for moving back or up are found in
+global variables named `BC' and `UP'.  These are actual external C
+variables with upper case names; they are declared `char *'.  It is up
+to you to store suitable values in them, normally obtained from the
+`le' and `up' terminal capabilities in the terminal description with
+`tgetstr'.  Alternatively, if these two variables are both zero, the
+feature of avoiding nulls, tabs and newlines is turned off.
+
+   It is safe to use `tgoto' for commands other than `cm' only if you
+have stored zero in `BC' and `UP'.
+
+   Note that `tgoto' reverses the order of its operands: the horizontal
+position comes before the vertical position in the arguments to
+`tgoto', even though the vertical position comes before the horizontal
+in the parameters of the `cm' string.  If you use `tgoto' with a
+command such as `AL' that takes one parameter, you must pass the
+parameter to `tgoto' as the "vertical position".
+
+\1f
+File: termcap.info,  Node: Data Base,  Next: Capabilities,  Prev: Library,  Up: Top
+
+The Format of the Data Base
+***************************
+
+   The termcap data base of terminal descriptions is stored in the file
+`/etc/termcap'.  It contains terminal descriptions, blank lines, and
+comments.
+
+   A terminal description starts with one or more names for the
+terminal type.  The information in the description is a series of
+"capability names" and values.  The capability names have standard
+meanings (*note Capabilities::.) and their values describe the terminal.
+
+* Menu:
+
+* Format::      Overall format of a terminal description.
+* Capability Format::  Format of capabilities within a description.
+* Naming::      Naming conventions for terminal types.
+* Inheriting::  Inheriting part of a description from
+a related terminal type.
+* Changing::    When changes in the data base take effect.
+
+\1f
+File: termcap.info,  Node: Format,  Next: Capability Format,  Up: Data Base
+
+Terminal Description Format
+===========================
+
+   Aside from comments (lines starting with `#', which are ignored),
+each nonblank line in the termcap data base is a terminal description.
+A terminal description is nominally a single line, but it can be split
+into multiple lines by inserting the two characters `\ newline'.  This
+sequence is ignored wherever it appears in a description.
+
+   The preferred way to split the description is between capabilities:
+insert the four characters `: \ newline tab' immediately before any
+colon.  This allows each sub-line to start with some indentation.  This
+works because, after the `\ newline' are ignored, the result is `: tab
+:'; the first colon ends the preceding capability and the second colon
+starts the next capability.  If you split with `\ newline' alone, you
+may not add any indentation after them.
+
+   Here is a real example of a terminal description:
+
+     dw|vt52|DEC vt52:\
+             :cr=^M:do=^J:nl=^J:bl=^G:\
+             :le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:\
+             :cm=\EY%+ %+ :co#80:li#24:\
+             :nd=\EC:ta=^I:pt:sr=\EI:up=\EA:\
+             :ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:
+
+   Each terminal description begins with several names for the terminal
+type.  The names are separated by `|' characters, and a colon ends the
+last name.  The first name should be two characters long; it exists
+only for the sake of very old Unix systems and is never used in modern
+systems.  The last name should be a fully verbose name such as "DEC
+vt52" or "Ann Arbor Ambassador with 48 lines".  The other names should
+include whatever the user ought to be able to specify to get this
+terminal type, such as `vt52' or `aaa-48'.  *Note Naming::, for
+information on how to choose terminal type names.
+
+   After the terminal type names come the terminal capabilities,
+separated by colons and with a colon after the last one.  Each
+capability has a two-letter name, such as `cm' for "cursor motion
+string" or `li' for "number of display lines".
+
+\1f
+File: termcap.info,  Node: Capability Format,  Next: Naming,  Prev: Format,  Up: Data Base
+
+Writing the Capabilities
+========================
+
+   There are three kinds of capabilities: flags, numbers, and strings.
+Each kind has its own way of being written in the description.  Each
+defined capability has by convention a particular kind of value; for
+example, `li' always has a numeric value and `cm' always a string value.
+
+   A flag capability is thought of as having a boolean value: the value
+is true if the capability is present, false if not.  When the
+capability is present, just write its name between two colons.
+
+   A numeric capability has a value which is a nonnegative number.
+Write the capability name, a `#', and the number, between two colons.
+For example, `...:li#48:...' is how you specify the `li' capability for
+48 lines.
+
+   A string-valued capability has a value which is a sequence of
+characters.  Usually these are the characters used to perform some
+display operation.  Write the capability name, a `=', and the
+characters of the value, between two colons.  For example,
+`...:cm=\E[%i%d;%dH:...' is how the cursor motion command for a
+standard ANSI terminal would be specified.
+
+   Special characters in the string value can be expressed using
+`\'-escape sequences as in C; in addition, `\E' stands for ESC.  `^' is
+also a kind of escape character; `^' followed by CHAR stands for the
+control-equivalent of CHAR.  Thus, `^a' stands for the character
+control-a, just like `\001'.  `\' and `^' themselves can be represented
+as `\\' and `\^'.
+
+   To include a colon in the string, you must write `\072'.  You might
+ask, "Why can't `\:' be used to represent a colon?"  The reason is that
+the interrogation functions do not count slashes while looking for a
+capability.  Even if `:ce=ab\:cd:' were interpreted as giving the `ce'
+capability the value `ab:cd', it would also appear to define `cd' as a
+flag.
+
+   The string value will often contain digits at the front to specify
+padding (*note Padding::.) and/or `%'-sequences within to specify how
+to encode parameters (*note Parameters::.).  Although these things are
+not to be output literally to the terminal, they are considered part of
+the value of the capability.  They are special only when the string
+value is processed by `tputs', `tparam' or `tgoto'.  By contrast, `\'
+and `^' are considered part of the syntax for specifying the characters
+in the string.
+
+   Let's look at the VT52 example again:
+
+     dw|vt52|DEC vt52:\
+             :cr=^M:do=^J:nl=^J:bl=^G:\
+             :le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:\
+             :cm=\EY%+ %+ :co#80:li#24:\
+             :nd=\EC:ta=^I:pt:sr=\EI:up=\EA:\
+             :ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:
+
+   Here we see the numeric-valued capabilities `co' and `li', the flags
+`bs' and `pt', and many string-valued capabilities.  Most of the
+strings start with ESC represented as `\E'.  The rest contain control
+characters represented using `^'.  The meanings of the individual
+capabilities are defined elsewhere (*note Capabilities::.).
+
diff --git a/lib/termcap/grot/termcap.info-2 b/lib/termcap/grot/termcap.info-2
new file mode 100644 (file)
index 0000000..7142dc8
--- /dev/null
@@ -0,0 +1,969 @@
+This is Info file /home/gd/gnu/termcap/termcap.info, produced by
+Makeinfo-1.52 from the input file /home/gd/gnu/termcap/termcap.texi.
+
+   This file documents the termcap library of the GNU system.
+
+   Copyright (C) 1988 Free Software Foundation, Inc.
+
+   Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+   Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+   Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+\1f
+File: termcap.info,  Node: Naming,  Next: Inheriting,  Prev: Capability Format,  Up: Data Base
+
+Terminal Type Name Conventions
+==============================
+
+   There are conventions for choosing names of terminal types.  For one
+thing, all letters should be in lower case.  The terminal type for a
+terminal in its most usual or most fundamental mode of operation should
+not have a hyphen in it.
+
+   If the same terminal has other modes of operation which require
+different terminal descriptions, these variant descriptions are given
+names made by adding suffixes with hyphens.  Such alternate descriptions
+are used for two reasons:
+
+   * When the terminal has a switch that changes its behavior.  Since
+     the computer cannot tell how the switch is set, the user must tell
+     the computer by choosing the appropriate terminal type name.
+
+     For example, the VT-100 has a setup flag that controls whether the
+     cursor wraps at the right margin.  If this flag is set to "wrap",
+     you must use the terminal type `vt100-am'.  Otherwise you must use
+     `vt100-nam'.  Plain `vt100' is defined as a synonym for either
+     `vt100-am' or `vt100-nam' depending on the preferences of the
+     local site.
+
+     The standard suffix `-am' stands for "automatic margins".
+
+   * To give the user a choice in how to use the terminal.  This is done
+     when the terminal has a switch that the computer normally controls.
+
+     For example, the Ann Arbor Ambassador can be configured with many
+     screen sizes ranging from 20 to 60 lines.  Fewer lines make bigger
+     characters but more lines let you see more of what you are editing.
+     As a result, users have different preferences.  Therefore, termcap
+     provides terminal types for many screen sizes.  If you choose type
+     `aaa-30', the terminal will be configured to use 30 lines; if you
+     choose `aaa-48', 48 lines will be used, and so on.
+
+   Here is a list of standard suffixes and their conventional meanings:
+
+`-w'
+     Short for "wide".  This is a mode that gives the terminal more
+     columns than usual.  This is normally a user option.
+
+`-am'
+     "Automatic margins".  This is an alternate description for use when
+     the terminal's margin-wrap switch is on; it contains the `am'
+     flag.  The implication is that normally the switch is off and the
+     usual description for the terminal says that the switch is off.
+
+`-nam'
+     "No automatic margins".  The opposite of `-am', this names an
+     alternative description which lacks the `am' flag.  This implies
+     that the terminal is normally operated with the margin-wrap switch
+     turned on, and the normal description of the terminal says so.
+
+`-na'
+     "No arrows".  This terminal description initializes the terminal to
+     keep its arrow keys in local mode.  This is a user option.
+
+`-rv'
+     "Reverse video".  This terminal description causes text output for
+     normal video to appear as reverse, and text output for reverse
+     video to come out as normal.  Often this description differs from
+     the usual one by interchanging the two strings which turn reverse
+     video on and off.
+
+     This is a user option; you can choose either the "reverse video"
+     variant terminal type or the normal terminal type, and termcap will
+     obey.
+
+`-s'
+     "Status".  Says to enable use of a status line which ordinary
+     output does not touch (*note Status Line::.).
+
+     Some terminals have a special line that is used only as a status
+     line.  For these terminals, there is no need for an `-s' variant;
+     the status line commands should be defined by default.  On other
+     terminals, enabling a status line means removing one screen line
+     from ordinary use and reducing the effective screen height.  For
+     these terminals, the user can choose the `-s' variant type to
+     request use of a status line.
+
+`-NLINES'
+     Says to operate with NLINES lines on the screen, for terminals
+     such as the Ambassador which provide this as an option.  Normally
+     this is a user option; by choosing the terminal type, you control
+     how many lines termcap will use.
+
+`-NPAGESp'
+     Says that the terminal has NPAGES pages worth of screen memory,
+     for terminals where this is a hardware option.
+
+`-unk'
+     Says that description is not for direct use, but only for
+     reference in `tc' capabilities.  Such a description is a kind of
+     subroutine, because it describes the common characteristics of
+     several variant descriptions that would use other suffixes in
+     place of `-unk'.
+
+\1f
+File: termcap.info,  Node: Inheriting,  Next: Changing,  Prev: Naming,  Up: Data Base
+
+Inheriting from Related Descriptions
+====================================
+
+   When two terminal descriptions are similar, their identical parts do
+not need to be given twice.  Instead, one of the two can be defined in
+terms of the other, using the `tc' capability.  We say that one
+description "refers to" the other, or "inherits from" the other.
+
+   The `tc' capability must be the last one in the terminal description,
+and its value is a string which is the name of another terminal type
+which is referred to.  For example,
+
+     N9|aaa|ambassador|aaa-30|ann arbor ambassador/30 lines:\
+             :ti=\E[2J\E[30;0;0;30p:\
+             :te=\E[60;0;0;30p\E[30;1H\E[J:\
+             :li#30:tc=aaa-unk:
+
+defines the terminal type `aaa-30' (also known as plain `aaa') in terms
+of `aaa-unk', which defines everything about the Ambassador that is
+independent of screen height.  The types `aaa-36', `aaa-48' and so on
+for other screen heights are likewise defined to inherit from `aaa-unk'.
+
+   The capabilities overridden by `aaa-30' include `li', which says how
+many lines there are, and `ti' and `te', which configure the terminal
+to use that many lines.
+
+   The effective terminal description for type `aaa' consists of the
+text shown above followed by the text of the description of `aaa-unk'.
+The `tc' capability is handled automatically by `tgetent', which finds
+the description thus referenced and combines the two descriptions
+(*note Find::.).  Therefore, only the implementor of the terminal
+descriptions needs to think about using `tc'.  Users and application
+programmers do not need to be concerned with it.
+
+   Since the reference terminal description is used last, capabilities
+specified in the referring description override any specifications of
+the same capabilities in the reference description.
+
+   The referring description can cancel out a capability without
+specifying any new value for it by means of a special trick.  Write the
+capability in the referring description, with the character `@' after
+the capability name, as follows:
+
+     NZ|aaa-30-nam|ann arbor ambassador/30 lines/no automatic-margins:\
+             :am@:tc=aaa-30:
+
+\1f
+File: termcap.info,  Node: Changing,  Prev: Inheriting,  Up: Data Base
+
+When Changes in the Data Base Take Effect
+=========================================
+
+   Each application program must read the terminal description from the
+data base, so a change in the data base is effective for all jobs
+started after the change is made.
+
+   The change will usually have no effect on a job that have been in
+existence since before the change. The program probably read the
+terminal description once, when it was started, and is continuing to
+use what it read then.  If the program does not have a feature for
+reexamining the data base, then you will need to run it again (probably
+killing the old job).
+
+   If the description in use is coming from the `TERMCAP' environment
+variable, then the data base file is effectively overridden, and
+changes in it will have no effect until you change the `TERMCAP'
+variable as well.  For example, some users' `.login' files
+automatically copy the terminal description into `TERMCAP' to speed
+startup of applications.  If you have done this, you will need to
+change the `TERMCAP' variable to make the changed data base take effect.
+
+\1f
+File: termcap.info,  Node: Capabilities,  Next: Summary,  Prev: Data Base,  Up: Top
+
+Definitions of the Terminal Capabilities
+****************************************
+
+   This section is divided into many subsections, each for one aspect of
+use of display terminals.  For writing a display program, you usually
+need only check the subsections for the operations you want to use.
+For writing a terminal description, you must read each subsection and
+fill in the capabilities described there.
+
+   String capabilities that are display commands may require numeric
+parameters (*note Parameters::.).  Most such capabilities do not use
+parameters.  When a capability requires parameters, this is explicitly
+stated at the beginning of its definition.  In simple cases, the first
+or second sentence of the definition mentions all the parameters, in
+the order they should be given, using a name in upper case for each
+one.  For example, the `rp' capability is a command that requires two
+parameters; its definition begins as follows:
+
+     String of commands to output a graphic character C, repeated N
+     times.
+
+   In complex cases or when there are many parameters, they are
+described explicitly.
+
+   When a capability is described as obsolete, this means that programs
+should not be written to look for it, but terminal descriptions should
+still be written to provide it.
+
+   When a capability is described as very obsolete, this means that it
+should be omitted from terminal descriptions as well.
+
+* Menu:
+
+* Basic::       Basic characteristics.
+* Screen Size::  Screen size, and what happens when it changes.
+* Cursor Motion::  Various ways to move the cursor.
+* Wrapping::    What happens if you write a character in the last column.
+* Scrolling::   Pushing text up and down on the screen.
+* Windows::     Limiting the part of the window that output affects.
+* Clearing::    Erasing one or many lines.
+* Insdel Line::  Making new blank lines in mid-screen; deleting lines.
+* Insdel Char::  Inserting and deleting characters within a line.
+* Standout::    Highlighting some of the text.
+* Underlining::  Underlining some of the text.
+* Cursor Visibility::  Making the cursor more or less easy to spot.
+* Bell::        Attracts user's attention; not localized on the screen.
+* Keypad::      Recognizing when function keys or arrows are typed.
+* Meta Key::    META acts like an extra shift key.
+* Initialization::  Commands used to initialize or reset the terminal.
+* Pad Specs::   Info for the kernel on how much padding is needed.
+* Status Line::  A status line displays "background" information.
+* Half-Line::   Moving by half-lines, for superscripts and subscripts.
+* Printer::     Controlling auxiliary printers of display terminals.
+
+\1f
+File: termcap.info,  Node: Basic,  Next: Screen Size,  Up: Capabilities
+
+Basic Characteristics
+=====================
+
+   This section documents the capabilities that describe the basic and
+nature of the terminal, and also those that are relevant to the output
+of graphic characters.
+
+`os'
+     Flag whose presence means that the terminal can overstrike.  This
+     means that outputting a graphic character does not erase whatever
+     was present in the same character position before.  The terminals
+     that can overstrike include printing terminals, storage tubes (all
+     obsolete nowadays), and many bit-map displays.
+
+`eo'
+     Flag whose presence means that outputting a space erases a
+     character position even if the terminal supports overstriking.  If
+     this flag is not present and overstriking is supported, output of
+     a space has no effect except to move the cursor.
+
+     (On terminals that do not support overstriking, you can always
+     assume that outputting a space at a position erases whatever
+     character was previously displayed there.)
+
+`gn'
+     Flag whose presence means that this terminal type is a generic type
+     which does not really describe any particular terminal.  Generic
+     types are intended for use as the default type assigned when the
+     user connects to the system, with the intention that the user
+     should specify what type he really has.  One example of a generic
+     type is the type `network'.
+
+     Since the generic type cannot say how to do anything interesting
+     with the terminal, termcap-using programs will always find that the
+     terminal is too weak to be supported if the user has failed to
+     specify a real terminal type in place of the generic one.  The
+     `gn' flag directs these programs to use a different error message:
+     "You have not specified your real terminal type", rather than
+     "Your terminal is not powerful enough to be used".
+
+`hc'
+     Flag whose presence means this is a hardcopy terminal.
+
+`rp'
+     String of commands to output a graphic character C, repeated N
+     times.  The first parameter value is the ASCII code for the desired
+     character, and the second parameter is the number of times to
+     repeat the character.  Often this command requires padding
+     proportional to the number of times the character is repeated.
+     This effect can be had by using parameter arithmetic with
+     `%'-sequences to compute the amount of padding, then generating
+     the result as a number at the front of the string so that `tputs'
+     will treat it as padding.
+
+`hz'
+     Flag whose presence means that the ASCII character `~' cannot be
+     output on this terminal because it is used for display commands.
+
+     Programs handle this flag by checking all text to be output and
+     replacing each `~' with some other character(s).  If this is not
+     done, the screen will be thoroughly garbled.
+
+     The old Hazeltine terminals that required such treatment are
+     probably very rare today, so you might as well not bother to
+     support this flag.
+
+`CC'
+     String whose presence means the terminal has a settable command
+     character.  The value of the string is the default command
+     character (which is usually ESC).
+
+     All the strings of commands in the terminal description should be
+     written to use the default command character.  If you are writing
+     an application program that changes the command character, use the
+     `CC' capability to figure out how to translate all the display
+     commands to work with the new command character.
+
+     Most programs have no reason to look at the `CC' capability.
+
+`xb'
+     Flag whose presence identifies Superbee terminals which are unable
+     to transmit the characters ESC and `Control-C'.  Programs which
+     support this flag are supposed to check the input for the code
+     sequences sent by the F1 and F2 keys, and pretend that ESC or
+     `Control-C' (respectively) had been read.  But this flag is
+     obsolete, and not worth supporting.
+
+\1f
+File: termcap.info,  Node: Screen Size,  Next: Cursor Motion,  Prev: Basic,  Up: Capabilities
+
+Screen Size
+===========
+
+   A terminal description has two capabilities, `co' and `li', that
+describe the screen size in columns and lines.  But there is more to
+the question of screen size than this.
+
+   On some operating systems the "screen" is really a window and the
+effective width can vary.  On some of these systems, `tgetnum' uses the
+actual width of the window to decide what value to return for the `co'
+capability, overriding what is actually written in the terminal
+description.  On other systems, it is up to the application program to
+check the actual window width using a system call.  For example, on BSD
+4.3 systems, the system call `ioctl' with code `TIOCGWINSZ' will tell
+you the current screen size.
+
+   On all window systems, termcap is powerless to advise the application
+program if the user resizes the window.  Application programs must deal
+with this possibility in a system-dependent fashion.  On some systems
+the C shell handles part of the problem by detecting changes in window
+size and setting the `TERMCAP' environment variable appropriately.
+This takes care of application programs that are started subsequently.
+It does not help application programs already running.
+
+   On some systems, including BSD 4.3, all programs using a terminal get
+a signal named `SIGWINCH' whenever the screen size changes.  Programs
+that use termcap should handle this signal by using `ioctl TIOCGWINSZ'
+to learn the new screen size.
+
+`co'
+     Numeric value, the width of the screen in character positions.
+     Even hardcopy terminals normally have a `co' capability.
+
+`li'
+     Numeric value, the height of the screen in lines.
+
+\1f
+File: termcap.info,  Node: Cursor Motion,  Next: Wrapping,  Prev: Screen Size,  Up: Capabilities
+
+Cursor Motion
+=============
+
+   Termcap assumes that the terminal has a "cursor", a spot on the
+screen where a visible mark is displayed, and that most display
+commands take effect at the position of the cursor.  It follows that
+moving the cursor to a specified location is very important.
+
+   There are many terminal capabilities for different cursor motion
+operations.  A terminal description should define as many as possible,
+but most programs do not need to use most of them.  One capability,
+`cm', moves the cursor to an arbitrary place on the screen; this by
+itself is sufficient for any application as long as there is no need to
+support hardcopy terminals or certain old, weak displays that have only
+relative motion commands.  Use of other cursor motion capabilities is an
+optimization, enabling the program to output fewer characters in some
+common cases.
+
+   If you plan to use the relative cursor motion commands in an
+application program, you must know what the starting cursor position
+is.  To do this, you must keep track of the cursor position and update
+the records each time anything is output to the terminal, including
+graphic characters.  In addition, it is necessary to know whether the
+terminal wraps after writing in the rightmost column.  *Note Wrapping::.
+
+   One other motion capability needs special mention: `nw' moves the
+cursor to the beginning of the following line, perhaps clearing all the
+starting line after the cursor, or perhaps not clearing at all.  This
+capability is a least common denominator that is probably supported
+even by terminals that cannot do most other things such as `cm' or `do'.
+Even hardcopy terminals can support `nw'.
+
+`cm'
+     String of commands to position the cursor at line L, column C.
+     Both parameters are origin-zero, and are defined relative to the
+     screen, not relative to display memory.
+
+     All display terminals except a few very obsolete ones support `cm',
+     so it is acceptable for an application program to refuse to
+     operate on terminals lacking `cm'.
+
+`ho'
+     String of commands to move the cursor to the upper left corner of
+     the screen (this position is called the "home position").  In
+     terminals where the upper left corner of the screen is not the
+     same as the beginning of display memory, this command must go to
+     the upper left corner of the screen, not the beginning of display
+     memory.
+
+     Every display terminal supports this capability, and many
+     application programs refuse to operate if the `ho' capability is
+     missing.
+
+`ll'
+     String of commands to move the cursor to the lower left corner of
+     the screen.  On some terminals, moving up from home position does
+     this, but programs should never assume that will work.  Just
+     output the `ll' string (if it is provided); if moving to home
+     position and then moving up is the best way to get there, the `ll'
+     command will do that.
+
+`cr'
+     String of commands to move the cursor to the beginning of the line
+     it is on.  If this capability is not specified, many programs
+     assume they can use the ASCII carriage return character for this.
+
+`le'
+     String of commands to move the cursor left one column.  Unless the
+     `bw' flag capability is specified, the effect is undefined if the
+     cursor is at the left margin; do not use this command there.  If
+     `bw' is present, this command may be used at the left margin, and
+     it wraps the cursor to the last column of the preceding line.
+
+`nd'
+     String of commands to move the cursor right one column.  The
+     effect is undefined if the cursor is at the right margin; do not
+     use this command there, not even if `am' is present.
+
+`up'
+     String of commands to move the cursor vertically up one line.  The
+     effect of sending this string when on the top line is undefined;
+     programs should never use it that way.
+
+`do'
+     String of commands to move the cursor vertically down one line.
+     The effect of sending this string when on the bottom line is
+     undefined; programs should never use it that way.
+
+     Some programs do use `do' to scroll up one line if used at the
+     bottom line, if `sf' is not defined but `sr' is.  This is only to
+     compensate for certain old, incorrect terminal descriptions.  (In
+     principle this might actually lead to incorrect behavior on other
+     terminals, but that seems to happen rarely if ever.)  But the
+     proper solution is that the terminal description should define
+     `sf' as well as `do' if the command is suitable for scrolling.
+
+     The original idea was that this string would not contain a newline
+     character and therefore could be used without disabling the
+     kernel's usual habit of converting of newline into a
+     carriage-return newline sequence.  But many terminal descriptions
+     do use newline in the `do' string, so this is not possible; a
+     program which sends the `do' string must disable output conversion
+     in the kernel (*note Initialize::.).
+
+`bw'
+     Flag whose presence says that `le' may be used in column zero to
+     move to the last column of the preceding line.  If this flag is
+     not present, `le' should not be used in column zero.
+
+`nw'
+     String of commands to move the cursor to start of next line,
+     possibly clearing rest of line (following the cursor) before
+     moving.
+
+`DO', `UP', `LE', `RI'
+     Strings of commands to move the cursor N lines down vertically, up
+     vertically, or N columns left or right.  Do not attempt to move
+     past any edge of the screen with these commands; the effect of
+     trying that is undefined.  Only a few terminal descriptions provide
+     these commands, and most programs do not use them.
+
+`CM'
+     String of commands to position the cursor at line L, column C,
+     relative to display memory.  Both parameters are origin-zero.
+     This capability is present only in terminals where there is a
+     difference between screen-relative and memory-relative addressing,
+     and not even in all such terminals.
+
+`ch'
+     String of commands to position the cursor at column C in the same
+     line it is on.  This is a special case of `cm' in which the
+     vertical position is not changed.  The `ch' capability is provided
+     only when it is faster to output than `cm' would be in this
+     special case.  Programs should not assume most display terminals
+     have `ch'.
+
+`cv'
+     String of commands to position the cursor at line L in the same
+     column.  This is a special case of `cm' in which the horizontal
+     position is not changed.  The `cv' capability is provided only
+     when it is faster to output than `cm' would be in this special
+     case.  Programs should not assume most display terminals have `cv'.
+
+`sc'
+     String of commands to make the terminal save the current cursor
+     position.  Only the last saved position can be used.  If this
+     capability is present, `rc' should be provided also.  Most
+     terminals have neither.
+
+`rc'
+     String of commands to make the terminal restore the last saved
+     cursor position.  If this capability is present, `sc' should be
+     provided also.  Most terminals have neither.
+
+`ff'
+     String of commands to advance to the next page, for a hardcopy
+     terminal.
+
+`ta'
+     String of commands to move the cursor right to the next hardware
+     tab stop column.  Missing if the terminal does not have any kind of
+     hardware tabs.  Do not send this command if the kernel's terminal
+     modes say that the kernel is expanding tabs into spaces.
+
+`bt'
+     String of commands to move the cursor left to the previous hardware
+     tab stop column.  Missing if the terminal has no such ability; many
+     terminals do not.  Do not send this command if the kernel's
+     terminal modes say that the kernel is expanding tabs into spaces.
+
+   The following obsolete capabilities should be included in terminal
+descriptions when appropriate, but should not be looked at by new
+programs.
+
+`nc'
+     Flag whose presence means the terminal does not support the ASCII
+     carriage return character as `cr'.  This flag is needed because
+     old programs assume, when the `cr' capability is missing, that
+     ASCII carriage return can be used for the purpose.  We use `nc' to
+     tell the old programs that carriage return may not be used.
+
+     New programs should not assume any default for `cr', so they need
+     not look at `nc'.  However, descriptions should contain `nc'
+     whenever they do not contain `cr'.
+
+`xt'
+     Flag whose presence means that the ASCII tab character may not be
+     used for cursor motion.  This flag exists because old programs
+     assume, when the `ta' capability is missing, that ASCII tab can be
+     used for the purpose.  We use `xt' to tell the old programs not to
+     use tab.
+
+     New programs should not assume any default for `ta', so they need
+     not look at `xt' in connection with cursor motion.  Note that `xt'
+     also has implications for standout mode (*note Standout::.).  It
+     is obsolete in regard to cursor motion but not in regard to
+     standout.
+
+     In fact, `xt' means that the terminal is a Teleray 1061.
+
+`bc'
+     Very obsolete alternative name for the `le' capability.
+
+`bs'
+     Flag whose presence means that the ASCII character backspace may be
+     used to move the cursor left.  Obsolete; look at `le' instead.
+
+`nl'
+     Obsolete capability which is a string that can either be used to
+     move the cursor down or to scroll.  The same string must scroll
+     when used on the bottom line and move the cursor when used on any
+     other line.  New programs should use `do' or `sf', and ignore `nl'.
+
+     If there is no `nl' capability, some old programs assume they can
+     use the newline character for this purpose.  These programs follow
+     a bad practice, but because they exist, it is still desirable to
+     define the `nl' capability in a terminal description if the best
+     way to move down is *not* a newline.
+
+\1f
+File: termcap.info,  Node: Wrapping,  Next: Scrolling,  Prev: Cursor Motion,  Up: Capabilities
+
+Wrapping
+========
+
+   "Wrapping" means moving the cursor from the right margin to the left
+margin of the following line.  Some terminals wrap automatically when a
+graphic character is output in the last column, while others do not.
+Most application programs that use termcap need to know whether the
+terminal wraps.  There are two special flag capabilities to describe
+what the terminal does when a graphic character is output in the last
+column.
+
+`am'
+     Flag whose presence means that writing a character in the last
+     column causes the cursor to wrap to the beginning of the next line.
+
+     If `am' is not present, writing in the last column leaves the
+     cursor at the place where the character was written.
+
+     Writing in the last column of the last line should be avoided on
+     terminals with `am', as it may or may not cause scrolling to occur
+     (*note Scrolling::.).  Scrolling is surely not what you would
+     intend.
+
+     If your program needs to check the `am' flag, then it also needs
+     to check the `xn' flag which indicates that wrapping happens in a
+     strange way.  Many common terminals have the `xn' flag.
+
+`xn'
+     Flag whose presence means that the cursor wraps in a strange way.
+     At least two distinct kinds of strange behavior are known; the
+     termcap data base does not contain anything to distinguish the two.
+
+     On Concept-100 terminals, output in the last column wraps the
+     cursor almost like an ordinary `am' terminal.  But if the next
+     thing output is a newline, it is ignored.
+
+     DEC VT-100 terminals (when the wrap switch is on) do a different
+     strange thing: the cursor wraps only if the next thing output is
+     another graphic character.  In fact, the wrap occurs when the
+     following graphic character is received by the terminal, before the
+     character is placed on the screen.
+
+     On both of these terminals, after writing in the last column a
+     following graphic character will be displayed in the first column
+     of the following line.  But the effect of relative cursor motion
+     characters such as newline or backspace at such a time depends on
+     the terminal.  The effect of erase or scrolling commands also
+     depends on the terminal.  You can't assume anything about what
+     they will do on a terminal that has `xn'.  So, to be safe, you
+     should never do these things at such a time on such a terminal.
+
+     To be sure of reliable results on a terminal which has the `xn'
+     flag, output a `cm' absolute positioning command after writing in
+     the last column.  Another safe thing to do is to output
+     carriage-return newline, which will leave the cursor at the
+     beginning of the following line.
+
+\1f
+File: termcap.info,  Node: Scrolling,  Next: Windows,  Prev: Wrapping,  Up: Capabilities
+
+Scrolling
+=========
+
+   "Scrolling" means moving the contents of the screen up or down one or
+more lines.  Moving the contents up is "forward scrolling"; moving them
+down is "reverse scrolling".
+
+   Scrolling happens after each line of output during ordinary output
+on most display terminals.  But in an application program that uses
+termcap for random-access output, scrolling happens only when
+explicitly requested with the commands in this section.
+
+   Some terminals have a "scroll region" feature.  This lets you limit
+the effect of scrolling to a specified range of lines.  Lines outside
+the range are unaffected when scrolling happens.  The scroll region
+feature is available if either `cs' or `cS' is present.
+
+`sf'
+     String of commands to scroll the screen one line up, assuming it is
+     output with the cursor at the beginning of the bottom line.
+
+`sr'
+     String of commands to scroll the screen one line down, assuming it
+     is output with the cursor at the beginning of the top line.
+
+`do'
+     A few programs will try to use `do' to do the work of `sf'.  This
+     is not really correct--it is an attempt to compensate for the
+     absence of a `sf' command in some old terminal descriptions.
+
+     Since these terminal descriptions do define `sr', perhaps at one
+     time the definition of `do' was different and it could be used for
+     scrolling as well.  But it isn't desirable to combine these two
+     functions in one capability, since scrolling often requires more
+     padding than simply moving the cursor down.  Defining `sf' and
+     `do' separately allows you to specify the padding properly.  Also,
+     all sources agree that `do' should not be relied on to do
+     scrolling.
+
+     So the best approach is to add `sf' capabilities to the
+     descriptions of these terminals, copying the definition of `do' if
+     that does scroll.
+
+`SF'
+     String of commands to scroll the screen N lines up, assuming it is
+     output with the cursor at the beginning of the bottom line.
+
+`SR'
+     String of commands to scroll the screen N lines down, assuming it
+     is output with the cursor at the beginning of the top line.
+
+`cs'
+     String of commands to set the scroll region.  This command takes
+     two parameters, START and END, which are the line numbers
+     (origin-zero) of the first line to include in the scroll region
+     and of the last line to include in it.  When a scroll region is
+     set, scrolling is limited to the specified range of lines; lines
+     outside the range are not affected by scroll commands.
+
+     Do not try to move the cursor outside the scroll region.  The
+     region remains set until explicitly removed.  To remove the scroll
+     region, use another `cs' command specifying the full height of the
+     screen.
+
+     The cursor position is undefined after the `cs' command is set, so
+     position the cursor with `cm' immediately afterward.
+
+`cS'
+     String of commands to set the scroll region using parameters in
+     different form.  The effect is the same as if `cs' were used.
+     Four parameters are required:
+
+       1. Total number of lines on the screen.
+
+       2. Number of lines above desired scroll region.
+
+       3. Number of lines below (outside of) desired scroll region.
+
+       4. Total number of lines on the screen, the same as the first
+          parameter.
+
+     This capability is a GNU extension that was invented to allow the
+     Ann Arbor Ambassador's scroll-region command to be described; it
+     could also be done by putting non-Unix `%'-sequences into a `cs'
+     string, but that would have confused Unix programs that used the
+     `cs' capability with the Unix termcap.  Currently only GNU Emacs
+     uses the `cS' capability.
+
+`ns'
+     Flag which means that the terminal does not normally scroll for
+     ordinary sequential output.  For modern terminals, this means that
+     outputting a newline in ordinary sequential output with the cursor
+     on the bottom line wraps to the top line.  For some obsolete
+     terminals, other things may happen.
+
+     The terminal may be able to scroll even if it does not normally do
+     so.  If the `sf' capability is provided, it can be used for
+     scrolling regardless of `ns'.
+
+`da'
+     Flag whose presence means that lines scrolled up off the top of the
+     screen may come back if scrolling down is done subsequently.
+
+     The `da' and `db' flags do not, strictly speaking, affect how to
+     scroll.  But programs that scroll usually need to clear the lines
+     scrolled onto the screen, if these flags are present.
+
+`db'
+     Flag whose presence means that lines scrolled down off the bottom
+     of the screen may come back if scrolling up is done subsequently.
+
+`lm'
+     Numeric value, the number of lines of display memory that the
+     terminal has.  A value of zero means that the terminal has more
+     display memory than can fit on the screen, but no fixed number of
+     lines.  (The number of lines may depend on the amount of text in
+     each line.)
+
+   Any terminal description that defines `SF' should also define `sf';
+likewise for `SR' and `sr'.  However, many terminals can only scroll by
+one line at a time, so it is common to find `sf' and not `SF', or `sr'
+without `SR'.
+
+   Therefore, all programs that use the scrolling facilities should be
+prepared to work with `sf' in the case that `SF' is absent, and
+likewise with `sr'.  On the other hand, an application program that
+uses only `sf' and not `SF' is acceptable, though slow on some
+terminals.
+
+   When outputting a scroll command with `tputs', the NLINES argument
+should be the total number of lines in the portion of the screen being
+scrolled.  Very often these commands require padding proportional to
+this number of lines.  *Note Padding::.
+
+\1f
+File: termcap.info,  Node: Windows,  Next: Clearing,  Prev: Scrolling,  Up: Capabilities
+
+Windows
+=======
+
+   A "window", in termcap, is a rectangular portion of the screen to
+which all display operations are restricted.  Wrapping, clearing,
+scrolling, insertion and deletion all operate as if the specified
+window were all the screen there was.
+
+`wi'
+     String of commands to set the terminal output screen window.  This
+     string requires four parameters, all origin-zero:
+       1. The first line to include in the window.
+
+       2. The last line to include in the window.
+
+       3. The first column to include in the window.
+
+       4. The last column to include in the window.
+
+   Most terminals do not support windows.
+
+\1f
+File: termcap.info,  Node: Clearing,  Next: Insdel Line,  Prev: Windows,  Up: Capabilities
+
+Clearing Parts of the Screen
+============================
+
+   There are several terminal capabilities for clearing parts of the
+screen to blank.  All display terminals support the `cl' string, and
+most display terminals support all of these capabilities.
+
+`cl'
+     String of commands to clear the entire screen and position the
+     cursor at the upper left corner.
+
+`cd'
+     String of commands to clear the line the cursor is on, and all the
+     lines below it, down to the bottom of the screen.  This command
+     string should be used only with the cursor in column zero; their
+     effect is undefined if the cursor is elsewhere.
+
+`ce'
+     String of commands to clear from the cursor to the end of the
+     current line.
+
+`ec'
+     String of commands to clear N characters, starting with the
+     character that the cursor is on.  This command string is expected
+     to leave the cursor position unchanged.  The parameter N should
+     never be large enough to reach past the right margin; the effect
+     of such a large parameter would be undefined.
+
+   Clear to end of line (`ce') is extremely important in programs that
+maintain an updating display.  Nearly all display terminals support this
+operation, so it is acceptable for a an application program to refuse to
+work if `ce' is not present.  However, if you do not want this
+limitation, you can accomplish clearing to end of line by outputting
+spaces until you reach the right margin.  In order to do this, you must
+know the current horizontal position.  Also, this technique assumes
+that writing a space will erase.  But this happens to be true on all
+the display terminals that fail to support `ce'.
+
+\1f
+File: termcap.info,  Node: Insdel Line,  Next: Insdel Char,  Prev: Clearing,  Up: Capabilities
+
+Insert/Delete Line
+==================
+
+   "Inserting a line" means creating a blank line in the middle of the
+screen, and pushing the existing lines of text apart.  In fact, the
+lines above the insertion point do not change, while the lines below
+move down, and one is normally lost at the bottom of the screen.
+
+   "Deleting a line" means causing the line to disappear from the
+screen, closing up the gap by moving the lines below it upward.  A new
+line appears at the bottom of the screen.  Usually this line is blank,
+but on terminals with the `db' flag it may be a line previously moved
+off the screen bottom by scrolling or line insertion.
+
+   Insertion and deletion of lines is useful in programs that maintain
+an updating display some parts of which may get longer or shorter.
+They are also useful in editors for scrolling parts of the screen, and
+for redisplaying after lines of text are killed or inserted.
+
+   Many terminals provide commands to insert or delete a single line at
+the cursor position.  Some provide the ability to insert or delete
+several lines with one command, using the number of lines to insert or
+delete as a parameter.  Always move the cursor to column zero before
+using any of these commands.
+
+`al'
+     String of commands to insert a blank line before the line the
+     cursor is on.  The existing line, and all lines below it, are
+     moved down.  The last line in the screen (or in the scroll region,
+     if one is set) disappears and in most circumstances is discarded.
+     It may not be discarded if the `db' is present (*note
+     Scrolling::.).
+
+     The cursor must be at the left margin before this command is used.
+     This command does not move the cursor.
+
+`dl'
+     String of commands to delete the line the cursor is on.  The
+     following lines move up, and a blank line appears at the bottom of
+     the screen (or bottom of the scroll region).  If the terminal has
+     the `db' flag, a nonblank line previously pushed off the screen
+     bottom may reappear at the bottom.
+
+     The cursor must be at the left margin before this command is used.
+     This command does not move the cursor.
+
+`AL'
+     String of commands to insert N blank lines before the line that
+     the cursor is on.  It is like `al' repeated N times, except that
+     it is as fast as one `al'.
+
+`DL'
+     String of commands to delete N lines starting with the line that
+     the cursor is on.  It is like `dl' repeated N times, except that
+     it is as fast as one `dl'.
+
+   Any terminal description that defines `AL' should also define `al';
+likewise for `DL' and `dl'.  However, many terminals can only insert or
+delete one line at a time, so it is common to find `al' and not `AL',
+or `dl' without `DL'.
+
+   Therefore, all programs that use the insert and delete facilities
+should be prepared to work with `al' in the case that `AL' is absent,
+and likewise with `dl'.  On the other hand, it is acceptable to write
+an application that uses only `al' and `dl' and does not look for `AL'
+or `DL' at all.
+
+   If a terminal does not support line insertion and deletion directly,
+but does support a scroll region, the effect of insertion and deletion
+can be obtained with scrolling.  However, it is up to the individual
+user program to check for this possibility and use the scrolling
+commands to get the desired result.  It is fairly important to implement
+this alternate strategy, since it is the only way to get the effect of
+line insertion and deletion on the popular VT100 terminal.
+
+   Insertion and deletion of lines is affected by the scroll region on
+terminals that have a settable scroll region.  This is useful when it is
+desirable to move any few consecutive lines up or down by a few lines.
+*Note Scrolling::.
+
+   The line pushed off the bottom of the screen is not lost if the
+terminal has the `db' flag capability; instead, it is pushed into
+display memory that does not appear on the screen.  This is the same
+thing that happens when scrolling pushes a line off the bottom of the
+screen.  Either reverse scrolling or deletion of a line can bring the
+apparently lost line back onto the bottom of the screen.  If the
+terminal has the scroll region feature as well as `db', the pushed-out
+line really is lost if a scroll region is in effect.
+
+   When outputting an insert or delete command with `tputs', the NLINES
+argument should be the total number of lines from the cursor to the
+bottom of the screen (or scroll region).  Very often these commands
+require padding proportional to this number of lines.  *Note Padding::.
+
+   For `AL' and `DL' the NLINES argument should *not* depend on the
+number of lines inserted or deleted; only the total number of lines
+affected.  This is because it is just as fast to insert two or N lines
+with `AL' as to insert one line with `al'.
+
diff --git a/lib/termcap/grot/termcap.info-3 b/lib/termcap/grot/termcap.info-3
new file mode 100644 (file)
index 0000000..c1e6af9
--- /dev/null
@@ -0,0 +1,1469 @@
+This is Info file /home/gd/gnu/termcap/termcap.info, produced by
+Makeinfo-1.52 from the input file /home/gd/gnu/termcap/termcap.texi.
+
+   This file documents the termcap library of the GNU system.
+
+   Copyright (C) 1988 Free Software Foundation, Inc.
+
+   Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+   Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+   Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+\1f
+File: termcap.info,  Node: Insdel Char,  Next: Standout,  Prev: Insdel Line,  Up: Capabilities
+
+Insert/Delete Character
+=======================
+
+   "Inserting a character" means creating a blank space in the middle
+of a line, and pushing the rest of the line rightward.  The character
+in the rightmost column is lost.
+
+   "Deleting a character" means causing the character to disappear from
+the screen, closing up the gap by moving the rest of the line leftward.
+A blank space appears in the rightmost column.
+
+   Insertion and deletion of characters is useful in programs that
+maintain an updating display some parts of which may get longer or
+shorter.  It is also useful in editors for redisplaying the results of
+editing within a line.
+
+   Many terminals provide commands to insert or delete a single
+character at the cursor position.  Some provide the ability to insert
+or delete several characters with one command, using the number of
+characters to insert or delete as a parameter.
+
+   Many terminals provide an insert mode in which outputting a graphic
+character has the added effect of inserting a position for that
+character.  A special command string is used to enter insert mode and
+another is used to exit it.  The reason for designing a terminal with
+an insert mode rather than an insert command is that inserting
+character positions is usually followed by writing characters into
+them.  With insert mode, this is as fast as simply writing the
+characters, except for the fixed overhead of entering and leaving
+insert mode.  However, when the line speed is great enough, padding may
+be required for the graphic characters output in insert mode.
+
+   Some terminals require you to enter insert mode and then output a
+special command for each position to be inserted.  Or they may require
+special commands to be output before or after each graphic character to
+be inserted.
+
+   Deletion of characters is usually accomplished by a straightforward
+command to delete one or several positions; but on some terminals, it
+is necessary to enter a special delete mode before using the delete
+command, and leave delete mode afterward.  Sometimes delete mode and
+insert mode are the same mode.
+
+   Some terminals make a distinction between character positions in
+which a space character has been output and positions which have been
+cleared.  On these terminals, the effect of insert or delete character
+runs to the first cleared position rather than to the end of the line.
+In fact, the effect may run to more than one line if there is no
+cleared position to stop the shift on the first line.  These terminals
+are identified by the `in' flag capability.
+
+   On terminals with the `in' flag, the technique of skipping over
+characters that you know were cleared, and then outputting text later
+on in the same line, causes later insert and delete character
+operations on that line to do nonstandard things.  A program that has
+any chance of doing this must check for the `in' flag and must be
+careful to write explicit space characters into the intermediate
+columns when `in' is present.
+
+   A plethora of terminal capabilities are needed to describe all of
+this complexity.  Here is a list of them all.  Following the list, we
+present an algorithm for programs to use to take proper account of all
+of these capabilities.
+
+`im'
+     String of commands to enter insert mode.
+
+     If the terminal has no special insert mode, but it can insert
+     characters with a special command, `im' should be defined with a
+     null value, because the `vi' editor assumes that insertion of a
+     character is impossible if `im' is not provided.
+
+     New programs should not act like `vi'.  They should pay attention
+     to `im' only if it is defined.
+
+`ei'
+     String of commands to leave insert mode.  This capability must be
+     present if `im' is.
+
+     On a few old terminals the same string is used to enter and exit
+     insert mode.  This string turns insert mode on if it was off, and
+     off it it was on.  You can tell these terminals because the `ei'
+     string equals the `im' string.  If you want to support these
+     terminals, you must always remember accurately whether insert mode
+     is in effect.  However, these terminals are obsolete, and it is
+     reasonable to refuse to support them.  On all modern terminals, you
+     can safely output `ei' at any time to ensure that insert mode is
+     turned off.
+
+`ic'
+     String of commands to insert one character position at the cursor.
+     The cursor does not move.
+
+     If outputting a graphic character while in insert mode is
+     sufficient to insert the character, then the `ic' capability
+     should be defined with a null value.
+
+     If your terminal offers a choice of ways to insert--either use
+     insert mode or use a special command--then define `im' and do not
+     define `ic', since this gives the most efficient operation when
+     several characters are to be inserted.  *Do not* define both
+     strings, for that means that *both* must be used each time
+     insertion is done.
+
+`ip'
+     String of commands to output following an inserted graphic
+     character in insert mode.  Often it is used just for a padding
+     spec, when padding is needed after an inserted character (*note
+     Padding::.).
+
+`IC'
+     String of commands to insert N character positions at and after
+     the cursor.  It has the same effect as repeating the `ic' string
+     and a space, N times.
+
+     If `IC' is provided, application programs may use it without first
+     entering insert mode.
+
+`mi'
+     Flag whose presence means it is safe to move the cursor while in
+     insert mode and assume the terminal remains in insert mode.
+
+`in'
+     Flag whose presence means that the terminal distinguishes between
+     character positions in which space characters have been output and
+     positions which have been cleared.
+
+   An application program can assume that the terminal can do character
+insertion if *any one of* the capabilities `IC', `im', `ic' or `ip' is
+provided.
+
+   To insert N blank character positions, move the cursor to the place
+to insert them and follow this algorithm:
+
+  1. If an `IC' string is provided, output it with parameter N and you
+     are finished.  Otherwise (or if you don't want to bother to look
+     for an `IC' string) follow the remaining steps.
+
+  2. Output the `im' string, if there is one, unless the terminal is
+     already in insert mode.
+
+  3. Repeat steps 4 through 6, N times.
+
+  4. Output the `ic' string if any.
+
+  5. Output a space.
+
+  6. Output the `ip' string if any.
+
+  7. Output the `ei' string, eventually, to exit insert mode.  There is
+     no need to do this right away.  If the `mi' flag is present, you
+     can move the cursor and the cursor will remain in insert mode;
+     then you can do more insertion elsewhere without reentering insert
+     mode.
+
+   To insert N graphic characters, position the cursor and follow this
+algorithm:
+
+  1. If an `IC' string is provided, output it with parameter N, then
+     output the graphic characters, and you are finished.  Otherwise
+     (or if you don't want to bother to look for an `IC' string) follow
+     the remaining steps.
+
+  2. Output the `im' string, if there is one, unless the terminal is
+     already in insert mode.
+
+  3. For each character to be output, repeat steps 4 through 6.
+
+  4. Output the `ic' string if any.
+
+  5. Output the next graphic character.
+
+  6. Output the `ip' string if any.
+
+  7. Output the `ei' string, eventually, to exit insert mode.  There is
+     no need to do this right away.  If the `mi' flag is present, you
+     can move the cursor and the cursor will remain in insert mode;
+     then you can do more insertion elsewhere without reentering insert
+     mode.
+
+   Note that this is not the same as the original Unix termcap
+specifications in one respect: it assumes that the `IC' string can be
+used without entering insert mode.  This is true as far as I know, and
+it allows you be able to avoid entering and leaving insert mode, and
+also to be able to avoid the inserted-character padding after the
+characters that go into the inserted positions.
+
+   Deletion of characters is less complicated; deleting one column is
+done by outputting the `dc' string.  However, there may be a delete
+mode that must be entered with `dm' in order to make `dc' work.
+
+`dc'
+     String of commands to delete one character position at the cursor.
+     If `dc' is not present, the terminal cannot delete characters.
+
+`DC'
+     String of commands to delete N characters starting at the cursor.
+     It has the same effect as repeating the `dc' string N times.  Any
+     terminal description that has `DC' also has `dc'.
+
+`dm'
+     String of commands to enter delete mode.  If not present, there is
+     no delete mode, and `dc' can be used at any time (assuming there is
+     a `dc').
+
+`ed'
+     String of commands to exit delete mode.  This must be present if
+     `dm' is.
+
+   To delete N character positions, position the cursor and follow these
+steps:
+
+  1. If the `DC' string is present, output it with parameter N and you
+     are finished.  Otherwise, follow the remaining steps.
+
+  2. Output the `dm' string, unless you know the terminal is already in
+     delete mode.
+
+  3. Output the `dc' string N times.
+
+  4. Output the `ed' string eventually.  If the flag capability `mi' is
+     present, you can move the cursor and do more deletion without
+     leaving and reentering delete mode.
+
+   As with the `IC' string, we have departed from the original termcap
+specifications by assuming that `DC' works without entering delete mode
+even though `dc' would not.
+
+   If the `dm' and `im' capabilities are both present and have the same
+value, it means that the terminal has one mode for both insertion and
+deletion.  It is useful for a program to know this, because then it can
+do insertions after deletions, or vice versa, without leaving
+insert/delete mode and reentering it.
+
+\1f
+File: termcap.info,  Node: Standout,  Next: Underlining,  Prev: Insdel Char,  Up: Capabilities
+
+Standout and Appearance Modes
+=============================
+
+   "Appearance modes" are modifications to the ways characters are
+displayed.  Typical appearance modes include reverse video, dim, bright,
+blinking, underlined, invisible, and alternate character set.  Each
+kind of terminal supports various among these, or perhaps none.
+
+   For each type of terminal, one appearance mode or combination of
+them that looks good for highlighted text is chosen as the "standout
+mode".  The capabilities `so' and `se' say how to enter and leave
+standout mode.  Programs that use appearance modes only to highlight
+some text generally use the standout mode so that they can work on as
+many terminals as possible.  Use of specific appearance modes other
+than "underlined" and "alternate character set" is rare.
+
+   Terminals that implement appearance modes fall into two general
+classes as to how they do it.
+
+   In some terminals, the presence or absence of any appearance mode is
+recorded separately for each character position.  In these terminals,
+each graphic character written is given the appearance modes current at
+the time it is written, and keeps those modes until it is erased or
+overwritten.  There are special commands to turn the appearance modes
+on or off for characters to be written in the future.
+
+   In other terminals, the change of appearance modes is represented by
+a marker that belongs to a certain screen position but affects all
+following screen positions until the next marker.  These markers are
+traditionally called "magic cookies".
+
+   The same capabilities (`so', `se', `mb' and so on) for turning
+appearance modes on and off are used for both magic-cookie terminals
+and per-character terminals.  On magic cookie terminals, these give the
+commands to write the magic cookies.  On per-character terminals, they
+change the current modes that affect future output and erasure.  Some
+simple applications can use these commands without knowing whether or
+not they work by means of cookies.
+
+   However, a program that maintains and updates a display needs to know
+whether the terminal uses magic cookies, and exactly what their effect
+is.  This information comes from the `sg' capability.
+
+   The `sg' capability is a numeric capability whose presence indicates
+that the terminal uses magic cookies for appearance modes.  Its value is
+the number of character positions that a magic cookie occupies.  Usually
+the cookie occupies one or more character positions on the screen, and
+these character positions are displayed as blank, but in some terminals
+the cookie has zero width.
+
+   The `sg' capability describes both the magic cookie to turn standout
+on and the cookie to turn it off.  This makes the assumption that both
+kinds of cookie have the same width on the screen.  If that is not true,
+the narrower cookie must be "widened" with spaces until it has the same
+width as the other.
+
+   On some magic cookie terminals, each line always starts with normal
+display; in other words, the scope of a magic cookie never extends over
+more than one line.  But on other terminals, one magic cookie affects
+all the lines below it unless explicitly canceled.  Termcap does not
+define any way to distinguish these two ways magic cookies can work.
+To be safe, it is best to put a cookie at the beginning of each line.
+
+   On some per-character terminals, standout mode or other appearance
+modes may be canceled by moving the cursor.  On others, moving the
+cursor has no effect on the state of the appearance modes.  The latter
+class of terminals are given the flag capability `ms' ("can move in
+standout").  All programs that might have occasion to move the cursor
+while appearance modes are turned on must check for this flag; if it is
+not present, they should reset appearance modes to normal before doing
+cursor motion.
+
+   A program that has turned on only standout mode should use `se' to
+reset the standout mode to normal.  A program that has turned on only
+alternate character set mode should use `ae' to return it to normal.
+If it is possible that any other appearance modes are turned on, use the
+`me' capability to return them to normal.
+
+   Note that the commands to turn on one appearance mode, including `so'
+and `mb' ... `mr', if used while some other appearance modes are turned
+on, may combine the two modes on some terminals but may turn off the
+mode previously enabled on other terminals.  This is because some
+terminals do not have a command to set or clear one appearance mode
+without changing the others.  Programs should not attempt to use
+appearance modes in combination except with `sa', and when switching
+from one single mode to another should always turn off the previously
+enabled mode and then turn on the new desired mode.
+
+   On some old terminals, the `so' and `se' commands may be the same
+command, which has the effect of turning standout on if it is off, or
+off it is on.  It is therefore risky for a program to output extra `se'
+commands for good measure.  Fortunately, all these terminals are
+obsolete.
+
+   Programs that update displays in which standout-text may be replaced
+with non-standout text must check for the `xs' flag.  In a per-character
+terminal, this flag says that the only way to remove standout once
+written is to clear that portion of the line with the `ce' string or
+something even more powerful (*note Clearing::.); just writing new
+characters at those screen positions will not change the modes in
+effect there.  In a magic cookie terminal, `xs' says that the only way
+to remove a cookie is to clear a portion of the line that includes the
+cookie; writing a different cookie at the same position does not work.
+
+   Such programs must also check for the `xt' flag, which means that the
+terminal is a Teleray 1061.  On this terminal it is impossible to
+position the cursor at the front of a magic cookie, so the only two
+ways to remove a cookie are (1) to delete the line it is on or (2) to
+position the cursor at least one character before it (possibly on a
+previous line) and output the `se' string, which on these terminals
+finds and removes the next `so' magic cookie on the screen.  (It may
+also be possible to remove a cookie which is not at the beginning of a
+line by clearing that line.)  The `xt' capability also has implications
+for the use of tab characters, but in that regard it is obsolete (*Note
+Cursor Motion::).
+
+`so'
+     String of commands to enter standout mode.
+
+`se'
+     String of commands to leave standout mode.
+
+`sg'
+     Numeric capability, the width on the screen of the magic cookie.
+     This capability is absent in terminals that record appearance modes
+     character by character.
+
+`ms'
+     Flag whose presence means that it is safe to move the cursor while
+     the appearance modes are not in the normal state.  If this flag is
+     absent, programs should always reset the appearance modes to
+     normal before moving the cursor.
+
+`xs'
+     Flag whose presence means that the only way to reset appearance
+     modes already on the screen is to clear to end of line.  On a
+     per-character terminal, you must clear the area where the modes
+     are set.  On a magic cookie terminal, you must clear an area
+     containing the cookie.  See the discussion above.
+
+`xt'
+     Flag whose presence means that the cursor cannot be positioned
+     right in front of a magic cookie, and that `se' is a command to
+     delete the next magic cookie following the cursor.  See discussion
+     above.
+
+`mb'
+     String of commands to enter blinking mode.
+
+`md'
+     String of commands to enter double-bright mode.
+
+`mh'
+     String of commands to enter half-bright mode.
+
+`mk'
+     String of commands to enter invisible mode.
+
+`mp'
+     String of commands to enter protected mode.
+
+`mr'
+     String of commands to enter reverse-video mode.
+
+`me'
+     String of commands to turn off all appearance modes, including
+     standout mode and underline mode.  On some terminals it also turns
+     off alternate character set mode; on others, it may not.  This
+     capability must be present if any of `mb' ... `mr' is present.
+
+`as'
+     String of commands to turn on alternate character set mode.  This
+     mode assigns some or all graphic characters an alternate picture
+     on the screen.  There is no standard as to what the alternate
+     pictures look like.
+
+`ae'
+     String of commands to turn off alternate character set mode.
+
+`sa'
+     String of commands to turn on an arbitrary combination of
+     appearance modes.  It accepts 9 parameters, each of which controls
+     a particular kind of appearance mode.  A parameter should be 1 to
+     turn its appearance mode on, or zero to turn that mode off.  Most
+     terminals do not support the `sa' capability, even among those
+     that do have various appearance modes.
+
+     The nine parameters are, in order, STANDOUT, UNDERLINE, REVERSE,
+     BLINK, HALF-BRIGHT, DOUBLE-BRIGHT, BLANK, PROTECT, ALT CHAR SET.
+
+\1f
+File: termcap.info,  Node: Underlining,  Next: Cursor Visibility,  Prev: Standout,  Up: Capabilities
+
+Underlining
+===========
+
+   Underlining on most terminals is a kind of appearance mode, much like
+standout mode.  Therefore, it may be implemented using magic cookies or
+as a flag in the terminal whose current state affects each character
+that is output.  *Note Standout::, for a full explanation.
+
+   The `ug' capability is a numeric capability whose presence indicates
+that the terminal uses magic cookies for underlining.  Its value is the
+number of character positions that a magic cookie for underlining
+occupies; it is used for underlining just as `sg' is used for standout.
+Aside from the simplest applications, it is impossible to use
+underlining correctly without paying attention to the value of `ug'.
+
+`us'
+     String of commands to turn on underline mode or to output a magic
+     cookie to start underlining.
+
+`ue'
+     String of commands to turn off underline mode or to output a magic
+     cookie to stop underlining.
+
+`ug'
+     Width of magic cookie that represents a change of underline mode;
+     or missing, if the terminal does not use a magic cookie for this.
+
+`ms'
+     Flag whose presence means that it is safe to move the cursor while
+     the appearance modes are not in the normal state.  Underlining is
+     an appearance mode.  If this flag is absent, programs should
+     always turn off underlining before moving the cursor.
+
+   There are two other, older ways of doing underlining: there can be a
+command to underline a single character, or the output of `_', the
+ASCII underscore character, as an overstrike could cause a character to
+be underlined.  New programs need not bother to handle these
+capabilities unless the author cares strongly about the obscure
+terminals which support them.  However, terminal descriptions should
+provide these capabilities when appropriate.
+
+`uc'
+     String of commands to underline the character under the cursor, and
+     move the cursor right.
+
+`ul'
+     Flag whose presence means that the terminal can underline by
+     overstriking an underscore character (`_'); some terminals can do
+     this even though they do not support overstriking in general.  An
+     implication of this flag is that when outputting new text to
+     overwrite old text, underscore characters must be treated
+     specially lest they underline the old text instead.
+
+\1f
+File: termcap.info,  Node: Cursor Visibility,  Next: Bell,  Prev: Underlining,  Up: Capabilities
+
+Cursor Visibility
+=================
+
+   Some terminals have the ability to make the cursor invisible, or to
+enhance it.  Enhancing the cursor is often done by programs that plan
+to use the cursor to indicate to the user a position of interest that
+may be anywhere on the screen--for example, the Emacs editor enhances
+the cursor on entry.  Such programs should always restore the cursor to
+normal on exit.
+
+`vs'
+     String of commands to enhance the cursor.
+
+`vi'
+     String of commands to make the cursor invisible.
+
+`ve'
+     String of commands to return the cursor to normal.
+
+   If you define either `vs' or `vi', you must also define `ve'.
+
+\1f
+File: termcap.info,  Node: Bell,  Next: Keypad,  Prev: Cursor Visibility,  Up: Capabilities
+
+Bell
+====
+
+   Here we describe commands to make the terminal ask for the user to
+pay attention to it.
+
+`bl'
+     String of commands to cause the terminal to make an audible sound.
+     If this capability is absent, the terminal has no way to make a
+     suitable sound.
+
+`vb'
+     String of commands to cause the screen to flash to attract
+     attention ("visible bell").  If this capability is absent, the
+     terminal has no way to do such a thing.
+
+\1f
+File: termcap.info,  Node: Keypad,  Next: Meta Key,  Prev: Bell,  Up: Capabilities
+
+Keypad and Function Keys
+========================
+
+   Many terminals have arrow and function keys that transmit specific
+character sequences to the computer.  Since the precise sequences used
+depend on the terminal, termcap defines capabilities used to say what
+the sequences are.  Unlike most termcap string-valued capabilities,
+these are not strings of commands to be sent to the terminal, rather
+strings that are received from the terminal.
+
+   Programs that expect to use keypad keys should check, initially, for
+a `ks' capability and send it, to make the keypad actually transmit.
+Such programs should also send the `ke' string when exiting.
+
+`ks'
+     String of commands to make the function keys transmit.  If this
+     capability is not provided, but the others in this section are,
+     programs may assume that the function keys always transmit.
+
+`ke'
+     String of commands to make the function keys work locally.  This
+     capability is provided only if `ks' is.
+
+`kl'
+     String of input characters sent by typing the left-arrow key.  If
+     this capability is missing, you cannot expect the terminal to have
+     a left-arrow key that transmits anything to the computer.
+
+`kr'
+     String of input characters sent by typing the right-arrow key.
+
+`ku'
+     String of input characters sent by typing the up-arrow key.
+
+`kd'
+     String of input characters sent by typing the down-arrow key.
+
+`kh'
+     String of input characters sent by typing the "home-position" key.
+
+`K1' ... `K5'
+     Strings of input characters sent by the five other keys in a 3-by-3
+     array that includes the arrow keys, if the keyboard has such a
+     3-by-3 array.  Note that one of these keys may be the
+     "home-position" key, in which case one of these capabilities will
+     have the same value as the `kh' key.
+
+`k0'
+     String of input characters sent by function key 10 (or 0, if the
+     terminal has one labeled 0).
+
+`k1' ... `k9'
+     Strings of input characters sent by function keys 1 through 9,
+     provided for those function keys that exist.
+
+`kn'
+     Number: the number of numbered function keys, if there are more
+     than 10.
+
+`l0' ... `l9'
+     Strings which are the labels appearing on the keyboard on the keys
+     described by the capabilities `k0' ... `l9'.  These capabilities
+     should be left undefined if the labels are `f0' or `f10' and `f1'
+     ... `f9'.
+
+`kH'
+     String of input characters sent by the "home down" key, if there is
+     one.
+
+`kb'
+     String of input characters sent by the "backspace" key, if there is
+     one.
+
+`ka'
+     String of input characters sent by the "clear all tabs" key, if
+     there is one.
+
+`kt'
+     String of input characters sent by the "clear tab stop this column"
+     key, if there is one.
+
+`kC'
+     String of input characters sent by the "clear screen" key, if
+     there is one.
+
+`kD'
+     String of input characters sent by the "delete character" key, if
+     there is one.
+
+`kL'
+     String of input characters sent by the "delete line" key, if there
+     is one.
+
+`kM'
+     String of input characters sent by the "exit insert mode" key, if
+     there is one.
+
+`kE'
+     String of input characters sent by the "clear to end of line" key,
+     if there is one.
+
+`kS'
+     String of input characters sent by the "clear to end of screen"
+     key, if there is one.
+
+`kI'
+     String of input characters sent by the "insert character" or "enter
+     insert mode" key, if there is one.
+
+`kA'
+     String of input characters sent by the "insert line" key, if there
+     is one.
+
+`kN'
+     String of input characters sent by the "next page" key, if there is
+     one.
+
+`kP'
+     String of input characters sent by the "previous page" key, if
+     there is one.
+
+`kF'
+     String of input characters sent by the "scroll forward" key, if
+     there is one.
+
+`kR'
+     String of input characters sent by the "scroll reverse" key, if
+     there is one.
+
+`kT'
+     String of input characters sent by the "set tab stop in this
+     column" key, if there is one.
+
+`ko'
+     String listing the other function keys the terminal has.  This is a
+     very obsolete way of describing the same information found in the
+     `kH' ... `kT' keys.  The string contains a list of two-character
+     termcap capability names, separated by commas.  The meaning is
+     that for each capability name listed, the terminal has a key which
+     sends the string which is the value of that capability.  For
+     example, the value `:ko=cl,ll,sf,sr:' says that the terminal has
+     four function keys which mean "clear screen", "home down", "scroll
+     forward" and "scroll reverse".
+
+\1f
+File: termcap.info,  Node: Meta Key,  Next: Initialization,  Prev: Keypad,  Up: Capabilities
+
+Meta Key
+========
+
+   A Meta key is a key on the keyboard that modifies each character you
+type by controlling the 0200 bit.  This bit is on if and only if the
+Meta key is held down when the character is typed.  Characters typed
+using the Meta key are called Meta characters.  Emacs uses Meta
+characters as editing commands.
+
+`km'
+     Flag whose presence means that the terminal has a Meta key.
+
+`mm'
+     String of commands to enable the functioning of the Meta key.
+
+`mo'
+     String of commands to disable the functioning of the Meta key.
+
+   If the terminal has `km' but does not have `mm' and `mo', it means
+that the Meta key always functions.  If it has `mm' and `mo', it means
+that the Meta key can be turned on or off.  Send the `mm' string to
+turn it on, and the `mo' string to turn it off.  I do not know why one
+would ever not want it to be on.
+
+\1f
+File: termcap.info,  Node: Initialization,  Next: Pad Specs,  Prev: Meta Key,  Up: Capabilities
+
+Initialization
+==============
+
+`ti'
+     String of commands to put the terminal into whatever special modes
+     are needed or appropriate for programs that move the cursor
+     nonsequentially around the screen.  Programs that use termcap to do
+     full-screen display should output this string when they start up.
+
+`te'
+     String of commands to undo what is done by the `ti' string.
+     Programs that output the `ti' string on entry should output this
+     string when they exit.
+
+`is'
+     String of commands to initialize the terminal for each login
+     session.
+
+`if'
+     String which is the name of a file containing the string of
+     commands to initialize the terminal for each session of use.
+     Normally `is' and `if' are not both used.
+
+`i1'
+`i3'
+     Two more strings of commands to initialize the terminal for each
+     login session.  The `i1' string (if defined) is output before `is'
+     or `if', and the `i3' string (if defined) is output after.
+
+     The reason for having three separate initialization strings is to
+     make it easier to define a group of related terminal types with
+     slightly different initializations.  Define two or three of the
+     strings in the basic type; then the other types can override one
+     or two of the strings.
+
+`rs'
+     String of commands to reset the terminal from any strange mode it
+     may be in.  Normally this includes the `is' string (or other
+     commands with the same effects) and more.  What would go in the
+     `rs' string but not in the `is' string are annoying or slow
+     commands to bring the terminal back from strange modes that nobody
+     would normally use.
+
+`it'
+     Numeric value, the initial spacing between hardware tab stop
+     columns when the terminal is powered up.  Programs to initialize
+     the terminal can use this to decide whether there is a need to set
+     the tab stops.  If the initial width is 8, well and good; if it is
+     not 8, then the tab stops should be set; if they cannot be set,
+     the kernel is told to convert tabs to spaces, and other programs
+     will observe this and do likewise.
+
+`ct'
+     String of commands to clear all tab stops.
+
+`st'
+     String of commands to set tab stop at current cursor column on all
+     lines.
+
+\1f
+File: termcap.info,  Node: Pad Specs,  Next: Status Line,  Prev: Initialization,  Up: Capabilities
+
+Padding Capabilities
+====================
+
+   There are two terminal capabilities that exist just to explain the
+proper way to obey the padding specifications in all the command string
+capabilities.  One, `pc', must be obeyed by all termcap-using programs.
+
+`pb'
+     Numeric value, the lowest baud rate at which padding is actually
+     needed.  Programs may check this and refrain from doing any
+     padding at lower speeds.
+
+`pc'
+     String of commands for padding.  The first character of this
+     string is to be used as the pad character, instead of using null
+     characters for padding.  If `pc' is not provided, use null
+     characters.  Every program that uses termcap must look up this
+     capability and use it to set the variable `PC' that is used by
+     `tputs'.  *Note Padding::.
+
+   Some termcap capabilities exist just to specify the amount of
+padding that the kernel should give to cursor motion commands used in
+ordinary sequential output.
+
+`dC'
+     Numeric value, the number of msec of padding needed for the
+     carriage-return character.
+
+`dN'
+     Numeric value, the number of msec of padding needed for the newline
+     (linefeed) character.
+
+`dB'
+     Numeric value, the number of msec of padding needed for the
+     backspace character.
+
+`dF'
+     Numeric value, the number of msec of padding needed for the
+     formfeed character.
+
+`dT'
+     Numeric value, the number of msec of padding needed for the tab
+     character.
+
+   In some systems, the kernel uses the above capabilities; in other
+systems, the kernel uses the paddings specified in the string
+capabilities `cr', `sf', `le', `ff' and `ta'.  Descriptions of
+terminals which require such padding should contain the `dC' ...  `dT'
+capabilities and also specify the appropriate padding in the
+corresponding string capabilities.  Since no modern terminals require
+padding for ordinary sequential output, you probably won't need to do
+either of these things.
+
+\1f
+File: termcap.info,  Node: Status Line,  Next: Half-Line,  Prev: Pad Specs,  Up: Capabilities
+
+Status Line
+===========
+
+   A "status line" is a line on the terminal that is not used for
+ordinary display output but instead used for a special message.  The
+intended use is for a continuously updated description of what the
+user's program is doing, and that is where the name "status line" comes
+from, but in fact it could be used for anything.  The distinguishing
+characteristic of a status line is that ordinary output to the terminal
+does not affect it; it changes only if the special status line commands
+of this section are used.
+
+`hs'
+     Flag whose presence means that the terminal has a status line.  If
+     a terminal description specifies that there is a status line, it
+     must provide the `ts' and `fs' capabilities.
+
+`ts'
+     String of commands to move the terminal cursor into the status
+     line.  Usually these commands must specifically record the old
+     cursor position for the sake of the `fs' string.
+
+`fs'
+     String of commands to move the cursor back from the status line to
+     its previous position (outside the status line).
+
+`es'
+     Flag whose presence means that other display commands work while
+     writing the status line.  In other words, one can clear parts of
+     it, insert or delete characters, move the cursor within it using
+     `ch' if there is a `ch' capability, enter and leave standout mode,
+     and so on.
+
+`ds'
+     String of commands to disable the display of the status line.  This
+     may be absent, if there is no way to disable the status line
+     display.
+
+`ws'
+     Numeric value, the width of the status line.  If this capability is
+     absent in a terminal that has a status line, it means the status
+     line is the same width as the other lines.
+
+     Note that the value of `ws' is sometimes as small as 8.
+
+\1f
+File: termcap.info,  Node: Half-Line,  Next: Printer,  Prev: Status Line,  Up: Capabilities
+
+Half-Line Motion
+================
+
+   Some terminals have commands for moving the cursor vertically by
+half-lines, useful for outputting subscripts and superscripts.  Mostly
+it is hardcopy terminals that have such features.
+
+`hu'
+     String of commands to move the cursor up half a line.  If the
+     terminal is a display, it is your responsibility to avoid moving
+     up past the top line; however, most likely the terminal that
+     supports this is a hardcopy terminal and there is nothing to be
+     concerned about.
+
+`hd'
+     String of commands to move the cursor down half a line.  If the
+     terminal is a display, it is your responsibility to avoid moving
+     down past the bottom line, etc.
+
+\1f
+File: termcap.info,  Node: Printer,  Prev: Half-Line,  Up: Capabilities
+
+Controlling Printers Attached to Terminals
+==========================================
+
+   Some terminals have attached hardcopy printer ports.  They may be
+able to copy the screen contents to the printer; they may also be able
+to redirect output to the printer.  Termcap does not have anything to
+tell the program whether the redirected output appears also on the
+screen; it does on some terminals but not all.
+
+`ps'
+     String of commands to cause the contents of the screen to be
+     printed.  If it is absent, the screen contents cannot be printed.
+
+`po'
+     String of commands to redirect further output to the printer.
+
+`pf'
+     String of commands to terminate redirection of output to the
+     printer.  This capability must be present in the description if
+     `po' is.
+
+`pO'
+     String of commands to redirect output to the printer for next N
+     characters of output, regardless of what they are.  Redirection
+     will end automatically after N characters of further output.  Until
+     then, nothing that is output can end redirection, not even the
+     `pf' string if there is one.  The number N should not be more than
+     255.
+
+     One use of this capability is to send non-text byte sequences
+     (such as bit-maps) to the printer.
+
+   Most terminals with printers do not support all of `ps', `po' and
+`pO'; any one or two of them may be supported.  To make a program that
+can send output to all kinds of printers, it is necessary to check for
+all three of these capabilities, choose the most convenient of the ones
+that are provided, and use it in its own appropriate fashion.
+
+\1f
+File: termcap.info,  Node: Summary,  Next: Var Index,  Prev: Capabilities,  Up: Top
+
+Summary of Capability Names
+***************************
+
+   Here are all the terminal capability names in alphabetical order
+with a brief description of each.  For cross references to their
+definitions, see the index of capability names (*note Cap Index::.).
+
+`ae'
+     String to turn off alternate character set mode.
+
+`al'
+     String to insert a blank line before the cursor.
+
+`AL'
+     String to insert N blank lines before the cursor.
+
+`am'
+     Flag: output to last column wraps cursor to next line.
+
+`as'
+     String to turn on alternate character set mode.like.
+
+`bc'
+     Very obsolete alternative name for the `le' capability.
+
+`bl'
+     String to sound the bell.
+
+`bs'
+     Obsolete flag: ASCII backspace may be used for leftward motion.
+
+`bt'
+     String to move the cursor left to the previous hardware tab stop
+     column.
+
+`bw'
+     Flag: `le' at left margin wraps to end of previous line.
+
+`CC'
+     String to change terminal's command character.
+
+`cd'
+     String to clear the line the cursor is on, and following lines.
+
+`ce'
+     String to clear from the cursor to the end of the line.
+
+`ch'
+     String to position the cursor at column C in the same line.
+
+`cl'
+     String to clear the entire screen and put cursor at upper left
+     corner.
+
+`cm'
+     String to position the cursor at line L, column C.
+
+`CM'
+     String to position the cursor at line L, column C, relative to
+     display memory.
+
+`co'
+     Number: width of the screen.
+
+`cr'
+     String to move cursor sideways to left margin.
+
+`cs'
+     String to set the scroll region.
+
+`cS'
+     Alternate form of string to set the scroll region.
+
+`ct'
+     String to clear all tab stops.
+
+`cv'
+     String to position the cursor at line L in the same column.
+
+`da'
+     Flag: data scrolled off top of screen may be scrolled back.
+
+`db'
+     Flag: data scrolled off bottom of screen may be scrolled back.
+
+`dB'
+     Obsolete number: msec of padding needed for the backspace
+     character.
+
+`dc'
+     String to delete one character position at the cursor.
+
+`dC'
+     Obsolete number: msec of padding needed for the carriage-return
+     character.
+
+`DC'
+     String to delete N characters starting at the cursor.
+
+`dF'
+     Obsolete number: msec of padding needed for the formfeed character.
+
+`dl'
+     String to delete the line the cursor is on.
+
+`DL'
+     String to delete N lines starting with the cursor's line.
+
+`dm'
+     String to enter delete mode.
+
+`dN'
+     Obsolete number: msec of padding needed for the newline character.
+
+`do'
+     String to move the cursor vertically down one line.
+
+`DO'
+     String to move cursor vertically down N lines.
+
+`ds'
+     String to disable the display of the status line.
+
+`dT'
+     Obsolete number: msec of padding needed for the tab character.
+
+`ec'
+     String of commands to clear N characters at cursor.
+
+`ed'
+     String to exit delete mode.
+
+`ei'
+     String to leave insert mode.
+
+`eo'
+     Flag: output of a space can erase an overstrike.
+
+`es'
+     Flag: other display commands work while writing the status line.
+
+`ff'
+     String to advance to the next page, for a hardcopy terminal.
+
+`fs'
+     String to move the cursor back from the status line to its
+     previous position (outside the status line).
+
+`gn'
+     Flag: this terminal type is generic, not real.
+
+`hc'
+     Flag: hardcopy terminal.
+
+`hd'
+     String to move the cursor down half a line.
+
+`ho'
+     String to position cursor at upper left corner.
+
+`hs'
+     Flag: the terminal has a status line.
+
+`hu'
+     String to move the cursor up half a line.
+
+`hz'
+     Flag: terminal cannot accept `~' as output.
+
+`i1'
+     String to initialize the terminal for each login session.
+
+`i3'
+     String to initialize the terminal for each login session.
+
+`ic'
+     String to insert one character position at the cursor.
+
+`IC'
+     String to insert N character positions at the cursor.
+
+`if'
+     String naming a file of commands to initialize the terminal.
+
+`im'
+     String to enter insert mode.
+
+`in'
+     Flag: outputting a space is different from moving over empty
+     positions.
+
+`ip'
+     String to output following an inserted character in insert mode.
+
+`is'
+     String to initialize the terminal for each login session.
+
+`it'
+     Number: initial spacing between hardware tab stop columns.
+
+`k0'
+     String of input sent by function key 0 or 10.
+
+`k1 ... k9'
+     Strings of input sent by function keys 1 through 9.
+
+`K1 ... K5'
+     Strings sent by the five other keys in 3-by-3 array with arrows.
+
+`ka'
+     String of input sent by the "clear all tabs" key.
+
+`kA'
+     String of input sent by the "insert line" key.
+
+`kb'
+     String of input sent by the "backspace" key.
+
+`kC'
+     String of input sent by the "clear screen" key.
+
+`kd'
+     String of input sent by typing the down-arrow key.
+
+`kD'
+     String of input sent by the "delete character" key.
+
+`ke'
+     String to make the function keys work locally.
+
+`kE'
+     String of input sent by the "clear to end of line" key.
+
+`kF'
+     String of input sent by the "scroll forward" key.
+
+`kh'
+     String of input sent by typing the "home-position" key.
+
+`kH'
+     String of input sent by the "home down" key.
+
+`kI'
+     String of input sent by the "insert character" or "enter insert
+     mode" key.
+
+`kl'
+     String of input sent by typing the left-arrow key.
+
+`kL'
+     String of input sent by the "delete line" key.
+
+`km'
+     Flag: the terminal has a Meta key.
+
+`kM'
+     String of input sent by the "exit insert mode" key.
+
+`kn'
+     Numeric value, the number of numbered function keys.
+
+`kN'
+     String of input sent by the "next page" key.
+
+`ko'
+     Very obsolete string listing the terminal's named function keys.
+
+`kP'
+     String of input sent by the "previous page" key.
+
+`kr'
+     String of input sent by typing the right-arrow key.
+
+`kR'
+     String of input sent by the "scroll reverse" key.
+
+`ks'
+     String to make the function keys transmit.
+
+`kS'
+     String of input sent by the "clear to end of screen" key.
+
+`kt'
+     String of input sent by the "clear tab stop this column" key.
+
+`kT'
+     String of input sent by the "set tab stop in this column" key.
+
+`ku'
+     String of input sent by typing the up-arrow key.
+
+`l0'
+     String on keyboard labelling function key 0 or 10.
+
+`l1 ... l9'
+     Strings on keyboard labelling function keys 1 through 9.
+
+`le'
+     String to move the cursor left one column.
+
+`LE'
+     String to move cursor left N columns.
+
+`li'
+     Number: height of the screen.
+
+`ll'
+     String to position cursor at lower left corner.
+
+`lm'
+     Number: lines of display memory.
+
+`mb'
+     String to enter blinking mode.
+
+`md'
+     String to enter double-bright mode.
+
+`me'
+     String to turn off all appearance modes
+
+`mh'
+     String to enter half-bright mode.
+
+`mi'
+     Flag: cursor motion in insert mode is safe.
+
+`mk'
+     String to enter invisible mode.
+
+`mm'
+     String to enable the functioning of the Meta key.
+
+`mo'
+     String to disable the functioning of the Meta key.
+
+`mp'
+     String to enter protected mode.
+
+`mr'
+     String to enter reverse-video mode.
+
+`ms'
+     Flag: cursor motion in standout mode is safe.
+
+`nc'
+     Obsolete flag: do not use ASCII carriage-return on this terminal.
+
+`nd'
+     String to move the cursor right one column.
+
+`nl'
+     Obsolete alternative name for the `do' and `sf' capabilities.
+
+`ns'
+     Flag: the terminal does not normally scroll for sequential output.
+
+`nw'
+     String to move to start of next line, possibly clearing rest of
+     old line.
+
+`os'
+     Flag: terminal can overstrike.
+
+`pb'
+     Number: the lowest baud rate at which padding is actually needed.
+
+`pc'
+     String containing character for padding.
+
+`pf'
+     String to terminate redirection of output to the printer.
+
+`po'
+     String to redirect further output to the printer.
+
+`pO'
+     String to redirect N characters ofoutput to the printer.
+
+`ps'
+     String to print the screen on the attached printer.
+
+`rc'
+     String to move to last saved cursor position.
+
+`RI'
+     String to move cursor right N columns.
+
+`rp'
+     String to output character C repeated N times.
+
+`rs'
+     String to reset the terminal from any strange modes.
+
+`sa'
+     String to turn on an arbitrary combination of appearance modes.
+
+`sc'
+     String to save the current cursor position.
+
+`se'
+     String to leave standout mode.
+
+`sf'
+     String to scroll the screen one line up.
+
+`SF'
+     String to scroll the screen N lines up.
+
+`sg'
+     Number: width of magic standout cookie.  Absent if magic cookies
+     are not used.
+
+`so'
+     String to enter standout mode.
+
+`sr'
+     String to scroll the screen one line down.
+
+`SR'
+     String to scroll the screen N line down.
+
+`st'
+     String to set tab stop at current cursor column on all lines.
+     programs.
+
+`ta'
+     String to move the cursor right to the next hardware tab stop
+     column.
+
+`te'
+     String to return terminal to settings for sequential output.
+
+`ti'
+     String to initialize terminal for random cursor motion.
+
+`ts'
+     String to move the terminal cursor into the status line.
+
+`uc'
+     String to underline one character and move cursor right.
+
+`ue'
+     String to turn off underline mode
+
+`ug'
+     Number: width of underlining magic cookie.  Absent if underlining
+     doesn't use magic cookies.
+
+`ul'
+     Flag: underline by overstriking with an underscore.
+
+`up'
+     String to move the cursor vertically up one line.
+
+`UP'
+     String to move cursor vertically up N lines.
+
+`us'
+     String to turn on underline mode
+
+`vb'
+     String to make the screen flash.
+
+`ve'
+     String to return the cursor to normal.
+
+`vi'
+     String to make the cursor invisible.
+
+`vs'
+     String to enhance the cursor.
+
+`wi'
+     String to set the terminal output screen window.
+
+`ws'
+     Number: the width of the status line.
+
+`xb'
+     Flag: superbee terminal.
+
+`xn'
+     Flag: cursor wraps in a strange way.
+
+`xs'
+     Flag: clearing a line is the only way to clear the appearance
+     modes of positions in that line (or, only way to remove magic
+     cookies on that line).
+
+`xt'
+     Flag: Teleray 1061; several strange characteristics.
+
+\1f
+File: termcap.info,  Node: Var Index,  Next: Cap Index,  Prev: Summary,  Up: Top
+
+Variable and Function Index
+***************************
+
+* Menu:
+
+* BC:                                   tgoto.
+* ospeed:                               Output Padding.
+* PC:                                   Output Padding.
+* tgetent:                              Find.
+* tgetflag:                             Interrogate.
+* tgetnum:                              Interrogate.
+* tgetstr:                              Interrogate.
+* tgoto:                                tgoto.
+* tparam:                               tparam.
+* tputs:                                Output Padding.
+* UP:                                   tgoto.
+
diff --git a/lib/termcap/grot/termcap.info-4 b/lib/termcap/grot/termcap.info-4
new file mode 100644 (file)
index 0000000..21dd81c
--- /dev/null
@@ -0,0 +1,218 @@
+This is Info file /home/gd/gnu/termcap/termcap.info, produced by
+Makeinfo-1.52 from the input file /home/gd/gnu/termcap/termcap.texi.
+
+   This file documents the termcap library of the GNU system.
+
+   Copyright (C) 1988 Free Software Foundation, Inc.
+
+   Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+   Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+   Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+\1f
+File: termcap.info,  Node: Cap Index,  Next: Index,  Prev: Var Index,  Up: Top
+
+Capability Index
+****************
+
+* Menu:
+
+* ae:                                   Standout.
+* AL:                                   Insdel Line.
+* al:                                   Insdel Line.
+* am:                                   Wrapping.
+* as:                                   Standout.
+* bc:                                   Cursor Motion.
+* bl:                                   Bell.
+* bs:                                   Cursor Motion.
+* bt:                                   Cursor Motion.
+* bw:                                   Cursor Motion.
+* CC:                                   Basic.
+* cd:                                   Clearing.
+* ce:                                   Clearing.
+* ch:                                   Cursor Motion.
+* cl:                                   Clearing.
+* CM:                                   Cursor Motion.
+* cm:                                   Cursor Motion.
+* co:                                   Screen Size.
+* cr:                                   Cursor Motion.
+* cS:                                   Scrolling.
+* cs:                                   Scrolling.
+* ct:                                   Initialization.
+* cv:                                   Cursor Motion.
+* da:                                   Scrolling.
+* dB:                                   Pad Specs.
+* db:                                   Scrolling.
+* dC:                                   Pad Specs.
+* DC:                                   Insdel Char.
+* dc:                                   Insdel Char.
+* dF:                                   Pad Specs.
+* dl:                                   Insdel Line.
+* DL:                                   Insdel Line.
+* dm:                                   Insdel Char.
+* dN:                                   Pad Specs.
+* DO:                                   Cursor Motion.
+* do:                                   Cursor Motion.
+* ds:                                   Status Line.
+* dT:                                   Pad Specs.
+* ec:                                   Clearing.
+* ed:                                   Insdel Char.
+* ei:                                   Insdel Char.
+* eo:                                   Basic.
+* es:                                   Status Line.
+* ff:                                   Cursor Motion.
+* fs:                                   Status Line.
+* gn:                                   Basic.
+* hc:                                   Basic.
+* hd:                                   Half-Line.
+* ho:                                   Cursor Motion.
+* hs:                                   Status Line.
+* hu:                                   Half-Line.
+* hz:                                   Basic.
+* i1:                                   Initialization.
+* i3:                                   Initialization.
+* IC:                                   Insdel Char.
+* ic:                                   Insdel Char.
+* if:                                   Initialization.
+* im:                                   Insdel Char.
+* in:                                   Insdel Char.
+* ip:                                   Insdel Char.
+* is:                                   Initialization.
+* it:                                   Initialization.
+* K1...K5:                              Keypad.
+* k1...k9:                              Keypad.
+* kA...kT:                              Keypad.
+* ka...ku:                              Keypad.
+* km:                                   Meta Key.
+* l0...l9:                              Keypad.
+* le:                                   Cursor Motion.
+* LE:                                   Cursor Motion.
+* li:                                   Screen Size.
+* ll:                                   Cursor Motion.
+* lm:                                   Scrolling.
+* mb:                                   Standout.
+* md:                                   Standout.
+* me:                                   Standout.
+* mh:                                   Standout.
+* mi:                                   Insdel Char.
+* mk:                                   Standout.
+* mm:                                   Meta Key.
+* mo:                                   Meta Key.
+* mp:                                   Standout.
+* mr:                                   Standout.
+* ms:                                   Standout.
+* ms:                                   Underlining.
+* nc:                                   Cursor Motion.
+* nd:                                   Cursor Motion.
+* nl:                                   Cursor Motion.
+* ns:                                   Scrolling.
+* nw:                                   Cursor Motion.
+* os:                                   Basic.
+* pb:                                   Pad Specs.
+* pc:                                   Pad Specs.
+* pf:                                   Printer.
+* pO:                                   Printer.
+* po:                                   Printer.
+* ps:                                   Printer.
+* rc:                                   Cursor Motion.
+* RI:                                   Cursor Motion.
+* rp:                                   Basic.
+* rs:                                   Initialization.
+* sa:                                   Standout.
+* sc:                                   Cursor Motion.
+* se:                                   Standout.
+* sf:                                   Scrolling.
+* SF:                                   Scrolling.
+* sg:                                   Standout.
+* so:                                   Standout.
+* sr:                                   Scrolling.
+* SR:                                   Scrolling.
+* st:                                   Initialization.
+* ta:                                   Cursor Motion.
+* te:                                   Initialization.
+* ti:                                   Initialization.
+* ts:                                   Status Line.
+* uc:                                   Underlining.
+* ue:                                   Underlining.
+* ug:                                   Underlining.
+* ul:                                   Underlining.
+* up:                                   Cursor Motion.
+* UP:                                   Cursor Motion.
+* us:                                   Underlining.
+* vb:                                   Bell.
+* ve:                                   Cursor Visibility.
+* vi:                                   Cursor Visibility.
+* vs:                                   Cursor Visibility.
+* wi:                                   Windows.
+* ws:                                   Status Line.
+* xb:                                   Basic.
+* xn:                                   Wrapping.
+* xs:                                   Standout.
+* xt:                                   Standout.
+* xt:                                   Cursor Motion.
+
+\1f
+File: termcap.info,  Node: Index,  Prev: Cap Index,  Up: Top
+
+Concept Index
+*************
+
+* Menu:
+
+* %:                                    Encode Parameters.
+* appearance modes:                     Standout.
+* bell:                                 Bell.
+* clearing the screen:                  Clearing.
+* command character:                    Basic.
+* cursor motion:                        Cursor Motion.
+* delete character:                     Insdel Char.
+* delete line:                          Insdel Line.
+* delete mode:                          Insdel Char.
+* description format:                   Format.
+* erasing:                              Clearing.
+* generic terminal type:                Basic.
+* home position:                        Cursor Motion.
+* inheritance:                          Inheriting.
+* initialization:                       Initialization.
+* insert character:                     Insdel Char.
+* insert line:                          Insdel Line.
+* insert mode:                          Insdel Char.
+* line speed:                           Output Padding.
+* magic cookie:                         Standout.
+* meta key:                             Meta Key.
+* names of terminal types:              Naming.
+* overstrike:                           Basic.
+* padding:                              Pad Specs.
+* padding:                              Padding.
+* parameters:                           Parameters.
+* printer:                              Printer.
+* repeat output:                        Basic.
+* reset:                                Initialization.
+* screen size:                          Screen Size.
+* screen size:                          Screen Size.
+* screen size:                          Naming.
+* scrolling:                            Scrolling.
+* standout:                             Standout.
+* status line:                          Status Line.
+* Superbee:                             Basic.
+* tab stops:                            Initialization.
+* termcap:                              Introduction.
+* terminal flags (kernel):              Initialize.
+* underlining:                          Underlining.
+* visibility:                           Cursor Visibility.
+* visible bell:                         Bell.
+* window:                               Windows.
+* wrapping:                             Naming.
+* wrapping:                             Wrapping.
+
+
diff --git a/lib/termcap/grot/termcap.texi b/lib/termcap/grot/termcap.texi
new file mode 100644 (file)
index 0000000..d991838
--- /dev/null
@@ -0,0 +1,3603 @@
+\input texinfo  @c -*-texinfo-*-
+@setfilename termcap
+@settitle The Termcap Library
+@smallbook
+
+@ifinfo
+This file documents the termcap library of the GNU system.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@setchapternewpage odd
+
+@c @shorttitlepage The Termcap Manual
+
+@titlepage
+@ignore
+@sp 6
+@center @titlefont{Termcap}
+@sp 1
+@center The Termcap Library and Data Base
+@sp 4
+@center Second Edition
+@sp 1
+@center December 1992
+@sp 5
+@center Richard M. Stallman
+@sp 1
+@center Free Software Foundation
+@end ignore
+
+@c Real title page
+@title The Termcap Manual
+@subtitle The Termcap Library and Data Base
+@subtitle Second Edition
+@subtitle December 1992
+@author Richard M. Stallman
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1988 Free Software Foundation, Inc.
+
+Published by the Free Software Foundation
+(675 Mass Ave, Cambridge MA 02139).
+Printed copies are available for $10 each.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@sp 2
+Cover art by Etienne Suvasa.
+@end titlepage
+@page
+
+@synindex vr fn
+
+@node Top, Introduction, (dir), (dir)
+
+@menu
+* Introduction::  What is termcap?  Why this manual?
+* Library::     The termcap library functions.
+* Data Base::   What terminal descriptions in @file{/etc/termcap} look like.
+* Capabilities::  Definitions of the individual terminal capabilities:
+                 how to write them in descriptions, and how to use
+                 their values to do display updating.
+* Summary::     Brief table of capability names and their meanings.
+* Var Index::   Index of C functions and variables.
+* Cap Index::   Index of termcap capabilities.
+* Index::       Concept index.
+
+ --- The Detailed Node Listing ---
+
+The Termcap Library
+
+* Preparation::  Preparing to use the termcap library.
+* Find::        Finding the description of the terminal being used.
+* Interrogate::  Interrogating the description for particular capabilities.
+* Initialize::  Initialization for output using termcap.
+* Padding::     Outputting padding.
+* Parameters::  Encoding parameters such as cursor positions.
+
+Padding
+
+* Why Pad::     Explanation of padding.
+* Not Enough::  When there is not enough padding.
+* Describe Padding::  The data base says how much padding a terminal needs.
+* Output Padding::    Using @code{tputs} to output the needed padding.
+
+Filling In Parameters
+
+* Encode Parameters::  The language for encoding parameters.
+* Using Parameters::   Outputting a string command with parameters.
+
+Sending Display Commands with Parameters
+
+* tparam::      The general case, for GNU termcap only.
+* tgoto::       The special case of cursor motion.
+
+The Format of the Data Base
+
+* Format::      Overall format of a terminal description.
+* Capability Format::  Format of capabilities within a description.
+* Naming::      Naming conventions for terminal types.
+* Inheriting::  Inheriting part of a description from
+a related terminal type.
+* Changing::    When changes in the data base take effect.
+
+Definitions of the Terminal Capabilities
+
+* Basic::       Basic characteristics.
+* Screen Size::  Screen size, and what happens when it changes.
+* Cursor Motion::  Various ways to move the cursor.
+* Wrapping::    What happens if you write a character in the last column.
+* Scrolling::   Pushing text up and down on the screen.
+* Windows::     Limiting the part of the window that output affects.
+* Clearing::    Erasing one or many lines.
+* Insdel Line::  Making new blank lines in mid-screen; deleting lines.
+* Insdel Char::  Inserting and deleting characters within a line.
+* Standout::    Highlighting some of the text.
+* Underlining::  Underlining some of the text.
+* Cursor Visibility::  Making the cursor more or less easy to spot.
+* Bell::        Attracts user's attention; not localized on the screen.
+* Keypad::      Recognizing when function keys or arrows are typed.
+* Meta Key::    @key{META} acts like an extra shift key.
+* Initialization::  Commands used to initialize or reset the terminal.
+* Pad Specs::   Info for the kernel on how much padding is needed.
+* Status Line::  A status line displays ``background'' information.
+* Half-Line::   Moving by half-lines, for superscripts and subscripts.
+* Printer::     Controlling auxiliary printers of display terminals.
+@end menu
+
+@node Introduction, Library, Top, Top
+@unnumbered Introduction
+
+@cindex termcap
+@dfn{Termcap} is a library and data base that enables programs to use
+display terminals in a terminal-independent manner.  It originated in
+Berkeley Unix.
+
+The termcap data base describes the capabilities of hundreds of different
+display terminals in great detail.  Some examples of the information
+recorded for a terminal could include how many columns wide it is, what
+string to send to move the cursor to an arbitrary position (including how
+to encode the row and column numbers), how to scroll the screen up one or
+several lines, and how much padding is needed for such a scrolling
+operation.
+
+The termcap library is provided for easy access this data base in programs
+that want to do terminal-independent character-based display output.
+
+This manual describes the GNU version of the termcap library, which has
+some extensions over the Unix version.  All the extensions are identified
+as such, so this manual also tells you how to use the Unix termcap.
+
+The GNU version of the termcap library is available free as source code,
+for use in free programs, and runs on Unix and VMS systems (at least).  You
+can find it in the GNU Emacs distribution in the files @file{termcap.c} and
+@file{tparam.c}.
+
+This manual was written for the GNU project, whose goal is to develop a
+complete free operating system upward-compatible with Unix for user
+programs.  The project is approximately two thirds complete.  For more
+information on the GNU project, including the GNU Emacs editor and the
+mostly-portable optimizing C compiler, send one dollar to
+
+@display
+Free Software Foundation
+675 Mass Ave
+Cambridge, MA 02139
+@end display
+
+@node Library, Data Base, Introduction, Top
+@chapter The Termcap Library
+
+The termcap library is the application programmer's interface to the
+termcap data base.  It contains functions for the following purposes:
+
+@itemize @bullet
+@item
+Finding the description of the user's terminal type (@code{tgetent}).
+
+@item
+Interrogating the description for information on various topics
+(@code{tgetnum}, @code{tgetflag}, @code{tgetstr}).
+
+@item
+Computing and performing padding (@code{tputs}).
+
+@item
+Encoding numeric parameters such as cursor positions into the
+terminal-specific form required for display commands (@code{tparam},
+@code{tgoto}).
+@end itemize
+
+@menu
+* Preparation::  Preparing to use the termcap library.
+* Find::        Finding the description of the terminal being used.
+* Interrogate::  Interrogating the description for particular capabilities.
+* Initialize::  Initialization for output using termcap.
+* Padding::     Outputting padding.
+* Parameters::  Encoding parameters such as cursor positions.
+@end menu
+
+@node Preparation, Find,  , Library
+@section Preparing to Use the Termcap Library
+
+To use the termcap library in a program, you need two kinds of preparation:
+
+@itemize @bullet
+@item
+The compiler needs declarations of the functions and variables in the
+library.
+
+On GNU systems, it suffices to include the header file
+@file{termcap.h} in each source file that uses these functions and
+variables.@refill
+
+On Unix systems, there is often no such header file.  Then you must
+explictly declare the variables as external.  You can do likewise for
+the functions, or let them be implicitly declared and cast their
+values from type @code{int} to the appropriate type.
+
+We illustrate the declarations of the individual termcap library
+functions with ANSI C prototypes because they show how to pass the
+arguments.  If you are not using the GNU C compiler, you probably
+cannot use function prototypes, so omit the argument types and names
+from your declarations.
+
+@item
+The linker needs to search the library.  Usually either
+@samp{-ltermcap} or @samp{-ltermlib} as an argument when linking will
+do this.@refill
+@end itemize
+
+@node Find, Interrogate, Preparation, Library
+@section Finding a Terminal Description: @code{tgetent}
+
+@findex tgetent
+An application program that is going to use termcap must first look up the
+description of the terminal type in use.  This is done by calling
+@code{tgetent}, whose declaration in ANSI Standard C looks like:
+
+@example
+int tgetent (char *@var{buffer}, char *@var{termtype});
+@end example
+
+@noindent
+This function finds the description and remembers it internally so that
+you can interrogate it about specific terminal capabilities
+(@pxref{Interrogate}).
+
+The argument @var{termtype} is a string which is the name for the type of
+terminal to look up.  Usually you would obtain this from the environment
+variable @code{TERM} using @code{getenv ("TERM")}.
+
+If you are using the GNU version of termcap, you can alternatively ask
+@code{tgetent} to allocate enough space.  Pass a null pointer for
+@var{buffer}, and @code{tgetent} itself allocates the storage using
+@code{malloc}.  In this case the returned value on success is the address
+of the storage, cast to @code{int}.  But normally there is no need for you
+to look at the address.  Do not free the storage yourself.@refill
+
+With the Unix version of termcap, you must allocate space for the
+description yourself and pass the address of the space as the argument
+@var{buffer}.  There is no way you can tell how much space is needed, so
+the convention is to allocate a buffer 2048 characters long and assume that
+is enough.  (Formerly the convention was to allocate 1024 characters and
+assume that was enough.  But one day, for one kind of terminal, that was
+not enough.)
+
+No matter how the space to store the description has been obtained,
+termcap records its address internally for use when you later interrogate
+the description with @code{tgetnum}, @code{tgetstr} or @code{tgetflag}.  If
+the buffer was allocated by termcap, it will be freed by termcap too if you
+call @code{tgetent} again.  If the buffer was provided by you, you must
+make sure that its contents remain unchanged for as long as you still plan
+to interrogate the description.@refill
+
+The return value of @code{tgetent} is @minus{}1 if there is some difficulty
+accessing the data base of terminal types, 0 if the data base is accessible
+but the specified type is not defined in it, and some other value
+otherwise.
+
+Here is how you might use the function @code{tgetent}:
+
+@smallexample
+#ifdef unix
+static char term_buffer[2048];
+#else
+#define term_buffer 0
+#endif
+
+init_terminal_data ()
+@{
+  char *termtype = getenv ("TERM");
+  int success;
+
+  if (termtype == 0)
+    fatal ("Specify a terminal type with `setenv TERM <yourtype>'.\n");
+
+  success = tgetent (term_buffer, termtype);
+  if (success < 0)
+    fatal ("Could not access the termcap data base.\n");
+  if (success == 0)
+    fatal ("Terminal type `%s' is not defined.\n", termtype);
+@}
+@end smallexample
+
+@noindent
+Here we assume the function @code{fatal} prints an error message and exits.
+
+If the environment variable @code{TERMCAP} is defined, its value is used to
+override the terminal type data base.  The function @code{tgetent} checks
+the value of @code{TERMCAP} automatically.  If the value starts with
+@samp{/} then it is taken as a file name to use as the data base file,
+instead of @file{/etc/termcap} which is the standard data base.  If the
+value does not start with @samp{/} then it is itself used as the terminal
+description, provided that the terminal type @var{termtype} is among the
+types it claims to apply to.  @xref{Data Base}, for information on the
+format of a terminal description.@refill
+
+@node Interrogate, Initialize, Find, Library
+@section Interrogating the Terminal Description
+
+Each piece of information recorded in a terminal description is called a
+@dfn{capability}.  Each defined terminal capability has a two-letter code
+name and a specific meaning.  For example, the number of columns is named
+@samp{co}.  @xref{Capabilities}, for definitions of all the standard
+capability names.
+
+Once you have found the proper terminal description with @code{tgetent}
+(@pxref{Find}), your application program must @dfn{interrogate} it for
+various terminal capabilities.  You must specify the two-letter code of
+the capability whose value you seek.
+
+Capability values can be numeric, boolean (capability is either present or
+absent) or strings.  Any particular capability always has the same value
+type; for example, @samp{co} always has a numeric value, while @samp{am}
+(automatic wrap at margin) is always a flag, and @samp{cm} (cursor motion
+command) always has a string value.  The documentation of each capability
+says which type of value it has.@refill
+
+There are three functions to use to get the value of a capability,
+depending on the type of value the capability has.  Here are their
+declarations in ANSI C:
+
+@findex tgetnum
+@findex tgetflag
+@findex tgetstr
+@example
+int tgetnum (char *@var{name});
+int tgetflag (char *@var{name});
+char *tgetstr (char *@var{name}, char **@var{area});
+@end example
+
+@table @code
+@item tgetnum
+Use @code{tgetnum} to get a capability value that is numeric.  The
+argument @var{name} is the two-letter code name of the capability.  If
+the capability is present, @code{tgetnum} returns the numeric value
+(which is nonnegative).  If the capability is not mentioned in the
+terminal description, @code{tgetnum} returns @minus{}1.
+
+@item tgetflag
+Use @code{tgetflag} to get a boolean value.  If the capability
+@var{name} is present in the terminal description, @code{tgetflag}
+returns 1; otherwise, it returns 0.
+
+@item tgetstr
+Use @code{tgetstr} to get a string value.  It returns a pointer to a
+string which is the capability value, or a null pointer if the
+capability is not present in the terminal description.
+
+There are two ways @code{tgetstr} can find space to store the string value:
+
+@itemize @bullet
+@item
+You can ask @code{tgetstr} to allocate the space.  Pass a null
+pointer for the argument @var{area}, and @code{tgetstr} will use
+@code{malloc} to allocate storage big enough for the value.
+Termcap will never free this storage or refer to it again; you
+should free it when you are finished with it.
+
+This method is more robust, since there is no need to guess how
+much space is needed.  But it is supported only by the GNU
+termcap library.
+
+@item
+You can provide the space.  Provide for the argument @var{area} the
+address of a pointer variable of type @code{char *}.  Before calling
+@code{tgetstr}, initialize the variable to point at available space.
+Then @code{tgetstr} will store the string value in that space and will
+increment the pointer variable to point after the space that has been
+used.  You can use the same pointer variable for many calls to
+@code{tgetstr}.
+
+There is no way to determine how much space is needed for a single
+string, and no way for you to prevent or handle overflow of the area
+you have provided.  However, you can be sure that the total size of
+all the string values you will obtain from the terminal description is
+no greater than the size of the description (unless you get the same
+capability twice).  You can determine that size with @code{strlen} on
+the buffer you provided to @code{tgetent}.  See below for an example.
+
+Providing the space yourself is the only method supported by the Unix
+version of termcap.
+@end itemize
+@end table
+
+Note that you do not have to specify a terminal type or terminal
+description for the interrogation functions.  They automatically use the
+description found by the most recent call to @code{tgetent}.
+
+Here is an example of interrogating a terminal description for various
+capabilities, with conditionals to select between the Unix and GNU methods
+of providing buffer space.
+
+@example
+char *tgetstr ();
+
+char *cl_string, *cm_string;
+int height;
+int width;
+int auto_wrap;
+
+char PC;   /* For tputs.  */
+char *BC;  /* For tgoto.  */
+char *UP;
+
+interrogate_terminal ()
+@{
+#ifdef UNIX
+  /* Here we assume that an explicit term_buffer
+     was provided to tgetent.  */
+  char *buffer
+    = (char *) malloc (strlen (term_buffer));
+#define BUFFADDR &buffer
+#else
+#define BUFFADDR 0
+#endif
+
+  char *temp;
+
+  /* Extract information we will use.  */
+  cl_string = tgetstr ("cl", BUFFADDR);
+  cm_string = tgetstr ("cm", BUFFADDR);
+  auto_wrap = tgetflag ("am");
+  height = tgetnum ("li");
+  width = tgetnum ("co");
+
+  /* Extract information that termcap functions use.  */
+  temp = tgetstr ("pc", BUFFADDR);
+  PC = temp ? *temp : 0;
+  BC = tgetstr ("le", BUFFADDR);
+  UP = tgetstr ("up", BUFFADDR);
+@}
+@end example
+
+@noindent
+@xref{Padding}, for information on the variable @code{PC}.  @xref{Using
+Parameters}, for information on @code{UP} and @code{BC}.
+
+@node Initialize, Padding, Interrogate, Library
+@section Initialization for Use of Termcap
+@cindex terminal flags (kernel)
+
+Before starting to output commands to a terminal using termcap,
+an application program should do two things:
+
+@itemize @bullet
+@item
+Initialize various global variables which termcap library output
+functions refer to.  These include @code{PC} and @code{ospeed} for
+padding (@pxref{Output Padding}) and @code{UP} and @code{BC} for
+cursor motion (@pxref{tgoto}).@refill
+
+@item
+Tell the kernel to turn off alteration and padding of horizontal-tab
+characters sent to the terminal.
+@end itemize
+
+To turn off output processing in Berkeley Unix you would use @code{ioctl}
+with code @code{TIOCLSET} to set the bit named @code{LLITOUT}, and clear
+the bits @code{ANYDELAY} using @code{TIOCSETN}.  In POSIX or System V, you
+must clear the bit named @code{OPOST}.  Refer to the system documentation
+for details.@refill
+
+If you do not set the terminal flags properly, some older terminals will
+not work.  This is because their commands may contain the characters that
+normally signify newline, carriage return and horizontal tab---characters
+which the kernel thinks it ought to modify before output.
+
+When you change the kernel's terminal flags, you must arrange to restore
+them to their normal state when your program exits.  This implies that the
+program must catch fatal signals such as @code{SIGQUIT} and @code{SIGINT}
+and restore the old terminal flags before actually terminating.
+
+Modern terminals' commands do not use these special characters, so if you
+do not care about problems with old terminals, you can leave the kernel's
+terminal flags unaltered.
+
+@node Padding, Parameters, Initialize, Library
+@section Padding
+@cindex padding
+
+@dfn{Padding} means outputting null characters following a terminal display
+command that takes a long time to execute.  The terminal description says
+which commands require padding and how much; the function @code{tputs},
+described below, outputs a terminal command while extracting from it the
+padding information, and then outputs the padding that is necessary.
+
+@menu
+* Why Pad::     Explanation of padding.
+* Not Enough::  When there is not enough padding.
+* Describe Padding::  The data base says how much padding a terminal needs.
+* Output Padding::  Using @code{tputs} to output the needed padding.
+@end menu
+
+@node Why Pad, Not Enough,  , Padding
+@subsection Why Pad, and How
+
+Most types of terminal have commands that take longer to execute than they
+do to send over a high-speed line.  For example, clearing the screen may
+take 20msec once the entire command is received.  During that time, on a
+9600 bps line, the terminal could receive about 20 additional output
+characters while still busy clearing the screen.  Every terminal has a
+certain amount of buffering capacity to remember output characters that
+cannot be processed yet, but too many slow commands in a row can cause the
+buffer to fill up.  Then any additional output that cannot be processed
+immediately will be lost.
+
+To avoid this problem, we normally follow each display command with enough
+useless charaters (usually null characters) to fill up the time that the
+display command needs to execute.  This does the job if the terminal throws
+away null characters without using up space in the buffer (which most
+terminals do).  If enough padding is used, no output can ever be lost.  The
+right amount of padding avoids loss of output without slowing down
+operation, since the time used to transmit padding is time that nothing
+else could be done.
+
+The number of padding characters needed for an operation depends on the
+line speed.  In fact, it is proportional to the line speed.  A 9600 baud
+line transmits about one character per msec, so the clear screen command in
+the example above would need about 20 characters of padding.  At 1200 baud,
+however, only about 3 characters of padding are needed to fill up 20msec.
+
+@node Not Enough, Describe Padding, Why Pad, Padding
+@subsection When There Is Not Enough Padding
+
+There are several common manifestations of insufficient padding.
+
+@itemize @bullet
+@item
+Emacs displays @samp{I-search: ^Q-} at the bottom of the screen.
+
+This means that the terminal thought its buffer was getting full of
+display commands, so it tried to tell the computer to stop sending
+any.
+
+@item
+The screen is garbled intermittently, or the details of garbling vary
+when you repeat the action.  (A garbled screen could be due to a
+command which is simply incorrect, or to user option in the terminal
+which doesn't match the assumptions of the terminal description, but
+this usually leads to reproducible failure.)
+
+This means that the buffer did get full, and some commands were lost.
+Many changeable factors can change which ones are lost.
+
+@item
+Screen is garbled at high output speeds but not at low speeds.
+Padding problems nearly always go away at low speeds, usually even at
+1200 baud.
+
+This means that a high enough speed permits commands to arrive faster
+than they can be executed.
+@end itemize
+
+Although any obscure command on an obscure terminal might lack padding,
+in practice problems arise most often from the clearing commands
+@samp{cl} and @samp{cd} (@pxref{Clearing}), the scrolling commands
+@samp{sf} and @samp{sr} (@pxref{Scrolling}), and the line insert/delete
+commands @samp{al} and @samp{dl} (@pxref{Insdel Line}).
+
+Occasionally the terminal description fails to define @samp{sf} and some
+programs will use @samp{do} instead, so you may get a problem with
+@samp{do}.  If so, first define @samp{sf} just like @samp{do}, then
+add some padding to @samp{sf}.
+
+The best strategy is to add a lot of padding at first, perhaps 200 msec.
+This is much more than enough; in fact, it should cause a visible slowdown.
+(If you don't see a slowdown, the change has not taken effect;
+@pxref{Changing}.)  If this makes the problem go away, you have found the
+right place to add padding; now reduce the amount until the problem comes
+back, then increase it again.  If the problem remains, either it is in some
+other capability or it is not a matter of padding at all.
+
+Keep in mind that on many terminals the correct padding for insert/delete
+line or for scrolling is cursor-position dependent.  If you get problems
+from scrolling a large region of the screen but not from scrolling a small
+part (just a few lines moving), it may mean that fixed padding should be
+replaced with position-dependent padding.
+
+@node Describe Padding, Output Padding, Not Enough, Padding
+@subsection Specifying Padding in a Terminal Description
+
+In the terminal description, the amount of padding required by each display
+command is recorded as a sequence of digits at the front of the command.
+These digits specify the padding time in milliseconds (msec).  They can be
+followed optionally by a decimal point and one more digit, which is a
+number of tenths of msec.
+
+Sometimes the padding needed by a command depends on the cursor position.
+For example, the time taken by an ``insert line'' command is usually
+proportional to the number of lines that need to be moved down or cleared.
+An asterisk (@samp{*}) following the padding time says that the time
+should be multiplied by the number of screen lines affected by the command.
+
+@example
+:al=1.3*\E[L:
+@end example
+
+@noindent
+is used to describe the ``insert line'' command for a certain terminal.
+The padding required is 1.3 msec per line affected.  The command itself is
+@samp{@key{ESC} [ L}.
+
+The padding time specified in this way tells @code{tputs} how many pad
+characters to output.  @xref{Output Padding}.
+
+Two special capability values affect padding for all commands.  These are
+the @samp{pc} and @samp{pb}.  The variable @samp{pc} specifies the
+character to pad with, and @samp{pb} the speed below which no padding is
+needed.  The defaults for these variables, a null character and 0,
+are correct for most terminals.  @xref{Pad Specs}.
+
+@node Output Padding,  , Describe Padding, Padding
+@subsection Performing Padding with @code{tputs}
+@cindex line speed
+
+@findex tputs
+Use the termcap function @code{tputs} to output a string containing an
+optional padding spec of the form described above (@pxref{Describe
+Padding}).  The function @code{tputs} strips off and decodes the padding
+spec, outputs the rest of the string, and then outputs the appropriate
+padding.  Here is its declaration in ANSI C:
+
+@example
+char PC;
+short ospeed;
+
+int tputs (char *@var{string}, int @var{nlines}, int (*@var{outfun}) ());
+@end example
+
+Here @var{string} is the string (including padding spec) to be output;
+@var{nlines} is the number of lines affected by the operation, which is
+used to multiply the amount of padding if the padding spec ends with a
+@samp{*}.  Finally, @var{outfun} is a function (such as @code{fputchar})
+that is called to output each character.  When actually called,
+@var{outfun} should expect one argument, a character.
+
+@vindex ospeed
+@vindex PC
+The operation of @code{tputs} is controlled by two global variables,
+@code{ospeed} and @code{PC}.  The value of @code{ospeed} is supposed to be
+the terminal output speed, encoded as in the @code{ioctl} system call which
+gets the speed information.  This is needed to compute the number of
+padding characters.  The value of @code{PC} is the character used for
+padding.
+
+You are responsible for storing suitable values into these variables before
+using @code{tputs}.  The value stored into the @code{PC} variable should be
+taken from the @samp{pc} capability in the terminal description (@pxref{Pad
+Specs}).  Store zero in @code{PC} if there is no @samp{pc}
+capability.@refill
+
+The argument @var{nlines} requires some thought.  Normally, it should be
+the number of lines whose contents will be cleared or moved by the command.
+For cursor motion commands, or commands that do editing within one line,
+use the value 1.  For most commands that affect multiple lines, such as
+@samp{al} (insert a line) and @samp{cd} (clear from the cursor to the end
+of the screen), @var{nlines} should be the screen height minus the current
+vertical position (origin 0).  For multiple insert and scroll commands such
+as @samp{AL} (insert multiple lines), that same value for @var{nlines} is
+correct; the number of lines being inserted is @i{not} correct.@refill
+
+If a ``scroll window'' feature is used to reduce the number of lines
+affected by a command, the value of @var{nlines} should take this into
+account.  This is because the delay time required depends on how much work
+the terminal has to do, and the scroll window feature reduces the work.
+@xref{Scrolling}.
+
+Commands such as @samp{ic} and @samp{dc} (insert or delete characters) are
+problematical because the padding needed by these commands is proportional
+to the number of characters affected, which is the number of columns from
+the cursor to the end of the line.  It would be nice to have a way to
+specify such a dependence, and there is no need for dependence on vertical
+position in these commands, so it is an obvious idea to say that for these
+commands @var{nlines} should really be the number of columns affected.
+However, the definition of termcap clearly says that @var{nlines} is always
+the number of lines affected, even in this case, where it is always 1.  It
+is not easy to change this rule now, because too many programs and terminal
+descriptions have been written to follow it.
+
+Because @var{nlines} is always 1 for the @samp{ic} and @samp{dc} strings,
+there is no reason for them to use @samp{*}, but some of them do.  These
+should be corrected by deleting the @samp{*}.  If, some day, such entries
+have disappeared, it may be possible to change to a more useful convention
+for the @var{nlines} argument for these operations without breaking any
+programs.
+
+@node Parameters,  , Padding, Library
+@section Filling In Parameters
+@cindex parameters
+
+Some terminal control strings require numeric @dfn{parameters}.  For
+example, when you move the cursor, you need to say what horizontal and
+vertical positions to move it to.  The value of the terminal's @samp{cm}
+capability, which says how to move the cursor, cannot simply be a string of
+characters; it must say how to express the cursor position numbers and
+where to put them within the command.
+
+The specifications of termcap include conventions as to which string-valued
+capabilities require parameters, how many parameters, and what the
+parameters mean; for example, it defines the @samp{cm} string to take
+two parameters, the vertical and horizontal positions, with 0,0 being the
+upper left corner.  These conventions are described where the individual
+commands are documented.
+
+Termcap also defines a language used within the capability definition for
+specifying how and where to encode the parameters for output.  This language
+uses character sequences starting with @samp{%}.  (This is the same idea as
+@code{printf}, but the details are different.)  The language for parameter
+encoding is described in this section.
+
+A program that is doing display output calls the functions @code{tparam} or
+@code{tgoto} to encode parameters according to the specifications.  These
+functions produce a string containing the actual commands to be output (as
+well a padding spec which must be processed with @code{tputs};
+@pxref{Padding}).
+
+@menu
+* Encode Parameters::  The language for encoding parameters.
+* Using Parameters::  Outputting a string command with parameters.
+@end menu
+
+@node Encode Parameters, Using Parameters,  , Parameters
+@subsection Describing the Encoding
+@cindex %
+
+A terminal command string that requires parameters contains special
+character sequences starting with @samp{%} to say how to encode the
+parameters.  These sequences control the actions of @code{tparam} and
+@code{tgoto}.
+
+The parameters values passed to @code{tparam} or @code{tgoto} are
+considered to form a vector.  A pointer into this vector determines
+the next parameter to be processed.  Some of the @samp{%}-sequences
+encode one parameter and advance the pointer to the next parameter.
+Other @samp{%}-sequences alter the pointer or alter the parameter
+values without generating output.
+
+For example, the @samp{cm} string for a standard ANSI terminal is written
+as @samp{\E[%i%d;%dH}.  (@samp{\E} stands for @key{ESC}.)  @samp{cm} by
+convention always requires two parameters, the vertical and horizontal goal
+positions, so this string specifies the encoding of two parameters.  Here
+@samp{%i} increments the two values supplied, and each @samp{%d} encodes
+one of the values in decimal.  If the cursor position values 20,58 are
+encoded with this string, the result is @samp{\E[21;59H}.
+
+First, here are the @samp{%}-sequences that generate output.  Except for
+@samp{%%}, each of them encodes one parameter and advances the pointer
+to the following parameter.
+
+@table @samp
+@item %%
+Output a single @samp{%}.  This is the only way to represent a literal
+@samp{%} in a terminal command with parameters.  @samp{%%} does not
+use up a parameter.
+
+@item %d
+As in @code{printf}, output the next parameter in decimal.
+
+@item %2
+Like @samp{%02d} in @code{printf}: output the next parameter in
+decimal, and always use at least two digits.
+
+@item %3
+Like @samp{%03d} in @code{printf}: output the next parameter in
+decimal, and always use at least three digits.  Note that @samp{%4}
+and so on are @emph{not} defined.
+
+@item %.
+Output the next parameter as a single character whose ASCII code is
+the parameter value.  Like @samp{%c} in @code{printf}.
+
+@item %+@var{char}
+Add the next parameter to the character @var{char}, and output the
+resulting character.  For example, @samp{%+ } represents 0 as a space,
+1 as @samp{!}, etc.
+@end table
+
+The following @samp{%}-sequences specify alteration of the parameters
+(their values, or their order) rather than encoding a parameter for output.
+They generate no output; they are used only for their side effects
+on the parameters.  Also, they do not advance the ``next parameter'' pointer
+except as explicitly stated.  Only @samp{%i}, @samp{%r} and @samp{%>} are
+defined in standard Unix termcap.  The others are GNU extensions.@refill
+
+@table @samp
+@item %i
+Increment the next two parameters.  This is used for terminals that
+expect cursor positions in origin 1.  For example, @samp{%i%d,%d} would
+output two parameters with @samp{1} for 0, @samp{2} for 1, etc.
+
+@item %r
+Interchange the next two parameters.  This is used for terminals whose
+cursor positioning command expects the horizontal position first.
+
+@item %s
+Skip the next parameter.  Do not output anything.
+
+@item %b
+Back up one parameter.  The last parameter used will become once again
+the next parameter to be output, and the next output command will use
+it.  Using @samp{%b} more than once, you can back up any number of
+parameters, and you can refer to each parameter any number of times.
+
+@item %>@var{c1}@var{c2}
+Conditionally increment the next parameter.  Here @var{c1} and
+@var{c2} are characters which stand for their ASCII codes as numbers.
+If the next parameter is greater than the ASCII code of @var{c1}, the
+ASCII code of @var{c2} is added to it.@refill
+
+@item %a @var{op} @var{type} @var{pos}
+Perform arithmetic on the next parameter, do not use it up, and do not
+output anything.  Here @var{op} specifies the arithmetic operation,
+while @var{type} and @var{pos} together specify the other operand.
+
+Spaces are used above to separate the operands for clarity; the spaces
+don't appear in the data base, where this sequence is exactly five
+characters long.
+
+The character @var{op} says what kind of arithmetic operation to
+perform.  It can be any of these characters:
+
+@table @samp
+@item =
+assign a value to the next parameter, ignoring its old value.
+The new value comes from the other operand.
+
+@item +
+add the other operand to the next parameter.
+
+@item -
+subtract the other operand from the next parameter.
+
+@item *
+multiply the next parameter by the other operand.
+
+@item /
+divide the next parameter by the other operand.
+@end table
+
+The ``other operand'' may be another parameter's value or a constant;
+the character @var{type} says which.  It can be:
+
+@table @samp
+@item p
+Use another parameter.  The character @var{pos} says which
+parameter to use.  Subtract 64 from its ASCII code to get the
+position of the desired parameter relative to this one.  Thus,
+the character @samp{A} as @var{pos} means the parameter after the
+next one; the character @samp{?} means the parameter before the
+next one.
+
+@item c
+Use a constant value.  The character @var{pos} specifies the
+value of the constant.  The 0200 bit is cleared out, so that 0200
+can be used to represent zero.
+@end table
+@end table
+
+The following @samp{%}-sequences are special purpose hacks to compensate
+for the weird designs of obscure terminals.  They modify the next parameter
+or the next two parameters but do not generate output and do not use up any
+parameters.  @samp{%m} is a GNU extension; the others are defined in
+standard Unix termcap.
+
+@table @samp
+@item %n
+Exclusive-or the next parameter with 0140, and likewise the parameter
+after next.
+
+@item %m
+Complement all the bits of the next parameter and the parameter after next.
+
+@item %B
+Encode the next parameter in BCD.  It alters the value of the
+parameter by adding six times the quotient of the parameter by ten.
+Here is a C statement that shows how the new value is computed:
+
+@example
+@var{parm} = (@var{parm} / 10) * 16 + @var{parm} % 10;
+@end example
+
+@item %D
+Transform the next parameter as needed by Delta Data terminals.
+This involves subtracting twice the remainder of the parameter by 16.
+
+@example
+@var{parm} -= 2 * (@var{parm} % 16);
+@end example
+@end table
+
+@node Using Parameters,  , Encode Parameters, Parameters
+@subsection Sending Display Commands with Parameters
+
+The termcap library functions @code{tparam} and @code{tgoto} serve as the
+analog of @code{printf} for terminal string parameters.  The newer function
+@code{tparam} is a GNU extension, more general but missing from Unix
+termcap.  The original parameter-encoding function is @code{tgoto}, which
+is preferable for cursor motion.
+
+@menu
+* tparam::      The general case, for GNU termcap only.
+* tgoto::       The special case of cursor motion.
+@end menu
+
+@node tparam, tgoto,  , Using Parameters
+@subsubsection @code{tparam}
+
+@findex tparam
+The function @code{tparam} can encode display commands with any number of
+parameters and allows you to specify the buffer space.  It is the preferred
+function for encoding parameters for all but the @samp{cm} capability.  Its
+ANSI C declaration is as follows:
+
+@smallexample
+char *tparam (char *@var{ctlstring}, char *@var{buffer}, int @var{size}, int @var{parm1},...)
+@end smallexample
+
+The arguments are a control string @var{ctlstring} (the value of a terminal
+capability, presumably), an output buffer @var{buffer} and @var{size}, and
+any number of integer parameters to be encoded.  The effect of
+@code{tparam} is to copy the control string into the buffer, encoding
+parameters according to the @samp{%} sequences in the control string.
+
+You describe the output buffer by its address, @var{buffer}, and its size
+in bytes, @var{size}.  If the buffer is not big enough for the data to be
+stored in it, @code{tparam} calls @code{malloc} to get a larger buffer.  In
+either case, @code{tparam} returns the address of the buffer it ultimately
+uses.  If the value equals @var{buffer}, your original buffer was used.
+Otherwise, a new buffer was allocated, and you must free it after you are
+done with printing the results.  If you pass zero for @var{size} and
+@var{buffer}, @code{tparam} always allocates the space with @code{malloc}.
+
+All capabilities that require parameters also have the ability to specify
+padding, so you should use @code{tputs} to output the string produced by
+@code{tparam}.  @xref{Padding}.  Here is an example.
+
+@example
+@{
+char *buf;
+char buffer[40];
+
+buf = tparam (command, buffer, 40, parm);
+tputs (buf, 1, fputchar);
+if (buf != buffer)
+free (buf);
+@}
+@end example
+
+If a parameter whose value is zero is encoded with @samp{%.}-style
+encoding, the result is a null character, which will confuse @code{tputs}.
+This would be a serious problem, but luckily @samp{%.} encoding is used
+only by a few old models of terminal, and only for the @samp{cm}
+capability.  To solve the problem, use @code{tgoto} rather than
+@code{tparam} to encode the @samp{cm} capability.@refill
+
+@node tgoto,  , tparam, Using Parameters
+@subsubsection @code{tgoto}
+
+@findex tgoto
+The special case of cursor motion is handled by @code{tgoto}.  There
+are two reasons why you might choose to use @code{tgoto}:
+
+@itemize @bullet
+@item
+For Unix compatibility, because Unix termcap does not have @code{tparam}.
+
+@item
+For the @samp{cm} capability, since @code{tgoto} has a special feature
+to avoid problems with null characters, tabs and newlines on certain old
+terminal types that use @samp{%.} encoding for that capability.
+@end itemize
+
+Here is how @code{tgoto} might be declared in ANSI C:
+
+@example
+char *tgoto (char *@var{cstring}, int @var{hpos}, int @var{vpos})
+@end example
+
+There are three arguments, the terminal description's @samp{cm} string and
+the two cursor position numbers; @code{tgoto} computes the parametrized
+string in an internal static buffer and returns the address of that buffer.
+The next time you use @code{tgoto} the same buffer will be reused.
+
+@vindex UP
+@vindex BC
+Parameters encoded with @samp{%.} encoding can generate null characters,
+tabs or newlines.  These might cause trouble: the null character because
+@code{tputs} would think that was the end of the string, the tab because
+the kernel or other software might expand it into spaces, and the newline
+becaue the kernel might add a carriage-return, or padding characters
+normally used for a newline.  To prevent such problems, @code{tgoto} is
+careful to avoid these characters.  Here is how this works: if the target
+cursor position value is such as to cause a problem (that is to say, zero,
+nine or ten), @code{tgoto} increments it by one, then compensates by
+appending a string to move the cursor back or up one position.
+
+The compensation strings to use for moving back or up are found in global
+variables named @code{BC} and @code{UP}.  These are actual external C
+variables with upper case names; they are declared @code{char *}.  It is up
+to you to store suitable values in them, normally obtained from the
+@samp{le} and @samp{up} terminal capabilities in the terminal description
+with @code{tgetstr}.  Alternatively, if these two variables are both zero,
+the feature of avoiding nulls, tabs and newlines is turned off.
+
+It is safe to use @code{tgoto} for commands other than @samp{cm} only if
+you have stored zero in @code{BC} and @code{UP}.
+
+Note that @code{tgoto} reverses the order of its operands: the horizontal
+position comes before the vertical position in the arguments to
+@code{tgoto}, even though the vertical position comes before the horizontal
+in the parameters of the @samp{cm} string.  If you use @code{tgoto} with a
+command such as @samp{AL} that takes one parameter, you must pass the
+parameter to @code{tgoto} as the ``vertical position''.@refill
+
+@node Data Base, Capabilities, Library, Top
+@chapter The Format of the Data Base
+
+The termcap data base of terminal descriptions is stored in the file
+@file{/etc/termcap}.  It contains terminal descriptions, blank lines, and
+comments.
+
+A terminal description starts with one or more names for the terminal type.
+The information in the description is a series of @dfn{capability names}
+and values.  The capability names have standard meanings
+(@pxref{Capabilities}) and their values describe the terminal.
+
+@menu
+* Format::      Overall format of a terminal description.
+* Capability Format::  Format of capabilities within a description.
+* Naming::      Naming conventions for terminal types.
+* Inheriting::  Inheriting part of a description from
+a related terminal type.
+* Changing::    When changes in the data base take effect.
+@end menu
+
+@node Format, Capability Format,  , Data Base
+@section Terminal Description Format
+@cindex description format
+
+Aside from comments (lines starting with @samp{#}, which are ignored), each
+nonblank line in the termcap data base is a terminal description.
+A terminal description is nominally a single line, but it can be split
+into multiple lines by inserting the two characters @samp{\ newline}.
+This sequence is ignored wherever it appears in a description.
+
+The preferred way to split the description is between capabilities: insert
+the four characters @samp{: \ newline tab} immediately before any colon.
+This allows each sub-line to start with some indentation.  This works
+because, after the @samp{\ newline} are ignored, the result is @samp{: tab
+:}; the first colon ends the preceding capability and the second colon
+starts the next capability.  If you split with @samp{\ newline} alone, you
+may not add any indentation after them.
+
+Here is a real example of a terminal description:
+
+@example
+dw|vt52|DEC vt52:\
+        :cr=^M:do=^J:nl=^J:bl=^G:\
+        :le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:\
+        :cm=\EY%+ %+ :co#80:li#24:\
+        :nd=\EC:ta=^I:pt:sr=\EI:up=\EA:\
+        :ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:
+@end example
+
+Each terminal description begins with several names for the terminal type.
+The names are separated by @samp{|} characters, and a colon ends the last
+name.  The first name should be two characters long; it exists only for the
+sake of very old Unix systems and is never used in modern systems.  The
+last name should be a fully verbose name such as ``DEC vt52'' or ``Ann
+Arbor Ambassador with 48 lines''.  The other names should include whatever
+the user ought to be able to specify to get this terminal type, such as
+@samp{vt52} or @samp{aaa-48}.  @xref{Naming}, for information on how to
+choose terminal type names.
+
+After the terminal type names come the terminal capabilities, separated by
+colons and with a colon after the last one.  Each capability has a
+two-letter name, such as @samp{cm} for ``cursor motion string'' or @samp{li}
+for ``number of display lines''.
+
+@node Capability Format, Naming, Format, Data Base
+@section Writing the Capabilities
+
+There are three kinds of capabilities: flags, numbers, and strings.  Each
+kind has its own way of being written in the description.  Each defined
+capability has by convention a particular kind of value; for example,
+@samp{li} always has a numeric value and @samp{cm} always a string value.
+
+A flag capability is thought of as having a boolean value: the value is
+true if the capability is present, false if not.  When the capability is
+present, just write its name between two colons.
+
+A numeric capability has a value which is a nonnegative number.  Write the
+capability name, a @samp{#}, and the number, between two colons.  For
+example, @samp{@dots{}:li#48:@dots{}} is how you specify the @samp{li}
+capability for 48 lines.@refill
+
+A string-valued capability has a value which is a sequence of characters.
+Usually these are the characters used to perform some display operation.
+Write the capability name, a @samp{=}, and the characters of the value,
+between two colons.  For example, @samp{@dots{}:cm=\E[%i%d;%dH:@dots{}} is
+how the cursor motion command for a standard ANSI terminal would be
+specified.@refill
+
+Special characters in the string value can be expressed using
+@samp{\}-escape sequences as in C; in addition, @samp{\E} stands for
+@key{ESC}.  @samp{^} is also a kind of escape character; @samp{^} followed
+by @var{char} stands for the control-equivalent of @var{char}.  Thus,
+@samp{^a} stands for the character control-a, just like @samp{\001}.
+@samp{\} and @samp{^} themselves can be represented as @samp{\\} and
+@samp{\^}.@refill
+
+To include a colon in the string, you must write @samp{\072}.  You might
+ask, ``Why can't @samp{\:} be used to represent a colon?''  The reason is
+that the interrogation functions do not count slashes while looking for a
+capability.  Even if @samp{:ce=ab\:cd:} were interpreted as giving the
+@samp{ce} capability the value @samp{ab:cd}, it would also appear to define
+@samp{cd} as a flag.
+
+The string value will often contain digits at the front to specify padding
+(@pxref{Padding}) and/or @samp{%}-sequences within to specify how to encode
+parameters (@pxref{Parameters}).  Although these things are not to be
+output literally to the terminal, they are considered part of the value of
+the capability.  They are special only when the string value is processed
+by @code{tputs}, @code{tparam} or @code{tgoto}.  By contrast, @samp{\} and
+@samp{^} are considered part of the syntax for specifying the characters
+in the string.
+
+Let's look at the VT52 example again:
+
+@example
+dw|vt52|DEC vt52:\
+        :cr=^M:do=^J:nl=^J:bl=^G:\
+        :le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:\
+        :cm=\EY%+ %+ :co#80:li#24:\     
+        :nd=\EC:ta=^I:pt:sr=\EI:up=\EA:\
+        :ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:
+@end example
+
+Here we see the numeric-valued capabilities @samp{co} and @samp{li}, the
+flags @samp{bs} and @samp{pt}, and many string-valued capabilities.  Most
+of the strings start with @key{ESC} represented as @samp{\E}.  The rest
+contain control characters represented using @samp{^}.  The meanings of the
+individual capabilities are defined elsewhere (@pxref{Capabilities}).
+
+@node Naming, Inheriting, Capability Format, Data Base
+@section Terminal Type Name Conventions
+@cindex names of terminal types
+
+There are conventions for choosing names of terminal types.  For one thing,
+all letters should be in lower case.  The terminal type for a terminal in
+its most usual or most fundamental mode of operation should not have a
+hyphen in it.
+
+If the same terminal has other modes of operation which require
+different terminal descriptions, these variant descriptions are given
+names made by adding suffixes with hyphens.  Such alternate descriptions
+are used for two reasons:
+
+@itemize @bullet
+@item
+When the terminal has a switch that changes its behavior.  Since the
+computer cannot tell how the switch is set, the user must tell the
+computer by choosing the appropriate terminal type name.
+
+@cindex wrapping
+For example, the VT-100 has a setup flag that controls whether the
+cursor wraps at the right margin.  If this flag is set to ``wrap'',
+you must use the terminal type @samp{vt100-am}.  Otherwise you must
+use @samp{vt100-nam}.  Plain @samp{vt100} is defined as a synonym for
+either @samp{vt100-am} or @samp{vt100-nam} depending on the
+preferences of the local site.@refill
+
+The standard suffix @samp{-am} stands for ``automatic margins''.
+
+@item
+To give the user a choice in how to use the terminal.  This is done
+when the terminal has a switch that the computer normally controls.
+
+@cindex screen size
+For example, the Ann Arbor Ambassador can be configured with many
+screen sizes ranging from 20 to 60 lines.  Fewer lines make bigger
+characters but more lines let you see more of what you are editing.
+As a result, users have different preferences.  Therefore, termcap
+provides terminal types for many screen sizes.  If you choose type
+@samp{aaa-30}, the terminal will be configured to use 30 lines; if you
+choose @samp{aaa-48}, 48 lines will be used, and so on.
+@end itemize
+
+Here is a list of standard suffixes and their conventional meanings:
+
+@table @samp
+@item -w
+Short for ``wide''.  This is a mode that gives the terminal more
+columns than usual.  This is normally a user option.
+
+@item -am
+``Automatic margins''.  This is an alternate description for use when
+the terminal's margin-wrap switch is on; it contains the @samp{am}
+flag.  The implication is that normally the switch is off and the
+usual description for the terminal says that the switch is off.
+
+@item -nam
+``No automatic margins''.  The opposite of @samp{-am}, this names an
+alternative description which lacks the @samp{am} flag.  This implies
+that the terminal is normally operated with the margin-wrap switch
+turned on, and the normal description of the terminal says so.
+
+@item -na
+``No arrows''.  This terminal description initializes the terminal to
+keep its arrow keys in local mode.  This is a user option.
+
+@item -rv
+``Reverse video''.  This terminal description causes text output for
+normal video to appear as reverse, and text output for reverse video
+to come out as normal.  Often this description differs from the usual
+one by interchanging the two strings which turn reverse video on and
+off.@refill
+
+This is a user option; you can choose either the ``reverse video''
+variant terminal type or the normal terminal type, and termcap will
+obey.
+
+@item -s
+``Status''.  Says to enable use of a status line which ordinary output
+does not touch (@pxref{Status Line}).
+
+Some terminals have a special line that is used only as a status line.
+For these terminals, there is no need for an @samp{-s} variant; the
+status line commands should be defined by default.  On other
+terminals, enabling a status line means removing one screen line from
+ordinary use and reducing the effective screen height.  For these
+terminals, the user can choose the @samp{-s} variant type to request
+use of a status line.
+
+@item -@var{nlines}
+Says to operate with @var{nlines} lines on the screen, for terminals
+such as the Ambassador which provide this as an option.  Normally this
+is a user option; by choosing the terminal type, you control how many
+lines termcap will use.
+
+@item -@var{npages}p
+Says that the terminal has @var{npages} pages worth of screen memory,
+for terminals where this is a hardware option.
+
+@item -unk
+Says that description is not for direct use, but only for reference in
+@samp{tc} capabilities.  Such a description is a kind of subroutine,
+because it describes the common characteristics of several variant
+descriptions that would use other suffixes in place of @samp{-unk}.
+@end table
+
+@node Inheriting, Changing, Naming, Data Base
+@section Inheriting from Related Descriptions
+
+@cindex inheritance
+When two terminal descriptions are similar, their identical parts do not
+need to be given twice.  Instead, one of the two can be defined in terms of
+the other, using the @samp{tc} capability.  We say that one description
+@dfn{refers to} the other, or @dfn{inherits from} the other.
+
+The @samp{tc} capability must be the last one in the terminal description,
+and its value is a string which is the name of another terminal type which
+is referred to.  For example,
+
+@example
+N9|aaa|ambassador|aaa-30|ann arbor ambassador/30 lines:\
+        :ti=\E[2J\E[30;0;0;30p:\
+        :te=\E[60;0;0;30p\E[30;1H\E[J:\
+        :li#30:tc=aaa-unk:
+@end example
+
+@noindent
+defines the terminal type @samp{aaa-30} (also known as plain @samp{aaa}) in
+terms of @samp{aaa-unk}, which defines everything about the Ambassador that
+is independent of screen height.  The types @samp{aaa-36}, @samp{aaa-48}
+and so on for other screen heights are likewise defined to inherit from
+@samp{aaa-unk}.
+
+The capabilities overridden by @samp{aaa-30} include @samp{li}, which says
+how many lines there are, and @samp{ti} and @samp{te}, which configure the
+terminal to use that many lines.
+
+The effective terminal description for type @samp{aaa} consists of the text
+shown above followed by the text of the description of @samp{aaa-unk}.  The
+@samp{tc} capability is handled automatically by @code{tgetent}, which
+finds the description thus referenced and combines the two descriptions
+(@pxref{Find}).  Therefore, only the implementor of the terminal
+descriptions needs to think about using @samp{tc}.  Users and application
+programmers do not need to be concerned with it.
+
+Since the reference terminal description is used last, capabilities
+specified in the referring description override any specifications of the
+same capabilities in the reference description.
+
+The referring description can cancel out a capability without specifying
+any new value for it by means of a special trick.  Write the capability in
+the referring description, with the character @samp{@@} after the capability
+name, as follows:
+
+@smallexample
+NZ|aaa-30-nam|ann arbor ambassador/30 lines/no automatic-margins:\
+        :am@@:tc=aaa-30:
+@end smallexample
+
+@node Changing,  , Inheriting, Data Base
+@section When Changes in the Data Base Take Effect
+
+Each application program must read the terminal description from the
+data base, so a change in the data base is effective for all jobs started
+after the change is made.
+
+The change will usually have no effect on a job that have been in existence
+since before the change. The program probably read the terminal description
+once, when it was started, and is continuing to use what it read then.
+If the program does not have a feature for reexamining the data base, then
+you will need to run it again (probably killing the old job).
+
+If the description in use is coming from the @code{TERMCAP} environment
+variable, then the data base file is effectively overridden, and changes in
+it will have no effect until you change the @code{TERMCAP} variable as
+well.  For example, some users' @file{.login} files automatically copy the
+terminal description into @code{TERMCAP} to speed startup of applications.
+If you have done this, you will need to change the @code{TERMCAP} variable
+to make the changed data base take effect.
+
+@node Capabilities, Summary, Data Base, Top
+@chapter Definitions of the Terminal Capabilities
+
+This section is divided into many subsections, each for one aspect of
+use of display terminals.  For writing a display program, you usually need
+only check the subsections for the operations you want to use.  For writing
+a terminal description, you must read each subsection and fill in the
+capabilities described there.
+
+String capabilities that are display commands may require numeric
+parameters (@pxref{Parameters}).  Most such capabilities do not use
+parameters.  When a capability requires parameters, this is explicitly
+stated at the beginning of its definition.  In simple cases, the first or
+second sentence of the definition mentions all the parameters, in the order
+they should be given, using a name
+@iftex
+in italics
+@end iftex
+@ifinfo
+in upper case
+@end ifinfo
+for each one.  For example, the @samp{rp} capability is a command that
+requires two parameters; its definition begins as follows:
+
+@quotation
+String of commands to output a graphic character @var{c}, repeated @var{n}
+times.
+@end quotation
+
+In complex cases or when there are many parameters, they are described
+explicitly.
+
+When a capability is described as obsolete, this means that programs should
+not be written to look for it, but terminal descriptions should still be
+written to provide it.
+
+When a capability is described as very obsolete, this means that it should
+be omitted from terminal descriptions as well.
+
+@menu
+* Basic::       Basic characteristics.
+* Screen Size::  Screen size, and what happens when it changes.
+* Cursor Motion::  Various ways to move the cursor.
+* Wrapping::    What happens if you write a character in the last column.
+* Scrolling::   Pushing text up and down on the screen.
+* Windows::     Limiting the part of the window that output affects.
+* Clearing::    Erasing one or many lines.
+* Insdel Line::  Making new blank lines in mid-screen; deleting lines.
+* Insdel Char::  Inserting and deleting characters within a line.
+* Standout::    Highlighting some of the text.
+* Underlining::  Underlining some of the text.
+* Cursor Visibility::  Making the cursor more or less easy to spot.
+* Bell::        Attracts user's attention; not localized on the screen.
+* Keypad::      Recognizing when function keys or arrows are typed.
+* Meta Key::    @key{META} acts like an extra shift key.
+* Initialization::  Commands used to initialize or reset the terminal.
+* Pad Specs::   Info for the kernel on how much padding is needed.
+* Status Line::  A status line displays ``background'' information.
+* Half-Line::   Moving by half-lines, for superscripts and subscripts.
+* Printer::     Controlling auxiliary printers of display terminals.
+@end menu
+
+@node Basic, Screen Size,  , Capabilities
+@section Basic Characteristics
+
+This section documents the capabilities that describe the basic and
+nature of the terminal, and also those that are relevant to the output
+of graphic characters.
+
+@table @samp
+@item os
+@kindex os
+@cindex overstrike
+Flag whose presence means that the terminal can overstrike.  This
+means that outputting a graphic character does not erase whatever was
+present in the same character position before.  The terminals that can
+overstrike include printing terminals, storage tubes (all obsolete
+nowadays), and many bit-map displays.
+
+@item eo
+@kindex eo
+Flag whose presence means that outputting a space erases a character
+position even if the terminal supports overstriking.  If this flag is
+not present and overstriking is supported, output of a space has no
+effect except to move the cursor.
+
+(On terminals that do not support overstriking, you can always assume
+that outputting a space at a position erases whatever character was
+previously displayed there.)
+
+@item gn
+@kindex gn
+@cindex generic terminal type
+Flag whose presence means that this terminal type is a generic type
+which does not really describe any particular terminal.  Generic types
+are intended for use as the default type assigned when the user
+connects to the system, with the intention that the user should
+specify what type he really has.  One example of a generic type
+is the type @samp{network}.
+
+Since the generic type cannot say how to do anything interesting with
+the terminal, termcap-using programs will always find that the
+terminal is too weak to be supported if the user has failed to specify
+a real terminal type in place of the generic one.  The @samp{gn} flag
+directs these programs to use a different error message: ``You have
+not specified your real terminal type'', rather than ``Your terminal
+is not powerful enough to be used''.
+
+@item hc
+@kindex hc
+Flag whose presence means this is a hardcopy terminal.
+
+@item rp
+@kindex rp
+@cindex repeat output
+String of commands to output a graphic character @var{c}, repeated @var{n}
+times.  The first parameter value is the ASCII code for the desired
+character, and the second parameter is the number of times to repeat the
+character.  Often this command requires padding proportional to the 
+number of times the character is repeated.  This effect can be had by
+using parameter arithmetic with @samp{%}-sequences to compute the
+amount of padding, then generating the result as a number at the front
+of the string so that @code{tputs} will treat it as padding.
+
+@item hz
+@kindex hz
+Flag whose presence means that the ASCII character @samp{~} cannot be
+output on this terminal because it is used for display commands.
+
+Programs handle this flag by checking all text to be output and
+replacing each @samp{~} with some other character(s).  If this is not
+done, the screen will be thoroughly garbled.
+
+The old Hazeltine terminals that required such treatment are probably
+very rare today, so you might as well not bother to support this flag.
+
+@item CC
+@kindex CC
+@cindex command character
+String whose presence means the terminal has a settable command
+character.  The value of the string is the default command character
+(which is usually @key{ESC}).
+
+All the strings of commands in the terminal description should be
+written to use the default command character.  If you are writing an
+application program that changes the command character, use the
+@samp{CC} capability to figure out how to translate all the display
+commands to work with the new command character.
+
+Most programs have no reason to look at the @samp{CC} capability.
+
+@item xb
+@kindex xb
+@cindex Superbee
+Flag whose presence identifies Superbee terminals which are unable to
+transmit the characters @key{ESC} and @kbd{Control-C}.  Programs which
+support this flag are supposed to check the input for the code sequences
+sent by the @key{F1} and @key{F2} keys, and pretend that @key{ESC}
+or @kbd{Control-C} (respectively) had been read.  But this flag is
+obsolete, and not worth supporting.
+@end table
+
+@node Screen Size, Cursor Motion, Basic, Capabilities
+@section Screen Size
+@cindex screen size
+
+A terminal description has two capabilities, @samp{co} and @samp{li},
+that describe the screen size in columns and lines.  But there is more
+to the question of screen size than this.
+
+On some operating systems the ``screen'' is really a window and the
+effective width can vary.  On some of these systems, @code{tgetnum}
+uses the actual width of the window to decide what value to return for
+the @samp{co} capability, overriding what is actually written in the
+terminal description.  On other systems, it is up to the application
+program to check the actual window width using a system call.  For
+example, on BSD 4.3 systems, the system call @code{ioctl} with code
+@code{TIOCGWINSZ} will tell you the current screen size.
+
+On all window systems, termcap is powerless to advise the application
+program if the user resizes the window.  Application programs must
+deal with this possibility in a system-dependent fashion.  On some
+systems the C shell handles part of the problem by detecting changes
+in window size and setting the @code{TERMCAP} environment variable
+appropriately.  This takes care of application programs that are
+started subsequently.  It does not help application programs already
+running.
+
+On some systems, including BSD 4.3, all programs using a terminal get
+a signal named @code{SIGWINCH} whenever the screen size changes.
+Programs that use termcap should handle this signal by using
+@code{ioctl TIOCGWINSZ} to learn the new screen size.
+
+@table @samp
+@item co
+@kindex co
+@cindex screen size
+Numeric value, the width of the screen in character positions.  Even
+hardcopy terminals normally have a @samp{co} capability.
+
+@item li
+@kindex li
+Numeric value, the height of the screen in lines.
+@end table
+
+@node Cursor Motion, Wrapping, Screen Size, Capabilities
+@section Cursor Motion
+@cindex cursor motion
+
+Termcap assumes that the terminal has a @dfn{cursor}, a spot on the screen
+where a visible mark is displayed, and that most display commands take
+effect at the position of the cursor.  It follows that moving the cursor
+to a specified location is very important.
+
+There are many terminal capabilities for different cursor motion
+operations.  A terminal description should define as many as possible, but
+most programs do not need to use most of them.  One capability, @samp{cm},
+moves the cursor to an arbitrary place on the screen; this by itself is
+sufficient for any application as long as there is no need to support
+hardcopy terminals or certain old, weak displays that have only relative
+motion commands.  Use of other cursor motion capabilities is an
+optimization, enabling the program to output fewer characters in some
+common cases.
+
+If you plan to use the relative cursor motion commands in an application
+program, you must know what the starting cursor position is.  To do this,
+you must keep track of the cursor position and update the records each
+time anything is output to the terminal, including graphic characters.
+In addition, it is necessary to know whether the terminal wraps after
+writing in the rightmost column.  @xref{Wrapping}.
+
+One other motion capability needs special mention: @samp{nw} moves the
+cursor to the beginning of the following line, perhaps clearing all the
+starting line after the cursor, or perhaps not clearing at all.  This
+capability is a least common denominator that is probably supported even by
+terminals that cannot do most other things such as @samp{cm} or @samp{do}.
+Even hardcopy terminals can support @samp{nw}.
+
+@table @asis
+@item @samp{cm}
+@kindex cm
+String of commands to position the cursor at line @var{l}, column @var{c}.
+Both parameters are origin-zero, and are defined relative to the
+screen, not relative to display memory.
+
+All display terminals except a few very obsolete ones support @samp{cm},
+so it is acceptable for an application program to refuse to operate on
+terminals lacking @samp{cm}.
+
+@item @samp{ho}
+@kindex ho
+@cindex home position
+String of commands to move the cursor to the upper left corner of the
+screen (this position is called the @dfn{home position}).  In
+terminals where the upper left corner of the screen is not the same as
+the beginning of display memory, this command must go to the upper
+left corner of the screen, not the beginning of display memory.
+
+Every display terminal supports this capability, and many application
+programs refuse to operate if the @samp{ho} capability is missing.
+
+@item @samp{ll}
+@kindex ll
+String of commands to move the cursor to the lower left corner of the
+screen.  On some terminals, moving up from home position does this,
+but programs should never assume that will work.  Just output the
+@samp{ll} string (if it is provided); if moving to home position and
+then moving up is the best way to get there, the @samp{ll} command
+will do that.
+
+@item @samp{cr}
+@kindex cr
+String of commands to move the cursor to the beginning of the line it
+is on.  If this capability is not specified, many programs assume
+they can use the ASCII carriage return character for this.
+
+@item @samp{le}
+@kindex le
+String of commands to move the cursor left one column.  Unless the
+@samp{bw} flag capability is specified, the effect is undefined if the
+cursor is at the left margin; do not use this command there.  If
+@samp{bw} is present, this command may be used at the left margin, and
+it wraps the cursor to the last column of the preceding line.
+
+@item @samp{nd}
+@kindex nd
+String of commands to move the cursor right one column.  The effect is
+undefined if the cursor is at the right margin; do not use this
+command there, not even if @samp{am} is present.
+
+@item @samp{up}
+@kindex up
+String of commands to move the cursor vertically up one line.  The
+effect of sending this string when on the top line is undefined;
+programs should never use it that way.
+
+@item @samp{do}
+@kindex do
+String of commands to move the cursor vertically down one line.  The
+effect of sending this string when on the bottom line is undefined;
+programs should never use it that way.
+
+Some programs do use @samp{do} to scroll up one line if used at the
+bottom line, if @samp{sf} is not defined but @samp{sr} is.  This is
+only to compensate for certain old, incorrect terminal descriptions.
+(In principle this might actually lead to incorrect behavior on other
+terminals, but that seems to happen rarely if ever.)  But the proper
+solution is that the terminal description should define @samp{sf} as
+well as @samp{do} if the command is suitable for scrolling.
+
+The original idea was that this string would not contain a newline
+character and therefore could be used without disabling the kernel's
+usual habit of converting of newline into a carriage-return newline
+sequence.  But many terminal descriptions do use newline in the
+@samp{do} string, so this is not possible; a program which sends the
+@samp{do} string must disable output conversion in the kernel
+(@pxref{Initialize}).
+
+@item @samp{bw}
+@kindex bw
+Flag whose presence says that @samp{le} may be used in column zero
+to move to the last column of the preceding line.  If this flag
+is not present, @samp{le} should not be used in column zero.
+
+@item @samp{nw}
+@kindex nw
+String of commands to move the cursor to start of next line, possibly
+clearing rest of line (following the cursor) before moving.
+
+@item @samp{DO}, @samp{UP}, @samp{LE}, @samp{RI}
+@kindex DO
+@kindex LE
+@kindex RI
+@kindex UP
+Strings of commands to move the cursor @var{n} lines down vertically,
+up vertically, or @var{n} columns left or right.  Do not attempt to
+move past any edge of the screen with these commands; the effect of
+trying that is undefined.  Only a few terminal descriptions provide
+these commands, and most programs do not use them.
+
+@item @samp{CM}
+@kindex CM
+String of commands to position the cursor at line @var{l}, column
+@var{c}, relative to display memory.  Both parameters are origin-zero.
+This capability is present only in terminals where there is a
+difference between screen-relative and memory-relative addressing, and
+not even in all such terminals.
+
+@item @samp{ch}
+@kindex ch
+String of commands to position the cursor at column @var{c} in the
+same line it is on.  This is a special case of @samp{cm} in which the
+vertical position is not changed.  The @samp{ch} capability is
+provided only when it is faster to output than @samp{cm} would be in
+this special case.  Programs should not assume most display terminals
+have @samp{ch}.
+
+@item @samp{cv}
+@kindex cv
+String of commands to position the cursor at line @var{l} in the same
+column.  This is a special case of @samp{cm} in which the horizontal
+position is not changed.  The @samp{cv} capability is provided only
+when it is faster to output than @samp{cm} would be in this special
+case.  Programs should not assume most display terminals have
+@samp{cv}.
+
+@item @samp{sc}
+@kindex sc
+String of commands to make the terminal save the current cursor
+position.  Only the last saved position can be used.  If this
+capability is present, @samp{rc} should be provided also.  Most
+terminals have neither.
+
+@item @samp{rc}
+@kindex rc
+String of commands to make the terminal restore the last saved cursor
+position.  If this capability is present, @samp{sc} should be provided
+also.  Most terminals have neither.
+
+@item @samp{ff}
+@kindex ff
+String of commands to advance to the next page, for a hardcopy
+terminal.
+
+@item @samp{ta}
+@kindex ta
+String of commands to move the cursor right to the next hardware tab
+stop column.  Missing if the terminal does not have any kind of
+hardware tabs.  Do not send this command if the kernel's terminal
+modes say that the kernel is expanding tabs into spaces.
+
+@item @samp{bt}
+@kindex bt
+String of commands to move the cursor left to the previous hardware
+tab stop column.  Missing if the terminal has no such ability; many
+terminals do not.  Do not send this command if the kernel's terminal
+modes say that the kernel is expanding tabs into spaces.
+@end table
+
+The following obsolete capabilities should be included in terminal
+descriptions when appropriate, but should not be looked at by new programs.
+
+@table @samp
+@item nc
+@kindex nc
+Flag whose presence means the terminal does not support the ASCII
+carriage return character as @samp{cr}.  This flag is needed because
+old programs assume, when the @samp{cr} capability is missing, that
+ASCII carriage return can be used for the purpose.  We use @samp{nc}
+to tell the old programs that carriage return may not be used.
+
+New programs should not assume any default for @samp{cr}, so they need
+not look at @samp{nc}.  However, descriptions should contain @samp{nc}
+whenever they do not contain @samp{cr}.
+
+@item xt
+@kindex xt
+Flag whose presence means that the ASCII tab character may not be used
+for cursor motion.  This flag exists because old programs assume, when
+the @samp{ta} capability is missing, that ASCII tab can be used for
+the purpose.  We use @samp{xt} to tell the old programs not to use tab.
+
+New programs should not assume any default for @samp{ta}, so they need
+not look at @samp{xt} in connection with cursor motion.  Note that
+@samp{xt} also has implications for standout mode (@pxref{Standout}).
+It is obsolete in regard to cursor motion but not in regard to
+standout.
+
+In fact, @samp{xt} means that the terminal is a Teleray 1061.
+
+@item bc
+@kindex bc
+Very obsolete alternative name for the @samp{le} capability.
+
+@item bs
+@kindex bs
+Flag whose presence means that the ASCII character backspace may be
+used to move the cursor left.  Obsolete; look at @samp{le} instead.
+
+@item nl
+@kindex nl
+Obsolete capability which is a string that can either be used to move
+the cursor down or to scroll.  The same string must scroll when used
+on the bottom line and move the cursor when used on any other line.
+New programs should use @samp{do} or @samp{sf}, and ignore @samp{nl}.
+
+If there is no @samp{nl} capability, some old programs assume they can
+use the newline character for this purpose.  These programs follow a
+bad practice, but because they exist, it is still desirable to define
+the @samp{nl} capability in a terminal description if the best way to
+move down is @emph{not} a newline.
+@end table
+
+@node Wrapping, Scrolling, Cursor Motion, Capabilities
+@section Wrapping
+@cindex wrapping
+
+@dfn{Wrapping} means moving the cursor from the right margin to the left
+margin of the following line.  Some terminals wrap automatically when a
+graphic character is output in the last column, while others do not.  Most
+application programs that use termcap need to know whether the terminal
+wraps.  There are two special flag capabilities to describe what the
+terminal does when a graphic character is output in the last column.
+
+@table @samp
+@item am
+@kindex am
+Flag whose presence means that writing a character in the last column
+causes the cursor to wrap to the beginning of the next line.
+
+If @samp{am} is not present, writing in the last column leaves the
+cursor at the place where the character was written.
+
+Writing in the last column of the last line should be avoided on
+terminals with @samp{am}, as it may or may not cause scrolling to
+occur (@pxref{Scrolling}).  Scrolling is surely not what you would
+intend.
+
+If your program needs to check the @samp{am} flag, then it also needs
+to check the @samp{xn} flag which indicates that wrapping happens in a
+strange way.  Many common terminals have the @samp{xn} flag.
+
+@item xn
+@kindex xn
+Flag whose presence means that the cursor wraps in a strange way.  At
+least two distinct kinds of strange behavior are known; the termcap
+data base does not contain anything to distinguish the two.
+
+On Concept-100 terminals, output in the last column wraps the cursor
+almost like an ordinary @samp{am} terminal.  But if the next thing
+output is a newline, it is ignored.
+
+DEC VT-100 terminals (when the wrap switch is on) do a different
+strange thing: the cursor wraps only if the next thing output is
+another graphic character.  In fact, the wrap occurs when the
+following graphic character is received by the terminal, before the
+character is placed on the screen.
+
+On both of these terminals, after writing in the last column a
+following graphic character will be displayed in the first column of
+the following line.  But the effect of relative cursor motion
+characters such as newline or backspace at such a time depends on the
+terminal.  The effect of erase or scrolling commands also depends on
+the terminal.  You can't assume anything about what they will do on a
+terminal that has @samp{xn}.  So, to be safe, you should never do
+these things at such a time on such a terminal.
+
+To be sure of reliable results on a terminal which has the @samp{xn}
+flag, output a @samp{cm} absolute positioning command after writing in
+the last column.  Another safe thing to do is to output carriage-return
+newline, which will leave the cursor at the beginning of the following
+line.
+@end table
+
+@node Scrolling, Windows, Wrapping, Capabilities
+@section Scrolling
+@cindex scrolling
+
+@dfn{Scrolling} means moving the contents of the screen up or down one or
+more lines.  Moving the contents up is @dfn{forward scrolling}; moving them
+down is @dfn{reverse scrolling}.
+
+Scrolling happens after each line of output during ordinary output on most
+display terminals.  But in an application program that uses termcap for
+random-access output, scrolling happens only when explicitly requested with
+the commands in this section.
+
+Some terminals have a @dfn{scroll region} feature.  This lets you limit
+the effect of scrolling to a specified range of lines.  Lines outside the
+range are unaffected when scrolling happens.  The scroll region feature
+is available if either @samp{cs} or @samp{cS} is present.
+
+@table @samp
+@item sf
+@kindex sf
+String of commands to scroll the screen one line up, assuming it is
+output with the cursor at the beginning of the bottom line.
+
+@item sr
+@kindex sr
+String of commands to scroll the screen one line down, assuming it is
+output with the cursor at the beginning of the top line.
+
+@item do
+A few programs will try to use @samp{do} to do the work of @samp{sf}.
+This is not really correct---it is an attempt to compensate for the
+absence of a @samp{sf} command in some old terminal descriptions.
+
+Since these terminal descriptions do define @samp{sr}, perhaps at one
+time the definition of @samp{do} was different and it could be used
+for scrolling as well.  But it isn't desirable to combine these two
+functions in one capability, since scrolling often requires more
+padding than simply moving the cursor down.  Defining @samp{sf} and
+@samp{do} separately allows you to specify the padding properly.
+Also, all sources agree that @samp{do} should not be relied on to do
+scrolling.
+
+So the best approach is to add @samp{sf} capabilities to the
+descriptions of these terminals, copying the definition of @samp{do}
+if that does scroll.
+
+@item SF
+@kindex SF
+String of commands to scroll the screen @var{n} lines up, assuming it
+is output with the cursor at the beginning of the bottom line.
+
+@item SR
+@kindex SR
+String of commands to scroll the screen @var{n} lines down, assuming it
+is output with the cursor at the beginning of the top line.
+
+@item cs
+@kindex cs
+String of commands to set the scroll region.  This command takes two
+parameters, @var{start} and @var{end}, which are the line numbers
+(origin-zero) of the first line to include in the scroll region and of
+the last line to include in it.  When a scroll region is set,
+scrolling is limited to the specified range of lines; lines outside
+the range are not affected by scroll commands.
+
+Do not try to move the cursor outside the scroll region.  The region
+remains set until explicitly removed.  To remove the scroll region,
+use another @samp{cs} command specifying the full height of the
+screen.
+
+The cursor position is undefined after the @samp{cs} command is set,
+so position the cursor with @samp{cm} immediately afterward.
+
+@item cS
+@kindex cS
+String of commands to set the scroll region using parameters in
+different form.  The effect is the same as if @samp{cs} were used.
+Four parameters are required:
+
+@enumerate
+@item
+Total number of lines on the screen.
+@item
+Number of lines above desired scroll region.
+@item
+Number of lines below (outside of) desired scroll region.
+@item
+Total number of lines on the screen, the same as the first parameter.
+@end enumerate
+
+This capability is a GNU extension that was invented to allow the Ann
+Arbor Ambassador's scroll-region command to be described; it could
+also be done by putting non-Unix @samp{%}-sequences into a @samp{cs}
+string, but that would have confused Unix programs that used the
+@samp{cs} capability with the Unix termcap.  Currently only GNU Emacs
+uses the @samp{cS} capability.
+
+@item ns
+@kindex ns
+Flag which means that the terminal does not normally scroll for
+ordinary sequential output.  For modern terminals, this means that
+outputting a newline in ordinary sequential output with the cursor on
+the bottom line wraps to the top line.  For some obsolete terminals,
+other things may happen.
+
+The terminal may be able to scroll even if it does not normally do so.
+If the @samp{sf} capability is provided, it can be used for scrolling
+regardless of @samp{ns}.
+
+@item da
+@kindex da
+Flag whose presence means that lines scrolled up off the top of the
+screen may come back if scrolling down is done subsequently.
+
+The @samp{da} and @samp{db} flags do not, strictly speaking, affect
+how to scroll.  But programs that scroll usually need to clear the
+lines scrolled onto the screen, if these flags are present.
+
+@item db
+@kindex db
+Flag whose presence means that lines scrolled down off the bottom of
+the screen may come back if scrolling up is done subsequently.
+
+@item lm
+@kindex lm
+Numeric value, the number of lines of display memory that the terminal
+has.  A value of zero means that the terminal has more display memory
+than can fit on the screen, but no fixed number of lines.  (The number
+of lines may depend on the amount of text in each line.)
+@end table
+
+Any terminal description that defines @samp{SF} should also define @samp{sf};
+likewise for @samp{SR} and @samp{sr}.  However, many terminals can only
+scroll by one line at a time, so it is common to find @samp{sf} and not
+@samp{SF}, or @samp{sr} without @samp{SR}.@refill
+
+Therefore, all programs that use the scrolling facilities should be
+prepared to work with @samp{sf} in the case that @samp{SF} is absent, and
+likewise with @samp{sr}.  On the other hand, an application program that
+uses only @samp{sf} and not @samp{SF} is acceptable, though slow on some
+terminals.@refill
+
+When outputting a scroll command with @code{tputs}, the @var{nlines}
+argument should be the total number of lines in the portion of the screen
+being scrolled.  Very often these commands require padding proportional to
+this number of lines.  @xref{Padding}.
+
+@node Windows, Clearing, Scrolling, Capabilities
+@section Windows
+@cindex window
+
+A @dfn{window}, in termcap, is a rectangular portion of the screen to which
+all display operations are restricted.  Wrapping, clearing, scrolling,
+insertion and deletion all operate as if the specified window were all the
+screen there was.
+
+@table @samp
+@item wi
+@kindex wi
+String of commands to set the terminal output screen window.
+This string requires four parameters, all origin-zero:
+@enumerate
+@item
+The first line to include in the window.
+@item
+The last line to include in the window.
+@item
+The first column to include in the window.
+@item
+The last column to include in the window.
+@end enumerate
+@end table
+
+Most terminals do not support windows.
+
+@node Clearing, Insdel Line, Windows, Capabilities
+@section Clearing Parts of the Screen
+@cindex erasing
+@cindex clearing the screen
+
+There are several terminal capabilities for clearing parts of the screen
+to blank.  All display terminals support the @samp{cl} string, and most
+display terminals support all of these capabilities.
+
+@table @samp
+@item cl
+@kindex cl
+String of commands to clear the entire screen and position the cursor
+at the upper left corner.
+
+@item cd
+@kindex cd
+String of commands to clear the line the cursor is on, and all the
+lines below it, down to the bottom of the screen.  This command string
+should be used only with the cursor in column zero; their effect is
+undefined if the cursor is elsewhere.
+
+@item ce
+@kindex ce
+String of commands to clear from the cursor to the end of the current
+line.
+
+@item ec
+@kindex ec
+String of commands to clear @var{n} characters, starting with the
+character that the cursor is on.  This command string is expected to
+leave the cursor position unchanged.  The parameter @var{n} should never
+be large enough to reach past the right margin; the effect of such a
+large parameter would be undefined.
+@end table
+
+Clear to end of line (@samp{ce}) is extremely important in programs that
+maintain an updating display.  Nearly all display terminals support this
+operation, so it is acceptable for a an application program to refuse to
+work if @samp{ce} is not present.  However, if you do not want this
+limitation, you can accomplish clearing to end of line by outputting spaces
+until you reach the right margin.  In order to do this, you must know the
+current horizontal position.  Also, this technique assumes that writing a
+space will erase.  But this happens to be true on all the display terminals
+that fail to support @samp{ce}.
+
+@node Insdel Line, Insdel Char, Clearing, Capabilities
+@section Insert/Delete Line
+
+@cindex insert line
+@cindex delete line
+@dfn{Inserting a line} means creating a blank line in the middle
+of the screen, and pushing the existing lines of text apart.  In fact,
+the lines above the insertion point do not change, while the lines below
+move down, and one is normally lost at the bottom of the screen.
+
+@dfn{Deleting a line} means causing the line to disappear from the screen,
+closing up the gap by moving the lines below it upward.  A new line
+appears at the bottom of the screen.  Usually this line is blank, but
+on terminals with the @samp{db} flag it may be a line previously moved
+off the screen bottom by scrolling or line insertion.
+
+Insertion and deletion of lines is useful in programs that maintain an
+updating display some parts of which may get longer or shorter.  They are
+also useful in editors for scrolling parts of the screen, and for
+redisplaying after lines of text are killed or inserted.
+
+Many terminals provide commands to insert or delete a single line at the
+cursor position.  Some provide the ability to insert or delete several
+lines with one command, using the number of lines to insert or delete as a
+parameter.  Always move the cursor to column zero before using any of
+these commands.
+
+@table @samp
+@item al
+@kindex al
+String of commands to insert a blank line before the line the cursor
+is on.  The existing line, and all lines below it, are moved down.
+The last line in the screen (or in the scroll region, if one is set)
+disappears and in most circumstances is discarded.  It may not be
+discarded if the @samp{db} is present (@pxref{Scrolling}).
+
+The cursor must be at the left margin before this command is used.
+This command does not move the cursor.
+
+@item dl
+@kindex dl
+String of commands to delete the line the cursor is on.  The following
+lines move up, and a blank line appears at the bottom of the screen
+(or bottom of the scroll region).  If the terminal has the @samp{db}
+flag, a nonblank line previously pushed off the screen bottom may
+reappear at the bottom.
+
+The cursor must be at the left margin before this command is used.
+This command does not move the cursor.
+
+@item AL
+@kindex AL
+String of commands to insert @var{n} blank lines before the line that
+the cursor is on.  It is like @samp{al} repeated @var{n} times, except
+that it is as fast as one @samp{al}.
+
+@item DL
+@kindex DL
+String of commands to delete @var{n} lines starting with the line that
+the cursor is on.  It is like @samp{dl} repeated @var{n} times, except
+that it is as fast as one @samp{dl}.
+@end table
+
+Any terminal description that defines @samp{AL} should also define
+@samp{al}; likewise for @samp{DL} and @samp{dl}.  However, many terminals
+can only insert or delete one line at a time, so it is common to find
+@samp{al} and not @samp{AL}, or @samp{dl} without @samp{DL}.@refill
+
+Therefore, all programs that use the insert and delete facilities should be
+prepared to work with @samp{al} in the case that @samp{AL} is absent, and
+likewise with @samp{dl}.  On the other hand, it is acceptable to write
+an application that uses only @samp{al} and @samp{dl} and does not look
+for @samp{AL} or @samp{DL} at all.@refill
+
+If a terminal does not support line insertion and deletion directly,
+but does support a scroll region, the effect of insertion and deletion
+can be obtained with scrolling.  However, it is up to the individual
+user program to check for this possibility and use the scrolling
+commands to get the desired result.  It is fairly important to implement
+this alternate strategy, since it is the only way to get the effect of
+line insertion and deletion on the popular VT100 terminal.
+
+Insertion and deletion of lines is affected by the scroll region on
+terminals that have a settable scroll region.  This is useful when it is
+desirable to move any few consecutive lines up or down by a few lines.
+@xref{Scrolling}.
+
+The line pushed off the bottom of the screen is not lost if the terminal
+has the @samp{db} flag capability; instead, it is pushed into display
+memory that does not appear on the screen.  This is the same thing that
+happens when scrolling pushes a line off the bottom of the screen.
+Either reverse scrolling or deletion of a line can bring the apparently
+lost line back onto the bottom of the screen.  If the terminal has the
+scroll region feature as well as @samp{db}, the pushed-out line really
+is lost if a scroll region is in effect.
+
+When outputting an insert or delete command with @code{tputs}, the
+@var{nlines} argument should be the total number of lines from the cursor
+to the bottom of the screen (or scroll region).  Very often these commands
+require padding proportional to this number of lines.  @xref{Padding}.
+
+For @samp{AL} and @samp{DL} the @var{nlines} argument should @emph{not}
+depend on the number of lines inserted or deleted; only the total number of
+lines affected.  This is because it is just as fast to insert two or
+@var{n} lines with @samp{AL} as to insert one line with @samp{al}.
+
+@node Insdel Char, Standout, Insdel Line, Capabilities
+@section Insert/Delete Character
+@cindex insert character
+@cindex delete character
+
+@dfn{Inserting a character} means creating a blank space in the middle of a
+line, and pushing the rest of the line rightward.  The character in the
+rightmost column is lost.
+
+@dfn{Deleting a character} means causing the character to disappear from
+the screen, closing up the gap by moving the rest of the line leftward.  A
+blank space appears in the rightmost column.
+
+Insertion and deletion of characters is useful in programs that maintain an
+updating display some parts of which may get longer or shorter.  It is also
+useful in editors for redisplaying the results of editing within a line.
+
+Many terminals provide commands to insert or delete a single character at
+the cursor position.  Some provide the ability to insert or delete several
+characters with one command, using the number of characters to insert or
+delete as a parameter.
+
+@cindex insert mode
+Many terminals provide an insert mode in which outputting a graphic
+character has the added effect of inserting a position for that character.
+A special command string is used to enter insert mode and another is used
+to exit it.  The reason for designing a terminal with an insert mode rather
+than an insert command is that inserting character positions is usually
+followed by writing characters into them.  With insert mode, this is as
+fast as simply writing the characters, except for the fixed overhead of
+entering and leaving insert mode.  However, when the line speed is great
+enough, padding may be required for the graphic characters output in insert
+mode.
+
+Some terminals require you to enter insert mode and then output a special
+command for each position to be inserted.  Or they may require special
+commands to be output before or after each graphic character to be
+inserted.
+
+@cindex delete mode
+Deletion of characters is usually accomplished by a straightforward command
+to delete one or several positions; but on some terminals, it is necessary
+to enter a special delete mode before using the delete command, and leave
+delete mode afterward.  Sometimes delete mode and insert mode are the same
+mode.
+
+Some terminals make a distinction between character positions in which a
+space character has been output and positions which have been cleared.  On
+these terminals, the effect of insert or delete character runs to the first
+cleared position rather than to the end of the line.  In fact, the effect
+may run to more than one line if there is no cleared position to stop the
+shift on the first line.  These terminals are identified by the @samp{in}
+flag capability.
+
+On terminals with the @samp{in} flag, the technique of skipping over
+characters that you know were cleared, and then outputting text later on in
+the same line, causes later insert and delete character operations on that
+line to do nonstandard things.  A program that has any chance of doing this
+must check for the @samp{in} flag and must be careful to write explicit
+space characters into the intermediate columns when @samp{in} is present.
+
+A plethora of terminal capabilities are needed to describe all of this
+complexity.  Here is a list of them all.  Following the list, we present
+an algorithm for programs to use to take proper account of all of these
+capabilities.
+
+@table @samp
+@item im
+@kindex im
+String of commands to enter insert mode.
+
+If the terminal has no special insert mode, but it can insert
+characters with a special command, @samp{im} should be defined with a
+null value, because the @samp{vi} editor assumes that insertion of a
+character is impossible if @samp{im} is not provided.
+
+New programs should not act like @samp{vi}.  They should pay attention
+to @samp{im} only if it is defined.
+
+@item ei
+@kindex ei
+String of commands to leave insert mode.  This capability must be
+present if @samp{im} is.
+
+On a few old terminals the same string is used to enter and exit
+insert mode.  This string turns insert mode on if it was off, and off
+it it was on.  You can tell these terminals because the @samp{ei}
+string equals the @samp{im} string.  If you want to support these
+terminals, you must always remember accurately whether insert mode is
+in effect.  However, these terminals are obsolete, and it is
+reasonable to refuse to support them.  On all modern terminals, you
+can safely output @samp{ei} at any time to ensure that insert mode is
+turned off.
+
+@item ic
+@kindex ic
+String of commands to insert one character position at the cursor.
+The cursor does not move.
+
+If outputting a graphic character while in insert mode is sufficient
+to insert the character, then the @samp{ic} capability should be
+defined with a null value.
+
+If your terminal offers a choice of ways to insert---either use insert
+mode or use a special command---then define @samp{im} and do not define
+@samp{ic}, since this gives the most efficient operation when several
+characters are to be inserted.  @emph{Do not} define both strings, for
+that means that @emph{both} must be used each time insertion is done.
+
+@item ip
+@kindex ip
+String of commands to output following an inserted graphic character
+in insert mode.  Often it is used just for a padding spec, when padding
+is needed after an inserted character (@pxref{Padding}).
+
+@item IC
+@kindex IC
+String of commands to insert @var{n} character positions at and after
+the cursor.  It has the same effect as repeating the @samp{ic} string
+and a space, @var{n} times.
+
+If @samp{IC} is provided, application programs may use it without first
+entering insert mode.
+
+@item mi
+@kindex mi
+Flag whose presence means it is safe to move the cursor while in insert
+mode and assume the terminal remains in insert mode.
+
+@item in
+@kindex in
+Flag whose presence means that the terminal distinguishes between
+character positions in which space characters have been output and
+positions which have been cleared.
+@end table
+
+An application program can assume that the terminal can do character
+insertion if @emph{any one of} the capabilities @samp{IC}, @samp{im},
+@samp{ic} or @samp{ip} is provided.
+
+To insert @var{n} blank character positions, move the cursor to the place
+to insert them and follow this algorithm:
+
+@enumerate
+@item
+If an @samp{IC} string is provided, output it with parameter @var{n}
+and you are finished.  Otherwise (or if you don't want to bother to
+look for an @samp{IC} string) follow the remaining steps.
+
+@item
+Output the @samp{im} string, if there is one, unless the terminal is
+already in insert mode.
+
+@item
+Repeat steps 4 through 6, @var{n} times.
+
+@item
+Output the @samp{ic} string if any.
+
+@item
+Output a space.
+
+@item
+Output the @samp{ip} string if any.
+
+@item
+Output the @samp{ei} string, eventually, to exit insert mode.  There
+is no need to do this right away.  If the @samp{mi} flag is present,
+you can move the cursor and the cursor will remain in insert mode;
+then you can do more insertion elsewhere without reentering insert
+mode.
+@end enumerate
+
+To insert @var{n} graphic characters, position the cursor and follow this
+algorithm:
+
+@enumerate
+@item
+If an @samp{IC} string is provided, output it with parameter @var{n},
+then output the graphic characters, and you are finished.  Otherwise
+(or if you don't want to bother to look for an @samp{IC} string)
+follow the remaining steps.
+
+@item
+Output the @samp{im} string, if there is one, unless the terminal is
+already in insert mode.
+
+@item
+For each character to be output, repeat steps 4 through 6.
+
+@item
+Output the @samp{ic} string if any.
+
+@item
+Output the next graphic character.
+
+@item
+Output the @samp{ip} string if any.
+
+@item
+Output the @samp{ei} string, eventually, to exit insert mode.  There
+is no need to do this right away.  If the @samp{mi} flag is present,
+you can move the cursor and the cursor will remain in insert mode;
+then you can do more insertion elsewhere without reentering insert
+mode.
+@end enumerate
+
+Note that this is not the same as the original Unix termcap specifications
+in one respect: it assumes that the @samp{IC} string can be used without
+entering insert mode.  This is true as far as I know, and it allows you be
+able to avoid entering and leaving insert mode, and also to be able to
+avoid the inserted-character padding after the characters that go into the
+inserted positions.
+
+Deletion of characters is less complicated; deleting one column is done by
+outputting the @samp{dc} string.  However, there may be a delete mode that
+must be entered with @samp{dm} in order to make @samp{dc} work.
+
+@table @samp
+@item dc
+@kindex dc
+String of commands to delete one character position at the cursor.  If
+@samp{dc} is not present, the terminal cannot delete characters.
+
+@item DC
+@kindex DC
+String of commands to delete @var{n} characters starting at the cursor.
+It has the same effect as repeating the @samp{dc} string @var{n} times.
+Any terminal description that has @samp{DC} also has @samp{dc}.
+
+@item dm
+@kindex dm
+String of commands to enter delete mode.  If not present, there is no
+delete mode, and @samp{dc} can be used at any time (assuming there is
+a @samp{dc}).
+
+@item ed
+@kindex ed
+String of commands to exit delete mode.  This must be present if
+@samp{dm} is.
+@end table
+
+To delete @var{n} character positions, position the cursor and follow these
+steps:
+
+@enumerate
+@item
+If the @samp{DC} string is present, output it with parameter @var{n}
+and you are finished.  Otherwise, follow the remaining steps.
+
+@item
+Output the @samp{dm} string, unless you know the terminal is already
+in delete mode.
+
+@item
+Output the @samp{dc} string @var{n} times.
+
+@item
+Output the @samp{ed} string eventually.  If the flag capability
+@samp{mi} is present, you can move the cursor and do more deletion
+without leaving and reentering delete mode.
+@end enumerate
+
+As with the @samp{IC} string, we have departed from the original termcap
+specifications by assuming that @samp{DC} works without entering delete
+mode even though @samp{dc} would not.
+
+If the @samp{dm} and @samp{im} capabilities are both present and have the
+same value, it means that the terminal has one mode for both insertion and
+deletion.  It is useful for a program to know this, because then it can do
+insertions after deletions, or vice versa, without leaving insert/delete
+mode and reentering it.
+
+@node Standout, Underlining, Insdel Char, Capabilities
+@section Standout and Appearance Modes
+@cindex appearance modes
+@cindex standout
+@cindex magic cookie
+
+@dfn{Appearance modes} are modifications to the ways characters are
+displayed.  Typical appearance modes include reverse video, dim, bright,
+blinking, underlined, invisible, and alternate character set.  Each kind of
+terminal supports various among these, or perhaps none.
+
+For each type of terminal, one appearance mode or combination of them that
+looks good for highlighted text is chosen as the @dfn{standout mode}.  The
+capabilities @samp{so} and @samp{se} say how to enter and leave standout
+mode.  Programs that use appearance modes only to highlight some text
+generally use the standout mode so that they can work on as many terminals
+as possible.  Use of specific appearance modes other than ``underlined''
+and ``alternate character set'' is rare.
+
+Terminals that implement appearance modes fall into two general classes as
+to how they do it.
+
+In some terminals, the presence or absence of any appearance mode is
+recorded separately for each character position.  In these terminals, each
+graphic character written is given the appearance modes current at the time
+it is written, and keeps those modes until it is erased or overwritten.
+There are special commands to turn the appearance modes on or off for
+characters to be written in the future.
+
+In other terminals, the change of appearance modes is represented by a
+marker that belongs to a certain screen position but affects all following
+screen positions until the next marker.  These markers are traditionally
+called @dfn{magic cookies}.
+
+The same capabilities (@samp{so}, @samp{se}, @samp{mb} and so on) for
+turning appearance modes on and off are used for both magic-cookie
+terminals and per-character terminals.  On magic cookie terminals, these
+give the commands to write the magic cookies.  On per-character terminals,
+they change the current modes that affect future output and erasure.  Some
+simple applications can use these commands without knowing whether or not
+they work by means of cookies.
+
+However, a program that maintains and updates a display needs to know
+whether the terminal uses magic cookies, and exactly what their effect is.
+This information comes from the @samp{sg} capability.
+
+The @samp{sg} capability is a numeric capability whose presence indicates
+that the terminal uses magic cookies for appearance modes.  Its value is
+the number of character positions that a magic cookie occupies.  Usually
+the cookie occupies one or more character positions on the screen, and these
+character positions are displayed as blank, but in some terminals the
+cookie has zero width.
+
+The @samp{sg} capability describes both the magic cookie to turn standout
+on and the cookie to turn it off.  This makes the assumption that both
+kinds of cookie have the same width on the screen.  If that is not true,
+the narrower cookie must be ``widened'' with spaces until it has the same
+width as the other.
+
+On some magic cookie terminals, each line always starts with normal
+display; in other words, the scope of a magic cookie never extends over
+more than one line.  But on other terminals, one magic cookie affects all
+the lines below it unless explicitly canceled.  Termcap does not define any
+way to distinguish these two ways magic cookies can work.  To be safe, it
+is best to put a cookie at the beginning of each line.
+
+On some per-character terminals, standout mode or other appearance modes
+may be canceled by moving the cursor.  On others, moving the cursor has no
+effect on the state of the appearance modes.  The latter class of terminals
+are given the flag capability @samp{ms} (``can move in standout'').  All
+programs that might have occasion to move the cursor while appearance modes
+are turned on must check for this flag; if it is not present, they should
+reset appearance modes to normal before doing cursor motion.
+
+A program that has turned on only standout mode should use @samp{se} to
+reset the standout mode to normal.  A program that has turned on only
+alternate character set mode should use @samp{ae} to return it to normal.
+If it is possible that any other appearance modes are turned on, use the
+@samp{me} capability to return them to normal.
+
+Note that the commands to turn on one appearance mode, including @samp{so}
+and @samp{mb} @dots{} @samp{mr}, if used while some other appearance modes
+are turned on, may combine the two modes on some terminals but may turn off
+the mode previously enabled on other terminals.  This is because some
+terminals do not have a command to set or clear one appearance mode without
+changing the others.  Programs should not attempt to use appearance modes
+in combination except with @samp{sa}, and when switching from one single
+mode to another should always turn off the previously enabled mode and then
+turn on the new desired mode.
+
+On some old terminals, the @samp{so} and @samp{se} commands may be the same
+command, which has the effect of turning standout on if it is off, or off
+it is on.  It is therefore risky for a program to output extra @samp{se}
+commands for good measure.  Fortunately, all these terminals are obsolete.
+
+Programs that update displays in which standout-text may be replaced with
+non-standout text must check for the @samp{xs} flag.  In a per-character
+terminal, this flag says that the only way to remove standout once written is
+to clear that portion of the line with the @samp{ce} string or something
+even more powerful (@pxref{Clearing}); just writing new characters at those
+screen positions will not change the modes in effect there.  In a magic
+cookie terminal, @samp{xs} says that the only way to remove a cookie is to
+clear a portion of the line that includes the cookie; writing a different
+cookie at the same position does not work.
+
+Such programs must also check for the @samp{xt} flag, which means that the
+terminal is a Teleray 1061.  On this terminal it is impossible to position
+the cursor at the front of a magic cookie, so the only two ways to remove a
+cookie are (1) to delete the line it is on or (2) to position the cursor at
+least one character before it (possibly on a previous line) and output the
+@samp{se} string, which on these terminals finds and removes the next
+@samp{so} magic cookie on the screen.  (It may also be possible to remove a
+cookie which is not at the beginning of a line by clearing that line.)  The
+@samp{xt} capability also has implications for the use of tab characters,
+but in that regard it is obsolete (@xref{Cursor Motion}).
+
+@table @samp
+@item so
+@kindex so
+String of commands to enter standout mode.
+
+@item se
+@kindex se
+String of commands to leave standout mode.
+
+@item sg
+@kindex sg
+Numeric capability, the width on the screen of the magic cookie.  This
+capability is absent in terminals that record appearance modes
+character by character.
+
+@item ms
+@kindex ms
+Flag whose presence means that it is safe to move the cursor while the
+appearance modes are not in the normal state.  If this flag is absent,
+programs should always reset the appearance modes to normal before
+moving the cursor.
+
+@item xs
+@kindex xs
+Flag whose presence means that the only way to reset appearance modes
+already on the screen is to clear to end of line.  On a per-character
+terminal, you must clear the area where the modes are set.  On a magic
+cookie terminal, you must clear an area containing the cookie.
+See the discussion above.
+
+@item xt
+@kindex xt
+Flag whose presence means that the cursor cannot be positioned right
+in front of a magic cookie, and that @samp{se} is a command to delete
+the next magic cookie following the cursor.  See discussion above.
+
+@item mb
+@kindex mb
+String of commands to enter blinking mode.
+
+@item md
+@kindex md
+String of commands to enter double-bright mode.
+
+@item mh
+@kindex mh
+String of commands to enter half-bright mode.
+
+@item mk
+@kindex mk
+String of commands to enter invisible mode.
+
+@item mp
+@kindex mp
+String of commands to enter protected mode.
+
+@item mr
+@kindex mr
+String of commands to enter reverse-video mode.
+
+@item me
+@kindex me
+String of commands to turn off all appearance modes, including
+standout mode and underline mode.  On some terminals it also turns off
+alternate character set mode; on others, it may not.  This capability
+must be present if any of @samp{mb} @dots{} @samp{mr} is present.
+
+@item as
+@kindex as
+String of commands to turn on alternate character set mode.  This mode
+assigns some or all graphic characters an alternate picture on the
+screen.  There is no standard as to what the alternate pictures look
+like.
+
+@item ae
+@kindex ae
+String of commands to turn off alternate character set mode.
+
+@item sa
+@kindex sa
+String of commands to turn on an arbitrary combination of appearance
+modes.  It accepts 9 parameters, each of which controls a particular
+kind of appearance mode.  A parameter should be 1 to turn its appearance
+mode on, or zero to turn that mode off.  Most terminals do not support
+the @samp{sa} capability, even among those that do have various
+appearance modes.
+
+The nine parameters are, in order, @var{standout}, @var{underline},
+@var{reverse}, @var{blink}, @var{half-bright}, @var{double-bright},
+@var{blank}, @var{protect}, @var{alt char set}.
+@end table
+
+@node Underlining, Cursor Visibility, Standout, Capabilities
+@section Underlining
+@cindex underlining
+
+Underlining on most terminals is a kind of appearance mode, much like
+standout mode.  Therefore, it may be implemented using magic cookies or as
+a flag in the terminal whose current state affects each character that is
+output.  @xref{Standout}, for a full explanation.
+
+The @samp{ug} capability is a numeric capability whose presence indicates
+that the terminal uses magic cookies for underlining.  Its value is the
+number of character positions that a magic cookie for underlining occupies;
+it is used for underlining just as @samp{sg} is used for standout.  Aside
+from the simplest applications, it is impossible to use underlining
+correctly without paying attention to the value of @samp{ug}.
+
+@table @samp
+@item us
+@kindex us
+String of commands to turn on underline mode or to output a magic cookie
+to start underlining.
+
+@item ue
+@kindex ue
+String of commands to turn off underline mode or to output a magic
+cookie to stop underlining.
+
+@item ug
+@kindex ug
+Width of magic cookie that represents a change of underline mode;
+or missing, if the terminal does not use a magic cookie for this.
+
+@item ms
+@kindex ms
+Flag whose presence means that it is safe to move the cursor while the
+appearance modes are not in the normal state.  Underlining is an
+appearance mode.  If this flag is absent, programs should always turn
+off underlining before moving the cursor.
+@end table
+
+There are two other, older ways of doing underlining: there can be a
+command to underline a single character, or the output of @samp{_}, the
+ASCII underscore character, as an overstrike could cause a character to be
+underlined.  New programs need not bother to handle these capabilities
+unless the author cares strongly about the obscure terminals which support
+them.  However, terminal descriptions should provide these capabilities
+when appropriate.
+
+@table @samp
+@item uc
+@kindex uc
+String of commands to underline the character under the cursor, and
+move the cursor right.
+
+@item ul
+@kindex ul
+Flag whose presence means that the terminal can underline by
+overstriking an underscore character (@samp{_}); some terminals can do
+this even though they do not support overstriking in general.  An
+implication of this flag is that when outputting new text to overwrite
+old text, underscore characters must be treated specially lest they
+underline the old text instead.
+@end table
+
+@node Cursor Visibility, Bell, Underlining, Capabilities
+@section Cursor Visibility
+@cindex visibility
+
+Some terminals have the ability to make the cursor invisible, or to enhance
+it.  Enhancing the cursor is often done by programs that plan to use the
+cursor to indicate to the user a position of interest that may be anywhere
+on the screen---for example, the Emacs editor enhances the cursor on entry.
+Such programs should always restore the cursor to normal on exit.
+
+@table @samp
+@item vs
+@kindex vs
+String of commands to enhance the cursor.
+
+@item vi
+@kindex vi
+String of commands to make the cursor invisible.
+
+@item ve
+@kindex ve
+String of commands to return the cursor to normal.
+@end table
+
+If you define either @samp{vs} or @samp{vi}, you must also define @samp{ve}.
+
+@node Bell, Keypad, Cursor Visibility, Capabilities
+@section Bell
+@cindex bell
+@cindex visible bell
+
+Here we describe commands to make the terminal ask for the user to pay
+attention to it.
+
+@table @samp
+@item bl
+@kindex bl
+String of commands to cause the terminal to make an audible sound.  If
+this capability is absent, the terminal has no way to make a suitable
+sound.
+
+@item vb
+@kindex vb
+String of commands to cause the screen to flash to attract attention
+(``visible bell'').  If this capability is absent, the terminal has no
+way to do such a thing.
+@end table
+
+@node Keypad, Meta Key, Bell, Capabilities
+@section Keypad and Function Keys
+
+Many terminals have arrow and function keys that transmit specific
+character sequences to the computer.  Since the precise sequences used
+depend on the terminal, termcap defines capabilities used to say what the
+sequences are.  Unlike most termcap string-valued capabilities, these are
+not strings of commands to be sent to the terminal, rather strings that
+are received from the terminal.
+
+Programs that expect to use keypad keys should check, initially, for a
+@samp{ks} capability and send it, to make the keypad actually transmit.
+Such programs should also send the @samp{ke} string when exiting.
+
+@table @asis
+@item @samp{ks}
+@kindex ka@dots{}ku
+String of commands to make the function keys transmit.  If this
+capability is not provided, but the others in this section are,
+programs may assume that the function keys always transmit.
+
+@item @samp{ke}
+String of commands to make the function keys work locally.  This
+capability is provided only if @samp{ks} is.
+
+@item @samp{kl}
+String of input characters sent by typing the left-arrow key.  If this
+capability is missing, you cannot expect the terminal to have a
+left-arrow key that transmits anything to the computer.
+
+@item @samp{kr}
+String of input characters sent by typing the right-arrow key.
+
+@item @samp{ku}
+String of input characters sent by typing the up-arrow key.
+
+@item @samp{kd}
+String of input characters sent by typing the down-arrow key.
+
+@item @samp{kh}
+String of input characters sent by typing the ``home-position'' key.
+
+@item @samp{K1} @dots{} @samp{K5}
+@kindex K1@dots{}K5
+Strings of input characters sent by the five other keys in a 3-by-3
+array that includes the arrow keys, if the keyboard has such a 3-by-3
+array.  Note that one of these keys may be the ``home-position'' key,
+in which case one of these capabilities will have the same value as
+the @samp{kh} key.
+
+@item @samp{k0}
+String of input characters sent by function key 10 (or 0, if the terminal
+has one labeled 0).
+
+@item @samp{k1} @dots{} @samp{k9}
+@kindex k1@dots{}k9
+Strings of input characters sent by function keys 1 through 9,
+provided for those function keys that exist.
+
+@item @samp{kn}
+Number: the number of numbered function keys, if there are more than
+10.
+
+@item @samp{l0} @dots{} @samp{l9}
+@kindex l0@dots{}l9
+Strings which are the labels appearing on the keyboard on the keys
+described by the capabilities @samp{k0} @dots{} @samp{l9}.  These
+capabilities should be left undefined if the labels are @samp{f0} or
+@samp{f10} and @samp{f1} @dots{} @samp{f9}.@refill
+
+@item @samp{kH}
+@kindex kA@dots{}kT
+String of input characters sent by the ``home down'' key, if there is
+one.
+
+@item @samp{kb}
+String of input characters sent by the ``backspace'' key, if there is
+one.
+
+@item @samp{ka}
+String of input characters sent by the ``clear all tabs'' key, if there
+is one.
+
+@item @samp{kt}
+String of input characters sent by the ``clear tab stop this column''
+key, if there is one.
+
+@item @samp{kC}
+String of input characters sent by the ``clear screen'' key, if there is
+one.
+
+@item @samp{kD}
+String of input characters sent by the ``delete character'' key, if
+there is one.
+
+@item @samp{kL}
+String of input characters sent by the ``delete line'' key, if there is
+one.
+
+@item @samp{kM}
+String of input characters sent by the ``exit insert mode'' key, if
+there is one.
+
+@item @samp{kE}
+String of input characters sent by the ``clear to end of line'' key, if
+there is one.
+
+@item @samp{kS}
+String of input characters sent by the ``clear to end of screen'' key,
+if there is one.
+
+@item @samp{kI}
+String of input characters sent by the ``insert character'' or ``enter
+insert mode'' key, if there is one.
+
+@item @samp{kA}
+String of input characters sent by the ``insert line'' key, if there is
+one.
+
+@item @samp{kN}
+String of input characters sent by the ``next page'' key, if there is
+one.
+
+@item @samp{kP}
+String of input characters sent by the ``previous page'' key, if there is
+one.
+
+@item @samp{kF}
+String of input characters sent by the ``scroll forward'' key, if there
+is one.
+
+@item @samp{kR}
+String of input characters sent by the ``scroll reverse'' key, if there
+is one.
+
+@item @samp{kT}
+String of input characters sent by the ``set tab stop in this column''
+key, if there is one.
+
+@item @samp{ko}
+String listing the other function keys the terminal has.  This is a
+very obsolete way of describing the same information found in the
+@samp{kH} @dots{} @samp{kT} keys.  The string contains a list of
+two-character termcap capability names, separated by commas.  The
+meaning is that for each capability name listed, the terminal has a
+key which sends the string which is the value of that capability.  For
+example, the value @samp{:ko=cl,ll,sf,sr:} says that the terminal has
+four function keys which mean ``clear screen'', ``home down'',
+``scroll forward'' and ``scroll reverse''.@refill
+@end table
+
+@node Meta Key, Initialization, Keypad, Capabilities
+@section Meta Key
+
+@cindex meta key
+A Meta key is a key on the keyboard that modifies each character you type
+by controlling the 0200 bit.  This bit is on if and only if the Meta key is
+held down when the character is typed.  Characters typed using the Meta key
+are called Meta characters.  Emacs uses Meta characters as editing
+commands.
+
+@table @samp
+@item km
+@kindex km
+Flag whose presence means that the terminal has a Meta key.
+
+@item mm
+@kindex mm
+String of commands to enable the functioning of the Meta key.
+
+@item mo
+@kindex mo
+String of commands to disable the functioning of the Meta key.
+@end table
+
+If the terminal has @samp{km} but does not have @samp{mm} and @samp{mo}, it
+means that the Meta key always functions.  If it has @samp{mm} and
+@samp{mo}, it means that the Meta key can be turned on or off.  Send the
+@samp{mm} string to turn it on, and the @samp{mo} string to turn it off.
+I do not know why one would ever not want it to be on.
+
+@node Initialization, Pad Specs, Meta Key, Capabilities
+@section Initialization
+@cindex reset
+@cindex initialization
+@cindex tab stops
+
+@table @samp
+@item ti
+@kindex ti
+String of commands to put the terminal into whatever special modes are
+needed or appropriate for programs that move the cursor
+nonsequentially around the screen.  Programs that use termcap to do
+full-screen display should output this string when they start up.
+
+@item te
+@kindex te
+String of commands to undo what is done by the @samp{ti} string.
+Programs that output the @samp{ti} string on entry should output this
+string when they exit.
+
+@item is
+@kindex is
+String of commands to initialize the terminal for each login session.
+
+@item if
+@kindex if
+String which is the name of a file containing the string of commands
+to initialize the terminal for each session of use.  Normally @samp{is}
+and @samp{if} are not both used.
+
+@item i1
+@itemx i3
+@kindex i1
+@kindex i3
+Two more strings of commands to initialize the terminal for each login
+session.  The @samp{i1} string (if defined) is output before @samp{is}
+or @samp{if}, and the @samp{i3} string (if defined) is output after.
+
+The reason for having three separate initialization strings is to make
+it easier to define a group of related terminal types with slightly
+different initializations.  Define two or three of the strings in the
+basic type; then the other types can override one or two of the
+strings.
+
+@item rs
+@kindex rs
+String of commands to reset the terminal from any strange mode it may
+be in.  Normally this includes the @samp{is} string (or other commands
+with the same effects) and more.  What would go in the @samp{rs}
+string but not in the @samp{is} string are annoying or slow commands
+to bring the terminal back from strange modes that nobody would
+normally use.
+
+@item it
+@kindex it
+Numeric value, the initial spacing between hardware tab stop columns
+when the terminal is powered up.  Programs to initialize the terminal
+can use this to decide whether there is a need to set the tab stops.
+If the initial width is 8, well and good; if it is not 8, then the
+tab stops should be set; if they cannot be set, the kernel is told
+to convert tabs to spaces, and other programs will observe this and do
+likewise.
+
+@item ct
+@kindex ct
+String of commands to clear all tab stops.
+
+@item st
+@kindex st
+String of commands to set tab stop at current cursor column on all
+lines.
+@end table
+
+@node Pad Specs, Status Line, Initialization, Capabilities
+@section Padding Capabilities
+@cindex padding
+
+There are two terminal capabilities that exist just to explain the proper
+way to obey the padding specifications in all the command string
+capabilities.  One, @samp{pc}, must be obeyed by all termcap-using
+programs.
+
+@table @samp
+@item pb
+@kindex pb
+Numeric value, the lowest baud rate at which padding is actually
+needed.  Programs may check this and refrain from doing any padding at
+lower speeds.
+
+@item pc
+@kindex pc
+String of commands for padding.  The first character of this string is
+to be used as the pad character, instead of using null characters for
+padding.  If @samp{pc} is not provided, use null characters.  Every
+program that uses termcap must look up this capability and use it to
+set the variable @code{PC} that is used by @code{tputs}.
+@xref{Padding}.
+@end table
+
+Some termcap capabilities exist just to specify the amount of padding that
+the kernel should give to cursor motion commands used in ordinary
+sequential output.
+
+@table @samp
+@item dC
+@kindex dC
+Numeric value, the number of msec of padding needed for the
+carriage-return character.
+
+@item dN
+@kindex dN
+Numeric value, the number of msec of padding needed for the newline
+(linefeed) character.
+
+@item dB
+@kindex dB
+Numeric value, the number of msec of padding needed for the backspace
+character.
+
+@item dF
+@kindex dF
+Numeric value, the number of msec of padding needed for the formfeed
+character.
+
+@item dT
+@kindex dT
+Numeric value, the number of msec of padding needed for the tab
+character.
+@end table
+
+In some systems, the kernel uses the above capabilities; in other systems,
+the kernel uses the paddings specified in the string capabilities
+@samp{cr}, @samp{sf}, @samp{le}, @samp{ff} and @samp{ta}.  Descriptions of
+terminals which require such padding should contain the @samp{dC} @dots{}
+@samp{dT} capabilities and also specify the appropriate padding in the
+corresponding string capabilities.  Since no modern terminals require
+padding for ordinary sequential output, you probably won't need to do
+either of these things.
+
+@node Status Line, Half-Line, Pad Specs, Capabilities
+@section Status Line
+
+@cindex status line
+A @dfn{status line} is a line on the terminal that is not used for ordinary
+display output but instead used for a special message.  The intended use is
+for a continuously updated description of what the user's program is doing,
+and that is where the name ``status line'' comes from, but in fact it could
+be used for anything.  The distinguishing characteristic of a status line
+is that ordinary output to the terminal does not affect it; it changes only
+if the special status line commands of this section are used.
+
+@table @samp
+@item hs
+@kindex hs
+Flag whose presence means that the terminal has a status line.  If a
+terminal description specifies that there is a status line, it must
+provide the @samp{ts} and @samp{fs} capabilities.
+
+@item ts
+@kindex ts
+String of commands to move the terminal cursor into the status line.
+Usually these commands must specifically record the old cursor
+position for the sake of the @samp{fs} string.
+
+@item fs
+@kindex fs
+String of commands to move the cursor back from the status line to its
+previous position (outside the status line).
+
+@item es
+@kindex es
+Flag whose presence means that other display commands work while
+writing the status line.  In other words, one can clear parts of it,
+insert or delete characters, move the cursor within it using @samp{ch}
+if there is a @samp{ch} capability, enter and leave standout mode, and
+so on.
+
+@item ds
+@kindex ds
+String of commands to disable the display of the status line.  This
+may be absent, if there is no way to disable the status line display.
+
+@item ws
+@kindex ws
+Numeric value, the width of the status line.  If this capability is
+absent in a terminal that has a status line, it means the status line
+is the same width as the other lines.
+
+Note that the value of @samp{ws} is sometimes as small as 8.
+@end table
+
+@node Half-Line, Printer, Status Line, Capabilities
+@section Half-Line Motion
+
+Some terminals have commands for moving the cursor vertically by half-lines,
+useful for outputting subscripts and superscripts.  Mostly it is hardcopy
+terminals that have such features.
+
+@table @samp
+@item hu
+@kindex hu
+String of commands to move the cursor up half a line.  If the terminal
+is a display, it is your responsibility to avoid moving up past the
+top line; however, most likely the terminal that supports this is a
+hardcopy terminal and there is nothing to be concerned about.
+
+@item hd
+@kindex hd
+String of commands to move the cursor down half a line.  If the
+terminal is a display, it is your responsibility to avoid moving down
+past the bottom line, etc.
+@end table
+
+@node Printer,  , Half-Line, Capabilities
+@section Controlling Printers Attached to Terminals
+@cindex printer
+
+Some terminals have attached hardcopy printer ports.  They may be able to
+copy the screen contents to the printer; they may also be able to redirect
+output to the printer.  Termcap does not have anything to tell the program
+whether the redirected output appears also on the screen; it does on some
+terminals but not all.
+
+@table @samp
+@item ps
+@kindex ps
+String of commands to cause the contents of the screen to be printed.
+If it is absent, the screen contents cannot be printed.
+
+@item po
+@kindex po
+String of commands to redirect further output to the printer.
+
+@item pf
+@kindex pf
+String of commands to terminate redirection of output to the printer.
+This capability must be present in the description if @samp{po} is.
+
+@item pO
+@kindex pO
+String of commands to redirect output to the printer for next @var{n}
+characters of output, regardless of what they are.  Redirection will
+end automatically after @var{n} characters of further output.  Until
+then, nothing that is output can end redirection, not even the
+@samp{pf} string if there is one.  The number @var{n} should not be
+more than 255.
+
+One use of this capability is to send non-text byte sequences (such as
+bit-maps) to the printer.
+@end table
+
+Most terminals with printers do not support all of @samp{ps}, @samp{po} and
+@samp{pO}; any one or two of them may be supported.  To make a program that
+can send output to all kinds of printers, it is necessary to check for all
+three of these capabilities, choose the most convenient of the ones that
+are provided, and use it in its own appropriate fashion.
+
+@node Summary, Var Index, Capabilities, Top
+@chapter Summary of Capability Names
+
+Here are all the terminal capability names in alphabetical order
+with a brief description of each.  For cross references to their definitions,
+see the index of capability names (@pxref{Cap Index}).
+
+@table @samp
+@item ae
+String to turn off alternate character set mode.
+@item al
+String to insert a blank line before the cursor.
+@item AL
+String to insert @var{n} blank lines before the cursor.
+@item am
+Flag: output to last column wraps cursor to next line.
+@item as
+String to turn on alternate character set mode.like.
+@item bc
+Very obsolete alternative name for the @samp{le} capability.
+@item bl
+String to sound the bell.
+@item bs
+Obsolete flag: ASCII backspace may be used for leftward motion.
+@item bt
+String to move the cursor left to the previous hardware tab stop column.
+@item bw
+Flag: @samp{le} at left margin wraps to end of previous line.
+@item CC
+String to change terminal's command character.
+@item cd
+String to clear the line the cursor is on, and following lines.
+@item ce
+String to clear from the cursor to the end of the line.
+@item ch
+String to position the cursor at column @var{c} in the same line.
+@item cl
+String to clear the entire screen and put cursor at upper left corner.
+@item cm
+String to position the cursor at line @var{l}, column @var{c}.
+@item CM
+String to position the cursor at line @var{l}, column
+@var{c}, relative to display memory.
+@item co
+Number: width of the screen.
+@item cr
+String to move cursor sideways to left margin.
+@item cs
+String to set the scroll region.
+@item cS
+Alternate form of string to set the scroll region.
+@item ct
+String to clear all tab stops.
+@item cv
+String to position the cursor at line @var{l} in the same column.
+@item da
+Flag: data scrolled off top of screen may be scrolled back.
+@item db
+Flag: data scrolled off bottom of screen may be scrolled back.
+@item dB
+Obsolete number: msec of padding needed for the backspace character.
+@item dc
+String to delete one character position at the cursor.
+@item dC
+Obsolete number: msec of padding needed for the carriage-return character.
+@item DC
+String to delete @var{n} characters starting at the cursor.
+@item dF
+Obsolete number: msec of padding needed for the formfeed character.
+@item dl
+String to delete the line the cursor is on.
+@item DL
+String to delete @var{n} lines starting with the cursor's line.
+@item dm
+String to enter delete mode.
+@item dN
+Obsolete number: msec of padding needed for the newline character.
+@item do
+String to move the cursor vertically down one line.
+@item DO
+String to move cursor vertically down @var{n} lines.
+@item ds
+String to disable the display of the status line.
+@item dT
+Obsolete number: msec of padding needed for the tab character.
+@item ec
+String of commands to clear @var{n} characters at cursor.
+@item ed
+String to exit delete mode.
+@item ei
+String to leave insert mode.
+@item eo
+Flag: output of a space can erase an overstrike.
+@item es
+Flag: other display commands work while writing the status line.
+@item ff
+String to advance to the next page, for a hardcopy terminal.
+@item fs
+String to move the cursor back from the status line to its
+previous position (outside the status line).
+@item gn
+Flag: this terminal type is generic, not real.
+@item hc
+Flag: hardcopy terminal.
+@item hd
+String to move the cursor down half a line.
+@item ho
+String to position cursor at upper left corner.
+@item hs
+Flag: the terminal has a status line.
+@item hu
+String to move the cursor up half a line.
+@item hz
+Flag: terminal cannot accept @samp{~} as output.
+@item i1
+String to initialize the terminal for each login session.
+@item i3
+String to initialize the terminal for each login session.
+@item ic
+String to insert one character position at the cursor.
+@item IC
+String to insert @var{n} character positions at the cursor.
+@item if
+String naming a file of commands to initialize the terminal.
+@item im
+String to enter insert mode.
+@item in
+Flag: outputting a space is different from moving over empty positions.
+@item ip
+String to output following an inserted character in insert mode.
+@item is
+String to initialize the terminal for each login session.
+@item it
+Number: initial spacing between hardware tab stop columns.
+@item k0
+String of input sent by function key 0 or 10.
+@item k1 @dots{} k9
+Strings of input sent by function keys 1 through 9.
+@item K1 @dots{} K5
+Strings sent by the five other keys in 3-by-3 array with arrows.
+@item ka
+String of input sent by the ``clear all tabs'' key.
+@item kA
+String of input sent by the ``insert line'' key.
+@item kb
+String of input sent by the ``backspace'' key.
+@item kC
+String of input sent by the ``clear screen'' key.
+@item kd
+String of input sent by typing the down-arrow key.
+@item kD
+String of input sent by the ``delete character'' key.
+@item ke
+String to make the function keys work locally.
+@item kE
+String of input sent by the ``clear to end of line'' key.
+@item kF
+String of input sent by the ``scroll forward'' key.
+@item kh
+String of input sent by typing the ``home-position'' key.
+@item kH
+String of input sent by the ``home down'' key.
+@item kI
+String of input sent by the ``insert character'' or ``enter
+insert mode'' key.
+@item kl
+String of input sent by typing the left-arrow key.
+@item kL
+String of input sent by the ``delete line'' key.
+@item km
+Flag: the terminal has a Meta key.
+@item kM
+String of input sent by the ``exit insert mode'' key.
+@item kn
+Numeric value, the number of numbered function keys.
+@item kN
+String of input sent by the ``next page'' key.
+@item ko
+Very obsolete string listing the terminal's named function keys.
+@item kP
+String of input sent by the ``previous page'' key.
+@item kr
+String of input sent by typing the right-arrow key.
+@item kR
+String of input sent by the ``scroll reverse'' key.
+@item ks
+String to make the function keys transmit.
+@item kS
+String of input sent by the ``clear to end of screen'' key.
+@item kt
+String of input sent by the ``clear tab stop this column'' key.
+@item kT
+String of input sent by the ``set tab stop in this column'' key.
+@item ku
+String of input sent by typing the up-arrow key.
+@item l0
+String on keyboard labelling function key 0 or 10.
+@item l1 @dots{} l9
+Strings on keyboard labelling function keys 1 through 9.
+@item le
+String to move the cursor left one column.
+@item LE
+String to move cursor left @var{n} columns.
+@item li
+Number: height of the screen.
+@item ll
+String to position cursor at lower left corner.
+@item lm
+Number: lines of display memory.
+@item mb
+String to enter blinking mode.
+@item md
+String to enter double-bright mode.
+@item me
+String to turn off all appearance modes
+@item mh
+String to enter half-bright mode.
+@item mi
+Flag: cursor motion in insert mode is safe.
+@item mk
+String to enter invisible mode.
+@item mm
+String to enable the functioning of the Meta key.
+@item mo
+String to disable the functioning of the Meta key.
+@item mp
+String to enter protected mode.
+@item mr
+String to enter reverse-video mode.
+@item ms
+Flag: cursor motion in standout mode is safe.
+@item nc
+Obsolete flag: do not use ASCII carriage-return on this terminal.
+@item nd
+String to move the cursor right one column.
+@item nl
+Obsolete alternative name for the @samp{do} and @samp{sf} capabilities.
+@item ns
+Flag: the terminal does not normally scroll for sequential output.
+@item nw
+String to move to start of next line, possibly clearing rest of old line.
+@item os
+Flag: terminal can overstrike.
+@item pb
+Number: the lowest baud rate at which padding is actually needed.
+@item pc
+String containing character for padding.
+@item pf
+String to terminate redirection of output to the printer.
+@item po
+String to redirect further output to the printer.
+@item pO
+String to redirect @var{n} characters ofoutput to the printer.
+@item ps
+String to print the screen on the attached printer.
+@item rc
+String to move to last saved cursor position.
+@item RI
+String to move cursor right @var{n} columns.
+@item rp
+String to output character @var{c} repeated @var{n} times.
+@item rs
+String to reset the terminal from any strange modes.
+@item sa
+String to turn on an arbitrary combination of appearance modes.
+@item sc
+String to save the current cursor position.
+@item se
+String to leave standout mode.
+@item sf
+String to scroll the screen one line up.
+@item SF
+String to scroll the screen @var{n} lines up.
+@item sg
+Number: width of magic standout cookie.  Absent if magic cookies are
+not used.
+@item so
+String to enter standout mode.
+@item sr
+String to scroll the screen one line down.
+@item SR
+String to scroll the screen @var{n} line down.
+@item st
+String to set tab stop at current cursor column on all lines.
+programs.
+@item ta
+String to move the cursor right to the next hardware tab stop column.
+@item te
+String to return terminal to settings for sequential output.
+@item ti
+String to initialize terminal for random cursor motion.
+@item ts
+String to move the terminal cursor into the status line.
+@item uc
+String to underline one character and move cursor right.
+@item ue
+String to turn off underline mode
+@item ug
+Number: width of underlining magic cookie.  Absent if underlining
+doesn't use magic cookies.
+@item ul
+Flag: underline by overstriking with an underscore.
+@item up
+String to move the cursor vertically up one line.
+@item UP
+String to move cursor vertically up @var{n} lines.
+@item us
+String to turn on underline mode
+@item vb
+String to make the screen flash.
+@item ve
+String to return the cursor to normal.
+@item vi
+String to make the cursor invisible.
+@item vs
+String to enhance the cursor.
+@item wi
+String to set the terminal output screen window.
+@item ws
+Number: the width of the status line.
+@item xb
+Flag: superbee terminal.
+@item xn
+Flag: cursor wraps in a strange way.
+@item xs
+Flag: clearing a line is the only way to clear the appearance modes of
+positions in that line (or, only way to remove magic cookies on that
+line).
+@item xt
+Flag: Teleray 1061; several strange characteristics.
+@end table
+
+@node Var Index, Cap Index, Summary, Top
+@unnumbered Variable and Function Index
+
+@printindex fn
+
+@node Cap Index, Index, Var Index, Top
+@unnumbered Capability Index
+
+@printindex ky
+
+@node Index,  , Cap Index, Top
+@unnumbered Concept Index
+
+@printindex cp
+
+@contents
+@bye
+
diff --git a/lib/termcap/grot/texinfo.tex b/lib/termcap/grot/texinfo.tex
new file mode 100644 (file)
index 0000000..d10917e
--- /dev/null
@@ -0,0 +1,3941 @@
+%% TeX macros to handle texinfo files
+
+%   Copyright (C) 1985, 86, 88, 90, 91, 92, 1993 Free Software Foundation, Inc.
+
+%This texinfo.tex 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, or (at
+%your option) any later version.
+
+%This texinfo.tex file 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 texinfo.tex file; see the file COPYING.  If not, write
+%to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+%USA.
+
+
+%In other words, you are welcome to use, share and improve this program.
+%You are forbidden to forbid anyone else to use, share and improve
+%what you give them.   Help stamp out software-hoarding!
+
+\def\texinfoversion{2.104}
+\message{Loading texinfo package [Version \texinfoversion]:}
+\message{}
+
+% Print the version number if in a .fmt file.
+\everyjob{\message{[Texinfo version \texinfoversion]}\message{}}
+
+% Save some parts of plain tex whose names we will redefine.
+
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexdots=\dots
+\let\ptexdot=\.
+\let\ptexstar=\*
+\let\ptexend=\end
+\let\ptexbullet=\bullet
+\let\ptexb=\b
+\let\ptexc=\c
+\let\ptexi=\i
+\let\ptext=\t
+\let\ptexl=\l
+\let\ptexL=\L
+
+\def\tie{\penalty 10000\ }     % Save plain tex definition of ~.
+
+\message{Basics,}
+\chardef\other=12
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Ignore a token.
+% 
+\def\gobble#1{}
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset  \bindingoffset=0pt
+\newdimen \normaloffset   \normaloffset=\hoffset
+\newdimen\pagewidth \newdimen\pageheight
+\pagewidth=\hsize \pageheight=\vsize
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal.  We don't just call \tracingall here,
+% since that produces some useless output on the terminal.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{\tracingcommands2 \tracingstats2 
+   \tracingpages1 \tracingoutput1 \tracinglostchars1 
+   \tracingmacros2 \tracingparagraphs1 \tracingrestores1 
+   \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+
+%---------------------Begin change-----------------------
+%
+%%%% For @cropmarks command.
+% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\cornerlong \newdimen\cornerthick
+\newdimen \topandbottommargin
+\newdimen \outerhsize \newdimen \outervsize
+\cornerlong=1pc\cornerthick=.3pt       % These set size of cropmarks
+\outerhsize=7in
+%\outervsize=9.5in
+% Alternative @smallbook page size is 9.25in
+\outervsize=9.25in
+\topandbottommargin=.75in
+%
+%---------------------End change-----------------------
+
+% \onepageout takes a vbox as an argument.  Note that \pagecontents
+% does insertions itself, but you have to call it yourself.
+\chardef\PAGE=255  \output={\onepageout{\pagecontents\PAGE}}
+\def\onepageout#1{\hoffset=\normaloffset
+\ifodd\pageno  \advance\hoffset by \bindingoffset
+\else \advance\hoffset by -\bindingoffset\fi
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}%
+{\let\hsize=\pagewidth \makefootline}}}%
+\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+
+%%%% For @cropmarks command %%%%
+
+% Here is a modification of the main output routine for Near East Publications
+% This provides right-angle cropmarks at all four corners.
+% The contents of the page are centerlined into the cropmarks,
+% and any desired binding offset is added as an \hskip on either
+% site of the centerlined box.  (P. A. MacKay, 12 November, 1986)
+%
+\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+                \shipout
+                \vbox to \outervsize{\hsize=\outerhsize
+                 \vbox{\line{\ewtop\hfill\ewtop}}
+                 \nointerlineskip
+                 \line{\vbox{\moveleft\cornerthick\nstop}
+                       \hfill
+                       \vbox{\moveright\cornerthick\nstop}}
+                 \vskip \topandbottommargin
+                 \centerline{\ifodd\pageno\hskip\bindingoffset\fi
+                       \vbox{
+                       {\let\hsize=\pagewidth \makeheadline}
+                       \pagebody{#1}
+                       {\let\hsize=\pagewidth \makefootline}}
+                       \ifodd\pageno\else\hskip\bindingoffset\fi}
+                \vskip \topandbottommargin plus1fill minus1fill
+                 \boxmaxdepth\cornerthick
+                 \line{\vbox{\moveleft\cornerthick\nsbot}
+                       \hfill
+                       \vbox{\moveright\cornerthick\nsbot}}
+                 \nointerlineskip
+                 \vbox{\line{\ewbot\hfill\ewbot}}
+       }}
+  \advancepageno 
+  \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+%
+% Do @cropmarks to get crop marks
+\def\cropmarks{\let\onepageout=\croppageout }
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+%
+% Here are the rules for the cropmarks.  Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+  {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+  {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1.  The argument is the rest of
+% the input line (except we remove a trailing comment).  #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg#1{%
+  \let\next = #1%
+  \begingroup
+    \obeylines
+    \futurelet\temp\parseargx
+}
+
+% If the next token is an obeyed space (from an @example environment or
+% the like), remove it and recurse.  Otherwise, we're done.
+\def\parseargx{%
+  % \obeyedspace is defined far below, after the definition of \sepspaces.
+  \ifx\obeyedspace\temp
+    \expandafter\parseargdiscardspace
+  \else
+    \expandafter\parseargline
+  \fi
+}
+
+% Remove a single space (as the delimiter token to the macro call).
+{\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+{\obeylines %
+  \gdef\parseargline#1^^M{%
+    \endgroup % End of the group started in \parsearg.
+    %
+    % First remove any @c comment, then any @comment.
+    % Result of each macro is put in \toks0.
+    \argremovec #1\c\relax %
+    \expandafter\argremovecomment \the\toks0 \comment\relax %
+    %
+    % Call the caller's macro, saved as \next in \parsearg.
+    \expandafter\next\expandafter{\the\toks0}%
+  }%
+}
+
+% Since all \c{,omment} does is throw away the argument, we can let TeX
+% do that for us.  The \relax here is matched by the \relax in the call
+% in \parseargline; it could be more or less anything, its purpose is
+% just to delimit the argument to the \c.
+\def\argremovec#1\c#2\relax{\toks0 = {#1}}
+\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+%    @end itemize  @c foo
+% will have two active spaces as part of the argument with the
+% `itemize'.  Here we remove all active spaces from #1, and assign the
+% result to \toks0.
+%
+% This loses if there are any *other* active characters besides spaces
+% in the argument -- _ ^ +, for example -- since they get expanded.
+% Fortunately, Texinfo does not define any such commands.  (If it ever
+% does, the catcode of the characters in questionwill have to be changed
+% here.)  But this means we cannot call \removeactivespaces as part of
+% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+% that \parsearg gets might well have any character at all in it.
+% 
+\def\removeactivespaces#1{%
+  \begingroup
+    \ignoreactivespaces
+    \edef\temp{#1}%
+    \global\toks0 = \expandafter{\temp}%
+  \endgroup
+}
+
+% Change the active space to expand to nothing.
+% 
+\begingroup
+  \obeyspaces
+  \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+\endgroup
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment.  Type Return to continue.}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo  is the same as @foo, for now.
+\newhelp\EMsimple{Type <Return> to continue.}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+% @end foo executes the definition of \Efoo.
+%
+\def\end{\parsearg\endxxx}
+\def\endxxx #1{%
+  \removeactivespaces{#1}%
+  \edef\endthing{\the\toks0}%
+  %
+  \expandafter\ifx\csname E\endthing\endcsname\relax
+    \expandafter\ifx\csname \endthing\endcsname\relax
+      % There's no \foo, i.e., no ``environment'' foo.
+      \errhelp = \EMsimple
+      \errmessage{Undefined command `@end \endthing'}%
+    \else
+      \unmatchedenderror\endthing
+    \fi
+  \else
+    % Everything's ok; the right environment has been started.
+    \csname E\endthing\endcsname
+  \fi
+}
+
+% There is an environment #1, but it hasn't been started.  Give an error.
+% 
+\def\unmatchedenderror#1{%
+  \errhelp = \EMsimple
+  \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+}
+
+% Define the control sequence \E#1 to give an unmatched @end error.
+% 
+\def\defineunmatchedend#1{%
+  \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+}
+
+
+% Single-spacing is done by various environments.
+
+\newskip\singlespaceskip \singlespaceskip = \baselineskip
+\def\singlespace{%
+{\advance \baselineskip by -\singlespaceskip
+\kern \baselineskip}%
+\baselineskip=\singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt \char '100}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+
+\def\mylbrace {{\tt \char '173}}
+\def\myrbrace {{\tt \char '175}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @w prevents a word break.  Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox.  We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line.  According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0).  If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+% 
+\def\group{\begingroup
+  \ifnum\catcode13=\active \else
+    \errhelp = \groupinvalidhelp
+    \errmessage{@group invalid in context where filling is enabled}%
+  \fi
+  %
+  % The \vtop we start below produces a box with normal height and large
+  % depth; thus, TeX puts \baselineskip glue before it, and (when the
+  % next line of text is done) \lineskip glue after it.  (See p.82 of
+  % the TeXbook.)  But the next line of text also gets us \parskip glue.
+  % Final result: space below is slightly more than space above.
+  \def\Egroup{%
+    \egroup           % End the \vtop.
+    \endgroup         % End the \group.
+  }%
+  %
+  \vtop\bgroup
+    % We have to put a strut on the last line in case the @group is in
+    % the midst of an example, rather than completely enclosing it.
+    % Otherwise, the interline space between the last line of the group
+    % and the first line afterwards is too small.  But we can't put the
+    % strut in \Egroup, since there it would be on a line by itself.
+    % Hence this just inserts a strut at the beginning of each line.
+    \everypar = {\strut}%
+    %
+    % We do @comment here in case we are called inside an environment,
+    % such as @example, where each end-of-line in the input causes an
+    % end-of-line in the output.  We don't want the end-of-line after
+    % the `@group' to put extra space in the output.  Since @group
+    % should appear on a line by itself (according to the Texinfo
+    % manual), we don't worry about eating any user text.
+    \comment
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+% 
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil  \mil=0.001in
+
+\def\need{\parsearg\needx}
+
+% Old definition--didn't work.
+%\def\needx #1{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000
+%\prevdepth=-1000pt
+%}}
+
+\def\needx#1{%
+  % Go into vertical mode, so we don't make a big box in the middle of a
+  % paragraph.
+  \par
+  %
+  % Don't add any leading before our big empty box, but allow a page
+  % break, since the best break might be right here.
+  \allowbreak
+  \nointerlineskip
+  \vtop to #1\mil{\vfil}%
+  % 
+  % TeX does not even consider page breaks if a penalty added to the
+  % main vertical list is 10000 or more.  But in order to see if the
+  % empty box we just added fits on the page, we must make it consider
+  % page breaks.  On the other hand, we don't want to actually break the
+  % page after the empty box.  So we use a penalty of 9999.
+  % 
+  % There is an extremely small chance that TeX will actually break the
+  % page at this \penalty, if there are no other feasible breakpoints in
+  % sight.  (If the user is using lots of big @group commands, which
+  % almost-but-not-quite fill up a page, TeX will have a hard time doing
+  % good page breaking, for example.)  However, I could not construct an
+  % example where a page broke at this \penalty; if it happens in a real
+  % document, then we can reconsider our strategy.
+  \penalty9999
+  %
+  % Back up by the size of the box, whether we did a page break or not.
+  \kern -#1\mil
+  %
+  % Do not allow a page break right after this kern.
+  \nobreak
+}
+
+% @br   forces paragraph break
+
+\let\br = \par
+
+% @dots{}  output some dots
+
+\def\dots{$\ldots$}
+
+% @page    forces the start of a new page
+
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\def\exdent{\parsearg\exdentyyy}
+\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+% This defn is used inside nofill environments such as @example.
+\def\nofillexdent{\parsearg\nofillexdentyyy}
+\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+\leftline{\hskip\leftskip{\rm#1}}}}
+
+%\hbox{{\rm#1}}\hfil\break}}
+
+% @include file    insert text of that file as input.
+
+\def\include{\parsearg\includezzz}
+%Use \input\thisfile to avoid blank after \input, which may be an active
+%char (in which case the blank would become the \input argument).
+%The grouping keeps the value of \thisfile correct even when @include
+%is nested.
+\def\includezzz #1{\begingroup
+\def\thisfile{#1}\input\thisfile
+\endgroup}
+
+\def\thisfile{}
+
+% @center line   outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n   outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\par \vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore  is another way to write a comment
+
+\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other%
+\parsearg \commentxxx}
+
+\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 }
+
+\let\c=\comment
+
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+\let\chapter=\relax
+\let\unnumbered=\relax
+\let\top=\relax
+\let\unnumberedsec=\relax
+\let\unnumberedsection=\relax
+\let\unnumberedsubsec=\relax
+\let\unnumberedsubsection=\relax
+\let\unnumberedsubsubsec=\relax
+\let\unnumberedsubsubsection=\relax
+\let\section=\relax
+\let\subsec=\relax
+\let\subsubsec=\relax
+\let\subsection=\relax
+\let\subsubsection=\relax
+\let\appendix=\relax
+\let\appendixsec=\relax
+\let\appendixsection=\relax
+\let\appendixsubsec=\relax
+\let\appendixsubsection=\relax
+\let\appendixsubsubsec=\relax
+\let\appendixsubsubsection=\relax
+\let\contents=\relax
+\let\smallbook=\relax
+\let\titlepage=\relax
+}
+
+% Used in nested conditionals, where we have to parse the Texinfo source
+% and so want to turn off most commands, in case they are used
+% incorrectly.  
+% 
+\def\ignoremorecommands{%
+  \let\defcv = \relax
+  \let\deffn = \relax
+  \let\deffnx = \relax
+  \let\defindex = \relax
+  \let\defivar = \relax
+  \let\defmac = \relax
+  \let\defmethod = \relax
+  \let\defop = \relax
+  \let\defopt = \relax
+  \let\defspec = \relax
+  \let\deftp = \relax
+  \let\deftypefn = \relax
+  \let\deftypefun = \relax
+  \let\deftypevar = \relax
+  \let\deftypevr = \relax
+  \let\defun = \relax
+  \let\defvar = \relax
+  \let\defvr = \relax
+  \let\ref = \relax
+  \let\xref = \relax
+  \let\printindex = \relax
+  \let\pxref = \relax
+  \let\settitle = \relax
+  \let\include = \relax
+}
+
+% Ignore @ignore ... @end ignore.
+% 
+\def\ignore{\doignore{ignore}}
+
+% Also ignore @ifinfo, @menu, and @direntry text.
+% 
+\def\ifinfo{\doignore{ifinfo}}
+\def\menu{\doignore{menu}}
+\def\direntry{\doignore{direntry}}
+
+% Ignore text until a line `@end #1'.
+% 
+\def\doignore#1{\begingroup
+  % Don't complain about control sequences we have declared \outer.
+  \ignoresections
+  %
+  % Define a command to swallow text until we reach `@end #1'.
+  \long\def\doignoretext##1\end #1{\enddoignore}%
+  %
+  % Make sure that spaces turn into tokens that match what \doignoretext wants.
+  \catcode32 = 10
+  %
+  % And now expand that command.
+  \doignoretext
+}
+
+% What we do to finish off ignored text.
+% 
+\def\enddoignore{\endgroup\ignorespaces}%
+
+\newif\ifwarnedobs\warnedobsfalse
+\def\obstexwarn{%
+  \ifwarnedobs\relax\else
+  % We need to warn folks that they may have trouble with TeX 3.0.
+  % This uses \immediate\write16 rather than \message to get newlines.
+    \immediate\write16{}
+    \immediate\write16{***WARNING*** for users of Unix TeX 3.0!}
+    \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
+    \immediate\write16{If you are running another version of TeX, relax.}
+    \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
+    \immediate\write16{  Then upgrade your TeX installation if you can.}
+    \immediate\write16{If you are stuck with version 3.0, run the}
+    \immediate\write16{  script ``tex3patch'' from the Texinfo distribution}
+    \immediate\write16{  to use a workaround.}
+    \immediate\write16{}
+    \warnedobstrue
+    \fi
+}
+
+% **In TeX 3.0, setting text in \nullfont hangs tex.  For a
+% workaround (which requires the file ``dummy.tfm'' to be installed),
+% uncomment the following line:
+%%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+
+% Ignore text, except that we keep track of conditional commands for
+% purposes of nesting, up to an `@end #1' command.
+% 
+\def\nestedignore#1{%
+  \obstexwarn
+  % We must actually expand the ignored text to look for the @end
+  % command, so that nested ignore constructs work.  Thus, we put the
+  % text into a \vbox and then do nothing with the result.  To minimize
+  % the change of memory overflow, we follow the approach outlined on
+  % page 401 of the TeXbook: make the current font be a dummy font.
+  % 
+  \setbox0 = \vbox\bgroup
+    % Don't complain about control sequences we have declared \outer.
+    \ignoresections
+    %
+    % Define `@end #1' to end the box, which will in turn undefine the
+    % @end command again.
+    \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
+    %
+    % We are going to be parsing Texinfo commands.  Most cause no
+    % trouble when they are used incorrectly, but some commands do
+    % complicated argument parsing or otherwise get confused, so we
+    % undefine them.
+    %
+    % We can't do anything about stray @-signs, unfortunately;
+    % they'll produce `undefined control sequence' errors.
+    \ignoremorecommands
+    % 
+    % Set the current font to be \nullfont, a TeX primitive, and define
+    % all the font commands to also use \nullfont.  We don't use
+    % dummy.tfm, as suggested in the TeXbook, because not all sites
+    % might have that installed.  Therefore, math mode will still
+    % produce output, but that should be an extremely small amount of
+    % stuff compared to the main input.
+    %
+    \nullfont
+    \let\tenrm = \nullfont  \let\tenit = \nullfont  \let\tensl = \nullfont
+    \let\tenbf = \nullfont  \let\tentt = \nullfont  \let\smallcaps = \nullfont
+    \let\tensf = \nullfont
+    %
+    % Don't complain when characters are missing from the fonts.
+    \tracinglostchars = 0
+    %
+    % Don't bother to do space factor calculations.
+    \frenchspacing
+    %
+    % Don't report underfull hboxes.
+    \hbadness = 10000
+    %
+    % Do minimal line-breaking.
+    \pretolerance = 10000
+    %
+    % Do not execute instructions in @tex
+    \def\tex{\doignore{tex}}
+}
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+% 
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it.
+%
+\def\set{\parsearg\setxxx}
+\def\setxxx#1{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+  \def\temp{#2}%
+  \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+  \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+  \fi
+}
+\def\setzzz#1#2 \endsetzzz{\expandafter\xdef\csname SET#1\endcsname{#2}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+% @value{foo} gets the text saved in variable foo.
+%
+\def\value#1{\expandafter
+               \ifx\csname SET#1\endcsname\relax
+                       {\{No value for ``#1''\}}
+               \else \csname SET#1\endcsname \fi}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+% 
+\def\ifset{\parsearg\ifsetxxx}
+\def\ifsetxxx #1{%
+  \expandafter\ifx\csname SET#1\endcsname\relax
+    \expandafter\ifsetfail
+  \else
+    \expandafter\ifsetsucceed
+  \fi
+}
+\def\ifsetsucceed{\conditionalsucceed{ifset}}
+\def\ifsetfail{\nestedignore{ifset}}
+\defineunmatchedend{ifset}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+% 
+\def\ifclear{\parsearg\ifclearxxx}
+\def\ifclearxxx #1{%
+  \expandafter\ifx\csname SET#1\endcsname\relax
+    \expandafter\ifclearsucceed
+  \else
+    \expandafter\ifclearfail
+  \fi
+}
+\def\ifclearsucceed{\conditionalsucceed{ifclear}}
+\def\ifclearfail{\nestedignore{ifclear}}
+\defineunmatchedend{ifclear}
+
+% @iftex always succeeds; we read the text following, through @end
+% iftex).  But `@end iftex' should be valid only after an @iftex.
+% 
+\def\iftex{\conditionalsucceed{iftex}}
+\defineunmatchedend{iftex}
+
+% We can't just want to start a group at @iftex (for example) and end it
+% at @end iftex, since then @set commands inside the conditional have no
+% effect (they'd get reverted at the end of the group).  So we must
+% define \Eiftex to redefine itself to be its previous value.  (We can't
+% just define it to fail again with an ``unmatched end'' error, since
+% the @ifset might be nested.)
+% 
+\def\conditionalsucceed#1{%
+  \edef\temp{%
+    % Remember the current value of \E#1.
+    \let\nece{prevE#1} = \nece{E#1}%
+    %
+    % At the `@end #1', redefine \E#1 to be its previous value.
+    \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+  }%
+  \temp
+}
+
+% We need to expand lots of \csname's, but we don't want to expand the
+% control sequences after we've constructed them.
+%
+\def\nece#1{\expandafter\noexpand\csname#1\endcsname}
+
+% @asis just yields its argument.  Used with @table, for example.
+% 
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written.  Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo).  So we must use a
+% control sequence to switch into and out of math mode.
+% 
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+% 
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{\implicitmath\ptexbullet\implicitmath}
+\def\minus{\implicitmath-\implicitmath}
+
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\nwnode=\node
+\let\lastnode=\relax
+
+\def\donoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\setref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\unnumbnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\def\appendixnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi
+\let\lastnode=\relax}
+
+\let\refill=\relax
+  
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+   \readauxfile
+   \opencontents
+   \openindices
+   \fixbackslash  % Turn off hack to swallow `\input texinfo'.
+   \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+   \comment % Ignore the actual filename.
+}
+
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{See Info file \file{\ignorespaces #3{}},
+  node \samp{\ignorespaces#1{}}}
+
+\message{fonts,}
+
+% Font-change commands.
+
+% Texinfo supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+%% Try out Computer Modern fonts at \magstephalf
+\let\mainmagstep=\magstephalf
+
+\ifx\bigger\relax
+\let\mainmagstep=\magstep1
+\font\textrm=cmr12
+\font\texttt=cmtt12
+\else
+\font\textrm=cmr10 scaled \mainmagstep
+\font\texttt=cmtt10 scaled \mainmagstep
+\fi
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\font\textbf=cmb10 scaled \mainmagstep 
+\font\textit=cmti10 scaled \mainmagstep
+\font\textsl=cmsl10 scaled \mainmagstep
+\font\textsf=cmss10 scaled \mainmagstep
+\font\textsc=cmcsc10 scaled \mainmagstep
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun, etc.
+\font\defbf=cmbx10 scaled \magstep1 %was 1314
+\font\deftt=cmtt10 scaled \magstep1
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+% Fonts for indices and small examples.
+% We actually use the slanted font rather than the italic, 
+% because texinfo normally uses the slanted fonts for that.
+% Do not make many font distinctions in general in the index, since they
+% aren't very useful.
+\font\ninett=cmtt9
+\font\indrm=cmr9
+\font\indit=cmsl9
+\let\indsl=\indit
+\let\indtt=\ninett
+\let\indsf=\indrm
+\let\indbf=\indrm
+\let\indsc=\indrm
+\font\indi=cmmi9
+\font\indsy=cmsy9
+
+% Fonts for headings
+\font\chaprm=cmbx12 scaled \magstep2
+\font\chapit=cmti12 scaled \magstep2
+\font\chapsl=cmsl12 scaled \magstep2
+\font\chaptt=cmtt12 scaled \magstep2
+\font\chapsf=cmss12 scaled \magstep2
+\let\chapbf=\chaprm
+\font\chapsc=cmcsc10 scaled\magstep3
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+\font\secrm=cmbx12 scaled \magstep1
+\font\secit=cmti12 scaled \magstep1
+\font\secsl=cmsl12 scaled \magstep1
+\font\sectt=cmtt12 scaled \magstep1
+\font\secsf=cmss12 scaled \magstep1
+\font\secbf=cmbx12 scaled \magstep1
+\font\secsc=cmcsc10 scaled\magstep2
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% \font\ssecrm=cmbx10 scaled \magstep1    % This size an font looked bad.
+% \font\ssecit=cmti10 scaled \magstep1    % The letters were too crowded.
+% \font\ssecsl=cmsl10 scaled \magstep1
+% \font\ssectt=cmtt10 scaled \magstep1
+% \font\ssecsf=cmss10 scaled \magstep1
+
+%\font\ssecrm=cmb10 scaled 1315        % Note the use of cmb rather than cmbx.
+%\font\ssecit=cmti10 scaled 1315       % Also, the size is a little larger than
+%\font\ssecsl=cmsl10 scaled 1315       % being scaled magstep1.
+%\font\ssectt=cmtt10 scaled 1315
+%\font\ssecsf=cmss10 scaled 1315
+
+%\let\ssecbf=\ssecrm
+
+\font\ssecrm=cmbx12 scaled \magstephalf
+\font\ssecit=cmti12 scaled \magstephalf
+\font\ssecsl=cmsl12 scaled \magstephalf
+\font\ssectt=cmtt12 scaled \magstephalf
+\font\ssecsf=cmss12 scaled \magstephalf
+\font\ssecbf=cmbx12 scaled \magstephalf
+\font\ssecsc=cmcsc10 scaled \magstep1 
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled \magstep1
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% Fonts for title page:
+\font\titlerm = cmbx12 scaled \magstep3
+\let\authorrm = \secrm
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families.  Since
+% texinfo doesn't allow for producing subscripts and superscripts, we
+% don't bother to reset \scriptfont and \scriptscriptfont (which would
+% also require loading a lot more fonts).
+% 
+\def\resetmathfonts{%
+  \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy
+  \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf
+  \textfont\ttfam = \tentt \textfont\sffam = \tensf
+}
+
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE.  We do this so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current.  Plain TeX does, for example,
+% \def\bf{\fam=\bffam \tenbf}  By redefining \tenbf, we obviate the need
+% to redefine \bf itself.  
+\def\textfonts{%
+  \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+  \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+  \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
+  \resetmathfonts}
+\def\chapfonts{%
+  \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl 
+  \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+  \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy
+  \resetmathfonts}
+\def\secfonts{%
+  \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+  \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+  \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
+  \resetmathfonts}
+\def\subsecfonts{%
+  \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+  \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+  \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
+  \resetmathfonts}
+\def\indexfonts{%
+  \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
+  \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
+  \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy
+  \resetmathfonts}
+
+% Set up the default fonts, so we can use them for creating boxes.
+% 
+\textfonts
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\font\shortcontrm=cmr12
+\font\shortcontbf=cmbx12
+\font\shortcontsl=cmsl12
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartitalic
+\let\dfn=\smartitalic
+\let\emph=\smartitalic
+\let\cite=\smartitalic
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph.  Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+% 
+\def\nohyphenation{\hyphenchar\font = -1  \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+\def\t#1{%
+  {\tt \nohyphenation \rawbackslash \frenchspacing #1}%
+  \null
+}
+\let\ttfont = \t
+%\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null}
+\def\samp #1{`\tclose{#1}'\null}
+\def\key #1{{\tt \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+\let\file=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+  {%
+    % Change normal interword space to be same as for the current font.
+    \spaceskip = \fontdimen2\font
+    %
+    % Switch to typewriter.
+    \tt
+    %
+    % But `\ ' produces the large typewriter interword space.
+    \def\ {{\spaceskip = 0pt{} }}%
+    %
+    % Turn off hyphenation.
+    \nohyphenation
+    % 
+    \rawbackslash
+    \frenchspacing
+    #1%
+  }%
+  \null
+}
+\let\code=\tclose
+%\let\exp=\tclose  %Was temporary
+
+% @kbd is like @code, except that if the argument is just one @key command, 
+% then @kbd has no effect.
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else\tclose{\look}\fi
+\else\tclose{\look}\fi}
+
+% Typeset a dimension, e.g., `in' or `pt'.  The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of
+% @dmn{}pt.
+% 
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+\def\l#1{{\li #1}\null}                % 
+
+\def\r#1{{\rm #1}}             % roman font
+% Use of \lowercase was suggested.
+\def\sc#1{{\smallcaps#1}}      % smallcaps font
+\def\ii#1{{\it #1}}            % italic font
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page.  Must do @settitle before @titlepage.
+\def\titlefont#1{{\titlerm #1}}
+
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+\def\shorttitlepage{\parsearg\shorttitlepagezzz}
+\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+       \endgroup\page\hbox{}\page}
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+   \let\subtitlerm=\tenrm
+% I deinstalled the following change because \cmr12 is undefined.
+% This change was not in the ChangeLog anyway.  --rms.
+%   \let\subtitlerm=\cmr12
+   \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+   %
+   \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+   %
+   % Leave some space at the very top of the page.
+   \vglue\titlepagetopglue
+   %
+   % Now you can print the title using @title.
+   \def\title{\parsearg\titlezzz}%
+   \def\titlezzz##1{\leftline{\titlefont{##1}}
+                   % print a rule at the page bottom also.
+                   \finishedtitlepagefalse
+                   \vskip4pt \hrule height 4pt \vskip4pt}%
+   % No rule at page bottom unless we print one at the top with @title.
+   \finishedtitlepagetrue
+   %
+   % Now you can put text using @subtitle.
+   \def\subtitle{\parsearg\subtitlezzz}%
+   \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+   %
+   % @author should come last, but may come many times.
+   \def\author{\parsearg\authorzzz}%
+   \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+      {\authorfont \leftline{##1}}}%
+   %  
+   % Most title ``pages'' are actually two pages long, with space
+   % at the top of the second.  We don't want the ragged left on the second.
+   \let\oldpage = \page
+   \def\page{%
+      \iffinishedtitlepage\else
+        \finishtitlepage
+      \fi
+      \oldpage
+      \let\page = \oldpage
+      \hbox{}}%
+%   \def\page{\oldpage \hbox{}}
+}
+
+\def\Etitlepage{%
+   \iffinishedtitlepage\else
+      \finishtitlepage
+   \fi
+   % It is important to do the page break before ending the group,
+   % because the headline and footline are only empty inside the group.
+   % If we use the new definition of \page, we always get a blank page
+   % after the title page, which we certainly don't want.
+   \oldpage
+   \endgroup
+   \HEADINGSon
+}
+
+\def\finishtitlepage{%
+   \vskip4pt \hrule height 2pt
+   \vskip\titlepagebottomglue
+   \finishedtitlepagetrue
+}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks \evenheadline    % Token sequence for heading line of even pages
+\newtoks \oddheadline     % Token sequence for heading line of odd pages
+\newtoks \evenfootline    % Token sequence for footing line of even pages
+\newtoks \oddfootline     % Token sequence for footing line of odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+                            \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+                            \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what  @headings on  does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
+\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
+\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+%
+}% unbind the catcode of @.
+
+% @headings double     turns headings on for double-sided printing.
+% @headings single     turns headings on for single-sided printing.
+% @headings off                turns them off.
+% @headings on         same as @headings double, retained for compatibility.
+% @headings after      turns on double-sided headings after this page.
+% @headings doubleafter        turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+%\pagealignmacro
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{\number\day\space
+\ifcase\month\or
+January\or February\or March\or April\or May\or June\or
+July\or August\or September\or October\or November\or December\fi
+\space\number\year}
+
+% Use this if you want the Month Day, Year style of output.
+%\def\today{\ifcase\month\or
+%January\or February\or March\or April\or May\or June\or
+%July\or August\or September\or October\or November\or December\fi
+%\space\number\day, \number\year}
+
+% @settitle line...  specifies the title of the document, for headings
+% It generates no output of its own
+
+\def\thistitle{No Title}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+\message{tables,}
+
+% @tabs -- simple alignment
+
+% These don't work.  For one thing, \+ is defined as outer.
+% So these macros cannot even be defined.
+
+%\def\tabs{\parsearg\tabszzz}
+%\def\tabszzz #1{\settabs\+#1\cr}
+%\def\tabline{\parsearg\tablinezzz}
+%\def\tablinezzz #1{\+#1\cr}
+%\def\&{&}
+
+% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent  \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin  \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @vtable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\par \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \par \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\par \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+                 \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+                 \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+  \advance\hsize by -\rightskip
+  \advance\hsize by -\tableindent
+  \setbox0=\hbox{\itemfont{#1}}%
+  \itemindex{#1}%
+  \nobreak % This prevents a break before @itemx.
+  %
+  % Be sure we are not still in the middle of a paragraph.
+  \parskip=0in
+  \par
+  %
+  % If the item text does not fit in the space we have, put it on a line
+  % by itself, and do not allow a page break either before or after that
+  % line.  We do not start a paragraph here because then if the next
+  % command is, e.g., @kindex, the whatsit would get put into the
+  % horizontal list on a line by itself, resulting in extra blank space.
+  \ifdim \wd0>\itemmax
+    \setbox0=\hbox{\hskip \leftskip \hskip -\tableindent \unhbox0}\box0
+    \nobreak
+  \else
+    % The item text fits into the space.  Start a paragraph, so that the
+    % following text (if any) will end up on the same line.  Since that
+    % text will be indented by \tableindent, we make the item text be in
+    % a zero-width box.
+    \noindent
+    \rlap{\hskip -\tableindent\box0}%
+  \fi
+  \endgroup
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+%% Contains a kludge to get @end[description] to work
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1        \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1        \endtabley
+\def\Eftable{\endgraf\endgroup\afterenvbreak}%
+\let\Etable=\relax}}
+
+\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+{\obeylines\obeyspaces%
+\gdef\vtablex #1^^M{%
+\tabley\vritemindex#1        \endtabley
+\def\Evtable{\endgraf\endgroup\afterenvbreak}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+\def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Neccessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\exdentamount=\tableindent
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\endgroup\afterenvbreak}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+  \begingroup % ended by the @end itemsize
+  \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\exdentamount=\itemindent
+\parindent = 0pt %
+\parskip = \smallskipamount %
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\endgroup\afterenvbreak}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+  \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+% 
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list.  No
+% argument is the same as `1'.
+% 
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1  \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+  \begingroup % ended by the @end enumerate
+  %
+  % If we were given no argument, pretend we were given `1'.
+  \def\thearg{#1}%
+  \ifx\thearg\empty \def\thearg{1}\fi
+  %
+  % Detect if the argument is a single token.  If so, it might be a
+  % letter.  Otherwise, the only valid thing it can be is a number.
+  % (We will always have one token, because of the test we just made.
+  % This is a good thing, since \splitoff doesn't work given nothing at
+  % all -- the first parameter is undelimited.)
+  \expandafter\splitoff\thearg\endmark
+  \ifx\rest\empty
+    % Only one token in the argument.  It could still be anything.
+    % A ``lowercase letter'' is one whose \lccode is nonzero.
+    % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+    %   not equal to itself.
+    % Otherwise, we assume it's a number.
+    % 
+    % We need the \relax at the end of the \ifnum lines to stop TeX from
+    % continuing to look for a <number>.
+    % 
+    \ifnum\lccode\expandafter`\thearg=0\relax 
+      \numericenumerate % a number (we hope)
+    \else
+      % It's a letter.
+      \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+        \lowercaseenumerate % lowercase letter
+      \else
+        \uppercaseenumerate % uppercase letter
+      \fi
+    \fi
+  \else
+    % Multiple tokens in the argument.  We hope it's a number.
+    \numericenumerate
+  \fi
+}
+
+% An @enumerate whose labels are integers.  The starting integer is
+% given in \thearg.
+% 
+\def\numericenumerate{%
+  \itemno = \thearg
+  \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+  \itemno = \expandafter`\thearg
+  \startenumeration{%
+    % Be sure we're not beyond the end of the alphabet.
+    \ifnum\itemno=0
+      \errmessage{No more lowercase letters in @enumerate; get a bigger
+                  alphabet}%
+    \fi
+    \char\lccode\itemno
+  }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+  \itemno = \expandafter`\thearg
+  \startenumeration{%
+    % Be sure we're not beyond the end of the alphabet.
+    \ifnum\itemno=0
+      \errmessage{No more uppercase letters in @enumerate; get a bigger
+                  alphabet}
+    \fi
+    \char\uccode\itemno
+  }%
+}
+
+% Call itemizey, adding a period to the first argument and supplying the
+% common last two arguments.  Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+% 
+\def\startenumeration#1{%
+  \advance\itemno by -1
+  \itemizey{#1.}\Eenumerate\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+% 
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that        accumulates this index.  The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+
+\def\newindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1        % Open the file
+\expandafter\xdef\csname#1index\endcsname{%    % Define \xxxindex
+\noexpand\doindex {#1}}
+}
+
+% @defindex foo  ==  \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1        % Open the file
+\expandafter\xdef\csname#1index\endcsname{%    % Define \xxxindex
+\noexpand\docodeindex {#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar    makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+\def\synindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{%    % Define \xxxindex
+\noexpand\doindex {#2}}%
+}
+
+% @syncodeindex foo bar   similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{%    % Define \xxxindex
+\noexpand\docodeindex {#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+%  and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+\def\_{{\realbackslash _}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+\def\char{\realbackslash char}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\copyright{\realbackslash copyright }%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\t##1{\realbackslash r {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+\def\dfn##1{\realbackslash dfn {##1}}%
+\def\emph##1{\realbackslash emph {##1}}%
+}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the active chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+@gdef@realbackslash{\}}
+
+\let\indexbackslash=0  %overridden during \printindex.
+
+\def\doind #1#2{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0% Expand all macros now EXCEPT \folio
+\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+% so it will be output as is; and it will print as backslash in the indx.
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2}%
+}%
+% Now produce the complete index entry.  We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}}}%
+\temp }%
+}\penalty\count10}}
+
+\def\dosubind #1#2#3{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0%
+\def\rawbackslashxx{\indexbackslash}%
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2 #3}%
+}%
+% Now produce the complete index entry.  We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}{#3}}}%
+\temp }%
+}\penalty\count10}}
+
+% The index entry written in the file actually looks like
+%  \entry {sortstring}{page}{topic}
+% or
+%  \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+%  \initial {c}
+%     before the first topic whose initial is c
+%  \entry {topic}{pagelist}
+%     for a topic that is used without subtopics
+%  \primary {topic}
+%     for the beginning of a topic that is used with subtopics
+%  \secondary {subtopic}{pagelist}
+%     for each subtopic.
+
+% Define the user-accessible indexing commands 
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% This is what you call to cause a particular index to get printed.
+% Write
+% @unnumbered Function Index
+% @printindex fn
+
+\def\printindex{\parsearg\doprintindex}
+
+\def\doprintindex#1{%
+  \tex
+  \dobreak \chapheadingskip {10000}
+  \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other
+  \catcode`\$=\other\catcode`\_=\other
+  \catcode`\~=\other
+  %
+  % The following don't help, since the chars were translated
+  % when the raw index was written, and their fonts were discarded
+  % due to \indexnofonts.
+  %\catcode`\"=\active
+  %\catcode`\^=\active
+  %\catcode`\_=\active
+  %\catcode`\|=\active
+  %\catcode`\<=\active
+  %\catcode`\>=\active
+  % %
+  \def\indexbackslash{\rawbackslashxx}
+  \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt
+  \begindoublecolumns
+  %
+  % See if the index file exists and is nonempty.
+  \openin 1 \jobname.#1s
+  \ifeof 1 
+    % \enddoublecolumns gets confused if there is no text in the index,
+    % and it loses the chapter title and the aux file entries for the
+    % index.  The easiest way to prevent this problem is to make sure
+    % there is some text.
+    (Index is nonexistent)
+    \else
+    %
+    % If the index file exists but is empty, then \openin leaves \ifeof
+    % false.  We have to make TeX try to read something from the file, so
+    % it can discover if there is anything in it.
+    \read 1 to \temp
+    \ifeof 1
+      (Index is empty)
+    \else
+      \input \jobname.#1s
+    \fi
+  \fi
+  \closein 1
+  \enddoublecolumns
+  \Etex
+}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+% Same as \bigskipamount except no shrink.
+% \balancecolumns gets confused if there is any shrink.
+\newskip\initialskipamount \initialskipamount 12pt plus4pt
+
+\def\initial #1{%
+{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+\ifdim\lastskip<\initialskipamount
+\removelastskip \penalty-200 \vskip \initialskipamount\fi
+\line{\secbf#1\hfill}\kern 2pt\penalty10000}}
+
+% This typesets a paragraph consisting of #1, dot leaders, and then #2
+% flush to the right margin.  It is used for index and table of contents
+% entries.  The paragraph is indented by \leftskip.
+% 
+\def\entry #1#2{\begingroup
+  %
+  % Start a new paragraph if necessary, so our assignments below can't
+  % affect previous text.
+  \par
+  %
+  % Do not fill out the last line with white space.
+  \parfillskip = 0in
+  %
+  % No extra space above this paragraph.
+  \parskip = 0in
+  %
+  % Do not prefer a separate line ending with a hyphen to fewer lines.
+  \finalhyphendemerits = 0
+  %
+  % \hangindent is only relevant when the entry text and page number
+  % don't both fit on one line.  In that case, bob suggests starting the
+  % dots pretty far over on the line.  Unfortunately, a large
+  % indentation looks wrong when the entry text itself is broken across
+  % lines.  So we use a small indentation and put up with long leaders.
+  % 
+  % \hangafter is reset to 1 (which is the value we want) at the start
+  % of each paragraph, so we need not do anything with that.
+  \hangindent=2em
+  %
+  % When the entry text needs to be broken, just fill out the first line
+  % with blank space.
+  \rightskip = 0pt plus1fil
+  %
+  % Start a ``paragraph'' for the index entry so the line breaking
+  % parameters we've set above will have an effect.
+  \noindent
+  %
+  % Insert the text of the index entry.  TeX will do line-breaking on it.
+  #1%
+  %
+  % If we must, put the page number on a line of its own, and fill out
+  % this line with blank space.  (The \hfil is overwhelmed with the
+  % fill leaders glue in \indexdotfill if the page number does fit.)
+  \hfil\penalty50
+  \null\nobreak\indexdotfill % Have leaders before the page number.
+  %
+  % The `\ ' here is removed by the implicit \unskip that TeX does as
+  % part of (the primitive) \par.  Without it, a spurious underfull
+  % \hbox ensues.
+  \ #2% The page number ends the paragraph.
+  \par
+\endgroup}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+  \hbox{$\mathsurround=0pt \mkern1.5mu . \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
+}}
+
+%% Define two-column mode, which is used in indexes.
+%% Adapted from the TeXbook, page 416.
+\catcode `\@=11
+
+\newbox\partialpage
+
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup
+  % Grab any single-column material above us.
+  \output = {\global\setbox\partialpage
+    =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}%
+  \eject
+  %
+  % Now switch to the double-column output routine.
+  \output={\doublecolumnout}%
+  %
+  % Change the page size parameters.  We could do this once outside this
+  % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+  % format, but then we repeat the same computation.  Repeating a couple
+  % of assignments once per index is clearly meaningless for the
+  % execution time, so we may as well do it once.
+  % 
+  % First we halve the line length, less a little for the gutter between
+  % the columns.  We compute the gutter based on the line length, so it
+  % changes automatically with the paper format.  The magic constant
+  % below is chosen so that the gutter has the same value (well, +- <
+  % 1pt) as it did when we hard-coded it.
+  % 
+  % We put the result in a separate register, \doublecolumhsize, so we
+  % can restore it in \pagesofar, after \hsize itself has (potentially)
+  % been clobbered.
+  % 
+  \doublecolumnhsize = \hsize
+    \advance\doublecolumnhsize by -.04154\hsize
+    \divide\doublecolumnhsize by 2
+  \hsize = \doublecolumnhsize
+  %
+  % Double the \vsize as well.  (We don't need a separate register here,
+  % since nobody clobbers \vsize.)
+  \vsize = 2\vsize
+  \doublecolumnpagegoal
+}
+
+\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage}
+
+\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth
+  \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage
+  \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1}
+  \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3}
+  \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+  \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+}
+\def\doublecolumnpagegoal{%
+  \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@
+}
+\def\pagesofar{\unvbox\partialpage %
+  \hsize=\doublecolumnhsize % have to restore this since output routine
+  \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}}
+\def\doublecolumnout{%
+  \setbox5=\copy255
+  {\vbadness=10000 \doublecolumnsplit}
+  \ifvbox255
+    \setbox0=\vtop to\dimen@{\unvbox0}
+    \setbox2=\vtop to\dimen@{\unvbox2}
+    \onepageout\pagesofar \unvbox255 \penalty\outputpenalty
+  \else
+    \setbox0=\vbox{\unvbox5}
+    \ifvbox0
+      \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+      \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth
+      {\vbadness=10000
+       \loop \global\setbox5=\copy0
+          \setbox1=\vsplit5 to\dimen@
+          \setbox3=\vsplit5 to\dimen@
+          \ifvbox5 \global\advance\dimen@ by1pt \repeat
+        \setbox0=\vbox to\dimen@{\unvbox1}
+        \setbox2=\vbox to\dimen@{\unvbox3}
+        \global\setbox\partialpage=\vbox{\pagesofar}
+        \doublecolumnpagegoal
+      }
+    \fi
+  \fi
+}
+
+\catcode `\@=\other
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno        \secno=0
+\newcount \subsecno     \subsecno=0
+\newcount \subsubsecno  \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount \appendixno  \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+\newwrite \contentsfile
+% This is called from \setfilename.
+\def\opencontents{\openout \contentsfile = \jobname.toc}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it.  @section does likewise
+
+\def\thischapter{} \def\thissection{}
+\def\seccheck#1{\if \pageno<0 %
+\errmessage{@#1 not allowed after generating table of contents}\fi
+%
+}
+
+\def\chapternofonts{%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\def\result{\realbackslash result}
+\def\equiv{\realbackslash equiv}
+\def\expansion{\realbackslash expansion}
+\def\print{\realbackslash print}
+\def\TeX{\realbackslash TeX}
+\def\dots{\realbackslash dots}
+\def\copyright{\realbackslash copyright}
+\def\tt{\realbackslash tt}
+\def\bf{\realbackslash bf }
+\def\w{\realbackslash w}
+\def\less{\realbackslash less}
+\def\gtr{\realbackslash gtr}
+\def\hat{\realbackslash hat}
+\def\char{\realbackslash char}
+\def\tclose##1{\realbackslash tclose {##1}}
+\def\code##1{\realbackslash code {##1}}
+\def\samp##1{\realbackslash samp {##1}}
+\def\r##1{\realbackslash r {##1}}
+\def\b##1{\realbackslash b {##1}}
+\def\key##1{\realbackslash key {##1}}
+\def\file##1{\realbackslash file {##1}}
+\def\kbd##1{\realbackslash kbd {##1}}
+% These are redefined because @smartitalic wouldn't work inside xdef.
+\def\i##1{\realbackslash i {##1}}
+\def\cite##1{\realbackslash cite {##1}}
+\def\var##1{\realbackslash var {##1}}
+\def\emph##1{\realbackslash emph {##1}}
+\def\dfn##1{\realbackslash dfn {##1}}
+}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raise/lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% Choose a numbered-heading macro
+% #1 is heading level if unmodified by @raisesections or @lowersections
+% #2 is text for heading
+\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+  \chapterzzz{#2}
+\or
+  \seczzz{#2}
+\or
+  \numberedsubseczzz{#2}
+\or
+  \numberedsubsubseczzz{#2}
+\else
+  \ifnum \absseclevel<0
+    \chapterzzz{#2}
+  \else
+    \numberedsubsubseczzz{#2}
+  \fi
+\fi
+}
+
+% like \numhead, but chooses appendix heading levels
+\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+  \appendixzzz{#2}
+\or
+  \appendixsectionzzz{#2}
+\or
+  \appendixsubseczzz{#2}
+\or
+  \appendixsubsubseczzz{#2}
+\else
+  \ifnum \absseclevel<0
+    \appendixzzz{#2}
+  \else
+    \appendixsubsubseczzz{#2}
+  \fi
+\fi
+}
+
+% like \numhead, but chooses numberless heading levels
+\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+  \unnumberedzzz{#2}
+\or
+  \unnumberedseczzz{#2}
+\or
+  \unnumberedsubseczzz{#2}
+\or
+  \unnumberedsubsubseczzz{#2}
+\else
+  \ifnum \absseclevel<0
+    \unnumberedzzz{#2}
+  \else
+    \unnumberedsubsubseczzz{#2}
+  \fi
+\fi
+}
+
+
+\def\thischaptername{No Chapter Title}
+\outer\def\chapter{\parsearg\chapteryyy}
+\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz #1{\seccheck{chapter}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \chapno by 1 \message{Chapter \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{Chapter \the\chapno: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp  %
+\donoderef %
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+}}
+
+\outer\def\appendix{\parsearg\appendixyyy}
+\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz #1{\seccheck{appendix}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \appendixno by 1 \message{Appendix \appendixletter}%
+\chapmacro {#1}{Appendix \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry 
+  {#1}{Appendix \appendixletter}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp  %
+\appendixnoderef %
+\global\let\section = \appendixsec
+\global\let\subsection = \appendixsubsec
+\global\let\subsubsection = \appendixsubsubsec
+}}
+
+\outer\def\top{\parsearg\unnumberedyyy}
+\outer\def\unnumbered{\parsearg\unnumberedyyy}
+\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0
+%
+% This used to be simply \message{#1}, but TeX fully expands the
+% argument to \message.  Therefore, if #1 contained @-commands, TeX
+% expanded them.  For example, in `@unnumbered The @cite{Book}', TeX
+% expanded @cite (which turns out to cause errors because \cite is meant
+% to be executed, not expanded).  
+% 
+% Anyway, we don't want the fully-expanded definition of @cite to appear
+% as a result of the \message, we just want `@cite' itself.  We use
+% \the<toks register> to achieve this: TeX expands \the<toks> only once,
+% simply yielding the contents of the <toks register>.
+\toks0 = {#1}\message{(\the\toks0)}%
+%
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp  %
+\unnumbnoderef %
+\global\let\section = \unnumberedsec
+\global\let\subsection = \unnumberedsubsec
+\global\let\subsubsection = \unnumberedsubsubsec
+}}
+
+\outer\def\numberedsec{\parsearg\secyyy}
+\def\secyyy #1{\numhead1{#1}} % normally calls seczzz
+\def\seczzz #1{\seccheck{section}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appenixsection{\parsearg\appendixsecyyy}
+\outer\def\appendixsec{\parsearg\appendixsecyyy}
+\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz #1{\seccheck{appendixsection}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz #1{\seccheck{subsection}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz #1{\seccheck{appendixsubsec}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz #1{\seccheck{subsubsection}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+  {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry %
+  {#1}
+  {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}
+  {\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+  {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry{#1}%
+  {\appendixletter}
+  {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they should now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and
+% such:
+%      1) We use \vbox rather than the earlier \line to permit
+%         overlong headings to fold.
+%      2) \hyphenpenalty is set to 10000 because hyphenation in a
+%         heading is obnoxious; this forbids it.
+%       3) Likewise, headings look best if no \parindent is used, and
+%          if justification is not attempted.  Hence \raggedright.
+
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                  \parindent=0pt\raggedright
+                  \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                  \parindent=0pt\raggedright
+                  \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\heading{\parsearg\secheadingi}
+
+\def\subheading{\parsearg\subsecheadingi}
+
+\def\subsubheading{\parsearg\subsubsecheadingi}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain}
+
+\def\chfplain #1#2{%
+  \pchapsepmacro
+  {%
+    \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                     \parindent=0pt\raggedright
+                     \rm #2\enspace #1}%
+  }%
+  \bigskip
+  \penalty5000
+}
+
+\def\unnchfplain #1{%
+\pchapsepmacro %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                  \parindent=0pt\raggedright
+                  \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                       \parindent=0pt\raggedright
+                       \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen}
+
+% Parameter controlling skip before section headings.
+
+\newskip \subsecheadingskip  \subsecheadingskip = 17pt plus 8pt minus 4pt
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+
+\newskip \secheadingskip  \secheadingskip = 21pt plus 8pt minus 4pt
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+
+% @paragraphindent  is defined for the Info formatting commands only.
+\let\paragraphindent=\comment
+
+% Section fonts are the base font at magstep2, which produces
+% a size a bit more than 14 points in the default situation.   
+
+\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}}
+\def\plainsecheading #1{\secheadingi {#1}}
+\def\secheadingi #1{{\advance \secheadingskip by \parskip %
+\secheadingbreak}%
+{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                 \parindent=0pt\raggedright
+                 \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+
+% Subsection fonts are the base font at magstep1, 
+% which produces a size of 12 points.
+
+\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}}
+\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                     \parindent=0pt\raggedright
+                     \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
+
+\def\subsubsecfonts{\subsecfonts} % Maybe this should change:
+                                 % Perhaps make sssec fonts scaled
+                                 % magstep half
+\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}}
+\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip %
+\subsecheadingbreak}%
+{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                       \parindent=0pt\raggedright
+                       \rm #1\hfill}}%
+\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000}
+
+
+\message{toc printing,}
+
+% Finish up the main text and prepare to read what we've written
+% to \contentsfile.
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\def\startcontents#1{%
+   \pagealignmacro
+   \immediate\closeout \contentsfile
+   \ifnum \pageno>0
+      \pageno = -1             % Request roman numbered pages.
+   \fi
+   % Don't need to put `Contents' or `Short Contents' in the headline. 
+   % It is abundantly clear what they are.
+   \unnumbchapmacro{#1}\def\thischapter{}%
+   \begingroup                 % Set up to handle contents files properly.
+      \catcode`\\=0  \catcode`\{=1  \catcode`\}=2  \catcode`\@=11
+      \raggedbottom             % Worry more about breakpoints than the bottom.
+      \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+}
+
+  
+% Normal (long) toc.
+\outer\def\contents{%
+   \startcontents{Table of Contents}%
+      \input \jobname.toc
+   \endgroup
+   \vfill \eject
+}
+
+% And just the chapters.
+\outer\def\summarycontents{%
+   \startcontents{Short Contents}%
+      %
+      \let\chapentry = \shortchapentry
+      \let\unnumbchapentry = \shortunnumberedentry
+      % We want a true roman here for the page numbers.
+      \secfonts
+      \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+      \rm
+      \advance\baselineskip by 1pt % Open it up a little.
+      \def\secentry ##1##2##3##4{}
+      \def\unnumbsecentry ##1##2{}
+      \def\subsecentry ##1##2##3##4##5{}
+      \def\unnumbsubsecentry ##1##2{}
+      \def\subsubsecentry ##1##2##3##4##5##6{}
+      \def\unnumbsubsubsecentry ##1##2{}
+      \input \jobname.toc
+   \endgroup
+   \vfill \eject
+}
+\let\shortcontents = \summarycontents
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+% See comments in \dochapentry re vbox and related settings
+\def\shortchapentry#1#2#3{%
+  \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}%
+}
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
+% We could simplify the code here by writing out an \appendixentry
+% command in the toc file for appendices, instead of using \chapentry
+% for both, but it doesn't seem worth it.
+\setbox0 = \hbox{\shortcontrm Appendix }
+\newdimen\shortappendixwidth \shortappendixwidth = \wd0
+
+\def\shortchaplabel#1{%
+  % We typeset #1 in a box of constant width, regardless of the text of
+  % #1, so the chapter titles will come out aligned.
+  \setbox0 = \hbox{#1}%
+  \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
+  %
+  % This space should be plenty, since a single number is .5em, and the
+  % widest letter (M) is 1em, at least in the Computer Modern fonts.
+  % (This space doesn't include the extra space that gets added after
+  % the label; that gets put in in \shortchapentry above.)
+  \advance\dimen0 by 1.1em
+  \hbox to \dimen0{#1\hfil}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{%
+  \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the 
+% page number.
+%
+% If the toc has to be broken over pages, we would want to be at chapters 
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+   \penalty-300 \vskip\baselineskip
+   \begingroup
+     \chapentryfonts
+     \tocentry{#1}{\dopageno{#2}}%
+   \endgroup
+   \nobreak\vskip .25\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+  \secentryfonts \leftskip=\tocindent
+  \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+  \subsecentryfonts \leftskip=2\tocindent
+  \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+  \subsubsecentryfonts \leftskip=3\tocindent
+  \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+% Final typesetting of a toc entry; we use the same \entry macro as for
+% the index entries, but we want to suppress hyphenation here.  (We
+% can't do that in the \entry macro, since index entries might consist
+% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+% 
+\def\tocentry#1#2{\begingroup
+  \hyphenpenalty = 10000
+  \entry{#1}{#2}%
+\endgroup}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+
+% Since these characters are used in examples, it should be an even number of 
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox    \newbox\longdblarrowbox
+\newbox\pushcharbox    \newbox\bullbox
+\newbox\equivbox       \newbox\errorbox
+
+\let\ptexequiv = \equiv
+
+%{\tentt
+%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+%                                      depth .1ex\hfil}
+%}
+
+\def\point{$\star$}
+
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% Adapted from the TeXbook's \boxit.
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+
+\global\setbox\errorbox=\hbox to \dimen0{\hfil
+   \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+   \advance\hsize by -2\dimen2 % Rules.
+   \vbox{
+      \hrule height\dimen2
+      \hbox{\vrule width\dimen2 \kern3pt          % Space to left of text.
+         \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+         \kern3pt\vrule width\dimen2}% Space to right.
+      \hrule height\dimen2}
+    \hfil}
+
+% The @error{} command.
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex    escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+\catcode `\%=14
+\catcode 43=12
+\catcode`\"=12
+\catcode`\==12
+\catcode`\|=12
+\catcode`\<=12
+\catcode`\>=12
+\escapechar=`\\
+%
+\let\{=\ptexlbrace
+\let\}=\ptexrbrace
+\let\.=\ptexdot
+\let\*=\ptexstar
+\let\dots=\ptexdots
+\def\@{@}%
+\let\bullet=\ptexbullet
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl
+\let\L=\ptexL
+%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^M gets inside @lisp
+% phr: changed space to \null, to avoid overfull hbox problems.
+{\obeyspaces%
+\gdef\lisppar{\null\endgraf}}
+
+% Make each space character in the input produce a normal interword
+% space in the output.  Don't allow a line break at this space, as this
+% is used only in environments like @example, where each line of input
+% should produce a line of output anyway.
+% 
+{\obeyspaces %
+\gdef\sepspaces{\obeyspaces\let =\tie}}
+
+% Define \obeyedspace to be our active space, whatever it is.  This is
+% for use in \parsearg.
+{\sepspaces %
+\global\let\obeyedspace= }
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical.
+\def\aboveenvbreak{{\advance\envskipamount by \parskip
+\endgraf \ifdim\lastskip<\envskipamount
+\removelastskip \penalty-50 \vskip\envskipamount \fi}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag.  If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \cartouche: draw rectangle w/rounded corners around argument
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+       \ctl\leaders\hrule height\circthick\hfil\ctr
+       \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+       \cbl\leaders\hrule height\circthick\hfil\cbr
+       \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\long\def\cartouche{%
+\begingroup
+       \lskip=\leftskip \rskip=\rightskip
+       \leftskip=0pt\rightskip=0pt %we want these *outside*.
+       \cartinner=\hsize \advance\cartinner by-\lskip 
+                         \advance\cartinner by-\rskip
+       \cartouter=\hsize
+       \advance\cartouter by 18pt % allow for 3pt kerns on either
+%                                   side, and for 6pt waste from
+%                                   each corner char
+       \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+       % Flag to tell @lisp, etc., not to narrow margin.
+       \let\nonarrowing=\comment
+       \vbox\bgroup
+               \baselineskip=0pt\parskip=0pt\lineskip=0pt
+               \carttop
+               \hbox\bgroup
+                       \hskip\lskip
+                       \vrule\kern3pt
+                       \vbox\bgroup
+                               \hsize=\cartinner
+                               \kern3pt
+                               \begingroup
+                                       \baselineskip=\normbskip
+                                       \lineskip=\normlskip
+                                       \parskip=\normpskip
+                                       \vskip -\parskip
+\def\Ecartouche{%
+                               \endgroup
+                               \kern3pt
+                       \egroup
+                       \kern3pt\vrule
+                       \hskip\rskip
+               \egroup
+               \cartbot
+       \egroup
+\endgroup
+}}     
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+  \aboveenvbreak
+  \inENV % This group ends at the end of the body
+  \hfuzz = 12pt % Don't be fussy
+  \sepspaces % Make spaces be word-separators rather than space tokens.
+  \singlespace % single space lines
+  \let\par = \lisppar % don't ignore blank lines
+  \obeylines % each line of input is a line of output
+  \parskip = 0pt
+  \parindent = 0pt
+  \emergencystretch = 0pt % don't try to avoid overfull boxes
+  % @cartouche defines \nonarrowing to inhibit narrowing
+  % at next level down.
+  \ifx\nonarrowing\relax
+    \advance \leftskip by \lispnarrowing
+    \exdentamount=\lispnarrowing
+    \let\exdent=\nofillexdent
+    \let\nonarrowing=\relax
+  \fi
+}
+
+\def\Elisp{\endgroup\afterenvbreak}%
+
+\def\lisp{\begingroup
+  \nonfillstart
+  \def\Elisp{\endgroup\afterenvbreak}%
+  \tt
+  \rawbackslash % output the \ character from the current font
+  \gobble
+}
+
+% Define the \E... control sequence only if we are inside the
+% environment, so the error checking in \end will work.
+% 
+% We must call \lisp last in the definition, since it reads the
+% return following the @example (or whatever) command.
+%
+\def\example{\begingroup \def\Eexample{\Elisp\endgroup}\lisp}
+\def\smallexample{\begingroup \def\Esmallexample{\Elisp\endgroup}\lisp}
+
+% Macro for 9 pt. examples, necessary to print with 5" lines.  From
+% Pavel@xerox.  This is not used for @smallexamples unless the
+% @smallbook command is given.
+%
+\def\smalllispx{\begingroup
+  \nonfillstart
+  \def\Esmalllisp{\endgroup\afterenvbreak}%
+  %
+  % Smaller interline space and fonts for small examples.
+  \baselineskip 10pt
+  \indexfonts \tt
+  \rawbackslash % output the \ character from the current font
+  \gobble
+}
+
+% This is @display; same as @lisp except use roman font.
+%
+\def\display{\begingroup
+  \nonfillstart
+  \def\Edisplay{\endgroup\afterenvbreak}%
+  \gobble
+}
+
+% This is @format; same as @display except don't narrow margins.
+%
+\def\format{\begingroup
+  \let\nonarrowing = t
+  \nonfillstart
+  \def\Eformat{\endgroup\afterenvbreak}
+  \gobble
+}
+
+% @flushleft (same as @format) and @flushright.
+%
+\def\flushleft{\begingroup
+  \let\nonarrowing = t
+  \nonfillstart
+  \def\Eflushleft{\endgroup\afterenvbreak}%
+  \gobble
+}
+\def\flushright{\begingroup
+  \let\nonarrowing = t
+  \nonfillstart
+  \def\Eflushright{\endgroup\afterenvbreak}%
+  \advance\leftskip by 0pt plus 1fill
+  \gobble}
+
+% @quotation does normal linebreaking and narrows the margins.
+%
+\def\quotation{%
+\begingroup\inENV %This group ends at the end of the @quotation body
+{\parskip=0pt  % because we will skip by \parskip too, later
+\aboveenvbreak}%
+\singlespace
+\parindent=0pt
+\def\Equotation{\par\endgroup\afterenvbreak}%
+% @cartouche defines \nonarrowing to inhibit narrowing
+% at next level down.
+\ifx\nonarrowing\relax
+\advance \leftskip by \lispnarrowing
+\advance \rightskip by \lispnarrowing
+\exdentamount=\lispnarrowing
+\let\nonarrowing=\relax
+\fi}
+
+\message{defuns,}
+% Define formatter for defuns
+% First, allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+% Be sure that we always have a definition for `(', etc.  For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+\global\let(=\lparen \global\let)=\rparen
+\global\let[=\lbrack \global\let]=\rbrack
+
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
+\global\advance\parencount by 1 }
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+% also in that case restore the outer-level definition of (.
+\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+\global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text.  This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
+\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+% Get the values of \leftskip and \rightskip as they were
+% outside the @def...
+\dimen2=\leftskip
+\advance\dimen2 by -\defbodyindent
+\dimen3=\rightskip
+\advance\dimen3 by -\defbodyindent
+\noindent        %
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1     %
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+{% Adjust \hsize to exclude the ambient margins,
+% so that \rightline will obey them.
+\advance \hsize by -\dimen2 \advance \hsize by -\dimen3
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}%
+% Make all lines underfull and no complaints:
+\tolerance=10000 \hbadness=10000    
+\advance\leftskip by -\defbodyindent
+\exdentamount=\defbodyindent
+{\df #1}\enskip        % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+%    such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\activeparens\spacesplit#3}
+
+\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+
+\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\spacesplit#3}
+
+\def\defvrparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#4}}}
+
+% This seems to work right in all cases.
+\let\deftpparsebody=\defvrparsebody
+% This fails to work.  When given `@deftp {Data Type} foo_t',
+% it thinks the type name is just `f'.
+%%% This is the same as all the others except for the last line.  We need
+%%% to parse the arguments differently for @deftp, since the ``attributes''
+%%% there are optional.
+%%% 
+%%\def\deftpparsebody #1#2#3#4 {\begingroup\inENV %
+%%\medbreak %
+%%% Define the end token that this defining construct specifies
+%%% so that it will exit this group.
+%%\def#1{\endgraf\endgroup\medbreak}%
+%%\def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+%%\parindent=0in
+%%\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+%%\exdentamount=\defbodyindent
+%%\begingroup\obeylines\parsetpheaderline{#3{#4}}}
+
+%%{\obeylines %
+%%  % Parse the type name and any attributes (field names, etc.).
+%%  % #1 is the beginning of the macro call that will produce the output,
+%%  %   i.e., \deftpheader{CLASS}; this is passed from \deftpparsebody.
+%%  % #2 is the type name, e.g., `struct termios'.
+%%  % #3 is the (possibly empty) attribute list.
+%%  % 
+%%  \gdef\parsetpheaderline#1#2#3^^M{%
+%%    \endgroup % Started in \deftpparsebody.
+%%    %
+%%    % If the attribute list is in fact empty, there will be no space after
+%%    % #2; so we can't put a space in our TeX parameter list.  But if it
+%%    % isn't empty, then #3 will begin with an unwanted space.
+%%    \def\theargs{\ignorespaces #3}%
+%%    %
+%%    % Call the macro to produce the output.
+%%    #1{#2}\theargs %
+%%  }%
+%%}
+
+\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+%  the first is all of #2 before the space token,
+%  the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs #1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\hyphenchar\tensl=0
+#1%
+\hyphenchar\tensl=45
+\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\functionparens
+\code{#1}%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Function}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type.  #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\code{#1} #2}{Function}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% #1 is the classification.  #2 is the data type.  #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup\defname {\code{#2} #3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Macro}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Special Form}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% This definition is run if you use @defunx
+% anywhere other than immediately after a @defun or @defunx.
+
+\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+\def\defunx #1 {\errmessage{@defunx in invalid context}}
+\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}}
+
+% @defmethod, and so on
+
+% @defop {Funny Method} foo-class frobnicate argument
+
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+
+\def\defopheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype{} on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defmethod == @defop Method
+
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+
+\def\defmethodheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% entry in function index
+\begingroup\defname {#2}{Method on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype{} of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar == @defcv {Instance Variable}
+
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+
+\def\defivarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{Instance Variable of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% These definitions are run if you use @defmethodx, etc.,
+% anywhere other than immediately after a @defmethod, etc.
+
+\def\defopx #1 {\errmessage{@defopx in invalid context}}
+\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+% Now @defvar
+
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{Variable}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{User Option}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type.  #2 is the name.
+\def\deftypevarheader #1#2{%
+\doind {vr}{\code{#2}}% Make entry in variables index
+\begingroup\defname {\code{#1} #2}{Variable}%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}%
+\begingroup\defname {\code{#2} #3}{#1}
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% This definition is run if you use @defvarx
+% anywhere other than immediately after a @defvar or @defvarx.
+
+\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+\newif\ifhavexrefs  % True if xref values are known.
+\newif\ifwarnedxrefs  % True if we warned once that they aren't known.
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+\def\appendixsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Yappendixletterandtype}}
+
+% \xref, \pxref, and \ref generate cross-references to specified points.
+% For \xrefX, #1 is the node name, #2 the name of the Info
+% cross-reference, #3 the printed node name, #4 the name of the Info
+% file, #5 the name of the printed manual.  All but the node name can be
+% omitted.
+% 
+\def\pxref#1{see \xrefX[#1,,,,,,,]}
+\def\xref#1{See \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup%
+\def\printedmanual{\ignorespaces #5}%
+\def\printednodename{\ignorespaces #3}%
+%
+\setbox1=\hbox{\printedmanual}%
+\setbox0=\hbox{\printednodename}%
+\ifdim \wd0=0pt%
+\def\printednodename{\ignorespaces #1}%
+%%% Uncommment the following line to make the actual chapter or section title
+%%% appear inside the square brackets.
+%\def\printednodename{#1-title}%
+\fi%
+%
+%
+% If we use \unhbox0 and \unhbox1 to print the node names, TeX does
+% not insert empty discretionaries after hyphens, which means that it
+% will not find a line break at a hyphen in a node names.  Since some
+% manuals are best written with fairly long node names, containing
+% hyphens, this is a loss.  Therefore, we simply give the text of
+% the node name again, so it is as if TeX is seeing it for the first
+% time.
+\ifdim \wd1>0pt
+section ``\printednodename'' in \cite{\printedmanual}%
+\else%
+\turnoffactive%
+\refx{#1-snt}{} [\printednodename], page\tie\refx{#1-pg}{}%
+\fi
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \turnoffactive so that punctuation chars such as underscore
+% work in node names.
+\def\dosetq #1#2{{\let\folio=0 \turnoffactive%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into
+% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thischapter}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 Chapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 Section\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+% 
+\ifx\inputlineno\thisisundefined
+  \let\linenumber = \empty % Non-3.0.
+\else
+  \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+
+\def\refx#1#2{%
+  \expandafter\ifx\csname X#1\endcsname\relax
+    % If not defined, say something at least.
+    $\langle$un\-de\-fined$\rangle$%
+    \ifhavexrefs
+      \message{\linenumber Undefined cross reference `#1'.}%
+    \else
+      \ifwarnedxrefs\else
+        \global\warnedxrefstrue
+        \message{Cross reference values unknown; you must run TeX again.}%
+      \fi
+    \fi
+  \else
+    % It's defined, so just use it.
+    \csname X#1\endcsname
+  \fi
+  #2% Output the suffix in any case.
+}
+
+% Read the last existing aux file, if any.  No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+\def\readauxfile{%
+\begingroup
+\catcode `\^^@=\other
+\catcode `\\ 1=\other
+\catcode `\\ 2=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\\v=\other
+\catcode `\^^L=\other
+\catcode `\\ e=\other
+\catcode `\\ f=\other
+\catcode `\\10=\other
+\catcode `\\11=\other
+\catcode `\\12=\other
+\catcode `\\13=\other
+\catcode `\\14=\other
+\catcode `\\15=\other
+\catcode `\\16=\other
+\catcode `\\17=\other
+\catcode `\\18=\other
+\catcode `\\19=\other
+\catcode 26=\other
+\catcode `\^^[=\other
+\catcode `\^^\=\other
+\catcode `\^^]=\other
+\catcode `\^^^=\other
+\catcode `\^^_=\other
+\catcode `\@=\other
+\catcode `\^=\other
+\catcode `\~=\other
+\catcode `\[=\other
+\catcode `\]=\other
+\catcode`\"=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode `\$=\other
+\catcode `\#=\other
+\catcode `\&=\other
+% `\+ does not work, so use 43.
+\catcode 43=\other
+% the aux file uses ' as the escape.
+% Turn off \ as an escape so we do not lose on
+% entries which were dumped with control sequences in their names.
+% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+% Reference to such entries still does not work the way one would wish,
+% but at least they do not bomb out when the aux file is read in.
+\catcode `\{=1 \catcode `\}=2
+\catcode `\%=\other
+\catcode `\'=0
+\catcode `\\=\other
+\openin 1 \jobname.aux
+\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue
+\global\warnedobstrue
+\fi
+% Open the new aux file.  Tex will close it automatically at exit.
+\openout \auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed.
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only..
+\let\footnotestyle=\comment
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+%
+% Auto-number footnotes.  Otherwise like plain.
+\gdef\footnote{%
+  \global\advance\footnoteno by \@ne
+  \edef\thisfootno{$^{\the\footnoteno}$}%
+  %
+  % In case the footnote comes at the end of a sentence, preserve the
+  % extra spacing after we do the footnote number.
+  \let\@sf\empty
+  \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+  %
+  % Remove inadvertent blank space before typesetting the footnote number.
+  \unskip
+  \thisfootno\@sf
+  \footnotezzz
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter.  Our footnotes don't need to be so general.
+% 
+\long\gdef\footnotezzz#1{\insert\footins{%
+  % We want to typeset this text as a normal paragraph, even if the
+  % footnote reference occurs in (for example) a display environment.
+  % So reset some parameters.
+  \interlinepenalty\interfootnotelinepenalty
+  \splittopskip\ht\strutbox % top baseline for broken footnotes
+  \splitmaxdepth\dp\strutbox
+  \floatingpenalty\@MM
+  \leftskip\z@skip
+  \rightskip\z@skip
+  \spaceskip\z@skip
+  \xspaceskip\z@skip
+  \parindent\defaultparindent
+  %
+  % Hang the footnote text off the number.
+  \hang
+  \textindent{\thisfootno}%
+  %
+  % Don't crash into the line above the footnote text.  Since this
+  % expands into a box, it must come within the paragraph, lest it
+  % provide a place where TeX can split the footnote.
+  \footstrut
+  #1\strut}%
+}
+
+}%end \catcode `\@=11
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly.  There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+% 
+\def\lineskipfactor{.1}
+\def\strutheightpercent{.71}
+\def\strutdepthpercent{.29}
+%
+\def\setleading#1{%
+  \baselineskip = #1\relax
+  \normalbaselineskip = \baselineskip
+  \lineskip = \lineskipfactor\baselineskip
+  \setbox\strutbox =\hbox{%
+    \vrule width0pt height\strutheightpercent\baselineskip
+                    depth \strutdepthpercent \baselineskip
+  }%
+}
+
+% @| inserts a changebar to the left of the current line.  It should
+% surround any changed text.  This approach does *not* work if the
+% change spans more than two lines of output.  To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+% 
+\def\|{%
+  % \vadjust can only be used in horizontal mode.
+  \leavevmode
+  %
+  % Append this vertical mode material after the current line in the output.
+  \vadjust{%
+    % We want to insert a rule with the height and depth of the current
+    % leading; that is exactly what \strutbox is supposed to record.
+    \vskip-\baselineskip
+    %
+    % \vadjust-items are inserted at the left edge of the type.  So
+    % the \llap here moves out into the left-hand margin.
+    \llap{%
+      %
+      % For a thicker or thinner bar, change the `1pt'.
+      \vrule height\baselineskip width1pt
+      %
+      % This is the space between the bar and the text.
+      \hskip 12pt
+    }%
+  }%
+}
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+% 
+\def\finalout{\overfullrule=0pt}
+
+
+% End of control word definitions.
+
+\message{and turning on texinfo input format.}
+
+\def\openindices{%
+   \newindex{cp}%
+   \newcodeindex{fn}%
+   \newcodeindex{vr}%
+   \newcodeindex{tp}%
+   \newcodeindex{ky}%
+   \newcodeindex{pg}%
+}
+
+% Set some numeric style parameters, for 8.5 x 11 format.
+
+%\hsize = 6.5in
+\newdimen\defaultparindent \defaultparindent = 15pt
+\parindent = \defaultparindent
+\parskip 18pt plus 1pt
+\setleading{15pt}
+\advance\topskip by 1.2cm
+
+% Prevent underfull vbox error messages.
+\vbadness=10000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything.  We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize.  This makes it come to about 9pt for the 8.5x11 format.
+% 
+\ifx\emergencystretch\thisisundefined
+  % Allow us to assign to \emergencystretch anyway.
+  \def\emergencystretch{\dimen0}%
+\else
+  \emergencystretch = \hsize
+  \divide\emergencystretch by 45
+\fi
+
+% Use @smallbook to reset parameters for 7x9.5 format  (or else 7x9.25)
+\def\smallbook{
+
+% These values for secheadingskip and subsecheadingskip are
+% experiments.  RJC 7 Aug 1992
+\global\secheadingskip = 17pt plus 6pt minus 3pt
+\global\subsecheadingskip = 14pt plus 6pt minus 3pt
+
+\global\lispnarrowing = 0.3in
+\setleading{12pt}
+\advance\topskip by -1cm
+\global\parskip 3pt plus 1pt
+\global\hsize = 5in
+\global\vsize=7.5in
+\global\tolerance=700
+\global\hfuzz=1pt
+\global\contentsrightmargin=0pt
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+
+\global\let\smalllisp=\smalllispx
+\global\let\smallexample=\smalllispx
+\global\def\Esmallexample{\Esmalllisp}
+}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{
+\global\tolerance=700
+\global\hfuzz=1pt
+\setleading{12pt}
+\global\parskip 15pt plus 1pt
+
+\global\vsize= 53\baselineskip
+\advance\vsize by \topskip
+%\global\hsize=   5.85in     % A4 wide 10pt
+\global\hsize=  6.5in
+\global\outerhsize=\hsize
+\global\advance\outerhsize by 0.5in
+\global\outervsize=\vsize
+\global\advance\outervsize by 0.6in
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise.  Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+% 
+\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt \char '042}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt \char '176}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\lvvmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+% \lvvmode is equivalent in function to \leavevmode.
+% Using \leavevmode runs into trouble when written out to
+% an index file due to the expansion of \leavevmode into ``\unhbox
+% \voidb@x'' ---which looks to TeX like ``\unhbox \voidb\x'' due to our
+% magic tricks with @.
+\def\lvvmode{\vbox to 0pt{}}
+
+\catcode`\|=\active
+\def|{{\tt \char '174}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+\def\turnoffactive{\let"=\normaldoublequote
+\let~=\normaltilde
+\let^=\normalcaret
+\let_=\normalunderscore
+\let|=\normalverticalbar
+\let<=\normalless
+\let>=\normalgreater
+\let+=\normalplus}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% Say @foo, not \foo, in error messages.
+\escapechar=`\@
+
+% \catcode 17=0   % Define control-q
+\catcode`\\=\active
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing 
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix 
+% that, assuming it is called before the first `\' could plausibly occur.
+% 
+@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi}
+
+%% These look ok in all fonts, so just make them not special.  The @rm below
+%% makes sure that the current font starts out as the newly loaded cmr10
+@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+
+@textfonts
+@rm
+
+@c Local variables:
+@c page-delimiter: "^\\\\message"
+@c End:
diff --git a/lib/termcap/termcap.c b/lib/termcap/termcap.c
new file mode 100644 (file)
index 0000000..3d6125a
--- /dev/null
@@ -0,0 +1,716 @@
+/* Work-alike for termcap, plus extra features.
+   Copyright (C) 1985, 1986, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Emacs config.h may rename various library functions such as malloc.  */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else /* not HAVE_CONFIG_H */
+
+#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
+#define bcopy(s, d, n) memcpy ((d), (s), (n))
+#endif
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#include <string.h>
+#else
+char *getenv ();
+char *malloc ();
+char *realloc ();
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef _POSIX_VERSION
+#include <fcntl.h>
+#endif
+
+#endif /* not HAVE_CONFIG_H */
+
+#ifndef NULL
+#define NULL (char *) 0
+#endif
+
+/* BUFSIZE is the initial size allocated for the buffer
+   for reading the termcap file.
+   It is not a limit.
+   Make it large normally for speed.
+   Make it variable when debugging, so can exercise
+   increasing the space dynamically.  */
+
+#ifndef BUFSIZE
+#ifdef DEBUG
+#define BUFSIZE bufsize
+
+int bufsize = 128;
+#else
+#define BUFSIZE 2048
+#endif
+#endif
+
+#ifndef emacs
+static void
+memory_out ()
+{
+  write (2, "virtual memory exhausted\n", 25);
+  exit (1);
+}
+
+static char *
+xmalloc (size)
+     unsigned size;
+{
+  register char *tem = malloc (size);
+
+  if (!tem)
+    memory_out ();
+  return tem;
+}
+
+static char *
+xrealloc (ptr, size)
+     char *ptr;
+     unsigned size;
+{
+  register char *tem = realloc (ptr, size);
+
+  if (!tem)
+    memory_out ();
+  return tem;
+}
+#endif /* not emacs */
+\f
+/* Looking up capabilities in the entry already found.  */
+
+/* The pointer to the data made by tgetent is left here
+   for tgetnum, tgetflag and tgetstr to find.  */
+static char *term_entry;
+
+static char *tgetst1 ();
+
+/* Search entry BP for capability CAP.
+   Return a pointer to the capability (in BP) if found,
+   0 if not found.  */
+
+static char *
+find_capability (bp, cap)
+     register char *bp, *cap;
+{
+  for (; *bp; bp++)
+    if (bp[0] == ':'
+       && bp[1] == cap[0]
+       && bp[2] == cap[1])
+      return &bp[4];
+  return NULL;
+}
+
+int
+tgetnum (cap)
+     char *cap;
+{
+  register char *ptr = find_capability (term_entry, cap);
+  if (!ptr || ptr[-1] != '#')
+    return -1;
+  return atoi (ptr);
+}
+
+int
+tgetflag (cap)
+     char *cap;
+{
+  register char *ptr = find_capability (term_entry, cap);
+  return ptr && ptr[-1] == ':';
+}
+
+/* Look up a string-valued capability CAP.
+   If AREA is non-null, it points to a pointer to a block in which
+   to store the string.  That pointer is advanced over the space used.
+   If AREA is null, space is allocated with `malloc'.  */
+
+char *
+tgetstr (cap, area)
+     char *cap;
+     char **area;
+{
+  register char *ptr = find_capability (term_entry, cap);
+  if (!ptr || (ptr[-1] != '=' && ptr[-1] != '~'))
+    return NULL;
+  return tgetst1 (ptr, area);
+}
+
+/* Table, indexed by a character in range 0100 to 0140 with 0100 subtracted,
+   gives meaning of character following \, or a space if no special meaning.
+   Eight characters per line within the string.  */
+
+static char esctab[]
+  = " \007\010  \033\014 \
+      \012 \
+  \015 \011 \013 \
+        ";
+
+/* PTR points to a string value inside a termcap entry.
+   Copy that value, processing \ and ^ abbreviations,
+   into the block that *AREA points to,
+   or to newly allocated storage if AREA is NULL.
+   Return the address to which we copied the value,
+   or NULL if PTR is NULL.  */
+
+static char *
+tgetst1 (ptr, area)
+     char *ptr;
+     char **area;
+{
+  register char *p, *r;
+  register int c;
+  register int size;
+  char *ret;
+  register int c1;
+
+  if (!ptr)
+    return NULL;
+
+  /* `ret' gets address of where to store the string.  */
+  if (!area)
+    {
+      /* Compute size of block needed (may overestimate).  */
+      p = ptr;
+      while ((c = *p++) && c != ':' && c != '\n')
+       ;
+      ret = (char *) xmalloc (p - ptr + 1);
+    }
+  else
+    ret = *area;
+
+  /* Copy the string value, stopping at null or colon.
+     Also process ^ and \ abbreviations.  */
+  p = ptr;
+  r = ret;
+  while ((c = *p++) && c != ':' && c != '\n')
+    {
+      if (c == '^')
+       c = *p++ & 037;
+      else if (c == '\\')
+       {
+         c = *p++;
+         if (c >= '0' && c <= '7')
+           {
+             c -= '0';
+             size = 0;
+
+             while (++size < 3 && (c1 = *p) >= '0' && c1 <= '7')
+               {
+                 c *= 8;
+                 c += c1 - '0';
+                 p++;
+               }
+           }
+         else if (c >= 0100 && c < 0200)
+           {
+             c1 = esctab[(c & ~040) - 0100];
+             if (c1 != ' ')
+               c = c1;
+           }
+       }
+      *r++ = c;
+    }
+  *r = '\0';
+  /* Update *AREA.  */
+  if (area)
+    *area = r + 1;
+  return ret;
+}
+\f
+/* Outputting a string with padding.  */
+
+short ospeed;
+/* If OSPEED is 0, we use this as the actual baud rate.  */
+int tputs_baud_rate;
+char PC;
+
+/* Actual baud rate if positive;
+   - baud rate / 100 if negative.  */
+
+static short speeds[] =
+  {
+#ifdef VMS
+    0, 50, 75, 110, 134, 150, -3, -6, -12, -18,
+    -20, -24, -36, -48, -72, -96, -192
+#else /* not VMS */
+    0, 50, 75, 110, 135, 150, -2, -3, -6, -12,
+    -18, -24, -48, -96, -192, -384
+#endif /* not VMS */
+  };
+
+void
+tputs (str, nlines, outfun)
+     register char *str;
+     int nlines;
+     register int (*outfun) ();
+{
+  register int padcount = 0;
+  register int speed;
+
+#ifdef emacs
+  extern baud_rate;
+  speed = baud_rate;
+#else
+  if (ospeed == 0)
+    speed = tputs_baud_rate;
+  else
+    speed = speeds[ospeed];
+#endif
+
+  if (!str)
+    return;
+
+  while (*str >= '0' && *str <= '9')
+    {
+      padcount += *str++ - '0';
+      padcount *= 10;
+    }
+  if (*str == '.')
+    {
+      str++;
+      padcount += *str++ - '0';
+    }
+  if (*str == '*')
+    {
+      str++;
+      padcount *= nlines;
+    }
+  while (*str)
+    (*outfun) (*str++);
+
+  /* padcount is now in units of tenths of msec.  */
+  padcount *= speeds[ospeed];
+  padcount += 500;
+  padcount /= 1000;
+  if (speeds[ospeed] < 0)
+    padcount = -padcount;
+  else
+    {
+      padcount += 50;
+      padcount /= 100;
+    }
+
+  while (padcount-- > 0)
+    (*outfun) (PC);
+}
+\f
+/* Finding the termcap entry in the termcap data base.  */
+
+struct buffer
+  {
+    char *beg;
+    int size;
+    char *ptr;
+    int ateof;
+    int full;
+  };
+
+/* Forward declarations of static functions.  */
+
+static int scan_file ();
+static char *gobble_line ();
+static int compare_contin ();
+static int name_match ();
+
+#ifdef VMS
+
+#include <rmsdef.h>
+#include <fab.h>
+#include <nam.h>
+
+static int
+valid_filename_p (fn)
+     char *fn;
+{
+  struct FAB fab = cc$rms_fab;
+  struct NAM nam = cc$rms_nam;
+  char esa[NAM$C_MAXRSS];
+
+  fab.fab$l_fna = fn;
+  fab.fab$b_fns = strlen(fn);
+  fab.fab$l_nam = &nam;
+  fab.fab$l_fop = FAB$M_NAM;
+
+  nam.nam$l_esa = esa;
+  nam.nam$b_ess = sizeof esa;
+
+  return SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL;
+}
+
+#else /* !VMS */
+
+#define valid_filename_p(fn) (*(fn) == '/')
+
+#endif /* !VMS */
+
+/* Find the termcap entry data for terminal type NAME
+   and store it in the block that BP points to.
+   Record its address for future use.
+
+   If BP is null, space is dynamically allocated.
+
+   Return -1 if there is some difficulty accessing the data base
+   of terminal types,
+   0 if the data base is accessible but the type NAME is not defined
+   in it, and some other value otherwise.  */
+
+int
+tgetent (bp, name)
+     char *bp, *name;
+{
+  register char *termcap_name;
+  register int fd;
+  struct buffer buf;
+  register char *bp1;
+  char *bp2;
+  char *term;
+  int malloc_size = 0;
+  register int c;
+  char *tcenv;                 /* TERMCAP value, if it contains :tc=.  */
+  char *indirect = NULL;       /* Terminal type in :tc= in TERMCAP value.  */
+  int filep;
+
+  termcap_name = getenv ("TERMCAP");
+  if (termcap_name && *termcap_name == '\0')
+    termcap_name = NULL;
+
+  filep = termcap_name && valid_filename_p (termcap_name);
+
+  /* If termcap_name is non-null and starts with / (in the un*x case, that is),
+     it is a file name to use instead of /etc/termcap.
+     If it is non-null and does not start with /,
+     it is the entry itself, but only if
+     the name the caller requested matches the TERM variable.  */
+
+  if (termcap_name && !filep && !strcmp (name, getenv ("TERM")))
+    {
+      indirect = tgetst1 (find_capability (termcap_name, "tc"), (char **) 0);
+      if (!indirect)
+       {
+         if (!bp)
+           bp = termcap_name;
+         else
+           strcpy (bp, termcap_name);
+         goto ret;
+       }
+      else
+       {                       /* It has tc=.  Need to read /etc/termcap.  */
+         tcenv = termcap_name;
+         termcap_name = NULL;
+       }
+    }
+
+  if (!termcap_name || !filep)
+#ifdef VMS
+    termcap_name = "emacs_library:[etc]termcap.dat";
+#else
+    termcap_name = "/etc/termcap";
+#endif
+
+  /* Here we know we must search a file and termcap_name has its name.  */
+
+  fd = open (termcap_name, 0, 0);
+  if (fd < 0)
+    return -1;
+
+  buf.size = BUFSIZE;
+  /* Add 1 to size to ensure room for terminating null.  */
+  buf.beg = (char *) xmalloc (buf.size + 1);
+  term = indirect ? indirect : name;
+
+  if (!bp)
+    {
+      malloc_size = indirect ? strlen (tcenv) + 1 : buf.size;
+      bp = (char *) xmalloc (malloc_size);
+    }
+  bp1 = bp;
+
+  if (indirect)
+    /* Copy the data from the environment variable.  */
+    {
+      strcpy (bp, tcenv);
+      bp1 += strlen (tcenv);
+    }
+
+  while (term)
+    {
+      /* Scan the file, reading it via buf, till find start of main entry.  */
+      if (scan_file (term, fd, &buf) == 0)
+       {
+         close (fd);
+         free (buf.beg);
+         if (malloc_size)
+           free (bp);
+         return 0;
+       }
+
+      /* Free old `term' if appropriate.  */
+      if (term != name)
+       free (term);
+
+      /* If BP is malloc'd by us, make sure it is big enough.  */
+      if (malloc_size)
+       {
+         malloc_size = bp1 - bp + buf.size;
+         termcap_name = (char *) xrealloc (bp, malloc_size);
+         bp1 += termcap_name - bp;
+         bp = termcap_name;
+       }
+
+      bp2 = bp1;
+
+      /* Copy the line of the entry from buf into bp.  */
+      termcap_name = buf.ptr;
+      while ((*bp1++ = c = *termcap_name++) && c != '\n')
+       /* Drop out any \ newline sequence.  */
+       if (c == '\\' && *termcap_name == '\n')
+         {
+           bp1--;
+           termcap_name++;
+         }
+      *bp1 = '\0';
+
+      /* Does this entry refer to another terminal type's entry?
+        If something is found, copy it into heap and null-terminate it.  */
+      term = tgetst1 (find_capability (bp2, "tc"), (char **) 0);
+    }
+
+  close (fd);
+  free (buf.beg);
+
+  if (malloc_size)
+    bp = (char *) xrealloc (bp, bp1 - bp + 1);
+
+ ret:
+  term_entry = bp;
+  if (malloc_size)
+    return (int) bp;
+  return 1;
+}
+
+/* Given file open on FD and buffer BUFP,
+   scan the file from the beginning until a line is found
+   that starts the entry for terminal type STR.
+   Return 1 if successful, with that line in BUFP,
+   or 0 if no entry is found in the file.  */
+
+static int
+scan_file (str, fd, bufp)
+     char *str;
+     int fd;
+     register struct buffer *bufp;
+{
+  register char *end;
+
+  bufp->ptr = bufp->beg;
+  bufp->full = 0;
+  bufp->ateof = 0;
+  *bufp->ptr = '\0';
+
+  lseek (fd, 0L, 0);
+
+  while (!bufp->ateof)
+    {
+      /* Read a line into the buffer.  */
+      end = NULL;
+      do
+       {
+         /* if it is continued, append another line to it,
+            until a non-continued line ends.  */
+         end = gobble_line (fd, bufp, end);
+       }
+      while (!bufp->ateof && end[-2] == '\\');
+
+      if (*bufp->ptr != '#'
+         && name_match (bufp->ptr, str))
+       return 1;
+
+      /* Discard the line just processed.  */
+      bufp->ptr = end;
+    }
+  return 0;
+}
+
+/* Return nonzero if NAME is one of the names specified
+   by termcap entry LINE.  */
+
+static int
+name_match (line, name)
+     char *line, *name;
+{
+  register char *tem;
+
+  if (!compare_contin (line, name))
+    return 1;
+  /* This line starts an entry.  Is it the right one?  */
+  for (tem = line; *tem && *tem != '\n' && *tem != ':'; tem++)
+    if (*tem == '|' && !compare_contin (tem + 1, name))
+      return 1;
+
+  return 0;
+}
+
+static int
+compare_contin (str1, str2)
+     register char *str1, *str2;
+{
+  register int c1, c2;
+  while (1)
+    {
+      c1 = *str1++;
+      c2 = *str2++;
+      while (c1 == '\\' && *str1 == '\n')
+       {
+         str1++;
+         while ((c1 = *str1++) == ' ' || c1 == '\t');
+       }
+      if (c2 == '\0')
+       {
+         /* End of type being looked up.  */
+         if (c1 == '|' || c1 == ':')
+           /* If end of name in data base, we win.  */
+           return 0;
+         else
+           return 1;
+        }
+      else if (c1 != c2)
+       return 1;
+    }
+}
+
+/* Make sure that the buffer <- BUFP contains a full line
+   of the file open on FD, starting at the place BUFP->ptr
+   points to.  Can read more of the file, discard stuff before
+   BUFP->ptr, or make the buffer bigger.
+
+   Return the pointer to after the newline ending the line,
+   or to the end of the file, if there is no newline to end it.
+
+   Can also merge on continuation lines.  If APPEND_END is
+   non-null, it points past the newline of a line that is
+   continued; we add another line onto it and regard the whole
+   thing as one line.  The caller decides when a line is continued.  */
+
+static char *
+gobble_line (fd, bufp, append_end)
+     int fd;
+     register struct buffer *bufp;
+     char *append_end;
+{
+  register char *end;
+  register int nread;
+  register char *buf = bufp->beg;
+  register char *tem;
+
+  if (!append_end)
+    append_end = bufp->ptr;
+
+  while (1)
+    {
+      end = append_end;
+      while (*end && *end != '\n') end++;
+      if (*end)
+        break;
+      if (bufp->ateof)
+       return buf + bufp->full;
+      if (bufp->ptr == buf)
+       {
+         if (bufp->full == bufp->size)
+           {
+             bufp->size *= 2;
+             /* Add 1 to size to ensure room for terminating null.  */
+             tem = (char *) xrealloc (buf, bufp->size + 1);
+             bufp->ptr = (bufp->ptr - buf) + tem;
+             append_end = (append_end - buf) + tem;
+             bufp->beg = buf = tem;
+           }
+       }
+      else
+       {
+         append_end -= bufp->ptr - buf;
+         bcopy (bufp->ptr, buf, bufp->full -= bufp->ptr - buf);
+         bufp->ptr = buf;
+       }
+      if (!(nread = read (fd, buf + bufp->full, bufp->size - bufp->full)))
+       bufp->ateof = 1;
+      bufp->full += nread;
+      buf[bufp->full] = '\0';
+    }
+  return end + 1;
+}
+\f
+#ifdef TEST
+
+#ifdef NULL
+#undef NULL
+#endif
+
+#include <stdio.h>
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char *term;
+  char *buf;
+
+  term = argv[1];
+  printf ("TERM: %s\n", term);
+
+  buf = (char *) tgetent (0, term);
+  if ((int) buf <= 0)
+    {
+      printf ("No entry.\n");
+      return 0;
+    }
+
+  printf ("Entry: %s\n", buf);
+
+  tprint ("cm");
+  tprint ("AL");
+
+  printf ("co: %d\n", tgetnum ("co"));
+  printf ("am: %d\n", tgetflag ("am"));
+}
+
+tprint (cap)
+     char *cap;
+{
+  char *x = tgetstr (cap, 0);
+  register char *y;
+
+  printf ("%s: ", cap);
+  if (x)
+    {
+      for (y = x; *y; y++)
+       if (*y <= ' ' || *y == 0177)
+         printf ("\\%0o", *y);
+       else
+         putchar (*y);
+      free (x);
+    }
+  else
+    printf ("none");
+  putchar ('\n');
+}
+
+#endif /* TEST */
+
diff --git a/lib/termcap/termcap.h b/lib/termcap/termcap.h
new file mode 100644 (file)
index 0000000..e9d9361
--- /dev/null
@@ -0,0 +1,62 @@
+/* Declarations for termcap library.
+   Copyright (C) 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef _TERMCAP_H
+#define _TERMCAP_H 1
+
+#if __STDC__
+
+extern int tgetent (char *buffer, const char *termtype);
+
+extern int tgetnum (const char *name);
+extern int tgetflag (const char *name);
+extern char *tgetstr (const char *name, char **area);
+
+extern char PC;
+extern short ospeed;
+extern void tputs (const char *string, int nlines, int (*outfun) ());
+
+extern char *tparam (const char *ctlstring, char *buffer, int size, ...);
+
+extern char *UP;
+extern char *BC;
+
+extern char *tgoto (const char *cstring, int hpos, int vpos);
+
+#else /* not __STDC__ */
+
+extern int tgetent ();
+
+extern int tgetnum ();
+extern int tgetflag ();
+extern char *tgetstr ();
+
+extern char PC;
+extern short ospeed;
+
+extern void tputs ();
+
+extern char *tparam ();
+
+extern char *UP;
+extern char *BC;
+
+extern char *tgoto ();
+
+#endif /* not __STDC__ */
+
+#endif /* not _TERMCAP_H */
diff --git a/lib/termcap/tparam.c b/lib/termcap/tparam.c
new file mode 100644 (file)
index 0000000..4badb65
--- /dev/null
@@ -0,0 +1,325 @@
+/* Merge parameters into a termcap entry string.
+   Copyright (C) 1985, 1987, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Emacs config.h may rename various library functions such as malloc.  */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else /* not HAVE_CONFIG_H */
+
+#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
+#define bcopy(s, d, n) memcpy ((d), (s), (n))
+#endif
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#include <string.h>
+#else
+char *malloc ();
+char *realloc ();
+#endif
+
+#endif /* not HAVE_CONFIG_H */
+
+#ifndef NULL
+#define NULL (char *) 0
+#endif
+\f
+#ifndef emacs
+static void
+memory_out ()
+{
+  write (2, "virtual memory exhausted\n", 25);
+  exit (1);
+}
+
+static char *
+xmalloc (size)
+     unsigned size;
+{
+  register char *tem = malloc (size);
+
+  if (!tem)
+    memory_out ();
+  return tem;
+}
+
+static char *
+xrealloc (ptr, size)
+     char *ptr;
+     unsigned size;
+{
+  register char *tem = realloc (ptr, size);
+
+  if (!tem)
+    memory_out ();
+  return tem;
+}
+#endif /* not emacs */
+\f
+/* Assuming STRING is the value of a termcap string entry
+   containing `%' constructs to expand parameters,
+   merge in parameter values and store result in block OUTSTRING points to.
+   LEN is the length of OUTSTRING.  If more space is needed,
+   a block is allocated with `malloc'.
+
+   The value returned is the address of the resulting string.
+   This may be OUTSTRING or may be the address of a block got with `malloc'.
+   In the latter case, the caller must free the block.
+
+   The fourth and following args to tparam serve as the parameter values.  */
+
+static char *tparam1 ();
+
+/* VARARGS 2 */
+char *
+tparam (string, outstring, len, arg0, arg1, arg2, arg3)
+     char *string;
+     char *outstring;
+     int len;
+     int arg0, arg1, arg2, arg3;
+{
+#ifdef NO_ARG_ARRAY
+  int arg[4];
+  arg[0] = arg0;
+  arg[1] = arg1;
+  arg[2] = arg2;
+  arg[3] = arg3;
+  return tparam1 (string, outstring, len, NULL, NULL, arg);
+#else
+  return tparam1 (string, outstring, len, NULL, NULL, &arg0);
+#endif
+}
+
+char *BC;
+char *UP;
+
+static char tgoto_buf[50];
+
+char *
+tgoto (cm, hpos, vpos)
+     char *cm;
+     int hpos, vpos;
+{
+  int args[2];
+  if (!cm)
+    return NULL;
+  args[0] = vpos;
+  args[1] = hpos;
+  return tparam1 (cm, tgoto_buf, 50, UP, BC, args);
+}
+
+static char *
+tparam1 (string, outstring, len, up, left, argp)
+     char *string;
+     char *outstring;
+     int len;
+     char *up, *left;
+     register int *argp;
+{
+  register int c;
+  register char *p = string;
+  register char *op = outstring;
+  char *outend;
+  int outlen = 0;
+
+  register int tem;
+  int *old_argp = argp;
+  int doleft = 0;
+  int doup = 0;
+
+  outend = outstring + len;
+
+  while (1)
+    {
+      /* If the buffer might be too short, make it bigger.  */
+      if (op + 5 >= outend)
+       {
+         register char *new;
+         if (outlen == 0)
+           {
+             outlen = len + 40;
+             new = (char *) xmalloc (outlen);
+             outend += 40;
+             bcopy (outstring, new, op - outstring);
+           }
+         else
+           {
+             outend += outlen;
+             outlen *= 2;
+             new = (char *) xrealloc (outstring, outlen);
+           }
+         op += new - outstring;
+         outend += new - outstring;
+         outstring = new;
+       }
+      c = *p++;
+      if (!c)
+       break;
+      if (c == '%')
+       {
+         c = *p++;
+         tem = *argp;
+         switch (c)
+           {
+           case 'd':           /* %d means output in decimal.  */
+             if (tem < 10)
+               goto onedigit;
+             if (tem < 100)
+               goto twodigit;
+           case '3':           /* %3 means output in decimal, 3 digits.  */
+             if (tem > 999)
+               {
+                 *op++ = tem / 1000 + '0';
+                 tem %= 1000;
+               }
+             *op++ = tem / 100 + '0';
+           case '2':           /* %2 means output in decimal, 2 digits.  */
+           twodigit:
+             tem %= 100;
+             *op++ = tem / 10 + '0';
+           onedigit:
+             *op++ = tem % 10 + '0';
+             argp++;
+             break;
+
+           case 'C':
+             /* For c-100: print quotient of value by 96, if nonzero,
+                then do like %+.  */
+             if (tem >= 96)
+               {
+                 *op++ = tem / 96;
+                 tem %= 96;
+               }
+           case '+':           /* %+x means add character code of char x.  */
+             tem += *p++;
+           case '.':           /* %. means output as character.  */
+             if (left)
+               {
+                 /* If want to forbid output of 0 and \n and \t,
+                    and this is one of them, increment it.  */
+                 while (tem == 0 || tem == '\n' || tem == '\t')
+                   {
+                     tem++;
+                     if (argp == old_argp)
+                       doup++, outend -= strlen (up);
+                     else
+                       doleft++, outend -= strlen (left);
+                   }
+               }
+             *op++ = tem ? tem : 0200;
+           case 'f':           /* %f means discard next arg.  */
+             argp++;
+             break;
+
+           case 'b':           /* %b means back up one arg (and re-use it).  */
+             argp--;
+             break;
+
+           case 'r':           /* %r means interchange following two args.  */
+             argp[0] = argp[1];
+             argp[1] = tem;
+             old_argp++;
+             break;
+
+           case '>':           /* %>xy means if arg is > char code of x, */
+             if (argp[0] > *p++) /* then add char code of y to the arg, */
+               argp[0] += *p;  /* and in any case don't output.  */
+             p++;              /* Leave the arg to be output later.  */
+             break;
+
+           case 'a':           /* %a means arithmetic.  */
+             /* Next character says what operation.
+                Add or subtract either a constant or some other arg.  */
+             /* First following character is + to add or - to subtract
+                or = to assign.  */
+             /* Next following char is 'p' and an arg spec
+                (0100 plus position of that arg relative to this one)
+                or 'c' and a constant stored in a character.  */
+             tem = p[2] & 0177;
+             if (p[1] == 'p')
+               tem = argp[tem - 0100];
+             if (p[0] == '-')
+               argp[0] -= tem;
+             else if (p[0] == '+')
+               argp[0] += tem;
+             else if (p[0] == '*')
+               argp[0] *= tem;
+             else if (p[0] == '/')
+               argp[0] /= tem;
+             else
+               argp[0] = tem;
+
+             p += 3;
+             break;
+
+           case 'i':           /* %i means add one to arg, */
+             argp[0] ++;       /* and leave it to be output later.  */
+             argp[1] ++;       /* Increment the following arg, too!  */
+             break;
+
+           case '%':           /* %% means output %; no arg.  */
+             goto ordinary;
+
+           case 'n':           /* %n means xor each of next two args with 140.  */
+             argp[0] ^= 0140;
+             argp[1] ^= 0140;
+             break;
+
+           case 'm':           /* %m means xor each of next two args with 177.  */
+             argp[0] ^= 0177;
+             argp[1] ^= 0177;
+             break;
+
+           case 'B':           /* %B means express arg as BCD char code.  */
+             argp[0] += 6 * (tem / 10);
+             break;
+
+           case 'D':           /* %D means weird Delta Data transformation.  */
+             argp[0] -= 2 * (tem % 16);
+             break;
+           }
+       }
+      else
+       /* Ordinary character in the argument string.  */
+      ordinary:
+       *op++ = c;
+    }
+  *op = 0;
+  while (doup-- > 0)
+    strcat (op, up);
+  while (doleft-- > 0)
+    strcat (op, left);
+  return outstring;
+}
+\f
+#ifdef DEBUG
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char buf[50];
+  int args[3];
+  args[0] = atoi (argv[2]);
+  args[1] = atoi (argv[3]);
+  args[2] = atoi (argv[4]);
+  tparam1 (argv[1], buf, "LEFT", "UP", args);
+  printf ("%s\n", buf);
+  return 0;
+}
+
+#endif /* DEBUG */
diff --git a/lib/termcap/version.c b/lib/termcap/version.c
new file mode 100644 (file)
index 0000000..51336db
--- /dev/null
@@ -0,0 +1,2 @@
+/* Make the library identifiable with the RCS ident command.  */
+static char *version_string = "\n$Version: GNU termcap 1.2 $\n";
diff --git a/lib/tilde/ChangeLog b/lib/tilde/ChangeLog
new file mode 100644 (file)
index 0000000..986db67
--- /dev/null
@@ -0,0 +1,6 @@
+Mon Jul 13 12:01:51 1992  Brian Fox  (bfox@cubit)
+
+       * tilde.c: (tilde_expand_word) If there is no variable $HOME, then
+       look up the user's home directory in the password database.
+
+
diff --git a/lib/tilde/Makefile b/lib/tilde/Makefile
new file mode 100644 (file)
index 0000000..50b4285
--- /dev/null
@@ -0,0 +1,98 @@
+## -*- text -*- ####################################################
+#                                                                 #
+# Makefile for the GNU Tilde Library.                             #
+#                                                                 #
+####################################################################
+
+# This Makefile is hand made from a template file, found in
+# ../template.  Each library must provide several Makefile
+# targets: `all', `clean', `documentation', `install', and
+# `what-tar'.  The `what-tar' target reports the names of the
+# files that need to be included in a tarfile to build the full
+# code and documentation for this library.
+
+# Please note that the values for INCLUDES, CC, AR, RM, CP,
+# RANLIB, and selfdir are passed in from ../Makefile, and do
+# not need to be defined here.
+RM = rm -f
+MV = mv
+CP = cp
+
+srcdir = .
+VPATH = .:$(srcdir)
+
+# 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.
+.c.o:
+       $(CC) -c $(CFLAGS) $(INCLUDES) $(LOCAL_DEFINES) $(CPPFLAGS) $<
+
+# LOCAL_DEFINES are flags that are specific to this library.
+# Define -DUSG if you are using a System V operating system.
+LOCAL_DEFINES = $(LOCAL_INCLUDES) #-DUSG
+
+# For libraries which include headers from other libraries.
+LOCAL_INCLUDES = -I..
+
+# The name of the library target.
+LIBRARY_NAME = libtilde.a
+
+# The C code source files for this library.
+CSOURCES = $(srcdir)/tilde.c
+
+# The header files for this library.
+HSOURCES = $(srcdir)/tilde.h
+
+OBJECTS = tilde.o
+
+# The texinfo files which document this library.
+DOCSOURCE = doc/tilde.texi
+DOCOBJECT = doc/tilde.dvi
+DOCSUPPORT = doc/Makefile
+DOCUMENTATION = $(DOCSOURCE) $(DOCOBJECT) $(DOCSUPPORT)
+
+SUPPORT = Makefile ChangeLog $(DOCSUPPORT)
+
+SOURCES  = $(CSOURCES) $(HSOURCES) $(DOCSOURCE)
+
+THINGS_TO_TAR = $(SOURCES) $(SUPPORT)
+
+######################################################################
+
+all: $(LIBRARY_NAME)
+
+$(LIBRARY_NAME): $(OBJECTS)
+       $(RM) $@
+       $(AR) cq $@ $(OBJECTS)
+       -[ -n "$(RANLIB)" ] && $(RANLIB) $@
+
+what-tar:
+       @for file in $(THINGS_TO_TAR); do \
+         echo $(selfdir)$$file; \
+       done
+
+documentation: force
+       -(cd doc; $(MAKE) $(MFLAGS))
+force:
+
+# The rule for 'includes' is written funny so that the if statement
+# always returns TRUE unless there really was an error installing the
+# include files.
+install:
+       -$(MV) $(bindir)/$(LIBRARY_NAME) $(bindir)/$(LIBRARY_NAME)-old
+       $(CP) $(LIBRARY_NAME) $(bindir)/$(LIBRARY_NAME)
+       -[ -n "$(RANLIB)" ] && $(RANLIB) -t $(bindir)/$(LIBRARY_NAME)
+
+clean:
+       $(RM) $(OBJECTS) $(LIBRARY_NAME)
+       -(cd doc && $(MAKE) $(MFLAGS) $@)
+
+maintainer-clean realclean mostlyclean distclean: clean
+
+
+######################################################################
+#                                                                   #
+#  Dependencies for the object files which make up this library.     #
+#                                                                   #
+######################################################################
+
+tilde.o: tilde.h tilde.c
diff --git a/lib/tilde/doc/Makefile b/lib/tilde/doc/Makefile
new file mode 100644 (file)
index 0000000..4e158bf
--- /dev/null
@@ -0,0 +1,5 @@
+all:
+       cp tilde.texi tilde.info
+
+clean realclean maintainer-clean:
+       rm -f tilde.?? tilde.info
diff --git a/lib/tilde/doc/tilde.texi b/lib/tilde/doc/tilde.texi
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/tilde/memalloc.h b/lib/tilde/memalloc.h
new file mode 100644 (file)
index 0000000..750d53d
--- /dev/null
@@ -0,0 +1,56 @@
+/* memalloc.h -- consolidate code for including alloca.h or malloc.h and
+   defining alloca. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (__MEMALLOC_H__)
+#  define __MEMALLOC_H__
+
+#if defined (sparc) && defined (sun) && !defined (HAVE_ALLOCA_H)
+#  define HAVE_ALLOCA_H
+#endif
+
+#if defined (__GNUC__) && !defined (HAVE_ALLOCA)
+#  define HAVE_ALLOCA
+#endif
+
+#if defined (HAVE_ALLOCA_H) && !defined (HAVE_ALLOCA)
+#  define HAVE_ALLOCA
+#endif /* HAVE_ALLOCA_H && !HAVE_ALLOCA */
+
+#if !defined (BUILDING_MAKEFILE)
+
+#if defined (__GNUC__)
+#  undef alloca
+#  define alloca __builtin_alloca
+#else /* !__GNUC__ */
+#  if defined (HAVE_ALLOCA_H)
+#    if defined (IBMESA)
+#      include <malloc.h>
+#    else /* !IBMESA */
+#      include <alloca.h>
+#    endif /* !IBMESA */
+#  else
+extern char *alloca ();
+#  endif /* !HAVE_ALLOCA_H */
+#endif /* !__GNUC__ */
+
+#endif /* !BUILDING_MAKEFILE */
+
+#endif /* __MEMALLOC_H__ */
diff --git a/lib/tilde/tilde.c b/lib/tilde/tilde.c
new file mode 100644 (file)
index 0000000..da75d95
--- /dev/null
@@ -0,0 +1,380 @@
+/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
+
+/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+   This file is part of GNU Readline, a library for reading lines
+   of text with interactive input and history editing.
+
+   Readline is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 1, or (at your option) any
+   later version.
+
+   Readline is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */  
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "tilde.h"
+#include <sys/types.h>
+#include <pwd.h>
+
+#if defined (USG) && !defined (HAVE_GETPW_DECLS)
+extern struct passwd *getpwuid (), *getpwnam ();
+#endif /* USG && !defined (HAVE_GETPW_DECLS) */
+
+#if !defined (savestring)
+extern char *xmalloc ();
+#  ifndef strcpy
+extern char *strcpy ();
+#  endif
+#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
+#endif /* !savestring */
+
+#if !defined (NULL)
+#  if defined (__STDC__)
+#    define NULL ((void *) 0)
+#  else
+#    define NULL 0x0
+#  endif /* !__STDC__ */
+#endif /* !NULL */
+
+#if defined (TEST) || defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* TEST || STATIC_MALLOC */
+
+/* The default value of tilde_additional_prefixes.  This is set to
+   whitespace preceding a tilde so that simple programs which do not
+   perform any word separation get desired behaviour. */
+static char *default_prefixes[] =
+  { " ~", "\t~", (char *)NULL };
+
+/* The default value of tilde_additional_suffixes.  This is set to
+   whitespace or newline so that simple programs which do not
+   perform any word separation get desired behaviour. */
+static char *default_suffixes[] =
+  { " ", "\n", (char *)NULL };
+
+/* If non-null, this contains the address of a function to call if the
+   standard meaning for expanding a tilde fails.  The function is called
+   with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
+   which is the expansion, or a NULL pointer if there is no expansion. */
+CPFunction *tilde_expansion_failure_hook = (CPFunction *)NULL;
+
+/* When non-null, this is a NULL terminated array of strings which
+   are duplicates for a tilde prefix.  Bash uses this to expand
+   `=~' and `:~'. */
+char **tilde_additional_prefixes = default_prefixes;
+
+/* When non-null, this is a NULL terminated array of strings which match
+   the end of a username, instead of just "/".  Bash sets this to
+   `:' and `=~'. */
+char **tilde_additional_suffixes = default_suffixes;
+
+/* Find the start of a tilde expansion in STRING, and return the index of
+   the tilde which starts the expansion.  Place the length of the text
+   which identified this tilde starter in LEN, excluding the tilde itself. */
+static int
+tilde_find_prefix (string, len)
+     char *string;
+     int *len;
+{
+  register int i, j, string_len;
+  register char **prefixes = tilde_additional_prefixes;
+
+  string_len = strlen (string);
+  *len = 0;
+
+  if (!*string || *string == '~')
+    return (0);
+
+  if (prefixes)
+    {
+      for (i = 0; i < string_len; i++)
+       {
+         for (j = 0; prefixes[j]; j++)
+           {
+             if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0)
+               {
+                 *len = strlen (prefixes[j]) - 1;
+                 return (i + *len);
+               }
+           }
+       }
+    }
+  return (string_len);
+}
+
+/* Find the end of a tilde expansion in STRING, and return the index of
+   the character which ends the tilde definition.  */
+static int
+tilde_find_suffix (string)
+     char *string;
+{
+  register int i, j, string_len;
+  register char **suffixes = tilde_additional_suffixes;
+
+  string_len = strlen (string);
+
+  for (i = 0; i < string_len; i++)
+    {
+      if (string[i] == '/' || !string[i])
+       break;
+
+      for (j = 0; suffixes && suffixes[j]; j++)
+       {
+         if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0)
+           return (i);
+       }
+    }
+  return (i);
+}
+
+/* Return a new string which is the result of tilde expanding STRING. */
+char *
+tilde_expand (string)
+     char *string;
+{
+  char *result, *tilde_expand_word ();
+  int result_size, result_index;
+
+  result_size = result_index = 0;
+  result = (char *)NULL;
+
+  /* Scan through STRING expanding tildes as we come to them. */
+  while (1)
+    {
+      register int start, end;
+      char *tilde_word, *expansion;
+      int len;
+
+      /* Make START point to the tilde which starts the expansion. */
+      start = tilde_find_prefix (string, &len);
+
+      /* Copy the skipped text into the result. */
+      if ((result_index + start + 1) > result_size)
+       result = (char *)xrealloc (result, 1 + (result_size += (start + 20)));
+
+      strncpy (result + result_index, string, start);
+      result_index += start;
+
+      /* Advance STRING to the starting tilde. */
+      string += start;
+
+      /* Make END be the index of one after the last character of the
+        username. */
+      end = tilde_find_suffix (string);
+
+      /* If both START and END are zero, we are all done. */
+      if (!start && !end)
+       break;
+
+      /* Expand the entire tilde word, and copy it into RESULT. */
+      tilde_word = (char *)xmalloc (1 + end);
+      strncpy (tilde_word, string, end);
+      tilde_word[end] = '\0';
+      string += end;
+
+      expansion = tilde_expand_word (tilde_word);
+      free (tilde_word);
+
+      len = strlen (expansion);
+      if ((result_index + len + 1) > result_size)
+       result = (char *)xrealloc (result, 1 + (result_size += (len + 20)));
+
+      strcpy (result + result_index, expansion);
+      result_index += len;
+      free (expansion);
+    }
+
+  result[result_index] = '\0';
+
+  return (result);
+}
+
+/* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
+   tilde.  If there is no expansion, call tilde_expansion_failure_hook. */
+char *
+tilde_expand_word (filename)
+     char *filename;
+{
+  char *dirname;
+
+  dirname = filename ? savestring (filename) : (char *)NULL;
+
+  if (dirname && *dirname == '~')
+    {
+      char *temp_name;
+      if (!dirname[1] || dirname[1] == '/')
+       {
+         /* Prepend $HOME to the rest of the string. */
+         char *temp_home = (char *)getenv ("HOME");
+
+         /* If there is no HOME variable, look up the directory in
+            the password database. */
+         if (!temp_home)
+           {
+             struct passwd *entry;
+
+             entry = getpwuid (getuid ());
+             if (entry)
+               temp_home = entry->pw_dir;
+           }
+
+         temp_name = xmalloc (1 + strlen (&dirname[1])
+                                + (temp_home ? strlen (temp_home) : 0));
+         temp_name[0] = '\0';
+         if (temp_home)
+           strcpy (temp_name, temp_home);
+         strcat (temp_name, dirname + 1);
+         free (dirname);
+         dirname = temp_name;
+       }
+      else
+       {
+         char *username;
+         struct passwd *user_entry;
+         int i;
+
+         username = xmalloc (strlen (dirname));
+         for (i = 1; dirname[i] && dirname[i] != '/'; i++)
+           username[i - 1] = dirname[i];
+         username[i - 1] = '\0';
+
+         if ((user_entry = getpwnam (username)) == 0)
+           {
+             /* If the calling program has a special syntax for
+                expanding tildes, and we couldn't find a standard
+                expansion, then let them try. */
+             if (tilde_expansion_failure_hook)
+               {
+                 char *expansion;
+
+                 expansion = (*tilde_expansion_failure_hook) (username);
+
+                 if (expansion)
+                   {
+                     temp_name = xmalloc (1 + strlen (expansion)
+                                                 + strlen (&dirname[i]));
+                     strcpy (temp_name, expansion);
+                     strcat (temp_name, &dirname[i]);
+                     free (expansion);
+                     free (dirname);
+                     dirname = temp_name;
+                   }
+               }
+             /* We shouldn't report errors. */
+           }
+         else
+           {
+             temp_name = xmalloc (1 + strlen (user_entry->pw_dir)
+                                    + strlen (&dirname[i]));
+             strcpy (temp_name, user_entry->pw_dir);
+             strcat (temp_name, &dirname[i]);
+             free (dirname);
+             dirname = temp_name;
+           }
+         endpwent ();
+         free (username);
+       }
+    }
+  return (dirname);
+}
+
+\f
+#if defined (TEST)
+#undef NULL
+#include <stdio.h>
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char *result, line[512];
+  int done = 0;
+
+  while (!done)
+    {
+      printf ("~expand: ");
+      fflush (stdout);
+
+      if (!gets (line))
+       strcpy (line, "done");
+
+      if ((strcmp (line, "done") == 0) ||
+         (strcmp (line, "quit") == 0) ||
+         (strcmp (line, "exit") == 0))
+       {
+         done = 1;
+         break;
+       }
+
+      result = tilde_expand (line);
+      printf ("  --> %s\n", result);
+      free (result);
+    }
+  exit (0);
+}
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+
+/*
+ * Local variables:
+ * compile-command: "gcc -g -DTEST -o tilde tilde.c"
+ * end:
+ */
+#endif /* TEST */
diff --git a/lib/tilde/tilde.h b/lib/tilde/tilde.h
new file mode 100644 (file)
index 0000000..726d081
--- /dev/null
@@ -0,0 +1,38 @@
+/* tilde.h: Externally available variables and function in libtilde.a. */
+
+#if !defined (__TILDE_H__)
+#  define __TILDE_H__
+
+/* Function pointers can be declared as (Function *)foo. */
+#if !defined (__FUNCTION_DEF)
+#  define __FUNCTION_DEF
+typedef int Function ();
+typedef void VFunction ();
+typedef char *CPFunction ();
+typedef char **CPPFunction ();
+#endif /* _FUNCTION_DEF */
+
+/* If non-null, this contains the address of a function to call if the
+   standard meaning for expanding a tilde fails.  The function is called
+   with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
+   which is the expansion, or a NULL pointer if there is no expansion. */
+extern CPFunction *tilde_expansion_failure_hook;
+
+/* When non-null, this is a NULL terminated array of strings which
+   are duplicates for a tilde prefix.  Bash uses this to expand
+   `=~' and `:~'. */
+extern char **tilde_additional_prefixes;
+
+/* When non-null, this is a NULL terminated array of strings which match
+   the end of a username, instead of just "/".  Bash sets this to
+   `:' and `=~'. */
+extern char **tilde_additional_suffixes;
+
+/* Return a new string which is the result of tilde expanding STRING. */
+extern char *tilde_expand ();
+
+/* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
+   tilde.  If there is no expansion, call tilde_expansion_failure_hook. */
+extern char *tilde_expand_word ();
+
+#endif /* __TILDE_H__ */
diff --git a/machines.h b/machines.h
new file mode 100644 (file)
index 0000000..7fe1ff9
--- /dev/null
@@ -0,0 +1,2392 @@
+/* machines.h --
+   Included file in the makefile that gets run through Cpp.  This file
+   tells which machines have what features based on the unique machine
+   identifier present in Cpp. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* **************************************************************** */
+/*                                                                  */
+/*                Global Assumptions (true for most systems).       */
+/*                                                                  */
+/* **************************************************************** */
+
+/* We make some global assumptions here.  This can be #undef'ed in
+   various machine specific entries. */
+
+/* If this file is being processed with Gcc, then the user has Gcc. */
+#if defined (__GNUC__) && !defined (NeXT) && !defined (__FreeBSD__)
+#  if !defined (HAVE_GCC)
+#    define HAVE_GCC
+#  endif /* HAVE_GCC */
+#endif /* __GNUC__ && !NeXT && !__FreeBSD__ */
+
+/* Assume that all machines have the getwd () system call.  We unset it
+   for USG systems. */
+#define HAVE_GETWD
+
+/* Assume that all systems have a working getcwd () call.  We unset it for
+   ISC systems. */
+#define HAVE_GETCWD
+
+/* Most (but not all) systems have a good, working version of dup2 ().
+   For systems that don't have the call (HP/UX), and for systems
+   that don't set the open-on-exec flag for the dup'ed file descriptors,
+   (Sequents running Dynix, Ultrix), #undef HAVE_DUP2 in the machine
+   description. */
+#define HAVE_DUP2
+
+/* Every machine that has Gcc has alloca as a builtin in Gcc.  If you are
+   compiling Bash without Gcc, then you must have alloca in a library,
+   in your C compiler, or be able to assemble or compile the alloca source
+   that we ship with Bash. */
+#define HAVE_ALLOCA
+
+/* We like most machines to use the GNU Malloc routines supplied in the
+   source code because they provide high quality error checking.  On
+   some machines, our malloc () cannot be used (because of library
+   conflicts, for example), and for those, you should specifically
+   #undef USE_GNU_MALLOC in the machine description. */
+#define USE_GNU_MALLOC
+
+/* This causes the Gnu malloc library (from glibc) to be used. */
+/* #define USE_GNU_MALLOC_LIBRARY */
+
+/* Assume that every operating system supplies strchr () and strrchr ()
+   in a standard library until proven otherwise. */
+#define HAVE_STRCHR
+
+/* Hardware-dependent CFLAGS. */
+#define MACHINE_CFLAGS
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Sun Microsystems Machines                   */
+/*                                                                 */
+/* **************************************************************** */
+
+/* NetBSD running on a sparc. */
+#if defined (sparc) && defined (__NetBSD__)
+#  define M_MACHINE "sun4"
+#  define M_OS "NetBSD"
+#  define SYSDEP_CFLAGS -DOPENDIR_NOT_ROBUST -DINT_GROUPS_ARRAY \
+                       -DRLIMTYPE=quad_t
+#  define SYSDEP_LDFLAGS -static
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#  define HAVE_VFPRINTF
+#  define HAVE_STRERROR
+#  define VOID_SIGHANDLER
+#  define HAVE_DIRENT
+#  define HAVE_STRCASECMP
+#  undef USE_GNU_MALLOC
+#endif /* sparc && __NetBSD__ */
+
+/* BSDI BSD/OS running on a sparc. */
+#if defined (sparc) && defined (__bsdi__)
+#  define M_MACHINE "sun4"
+#  define M_OS "BSD_OS"
+#  define SYSDEP_CFLAGS -DOPENDIR_NOT_ROBUST -DRLIMTYPE=quad_t
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#  define HAVE_VFPRINTF
+#  define HAVE_STRERROR
+#  define VOID_SIGHANDLER
+#  define HAVE_DIRENT
+#  define HAVE_STRCASECMP
+#endif /* sparc && __bsdi__ */
+
+#if defined (sun) && !defined (M_MACHINE)
+/* We aren't currently using GNU Malloc on Suns because of a bug in Sun's
+   YP which bites us when Sun free ()'s an already free ()'ed address.
+   When Sun fixes their YP, we can start using our winning malloc again. */
+#undef USE_GNU_MALLOC
+
+/* Most Sun systems have signal handler functions that are void. */
+#  define VOID_SIGHANDLER
+
+/* Most Sun systems have the following. */
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_VFPRINTF
+#  define HAVE_GETGROUPS
+
+/* Check for SunOS4 or greater. */
+#  if defined (SunOS5)
+#    define M_OS "SunOS5"
+#    define SYSDEP_CFLAGS -DUSGr4 -DUSG -DSolaris -DOPENDIR_NOT_ROBUST \
+                         -DNO_SBRK_DECL -DINT_GROUPS_ARRAY
+#    define EXTRA_LIB_SEARCH_PATH /usr/ccs/lib
+#    if !defined (HAVE_GCC)
+#      define REQUIRED_LIBRARIES -ldl
+#      define SYSDEP_LDFLAGS -Bdynamic
+#    endif /* !HAVE_GCC */
+#    define HAVE_STRERROR
+#    undef HAVE_GETWD
+#    undef HAVE_SETLINEBUF
+#  endif /* SunOS5 */
+
+#  if defined (SunOS4)
+#    define M_OS "SunOS4"
+#    define SYSDEP_CFLAGS -DBSD_GETPGRP -DOPENDIR_NOT_ROBUST -DTERMIOS_LDISC \
+                         -DINT_GROUPS_ARRAY
+#    define HAVE_DIRENT
+#  endif /* SunOS4 */
+
+#  if !defined (SunOS4) && !defined (SunOS5)
+#    define M_OS "SunOS3"
+#    if !defined (sparc) && !defined (__sparc__)
+#      undef VOID_SIGHANDLER
+#    endif /* !sparc */
+#  endif /* !SunOS4 && !SunOS5 */
+
+#  if defined (mc68010)
+#    define sun2
+#    define M_MACHINE "sun2"
+#  endif
+#  if defined (mc68020)
+#    define sun3
+#    define M_MACHINE "sun3"
+#  endif
+#  if defined (sparc) || defined (__sparc__)
+#    define sun4
+#    define M_MACHINE "sparc"
+#  endif
+#  if defined (i386)
+#    define done386
+#    if !defined (SunOS5)
+#      define Sun386i
+#      define M_MACHINE "Sun386i"
+#    else
+#      define M_MACHINE "i386"
+#    endif
+#  endif /* i386 */
+
+#endif /* sun && !M_MACHINE */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     DEC Machines (vax, decstations)             */
+/*                                                                 */
+/* **************************************************************** */
+
+/* ************************ */
+/*                          */
+/*     Alpha with OSF/1     */
+/*                          */
+/* ************************ */
+#if defined (__alpha) || defined (alpha)
+#  define M_MACHINE "alpha"
+#  define M_OS "OSF1"
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_VFPRINTF
+#  define HAVE_STRERROR
+#  define HAVE_GETGROUPS
+#  define VOID_SIGHANDLER
+#  define USE_TERMCAP_EMULATION
+#  if !defined (__GNUC__)
+#    define SYSDEP_CFLAGS -DNLS -D_BSD
+#  endif /* !__GNUC__ */
+#  undef HAVE_ALLOCA
+#  undef USE_GNU_MALLOC
+#endif /* __alpha || alpha */
+
+/* ************************ */
+/*                          */
+/*  NetBSD/pmax (DEC mips)  */
+/*                          */  
+/* ************************ */
+#if defined(mips) && defined(__NetBSD__)
+#  define M_MACHINE "mips"   
+#  define M_OS "NetBSD"
+#  define SYSDEP_CFLAGS -DOPENDIR_NOT_ROBUST -DINT_GROUPS_ARRAY \
+                       -DRLIMTYPE=quad_t
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#  define HAVE_VFPRINTF
+#  define HAVE_STRERROR
+#  define VOID_SIGHANDLER
+#  define HAVE_DIRENT
+#  define HAVE_STRCASECMP
+#endif /* mips && __NetBSD__ */
+
+/* ************************ */
+/*                         */
+/*         Ultrix          */
+/*                         */
+/* ************************ */
+#if defined (ultrix)
+#  if defined (MIPSEL)
+#    undef HAVE_ALLOCA_H
+#    define M_MACHINE "MIPSEL"
+#  else /* !MIPSEL */
+#    define M_MACHINE "vax"
+#  endif /* !MIPSEL */
+#  define SYSDEP_CFLAGS -DBSD_GETPGRP -DTERMIOS_MISSING -DTERMIOS_LDISC \
+                       -DINT_GROUPS_ARRAY
+#  define M_OS "Ultrix"
+#  define HAVE_DIRENT
+#  define VOID_SIGHANDLER
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_VFPRINTF
+#  define HAVE_GETGROUPS
+#  undef HAVE_DUP2
+#endif /* ultrix */
+
+/* ************************ */
+/*                         */
+/*     VAX 4.3 BSD         */
+/*                         */
+/* ************************ */
+#if defined (vax) && !defined (ultrix)
+#  define M_MACHINE "vax"
+#  define M_OS "Bsd"
+#  define HAVE_SETLINEBUF
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_GETGROUPS
+#  define USE_VFPRINTF_EMULATION
+#endif /* vax && !ultrix */
+
+/* ************************ */
+/*                         */
+/*     Tahoe 4.3 BSD       */
+/*                         */
+/* ************************ */
+#if defined (tahoe)
+#  define M_MACHINE "tahoe"
+#  define M_OS "Bsd"
+#  define HAVE_SETLINEBUF
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_GETGROUPS
+#  define HAVE_VFPRINTF
+#endif /* tahoe */
+
+/* **************************************************************** */
+/*                                                                 */
+/*             Machines with MIPSco processors                     */
+/*                                                                 */
+/* **************************************************************** */
+
+/* **************************************** */
+/*                                         */
+/*             SGI Iris/IRIX               */
+/*                                         */
+/* **************************************** */
+#if defined (sgi)
+#  if defined (Irix3)
+#    define M_OS "Irix3"
+#    if !defined (HAVE_GCC)
+#      undef MACHINE_CFLAGS
+#      define MACHINE_CFLAGS -real_frameptr -Wf,-XNl3072
+#    endif
+#    undef HAVE_ALLOCA
+#  endif /* Irix3 */
+#  if defined (Irix4)
+#    define M_OS "Irix4"
+#    if !defined (HAVE_GCC)
+#      undef MACHINE_CFLAGS
+#      define MACHINE_CFLAGS -Wf,-XNl3072
+#    endif
+#  endif /* Irix4 */
+#  if defined (Irix5)
+#    define M_OS "Irix5"
+#    if !defined (HAVE_GCC)
+#      undef MACHINE_CFLAGS
+#      define MACHINE_CFLAGS -Wf,-XNl3072
+#    endif
+#  endif /* Irix5 */
+#  if defined (Irix6)
+#    define M_OS "Irix6"
+#    if !defined (HAVE_GCC)
+#      undef MACHINE_CFLAGS
+#      define MACHINE_CFLAGS -mips2
+#    endif /* !HAVE_GCC */
+#  endif /* Irix6 */
+#  define M_MACHINE "sgi"
+#  define HAVE_GETGROUPS
+#  define VOID_SIGHANDLER
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_VFPRINTF
+#  define REQUIRED_LIBRARIES -lsun
+   /* SGI cc uses ansi c features *without* defining __STDC__ */
+#  if defined (__EXTENSIONS__) && !defined (__STDC__)
+#    define ANSIC -D__STDC__
+#  else
+#    define ANSIC
+#  endif /* !__EXTENSIONS__ || __STDC__ */
+#  if defined (Irix5) || defined (Irix6)
+#    define SGI_CFLAGS -DUSG -DPGRP_PIPE -DHAVE_BCOPY -DHAVE_GETPW_DECLS \
+                      -DHAVE_SOCKETS -DNO_SBRK_DECL
+#  else
+#    define SGI_CFLAGS -DUSG -DPGRP_PIPE -DHAVE_BCOPY -DHAVE_GETPW_DECLS \
+                      -DHAVE_SOCKETS
+#  endif /* !Irix5 */
+#  define SYSDEP_CFLAGS SGI_CFLAGS MACHINE_CFLAGS ANSIC
+#  define SYSDEP_LDFLAGS MACHINE_CFLAGS
+#endif  /* sgi */
+
+/* ************************ */
+/*                         */
+/*       NEC EWS 4800      */
+/*                         */
+/* ************************ */
+#if defined (nec_ews)
+#  if defined (SYSTYPE_SYSV) || defined (USGr4)
+#    define M_MACHINE "ews4800"
+#    define M_OS "USG"
+#    define HAVE_VFPRINTF
+#    define VOID_SIGHANDLER
+#    define HAVE_STRERROR
+#    define HAVE_DUP2
+#    undef HAVE_GETWD
+#    undef HAVE_RESOURCE /* ? */
+     /* Alloca requires either Gcc or cc with -lucb. */
+#    if !defined (HAVE_GCC)
+#      define EXTRA_LIB_SEARCH_PATH /usr/ucblib
+#      define REQUIRED_LIBRARIES -lc -lucb
+#    endif /* !HAVE_GCC */
+#    if defined (MIPSEB)
+#      if !defined (HAVE_GCC)
+#        undef MACHINE_CFLAGS
+#        define MACHINE_CFLAGS -Wf,-XNl3072
+#      endif
+#      define SYSDEP_CFLAGS MACHINE_CFLAGS -DUSGr4 -DUSGr3 -D_POSIX_JOB_CONTROL
+#    else /* !MIPSEB */
+#      define SYSDEP_CFLAGS -DUSGr4
+#    endif /* MIPSEB */
+#  else /* !SYSTYPE_SYSV && !USGr4 */
+#    define M_OS "Bsd"
+#  endif /* !SYSTYPE_SYSV && !USGr4 */
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#endif /* nec_ews */
+
+/* ************************ */
+/*                         */
+/*  Generic MIPS SVR4, 4.2  */
+/*                         */
+/* ************************ */
+#if defined (MIPSEB) && defined (USGr4)
+#  define M_MACHINE "MIPSEB"
+#  define M_OS "USG"
+#  if defined (sony) && !defined (HAVE_GCC)
+#    undef MACHINE_CFLAGS
+#    define MACHINE_CFLAGS -Wf,-XNl3072
+#  endif
+/* XXX - os/svr4.h -- for the future -- XXX */
+#  undef HAVE_GETWD
+#  define HAVE_DIRENT
+#  define HAVE_STRERROR
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+/* alloca */
+#  if !defined (HAVE_GCC)
+#    define EXTRA_LIB_SEARCH_PATH /usr/ucblib
+#    define REQUIRED_LIBRARIES -lc -lucb
+#  endif /* !HAVE_GCC */
+#  if defined (USGr4_2)
+#    define SYSDEP_CFLAGS MACHINE_CFLAGS -DUSGr4 -DUSGr4_2
+#  else
+#    define SYSDEP_CFLAGS MACHINE_CFLAGS -DUSGr4
+#  endif /* !USGr4_2 */
+#endif
+
+/* ************************ */
+/*                         */
+/*         Sony            */
+/*                         */
+/* ************************ */
+#if defined (sony) && !defined (M_MACHINE)
+#  if defined (MIPSEB)
+#    define M_MACHINE "MIPSEB"
+#  else /* !MIPSEB */
+#    define M_MACHINE "sony"
+#  endif /* !MIPSEB */
+
+#  if defined (SYSTYPE_SYSV) || defined (USGr4)
+#    define M_OS "USG"
+#    undef HAVE_GETWD
+#    define HAVE_DIRENT
+#    define HAVE_STRERROR
+#    define HAVE_VFPRINTF
+#    define VOID_SIGHANDLER
+     /* Alloca requires either Gcc or cc with -lucb. */
+#    if !defined (HAVE_GCC)
+#      define EXTRA_LIB_SEARCH_PATH /usr/ucblib
+#      define REQUIRED_LIBRARIES -lc -lucb
+#    endif /* !HAVE_GCC */
+#    if defined (MIPSEB)
+#      if !defined (HAVE_GCC)
+#        undef MACHINE_CFLAGS
+#        define MACHINE_CFLAGS -Wf,-XNl3072
+#      endif
+#      define SYSDEP_CFLAGS MACHINE_CFLAGS -DUSGr4
+#    else /* !MIPSEB */
+#      define SYSDEP_CFLAGS -DUSGr4
+#    endif /* !MIPSEB */
+#  else /* !SYSTYPE_SYSV && !USGr4 */
+#    define M_OS "Bsd"
+#    define SYSDEP_CFLAGS -DHAVE_UID_T
+#  endif /* !SYSTYPE_SYSV && !USGr4 */
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#endif /* sony */
+
+/* ******************************* */
+/*                                */
+/*  Ardent Titan OS v2.2 and later */
+/*                                */
+/* ******************************* */
+#if defined (ardent)
+#  define M_MACHINE "Ardent Titan"
+#  define M_OS "Bsd"
+#  if defined (titan)
+#    undef HAVE_GETGROUPS
+#  else
+#    define HAVE_GETGROUPS
+#  endif /* !titan */
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define SYSDEP_CFLAGS -43 -w
+#  define SYSDEP_LDFLAGS -43
+#  undef HAVE_ALLOCA
+#  undef USE_GNU_MALLOC
+#  undef HAVE_VFPRINTF
+#  undef HAVE_DIRENT_H
+#endif /* ardent */
+
+/* ************************ */
+/*                         */
+/*       Stardent          */
+/*                         */
+/* ************************ */
+#if defined (stardent) && !defined (M_MACHINE)
+#  define M_MACHINE "Stardent"
+#  define M_OS "USG"
+#  define HAVE_SYS_SIGLIST
+#  define USE_TERMCAP_EMULATION
+#  define VOID_SIGHANDLER
+#  undef HAVE_GETWD
+#  undef HAVE_ALLOCA
+#endif /* stardent */
+
+/* ******************************** */
+/*                                 */
+/*        MIPS RISC/os             */
+/*                                 */
+/* ******************************** */
+
+/* Notes on compiling with "make":
+
+   * Place /bsd43/bin in your PATH before /bin.
+   * Use `$(CC) -E' instead of `/lib/cpp' in Makefile.
+*/
+#if defined (mips) && ((!defined (M_MACHINE) && !defined (__nonstopux)) || defined (RiscOS))
+
+#  if defined (MIPSEB)
+#    define M_MACHINE "MIPSEB"
+#  else /* !MIPSEB */
+#    if defined (MIPSEL)
+#      define M_MACHINE "MIPSEL"
+#    else /* !MIPSEL */
+#      define M_MACHINE "mips"
+#    endif /* !MIPSEL */
+#  endif /* !MIPSEB */
+
+#  define M_OS "Bsd"
+
+   /* Special things for machines from MIPS Co. */
+#  define MIPS_CFLAGS -DOPENDIR_NOT_ROBUST -DPGRP_PIPE
+
+#  if !defined (HAVE_GCC)
+#    undef MACHINE_CFLAGS
+#    define MACHINE_CFLAGS -Wf,-XNl3072 -systype bsd43
+#    define SYSDEP_LDFLAGS -systype bsd43
+#  endif /* !HAVE_GCC */
+#  define SYSDEP_CFLAGS MACHINE_CFLAGS MIPS_CFLAGS
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_VFPRINTF
+#  define HAVE_GETGROUPS
+#  undef HAVE_UNISTD_H
+#  if !defined (HAVE_RESOURCE)
+#    define HAVE_RESOURCE
+#  endif /* !HAVE_RESOURCE */
+   /* /usr/include/sys/wait.h appears not to work correctly, so why use it? */
+#  undef HAVE_WAIT_H
+#endif /* mips */
+
+/* ************************ */
+/*                         */
+/*       Pyramid           */
+/*                         */
+/* ************************ */
+#if defined (pyr)
+#  define M_MACHINE "Pyramid"
+#  define M_OS "Bsd"
+#  if !defined (HAVE_GCC)
+#    undef HAVE_ALLOCA
+#  endif /* HAVE_GCC */
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#endif /* pyr */
+
+/* ************************ */
+/*                         */
+/*         IBMRT           */
+/*                         */
+/* ************************ */
+#if defined (ibm032)
+#  define M_MACHINE "IBMRT"
+#  define M_OS "Bsd"
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define USE_VFPRINTF_EMULATION
+   /* Alloca requires either gcc or hc or pcc with -ma in SYSDEP_CFLAGS. */
+#  if !defined (HAVE_GCC)
+#    define SYSDEP_CFLAGS -ma -U__STDC__
+#  endif /* !HAVE_GCC */
+#  define HAVE_GETGROUPS
+/* #define USE_GNU_TERMCAP */
+#endif /* ibm032 */
+
+/* **************************************************************** */
+/*                                                                 */
+/*       All Intel 386 Processor Machines are Defined Here!        */
+/*                                                                 */
+/* **************************************************************** */
+
+#if defined (i386)
+
+/* Sequent Symmetry running Dynix/ptx 2.x */
+#  if !defined (done386) && defined (_SEQUENT_)
+#    define done386
+#    define M_MACHINE "Symmetry"
+#    define M_OS "Dynix"
+#    define DYNIX_CFLAGS -DHAVE_GETDTABLESIZE -DHAVE_SETDTABLESIZE \
+                        -DHAVE_GETPW_DECLS -DHAVE_SOCKETS
+#    define SYSDEP_CFLAGS -DUSG -DUSGr3 DYNIX_CFLAGS
+#    define HAVE_DIRENT
+#    define HAVE_VFPRINTF
+#    define VOID_SIGHANDLER
+/* Might need to add -lsocket -linet -lnsl to the list of libraries. */
+#    define REQUIRED_LIBRARIES -lPW -lseq
+#    undef HAVE_GETWD
+#    undef HAVE_RESOURCE
+#    undef HAVE_ALLOCA
+#  endif /* _SEQUENT_ */
+
+/* Sequent Symmetry running Dynix (4.2 BSD) */
+#  if !defined (done386) && defined (sequent)
+#    define done386
+#    define M_MACHINE "Symmetry"
+#    define M_OS "Bsd"
+#    define SYSDEP_CFLAGS -DCPCC -DHAVE_SETDTABLESIZE
+#    define HAVE_SETLINEBUF
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_GETGROUPS
+#    define LD_HAS_NO_DASH_L
+#    undef HAVE_DUP2
+#  endif /* Sequent 386 */
+
+/* NeXT 3.x on i386 */
+#  if !defined (done386) && defined (NeXT)
+#    define done386
+#    define M_MACHINE "i386"
+#    define M_OS "NeXTstep"
+#    define HAVE_VFPRINTF
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_GETGROUPS
+#    define HAVE_STRERROR
+#    define VOID_SIGHANDLER
+#    if !defined (HAVE_RESOURCE)
+#      define HAVE_RESOURCE
+#    endif
+#    define HAVE_STRCASECMP
+#    define GCC_STANDARD
+#    undef HAVE_GETWD
+#    undef HAVE_GETCWD
+#    undef USE_GNU_MALLOC
+#    undef HAVE_DIRENT_H
+#    define SYSDEP_CFLAGS -DNeXT -DMKFIFO_MISSING -DRLOGIN_PGRP_BUG
+#  endif
+
+/* Generic 386 clone running Mach (4.3 BSD-compatible). */
+#  if !defined (done386) && defined (MACH)
+#    define done386
+#    define M_MACHINE "i386"
+#    define M_OS "Bsd"
+#    define HAVE_SETLINEBUF
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_GETGROUPS
+#  endif /* i386 && MACH */
+
+/* AIX PS/2 1.[23] for the [34]86. */
+#  if !defined (done386) && defined (aixpc)
+#    define done386
+#    define M_MACHINE "aixpc"
+#    define M_OS "AIX"
+#    define HAVE_VFPRINTF
+#    define VOID_SIGHANDLER
+#    if defined (AIX_13)       /* AIX PS/2 1.3 */
+#      define SYSDEP_CFLAGS -DTERMIOS_LDISC
+#      define REQUIRED_LIBRARIES -lc_s
+#    else
+#      define SYSDEP_CFLAGS -D_BSD -DTERMIOS_LDISC
+#      define REQUIRED_LIBRARIES -lbsd -lc_s
+#    endif /* !AIX_13 */
+#    define HAVE_GETGROUPS
+#    if !defined (HAVE_GCC)
+#      undef HAVE_ALLOCA
+#      undef HAVE_ALLOCA_H
+#    endif /* !HAVE_GCC */
+#    define USE_TERMCAP_EMULATION
+#  endif /* AIXPC i386 */
+
+/* System V Release 4 on the 386 */
+#  if !defined (done386) && defined (USGr4)
+#    define done386
+#    define M_MACHINE "i386"
+#    define M_OS "USG"
+#    define HAVE_DIRENT
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_VFPRINTF
+#    define VOID_SIGHANDLER
+     /* Alloca requires either Gcc or cc with -lucb. */
+#    if !defined (HAVE_GCC)
+#      define EXTRA_LIB_SEARCH_PATH /usr/ucblib
+#      define REQUIRED_LIBRARIES -lc -lucb
+#    endif /* !HAVE_GCC */
+#    define HAVE_GETGROUPS
+#    if defined (USGr4_2)
+#      define SYSDEP_CFLAGS -DUSGr4 -DUSGr4_2 -DNO_SBRK_DECL
+#    else
+#      define SYSDEP_CFLAGS -DUSGr4
+#    endif /* ! USGr4_2 */
+#    undef HAVE_GETWD
+#  endif /* System V Release 4 on i386 */
+
+/* 386 box running Interactive Unix 2.2 or greater. */
+#  if !defined (done386) && defined (isc386)
+#    define done386
+#    define M_MACHINE "isc386"
+#    define M_OS "USG"
+#    define HAVE_DIRENT
+#    define HAVE_VFPRINTF
+#    define VOID_SIGHANDLER
+#    define HAVE_GETGROUPS
+#    define USE_TERMCAP_EMULATION
+#    if defined (HAVE_GCC)
+#      define SYSDEP_LDFLAGS -posix
+#      define ISC_POSIX
+#    else
+#      define REQUIRED_LIBRARIES -lPW
+#      define SYSDEP_LDFLAGS -Xp
+#      define ISC_POSIX -Xp
+#    endif
+#    define ISC_SYSDEPS -DUSGr3 -DPGRP_PIPE -DHAVE_GETPW_DECLS -D_POSIX_SOURCE -DOPENDIR_NOT_ROBUST -DMEMMOVE_MISSING -DWAITPID_BROKEN
+#    if defined (__STDC__)
+#      if defined (HAVE_GCC)
+#        define ISC_EXTRA -DO_NDELAY=O_NONBLOCK
+#      else
+#        define ISC_EXTRA -Dmode_t="unsigned short" -DO_NDELAY=O_NONBLOCK
+#      endif /* HAVE_GCC */
+#    else
+#      define ISC_EXTRA
+#    endif /* __STDC__ */
+#    define SYSDEP_CFLAGS ISC_SYSDEPS ISC_POSIX ISC_EXTRA
+#    undef HAVE_GETWD
+#    if !defined (ISC_4)
+#      undef HAVE_GETCWD
+#    else
+#      undef HAVE_RESOURCE
+#    endif /* ISC_4 */
+#  endif /* isc386 */
+
+/* Xenix386 machine (with help from Ronald Khoo <ronald@robobar.co.uk>). */
+#  if !defined (done386) && defined (Xenix386)
+#    define done386
+#    define M_MACHINE "i386"
+#    define M_OS "Xenix"
+#    define XENIX_CFLAGS -DUSG -DUSGr3 -DMEMMOVE_MISSING
+
+#    if defined (XENIX_22)
+#      define XENIX_EXTRA -DREVERSED_SETVBUF_ARGS
+#      define REQUIRED_LIBRARIES -lx
+#    else /* !XENIX_22 */
+#      define HAVE_DIRENT
+#      if defined (XENIX_23)
+#        define XENIX_EXTRA -DLD_HAS_NO_DASH_L
+#        define REQUIRED_LIBRARIES -ldir
+#      else /* !XENIX_23 */
+#        define XENIX_EXTRA -xenix
+#        define SYSDEP_LDFLAGS -xenix
+#        define REQUIRED_LIBRARIES -ldir -l2.3
+#      endif /* !XENIX_23 */
+#    endif /* !XENIX_22 */
+
+#    define SYSDEP_CFLAGS XENIX_CFLAGS XENIX_EXTRA
+#    define HAVE_VFPRINTF
+#    define VOID_SIGHANDLER
+#    define ALLOCA_ASM x386-alloca.s
+#    define ALLOCA_OBJ x386-alloca.o
+#    undef HAVE_ALLOCA
+#    undef HAVE_GETWD
+#    undef HAVE_RESOURCE
+#  endif /* Xenix386 */
+
+/* SCO UNIX 3.2 chip@count.tct.com (Chip Salzenberg) */
+#  if !defined (done386) && defined (M_UNIX)
+#    define done386
+#    define M_MACHINE "i386"
+#    define M_OS "SCO"
+#    define SCO_CFLAGS -DUSG -DUSGr3 -DPGRP_PIPE
+#    if defined (SCOv4) || defined (SCOv5)
+#      define SYSDEP_CFLAGS SCO_CFLAGS -DWAITPID_BROKEN
+#    else /* !SCOv4 && !SCOv5 */
+#      define SYSDEP_CFLAGS SCO_CFLAGS -DOPENDIR_NOT_ROBUST -DMUST_UNBLOCK_CHILD
+#    endif /* !SCOv4 && !SCOv5 */
+#    define HAVE_VFPRINTF
+#    define VOID_SIGHANDLER
+#    define HAVE_GETGROUPS
+#    undef HAVE_GETWD
+#    undef HAVE_RESOURCE
+/* advice from wbader@cess.lehigh.edu and Eduard.Vopicka@vse.cz */
+#    if !defined (HAVE_GCC)
+#      define REQUIRED_LIBRARIES -lc_s -lc -lPW
+#    else
+#      define REQUIRED_LIBRARIES -lc_s -lc
+#    endif /* !HAVE_GCC */
+#  endif /* SCO Unix on 386 boxes. */
+
+#  if !defined (done386) && defined (__OSF1__)
+#    define done386
+#    define M_MACHINE "i386"
+#    define M_OS "OSF1"
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_SETLINEBUF
+#    define HAVE_VFPRINTF
+#    define HAVE_STRERROR
+#    define HAVE_GETGROUPS
+#    define VOID_SIGHANDLER
+#    define HAVE_BCOPY
+#    define USE_TERMCAP_EMULATION
+#    define SYSDEP_CFLAGS -D_BSD
+#    define REQUIRED_LIBRARIES -lbsd
+#  endif /* OSF/1 */
+
+/* BSDI BSD/OS running on a 386 or 486. */
+#  if !defined (done386) && defined (__bsdi__)
+#    define done386
+#    define M_MACHINE "i386"
+#    if defined (BSDI2)
+#      define M_OS "BSD_OS"
+#      define SYSDEP_CFLAGS -DOPENDIR_NOT_ROBUST -DRLIMTYPE=quad_t
+#    else
+#      define M_OS "BSD386"
+#      define SYSDEP_CFLAGS -DOPENDIR_NOT_ROBUST -DINT_GROUPS_ARRAY
+#    endif
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_SETLINEBUF
+#    define HAVE_GETGROUPS
+#    define HAVE_VFPRINTF
+#    define HAVE_STRERROR
+#    define VOID_SIGHANDLER
+#    define HAVE_DIRENT
+#    define HAVE_STRCASECMP
+#  endif /* !done386 && bsdi */
+
+/* NetBSD running on a 386 or 486. */
+#  if !defined (done386) && defined (__NetBSD__)
+#    define done386
+#    define M_MACHINE "i386"
+#    define M_OS "NetBSD"
+#    define SYSDEP_CFLAGS -DOPENDIR_NOT_ROBUST -DINT_GROUPS_ARRAY \
+                         -DRLIMTYPE=quad_t
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_SETLINEBUF
+#    define HAVE_GETGROUPS
+#    define HAVE_VFPRINTF
+#    define HAVE_STRERROR
+#    define VOID_SIGHANDLER
+#    define HAVE_DIRENT
+#    define HAVE_STRCASECMP
+#  endif /* !done386 && __NetBSD__ */
+
+/* FreeBSD running on a 386 or 486. */
+#  if !defined (done386) && defined (__FreeBSD__)
+#    define done386
+#    define M_MACHINE "i386"
+#    define M_OS "FreeBSD"
+#    if __FreeBSD__ > 1
+#      define SYSDEP_CFLAGS -D__BSD_4_4__ -DRLIMTYPE=quad_t
+#    else
+#      define SYSDEP_CFLAGS -DOPENDIR_NOT_ROBUST -DINT_GROUPS_ARRAY
+#    endif
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_SETLINEBUF
+#    define HAVE_GETGROUPS
+#    define HAVE_VFPRINTF
+#    define HAVE_STRERROR
+#    define VOID_SIGHANDLER
+#    define HAVE_DIRENT
+#    define HAVE_STRCASECMP
+#    define GCC_STANDARD
+#  endif /* !done386 && __FreeBSD__ */
+
+/* Jolitz 386BSD running on a 386 or 486. */
+#  if !defined (done386) && defined (__386BSD__)
+#    define done386
+#    define M_MACHINE "i386"
+#    define M_OS "_386BSD"
+#    define SYSDEP_CFLAGS -DOPENDIR_NOT_ROBUST -DINT_GROUPS_ARRAY
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_SETLINEBUF
+#    define HAVE_GETGROUPS
+#    define HAVE_VFPRINTF
+#    define HAVE_STRERROR
+#    define VOID_SIGHANDLER
+#    define HAVE_DIRENT
+#    define HAVE_STRCASECMP
+#  endif /* !done386 && __386BSD__ */
+
+#  if !defined (done386) && (defined (__linux__) || defined (linux))
+#    define done386
+#    define M_MACHINE "i386"
+#    define M_OS "Linux"
+#    define SYSDEP_CFLAGS -DHAVE_GETDTABLESIZE -DHAVE_BCOPY \
+                         -DHAVE_GETPW_DECLS -DHAVE_GETHOSTNAME
+#    define REQUIRED_LIBRARIES
+#    define HAVE_GETGROUPS
+#    define HAVE_STRERROR
+#    define VOID_SIGHANDLER
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_VFPRINTF
+#    define HAVE_VARARGS_H
+#    define SEARCH_LIB_NEEDS_SPACE
+#    if defined (__GNUC__)
+#      define HAVE_FIXED_INCLUDES
+#    endif /* __GNUC__ */
+#    undef USE_GNU_MALLOC
+#    undef HAVE_SETLINEBUF
+#    undef HAVE_GETWD
+#  endif  /* !done386 && __linux__ */
+
+/* QNX 4.2 with GCC pt@flard.ocunix.on.ca (Paul Trunley) */
+#  if !defined (done386) && defined (qnx)
+#    define done386
+#    define M_MACHINE "i386"
+#    define M_OS "QNX"
+#    define SYSDEP_CFLAGS -D_POSIX_SOURCE -O2 -DUSG
+#    define HAVE_VFPRINTF
+#    define VOID_SIGHANDLER
+#    define HAVE_GCC
+#    define HAVE_FIXED_INCLUDES
+#    define HAVE_STRERROR
+#    define HAVE_GETGROUPS
+#    undef USE_GNU_MALLOC
+#  endif /* QNX 4.2 with GCC */
+
+/* Lynx 2.1.0 (Mike Brennen <mbrennen@maverick.intecom.com>) */
+#  if !defined (done386) && (defined (__Lynx__) || defined (Lynx))
+#    define done386
+#    define M_MACHINE "i386"
+#    define M_OS "Lynx"
+#    define SYSDEP_CFLAGS -DHAVE_GETDTABLESIZE -DHAVE_BCOPY
+#    define REQUIRED_LIBRARIES -lc_p
+#    define HAVE_GETGROUPS
+#    define VOID_SIGHANDLER
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_VFPRINTF
+#    define HAVE_VARARGS_H
+#    if defined (__GNUC__)
+#      define HAVE_FIXED_INCLUDES
+#    endif /* __GNUC__ */
+/* Actually, Lynx does have unistd.h, but it defines _POSIX_VERSION,
+   and doesn't supply a fully compatible job control package.  We just
+   pretend that it doesn't have it. */
+#  undef HAVE_UNISTD_H
+/* Lynx's wait structure reverses w_Stopval and w_Stopsig - don't use it */
+#  undef HAVE_WAIT_H
+#  undef HAVE_DIRENT_H
+#  endif  /* !done386 && __Lynx__ */
+
+/* Assume a generic 386 running Sys V Release 3. */
+#  if !defined (done386)
+#    define done386
+#    define M_MACHINE "i386"
+#    define M_OS "USG"
+#    define SYSDEP_CFLAGS -DUSGr3
+#    define HAVE_VFPRINTF
+#    define VOID_SIGHANDLER
+     /* Alloca requires either Gcc or cc with libPW.a */
+#    if !defined (HAVE_GCC)
+#      define REQUIRED_LIBRARIES -lPW
+#    endif /* !HAVE_GCC */
+#    undef HAVE_GETWD
+#  endif /* Generic i386 Box running Sys V release 3. */
+#endif /* All i386 Machines with an `i386' define in cpp. */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                      Alliant FX/800                             */
+/*                                                                 */
+/* **************************************************************** */
+/* Original descs flushed.  FX/2800 machine desc 1.13 bfox@ai.mit.edu.
+   Do NOT use -O with the stock compilers.  If you must optimize, use
+   -uniproc with fxc, and avoid using scc. */
+#if defined (alliant)
+#  define M_MACHINE "alliant"
+#  define M_OS "Concentrix"
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#  define HAVE_VFPRINTF
+#  define HAVE_RESOURCE
+#  define VOID_SIGHANDLER
+#  define HAVE_STRERROR
+#  define USE_GNU_MALLOC
+#  define LD_HAS_NO_DASH_L
+#  define SYSDEP_CFLAGS -DTERMIOS_MISSING -DMKFIFO_MISSING \
+       -DBSD_GETPGRP -DRLOGIN_PGRP_BUG -w
+   /* Actually, Alliant does have unistd.h, but it defines _POSIX_VERSION,
+      and doesn't supply a fully compatible job control package.  We just
+      pretend that it doesn't have it. */
+#  undef HAVE_UNISTD_H
+#  undef HAVE_ALLOCA
+#endif /* alliant */
+
+/* ********************* */
+/*                       */
+/*      Linux/m68k       */
+/*                       */
+/* ********************* */
+#if defined (mc68000) && (defined (__linux__) || defined (linux))
+#  define M_MACHINE "m68k"
+#  define M_OS "Linux"
+#  define SYSDEP_CFLAGS -DHAVE_BCOPY -DHAVE_GETPW_DECLS -DHAVE_GETHOSTNAME
+#  define REQUIRED_LIBRARIES
+#  define HAVE_GETGROUPS
+#  define HAVE_STRERROR
+#  define VOID_SIGHANDLER
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_VFPRINTF
+#  define HAVE_VARARGS_H
+#  if defined (__GNUC__)
+#    define HAVE_FIXED_INCLUDES
+#  endif /* __GNUC__ */
+#  undef USE_GNU_MALLOC
+#  undef HAVE_SETLINEBUF
+#  define HAVE_STRCASECMP
+#endif  /* mc68000 && __linux__ */
+
+/* **************************************************************** */
+/*                                                                  */
+/*            Motorola Delta series running System V R3V6/7         */
+/*                                                                  */
+/* **************************************************************** */
+/* Contributed by Robert L. McMillin (rlm@ms_aspen.hac.com).  */
+
+#if defined (m68k) && defined (sysV68)
+#  define M_MACHINE "Delta"
+#  define M_OS "USG"
+#  define SYSDEP_CFLAGS -DUSGr3 -DMEMMOVE_MISSING
+#  define VOID_SIGHANDLER
+#  define HAVE_VFPRINTF
+#  define REQUIRED_LIBRARIES -lm881
+#  undef HAVE_GETWD
+#  undef HAVE_RESOURCE
+#  undef HAVE_DUP2
+#  undef HAVE_ALLOCA
+#endif /* Delta series */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                   Gould 9000 - UTX/32 R2.1A                     */
+/*                                                                 */
+/* **************************************************************** */
+#if defined (gould)            /* Maybe should be GOULD_PN ? */
+#  define M_MACHINE "gould"
+#  define M_OS "Bsd"
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#endif /* gould */
+
+/* ************************ */
+/*                         */
+/*         NeXT            */
+/*                         */
+/* ************************ */
+#if defined (NeXT) && !defined (M_MACHINE)
+#  define M_MACHINE "NeXT"
+#  define M_OS "NeXTstep"
+#  define HAVE_VFPRINTF
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_GETGROUPS
+#  define HAVE_STRERROR
+#  define VOID_SIGHANDLER
+#  if !defined (HAVE_RESOURCE)
+#    define HAVE_RESOURCE
+#  endif
+#  define HAVE_STRCASECMP
+#  define GCC_STANDARD
+#  undef HAVE_GETWD
+#  undef HAVE_GETCWD
+#  undef HAVE_DIRENT_H
+#  define SYSDEP_CFLAGS -DMKFIFO_MISSING -DRLOGIN_PGRP_BUG
+#  undef USE_GNU_MALLOC
+#endif /* NeXT */
+
+/* ********************** */
+/*                        */
+/*       m68k NetBSD      */
+/*                        */
+/* ********************** */
+#if defined (m68k) && defined (__NetBSD__)
+#  include <machine/param.h>
+#  define M_MACHINE MACHINE
+#  define M_OS "NetBSD"
+/* os/netbsd.h */
+#  define SYSDEP_CFLAGS -DOPENDIR_NOT_ROBUST -DINT_GROUPS_ARRAY \
+                       -DRLIMTYPE=quad_t
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#  define HAVE_VFPRINTF
+#  define HAVE_STRERROR
+#  define VOID_SIGHANDLER
+#  define HAVE_DIRENT
+#  define HAVE_STRCASECMP
+#endif /* m68k && __NetBSD__ */
+
+/* ************************ */
+/*                         */
+/*     hp9000 4.4 BSD      */
+/*                         */
+/* ************************ */
+#if defined (hp9000) && defined (__BSD_4_4__)
+#  define M_MACHINE "hp9000"
+#  define M_OS "BSD_4_4"
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#  define HAVE_STRERROR
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define HAVE_STRCASECMP
+#  define SYSDEP_CFLAGS -DHAVE_GETDTABLESIZE -DHAVE_BCOPY -DHAVE_RESOURCE
+#  undef HAVE_ALLOCA
+#endif /* hp9000 && __BSD_4_4__ */
+
+/* ************************ */
+/*                         */
+/*     hp9000 4.3 BSD      */
+/*                         */
+/* ************************ */
+#if defined (hp9000) && !defined (hpux) && !defined (M_MACHINE)
+#  define M_MACHINE "hp9000"
+#  define M_OS "Bsd"
+#  undef HAVE_ALLOCA
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#  define USE_VFPRINTF_EMULATION
+#endif /* hp9000 && !hpux */
+
+/* ************************ */
+/*                          */
+/*          hpux            */
+/*                          */
+/* ************************ */
+#if defined (hpux)
+
+/* HPUX comes in several different flavors, from pre-release 6.2 (basically
+   straight USG), to Posix compliant 9.0. */
+
+   /* HP machines come in several processor types.
+      They are distinguished here. */
+#  if defined (hp9000s200) && !defined (hp9000s300)
+#    define M_MACHINE "hp9000s200"
+#  endif /* hp9000s200 */
+#  if defined (hp9000s300) && !defined (M_MACHINE)
+#    define M_MACHINE "hp9000s300"
+#  endif /* hp9000s300 */
+#  if defined (hp9000s500) && !defined (M_MACHINE)
+#    define M_MACHINE "hp9000s500"
+#  endif /* hp9000s500 */
+#  if defined (hp9000s700) && !defined (M_MACHINE)
+#    define M_MACHINE "hp9000s700"
+#  endif /* hp9000s700 */
+#  if defined (hp9000s800) && !defined (M_MACHINE)
+#    define M_MACHINE "hp9000s800"
+#  endif /* hp9000s800 */
+#  if defined (hppa) && !defined (M_MACHINE)
+#    define M_MACHINE "hppa"
+#  endif /* hppa */
+
+/* Define the OS as the particular type that we are using. */
+/* This is for HP-UX systems earlier than HP-UX 6.2 -- no job control. */
+#  if defined (HPUX_USG)
+#    define M_OS "USG"
+#    define HPUX_CFLAGS -Dhpux
+#    define REQUIRED_LIBRARIES -lPW -lBSD
+#    undef HAVE_WAIT_H
+#    define HPUX_EXTRA
+#  else /* !HPUX_USG */
+
+/* All of the other operating systems need HPUX to be defined. */
+#    define HPUX_EXTRA -DHPUX -Dhpux -DHAVE_GETHOSTNAME -DUSG
+
+     /* HPUX 6.2 .. 6.5 require -lBSD for getwd (), and -lPW for alloca (). */
+#    if defined (HPUX_6)
+#      define M_OS "hpux_6"
+#      define REQUIRED_LIBRARIES -lPW -lBSD
+#      undef HAVE_ALLOCA
+#      undef HAVE_WAIT_H
+#    endif /* HPUX_6 */
+
+     /* On HP-UX 7.x, we do not link with -lBSD, so we don't have getwd (). */
+#    if defined (HPUX_7)
+#      define M_OS "hpux_7"
+#      define REQUIRED_LIBRARIES -lPW
+#      define HPUX_CFLAGS -DHAVE_SOCKETS
+#      undef HAVE_GETWD
+#      undef USE_GNU_MALLOC
+#    endif /* HPUX_7 */
+
+     /* HP-UX 8.x systems do not have a working alloca () on all platforms.
+       This can cause us problems, especially when globbing.  HP has the
+       same YP bug as Sun, so we #undef USE_GNU_MALLOC. */
+#    if defined (HPUX_8)
+#      define M_OS "hpux_8"
+#      if !defined (__GNUC__)
+#        undef HAVE_ALLOCA
+#       define HPUX_ANSI +O3 -Aa -D_HPUX_SOURCE
+#      else
+#       define HPUX_ANSI
+#      endif
+#      undef HAVE_GETWD
+#      undef USE_GNU_MALLOC
+#      define HPUX_CFLAGS -DNO_SBRK_DECL -DHAVE_SOCKETS HPUX_ANSI
+#    endif /* HPUX_8 */
+
+     /* HP-UX 9.0 reportedly fixes the alloca problems present in the 8.0
+        release.  If so, -lPW is required to include it. */
+#    if defined (HPUX_9)
+#      define M_OS "hpux_9"
+#      if !defined (__GNUC__)
+#        undef HAVE_ALLOCA
+#       define HPUX_ANSI +O3 -Ae
+#      else
+#       define HPUX_ANSI
+#      endif
+#      undef HAVE_GETWD
+#      undef USE_GNU_MALLOC
+#      undef HAVE_RESOURCE
+#      define HPUX_CFLAGS -DNO_SBRK_DECL -DHAVE_SOCKETS -DHAVE_GETHOSTNAME HPUX_ANSI
+#    endif /* HPUX_9 */
+
+#    if defined (HPUX_10)
+#      define M_OS "hpux_10"
+#      if !defined (__GNUC__)
+#        undef HAVE_ALLOCA
+#       define HPUX_ANSI +O3 -Ae
+#      else
+#       define HPUX_ANSI
+#      endif
+#      undef HAVE_GETWD
+#      undef USE_GNU_MALLOC
+#      undef HAVE_RESOURCE
+#      define HPUX_CFLAGS -DNO_SBRK_DECL -DHAVE_SOCKETS -DHAVE_GETHOSTNAME -DBSD_GETPGRP HPUX_ANSI
+#    endif /* HPUX_9 */
+
+#  endif /* !HPUX_USG */
+
+   /* All of the HPUX systems that we have tested have the following. */
+#  define HAVE_DIRENT
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define HAVE_GETGROUPS
+#  define HAVE_STRERROR
+#  define USE_TERMCAP_EMULATION
+#  define SEARCH_LIB_NEEDS_SPACE
+
+#  if defined (HPUX_CFLAGS)
+#    define SYSDEP_CFLAGS HPUX_CFLAGS HPUX_EXTRA
+#  else /* !HPUX_CFLAGS */
+#    define SYSDEP_CFLAGS HPUX_EXTRA
+#  endif /* !HPUX_CFLAGS */
+
+#endif /* hpux */
+
+/* ************************ */
+/*                          */
+/*        MIPS OSF/1        */
+/*                          */
+/* ************************ */
+#  if defined (MIPSEL) && defined (__OSF1__)
+#    define M_MACHINE "mips"
+#    define M_OS "OSF1"
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_SETLINEBUF
+#    define HAVE_VFPRINTF
+#    define HAVE_STRERROR
+#    define HAVE_GETGROUPS
+#    define VOID_SIGHANDLER
+#    define HAVE_BCOPY
+#    define USE_TERMCAP_EMULATION
+#    define SYSDEP_CFLAGS -D_BSD
+#    define REQUIRED_LIBRARIES -lbsd
+#  endif /* MIPSEL && __OSF1__ */
+
+/* ************************ */
+/*                          */
+/*        HP OSF/1          */
+/*                          */
+/* ************************ */
+#if defined (__hp_osf)
+#  define M_MACHINE "HPOSF1"
+#  define M_OS "OSF1"
+#  define SYSDEP_CFLAGS -q no_sl_enable
+#  define SYSDEP_LDFLAGS -q lang_level:classic
+#  define REQUIRED_LIBRARIES -lPW
+#  define HAVE_SETLINEBUF
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define HAVE_GETGROUPS
+#  define HAVE_STRERROR
+#  undef HAVE_ALLOCA
+#endif /* __hp_osf */
+
+/* ************************ */
+/*                          */
+/*        KSR1 OSF/1        */
+/*                          */
+/* ************************ */
+#if defined (__ksr1__)
+#  define M_MACHINE "KSR1"
+#  define M_OS "OSF1"
+#  define HAVE_SETLINEBUF
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define HAVE_GETGROUPS
+#  define HAVE_STRERROR
+#  define SYSDEP_CFLAGS -DHAVE_GETDTABLESIZE -DHAVE_BCOPY -DHAVE_UID_T
+#  undef HAVE_ALLOCA
+#  undef USE_GNU_MALLOC
+#endif /* ksr1 */
+
+/* ************************ */
+/*                          */
+/*   Intel Paragon - OSF/1  */
+/*                          */
+/* ************************ */
+#if defined (__i860) && defined (__PARAGON__)
+#  define M_MACHINE "Paragon"
+#  define M_OS "OSF1"
+#  define HAVE_GETGROUPS
+#  define HAVE_SETLINEBUF
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define HAVE_STRERROR
+#  define HAVE_SYS_SIGLIST
+#endif /* __i860 && __PARAGON__ */
+
+/* ************************ */
+/*                          */
+/* IBM AIX/ESA (OSF/1)      */
+/*                          */
+/* ************************ */
+#if defined(AIXESA) || (defined(__ibmesa) && defined(_AIX))
+#  define M_MACHINE "IBMESA"
+#  define M_OS "OSF1"
+#  define HAVE_GETGROUPS
+#  define HAVE_SETLINEBUF
+#  define HAVE_VPRINTF
+#  define VOID_SIGHANDLER
+#  define HAVE_STRERROR
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_ALLOCA_H                /* hack for AIX/ESA, which has malloc.h */
+#  undef USE_GNU_MALLOC
+#endif /* AIXESA || (__ibmesa && _AIX) */
+
+/* ************************ */
+/*                          */
+/*   Intel i860  -- SVR4    */
+/*                          */
+/* ************************ */
+#if defined (__i860) && defined (USGr4) && !defined (M_MACHINE)
+#  define M_MACHINE "i860"
+#  define M_OS "USG"
+#  define HAVE_DIRENT
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define HAVE_GETGROUPS
+#  if !defined (HAVE_GCC) && !defined (HAVE_ALLOCA_H)
+#    undef HAVE_ALLOCA
+#  endif /* !HAVE_GCC && !HAVE_ALLOCA_H */
+#  if defined (USGr4_2)
+#    define SYSDEP_CFLAGS -DUSGr4 -DUSGr4_2
+#  else
+#    define SYSDEP_CFLAGS -DUSGr4
+#  endif /* ! USGr4_2 */
+#  undef HAVE_GETWD
+#endif /* __i860 && USGr4 */
+
+/* ************************ */
+/*                         */
+/*         Xenix286        */
+/*                         */
+/* ************************ */
+#if defined (Xenix286)
+#  define M_MACHINE "i286"
+#  define M_OS "Xenix"
+
+#  define XENIX_CFLAGS -DUSG -DUSGr3 -DMEMMOVE_MISSING
+
+#  if defined (XENIX_22)
+#    define XENIX_EXTRA -DREVERSED_SETVBUF_ARGS
+#    define REQUIRED_LIBRARIES -lx
+#  else /* !XENIX_22 */
+#    define HAVE_DIRENT
+#    if defined (XENIX_23)
+#      define XENIX_EXTRA -DLD_HAS_NO_DASH_L
+#      define REQUIRED_LIBRARIES -ldir
+#    else /* !XENIX_23 */
+#      define XENIX_EXTRA -xenix
+#      define SYSDEP_LDFLAGS -xenix
+#      define REQUIRED_LIBRARIES -ldir -l2.3
+#    endif /* !XENIX_23 */
+#  endif /* !XENIX_22 */
+
+#  define SYSDEP_CFLAGS XENIX_CFLAGS XENIX_EXTRA
+#  undef HAVE_ALLOCA
+#  undef HAVE_GETWD
+#  undef HAVE_RESOURCE
+#endif /* Xenix286 */
+
+/* ************************ */
+/*                         */
+/*         convex          */
+/*                         */
+/* ************************ */
+#if defined (convex)
+#  define M_MACHINE "convex"
+#  define M_OS "Bsd"
+#  undef HAVE_ALLOCA
+#  define HAVE_SETLINEBUF
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_GETGROUPS
+#endif /* convex */
+
+/* ************************ */
+/*                          */
+/*          AIX/RT          */
+/*                          */
+/* ************************ */
+#if defined (aix) && !defined (aixpc)
+#  define M_MACHINE "AIXRT"
+#  define M_OS "USG"
+#  define HAVE_DIRENT
+#  define HAVE_VFPRINTF
+#  define HAVE_SYS_SIGLIST
+#  define VOID_SIGHANDLER
+#  define HAVE_GETGROUPS
+#  define USE_TERMCAP_EMULATION
+#  if !defined (HAVE_GCC)
+#    undef MACHINE_CFLAGS
+#    define MACHINE_CFLAGS -a
+#  endif /* !HAVE_GCC */
+#  define SYSDEP_CFLAGS MACHINE_CFLAGS -DNLS -DUSGr3 -DHAVE_BCOPY
+#  undef USE_GNU_MALLOC
+#  undef HAVE_ALLOCA
+#  undef HAVE_RESOURCE
+#endif /* aix && !aixpc */
+
+/* **************************************** */
+/*                                         */
+/*             IBM RISC 6000               */
+/*                                         */
+/* **************************************** */
+#if defined (RISC6000) || defined (_IBMR2)
+#  define M_MACHINE "RISC6000"
+#  define M_OS "AIX"
+#  define HAVE_DIRENT
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define USE_TERMCAP_EMULATION
+#  define HAVE_GETGROUPS
+#  define SYSDEP_CFLAGS -DNLS -DUSGr3 -DHAVE_BCOPY
+#  undef HAVE_ALLOCA
+#  undef HAVE_GETWD
+#  undef USE_GNU_MALLOC
+#endif /* RISC6000 */
+
+/* **************************************** */
+/*                                         */
+/*     u370 IBM AIX/370                    */
+/*                                         */
+/* **************************************** */
+#if defined (u370)
+#  if defined (_AIX370)
+#    define M_MACHINE "AIX370"
+#    define M_OS "Bsd"
+#    define REQUIRED_LIBRARIES -lbsd
+#    define HAVE_SETLINEBUF
+#    define HAVE_VFPRINTF
+#    define SYSDEP_CFLAGS -D_BSD
+#    define HAVE_GETGROUPS
+#    define USE_TERMCAP_EMULATION
+#    undef USE_GNU_MALLOC
+#  endif /* _AIX370 */
+#  if defined (USGr4) /* System V Release 4 on 370 series architecture. */
+#    define M_MACHINE "uxp"
+#    define M_OS "USG"
+#    define HAVE_DIRENT
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_VFPRINTF
+#    define USE_GNU_MALLOC
+#    define VOID_SIGHANDLER
+#    if !defined (HAVE_GCC)
+#      undef HAVE_ALLOCA
+#      define EXTRA_LIB_SEARCH_PATH /usr/ucblib
+#      define REQUIRED_LIBRARIES -lc -lucb
+#    endif /* !HAVE_GCC */
+#    define HAVE_GETGROUPS
+#    define HAVE_RESOURCE
+#    define SYSDEP_CFLAGS -DUSGr4 -DNO_SBRK_DECL
+#    endif /* USGr4 */
+#endif /* u370 */
+
+/* ************************ */
+/*                         */
+/*         ATT 3B          */
+/*                         */
+/* ************************ */
+#if defined (att3b) || defined (u3b2)
+#  if defined (att3b)
+#    define M_MACHINE "att3b"
+#    define HAVE_SYS_SIGLIST
+#  else /* !att3b */
+#    define M_MACHINE "u3b2"
+#  endif /* !att3b */
+#  define M_OS "USG"
+#  undef HAVE_GETWD
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+   /* For an AT&T Unix before V.3 take out the -DUSGr3 and the HAVE_DIRENT. */
+#  define SYSDEP_CFLAGS -DUSGr3
+#  define HAVE_DIRENT
+   /* Alloca requires either Gcc or cc with libPW.a. */
+#  if !defined (HAVE_GCC)
+#    define REQUIRED_LIBRARIES -lPW
+#  endif /* !HAVE_GCC */
+#endif /* att3b */
+
+/* ************************ */
+/*                         */
+/*         ATT 386         */
+/*                         */
+/* ************************ */
+#if defined (att386)
+#  define M_MACHINE "att386"
+#  define M_OS "USG"
+#  undef HAVE_GETWD
+   /* Alloca requires either Gcc or cc with libPW.a. */
+#  if !defined (HAVE_GCC)
+#    define REQUIRED_LIBRARIES -lPW
+#  endif /* HAVE_GCC */
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+   /* For an AT&T Unix before V.3 take out the -DUSGr3 and the HAVE_DIRENT. */
+#  define SYSDEP_CFLAGS -DUSGr3
+#  define HAVE_DIRENT
+#endif /* att386 */
+
+/* ************************ */
+/*                         */
+/*      ATT UNIX PC        */
+/*                         */
+/* ************************ */
+#if defined (unixpc)
+#  define M_MACHINE "unixpc"
+#  define M_OS "USG"
+#  define HAVE_VFPRINTF
+#  define HAVE_DIRENT
+#  if defined (HAVE_GCC)
+#    define REQUIRED_LIBRARIES -ldirent -shlib
+#  else /* !HAVE_GCC */
+#    define REQUIRED_LIBRARIES -ldirent
+#  endif /* !HAVE_GCC */
+#  undef HAVE_GETWD
+#  undef HAVE_DUP2
+#  undef VOID_SIGHANDLER
+#  undef HAVE_WAIT_H
+#endif /* unixpc */
+
+/* ************************ */
+/*                         */
+/*         Encore          */
+/*                         */
+/* ************************ */
+#if defined (MULTIMAX)
+#  if defined (n16)
+#    define M_MACHINE "Multimax32k"
+#  else
+#    define M_MACHINE "Multimax"
+#  endif /* n16 */
+#  if defined (UMAXV)
+#    define M_OS "USG"
+#    define REQUIRED_LIBRARIES -lPW
+#    define SYSDEP_CFLAGS -DUSGr3
+#    define HAVE_DIRENT
+#    define HAVE_VFPRINTF
+#    define USE_TERMCAP_EMULATION
+#    define VOID_SIGHANDLER
+#  else
+#    if defined (CMU)
+#      define M_OS "Mach"
+#    else
+#      define M_OS "Bsd"
+#    endif /* CMU */
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_STRERROR
+#    define HAVE_SETLINEBUF
+#  endif /* UMAXV */
+#  define HAVE_GETGROUPS
+#endif  /* MULTIMAX */
+
+/* ******************************************** */
+/*                                             */
+/*   Encore Series 91 (88K BCS w Job Control)  */
+/*                                             */
+/* ******************************************** */
+#if defined (__m88k) && defined (__UMAXV__)
+#  define M_MACHINE "Gemini"
+#  define M_OS "USG"
+#  define REQUIRED_LIBRARIES -lPW
+#  define USE_TERMCAP_EMULATION
+#  define HAVE_DIRENT
+#  define HAVE_GETGROUPS
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define SYSDEP_CFLAGS -q ext=pcc -D_POSIX_JOB_CONTROL -D_POSIX_VERSION \
+                       -Dmalloc=_malloc -Dfree=_free -Drealloc=_realloc
+#endif  /* m88k && __UMAXV__ */
+
+/* ******************************************** */
+/*                                             */
+/*    System V Release 4 on the ICL DRS6000     */
+/*                                             */
+/* ******************************************** */
+#if defined (drs6000)
+#  define M_MACHINE "drs6000"
+#  define M_OS "USG"
+#  define SYSDEP_CFLAGS -Xa -DUSGr4
+#  define SEARCH_LIB_NEEDS_SPACE
+#  define HAVE_DIRENT
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_VFPRINTF
+#  define HAVE_GETGROUPS
+#  define HAVE_STRERROR
+#  define VOID_SIGHANDLER
+#  define USE_GNU_TERMCAP
+#  if !defined (__GNUC__)
+#    undef HAVE_ALLOCA
+#  endif
+#  undef HAVE_ALLOCA_H
+#  undef USE_GNU_MALLOC
+#endif /* drs6000 */
+
+/* ******************************************** */
+/*                                             */
+/*   System V Release 4 on the Sparc (generic)  */
+/*                                             */
+/* ******************************************** */
+#if defined (sparc) && defined (__svr4__) && !defined (M_MACHINE)
+#  define M_MACHINE "sparc"
+#  define M_OS "SVR4"
+#  define SYSDEP_CFLAGS -DUSG -DUSGr4 -DHAVE_UID_T
+#  define HAVE_DIRENT
+#  define HAVE_VFPRINTF
+#  define HAVE_GETGROUPS
+#  define HAVE_STRERROR
+#  define VOID_SIGHANDLER
+#  define USE_GNU_TERMCAP
+#  if !defined (__GNUC__)
+#    undef HAVE_ALLOCA
+#  endif
+#  undef HAVE_BCOPY
+#  undef HAVE_GETWD
+#  undef USE_GNU_MALLOC
+#endif /* sparc && __svr4__ */
+
+/* ******************************************** */
+/*                                             */
+/*             Commodore Amiga                 */
+/*                                             */
+/* ******************************************** */
+#if defined (amiga) && defined (__NetBSD__)
+#  define M_MACHINE "amiga"
+#  define M_OS "NetBSD"
+#  define SYSDEP_CFLAGS -DOPENDIR_NOT_ROBUST -DINT_GROUPS_ARRAY \
+                       -DRLIMTYPE=quad_t
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#  define HAVE_VFPRINTF
+#  define HAVE_STRERROR
+#  define VOID_SIGHANDLER
+#  define HAVE_DIRENT
+#  define HAVE_STRCASECMP
+#endif /* amiga && __NetBSD__ */
+
+#if defined (amiga) && !defined (M_MACHINE)
+#  define M_MACHINE "amiga"
+#  define M_OS "USG"
+#  define SYSDEP_CFLAGS -DUSGr4
+#  if !defined (HAVE_GCC)
+#    define EXTRA_LIB_SEARCH_PATH /usr/ucblib
+#    define REQUIRED_LIBRARIES -lc -lucb
+#  endif /* !HAVE_GCC */
+#  define HAVE_DIRENT
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define HAVE_GETGROUPS
+#  define HAVE_STRERROR
+#  undef HAVE_GETWD
+#  undef USE_GNU_MALLOC
+#endif /* System V Release 4 on amiga */
+
+/* ************************ */
+/*                         */
+/*         clipper         */
+/*                         */
+/* ************************ */
+/* This is for the Orion 1/05 (A BSD 4.2 box based on a Clipper processor) */
+#if defined (clipper) && !defined (M_MACHINE)
+#  define M_MACHINE "clipper"
+#  define M_OS "Bsd"
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#endif  /* clipper */
+
+/* ******************************** */
+/*                                 */
+/*    Integrated Solutions 68020?   */
+/*                                 */
+/* ******************************** */
+#if defined (is68k)
+#  define M_MACHINE "is68k"
+#  define M_OS "Bsd"
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#  define USE_VFPRINTF_EMULATION
+#  undef HAVE_ALLOCA
+#endif /* is68k */
+
+/* ******************************** */
+/*                                 */
+/*        Omron Luna/Mach 2.5      */
+/*                                 */
+/* ******************************** */
+#if defined (luna88k)
+#  define M_MACHINE "Luna88k"
+#  define M_OS "Bsd"
+#  define HAVE_SYS_SIGLIST
+#  define USE_GNU_MALLOC
+#  define HAVE_SETLINEBUF
+#  define HAVE_VFPRINTF
+#  define HAVE_GETGROUPS
+#  define HAVE_VFPRINTF
+#endif /* luna88k */
+
+/* ************************ */
+/*                         */
+/*   BBN Butterfly GP1000   */
+/*   Mach 1000 v2.5        */
+/*                         */
+/* ************************ */
+#if defined (butterfly) && defined (BFLY1)
+#define M_MACHINE "BBN Butterfly"
+#define M_OS "Mach 1000"
+#define HAVE_SETLINEBUF
+#define HAVE_SYS_SIGLIST
+#define HAVE_GETGROUPS
+#define HAVE_VFPRINTF
+#  ifdef BUILDING_MAKEFILE
+MAKE = make
+#  endif /* BUILDING_MAKEFILE */
+#endif /* butterfly */
+
+/* **************************************** */
+/*                                         */
+/*         Apollo/SR10.2/BSD4.3            */
+/*                                         */
+/* **************************************** */
+/* This is for the Apollo DN3500 running SR10.2 BSD4.3 */
+#if defined (apollo)
+#  define M_MACHINE "apollo"
+#  define M_OS "Bsd"
+#  define SYSDEP_CFLAGS -D_POSIX_VERSION -D_INCLUDE_BSD_SOURCE \
+                       -D_INCLUDE_POSIX_SOURCE -DTERMIOS_MISSING \
+                       -DBSD_GETPGRP -Dpid_t=int
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#endif /* apollo */
+
+/* ************************ */
+/*                         */
+/*     DG AViiON           */
+/*                         */
+/* ************************ */
+/* This is for the DG AViiON box (runs DG/UX with both AT&T & BSD features.) */
+/* DG/UX comes standard with Gcc. */
+#if defined (__DGUX__) || defined (DGUX)
+#  define M_OS "DGUX"
+#  if !defined (_M88KBCS_TARGET)
+#    define M_MACHINE "AViiON"
+#    define REQUIRED_LIBRARIES -ldgc
+#  else /* _M88KBCS_TARGET */
+#    define M_MACHINE "m88kBCS_AV"
+#    undef MACHINE_CFLAGS
+#    define MACHINE_CFLAGS -D_M88K_SOURCE
+#    undef HAVE_RESOURCE
+#  endif /* _M88KBCS_TARGET */
+#  define SYSDEP_CFLAGS MACHINE_CFLAGS -D_DGUX_SOURCE -DPGRP_PIPE -DUSG
+#  define HAVE_GCC
+#  define HAVE_FIXED_INCLUDES
+#  define HAVE_STRERROR
+#  define HAVE_GETGROUPS
+#  define VOID_SIGHANDLER
+#  undef HAVE_GETWD
+#  undef USE_GNU_MALLOC
+
+/* If you want to build bash for M88K BCS compliance on a DG/UX 5.4
+   or above system, do the following:
+     - If you have built in this directory before run "make clean" to
+       endure the Bash directory is clean.
+     - Run "eval `sde-target m88kbcs`" to set the software development
+       environment to build BCS objects.
+     - Run "make".
+     - Do "eval `sde-target default`" to reset the SDE. */
+#endif /* __DGUX__ */
+
+/* ************************ */
+/*                         */
+/*    Harris Night Hawk            */
+/*                         */
+/* ************************ */
+/* This is for the Harris Night Hawk family. */
+#if defined (_CX_UX)
+#  if defined (_M88K)
+#    define M_MACHINE "nh4000"
+#  else /* !_M88K */
+#    if defined (hcx)
+#      define M_MACHINE "nh2000"
+#    else /* !hcx */
+#      if defined (gcx)
+#        define M_MACHINE "nh3000"
+#      endif /* gcx */
+#    endif /* !hcx */
+#  endif /* !_M88K */
+#  define M_OS "USG"
+#  define SYSDEP_CFLAGS -g -Xa -v -Dgetwd=bash_getwd -D_POSIX_SOURCE \
+                       -D_POSIX_JOB_CONTROL
+#  define USE_TERMCAP_EMULATION
+#  define HAVE_VFPRINTF
+#  define HAVE_GETGROUPS
+#  define VOID_SIGHANDLER
+#  undef USE_GNU_MALLOC
+#  undef HAVE_GETWD
+#endif /* _CX_UX */
+
+/* **************************************** */
+/*                                         */
+/*             Tektronix                   */
+/*                                         */
+/* **************************************** */
+/* These are unproven as yet. */
+#if defined (Tek4132)
+#  define M_MACHINE "Tek4132"
+#  define M_OS "Bsd"
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#endif /* Tek4132 */
+
+#if defined (Tek4300)
+#  define M_MACHINE "Tek4300"
+#  define M_OS "Bsd"
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#endif /* Tek4300 */
+
+/* ************************ */
+/*                          */
+/*     Tektronix XD88       */
+/*                          */
+/* ************************ */
+#if defined (m88k) && defined (XD88)
+#  define M_MACHINE "XD88"
+#  define M_OS "USG"
+#  define HAVE_DIRENT
+#  define HAVE_VFPRINTF
+#  define HAVE_GETCWD
+#  define VOID_SIGHANDLER
+#  define HAVE_GETGROUPS
+#  undef HAVE_GETWD
+#  undef HAVE_ALLOCA
+#endif /* m88k && XD88 */
+
+/* ************************ */
+/*                          */
+/*     Motorola M88100      */
+/*                          */
+/* ************************ */
+#if defined (m88k) && (defined (M88100) || defined (USGr4))
+#  define M_MACHINE "M88100"
+#  define M_OS "USG"
+#  if defined (USGr4)
+#    define SYSDEP_CFLAGS -DUSGr4 -D_POSIX_JOB_CONTROL
+#  else
+#    define SYSDEP_CFLAGS -D_POSIX_JOB_CONTROL -DWAITPID_BROKEN
+#  endif
+#  define HAVE_DIRENT
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define HAVE_GETGROUPS
+#  undef HAVE_GETWD
+#  if !defined (USGr4)
+#    undef HAVE_GETCWD
+#  endif
+#  undef HAVE_ALLOCA
+#endif /* m88k && M88100 */
+
+/* ************************ */
+/*                         */
+/*     Sequent Balances     */
+/*       (Dynix 3.x)       */
+/* ************************ */
+#if defined (sequent) && !defined (M_MACHINE)
+#  define M_MACHINE "Sequent"
+#  define M_OS "Bsd"
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#  define LD_HAS_NO_DASH_L
+#  undef HAVE_DUP2
+#endif /* sequent */
+
+/* ****************************************** */
+/*                                           */
+/*    NCR Tower 32, System V Release 3       */
+/*                                           */
+/* ****************************************** */
+#if defined (tower32)
+#  define M_MACHINE "tower32"
+#  define M_OS "USG"
+#  if !defined (HAVE_GCC)
+#    define REQUIRED_LIBRARIES -lPW
+     /* Disable stack/frame-pointer optimization, incompatible with alloca */
+#    undef MACHINE_CFLAGS
+#    define MACHINE_CFLAGS -W2,-aat
+#  endif /* !HAVE_GCC */
+#  define SYSDEP_CFLAGS -DUSGr3 MACHINE_CFLAGS
+#  define HAVE_VFPRINTF
+#  define USE_TERMCAP_EMULATION
+#  define VOID_SIGHANDLER
+#  undef HAVE_GETWD
+#endif /* tower32 */
+
+/* ************************ */
+/*                         */
+/*     Concurrent          */
+/*                         */
+/* ************************ */
+#if defined (concurrent)
+#  define M_MACHINE "Concurrent"
+#  if defined (USE_BSD_UNIVERSE)
+     /* Use the BSD universe (`universe ucb') */
+#    define M_OS "Bsd"
+#    define HAVE_SYS_SIGLIST
+#    define HAVE_SETLINEBUF
+#    define HAVE_GETGROUPS
+#  else /* !USE_BSD_UNIVERSE */
+   /* Concurrent 7000 with RTU 6.1A using the ATT universe (`universe att') */
+#    define M_OS "USG"
+#    define SYSDEP_CFLAGS -DHAVE_BCOPY -DHAVE_UID_T -DHAVE_GETDTABLESIZE -Dmc7000
+#    define REQUIRED_LIBRARIES -ljobs
+#    define HAVE_VPRINTF
+#    define HAVE_GETGROUPS
+#    define HAVE_DUP2
+#    define HAVE_DIRENT
+#    define HAVE_SYS_SIGLIST
+#  endif /* !USE_BSD_UNIVERSE */
+#endif /* concurrent */
+
+/* **************************************************************** */
+/*                                                                  */
+/*             Honeywell Bull X20 (lele@idea.sublink.org)          */
+/*                                                                  */
+/* **************************************************************** */
+#if defined (hbullx20)
+#  define M_MACHINE "Honeywell"
+#  define M_OS "USG"
+#  define SYSDEP_CFLAGS -DUSG
+   /* Bull x20 needs -lposix for struct dirent. */
+#  define REQUIRED_LIBRARIES -lPW -lposix
+#  define HAVE_DIRENT
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define USE_TERMCAP_EMULATION
+#  undef HAVE_GETWD
+#endif  /* hbullx20 */
+
+/* ************************ */
+/*                         */
+/*         CRAY            */
+/*                         */
+/* ************************ */
+#if defined (cray)
+#  include <sys/param.h>
+#  if defined (Cray1) || defined (Cray2)
+#    define M_MACHINE "Cray"
+#    define CRAY_STACK
+#  endif
+#  if defined (CrayXMP) && !defined (M_MACHINE)
+#    define M_MACHINE "CrayXMP"
+#    define CRAY_STACK -DCRAY_STACKSEG_END=getb67
+#  endif
+#  if defined (CrayYMP) && !defined (M_MACHINE)
+#    define M_MACHINE "CrayYMP"
+#    if RELEASE_LEVEL >= 7000
+#      define CRAY_STACK -DCRAY_STACKSEG_END=_getb67
+#    else
+#      define CRAY_STACK -DCRAY_STACKSEG_END=getb67
+#    endif /* RELEASE_LEVEL < 7000 */
+#  endif
+#  if !defined (M_MACHINE)
+#    define M_MACHINE "Cray"
+#    define CRAY_STACK
+#  endif
+#  define M_OS "Unicos"
+#  define SYSDEP_CFLAGS -DUSG -DPGRP_PIPE -DOPENDIR_NOT_ROBUST \
+                       -DHAVE_BCOPY CRAY_STACK
+#  define HAVE_VFPRINTF
+#  define HAVE_MULTIPLE_GROUPS
+#  define VOID_SIGHANDLER
+#  define USE_TERMCAP_EMULATION
+#  undef HAVE_ALLOCA
+#  undef HAVE_RESOURCE
+#  undef USE_GNU_MALLOC
+#endif /* cray */
+
+/* ************************ */
+/*                         */
+/*     MagicStation        */
+/*                         */
+/* ************************ */
+#if defined (MagicStation)
+#  define M_MACHINE "MagicStation"
+#  define M_OS "USG"
+#  define SYSDEP_CFLAGS -DUSGr4
+#  define HAVE_DIRENT
+#  define HAVE_GETGROUPS
+#  define HAVE_STRERROR
+#  define VOID_SIGHANDLER
+#  undef HAVE_ALLOCA
+#  undef HAVE_GETWD
+#endif /* MagicStation */
+
+/* ************************ */
+/*                         */
+/*        Plexus           */
+/*                         */
+/* ************************ */
+#if defined (plexus)
+#  define M_MACHINE "plexus"
+#  define M_OS "USG"
+#  define REQUIRED_LIBRARIES -lndir
+#  define USE_TERMCAP_EMULATION
+#  undef HAVE_DUP2
+#  undef HAVE_GETWD
+#  define HAVE_VFPRINTF
+#  undef HAVE_ALLOCA           /* -lPW doesn't work w/bash-cc? */
+#endif /* plexus */
+
+/* ************************ */
+/*                         */   
+/*     Siemens MX500        */
+/*      (SINIX 5.2x)       */
+/* ************************ */
+#ifdef sinix
+#define M_MACHINE "Siemens MX500"
+#define M_OS "SINIX V5.2x"
+#define USG
+#define HAVE_GETCWD
+#define VOID_SIGHANDLER
+#define HAVE_STRERROR
+#define HAVE_GETGROUPS
+#define HAVE_VFPRINTF
+#define HAVE_POSIX_SIGNALS
+#define HAVE_RESOURCE
+#define USE_GNU_MALLOC
+#define SYSDEP_CFLAGS -DUSGr3 -DUSG
+#define REQUIRED_LIBRARIES syscalls.o
+#undef HAVE_ALLOCA
+#undef HAVE_GETWD
+#endif /* sinix */
+
+/* ************************ */
+/*                         */
+/*  Symmetric 375 (4.2 BSD) */
+/*                         */
+/* ************************ */
+#if defined (scs) && !defined (M_MACHINE)
+#  define M_MACHINE "Symmetric_375"
+#  define M_OS "Bsd"
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_GETGROUPS
+#  define HAVE_SETLINEBUF
+#  define USE_VFPRINTF_EMULATION
+#  define USE_GNU_MALLOC
+#  undef HAVE_STRCHR
+#endif /* scs */
+
+/* ************************ */
+/*                         */
+/*          Tandem          */
+/*                         */
+/* ************************ */
+/* I don't know what this is supposed to be (Greg Lehey, LEMIS, 29 May 1995).
+ * Tandem had two very different machines which ran SVR3: the LXN, based on
+ * a Motorola 68000, and the S2, based on a MIPS R3000.  Both are obsolete
+ * (well, S2s should now be running NonStop UX version B, which is a flavour
+ * of SVR4).  I'm leaving this here and will test for NonStop UX B with the
+ * preprocessor variable __nonstopux, which is set by the native compiler and
+ * should also be set by any other compiler, such as gcc (caveat portor: you'$
+ * need to fix gcc config to to get this). */
+#if defined (tandem) && !defined (M_MACHINE)
+#  define M_MACHINE "tandem"
+#  define M_OS "USG"
+#  define SYSDEP_CFLAGS -DUSGr3
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+   /* Alloca requires either Gcc or cc with libPW.a */
+#  if !defined (HAVE_GCC)
+#    define REQUIRED_LIBRARIES -lPW
+#  endif /* !HAVE_GCC */
+#  undef HAVE_GETWD
+#endif /* Tandem running SVR3 */
+
+/* This is for NonStop UX Bxx, which is SVR4, but there's a very good
+ * chance it will trigger on NonStop UX Axx (SVR3).  If this happens,
+ * fix it or upgrade your OS. */
+#if defined (mips) && defined (__nonstopux)               /* Integrity, NonStop UX */
+#  define M_MACHINE "Integrity"
+#  define M_OS "NonStop_UX"
+#  undef HAVE_GETWD
+#  define HAVE_DIRENT
+#  define HAVE_STRERROR
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define HAVE_SYS_SIGLIST
+#  define HAVE_SETLINEBUF
+#  define HAVE_GETGROUPS
+#  undef HAVE_ALLOCA
+#endif
+
+/* ****************** */ 
+/*                    */
+/*  Fujitsu UXP/M     */
+/*                    */
+/* ****************** */ 
+
+#if defined (__uxpm__)
+#  define M_MACHINE "VP"
+#  define M_OS "USG"
+#  define VOID_SIGHANDLER
+#  define HAVE_POSIX_SIGNALS
+#  define HAVE_VFPRINTF
+#  define HAVE_DIRENT
+#  define HAVE_SETVBUF
+#  define HAVE_STRCHR
+#  define HAVE_STRERROR
+#  define HAVE_GETGROUPS
+#  define HAVE_DUP2
+#  undef HAVE_ALLOCA
+#  undef HAVE_GETWD
+#  define HAVE_GETCWD
+#  define HAVE_SYS_SIGLIST
+#  define NO_SBRK_DECL
+#  define SYSDEP_CFLAGS  -DHAVE_UID_T -Dsys_siglist=_sys_siglist  -DUSGr4 
+#  define EXTRA_LIB_SEARCH_PATH /usr/ucblib
+#  define REQUIRED_LIBRARIES -lc -lucb
+#endif
+
+/* ****************** */ 
+/*                    */
+/*     Amdahl UTS     */
+/*                    */
+/* ****************** */
+
+#if defined (UTS) && !defined (M_MACHINE)
+#  define M_MACHINE "uts"
+#  define M_OS "systemV"
+#  define SYSDEP_CFLAGS -DUSG -DMEMMOVE_MISSING
+#  define REQUIRED_LIBRARIES  
+#  undef HAVE_SYS_SIGLIST
+#  undef HAVE_GETWD
+#  undef HAVE_ALLOCA 
+#  define HAVE_VFPRINTF
+#  define HAVE_DIRENT  
+#  undef HAVE_RESOURCE   
+#endif  /* UTS */
+
+/* ************************ */
+/*                          */
+/* Stratus i860 running FTX (jonathan@sybase.com (Jonathan Stockley)) */
+/*                          */
+/* ************************ */
+/* Use 'make CPP_DEFINES=-D_FTX' to build as /usr/ccs/lib/cpp doesn't set
+   anything other than i860 which may be set on other i860 machines.
+   The C compiler, cc, sets _FTX & i860 but, unfortunately it barfs at stuff
+   in cpp-Makefile that has a # in it (it has it's own builtin cpp).
+*/
+#if defined(_FTX) && defined (i860) && !defined (M_MACHINE)
+#define M_MACHINE "Stratus_i860"
+#define M_OS "FTX"
+#define VOID_SIGHANDLER
+#define HAVE_POSIX_SIGNALS
+#define HAVE_VFPRINTF
+#define HAVE_SETVBUF
+#define REVERSED_SETVBUF_ARGS
+#define HAVE_STRCHR
+#define HAVE_STRERROR
+#define HAVE_GETGROUPS
+#define HAVE_DUP2
+#undef HAVE_ALLOCA
+#undef HAVE_GETWD
+#define HAVE_GETCWD
+#define HAVE_SYS_SIGLIST
+#define SYSDEP_CFLAGS  -DHAVE_UID_T -Dsys_siglist=_sys_siglist  -DUSGr4
+#define EXTRA_LIB_SEARCH_PATH /usr/ucblib
+#define REQUIRED_LIBRARIES -lc -lucb
+#endif /* _FTX */
+
+/* ************************ */
+/*                         */
+/*    PCS Cadmus System            */
+/*                         */
+/* ************************ */
+#if defined (cadmus) && !defined (M_MACHINE)
+#  define M_MACHINE "cadmus"
+#  define M_OS "BrainDeath"
+#  define SYSDEP_CFLAGS -DUSG
+#  define HAVE_DIRENT
+#  define HAVE_VFPRINTF
+#  define VOID_SIGHANDLER
+#  define USE_TERMCAP_EMULATION
+#  undef HAVE_GETWD
+#  undef HAVE_ALLOCA
+#  undef HAVE_WAIT_H
+#endif /* cadmus */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Generic Entry                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Use this entry for your machine if it isn't represented here.  It
+   is loosely based on a Vax running 4.3 BSD. */
+
+#if !defined (M_MACHINE)
+#  define UNKNOWN_MACHINE
+#endif
+
+#if defined (UNKNOWN_MACHINE)
+#  define M_MACHINE "UNKNOWN_MACHINE"
+#  define M_OS "UNKNOWN_OS"
+
+/* Required libraries for building on this system. */
+#  define REQUIRED_LIBRARIES
+
+/* Define HAVE_SYS_SIGLIST if your system has sys_siglist[]. */
+#  define HAVE_SYS_SIGLIST
+
+/* Undef HAVE_GETWD if your C library does not provide a working version
+   of getwd(). */
+/* #  undef HAVE_GETWD */
+
+/* Undef HAVE_GETCWD if your C library does not provide a working version
+   of getcwd(). */
+/* #  undef HAVE_GETCWD */
+
+/* Undef HAVE_ALLOCA if you are not using Gcc, and neither your library
+   nor compiler has a version of alloca ().  In that case, we will use
+   our version of alloca () in alloca.c */
+/* #  undef HAVE_ALLOCA */
+
+/* Undef USE_GNU_MALLOC if there appear to be library conflicts, or if you
+   especially desire to use your OS's version of malloc () and friends.  We
+   reccommend against this because GNU Malloc has debugging code built in. */
+/* #  undef USE_GNU_MALLOC */
+
+/* Define USE_GNU_TERMCAP if you want to use the GNU termcap library
+   instead of your system termcap library. */
+/* #  define USE_GNU_TERMCAP */
+
+/* Define HAVE_SETLINEBUF if your machine has the setlinebuf ()
+   stream library call.  Otherwise, setvbuf () will be used.  If
+   neither of them work, you can edit in your own buffer control
+   based upon your machines capabilities. */
+#  define HAVE_SETLINEBUF
+
+/* Define HAVE_VFPRINTF if your machines has the vfprintf () library
+   call.  Otherwise, printf will be used.  */
+#  define HAVE_VFPRINTF
+
+/* Define USE_VFPRINTF_EMULATION if you want to use the BSD-compatible
+   vfprintf() emulation in vprint.c. */
+/* #  define USE_VFPRINTF_EMULATION */
+
+/* Define HAVE_GETGROUPS if your OS allows you to be in multiple
+   groups simultaneously by supporting the `getgroups' system call. */
+#  define HAVE_GETGROUPS
+
+/* Define SYSDEP_CFLAGS to be the flags to cc that make your compiler
+   work.  For example, `-ma' on the RT makes alloca () work. */
+/* This is a summary of the semi-machine-independent definitions that
+   can go into SYSDEP_CFLAGS:
+
+       AFS     -       The Andrew File System is being used
+       AFS_CREATE_BUG - AFS has a bug with file creation if O_CREAT is
+                        specified
+       BSD_GETPGRP -   getpgrp(2) takes a pid argument, a la 4.3 BSD
+       HAVE_BCOPY -    bcopy(3) exists and works as in BSD
+       HAVE_GETDTABLESIZE - getdtablesize(2) exists and works correctly
+       HAVE_GETHOSTNAME - gethostname(2) or gethostname(3) is present and
+                          works as in BSD
+       HAVE_GETPW_DECLS - USG machines with the getpw* functions defined in
+                          <pwd.h> that cannot handle redefinitions in the
+                          bash source
+       HAVE_RESOURCE - <sys/resource.h> and [gs]rlimit exist and work
+       HAVE_SETDTABLESIZE - setdtablesize(2) exists and works correctly
+       HAVE_SOCKETS - this system has BSD sockets added to a System V base
+       HAVE_UID_T -    Definitions for uid_t and gid_t are in <sys/types.h>
+       INT_GROUPS_ARRAY - the second argument to getgroups(3) is an array
+                          of integers
+       MEMMOVE_MISSING - the system does not have memmove(3)
+       MKFIFO_MISSING - named pipes do not work or mkfifo(3) is missing
+       NO_SBRK_DECL - don't declare sbrk as extern char *sbrk() in
+                      lib/malloc/malloc.c
+       OPENDIR_NOT_ROBUST - opendir(3) allows you to open non-directory files
+       PGRP_PIPE -     Requires parent-child synchronization via pipes to
+                       make job control work right
+       REVERSED_SETVBUF_ARGS - brain-damaged implementation of setvbuf that
+                               has args 2 and 3 reversed from the SVID and
+                               ANSI standard
+       RLOGIN_PGRP_BUG - processes started by rlogind have a process group
+                         of 0
+                       TERMIOS_LDISC - system has a c_line line discipline member in struct
+                       termios
+       TERMIOS_MISSING - the termios(3) functions are not present or don't
+                         work, even though _POSIX_VERSION is defined
+       USG     -       The machine is running some sort of System V Unix
+       USGr3   -       The machine is running SVR3.x
+       USGr4   -       The machine is running SVR4
+       USGr4_2 -       The machine is running SVR4.2
+*/
+#  define SYSDEP_CFLAGS
+
+/* Define HAVE_STRERROR if your system supplies a definition for strerror ()
+   in the C library, or a macro in a header file. */
+/* #  define HAVE_STRERROR */
+
+/* Define HAVE_STRCASECMP if your system supplies definitions for the
+   casel-insensitive string comparison functions strcasecmp and strncasemp
+   in the C library or one of the system header files. */
+/* #  define HAVE_STRCASECMP */
+
+/* Define HAVE_DIRENT if you have the dirent library and a definition of
+   struct dirent.  If not, the BSD directory reading library and struct
+   direct are assumed. */
+/* #  define HAVE_DIRENT */
+
+/* If your system does not supply /usr/lib/libtermcap.a, but includes
+   the termcap routines as a part of the curses library, then define
+   this.  This is the case on some System V machines. */
+/* #  define USE_TERMCAP_EMULATION */
+
+/* Define VOID_SIGHANDLER if your system's signal () returns a pointer to
+   a function returning void. */
+/* #  define VOID_SIGHANDLER */
+
+/* Define EXTRA_LIB_SEARCH_PATH if your required libraries (or standard)
+   ones for that matter) are not normally in the ld search path.  For
+   example, some machines require /usr/ucblib in the ld search path so
+   that they can use -lucb. */
+/* #  define EXTRA_LIB_SEARCH_PATH /usr/ucblib */
+
+/* Define SEARCH_LIB_NEEDS_SPACE if your native ld requires a space after
+   the -L argument, which gives the name of an alternate directory to search
+   for libraries specified with -llib.  For example, the HPUX ld requires
+   this:
+       -L lib/readline -lreadline
+   instead of:
+       -Llib/readline -lreadline
+ */
+/* #  define SEARCH_LIB_NEEDS_SPACE */
+
+/* Define LD_HAS_NO_DASH_L if your ld can't grok the -L flag in any way, or
+   if it cannot grok the -l<lib> flag, or both. */
+/* #  define LD_HAS_NO_DASH_L */
+
+/* Define GCC_STANDARD if the standard `cc' is gcc and you don't want
+   to use the compiler named `gcc' for some reason. */
+/* #  define GCC_STANDARD */
+          
+#  if defined (LD_HAS_NO_DASH_L)
+#   undef SEARCH_LIB_NEEDS_SPACE
+#  endif /* LD_HAS_NO_DASH_L */
+
+#endif  /* UNKNOWN_MACHINE */
diff --git a/mailcheck.c b/mailcheck.c
new file mode 100644 (file)
index 0000000..78f657d
--- /dev/null
@@ -0,0 +1,427 @@
+/* mailcheck.c -- The check is in the mail... */
+
+/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "bashtypes.h"
+#include "posixstat.h"
+#include <sys/param.h>
+#include "bashansi.h"
+#include "shell.h"
+#include "maxpath.h"
+#include "execute_cmd.h"
+#include <tilde/tilde.h>
+
+#ifndef NOW
+#define NOW ((time_t)time ((time_t *)0))
+#endif
+
+typedef struct {
+  char *name;
+  time_t access_time;
+  time_t mod_time;
+  long file_size;
+} FILEINFO;
+
+/* The list of remembered mail files. */
+FILEINFO **mailfiles = (FILEINFO **)NULL;
+
+/* Number of mail files that we have. */
+int mailfiles_count = 0;
+
+/* The last known time that mail was checked. */
+int last_time_mail_checked = 0;
+
+/* Returns non-zero if it is time to check mail. */
+int
+time_to_check_mail ()
+{
+  char *temp = get_string_value ("MAILCHECK");
+  time_t now = NOW;
+  long seconds = -1L;
+
+  /* Skip leading whitespace in MAILCHECK. */
+  if (temp)
+    {
+      while (whitespace (*temp))
+       temp++;
+
+      seconds = atoi (temp);
+    }
+
+  /* Negative number, or non-numbers (such as empty string) cause no
+     checking to take place. */
+  if (seconds < 0)
+    return (0);
+
+  /* Time to check if MAILCHECK is explicitly set to zero, or if enough
+     time has passed since the last check. */
+  return (!seconds || ((now - last_time_mail_checked) >= seconds));
+}
+
+/* Okay, we have checked the mail.  Perhaps I should make this function
+   go away. */
+void
+reset_mail_timer ()
+{
+  last_time_mail_checked = NOW;
+}
+
+/* Locate a file in the list.  Return index of
+   entry, or -1 if not found. */
+static int
+find_mail_file (file)
+     char *file;
+{
+  register int i;
+
+  for (i = 0; i < mailfiles_count; i++)
+    if (STREQ ((mailfiles[i])->name, file))
+      return i;
+
+  return -1;
+}
+
+/* Add this file to the list of remembered files and return its index
+   in the list of mail files. */
+static int
+add_mail_file (file)
+     char *file;
+{
+  struct stat finfo;
+  char *filename;
+  int i;
+
+  filename = full_pathname (file);
+  i = find_mail_file (file);
+  if (i > -1)
+    {
+      if (stat (filename, &finfo) == 0)
+       {
+         mailfiles[i]->mod_time = finfo.st_mtime;
+         mailfiles[i]->access_time = finfo.st_atime;
+         mailfiles[i]->file_size = (long)finfo.st_size;
+       }
+      free (filename);
+      return i;
+    }
+
+  i = mailfiles_count++;
+  mailfiles = (FILEINFO **)xrealloc
+               (mailfiles, mailfiles_count * sizeof (FILEINFO *));
+
+  mailfiles[i] = (FILEINFO *)xmalloc (sizeof (FILEINFO));
+  mailfiles[i]->name = filename;
+  if (stat (filename, &finfo) == 0)
+    {
+      mailfiles[i]->access_time = finfo.st_atime;
+      mailfiles[i]->mod_time = finfo.st_mtime;
+      mailfiles[i]->file_size = finfo.st_size;
+    }
+  else
+    {
+      mailfiles[i]->access_time = mailfiles[i]->mod_time = (time_t)-1;
+      mailfiles[i]->file_size = -1L;
+    }
+  return i;
+}
+
+/* Reset the existing mail files access and modification times to zero. */
+void
+reset_mail_files ()
+{
+  register int i;
+
+  for (i = 0; i < mailfiles_count; i++)
+    {
+      mailfiles[i]->access_time = mailfiles[i]->mod_time = 0;
+      mailfiles[i]->file_size = 0L;
+    }
+}
+
+/* Free the information that we have about the remembered mail files. */
+void
+free_mail_files ()
+{
+  register int i;
+
+  for (i = 0; i < mailfiles_count; i++)
+    {
+      free (mailfiles[i]->name);
+      free (mailfiles[i]);
+    }
+
+  if (mailfiles)
+    free (mailfiles);
+
+  mailfiles_count = 0;
+  mailfiles = (FILEINFO **)NULL;
+}
+
+/* Return non-zero if FILE's mod date has changed and it has not been
+   accessed since modified. */
+static int
+file_mod_date_changed (file)
+     char *file;
+{
+  time_t time = (time_t)0;
+  struct stat finfo;
+  int i;
+
+  i = find_mail_file (file);
+  if (i != -1)
+    time = mailfiles[i]->mod_time;
+
+  if ((stat (file, &finfo) == 0) && (finfo.st_size > 0))
+    return (time != finfo.st_mtime);
+
+  return (0);
+}
+
+/* Return non-zero if FILE's access date has changed. */
+static int
+file_access_date_changed (file)
+     char *file;
+{
+  time_t time = (time_t)0;
+  struct stat finfo;
+  int i;
+
+  i = find_mail_file (file);
+  if (i != -1)
+    time = mailfiles[i]->access_time;
+
+  if ((stat (file, &finfo) == 0) && (finfo.st_size > 0))
+    return (time != finfo.st_atime);
+
+  return (0);
+}
+
+/* Return non-zero if FILE's size has increased. */
+static int
+file_has_grown (file)
+     char *file;
+{
+  long size = 0L;
+  struct stat finfo;
+  int i;
+
+  i = find_mail_file (file);
+  if (i != -1)
+    size = mailfiles[i]->file_size;
+
+  return ((stat (file, &finfo) == 0) && (finfo.st_size > size));
+}
+
+char *
+make_default_mailpath ()
+{
+  char *mp;
+
+  mp = xmalloc (1 + sizeof (DEFAULT_MAIL_PATH) + strlen (current_user.user_name));
+  strcpy (mp, DEFAULT_MAIL_PATH);
+  strcpy (mp + sizeof (DEFAULT_MAIL_PATH) - 1, current_user.user_name);
+  return (mp);
+}
+
+/* Return the colon separated list of pathnames to check for mail. */
+static char *
+get_mailpaths ()
+{
+  char *mailpaths;
+
+  mailpaths = get_string_value ("MAILPATH");
+
+  if (!mailpaths)
+    mailpaths = get_string_value ("MAIL");
+
+  if (mailpaths)
+    return (savestring (mailpaths));
+    
+  return (make_default_mailpath ());
+}
+
+/* Take an element from $MAILPATH and return the portion from
+   the first unquoted `?' or `%' to the end of the string.  This is the
+   message to be printed when the file contents change. */
+static char *
+parse_mailpath_spec (str)
+     char *str;
+{
+  char *s;
+  int pass_next;
+
+  for (s = str, pass_next = 0; s && *s; s++)
+    {
+      if (pass_next)
+       {
+         pass_next = 0;
+         continue;
+       }
+      if (*s == '\\')
+       {
+         pass_next++;
+         continue;
+       }
+      if (*s == '?' || *s == '%')
+        return s;
+    }
+  return ((char *)NULL);
+}
+      
+/* Remember the dates of the files specified by MAILPATH, or if there is
+   no MAILPATH, by the file specified in MAIL.  If neither exists, use a
+   default value, which we randomly concoct from using Unix. */
+void
+remember_mail_dates ()
+{
+  char *mailpaths;
+  char *mailfile, *mp;
+  int i = 0;
+
+  mailpaths = get_mailpaths ();  
+  while (mailfile = extract_colon_unit (mailpaths, &i))
+    {
+      mp = parse_mailpath_spec (mailfile);
+      if (mp && *mp)
+       *mp = '\0';
+      add_mail_file (mailfile);
+      free (mailfile);
+    }
+  free (mailpaths);
+}
+
+/* check_mail () is useful for more than just checking mail.  Since it has
+   the paranoids dream ability of telling you when someone has read your
+   mail, it can just as easily be used to tell you when someones .profile
+   file has been read, thus letting one know when someone else has logged
+   in.  Pretty good, huh? */
+
+/* Check for mail in some files.  If the modification date of any
+   of the files in MAILPATH has changed since we last did a
+   remember_mail_dates () then mention that the user has mail.
+   Special hack:  If the shell variable MAIL_WARNING is on and the
+   mail file has been accessed since the last time we remembered, then
+   the message "The mail in <mailfile> has been read" is printed. */
+void
+check_mail ()
+{
+  char *current_mail_file, *you_have_mail_message;
+  char *mailpaths, *mp;
+  int file_index = 0;
+  char *dollar_underscore;
+
+  dollar_underscore = get_string_value ("_");
+
+  if (dollar_underscore)
+    dollar_underscore = savestring (dollar_underscore);
+
+  mailpaths = get_mailpaths ();
+  while ((current_mail_file = extract_colon_unit (mailpaths, &file_index)))
+    {
+      char *t;
+      int use_user_notification;
+
+      if (!*current_mail_file)
+       {
+         free (current_mail_file);
+         continue;
+       }
+
+      t = full_pathname (current_mail_file);
+      free (current_mail_file);
+      current_mail_file = t;
+
+      use_user_notification = 0;
+      you_have_mail_message = "You have mail in $_";
+
+      mp = parse_mailpath_spec (current_mail_file);
+      if (mp && *mp)
+       {
+         *mp = '\0';
+         you_have_mail_message = ++mp;
+         use_user_notification++;
+       }
+
+      if (file_mod_date_changed (current_mail_file))
+       {
+         WORD_LIST *tlist;
+         int i, file_is_bigger;
+         bind_variable ("_", current_mail_file);
+#define atime mailfiles[i]->access_time
+#define mtime mailfiles[i]->mod_time
+
+         /* Have to compute this before the call to add_mail_file, which
+            resets all the information. */
+         file_is_bigger = file_has_grown (current_mail_file);
+
+         i = add_mail_file (current_mail_file);
+
+         if (i == -1)
+           continue;           /* if this returns -1 , it is a bug */
+
+         /* If the user has just run a program which manipulates the
+            mail file, then don't bother explaining that the mail
+            file has been manipulated.  Since some systems don't change
+            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)
+           {
+             free (current_mail_file);
+             continue;
+           }
+
+         /* If the mod time is later than the access time and the file
+            has grown, note the fact that this is *new* mail. */
+         if (!use_user_notification && (atime < mtime) && file_is_bigger)
+           you_have_mail_message = "You have new mail in $_";
+#undef atime
+#undef mtime
+
+         if ((tlist = expand_string (you_have_mail_message, 1)))
+           {
+             char *tem = string_list (tlist);
+             printf ("%s\n", tem);
+             free (tem);
+             dispose_words (tlist);
+           }
+         else
+           printf ("\n");
+       }
+
+      if (find_variable ("MAIL_WARNING") &&
+           file_access_date_changed (current_mail_file))
+       {
+         add_mail_file (current_mail_file);
+         printf ("The mail in %s has been read!\n", current_mail_file);
+       }
+
+      free (current_mail_file);
+    }
+  free (mailpaths);
+
+  if (dollar_underscore)
+    {
+      bind_variable ("_", dollar_underscore);
+      free (dollar_underscore);
+    }
+  else
+    unbind_variable ("_");
+}
diff --git a/make_cmd.c b/make_cmd.c
new file mode 100644 (file)
index 0000000..85eb3d5
--- /dev/null
@@ -0,0 +1,612 @@
+/* make_cmd.c --
+   Functions for making instances of the various parser constructs. */
+
+/* Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "bashtypes.h"
+#include <sys/file.h>
+#include "filecntl.h"
+#include "bashansi.h"
+#include "config.h"
+#include "command.h"
+#include "general.h"
+#include "error.h"
+#include "flags.h"
+#include "make_cmd.h"
+#include "subst.h"
+#include "input.h"
+#include "externs.h"
+
+#if defined (JOB_CONTROL)
+#include "jobs.h"
+#endif
+
+extern int line_number, current_command_line_count;
+extern int disallow_filename_globbing;
+
+WORD_DESC *
+make_word (string)
+     char *string;
+{
+  WORD_DESC *temp;
+
+  temp = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
+  temp->word = savestring (string);
+  temp->quoted = temp->dollar_present = temp->assignment = 0;
+
+  while (*string)
+    {
+      if (*string == '$') temp->dollar_present = 1;
+
+#ifdef OLDCODE
+      if (member (*string, "'`\\\""))
+       {
+         temp->quoted = 1;
+         if (*string == '\\')
+           string++;
+       }
+#else
+      switch (*string)
+       {
+         case '\\':
+           string++;
+           /*FALLTHROUGH*/
+         case '\'':
+         case '`':
+         case '"':
+           temp->quoted = 1;
+           break;
+       }
+#endif
+
+      if (*string)
+       (string++);
+    }
+  return (temp);
+}
+
+WORD_DESC *
+make_word_from_token (token)
+     int token;
+{
+  char tokenizer[2];
+
+  tokenizer[0] = token;
+  tokenizer[1] = '\0';
+
+  return (make_word (tokenizer));
+}
+
+WORD_LIST *
+make_word_list (word, link)
+     WORD_DESC *word;
+     WORD_LIST *link;
+{
+  WORD_LIST *temp;
+
+  temp = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
+  temp->word = word;
+  temp->next = link;
+  return (temp);
+}
+
+WORD_LIST *
+add_string_to_list (string, list)
+     char *string;
+     WORD_LIST *list;
+{
+  WORD_LIST *temp = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
+  temp->word = make_word (string);
+  temp->next = list;
+  return (temp);
+}
+
+#if 0
+WORD_DESC *
+coerce_to_word (number)
+     int number;
+{
+  char string[24];
+
+  sprintf (string, "%d", number);
+  return (make_word (string));
+}
+#endif
+
+COMMAND *
+make_command (type, pointer)
+     enum command_type type;
+     SIMPLE_COM *pointer;
+{
+  COMMAND *temp;
+
+  temp = (COMMAND *)xmalloc (sizeof (COMMAND));
+  temp->type = type;
+  temp->value.Simple = pointer;
+  temp->value.Simple->flags = 0;
+  temp->flags = 0;
+  temp->redirects = (REDIRECT *)NULL;
+  return (temp);
+}
+
+COMMAND *
+command_connect (com1, com2, connector)
+     COMMAND *com1, *com2;
+     int connector;
+{
+  CONNECTION *temp;
+
+  temp = (CONNECTION *)xmalloc (sizeof (CONNECTION));
+  temp->connector = connector;
+  temp->first = com1;
+  temp->second = com2;
+  return (make_command (cm_connection, (SIMPLE_COM *)temp));
+}
+
+COMMAND *
+make_for_command (name, map_list, action)
+     WORD_DESC *name;
+     WORD_LIST *map_list;
+     COMMAND *action;
+{
+  FOR_COM *temp = (FOR_COM *)xmalloc (sizeof (FOR_COM));
+
+  temp->flags = 0;
+  temp->name = name;
+  temp->map_list = map_list;
+  temp->action = action;
+  return (make_command (cm_for, (SIMPLE_COM *)temp));
+}
+
+#if defined (SELECT_COMMAND)
+COMMAND *
+make_select_command (name, map_list, action)
+     WORD_DESC *name;
+     WORD_LIST *map_list;
+     COMMAND *action;
+{
+  SELECT_COM *temp = (SELECT_COM *)xmalloc (sizeof (SELECT_COM));
+
+  temp->flags = 0;
+  temp->name = name;
+  temp->map_list = map_list;
+  temp->action = action;
+  return (make_command (cm_select, (SIMPLE_COM *)temp));
+}
+#endif
+
+COMMAND *
+make_group_command (command)
+     COMMAND *command;
+{
+  GROUP_COM *temp = (GROUP_COM *)xmalloc (sizeof (GROUP_COM));
+
+  temp->command = command;
+  return (make_command (cm_group, (SIMPLE_COM *)temp));
+}
+
+COMMAND *
+make_case_command (word, clauses)
+     WORD_DESC *word;
+     PATTERN_LIST *clauses;
+{
+  CASE_COM *temp;
+
+  temp = (CASE_COM *)xmalloc (sizeof (CASE_COM));
+  temp->flags = 0;
+  temp->word = word;
+  temp->clauses = REVERSE_LIST (clauses, PATTERN_LIST *);
+  return (make_command (cm_case, (SIMPLE_COM *)temp));
+}
+
+PATTERN_LIST *
+make_pattern_list (patterns, action)
+     WORD_LIST *patterns;
+     COMMAND *action;
+{
+  PATTERN_LIST *temp;
+
+  temp = (PATTERN_LIST *)xmalloc (sizeof (PATTERN_LIST));
+  temp->patterns = REVERSE_LIST (patterns, WORD_LIST *);
+  temp->action = action;
+  temp->next = NULL;
+  return (temp);
+}
+
+COMMAND *
+make_if_command (test, true_case, false_case)
+     COMMAND *test, *true_case, *false_case;
+{
+  IF_COM *temp;
+
+  temp = (IF_COM *)xmalloc (sizeof (IF_COM));
+  temp->flags = 0;
+  temp->test = test;
+  temp->true_case = true_case;
+  temp->false_case = false_case;
+  return (make_command (cm_if, (SIMPLE_COM *)temp));
+}
+
+static COMMAND *
+make_until_or_while (test, action, which)
+     COMMAND *test, *action;
+     enum command_type which;
+{
+  WHILE_COM *temp;
+
+  temp = (WHILE_COM *)xmalloc (sizeof (WHILE_COM));
+  temp->flags = 0;
+  temp->test = test;
+  temp->action = action;
+  return (make_command (which, (SIMPLE_COM *)temp));
+}
+
+COMMAND *
+make_while_command (test, action)
+     COMMAND *test, *action;
+{
+  return (make_until_or_while (test, action, cm_while));
+}
+
+COMMAND *
+make_until_command (test, action)
+     COMMAND *test, *action;
+{
+  return (make_until_or_while (test, action, cm_until));
+}
+
+COMMAND *
+make_bare_simple_command ()
+{
+  COMMAND *command;
+  SIMPLE_COM *temp = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM));
+
+  temp->flags = 0;
+  temp->line = line_number;
+  temp->words = (WORD_LIST *)NULL;
+  temp->redirects = (REDIRECT *)NULL;
+  command = (COMMAND *)xmalloc (sizeof (COMMAND));
+  command->type = cm_simple;
+  command->redirects = (REDIRECT *)NULL;
+  command->flags = 0;
+  command->value.Simple = temp;
+  return (command);
+}
+
+/* Return a command which is the connection of the word or redirection
+   in ELEMENT, and the command * or NULL in COMMAND. */
+COMMAND *
+make_simple_command (element, command)
+     ELEMENT element;
+     COMMAND *command;
+{
+  /* If we are starting from scratch, then make the initial command
+     structure.  Also note that we have to fill in all the slots, since
+     malloc doesn't return zeroed space. */
+  if (!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;
+    }
+  else
+    {
+      REDIRECT *r = element.redirect;
+      /* Due to the way <> is implemented, there may be more than a single
+        redirection in element.redirect.  We just follow the chain as far
+        as it goes, and hook onto the end. */
+      while (r->next)
+       r = r->next;
+      r->next = command->value.Simple->redirects;
+      command->value.Simple->redirects = element.redirect;
+    }
+  return (command);
+}
+
+#define POSIX_HERE_DOCUMENTS
+void
+make_here_document (temp)
+     REDIRECT *temp;
+{
+  int kill_leading = 0;
+
+  switch (temp->instruction)
+    {
+      /* Because we are Bourne compatible, we read the input for this
+        << or <<- redirection now, from wherever input is coming from.
+        We store the input read into a WORD_DESC.  Replace the text of
+        the redirectee.word with the new input text.  If <<- is on,
+        then remove leading TABS from each line. */
+
+      case r_deblank_reading_until:    /* <<-foo */
+       kill_leading++;
+       /* FALLTHROUGH */
+      case r_reading_until:            /* <<foo */
+       {
+         char *redir_word;
+         int redir_len;
+         char *full_line;
+         char *document = (char *)NULL;
+         int document_index = 0, document_size = 0;
+
+#if !defined (POSIX_HERE_DOCUMENTS)
+         /* Because of Bourne shell semantics, we turn off globbing, but
+            only for this style of redirection.  I feel a little ill.  */
+         {
+           int old_value = disallow_filename_globbing;
+           disallow_filename_globbing = 1;
+
+           redir_word = redirection_expand (temp->redirectee.filename);
+
+           disallow_filename_globbing = old_value;
+         }
+#else /* POSIX_HERE_DOCUMENTS */
+         /* Quote removal is the only expansion performed on the delimiter
+            for here documents, making it an extremely special case.  I
+            still feel ill. */
+         redir_word = string_quote_removal (temp->redirectee.filename->word, 0);
+#endif /* POSIX_HERE_DOCUMENTS */
+
+         /* redirection_expand will return NULL if the expansion results in
+            multiple words or no words.  Check for that here, and just abort
+            this here document if it does. */
+         if (redir_word)
+           redir_len = strlen (redir_word);
+         else
+           {
+             temp->here_doc_eof = savestring ("");
+             goto document_done;
+           }
+
+         free (temp->redirectee.filename->word);
+         temp->here_doc_eof = redir_word;
+
+         /* Read lines from wherever lines are coming from.
+            For each line read, if kill_leading, then kill the
+            leading tab characters.
+            If the line matches redir_word exactly, then we have
+            manufactured the document.  Otherwise, add the line to the
+            list of lines in the document. */
+
+         /* If the here-document delimiter was quoted, the lines should
+            be read verbatim from the input.  If it was not quoted, we
+            need to perform backslash-quoted newline removal. */
+         while (full_line = read_secondary_line
+                (temp->redirectee.filename->quoted == 0))
+           {
+             register char *line = full_line;
+             int len;
+
+             line_number++;
+
+             if (kill_leading && *line)
+               {
+                 /* Hack:  To be compatible with some Bourne shells, we 
+                    check the word before stripping the whitespace.  This
+                    is a hack, though. */
+                 if (STREQN (line, redir_word, redir_len) &&
+                     line[redir_len] == '\n')
+                   goto document_done;
+
+                 while (*line == '\t')
+                   line++;
+               }
+
+             if (!*line)
+               continue;
+
+             if (STREQN (line, redir_word, redir_len) &&
+                 line[redir_len] == '\n')
+               goto document_done;
+
+             len = strlen (line);
+             if (len + document_index >= document_size)
+               {
+                 document_size = document_size ? 2 * (document_size + len)
+                                               : 1000; /* XXX */
+                 document = xrealloc (document, document_size);
+               }
+
+             /* len is guaranteed to be > 0 because of the check for line
+                being an empty string before the call to strlen. */
+             FASTCOPY (line, document + document_index, len);
+             document_index += len;
+           }
+
+  document_done:
+         if (document)
+           document[document_index] = '\0';
+         else
+           document = savestring ("");
+         temp->redirectee.filename->word = document;
+       }
+    }
+}
+   
+/* Generate a REDIRECT from SOURCE, DEST, and INSTRUCTION. 
+   INSTRUCTION is the instruction type, SOURCE is a file descriptor,
+   and DEST is a file descriptor or a WORD_DESC *. */
+REDIRECT *
+make_redirection (source, instruction, dest_and_filename)
+     int source;
+     enum r_instruction instruction;
+     REDIRECTEE dest_and_filename;
+{
+  REDIRECT *temp = (REDIRECT *)xmalloc (sizeof (REDIRECT));
+
+  /* First do the common cases. */
+  temp->redirector = source;
+  temp->redirectee = dest_and_filename;
+  temp->instruction = instruction;
+  temp->flags = 0;
+  temp->next = (REDIRECT *)NULL;
+
+  switch (instruction)
+    {
+
+    case r_output_direction:   /* >foo */
+    case r_output_force:       /* >| foo */
+      temp->flags = O_TRUNC | O_WRONLY | O_CREAT;
+      break;
+
+    case r_input_direction:    /* <foo */
+    case r_inputa_direction:   /* foo & makes this. */
+      temp->flags = O_RDONLY;
+      break;
+
+    case r_appending_to:       /* >>foo */
+      temp->flags = O_APPEND | O_WRONLY | O_CREAT;
+      break;
+
+    case r_deblank_reading_until: /* <<-foo */
+    case r_reading_until:      /* << foo */
+      break;
+
+    case r_duplicating_input:          /* 1<&2 */
+    case r_duplicating_output:         /* 1>&2 */
+    case r_close_this:                 /* <&- */
+    case r_duplicating_input_word:     /* 1<&$foo */
+    case r_duplicating_output_word:    /* 1>&$foo */
+      break;
+    
+    case r_err_and_out:                /* command &>filename */
+      temp->flags = O_TRUNC | O_WRONLY | O_CREAT;
+      break;
+
+    case r_input_output:
+      temp->flags = O_RDWR | O_CREAT;
+      break;
+
+    default:
+      programming_error ("Redirection instruction from yyparse () '%d' is\n\
+out of range in make_redirection ().", instruction);
+      abort ();
+      break;
+    }
+  return (temp);
+}
+
+COMMAND *
+make_function_def (name, command)
+     WORD_DESC *name;
+     COMMAND *command;
+{
+  FUNCTION_DEF *temp;
+
+  temp = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF));
+  temp->command = command;
+  temp->name = name;
+  command->line = line_number - current_command_line_count + 1;
+  return (make_command (cm_function_def, (SIMPLE_COM *)temp));
+}
+
+/* Reverse the word list and redirection list in the simple command
+   has just been parsed.  It seems simpler to do this here the one
+   time then by any other method that I can think of. */
+COMMAND *
+clean_simple_command (command)
+     COMMAND *command;
+{
+  if (command->type != cm_simple)
+    {
+      programming_error
+       ("clean_simple_command () got a command with type %d.", command->type);
+    }
+  else
+    {
+      command->value.Simple->words =
+       REVERSE_LIST (command->value.Simple->words, WORD_LIST *);
+      command->value.Simple->redirects = 
+       REVERSE_LIST (command->value.Simple->redirects, REDIRECT *);
+    }
+
+  return (command);
+}
+
+/* Cons up a new array of words.  The words are taken from LIST,
+   which is a WORD_LIST *.  Absolutely everything is malloc'ed,
+   so you should free everything in this array when you are done.
+   The array is NULL terminated. */
+char **
+make_word_array (list)
+     WORD_LIST *list;
+{
+  int count = list_length (list);
+  char **array = (char **)xmalloc ((1 + count) * sizeof (char *));
+
+  for (count = 0; list; count++)
+    {
+      array[count] = xmalloc (1 + strlen (list->word->word));
+      strcpy (array[count], list->word->word);
+      list = list->next;
+    }
+  array[count] = (char *)NULL;
+  return (array);
+}
+
+/* The Yacc grammar productions have a problem, in that they take a
+   list followed by an ampersand (`&') and do a simple command connection,
+   making the entire list effectively asynchronous, instead of just
+   the last command.  This means that when the list is executed, all
+   the commands have stdin set to /dev/null when job control is not
+   active, instead of just the last.  This is wrong, and needs fixing
+   up.  This function takes the `&' and applies it to the last command
+   in the list.  This is done only for lists connected by `;'; it makes
+   `;' bind `tighter' than `&'. */
+COMMAND *
+connect_async_list (command, command2, connector)
+     COMMAND *command, *command2;
+     int connector;
+{
+  COMMAND *t, *t1, *t2;
+
+  t1 = command;
+  t = command->value.Connection->second;
+
+  if (!t || (command->flags & CMD_WANT_SUBSHELL) ||
+      command->value.Connection->connector != ';')
+    {
+      t = command_connect (command, command2, connector);
+      return t;
+    }
+
+  /* This is just defensive programming.  The Yacc precedence rules
+     will generally hand this function a command where t points directly
+     to the command we want (e.g. given a ; b ; c ; d &, t1 will point
+     to the `a ; b ; c' list and t will be the `d').  We only want to do
+     this if the list is not being executed as a unit in the background
+     with `( ... )', so we have to check for CMD_WANT_SUBSHELL.  That's
+     the only way to tell. */
+  while (((t->flags & CMD_WANT_SUBSHELL) == 0) && t->type == cm_connection &&
+        t->value.Connection->connector == ';')
+    {
+      t1 = t;
+      t = t->value.Connection->second;
+    }
+  /* Now we have t pointing to the last command in the list, and
+     t1->value.Connection->second == t. */
+  t2 = command_connect (t, command2, connector);
+  t1->value.Connection->second = t2;
+  return command;
+}
diff --git a/make_cmd.h b/make_cmd.h
new file mode 100644 (file)
index 0000000..2118770
--- /dev/null
@@ -0,0 +1,55 @@
+/* make_cmd.h -- Declarations of functions found in make_cmd.c */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_MAKE_CMD_H_)
+#define _MAKE_CMD_H_
+
+#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 WORD_DESC *make_word __P((char *));
+extern WORD_DESC *make_word_from_token __P((int));
+
+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 *));
+extern COMMAND *make_group_command __P((COMMAND *));
+extern COMMAND *make_case_command __P((WORD_DESC *, PATTERN_LIST *));
+extern PATTERN_LIST *make_pattern_list __P((WORD_LIST *, COMMAND *));
+extern COMMAND *make_if_command __P((COMMAND *, COMMAND *, COMMAND *));
+extern COMMAND *make_while_command __P((COMMAND *, COMMAND *));
+extern COMMAND *make_until_command __P((COMMAND *, COMMAND *));
+extern COMMAND *make_bare_simple_command __P((void));
+extern COMMAND *make_simple_command __P((ELEMENT, COMMAND *));
+extern void make_here_document __P((REDIRECT *));
+extern REDIRECT *make_redirection __P((int, enum r_instruction, REDIRECTEE));
+extern COMMAND *make_function_def __P((WORD_DESC *, COMMAND *));
+extern COMMAND *clean_simple_command __P((COMMAND *));
+extern char **make_word_array __P((WORD_LIST *));
+
+#if defined (SELECT_COMMAND)
+extern COMMAND *make_select_command __P((WORD_DESC *, WORD_LIST *, COMMAND *));
+#endif
+
+extern COMMAND *connect_async_list __P((COMMAND *, COMMAND *, int));
+
+#endif /* !_MAKE_CMD_H */
diff --git a/maxpath.h b/maxpath.h
new file mode 100644 (file)
index 0000000..6677309
--- /dev/null
+++ b/maxpath.h
@@ -0,0 +1,43 @@
+/* maxpath.h - Find out what this system thinks MAXPATHLEN is. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_MAXPATH_H)
+#define _MAXPATH_H
+
+#if !defined (MAXPATHLEN) && defined (HAVE_LIMITS_H)
+#  if !defined (BUILDING_MAKEFILE)
+#    include <limits.h>
+#  endif /* BUILDING_MAKEFILE */
+#endif /* !MAXPATHLEN && HAVE_LIMITS_H */
+
+#if !defined (MAXPATHLEN) && defined (HAVE_SYS_PARAM)
+#  include <sys/param.h>
+#endif /* !MAXPATHLEN && HAVE_SYS_PARAM */
+
+#if !defined (MAXPATHLEN) && defined (PATH_MAX)
+#  define MAXPATHLEN PATH_MAX
+#endif /* !MAXPATHLEN && PATH_MAX */
+
+/* Yecch!  Who cares about this gross concept in the first place? */
+#if !defined (MAXPATHLEN)
+#  define MAXPATHLEN 1024
+#endif /* MAXPATHLEN */
+
+#endif /* _MAXPATH_H */
diff --git a/memalloc.h b/memalloc.h
new file mode 100644 (file)
index 0000000..92c0648
--- /dev/null
@@ -0,0 +1,60 @@
+/* memalloc.h -- consolidate code for including alloca.h or malloc.h and
+   defining alloca. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (__MEMALLOC_H__)
+#  define __MEMALLOC_H__
+
+#if defined (sparc) && defined (sun) && !defined (HAVE_ALLOCA_H)
+#  define HAVE_ALLOCA_H
+#endif
+
+#if defined (__GNUC__) && !defined (HAVE_ALLOCA)
+#  define HAVE_ALLOCA
+#endif
+
+#if defined (HAVE_ALLOCA_H) && !defined (HAVE_ALLOCA)
+#  define HAVE_ALLOCA
+#endif /* HAVE_ALLOCA_H && !HAVE_ALLOCA */
+
+#if !defined (BUILDING_MAKEFILE)
+
+#if defined (__GNUC__)
+#  undef alloca
+#  define alloca __builtin_alloca
+#else /* !__GNUC__ */
+#  if defined (HAVE_ALLOCA_H)
+#    if defined (IBMESA)
+#      include <malloc.h>
+#    else /* !IBMESA */
+#      include <alloca.h>
+#    endif /* !IBMESA */
+#  else
+#    if defined (hpux_9) && defined (__STDC__)
+extern void *alloca ();
+#    else
+extern char *alloca ();
+#    endif
+#  endif /* !HAVE_ALLOCA_H */
+#endif /* !__GNUC__ */
+
+#endif /* !BUILDING_MAKEFILE */
+
+#endif /* __MEMALLOC_H__ */
diff --git a/newversion.c b/newversion.c
new file mode 100644 (file)
index 0000000..bdba480
--- /dev/null
@@ -0,0 +1,281 @@
+/* Simple program to make new version numbers for the shell.
+   Big deal, but it was getting out of hand to do everything
+   in the makefile. */
+
+/* Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <sys/types.h>
+#include "posixstat.h"
+#include <stdio.h>
+
+char *progname;
+char *dir;
+
+FILE *must_open ();
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  FILE *file;
+  float distver = 0.0;
+  int buildver = 0, patchlevel = 0;
+  int dist = 0, build = 0, patch = 0;
+  int dist_inc = 0, build_inc = 0, patch_inc = 0;
+  int dot_dist_needs_making = 0;
+  int arg_index = 1;
+  struct stat sb;
+
+  progname = argv[0];
+
+  while (arg_index < argc && argv[arg_index][0] == '-')
+    {
+      if (strcmp (argv[arg_index], "-dist") == 0)
+        {
+         dist++;
+         dist_inc++;
+        }
+      else if (strcmp (argv[arg_index], "-build") == 0)
+        {
+         build++;
+         build_inc++;
+        }
+      else if (strcmp (argv[arg_index], "-patch") == 0)
+        {
+          patch++;
+         patch_inc++;
+        }
+      else if (strcmp (argv[arg_index], "-dir") == 0)
+       {
+         dir = argv[++arg_index];
+         if (dir == 0)
+           {
+             fprintf (stderr, "%s: `-dir' requires an argument\n", progname);
+             exit (1);
+           }
+         if (stat (dir, &sb) < 0)
+           {
+             fprintf (stderr, "%s: cannot stat %s\n", progname, dir);
+             exit (1);
+           }
+         if ((sb.st_mode & S_IFMT) != S_IFDIR)
+           {
+             fprintf (stderr, "%s: not a directory\n", progname);
+             exit (1);
+           }
+       }
+      else
+       {
+         fprintf (stderr, "%s: unknown option: %s\n", progname, argv[arg_index]);
+         fprintf (stderr, "usage: %s [-dist|-patch|-build] [-dir directory]\n", progname);
+         exit (1);
+       }
+      arg_index++;
+    }
+
+  if (get_float_from_file (".distribution", &distver) == 0)
+    dot_dist_needs_making++;
+
+  if (get_int_from_file (".patchlevel", &patchlevel) == 0)
+    {
+      patchlevel = 0;
+      patch_inc = 0;
+    }
+
+  if (get_int_from_file (".build", &buildver) == 0)
+    buildver = 0;
+
+  /* Setting distribution version. */
+  if (dist && arg_index < argc)
+    if (sscanf (argv[arg_index], "%f", &distver) != 1)
+      {
+       fprintf (stderr, "%s: Bad input `%s'.  Expected float value for -dist.\n",
+                progname, argv[arg_index]);
+       exit (1);
+      }
+    else
+      {
+       arg_index++;
+       dist_inc = 0;
+      }
+
+  /* Setting patchlevel via argument. */
+  if (patch && arg_index < argc)
+    if (sscanf (argv[arg_index], "%d", &patchlevel) != 1)
+      {
+       fprintf (stderr, "%s: Bad input `%s'.  Expected int value for -patch.\n",
+                progname, argv[arg_index]);
+       exit (1);
+      }
+    else
+      {
+       arg_index++;
+       patch_inc = 0;
+      }
+    
+  if (build && arg_index < argc)
+    if (sscanf (argv[arg_index], "%d", &buildver) != 1)
+      {
+       fprintf (stderr, "%s: Bad input `%s'.  Expected int value for -build.\n",
+                progname, argv[arg_index]);
+       exit (1);
+      }
+    else
+      {
+       arg_index++;
+       build_inc = 0;
+      }
+
+  if (dot_dist_needs_making && !distver)
+    {
+      fprintf (stderr, "%s: There is no `.distribution' file to infer from.\n", progname);
+      exit (1);
+    }
+
+  if (dist_inc)
+    distver = distver + 0.01;
+
+  if (patch_inc)
+    patchlevel++;
+
+  if (build_inc)
+    buildver++;
+
+  file = must_open ("newversion.h", "w");
+
+  /* Output the leading comment. */
+  fprintf (file, 
+"/* Version control for the shell.  This file gets changed when you say\n\
+   `make newversion' to the Makefile.  It is created by newversion.aux. */\n");
+
+  fprintf (file, "\n/* The distribution version number of this shell. */\n");
+  fprintf (file, "#define DISTVERSION \"%.2f\"\n", distver);
+
+  fprintf (file, "\n/* The patch level of this version of the shell. */\n");
+  fprintf (file, "#define PATCHLEVEL %d\n", patchlevel);
+
+  fprintf (file, "\n/* The last built version of this shell. */\n");
+  fprintf (file, "#define BUILDVERSION %d\n", buildver);
+
+  fprintf (file, "\n/* A version string for use by sccs and the what command. */\n\n");
+  fprintf (file, "#define SCCSVERSION \"@(#)Bash version %.2f.%d(%d) GNU\"\n\n",
+    distver, patchlevel, buildver);
+
+  fclose (file);
+
+  file = must_open (".build", "w");
+  fprintf (file, "%d\n", buildver);
+  fclose (file);
+
+  /* Making a new distribution. */
+  if (dist)
+    {
+      file = must_open (".distribution", "w");
+      fprintf (file, "%.2f\n", distver);
+      fclose (file);
+    }
+
+  /* Releasing a new patch level. */
+  if (patch)
+    {
+      file = must_open (".patchlevel", "w");
+      fprintf (file, "%d\n", patchlevel);
+      fclose (file);
+    }
+
+  exit (0);
+}
+
+char *
+makename (fn)
+     char *fn;
+{
+  char *ret;
+  int dlen = 0;
+
+  if (dir)
+    dlen = strlen (dir) + 1;
+  ret = (char *)malloc (dlen + strlen (fn) + 1);
+  if (ret == 0)
+    {
+      fprintf (stderr, "%s: malloc failed\n", progname);
+      exit (1);
+    }
+  if (dir)
+    sprintf (ret, "%s/%s", dir, fn);
+  else
+    strcpy (ret, fn);
+
+  return ret;
+}
+
+get_float_from_file (filename, var)
+     char *filename;
+     float *var;
+{
+  FILE *stream;
+  int result;
+  char *name;
+
+  name = makename (filename);
+  stream = fopen (name, "r");
+  free (name);
+  if (stream == (FILE *)NULL)
+    return (0);
+  result = fscanf (stream, "%f\n", var);
+  fclose (stream);
+  return (result == 1);
+}
+
+get_int_from_file (filename, var)
+     char *filename;
+     int *var;
+{
+  FILE *stream;
+  int result;
+  char *name;
+
+  name = makename (filename);
+  stream = fopen (name, "r");
+  free (name);
+  if (stream == (FILE *)NULL)
+    return (0);
+  result = fscanf (stream, "%d\n", var);
+  fclose (stream);
+  return (result == 1);
+}
+
+FILE *
+must_open (name, mode)
+     char *name, *mode;
+{
+  FILE *temp = fopen (name, mode);
+
+  if (!temp)
+    {
+      fprintf (stderr, "%s: Cannot open `%s' for mode `%s'.\n",
+              progname, name, mode);
+      fprintf
+       (stderr,
+        "Perhaps you don't have %s permission to the file or directory.\n",
+        (strcmp (mode, "w") == 0) ? "write" : "read");
+      exit (3);
+    }
+  return (temp);
+}
diff --git a/nojobs.c b/nojobs.c
new file mode 100644 (file)
index 0000000..e5e8d2c
--- /dev/null
+++ b/nojobs.c
@@ -0,0 +1,644 @@
+/* The thing that makes children, remembers them, and contains wait loops. */
+
+/* This file works under BSD, System V, minix, and Posix systems. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 1, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "bashtypes.h"
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+
+#include "config.h"
+#include "command.h"
+#include "general.h"
+#include "filecntl.h"
+#include "jobs.h"
+#include "externs.h"
+#include "error.h"
+
+#if defined (BUFFERED_INPUT)
+#  include "input.h"
+#endif
+
+#if !defined (USG) && !defined (_POSIX_VERSION)
+#  include <sgtty.h>
+#else
+#  if defined (_POSIX_VERSION)
+#    include <termios.h>
+#  else
+#    include <termio.h>
+#    if !defined (AIXRT)
+#      include <sys/ttold.h>
+#    endif /* !AIXRT */
+#  endif /* !POSIX_VERSION */
+#endif /* USG && _POSIX_VERSION */
+
+#if !defined (SIGABRT)
+#  define SIGABRT SIGIOT
+#endif /* !SIGABRT */
+
+#if defined (USG) || defined (_POSIX_VERSION)
+#  define killpg(pg, sig)              kill(-(pg),(sig))
+#endif /* USG || _POSIX_VERSION */
+
+#if defined (USG)
+#  define siginterrupt(sig, code)
+#endif /* USG */
+
+#if defined (_POSIX_VERSION)
+#  define WAITPID(pid, statusp, options) waitpid (pid, statusp, options)
+#else
+#  define WAITPID(pid, statusp, options) wait (statusp)
+#endif /* !_POSIX_VERSION */
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+extern int interactive, interactive_shell, login_shell;
+extern int subshell_environment;
+extern int last_command_exit_value;
+#if defined (_POSIX_VERSION)
+extern sigset_t top_level_mask;
+#endif
+
+pid_t last_made_pid = NO_PID;
+pid_t last_asynchronous_pid = NO_PID;
+
+/* Call this when you start making children. */
+int already_making_children = 0;
+
+#if defined (_POSIX_VERSION)
+static void reap_zombie_children ();
+#endif
+
+struct proc_status {
+  pid_t pid;
+  int status;  /* Exit status of PID or 128 + fatal signal number */
+};
+
+static struct proc_status *pid_list = (struct proc_status *)NULL;
+static int pid_list_size = 0;
+
+#define PROC_BAD -1
+#define PROC_STILL_ALIVE -2
+
+/* Allocate new, or grow existing PID_LIST. */
+static void
+alloc_pid_list ()
+{
+  register int i;
+  int old = pid_list_size;
+
+  pid_list_size += 10;
+  pid_list = (struct proc_status *)
+    xrealloc (pid_list, pid_list_size * sizeof (struct proc_status));
+
+  /* None of the newly allocated slots have process id's yet. */
+  for (i = old; i < pid_list_size; i++)
+    pid_list[i].pid = NO_PID;  
+}
+
+/* Return the offset within the PID_LIST array of an empty slot.  This can
+   create new slots if all of the existing slots are taken. */
+static int
+find_proc_slot ()
+{
+  register int i;
+
+  for (i = 0; i < pid_list_size; i++)
+    if (pid_list[i].pid == NO_PID)
+      return (i);
+
+  if (i == pid_list_size)
+    alloc_pid_list ();
+
+  return (i);
+}
+
+/* Return the offset within the PID_LIST array of a slot containing PID,
+   or the value NO_PID if the pid wasn't found. */
+static int
+find_index_by_pid (pid)
+     pid_t pid;
+{
+  register int i;
+
+  for (i = 0; i < pid_list_size; i++)
+    if (pid_list[i].pid == pid)
+      return (i);
+
+  return (NO_PID);
+}
+
+/* Return the status of PID as looked up in the PID_LIST array.  A
+   return value of PROC_BAD indicates that PID wasn't found. */
+static int
+find_status_by_pid (pid)
+     pid_t pid;
+{
+  int i;
+
+  i = find_index_by_pid (pid);
+  if (i == NO_PID)
+    return (PROC_BAD);
+  return (pid_list[i].status);
+}
+
+/* Give PID the status value STATUS in the PID_LIST array. */
+static void
+set_pid_status (pid, status)
+     pid_t pid;
+     WAIT status;
+{
+  int slot;
+
+  slot = find_index_by_pid (pid);
+  if (slot == NO_PID)
+    return;
+
+  if (WIFSIGNALED (status))
+    pid_list[slot].status = 128 + WTERMSIG (status);
+  else
+    pid_list[slot].status = WEXITSTATUS (status);
+}
+
+static void
+add_pid (pid)
+     pid_t pid;
+{
+  int slot;
+
+  slot = find_proc_slot ();
+  pid_list[slot].pid = pid;
+  pid_list[slot].status = PROC_STILL_ALIVE;
+}
+
+int
+cleanup_dead_jobs ()
+{
+  register int i;
+
+#if defined (_POSIX_VERSION)
+  reap_zombie_children ();
+#endif
+
+  for (i = 0; i < pid_list_size; i++)
+    if (pid_list[i].status != PROC_STILL_ALIVE)
+      pid_list[i].pid = NO_PID;
+}
+
+/* Initialize the job control mechanism, and set up the tty stuff. */
+initialize_jobs ()
+{
+  get_tty_state ();
+}
+
+#if !defined (READLINE) && defined (TIOCGWINSZ) && defined (SIGWINCH)
+static SigHandler *old_winch;
+
+static sighandler
+sigwinch_sighandler (sig)
+     int sig;
+{
+  struct winsize win;
+
+#if defined (USG) && !defined (_POSIX_VERSION)
+  set_signal_handler (SIGWINCH, sigwinch_sighandler);
+#endif /* USG && !_POSIX_VERSION */
+  if ((ioctl (0, TIOCGWINSZ, &win) == 0) &&
+      win.ws_row > 0 && win.ws_col > 0)
+    set_lines_and_columns (win.ws_row, win.ws_col);
+}
+#endif /* !READLINE && TIOCGWINSZ && SIGWINCH */
+
+/* Setup this shell to handle C-C, etc. */
+void
+initialize_job_signals ()
+{
+  set_signal_handler (SIGINT, sigint_sighandler);
+#if !defined (READLINE) && defined (TIOCGWINSZ) && defined (SIGWINCH)
+  set_signal_handler (SIGWINCH, sigwinch_sighandler);
+#endif /* !READLINE && TIOCGWINSZ && SIGWINCH */
+
+  /* If this is a login shell we don't wish to be disturbed by
+     stop signals. */
+  if (login_shell)
+    {
+#if defined (SIGTSTP)
+      set_signal_handler (SIGTSTP, SIG_IGN);
+      set_signal_handler (SIGTTOU, SIG_IGN);
+      set_signal_handler (SIGTTIN, SIG_IGN);
+#endif
+    }
+}
+
+#if defined (_POSIX_VERSION)
+/* Collect the status of all zombie children so that their system
+   resources can be deallocated. */
+static void
+reap_zombie_children ()
+{
+#if defined (WNOHANG)
+  pid_t pid;
+  WAIT status;
+
+  while ((pid = waitpid (-1, (int *)&status, WNOHANG)) > 0)
+    set_pid_status (pid, status);
+#endif /* WNOHANG */
+}
+#endif /* _POSIX_VERSION */
+
+/* Fork, handling errors.  Returns the pid of the newly made child, or 0.
+   COMMAND is just for remembering the name of the command; we don't do
+   anything else with it.  ASYNC_P says what to do with the tty.  If
+   non-zero, then don't give it away. */
+pid_t
+make_child (command, async_p)
+     char *command;
+     int async_p;
+{
+  pid_t pid;
+#if defined (_POSIX_VERSION)
+  int retry = 1;
+#endif /* _POSIX_VERSION */
+
+  /* Discard saved memory. */
+  if (command)  
+    free (command);
+
+  start_pipeline ();
+
+#if defined (BUFFERED_INPUT)
+  /* If default_buffered_input is active, we are reading a script.  If
+     the command is asynchronous, we have already duplicated /dev/null
+     as fd 0, but have not changed the buffered stream corresponding to
+     the old fd 0.  We don't want to sync the stream in this case. */
+  if (default_buffered_input != -1 &&
+      (!async_p || default_buffered_input > 0))
+    sync_buffered_stream (default_buffered_input);
+#endif /* BUFFERED_INPUT */
+
+  /* Create the child, handle severe errors. */
+#if defined (_POSIX_VERSION)
+  retry_fork:
+#endif /* _POSIX_VERSION */
+
+  if ((pid = fork ()) < 0)
+    {
+#if defined (_POSIX_VERSION)
+      /* Posix systems with a non-blocking waitpid () system call available
+        get another chance after zombies are reaped. */
+      if (errno == EAGAIN && retry)
+       {
+         reap_zombie_children ();
+         retry = 0;
+         goto retry_fork;
+       }
+#endif /* _POSIX_VERSION */
+
+      internal_error ("fork: %s", strerror (errno));
+
+      throw_to_top_level ();
+    }
+  if (pid == 0)
+    {
+#if defined (BUFFERED_INPUT)
+      if (default_buffered_input > 0)
+       {
+          close_buffered_fd (default_buffered_input);
+          default_buffered_input = bash_input.location.buffered_fd = -1;
+       }
+#endif /* BUFFERED_INPUT */
+
+#if defined (_POSIX_VERSION)
+      /* Restore top-level signal mask. */
+      sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
+#endif
+
+      /* Ignore INT and QUIT in asynchronous children. */
+      if (async_p)
+       {
+#if 0
+         /* This now done by setup_async_signals (). */
+         set_signal_handler (SIGINT, SIG_IGN);
+         set_signal_handler (SIGQUIT, SIG_IGN);
+#endif
+         last_asynchronous_pid = getpid ();
+       }
+
+#if defined (SIGTSTP)
+      set_signal_handler (SIGTSTP, SIG_DFL);
+      set_signal_handler (SIGTTIN, SIG_DFL);
+      set_signal_handler (SIGTTOU, SIG_DFL);
+#endif
+    }
+  else
+    {
+      /* In the parent. */
+
+      last_made_pid = pid;
+
+      if (async_p)
+       last_asynchronous_pid = pid;
+
+      add_pid (pid);
+    }
+  return (pid);
+}
+
+/* Wait for a single pid (PID) and return its exit status. */
+wait_for_single_pid (pid)
+     pid_t pid;
+{
+  pid_t got_pid;
+  WAIT status;
+  int pstatus;
+
+  pstatus = find_status_by_pid (pid);
+
+  if (pstatus == PROC_BAD)
+    return (127);
+
+  if (pstatus != PROC_STILL_ALIVE)
+    return (pstatus);
+
+  siginterrupt (SIGINT, 1);
+  while ((got_pid = WAITPID (pid, &status, 0)) != pid)
+    {
+      if (got_pid < 0)
+       {
+         if (errno != EINTR && errno != ECHILD)
+           {
+             siginterrupt (SIGINT, 0);
+             file_error ("wait");
+           }
+         break;
+       }
+      else if (got_pid > 0)
+        set_pid_status (got_pid, status);
+    }
+
+  set_pid_status (got_pid, status);
+  siginterrupt (SIGINT, 0);
+  QUIT;
+
+  if (WIFSIGNALED (status))
+    return (128 + WTERMSIG (status));
+  else
+    return (WEXITSTATUS (status));
+}
+
+/* Wait for all of the shell's children to exit. */
+void
+wait_for_background_pids ()
+{
+  pid_t got_pid;
+  WAIT status;
+
+  /* If we aren't using job control, we let the kernel take care of the
+     bookkeeping for us.  wait () will return -1 and set errno to ECHILD 
+     when there are no more unwaited-for child processes on both
+     4.2 BSD-based and System V-based systems. */
+
+  siginterrupt (SIGINT, 1);
+
+  /* Wait for ECHILD */
+  while ((got_pid = WAITPID (-1, &status, 0)) != -1)
+    set_pid_status (got_pid, status);
+
+  if (errno != EINTR && errno != ECHILD)
+    {
+      siginterrupt (SIGINT, 0);
+      file_error("wait");
+    }
+
+  siginterrupt (SIGINT, 0);
+  QUIT;
+}
+
+/* Handle SIGINT while we are waiting for children in a script to exit.
+   All interrupts are effectively ignored by the shell, but allowed to
+   kill a running job. */
+static sighandler
+wait_sigint_handler (sig)
+     int sig;
+{
+#if 0
+  /* Run a trap handler if one has been defined. */
+  maybe_call_trap_handler (sig);
+#endif
+
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* !VOID_SIGHANDLER */
+}
+
+/* Wait for pid (one of our children) to terminate.  This is called only
+   by the execution code in execute_cmd.c. */
+int
+wait_for (pid)
+     pid_t pid;
+{
+  int return_val, pstatus;
+  pid_t got_pid;
+  WAIT status;
+  SigHandler *old_sigint_handler;
+
+  pstatus = find_status_by_pid (pid);
+
+  if (pstatus == PROC_BAD)
+    return (0);
+
+  if (pstatus != PROC_STILL_ALIVE)
+    return (pstatus);
+
+  /* If we are running a script, ignore SIGINT while we're waiting for
+     a child to exit.  The loop below does some of this, but not all. */
+  if (!interactive_shell)
+    old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
+
+  while ((got_pid = WAITPID (-1, &status, 0)) != pid) /* XXX was pid now -1 */
+    {
+      if (got_pid < 0 && errno == ECHILD)
+       {
+#if !defined (_POSIX_VERSION)
+         status.w_termsig = status.w_retcode = 0;
+#else
+         status = 0;
+#endif /* _POSIX_VERSION */
+         break;
+       }
+      else if (got_pid < 0 && errno != EINTR)
+       programming_error ("got errno %d while waiting for %d", errno, pid);
+      else if (got_pid > 0)
+       set_pid_status (got_pid, status);
+    }
+
+  set_pid_status (got_pid, status);
+
+#if defined (_POSIX_VERSION)
+  if (got_pid >= 0)
+    reap_zombie_children ();
+#endif /* _POSIX_VERSION */
+
+  if (!interactive_shell)
+    {
+      set_signal_handler (SIGINT, old_sigint_handler);
+      /* If the job exited because of SIGINT, make sure the shell acts as if
+        it had received one also. */
+      if (WIFSIGNALED (status) && (WTERMSIG (status) == SIGINT))
+       {
+         if (maybe_call_trap_handler (SIGINT) == 0)
+           (*old_sigint_handler) (SIGINT);
+       }
+    }
+           
+  /* Default return value. */
+  /* ``a full 8 bits of status is returned'' */
+  if (WIFSIGNALED (status))
+    return_val = 128 + WTERMSIG (status);
+  else
+    return_val = WEXITSTATUS (status);
+                            
+  if (!WIFSTOPPED (status) && WIFSIGNALED (status) &&
+      (WTERMSIG (status) != SIGINT))
+    {
+      fprintf (stderr, "%s", strsignal (WTERMSIG (status)));
+      if (WIFCORED (status))
+       fprintf (stderr, " (core dumped)");
+      fprintf (stderr, "\n");
+    }
+
+  if (interactive_shell && !subshell_environment)
+    {
+      if (WIFSIGNALED (status) || WIFSTOPPED (status))
+       set_tty_state ();
+      else
+       get_tty_state ();
+    }
+
+  return (return_val);
+}
+
+/* Give PID SIGNAL.  This determines what job the pid belongs to (if any).
+   If PID does belong to a job, and the job is stopped, then CONTinue the
+   job after giving it SIGNAL.  Returns -1 on failure.  If GROUP is non-null,
+   then kill the process group associated with PID. */
+int
+kill_pid (pid, signal, group)
+     pid_t pid;
+     int signal, group;
+{
+  int result;
+
+  if (group)
+    result = killpg (pid, signal);
+  else
+    result = kill (pid, signal);
+
+  return (result);
+}
+
+#if defined (_POSIX_VERSION)
+static struct termios shell_tty_info;
+#else
+#  if defined (USG)
+static struct termio shell_tty_info;
+#  else
+static struct sgttyb shell_tty_info;
+#  endif /* USG */
+#endif /* _POSIX_VERSION */
+
+static int got_tty_state = 0;
+
+/* Fill the contents of shell_tty_info with the current tty info. */
+get_tty_state ()
+{
+  int tty = open ("/dev/tty", O_RDONLY);
+  if (tty != -1)
+    {
+#if defined (_POSIX_VERSION)
+      tcgetattr (tty, &shell_tty_info);
+#else
+#  if defined (USG)
+      ioctl (tty, TCGETA, &shell_tty_info);
+#  else
+      ioctl (tty, TIOCGETP, &shell_tty_info);
+#  endif
+#endif
+      close (tty);
+      got_tty_state = 1;
+    }
+}
+
+/* Make the current tty use the state in shell_tty_info. */
+set_tty_state ()
+{
+  int tty = open ("/dev/tty", O_RDONLY);
+  if (tty != -1)
+    {
+      if (!got_tty_state)
+       {
+         close (tty);
+         return;
+       }
+#if defined (_POSIX_VERSION)
+      tcsetattr (tty, TCSADRAIN, &shell_tty_info);
+#else
+#  if defined (USG)
+      ioctl (tty, TCSETAW, &shell_tty_info);  /* Wait for output, no flush */
+#  else
+      ioctl (tty, TIOCSETN, &shell_tty_info);
+#  endif
+#endif
+      close (tty);
+    }
+}
+
+/* Give the terminal to PGRP.  */
+give_terminal_to (pgrp)
+     pid_t pgrp;
+{
+}
+
+/* Stop a pipeline. */
+stop_pipeline (async, ignore)
+     int async;
+     COMMAND *ignore;
+{
+  already_making_children = 0;
+}
+
+void
+start_pipeline ()
+{
+  already_making_children = 1;
+}
+
+/* Print descriptive information about the job with leader pid PID. */
+void
+describe_pid (pid)
+     pid_t pid;
+{
+  fprintf (stderr, "%d\n", (int) pid);
+}
diff --git a/parse.y b/parse.y
new file mode 100644 (file)
index 0000000..9c4c75a
--- /dev/null
+++ b/parse.y
@@ -0,0 +1,3005 @@
+/* Yacc grammar for bash. */
+
+/* Copyright (C) 1989 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 1, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file LICENSE.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+%{
+#include <stdio.h>
+#include "bashtypes.h"
+#include <signal.h>
+#include "bashansi.h"
+#include "shell.h"
+#include "flags.h"
+#include "input.h"
+
+#if defined (READLINE)
+#  include <readline/readline.h>
+#endif /* READLINE */
+
+#if defined (HISTORY)
+#  include "bashhist.h"
+#  include <readline/history.h>
+#endif /* HISTORY */
+
+#if defined (JOB_CONTROL)
+#  include "jobs.h"
+#endif /* JOB_CONTROL */
+
+#if defined (ALIAS)
+#  include "alias.h"
+#endif /* ALIAS */
+
+#if defined (PROMPT_STRING_DECODE)
+#include <sys/param.h>
+#include <time.h>
+#include "maxpath.h"
+#endif /* PROMPT_STRING_DECODE */
+
+#define YYDEBUG 1
+extern int eof_encountered;
+extern int no_line_editing;
+extern int current_command_number;
+extern int interactive, interactive_shell, login_shell;
+extern int posixly_correct;
+extern int last_command_exit_value;
+extern int interrupt_immediately;
+extern char *shell_name, *current_host_name;
+extern Function *last_shell_builtin, *this_shell_builtin;
+#if defined (READLINE)
+extern int bash_readline_initialized;
+#endif
+#if defined (BUFFERED_INPUT)
+extern int bash_input_fd_changed;
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*                 "Forward" declarations                          */
+/*                                                                 */
+/* **************************************************************** */
+
+/* This is kind of sickening.  In order to let these variables be seen by
+   all the functions that need them, I am forced to place their declarations
+   far away from the place where they should logically be found. */
+
+static int reserved_word_acceptable ();
+static int read_token ();
+
+static void report_syntax_error ();
+static void handle_eof_input_unit ();
+static void prompt_again ();
+static void reset_readline_prompt ();
+static void print_prompt ();
+
+/* PROMPT_STRING_POINTER points to one of these, never to an actual string. */
+char *ps1_prompt, *ps2_prompt;
+
+/* Handle on the current prompt string.  Indirectly points through
+   ps1_ or ps2_prompt. */
+char **prompt_string_pointer = (char **)NULL;
+char *current_prompt_string;
+
+/* The decoded prompt string.  Used if READLINE is not defined or if
+   editing is turned off.  Analogous to current_readline_prompt. */
+static char *current_decoded_prompt;
+
+/* The number of lines read from input while creating the current command. */
+int current_command_line_count = 0;
+
+/* Variables to manage the task of reading here documents, because we need to
+   defer the reading until after a complete command has been collected. */
+static REDIRECT *redir_stack[10];
+int need_here_doc = 0;
+
+/* Where shell input comes from.  History expansion is performed on each
+   line when the shell is interactive. */
+static char *shell_input_line = (char *)NULL;
+static int shell_input_line_index = 0;
+static int shell_input_line_size = 0;  /* Amount allocated for shell_input_line. */
+static int shell_input_line_len = 0;   /* strlen (shell_input_line) */
+
+/* Either zero or EOF. */
+static int shell_input_line_terminator = 0;
+
+static REDIRECTEE redir;
+%}
+
+%union {
+  WORD_DESC *word;             /* the word that we read. */
+  int number;                  /* the number that we read. */
+  WORD_LIST *word_list;
+  COMMAND *command;
+  REDIRECT *redirect;
+  ELEMENT element;
+  PATTERN_LIST *pattern;
+}
+
+/* Reserved words.  Members of the first group are only recognized
+   in the case that they are preceded by a list_terminator.  Members
+   of the second group are recognized only under special circumstances. */
+%token IF THEN ELSE ELIF FI CASE ESAC FOR SELECT WHILE UNTIL DO DONE FUNCTION
+%token IN BANG
+
+/* More general tokens. yylex () knows how to make these. */
+%token <word> WORD ASSIGNMENT_WORD
+%token <number> NUMBER
+%token AND_AND OR_OR GREATER_GREATER LESS_LESS LESS_AND
+%token GREATER_AND SEMI_SEMI LESS_LESS_MINUS AND_GREATER LESS_GREATER
+%token GREATER_BAR
+
+/* The types that the various syntactical units return. */
+
+%type <command> inputunit command pipeline
+%type <command> list list0 list1 simple_list simple_list1
+%type <command> simple_command shell_command_1 shell_command select_command
+%type <command> group_command function_def if_command elif_clause subshell
+%type <redirect> redirection redirections
+%type <element> simple_command_element
+%type <word_list> words pattern 
+%type <pattern> pattern_list case_clause_sequence case_clause_1 pattern_list_1
+
+%start inputunit
+
+%left '&' ';' '\n' yacc_EOF
+%left AND_AND OR_OR
+%right '|'
+%%
+
+inputunit:     simple_list '\n'
+                       {
+                         /* 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);
+                         YYACCEPT;
+                       }
+       |       '\n'
+                       {
+                         /* Case of regular command, but not a very
+                            interesting one.  Return a NULL command. */
+                         global_command = (COMMAND *)NULL;
+                         YYACCEPT;
+                       }
+       |
+               error '\n'
+                       {
+                         /* Error during parsing.  Return NULL command. */
+                         global_command = (COMMAND *)NULL;
+                         eof_encountered = 0;
+                         discard_parser_constructs (1);
+                         if (interactive)
+                           {
+                             YYACCEPT;
+                           }
+                         else
+                           {
+                             YYABORT;
+                           }
+                       }
+       |       yacc_EOF
+                       {
+                         /* Case of EOF seen by itself.  Do ignoreeof or 
+                            not. */
+                         global_command = (COMMAND *)NULL;
+                         handle_eof_input_unit ();
+                         YYACCEPT;
+                       }
+       ;
+
+words: 
+                       { $$ = (WORD_LIST *)NULL; }
+       |       words WORD
+                       { $$ = make_word_list ($2, $1); }
+       ;
+
+redirection:   '>' WORD
+                       {
+                         redir.filename = $2;
+                         $$ = make_redirection (1, r_output_direction, redir);
+                       }
+       |       '<' WORD
+                       {
+                         redir.filename = $2;
+                         $$ = make_redirection (0, r_input_direction, redir);
+                       }
+       |       NUMBER '>' WORD
+                       {
+                         redir.filename = $3;
+                         $$ = make_redirection ($1, r_output_direction, redir);
+                       }
+       |       NUMBER '<' WORD
+                       {
+                         redir.filename = $3;
+                         $$ = make_redirection ($1, r_input_direction, redir);
+                       }
+       |       GREATER_GREATER WORD
+                       {
+                         redir.filename = $2;
+                         $$ = make_redirection (1, r_appending_to, redir);
+                       }
+       |       NUMBER GREATER_GREATER WORD
+                       {
+                         redir.filename = $3;
+                         $$ = make_redirection ($1, r_appending_to, redir);
+                       }
+       |       LESS_LESS WORD
+                       {
+                         redir.filename = $2;
+                         $$ = make_redirection (0, r_reading_until, redir);
+                         redir_stack[need_here_doc++] = $$;
+                       }
+       |       NUMBER LESS_LESS WORD
+                       {
+                         redir.filename = $3;
+                         $$ = make_redirection ($1, r_reading_until, redir);
+                         redir_stack[need_here_doc++] = $$;
+                       }
+       |       LESS_AND NUMBER
+                       {
+                         redir.dest = $2;
+                         $$ = make_redirection (0, r_duplicating_input, redir);
+                       }
+       |       NUMBER LESS_AND NUMBER
+                       {
+                         redir.dest = $3;
+                         $$ = make_redirection ($1, r_duplicating_input, redir);
+                       }
+       |       GREATER_AND NUMBER
+                       {
+                         redir.dest = $2;
+                         $$ = make_redirection (1, r_duplicating_output, redir);
+                       }
+       |       NUMBER GREATER_AND NUMBER
+                       {
+                         redir.dest = $3;
+                         $$ = make_redirection ($1, r_duplicating_output, redir);
+                       }
+       |       LESS_AND WORD
+                       {
+                         redir.filename = $2;
+                         $$ = make_redirection (0, r_duplicating_input_word, redir);
+                       }
+       |       NUMBER LESS_AND WORD
+                       {
+                         redir.filename = $3;
+                         $$ = make_redirection ($1, r_duplicating_input_word, redir);
+                       }
+       |       GREATER_AND WORD
+                       {
+                         redir.filename = $2;
+                         $$ = make_redirection (1, r_duplicating_output_word, redir);
+                       }
+       |       NUMBER GREATER_AND WORD
+                       {
+                         redir.filename = $3;
+                         $$ = make_redirection ($1, r_duplicating_output_word, redir);
+                       }
+       |       LESS_LESS_MINUS WORD
+                       {
+                         redir.filename = $2;
+                         $$ = make_redirection
+                           (0, r_deblank_reading_until, redir);
+                         redir_stack[need_here_doc++] = $$;
+                       }
+       |       NUMBER LESS_LESS_MINUS WORD
+                       {
+                         redir.filename = $3;
+                         $$ = make_redirection
+                           ($1, r_deblank_reading_until, redir);
+                         redir_stack[need_here_doc++] = $$;
+                       }
+       |       GREATER_AND '-'
+                       {
+                         redir.dest = 0L;
+                         $$ = make_redirection (1, r_close_this, redir);
+                       }
+       |       NUMBER GREATER_AND '-'
+                       {
+                         redir.dest = 0L;
+                         $$ = make_redirection ($1, r_close_this, redir);
+                       }
+       |       LESS_AND '-'
+                       {
+                         redir.dest = 0L;
+                         $$ = make_redirection (0, r_close_this, redir);
+                       }
+       |       NUMBER LESS_AND '-'
+                       {
+                         redir.dest = 0L;
+                         $$ = make_redirection ($1, r_close_this, redir);
+                       }
+       |       AND_GREATER WORD
+                       {
+                         redir.filename = $2;
+                         $$ = make_redirection (1, r_err_and_out, redir);
+                       }
+       |       NUMBER LESS_GREATER WORD
+                       {
+                         redir.filename = $3;
+                         $$ = make_redirection ($1, r_input_output, redir);
+                       }
+       |       LESS_GREATER WORD
+                       {
+                         REDIRECT *t1, *t2;
+
+                         redir.filename = $2;
+                         if (posixly_correct)
+                           $$ = make_redirection (0, r_input_output, redir);
+                         else
+                           {
+                             t1 = make_redirection (0, r_input_direction, redir);
+                             redir.filename = copy_word ($2);
+                             t2 = make_redirection (1, r_output_direction, redir);
+                             t1->next = t2;
+                             $$ = t1;
+                           }
+                       }                         
+       |       GREATER_BAR WORD
+                       {
+                         redir.filename = $2;
+                         $$ = make_redirection (1, r_output_force, redir);
+                       }
+       |       NUMBER GREATER_BAR WORD
+                       {
+                         redir.filename = $3;
+                         $$ = make_redirection ($1, r_output_force, redir);
+                       }
+       ;
+
+simple_command_element: WORD
+                       { $$.word = $1; $$.redirect = 0; }
+       |       ASSIGNMENT_WORD
+                       { $$.word = $1; $$.redirect = 0; }
+       |       redirection
+                       { $$.redirect = $1; $$.word = 0; }
+       ;
+
+redirections:  redirection
+                       {
+                         $$ = $1;
+                       }
+       |       redirections redirection
+                       { 
+                         register REDIRECT *t = $1;
+
+                         while (t->next)
+                           t = t->next;
+                         t->next = $2; 
+                         $$ = $1;
+                       }
+       ;
+
+simple_command:        simple_command_element
+                       { $$ = make_simple_command ($1, (COMMAND *)NULL); }
+       |       simple_command simple_command_element
+                       { $$ = make_simple_command ($2, $1); }
+       ;
+
+command:       simple_command
+                       { $$ = clean_simple_command ($1); }
+       |       shell_command
+                       { $$ = $1; }
+       ;
+
+shell_command: shell_command_1
+                       { $$ = $1; }
+       |       shell_command_1 redirections
+                       {
+                         if ($1->redirects)
+                           {
+                             register REDIRECT *t;
+                             for (t = $1->redirects; t->next; t = t->next)
+                               ;
+                             t->next = $2;
+                           }
+                         else
+                           $1->redirects = $2;
+                         $$ = $1;
+                       }
+       ;
+
+shell_command_1: FOR WORD newlines DO list DONE
+                       { $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5); }
+       |       FOR WORD newlines '{' list '}'
+                       { $$ = make_for_command ($2, add_string_to_list ("$@", (WORD_LIST *)NULL), $5); }
+       |       FOR WORD ';' newlines DO list DONE
+                       { $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6); }
+       |       FOR WORD ';' newlines '{' list '}'
+                       { $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6); }
+       |       FOR WORD newlines IN words list_terminator newlines DO list DONE
+                       { $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9); }
+       |       FOR WORD newlines IN words list_terminator newlines '{' list '}'
+                       { $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9); }
+
+       |       CASE WORD newlines IN newlines ESAC
+                       { $$ = make_case_command ($2, (PATTERN_LIST *)NULL); }
+       |       CASE WORD newlines IN case_clause_sequence newlines ESAC
+                       { $$ = make_case_command ($2, $5); }
+       |       CASE WORD newlines IN case_clause_1 ESAC
+                       { $$ = make_case_command ($2, $5); }
+       |       WHILE list DO list DONE
+                       { $$ = make_while_command ($2, $4); }
+       |       UNTIL list DO list DONE
+                       { $$ = make_until_command ($2, $4); }
+       |       select_command
+                       { $$ = $1; }
+       |       if_command
+                       { $$ = $1; }
+       |       subshell
+                       { $$ = $1; }
+       |       group_command
+                       { $$ = $1; }
+       |       function_def
+                       { $$ = $1; }
+       ;
+
+select_command:        SELECT WORD newlines DO list DONE
+                       {
+#if defined (SELECT_COMMAND)
+                         $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5);
+#endif
+                       }
+       |       SELECT WORD newlines '{' list '}'
+                       {
+#if defined (SELECT_COMMAND)
+                         $$ = make_select_command ($2, add_string_to_list ("$@", (WORD_LIST *)NULL), $5);
+#endif
+                       }
+       |       SELECT WORD ';' newlines DO list DONE
+                       {
+#if defined (SELECT_COMMAND)
+                         $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6);
+#endif
+                       }
+       |       SELECT WORD ';' newlines '{' list '}'
+                       {
+#if defined (SELECT_COMMAND)
+                         $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6);
+#endif
+                       }
+       |       SELECT WORD newlines IN words list_terminator newlines DO list DONE
+                       {
+#if defined (SELECT_COMMAND)
+                         $$ = make_select_command ($2, (WORD_LIST *)reverse_list ($5), $9);
+#endif
+                       }
+       |       SELECT WORD newlines IN words list_terminator newlines '{' list '}'
+                       {
+#if defined (SELECT_COMMAND)
+                         $$ = make_select_command ($2, (WORD_LIST *)reverse_list ($5), $9);
+#endif
+                       }
+       ;
+
+function_def:  WORD '(' ')' newlines group_command
+                       { $$ = make_function_def ($1, $5); }
+
+       |       WORD '(' ')' newlines group_command redirections
+                       { $5->redirects = $6; $$ = make_function_def ($1, $5); }
+
+       |       FUNCTION WORD '(' ')' newlines group_command
+                       { $$ = make_function_def ($2, $6); }
+
+       |       FUNCTION WORD '(' ')' newlines group_command redirections
+                       { $6->redirects = $7; $$ = make_function_def ($2, $6); }
+
+       |       FUNCTION WORD newlines group_command
+                       { $$ = make_function_def ($2, $4); }
+
+       |       FUNCTION WORD newlines group_command redirections
+                       { $4->redirects = $5; $$ = make_function_def ($2, $4); }
+       ;
+
+subshell:      '(' list ')'
+                       { $2->flags |= CMD_WANT_SUBSHELL; $$ = $2; }
+       ;
+       
+if_command:    IF list THEN list FI
+                       { $$ = make_if_command ($2, $4, (COMMAND *)NULL); }
+       |       IF list THEN list ELSE list FI
+                       { $$ = make_if_command ($2, $4, $6); }
+       |       IF list THEN list elif_clause FI
+                       { $$ = make_if_command ($2, $4, $5); }
+       ;
+
+
+group_command: '{' list '}'
+                       { $$ = make_group_command ($2); }
+       ;
+
+elif_clause:   ELIF list THEN list
+                       { $$ = make_if_command ($2, $4, (COMMAND *)NULL); }
+       |       ELIF list THEN list ELSE list
+                       { $$ = make_if_command ($2, $4, $6); }
+       |       ELIF list THEN list elif_clause
+                       { $$ = make_if_command ($2, $4, $5); }
+       ;
+
+case_clause_1: pattern_list_1
+       |       case_clause_sequence pattern_list_1
+                       { $2->next = $1; $$ = $2; }
+       ;
+
+pattern_list_1:        newlines pattern ')' list
+                       { $$ = make_pattern_list ($2, $4); }
+       |       newlines pattern ')' newlines
+                       { $$ = make_pattern_list ($2, (COMMAND *)NULL); }
+       |       newlines '(' pattern ')' list
+                       { $$ = make_pattern_list ($3, $5); }
+       |       newlines '(' pattern ')' newlines
+                       { $$ = make_pattern_list ($3, (COMMAND *)NULL); }
+       ;
+
+case_clause_sequence:  pattern_list
+       |       case_clause_sequence pattern_list
+                       { $2->next = $1; $$ = $2; }
+       ;
+
+pattern_list:  newlines pattern ')' list SEMI_SEMI
+                       { $$ = make_pattern_list ($2, $4); }
+       |       newlines pattern ')' newlines SEMI_SEMI
+                       { $$ = make_pattern_list ($2, (COMMAND *)NULL); }
+       |       newlines '(' pattern ')' list SEMI_SEMI
+                       { $$ = make_pattern_list ($3, $5); }
+       |       newlines '(' pattern ')' newlines SEMI_SEMI
+                       { $$ = make_pattern_list ($3, (COMMAND *)NULL); }
+       ;
+
+pattern:       WORD
+                       { $$ = make_word_list ($1, (WORD_LIST *)NULL); }
+       |       pattern '|' WORD
+                       { $$ = make_word_list ($3, $1); }
+       ;
+
+/* A list allows leading or trailing newlines and
+   newlines as operators (equivalent to semicolons).
+   It must end with a newline or semicolon.
+   Lists are used within commands such as if, for, while.  */
+
+list:          newlines list0
+                       {
+                         $$ = $2;
+                         if (need_here_doc)
+                           gather_here_documents ();
+                        }
+       ;
+
+list0:         list1
+       |       list1 '\n' newlines
+       |       list1 '&' newlines
+                       {
+                         if ($1->type == cm_connection)
+                           $$ = connect_async_list ($1, (COMMAND *)NULL, '&');
+                         else
+                           $$ = command_connect ($1, (COMMAND *)NULL, '&');
+                       }
+       |       list1 ';' newlines
+
+       ;
+
+list1:         list1 AND_AND newlines list1
+                       { $$ = command_connect ($1, $4, AND_AND); }
+       |       list1 OR_OR newlines list1
+                       { $$ = command_connect ($1, $4, OR_OR); }
+       |       list1 '&' newlines list1
+                       {
+                         if ($1->type == cm_connection)
+                           $$ = connect_async_list ($1, $4, '&');
+                         else
+                           $$ = command_connect ($1, $4, '&');
+                       }
+       |       list1 ';' newlines list1
+                       { $$ = command_connect ($1, $4, ';'); }
+       |       list1 '\n' newlines list1
+                       { $$ = command_connect ($1, $4, ';'); }
+       |       pipeline
+                       { $$ = $1; }
+       |       BANG pipeline
+                       {
+                         $2->flags |= CMD_INVERT_RETURN;
+                         $$ = $2;
+                       }
+       ;
+
+list_terminator:'\n'
+       |       ';'
+       |       yacc_EOF
+       ;
+
+newlines:
+       |       newlines '\n'
+       ;
+
+/* A simple_list is a list that contains no significant newlines
+   and no leading or trailing newlines.  Newlines are allowed
+   only following operators, where they are not significant.
+
+   This is what an inputunit consists of.  */
+
+simple_list:   simple_list1
+                       {
+                         $$ = $1;
+                         if (need_here_doc)
+                           gather_here_documents ();
+                       }
+       |       simple_list1 '&'
+                       {
+                         if ($1->type == cm_connection)
+                           $$ = connect_async_list ($1, (COMMAND *)NULL, '&');
+                         else
+                           $$ = command_connect ($1, (COMMAND *)NULL, '&');
+                         if (need_here_doc)
+                           gather_here_documents ();
+                       }
+       |       simple_list1 ';'
+                       {
+                         $$ = $1;
+                         if (need_here_doc)
+                           gather_here_documents ();
+                       }
+       ;
+
+simple_list1:  simple_list1 AND_AND newlines simple_list1
+                       { $$ = command_connect ($1, $4, AND_AND); }
+       |       simple_list1 OR_OR newlines simple_list1
+                       { $$ = command_connect ($1, $4, OR_OR); }
+       |       simple_list1 '&' simple_list1
+                       {
+                         if ($1->type == cm_connection)
+                           $$ = connect_async_list ($1, $3, '&');
+                         else
+                           $$ = command_connect ($1, $3, '&');
+                       }
+       |       simple_list1 ';' simple_list1
+                       { $$ = command_connect ($1, $3, ';'); }
+       |       pipeline
+                       { $$ = $1; }
+       |       BANG pipeline
+                       {
+                         $2->flags |= CMD_INVERT_RETURN;
+                         $$ = $2;
+                       }
+       ;
+
+pipeline:
+               pipeline '|' newlines pipeline
+                       { $$ = command_connect ($1, $4, '|'); }
+       |       command
+                       { $$ = $1; }
+       ;
+%%
+
+/* Initial size to allocate for tokens, and the
+   amount to grow them by. */
+#define TOKEN_DEFAULT_GROW_SIZE 512
+
+/* The token currently being read. */
+static int current_token = 0;
+
+/* The last read token, or NULL.  read_token () uses this for context
+   checking. */
+static int last_read_token = 0;
+
+/* The token read prior to last_read_token. */
+static int token_before_that = 0;
+
+/* If non-zero, it is the token that we want read_token to return
+   regardless of what text is (or isn't) present to be read.  This
+   is reset by read_token. */
+static int token_to_read = 0;
+
+/* Global var is non-zero when end of file has been reached. */
+int EOF_Reached = 0;
+
+/* yy_getc () returns the next available character from input or EOF.
+   yy_ungetc (c) makes `c' the next character to read.
+   init_yy_io (get, unget, type, location) makes the function GET the
+   installed function for getting the next character, makes UNGET the
+   installed function for un-getting a character, sets the type of stream
+   (either string or file) from TYPE, and makes LOCATION point to where
+   the input is coming from. */
+
+/* Unconditionally returns end-of-file. */
+return_EOF ()
+{
+  return (EOF);
+}
+
+/* Variable containing the current get and unget functions.
+   See ./input.h for a clearer description. */
+BASH_INPUT bash_input;
+
+/* Set all of the fields in BASH_INPUT to NULL. */
+void
+initialize_bash_input ()
+{
+  bash_input.type = 0;
+  bash_input.name = (char *)NULL;
+  bash_input.location.file = (FILE *)NULL;
+  bash_input.location.string = (char *)NULL;
+  bash_input.getter = (Function *)NULL;
+  bash_input.ungetter = (Function *)NULL;
+}
+
+/* Set the contents of the current bash input stream from
+   GET, UNGET, TYPE, NAME, and LOCATION. */
+void
+init_yy_io (get, unget, type, name, location)
+     Function *get, *unget;
+     int type;
+     char *name;
+     INPUT_STREAM location;
+{
+  bash_input.type = type;
+  FREE (bash_input.name);
+
+  if (name)
+    bash_input.name = savestring (name);
+  else
+    bash_input.name = (char *)NULL;
+
+#if defined (CRAY)
+  memcpy((char *)&bash_input.location.string, (char *)&location.string, sizeof(location));
+#else
+  bash_input.location = location;
+#endif
+  bash_input.getter = get;
+  bash_input.ungetter = unget;
+}
+
+/* Call this to get the next character of input. */
+yy_getc ()
+{
+  return (*(bash_input.getter)) ();
+}
+
+/* Call this to unget C.  That is, to make C the next character
+   to be read. */
+yy_ungetc (c)
+     int c;
+{
+  return (*(bash_input.ungetter)) (c);
+}
+
+#if defined (BUFFERED_INPUT)
+int
+input_file_descriptor ()
+{
+  switch (bash_input.type)
+    {
+    case st_stream:
+      return (fileno (bash_input.location.file));
+    case st_bstream:
+      return (bash_input.location.buffered_fd);
+    default:
+      return (fileno (stdin));
+    }
+}
+#endif /* BUFFERED_INPUT */
+
+/* **************************************************************** */
+/*                                                                 */
+/*               Let input be read from readline ().               */
+/*                                                                 */
+/* **************************************************************** */
+
+#if defined (READLINE)
+char *current_readline_prompt = (char *)NULL;
+char *current_readline_line = (char *)NULL;
+int current_readline_line_index = 0;
+
+static int
+yy_readline_get ()
+{
+  if (!current_readline_line)
+    {
+      SigHandler *old_sigint;
+      int line_len;
+
+      if (!bash_readline_initialized)
+       initialize_readline ();
+
+#if defined (JOB_CONTROL)
+      if (job_control)
+       give_terminal_to (shell_pgrp);
+#endif /* JOB_CONTROL */
+
+      if (signal_is_ignored (SIGINT) == 0)
+       {
+         old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
+         interrupt_immediately++;
+       }
+
+      if (!current_readline_prompt)
+       current_readline_line = readline ("");
+      else
+       current_readline_line = readline (current_readline_prompt);
+
+      if (signal_is_ignored (SIGINT) == 0)
+       {
+         interrupt_immediately--;
+         set_signal_handler (SIGINT, old_sigint);
+       }
+
+      /* Reset the prompt to whatever is in the decoded value of
+        prompt_string_pointer. */
+      reset_readline_prompt ();
+
+      current_readline_line_index = 0;
+
+      if (!current_readline_line)
+       return (EOF);
+
+      line_len = strlen (current_readline_line);
+      current_readline_line = xrealloc (current_readline_line, 2 + line_len);
+      current_readline_line[line_len++] = '\n';
+      current_readline_line[line_len] = '\0';
+    }
+
+  if (!current_readline_line[current_readline_line_index])
+    {
+      free (current_readline_line);
+      current_readline_line = (char *)NULL;
+      return (yy_readline_get ());
+    }
+  else
+    {
+      int c = (unsigned char)current_readline_line[current_readline_line_index++];
+      return (c);
+    }
+}
+
+static int
+yy_readline_unget (c)
+{
+  if (current_readline_line_index && current_readline_line)
+    current_readline_line[--current_readline_line_index] = c;
+  return (c);
+}
+
+void  
+with_input_from_stdin ()
+{
+  INPUT_STREAM location;
+
+  if (bash_input.type != st_stdin && stream_on_stack (st_stdin) == 0)
+    {
+      location.string = current_readline_line;
+      init_yy_io (yy_readline_get, yy_readline_unget,
+                 st_stdin, "readline stdin", location);
+    }
+}
+
+#else  /* !READLINE */
+
+void
+with_input_from_stdin ()
+{
+  with_input_from_stream (stdin, "stdin");
+}
+#endif /* !READLINE */
+
+/* **************************************************************** */
+/*                                                                 */
+/*   Let input come from STRING.  STRING is zero terminated.       */
+/*                                                                 */
+/* **************************************************************** */
+
+static int
+yy_string_get ()
+{
+  register unsigned char *string;
+  register int c;
+
+  string = bash_input.location.string;
+  c = EOF;
+
+  /* If the string doesn't exist, or is empty, EOF found. */
+  if (string && *string)
+    {
+      c = *string++;
+      bash_input.location.string = string;
+    }
+  return (c);
+}
+
+static int
+yy_string_unget (c)
+     int c;
+{
+  *(--bash_input.location.string) = c;
+  return (c);
+}
+
+void
+with_input_from_string (string, name)
+     char *string;
+     char *name;
+{
+  INPUT_STREAM location;
+
+  location.string = string;
+
+  init_yy_io (yy_string_get, yy_string_unget, st_string, name, location);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                  Let input come from STREAM.                    */
+/*                                                                 */
+/* **************************************************************** */
+
+static int
+yy_stream_get ()
+{
+  int result = EOF;
+
+  if (bash_input.location.file)
+#if defined (NO_READ_RESTART_ON_SIGNAL)
+    result = (unsigned char)getc_with_restart (bash_input.location.file);
+#else
+    result = (unsigned char)getc (bash_input.location.file);
+#endif /* !NO_READ_RESTART_ON_SIGNAL */
+  return (result);
+}
+
+static int
+yy_stream_unget (c)
+     int c;
+{
+#if defined (NO_READ_RESTART_ON_SIGNAL)
+  return (ungetc_with_restart (c, bash_input.location.file));
+#else
+  return (ungetc (c, bash_input.location.file));
+#endif
+}
+
+void
+with_input_from_stream (stream, name)
+     FILE *stream;
+     char *name;
+{
+  INPUT_STREAM location;
+
+  location.file = stream;
+  init_yy_io (yy_stream_get, yy_stream_unget, st_stream, name, location);
+}
+
+typedef struct stream_saver {
+  struct stream_saver *next;
+  BASH_INPUT bash_input;
+  int line;
+#if defined (BUFFERED_INPUT)
+  BUFFERED_STREAM *bstream;
+#endif /* BUFFERED_INPUT */
+} STREAM_SAVER;
+
+/* The globally known line number. */
+int line_number = 0;
+
+STREAM_SAVER *stream_list = (STREAM_SAVER *)NULL;
+
+push_stream ()
+{
+  STREAM_SAVER *saver = (STREAM_SAVER *)xmalloc (sizeof (STREAM_SAVER));
+
+  xbcopy ((char *)&bash_input, (char *)&(saver->bash_input), sizeof (BASH_INPUT));
+
+#if defined (BUFFERED_INPUT)
+  saver->bstream = (BUFFERED_STREAM *)NULL;
+  /* If we have a buffered stream, clear out buffers[fd]. */
+  if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
+    {
+      saver->bstream = buffers[bash_input.location.buffered_fd];
+      buffers[bash_input.location.buffered_fd] = (BUFFERED_STREAM *)NULL;
+    }
+#endif /* BUFFERED_INPUT */
+
+  saver->line = line_number;
+  bash_input.name = (char *)NULL;
+  saver->next = stream_list;
+  stream_list = saver;
+  EOF_Reached = line_number = 0;
+}
+
+pop_stream ()
+{
+  int temp;
+
+  if (!stream_list)
+    EOF_Reached = 1;
+  else
+    {
+      STREAM_SAVER *saver = stream_list;
+
+      EOF_Reached = 0;
+      stream_list = stream_list->next;
+
+      init_yy_io (saver->bash_input.getter,
+                 saver->bash_input.ungetter,
+                 saver->bash_input.type,
+                 saver->bash_input.name,
+                 saver->bash_input.location);
+
+#if defined (BUFFERED_INPUT)
+      /* If we have a buffered stream, restore buffers[fd]. */
+      /* If the input file descriptor was changed while this was on the
+        save stack, update the buffered fd to the new file descriptor and
+        re-establish the buffer <-> bash_input fd correspondence. */
+      if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
+        {
+          if (bash_input_fd_changed)
+           {
+             bash_input_fd_changed = 0;
+             if (default_buffered_input >= 0)
+               {
+                 bash_input.location.buffered_fd = default_buffered_input;
+                 saver->bstream->b_fd = default_buffered_input;
+               }
+           }
+         buffers[bash_input.location.buffered_fd] = saver->bstream;
+        }
+#endif /* BUFFERED_INPUT */
+
+      line_number = saver->line;
+
+      FREE (saver->bash_input.name);
+      free (saver);
+    }
+}
+
+/* Return 1 if a stream of type TYPE is saved on the stack. */
+int
+stream_on_stack (type)
+     int type;
+{
+  register STREAM_SAVER *s;
+  for (s = stream_list; s; s = s->next)
+    if (s->bash_input.type == type)
+      return 1;
+  return 0;
+}
+
+\f
+/*
+ * This is used to inhibit alias expansion and reserved word recognition
+ * inside case statement pattern lists.  A `case statement pattern list'
+ * is:
+ *     everything between the `in' in a `case word in' and the next ')'
+ *     or `esac'
+ *     everything between a `;;' and the next `)' or `esac'
+ */
+static int in_case_pattern_list = 0;
+
+#if defined (ALIAS)
+/*
+ * Pseudo-global variables used in implementing token-wise alias expansion.
+ */
+
+static int expand_next_token = 0;
+
+/*
+ * Pushing and popping strings.  This works together with shell_getc to 
+ * implement alias expansion on a per-token basis.
+ */
+
+typedef struct string_saver {
+  struct string_saver *next;
+  int expand_alias;  /* Value to set expand_alias to when string is popped. */
+  char *saved_line;
+  int saved_line_size, saved_line_index, saved_line_terminator;
+} STRING_SAVER;
+
+STRING_SAVER *pushed_string_list = (STRING_SAVER *)NULL;
+
+static void save_expansion ();
+
+/*
+ * Push the current shell_input_line onto a stack of such lines and make S
+ * the current input.  Used when expanding aliases.  EXPAND is used to set
+ * the value of expand_next_token when the string is popped, so that the
+ * word after the alias in the original line is handled correctly when the
+ * alias expands to multiple words.  TOKEN is the token that was expanded
+ * into S; it is saved and used to prevent infinite recursive expansion.
+ */
+static void
+push_string (s, expand, token)
+     char *s;
+     int expand;
+     char *token;
+{
+  STRING_SAVER *temp = (STRING_SAVER *) xmalloc (sizeof (STRING_SAVER));
+
+  temp->expand_alias = expand;
+  temp->saved_line = shell_input_line;
+  temp->saved_line_size = shell_input_line_size;
+  temp->saved_line_index = shell_input_line_index;
+  temp->saved_line_terminator = shell_input_line_terminator;
+  temp->next = pushed_string_list;
+  pushed_string_list = temp;
+
+  save_expansion (token);
+
+  shell_input_line = s;
+  shell_input_line_size = strlen (s);
+  shell_input_line_index = 0;
+  shell_input_line_terminator = '\0';
+  expand_next_token = 0;
+}
+
+/*
+ * Make the top of the pushed_string stack be the current shell input.
+ * Only called when there is something on the stack.  Called from shell_getc
+ * when it thinks it has consumed the string generated by an alias expansion
+ * and needs to return to the original input line.
+ */
+static void
+pop_string ()
+{
+  STRING_SAVER *t;
+
+  FREE (shell_input_line);
+  shell_input_line = pushed_string_list->saved_line;
+  shell_input_line_index = pushed_string_list->saved_line_index;
+  shell_input_line_size = pushed_string_list->saved_line_size;
+  shell_input_line_terminator = pushed_string_list->saved_line_terminator;
+  expand_next_token = pushed_string_list->expand_alias;
+
+  t = pushed_string_list;
+  pushed_string_list = pushed_string_list->next;
+  free((char *)t);
+}
+
+static void
+free_string_list ()
+{
+  register STRING_SAVER *t = pushed_string_list, *t1;
+
+  while (t)
+    {
+      t1 = t->next;
+      FREE (t->saved_line);
+      free ((char *)t);
+      t = t1;
+    }
+  pushed_string_list = (STRING_SAVER *)NULL;
+}
+
+/* This is a stack to save the values of all tokens for which alias
+   expansion has been performed during the current call to read_token ().
+   It is used to prevent alias expansion loops:
+
+      alias foo=bar
+      alias bar=baz
+      alias baz=foo
+
+   Ideally this would be taken care of by push and pop string, but because
+   of when strings are popped the stack will not contain the correct
+   strings to test against.  (The popping is done in shell_getc, so that when
+   the current string is exhausted, shell_getc can simply pop that string off
+   the stack, restore the previous string, and continue with the character
+   following the token whose expansion was originally pushed on the stack.)
+
+   What we really want is a record of all tokens that have been expanded for
+   aliases during the `current' call to read_token().  This does that, at the
+   cost of being somewhat special-purpose (OK, OK vile and unclean). */
+
+typedef struct _exp_saver {
+      struct _exp_saver *next;
+      char *saved_token;
+} EXPANSION_SAVER;
+
+EXPANSION_SAVER *expanded_token_stack = (EXPANSION_SAVER *)NULL;
+
+static void
+save_expansion (s)
+     char *s;
+{
+  EXPANSION_SAVER *t;
+
+  t = (EXPANSION_SAVER *) xmalloc (sizeof (EXPANSION_SAVER));
+  t->saved_token = savestring (s);
+  t->next = expanded_token_stack;
+  expanded_token_stack = t;
+}
+
+/* Return 1 if TOKEN has already been expanded in the current `stack' of
+   expansions.  If it has been expanded already, it will appear as the value
+   of saved_token for some entry in the stack of expansions created for the
+   current token being expanded. */
+static int
+token_has_been_expanded (token)
+     char *token;
+{
+  register EXPANSION_SAVER *t = expanded_token_stack;
+
+  while (t)
+    {
+      if (STREQ (token, t->saved_token))
+       return (1);
+      t = t->next;
+    }
+  return (0);
+}
+
+static void
+free_expansion_stack ()
+{
+  register EXPANSION_SAVER *t = expanded_token_stack, *t1;
+
+  while (t)
+    {
+      t1 = t->next;
+      free (t->saved_token);
+      free (t);
+      t = t1;
+    }
+  expanded_token_stack = (EXPANSION_SAVER *)NULL;
+}
+
+#endif /* ALIAS */
+\f
+/* Return a line of text, taken from wherever yylex () reads input.
+   If there is no more input, then we return NULL.  If REMOVE_QUOTED_NEWLINE
+   is non-zero, we remove unquoted \<newline> pairs.  This is used by
+   read_secondary_line to read here documents. */
+static char *
+read_a_line (remove_quoted_newline)
+     int remove_quoted_newline;
+{
+  static char *line_buffer = (char *)NULL;
+  static int buffer_size = 0;
+  int indx = 0, c, peekc, pass_next;
+
+  pass_next = 0;
+  while (1)
+    {
+      c = yy_getc ();
+
+      /* Allow immediate exit if interrupted during input. */
+      QUIT;
+
+      if (c == 0)
+       continue;
+
+      /* If there is no more input, then we return NULL. */
+      if (c == EOF)
+       {
+         if (indx == 0)
+           return ((char *)NULL);
+         c = '\n';
+       }
+
+      /* `+2' in case the final character in the buffer is a newline. */
+      if (indx + 2 > buffer_size)
+       if (!buffer_size)
+         line_buffer = xmalloc (buffer_size = 128);
+       else
+         line_buffer = xrealloc (line_buffer, buffer_size += 128);
+
+      /* IF REMOVE_QUOTED_NEWLINES is non-zero, we are reading a
+        here document with an unquoted delimiter.  In this case,
+        the line will be expanded as if it were in double quotes.
+        We allow a backslash to escape the next character, but we
+        need to treat the backslash specially only if a backslash
+        quoting a backslash-newline pair appears in the line. */
+      if (pass_next)
+        {
+         line_buffer[indx++] = c;
+         pass_next = 0;
+        }
+      else if (c == '\\' && remove_quoted_newline)
+       {
+         peekc = yy_getc ();
+         if (peekc == '\n')
+           continue;   /* Make the unquoted \<newline> pair disappear. */
+         else
+           {
+             yy_ungetc (peekc);
+             pass_next = 1;
+             line_buffer[indx++] = c;          /* Preserve the backslash. */
+           }
+       }
+      else
+       line_buffer[indx++] = c;
+
+      if (c == '\n')
+       {
+         line_buffer[indx] = '\0';
+         return (line_buffer);
+       }
+    }
+}
+
+/* Return a line as in read_a_line (), but insure that the prompt is
+   the secondary prompt.  This is used to read the lines of a here
+   document.  REMOVE_QUOTED_NEWLINE is non-zero if we should remove
+   newlines quoted with backslashes while reading the line.  It is
+   non-zero unless the delimiter of the here document was quoted. */
+char *
+read_secondary_line (remove_quoted_newline)
+     int remove_quoted_newline;
+{
+  prompt_string_pointer = &ps2_prompt;
+  prompt_again ();
+  return (read_a_line (remove_quoted_newline));
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                             YYLEX ()                            */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Reserved words.  These are only recognized as the first word of a
+   command. */
+STRING_INT_ALIST word_token_alist[] = {
+  { "if", IF },
+  { "then", THEN },
+  { "else", ELSE },
+  { "elif", ELIF },
+  { "fi", FI },
+  { "case", CASE },
+  { "esac", ESAC },
+  { "for", FOR },
+#if defined (SELECT_COMMAND)
+  { "select", SELECT },
+#endif
+  { "while", WHILE },
+  { "until", UNTIL },
+  { "do", DO },
+  { "done", DONE },
+  { "in", IN },
+  { "function", FUNCTION },
+  { "{", '{' },
+  { "}", '}' },
+  { "!", BANG },
+  { (char *)NULL, 0}
+};
+
+/* Return the next shell input character.  This always reads characters
+   from shell_input_line; when that line is exhausted, it is time to
+   read the next line.  This is called by read_token when the shell is
+   processing normal command input. */
+static int
+shell_getc (remove_quoted_newline)
+     int remove_quoted_newline;
+{
+  int c;
+
+  QUIT;
+
+#if defined (ALIAS)
+  /* If shell_input_line[shell_input_line_index] == 0, but there is
+     something on the pushed list of strings, then we don't want to go
+     off and get another line.  We let the code down below handle it. */
+
+  if (!shell_input_line || ((!shell_input_line[shell_input_line_index]) &&
+                           (pushed_string_list == (STRING_SAVER *)NULL)))
+#else /* !ALIAS */
+  if (!shell_input_line || !shell_input_line[shell_input_line_index])
+#endif /* !ALIAS */
+    {
+      register int i, l;
+
+      restart_read_next_line:
+
+      line_number++;
+
+    restart_read:
+
+      /* Allow immediate exit if interrupted during input. */
+      QUIT;
+
+      i = 0;
+      shell_input_line_terminator = 0;
+
+#if defined (JOB_CONTROL)
+      /* This can cause a problem when reading a command as the result
+        of a trap, when the trap is called from flush_child.  This call
+        had better not cause jobs to disappear from the job table in
+        that case, or we will have big trouble. */
+      notify_and_cleanup ();
+#else /* !JOB_CONTROL */
+      cleanup_dead_jobs ();
+#endif /* !JOB_CONTROL */
+
+#if defined (READLINE)
+      if (interactive && bash_input.type != st_string && no_line_editing)
+#else
+      if (interactive && bash_input.type != st_string)
+#endif
+       print_prompt ();
+
+      if (bash_input.type == st_stream)
+       clearerr (stdin);
+
+      while (c = yy_getc ())
+       {
+         /* Allow immediate exit if interrupted during input. */
+         QUIT;
+
+         if (i + 2 > shell_input_line_size)
+           shell_input_line =
+             xrealloc (shell_input_line, shell_input_line_size += 256);
+
+         if (c == EOF)
+           {
+             if (bash_input.type == st_stream)
+               clearerr (stdin);
+
+             if (!i)
+               shell_input_line_terminator = EOF;
+
+             shell_input_line[i] = '\0';
+             break;
+           }
+
+         shell_input_line[i++] = c;
+
+         if (c == '\n')
+           {
+             shell_input_line[--i] = '\0';
+             current_command_line_count++;
+             break;
+           }
+       }
+      shell_input_line_index = 0;
+      shell_input_line_len = i;                /* == strlen (shell_input_line) */
+
+#if defined (HISTORY)
+      if (interactive && shell_input_line && shell_input_line[0])
+       {
+         char *expansions;
+
+         expansions = pre_process_line (shell_input_line, 1, 1);
+
+         free (shell_input_line);
+         shell_input_line = expansions;
+         shell_input_line_len = shell_input_line ?
+                                strlen (shell_input_line) :
+                                0;
+         if (!shell_input_line_len)
+           current_command_line_count--;
+
+         /* 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;
+       }
+#endif /* HISTORY */
+
+      if (shell_input_line)
+       {
+         /* Lines that signify the end of the shell's input should not be
+            echoed. */
+         if (echo_input_at_read && (shell_input_line[0] ||
+                                    shell_input_line_terminator != EOF))
+           fprintf (stderr, "%s\n", shell_input_line);
+       }
+      else
+       {
+         shell_input_line_size = 0;
+         prompt_string_pointer = &current_prompt_string;
+         prompt_again ();
+         goto restart_read;
+       }
+
+      /* Add the newline to the end of this string, iff the string does
+        not already end in an EOF character.  */
+      if (shell_input_line_terminator != EOF)
+       {
+         l = shell_input_line_len;     /* was a call to strlen */
+
+         if (l + 3 > shell_input_line_size)
+           shell_input_line = xrealloc (shell_input_line,
+                                       1 + (shell_input_line_size += 2));
+
+         shell_input_line[l] = '\n';
+         shell_input_line[l + 1] = '\0';
+       }
+    }
+  
+  c = shell_input_line[shell_input_line_index];
+
+  if (c)
+    shell_input_line_index++;
+
+  if (c == '\\' && remove_quoted_newline &&
+      shell_input_line[shell_input_line_index] == '\n')
+    {
+       prompt_again ();
+       goto restart_read_next_line;
+    }
+
+#if defined (ALIAS)
+  /* If C is NULL, we have reached the end of the current input string.  If
+     pushed_string_list is non-empty, it's time to pop to the previous string
+     because we have fully consumed the result of the last alias expansion.
+     Do it transparently; just return the next character of the string popped
+     to. */
+  if (!c && (pushed_string_list != (STRING_SAVER *)NULL))
+    {
+      pop_string ();
+      c = shell_input_line[shell_input_line_index];
+      if (c)
+       shell_input_line_index++;
+    }
+#endif /* ALIAS */
+
+  if (!c && shell_input_line_terminator == EOF)
+    {
+      if (shell_input_line_index != 0)
+       return ('\n');
+      else
+       return (EOF);
+    }
+
+  return ((unsigned char)c);
+}
+
+/* Put C back into the input for the shell. */
+static void
+shell_ungetc (c)
+     int c;
+{
+  if (shell_input_line && shell_input_line_index)
+    shell_input_line[--shell_input_line_index] = c;
+}
+
+/* Discard input until CHARACTER is seen. */
+static void
+discard_until (character)
+     int character;
+{
+  int c;
+
+  while ((c = shell_getc (0)) != EOF && c != character)
+    ;
+
+  if (c != EOF)
+    shell_ungetc (c);
+}
+\f
+/* Place to remember the token.  We try to keep the buffer
+   at a reasonable size, but it can grow. */
+static char *token = (char *)NULL;
+
+/* Current size of the token buffer. */
+static int token_buffer_size = 0;
+
+void
+execute_prompt_command (command)
+     char *command;
+{
+  Function *temp_last, *temp_this;
+  char *last_lastarg;
+  int temp_exit_value, temp_eof_encountered;
+
+  temp_last = last_shell_builtin;
+  temp_this = this_shell_builtin;
+  temp_exit_value = last_command_exit_value;
+  temp_eof_encountered = eof_encountered;
+  last_lastarg = get_string_value ("_");
+  if (last_lastarg)
+    last_lastarg = savestring (last_lastarg);
+
+  parse_and_execute (savestring (command), "PROMPT_COMMAND", 0);
+
+  last_shell_builtin = temp_last;
+  this_shell_builtin = temp_this;
+  last_command_exit_value = temp_exit_value;
+  eof_encountered = temp_eof_encountered;
+
+  bind_variable ("_", last_lastarg);
+  FREE (last_lastarg);
+
+  if (token_to_read == '\n')
+    token_to_read = 0;
+}
+
+/* Command to read_token () explaining what we want it to do. */
+#define READ 0
+#define RESET 1
+#define prompt_is_ps1 \
+      (!prompt_string_pointer || prompt_string_pointer == &ps1_prompt)
+
+/* Function for yyparse to call.  yylex keeps track of
+   the last two tokens read, and calls read_token.  */
+
+yylex ()
+{
+  if (interactive && (!current_token || current_token == '\n'))
+    {
+      /* Before we print a prompt, we might have to check mailboxes.
+        We do this only if it is time to do so. Notice that only here
+        is the mail alarm reset; nothing takes place in check_mail ()
+        except the checking of mail.  Please don't change this. */
+      if (prompt_is_ps1 && time_to_check_mail ())
+       {
+         check_mail ();
+         reset_mail_timer ();
+       }
+
+      /* Avoid printing a prompt if we're not going to read anything, e.g.
+        after resetting the parser with read_token (RESET). */
+      if (token_to_read == 0 && interactive)
+       prompt_again ();
+    }
+
+  token_before_that = last_read_token;
+  last_read_token = current_token;
+  current_token = read_token (READ);
+  return (current_token);
+}
+
+/* Called from shell.c when Control-C is typed at top level.  Or
+   by the error rule at top level. */
+reset_parser ()
+{
+  read_token (RESET);
+}
+  
+/* When non-zero, we have read the required tokens
+   which allow ESAC to be the next one read. */
+static int allow_esac_as_next = 0;
+
+/* When non-zero, accept single '{' as a token itself. */
+static int allow_open_brace = 0;
+
+/* DELIMITERS is a stack of the nested delimiters that we have
+   encountered so far. */
+static char *delimiters = (char *)NULL;
+
+/* Offset into the stack of delimiters. */
+int delimiter_depth = 0;
+
+/* How many slots are allocated to DELIMITERS. */
+static int delimiter_space = 0;
+
+void
+gather_here_documents ()
+{
+  int r = 0;
+  while (need_here_doc)
+    {
+      make_here_document (redir_stack[r++]);
+      need_here_doc--;
+    }
+}
+
+/* Macro for accessing the top delimiter on the stack.  Returns the
+   delimiter or zero if none. */
+#define current_delimiter() \
+  (delimiter_depth ? delimiters[delimiter_depth - 1] : 0)
+
+#define push_delimiter(character) \
+  do \
+    { \
+      if (delimiter_depth + 2 > delimiter_space) \
+       delimiters = xrealloc \
+         (delimiters, (delimiter_space += 10) * sizeof (char)); \
+      delimiters[delimiter_depth] = character; \
+      delimiter_depth++; \
+    } \
+  while (0)
+
+/* When non-zero, an open-brace used to create a group is awaiting a close
+   brace partner. */
+static int open_brace_awaiting_satisfaction = 0;
+
+#define command_token_position(token) \
+  (((token) == ASSIGNMENT_WORD) || \
+   ((token) != SEMI_SEMI && reserved_word_acceptable(token)))
+
+#define assignment_acceptable(token) command_token_position(token) && \
+                                       (in_case_pattern_list == 0)
+
+/* Check to see if TOKEN is a reserved word and return the token
+   value if it is. */
+#define CHECK_FOR_RESERVED_WORD(tok) \
+  do { \
+    if (!dollar_present && !quoted && \
+       reserved_word_acceptable (last_read_token)) \
+      { \
+       int i; \
+       for (i = 0; word_token_alist[i].word != (char *)NULL; i++) \
+         if (STREQ (tok, word_token_alist[i].word)) \
+           { \
+             if (in_case_pattern_list && (word_token_alist[i].token != ESAC)) \
+               break; \
+\
+             if (word_token_alist[i].token == ESAC) \
+               in_case_pattern_list = 0; \
+\
+             if (word_token_alist[i].token == '{') \
+               open_brace_awaiting_satisfaction++; \
+\
+             if (word_token_alist[i].token == '}' && open_brace_awaiting_satisfaction) \
+               open_brace_awaiting_satisfaction--; \
+\
+             return (word_token_alist[i].token); \
+           } \
+      } \
+  } while (0)
+
+/* Read the next token.  Command can be READ (normal operation) or 
+   RESET (to normalize state). */
+static int
+read_token (command)
+     int command;
+{
+  int character;               /* Current character. */
+  int peek_char;               /* Temporary look-ahead character. */
+  int result;                  /* The thing to return. */
+  WORD_DESC *the_word;         /* The value for YYLVAL when a WORD is read. */
+
+  if (token_buffer_size < TOKEN_DEFAULT_GROW_SIZE)
+    {
+      FREE (token);
+      token = xmalloc (token_buffer_size = TOKEN_DEFAULT_GROW_SIZE);
+    }
+
+  if (command == RESET)
+    {
+      delimiter_depth = 0;     /* No delimiters found so far. */
+      open_brace_awaiting_satisfaction = 0;
+      in_case_pattern_list = 0;
+
+#if defined (ALIAS)
+      if (pushed_string_list)
+       {
+         free_string_list ();
+         pushed_string_list = (STRING_SAVER *)NULL;
+       }
+
+      if (expanded_token_stack)
+       {
+         free_expansion_stack ();
+         expanded_token_stack = (EXPANSION_SAVER *)NULL;
+       }
+
+      expand_next_token = 0;
+#endif /* ALIAS */
+
+      if (shell_input_line)
+       {
+         free (shell_input_line);
+         shell_input_line = (char *)NULL;
+         shell_input_line_size = shell_input_line_index = 0;
+       }
+      last_read_token = '\n';
+      token_to_read = '\n';
+      return ('\n');
+    }
+
+  if (token_to_read)
+    {
+      int rt = token_to_read;
+      token_to_read = 0;
+      return (rt);
+    }
+
+#if defined (ALIAS)
+  /* If we hit read_token () and there are no saved strings on the
+     pushed_string_list, then we are no longer currently expanding a
+     token.  This can't be done in pop_stream, because pop_stream
+     may pop the stream before the current token has finished being
+     completely expanded (consider what happens when we alias foo to foo,
+     and then try to expand it). */
+  if (!pushed_string_list && expanded_token_stack)
+    {
+      free_expansion_stack ();
+      expanded_token_stack = (EXPANSION_SAVER *)NULL;
+    }
+
+  /* This is a place to jump back to once we have successfully expanded a
+     token with an alias and pushed the string with push_string () */
+ re_read_token:
+
+#endif /* ALIAS */
+
+  /* Read a single word from input.  Start by skipping blanks. */
+  while ((character = shell_getc (1)) != EOF && whitespace (character));
+
+  if (character == EOF)
+    {
+      EOF_Reached = 1;
+      return (yacc_EOF);
+    }
+
+  if (character == '#' && (!interactive || interactive_comments))
+    {
+      /* A comment.  Discard until EOL or EOF, and then return a newline. */
+      discard_until ('\n');
+      shell_getc (0);
+
+      /* If we're about to return an unquoted newline, we can go and collect
+        the text of any pending here documents. */
+      if (need_here_doc)
+        gather_here_documents ();
+
+#if defined (ALIAS)
+      expand_next_token = 0;
+#endif /* ALIAS */
+
+      return ('\n');
+    }
+
+  if (character == '\n')
+    {
+      /* If we're about to return an unquoted newline, we can go and collect
+        the text of any pending here document. */
+      if (need_here_doc)
+       gather_here_documents ();
+
+#if defined (ALIAS)
+      expand_next_token = 0;
+#endif /* ALIAS */
+
+      return (character);
+    }
+
+  if (member (character, "()<>;&|"))
+    {
+#if defined (ALIAS)
+      /* Turn off alias tokenization iff this character sequence would
+        not leave us ready to read a command. */
+      if (character == '<' || character == '>')
+       expand_next_token = 0;
+#endif /* ALIAS */
+
+      /* Please note that the shell does not allow whitespace to
+        appear in between tokens which are character pairs, such as
+        "<<" or ">>".  I believe this is the correct behaviour. */
+      if (character == (peek_char = shell_getc (1)))
+       {
+         switch (character)
+           {
+             /* If '<' then we could be at "<<" or at "<<-".  We have to
+                look ahead one more character. */
+           case '<':
+             peek_char = shell_getc (1);
+             if (peek_char == '-')
+               return (LESS_LESS_MINUS);
+             else
+               {
+                 shell_ungetc (peek_char);
+                 return (LESS_LESS);
+               }
+
+           case '>':
+             return (GREATER_GREATER);
+
+           case ';':
+             in_case_pattern_list = 1;
+#if defined (ALIAS)
+             expand_next_token = 0;
+#endif /* ALIAS */
+             return (SEMI_SEMI);
+
+           case '&':
+             return (AND_AND);
+
+           case '|':
+             return (OR_OR);
+           }
+       }
+      else
+       {
+         if (peek_char == '&')
+           {
+             switch (character)
+               {
+               case '<': return (LESS_AND);
+               case '>': return (GREATER_AND);
+               }
+           }
+         if (character == '<' && peek_char == '>')
+           return (LESS_GREATER);
+         if (character == '>' && peek_char == '|')
+           return (GREATER_BAR);
+         if (peek_char == '>' && character == '&')
+           return (AND_GREATER);
+       }
+      shell_ungetc (peek_char);
+
+      /* 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)
+       {
+         allow_open_brace = 1;
+#if defined (ALIAS)
+         expand_next_token = 0;
+#endif /* ALIAS */
+       }
+
+      if (in_case_pattern_list && (character == ')'))
+       in_case_pattern_list = 0;
+
+#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 == '(') == 0))
+#endif /* PROCESS_SUBSTITUTION */
+       return (character);
+    }
+
+  /* Hack <&- (close stdin) case. */
+  if (character == '-')
+    {
+      switch (last_read_token)
+       {
+       case LESS_AND:
+       case GREATER_AND:
+         return (character);
+       }
+    }
+  
+  /* Okay, if we got this far, we have to read a word.  Read one,
+     and then check it against the known ones. */
+  {
+    /* Index into the token that we are building. */
+    int token_index = 0;
+
+    /* ALL_DIGITS becomes zero when we see a non-digit. */
+    int all_digits = digit (character);
+
+    /* DOLLAR_PRESENT becomes non-zero if we see a `$'. */
+    int dollar_present = 0;
+
+    /* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */
+    int quoted = 0;
+
+    /* Non-zero means to ignore the value of the next character, and just
+       to add it no matter what. */
+    int pass_next_character = 0;
+
+    /* Non-zero means parsing a dollar-paren construct.  It is the count of
+       un-quoted closes we need to see. */
+    int dollar_paren_level = 0;
+
+    /* Non-zero means parsing a dollar-bracket construct ($[...]).  It is
+       the count of un-quoted `]' characters we need to see. */
+    int dollar_bracket_level = 0;
+
+    /* Non-zero means parsing a `${' construct.  It is the count of
+       un-quoted `}' we need to see. */
+    int dollar_brace_level = 0;
+
+    /* A level variable for parsing '${ ... }' constructs inside of double
+       quotes. */
+    int delimited_brace_level = 0;
+
+    /* A boolean variable denoting whether or not we are currently parsing
+       a double-quoted string embedded in a $( ) or ${ } construct. */
+    int embedded_quoted_string = 0;
+
+    /* Another level variable.  This one is for dollar_parens inside of
+       double-quotes. */
+    int delimited_paren_level = 0;
+
+    /* The current delimiting character. */
+    int cd;
+
+    for (;;)
+      {
+       if (character == EOF)
+         goto got_token;
+
+       if (pass_next_character)
+         {
+           pass_next_character = 0;
+           goto got_character;
+         }
+
+       cd = current_delimiter ();
+
+       if (cd && character == '\\' && cd != '\'')
+         {
+           peek_char = shell_getc (0);
+           if (peek_char != '\\')
+             shell_ungetc (peek_char);
+           else
+             {
+               token[token_index++] = character;
+               goto got_character;
+             }
+         }
+
+       /* Handle backslashes.  Quote lots of things when not inside of
+          double-quotes, quote some things inside of double-quotes. */
+          
+       if (character == '\\' && (!delimiter_depth || cd != '\''))
+         {
+           peek_char = shell_getc (0);
+
+           /* Backslash-newline is ignored in all cases excepting
+              when quoted with single quotes. */
+           if (peek_char == '\n')
+             {
+               character = '\n';
+               goto next_character;
+             }
+           else
+             {
+               shell_ungetc (peek_char);
+
+               /* If the next character is to be quoted, do it now. */
+               if (!cd || cd == '`' ||
+                   (cd == '"' && member (peek_char, slashify_in_quotes)))
+                 {
+                   pass_next_character++;
+                   quoted = 1;
+                   goto got_character;
+                 }
+             }
+         }
+
+       /* This is a hack, in its present form.  If a backquote substitution
+          appears within double quotes, everything within the backquotes
+          should be read as part of a single word.  Jesus.  Now I see why
+          Korn introduced the $() form. */
+       if (delimiter_depth && (cd == '"') && (character == '`'))
+         {
+           push_delimiter (character);
+           goto got_character;
+         }
+
+       cd = current_delimiter ();              /* XXX - may not need */
+       if (delimiter_depth)
+         {
+           if (character == cd)
+             {
+               /* If we see a double quote while parsing a double-quoted
+                 $( ) or ${ }, and we have not seen ) or }, respectively,
+                  note that we are in the middle of reading an embedded
+                  quoted string. */
+               if ((delimited_paren_level || delimited_brace_level) &&
+                   (character == '"'))
+                 {
+                   embedded_quoted_string = !embedded_quoted_string;
+                   goto got_character;
+                 }
+               
+               delimiter_depth--;
+               goto got_character;
+             }
+         }
+
+       if (cd != '\'')
+         {
+#if defined (PROCESS_SUBSTITUTION)
+           if (character == '$' || character == '<' || character == '>')
+#else
+           if (character == '$')
+#endif /* !PROCESS_SUBSTITUTION */
+             {
+               /* If we're in the middle of parsing a $( ) or ${ }
+                  construct with an embedded quoted string, don't
+                  bother looking at this character any further. */
+               if (embedded_quoted_string)
+                 goto got_character;
+
+               peek_char = shell_getc (1);
+               shell_ungetc (peek_char);
+               if (peek_char == '(')
+                 {
+                   if (!delimiter_depth)
+                     dollar_paren_level++;
+                   else
+                     delimited_paren_level++;
+
+                   pass_next_character++;
+                   goto got_character;
+                 }
+               else if (peek_char == '[' && character == '$')
+                 {
+                   if (!delimiter_depth)
+                     dollar_bracket_level++;
+
+                   pass_next_character++;
+                   goto got_character;
+                 }
+               /* This handles ${...} constructs. */
+               else if (peek_char == '{' && character == '$')
+                 {
+                   if (!delimiter_depth)
+                     dollar_brace_level++;
+                   else
+                     delimited_brace_level++;
+
+                   pass_next_character++;
+                   goto got_character;
+                 }
+             }
+
+           /* If we are parsing a $() or $[] construct, we need to balance
+              parens and brackets inside the construct.  This whole function
+              could use a rewrite. */
+           if (character == '(' && !embedded_quoted_string)
+             {
+               if (delimiter_depth && delimited_paren_level)
+                 delimited_paren_level++;
+
+               if (!delimiter_depth && dollar_paren_level)
+                 dollar_paren_level++;
+             }
+
+           if (character == '[')
+             {
+               if (!delimiter_depth && dollar_bracket_level)
+                 dollar_bracket_level++;
+             }
+
+           if (character == '{' && !embedded_quoted_string)
+             {
+               if (delimiter_depth && delimited_brace_level)
+                 delimited_brace_level++;
+
+               if (!delimiter_depth && dollar_brace_level)
+                 dollar_brace_level++;
+             }
+
+           /* This code needs to take into account whether we are inside a
+              case statement pattern list, and whether this paren is supposed
+              to terminate it (hey, it could happen).  It's not as simple
+              as just using in_case_pattern_list, because we're not parsing
+              anything while we're reading a $( ) construct.  Maybe we
+              should move that whole mess into the yacc parser. */
+           if (character == ')' && !embedded_quoted_string)
+             {
+               if (delimiter_depth && delimited_paren_level)
+                 delimited_paren_level--;
+
+               if (!delimiter_depth && dollar_paren_level)
+                 {
+                   dollar_paren_level--;
+                   goto got_character;
+                 }
+             }
+
+           if (character == ']')
+             {
+               if (!delimiter_depth && dollar_bracket_level)
+                 {
+                   dollar_bracket_level--;
+                   goto got_character;
+                 }
+             }
+
+           if (character == '}' && !embedded_quoted_string)
+             {
+               if (delimiter_depth && delimited_brace_level)
+                 delimited_brace_level--;
+
+               if (!delimiter_depth && dollar_brace_level)
+                 {
+                   dollar_brace_level--;
+                   goto got_character;
+                 }
+             }
+         }
+
+       if (!dollar_paren_level && !dollar_bracket_level &&
+           !dollar_brace_level && !delimiter_depth &&
+           member (character, " \t\n;&()|<>"))
+         {
+           shell_ungetc (character);
+           goto got_token;
+         }
+    
+       if (!delimiter_depth)
+         {
+           if (character == '"' || character == '`' || character == '\'')
+             {
+               push_delimiter (character);
+
+               quoted = 1;
+               goto got_character;
+             }
+         }
+
+       if (all_digits)
+         all_digits = digit (character);
+       if (character == '$')
+         dollar_present = 1;
+
+      got_character:
+
+       if (character == CTLESC || character == CTLNUL)
+         token[token_index++] = CTLESC;
+
+       token[token_index++] = character;
+
+       if (token_index == (token_buffer_size - 1))
+         {
+           token_buffer_size += TOKEN_DEFAULT_GROW_SIZE;
+           token = xrealloc (token, token_buffer_size);
+         }
+       next_character:
+       if (character == '\n' && interactive && bash_input.type != st_string)
+         prompt_again ();
+
+       /* We want to remove quoted newlines (that is, a \<newline> pair)
+          unless we are within single quotes or pass_next_character is
+          set (the shell equivalent of literal-next). */
+       character = shell_getc
+         ((current_delimiter () != '\'') && (!pass_next_character));
+      }
+
+  got_token:
+
+    token[token_index] = '\0';
+       
+    if ((delimiter_depth || dollar_paren_level || dollar_bracket_level) &&
+       character == EOF)
+      {
+       char reporter = '\0';
+
+       if (!delimiter_depth)
+         {
+           if (dollar_paren_level)
+             reporter = ')';
+           else if (dollar_bracket_level)
+             reporter = ']';
+         }
+
+       if (!reporter)
+         reporter = current_delimiter ();
+
+       report_error ("unexpected EOF while looking for `%c'", reporter);
+       return (-1);
+      }
+
+    if (all_digits)
+      {
+       /* Check to see what thing we should return.  If the last_read_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 (character == '<' || character == '>' ||
+           last_read_token == LESS_AND || last_read_token == GREATER_AND)
+         {
+           yylval.number = atoi (token);
+           return (NUMBER);
+         }
+      }
+
+    /* Handle special case.  IN is recognized if the last token
+       was WORD and the token before that was FOR or CASE. */
+    if ((last_read_token == WORD) &&
+#if defined (SELECT_COMMAND)
+       ((token_before_that == FOR) || (token_before_that == CASE) || (token_before_that == SELECT)) &&
+#else
+       ((token_before_that == FOR) || (token_before_that == CASE)) &&
+#endif
+       (token[0] == 'i' && token[1] == 'n' && !token[2]))
+      {
+       if (token_before_that == CASE)
+         {
+           in_case_pattern_list = 1;
+           allow_esac_as_next++;
+         }
+       return (IN);
+      }
+
+    /* Ditto for DO in the FOR case. */
+#if defined (SELECT_COMMAND)
+    if ((last_read_token == WORD) && ((token_before_that == FOR) || (token_before_that == SELECT)) &&
+#else
+    if ((last_read_token == WORD) && (token_before_that == FOR) &&
+#endif
+       (token[0] == 'd' && token[1] == 'o' && !token[2]))
+      return (DO);
+
+    /* Ditto for ESAC in the CASE case. 
+       Specifically, this handles "case word in esac", which is a legal
+       construct, certainly because someone will pass an empty arg to the
+       case construct, and we don't want it to barf.  Of course, we should
+       insist that the case construct has at least one pattern in it, but
+       the designers disagree. */
+    if (allow_esac_as_next)
+      {
+       allow_esac_as_next--;
+       if (STREQ (token, "esac"))
+         {
+           in_case_pattern_list = 0;
+           return (ESAC);
+         }
+      }
+
+    /* Ditto for `{' in the FUNCTION case. */
+    if (allow_open_brace)
+      {
+       allow_open_brace = 0;
+       if (token[0] == '{' && !token[1])
+         {
+           open_brace_awaiting_satisfaction++;
+           return ('{');
+         }
+      }
+
+    if (posixly_correct)
+      CHECK_FOR_RESERVED_WORD (token);
+
+#if defined (ALIAS)
+    /* 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
+       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
+       token is not the same as the current or any previously
+       processed alias.
+
+       Special cases that disqualify:
+        In a pattern list in a case statement (in_case_pattern_list). */
+    if (interactive_shell && !quoted && !in_case_pattern_list &&
+       (expand_next_token || command_token_position (last_read_token)))
+      {
+       char *alias_expand_word (), *expanded;
+
+       if (expanded_token_stack && token_has_been_expanded (token))
+         goto no_expansion;
+
+       expanded = alias_expand_word (token);
+       if (expanded)
+         {
+           int len = strlen (expanded), expand_next;
+
+           /* Erase the current token. */
+           token_index = 0;
+
+           expand_next = (expanded[len - 1] == ' ') ||
+                         (expanded[len - 1] == '\t');
+
+           push_string (expanded, expand_next, token);
+           goto re_read_token;
+         }
+       else
+         /* This is an eligible token that does not have an expansion. */
+no_expansion:
+         expand_next_token = 0;
+      }
+    else
+      {
+       expand_next_token = 0;
+      }
+#endif /* ALIAS */
+
+    if (!posixly_correct)
+      CHECK_FOR_RESERVED_WORD (token);
+
+    /* What if we are attempting to satisfy an open-brace grouper? */
+    if (open_brace_awaiting_satisfaction && token[0] == '}' && !token[1])
+      {
+       open_brace_awaiting_satisfaction--;
+       return ('}');
+      }
+
+    the_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
+    the_word->word = xmalloc (1 + token_index);
+    strcpy (the_word->word, token);
+    the_word->dollar_present = dollar_present;
+    the_word->quoted = quoted;
+    the_word->assignment = assignment (token);
+
+    yylval.word = the_word;
+    result = WORD;
+
+    /* A word is an assignment if it appears at the beginning of a
+       simple command, or after another assignment word.  This is
+       context-dependent, so it cannot be handled in the grammar. */
+    if (assignment_acceptable (last_read_token) && the_word->assignment)
+      result = ASSIGNMENT_WORD;
+
+    if (last_read_token == FUNCTION)
+      allow_open_brace = 1;
+  }
+  return (result);
+}
+
+/* Return 1 if TOKEN is a token that after being read would allow
+   a reserved word to be seen, else 0. */
+static int
+reserved_word_acceptable (token)
+     int token;
+{
+#if 0
+  if (member (token, "\n;()|&{") ||
+#else
+  if (token == '\n' || token == ';' || token == '(' || token == ')' ||
+      token == '|' || token == '&' || token == '{' ||
+#endif
+      token == '}' ||                  /* XXX */
+      token == AND_AND ||
+      token == BANG ||
+      token == DO ||
+      token == ELIF ||
+      token == ELSE ||
+      token == FI ||
+      token == IF ||
+      token == OR_OR ||
+      token == SEMI_SEMI ||
+      token == THEN ||
+      token == UNTIL ||
+      token == WHILE ||
+      token == DONE ||         /* XXX these two are experimental */
+      token == ESAC ||
+      token == 0)
+    return (1);
+  else
+    return (0);
+}
+
+/* Return the index of TOKEN in the alist of reserved words, or -1 if
+   TOKEN is not a shell reserved word. */
+int
+find_reserved_word (token)
+     char *token;
+{
+  int i;
+  for (i = 0; word_token_alist[i].word != (char *)NULL; i++)
+    if (STREQ (token, word_token_alist[i].word))
+      return i;
+  return -1;
+}
+
+#if defined (READLINE)
+/* Called after each time readline is called.  This insures that whatever
+   the new prompt string is gets propagated to readline's local prompt
+   variable. */
+static void
+reset_readline_prompt ()
+{
+  if (prompt_string_pointer)
+    {
+      char *temp_prompt;
+
+      temp_prompt = *prompt_string_pointer
+                       ? decode_prompt_string (*prompt_string_pointer)
+                       : (char *)NULL;
+
+      if (temp_prompt == 0)
+       {
+         temp_prompt = xmalloc (1);
+         temp_prompt[0] = '\0';
+       }
+
+      FREE (current_readline_prompt);
+
+      current_readline_prompt = temp_prompt;
+    }
+}
+#endif /* READLINE */
+
+#if defined (HISTORY)
+/* A list of tokens which can be followed by newlines, but not by
+   semi-colons.  When concatenating multiple lines of history, the
+   newline separator for such tokens is replaced with a space. */
+static int no_semi_successors[] = {
+  '\n', '{', '(', ')', ';', '&', '|',
+  CASE, DO, ELSE, IF, IN, SEMI_SEMI, THEN, UNTIL, WHILE, AND_AND, OR_OR,
+  0
+};
+
+/* If we are not within a delimited expression, try to be smart
+   about which separators can be semi-colons and which must be
+   newlines. */
+char *
+history_delimiting_chars ()
+{
+  if (!delimiter_depth)
+    {
+      register int i;
+
+      for (i = 0; no_semi_successors[i]; i++)
+       {
+         if (token_before_that == no_semi_successors[i])
+           return (" ");
+       }
+      return ("; ");
+    }
+  else
+    return ("\n");
+}
+#endif /* HISTORY */
+
+/* Issue a prompt, or prepare to issue a prompt when the next character
+   is read. */
+static void
+prompt_again ()
+{
+  char *temp_prompt;
+
+  if (!interactive)    /* XXX */
+    return;
+
+  ps1_prompt = get_string_value ("PS1");
+  ps2_prompt = get_string_value ("PS2");
+
+  if (!prompt_string_pointer)
+    prompt_string_pointer = &ps1_prompt;
+
+  temp_prompt = (*prompt_string_pointer)
+                       ? decode_prompt_string (*prompt_string_pointer)
+                       : (char *)NULL;
+
+  if (temp_prompt == 0)
+    {
+      temp_prompt = xmalloc (1);
+      temp_prompt[0] = '\0';
+    }
+
+  current_prompt_string = *prompt_string_pointer;
+  prompt_string_pointer = &ps2_prompt;
+
+#if defined (READLINE)
+  if (!no_line_editing)
+    {
+      FREE (current_readline_prompt);
+      current_readline_prompt = temp_prompt;
+    }
+  else
+#endif /* READLINE */
+    {
+      FREE (current_decoded_prompt);
+      current_decoded_prompt = temp_prompt;
+    }
+}
+
+static void
+print_prompt ()
+{
+  fprintf (stderr, "%s", current_decoded_prompt);
+  fflush (stderr);
+}
+
+/* Return a string which will be printed as a prompt.  The string
+   may contain special characters which are decoded as follows:
+   
+       \t      the time
+       \d      the date
+       \n      CRLF
+       \s      the name of the shell
+       \w      the current working directory
+       \W      the last element of PWD
+       \u      your username
+       \h      the hostname
+       \#      the command number of this command
+       \!      the history number of this command
+       \$      a $ or a # if you are root
+       \<octal> character code in octal
+       \\      a backslash
+*/
+#define PROMPT_GROWTH 50
+char *
+decode_prompt_string (string)
+     char *string;
+{
+  int result_size = PROMPT_GROWTH;
+  int result_index = 0;
+  char *result;
+  int c;
+  char *temp = (char *)NULL;
+  WORD_LIST *list;
+
+#if defined (PROMPT_STRING_DECODE)
+
+  result = xmalloc (PROMPT_GROWTH);
+  result[0] = 0;
+
+  while (c = *string++)
+    {
+      if (posixly_correct && c == '!')
+       {
+         if (*string == '!')
+           {
+             temp = savestring ("!");
+             goto add_string;
+           }
+         else
+           {
+#if !defined (HISTORY)
+               temp = savestring ("1");
+#else /* HISTORY */
+               temp = itos (history_number ());
+#endif /* HISTORY */
+               string--;       /* add_string increments string again. */
+               goto add_string;
+           }
+       } 
+      if (c == '\\')
+       {
+         c = *string;
+
+         switch (c)
+           {
+           case '0':
+           case '1':
+           case '2':
+           case '3':
+           case '4':
+           case '5':
+           case '6':
+           case '7':
+             {
+               char octal_string[4];
+               int n;
+
+               strncpy (octal_string, string, 3);
+               octal_string[3] = '\0';
+
+               n = read_octal (octal_string);
+               temp = xmalloc (3);
+
+               if (n == CTLESC || n == CTLNUL)
+                 {
+                   string += 3;
+                   temp[0] = CTLESC;
+                   temp[1] = n;
+                   temp[2] = '\0';
+                 }
+               else if (n == -1)
+                 {
+                   temp[0] = '\\';
+                   temp[1] = '\0';
+                 }
+               else
+                 {
+                   string += 3;
+                   temp[0] = n;
+                   temp[1] = '\0';
+                 }
+
+               c = 0;
+               goto add_string;
+             }
+         
+           case 't':
+           case 'd':
+             /* Make the current time/date into a string. */
+             {
+               time_t the_time = time (0);
+               char *ttemp = ctime (&the_time);
+               temp = savestring (ttemp);
+
+               if (c == 't')
+                 {
+                   strcpy (temp, temp + 11);
+                   temp[8] = '\0';
+                 }
+               else
+                 temp[10] = '\0';
+
+               goto add_string;
+             }
+
+           case 'n':
+             if (!no_line_editing)
+               temp = savestring ("\r\n");
+             else
+               temp = savestring ("\n");
+             goto add_string;
+
+           case 's':
+             {
+               temp = base_pathname (shell_name);
+               temp = savestring (temp);
+               goto add_string;
+             }
+       
+           case 'w':
+           case 'W':
+             {
+               /* Use the value of PWD because it is much more effecient. */
+#define EFFICIENT
+#ifdef EFFICIENT
+               char *polite_directory_format (), t_string[MAXPATHLEN];
+
+               temp = get_string_value ("PWD");
+
+               if (!temp)
+                 getwd (t_string);
+               else
+                 strcpy (t_string, temp);
+#else
+               getwd (t_string);
+#endif /* EFFICIENT */
+
+               if (c == 'W')
+                 {
+                   char *dir = (char *)strrchr (t_string, '/');
+                   if (dir && dir != t_string)
+                     strcpy (t_string, dir + 1);
+                   temp = savestring (t_string);
+                 }
+               else
+                 temp = savestring (polite_directory_format (t_string));
+               goto add_string;
+             }
+      
+           case 'u':
+             {
+               temp = savestring (current_user.user_name);
+               goto add_string;
+             }
+
+           case 'h':
+             {
+               char *t_string;
+
+               temp = savestring (current_host_name);
+               if (t_string = (char *)strchr (temp, '.'))
+                 *t_string = '\0';
+               goto add_string;
+             }
+
+           case '#':
+             {
+               temp = itos (current_command_number);
+               goto add_string;
+             }
+
+           case '!':
+             {
+#if !defined (HISTORY)
+               temp = savestring ("1");
+#else /* HISTORY */
+               temp = itos (history_number ());
+#endif /* HISTORY */
+               goto add_string;
+             }
+
+           case '$':
+             temp = savestring (geteuid () == 0 ? "#" : "$");
+             goto add_string;
+
+#if defined (READLINE)
+           case '[':
+           case ']':
+             temp = xmalloc(3);
+             temp[0] = '\001';
+             temp[1] = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
+             temp[2] = '\0';
+             goto add_string;
+#endif
+
+           case '\\':
+             temp = savestring ("\\");
+             goto add_string;
+
+           default:
+             temp = savestring ("\\ ");
+             temp[1] = c;
+
+           add_string:
+             if (c)
+               string++;
+             result =
+               sub_append_string (temp, result, &result_index, &result_size);
+             temp = (char *)NULL; /* Free ()'ed in sub_append_string (). */
+             result[result_index] = '\0';
+             break;
+           }
+       }
+      else
+       {
+         while (3 + result_index > result_size)
+           result = xrealloc (result, result_size += PROMPT_GROWTH);
+
+         result[result_index++] = c;
+         result[result_index] = '\0';
+       }
+    }
+#else /* !PROMPT_STRING_DECODE */
+  result = savestring (string);
+#endif /* !PROMPT_STRING_DECODE */
+
+  /* Perform variable and parameter expansion and command substitution on
+     the prompt string. */
+  list = expand_string_unsplit (result, 1);
+  free (result);
+  result = string_list (list);
+  dispose_words (list);
+
+  return (result);
+}
+
+/* Report a syntax error, and restart the parser.  Call here for fatal
+   errors. */
+yyerror ()
+{
+  report_syntax_error ((char *)NULL);
+  reset_parser ();
+}
+
+/* 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
+   out an appropriate message for you. */
+static void
+report_syntax_error (message)
+     char *message;
+{
+  if (message)
+    {
+      if (!interactive)
+       {
+         char *name = bash_input.name ? bash_input.name : "stdin";
+         report_error ("%s: line %d: `%s'", name, line_number, message);
+       }
+      else
+       {
+         if (EOF_Reached)
+           EOF_Reached = 0;
+         report_error ("%s", message);
+       }
+
+      last_command_exit_value = EX_USAGE;
+      return;
+    }
+
+  if (shell_input_line && *shell_input_line)
+    {
+      char *t = shell_input_line;
+      register int i = shell_input_line_index;
+      int token_end = 0;
+
+      if (!t[i] && i)
+       i--;
+
+      while (i && (t[i] == ' ' || t[i] == '\t' || t[i] == '\n'))
+       i--;
+
+      if (i)
+       token_end = i + 1;
+
+      while (i && !member (t[i], " \n\t;|&"))
+       i--;
+
+      while (i != token_end && member (t[i], " \t\n"))
+       i++;
+
+      if (token_end)
+       {
+         char *error_token;
+         error_token = xmalloc (1 + (token_end - i));
+         strncpy (error_token, t + i, token_end - i);
+         error_token[token_end - i] = '\0';
+
+         report_error ("syntax error near unexpected token `%s'", error_token);
+         free (error_token);
+       }
+      else if ((i == 0) && (token_end == 0))   /* a 1-character token */
+       {
+         char etoken[2];
+         etoken[0] = t[i];
+         etoken[1] = '\0';
+
+         report_error ("syntax error near unexpected token `%s'", etoken);
+       }
+
+      if (!interactive)
+       {
+         char *temp = savestring (shell_input_line);
+         char *name = bash_input.name ? bash_input.name : "stdin";
+         int l = strlen (temp);
+
+         while (l && temp[l - 1] == '\n')
+           temp[--l] = '\0';
+
+         report_error ("%s: line %d: `%s'", name, line_number, temp);
+         free (temp);
+       }
+    }
+  else
+    {
+      char *name, *msg;
+      if (!interactive)
+       name = bash_input.name ? bash_input.name : "stdin";
+      if (EOF_Reached)
+       msg = "syntax error: unexpected end of file";
+      else
+       msg = "syntax error";
+      if (!interactive)
+       report_error ("%s: line %d: %s", name, line_number, msg);
+      else
+       {
+         /* This file uses EOF_Reached only for error reporting
+            when the shell is interactive.  Other mechanisms are 
+            used to decide whether or not to exit. */
+         EOF_Reached = 0;
+         report_error (msg);
+       }
+    }
+  last_command_exit_value = EX_USAGE;
+}
+
+/* ??? Needed function. ??? We have to be able to discard the constructs
+   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. */
+discard_parser_constructs (error_p)
+     int error_p;
+{
+}
+   
+/* Do that silly `type "bye" to exit' stuff.  You know, "ignoreeof". */
+
+/* A flag denoting whether or not ignoreeof is set. */
+int ignoreeof = 0;
+
+/* The number of times that we have encountered an EOF character without
+   another character intervening.  When this gets above the limit, the
+   shell terminates. */
+int eof_encountered = 0;
+
+/* The limit for eof_encountered. */
+int eof_encountered_limit = 10;
+
+/* If we have EOF as the only input unit, this user wants to leave
+   the shell.  If the shell is not interactive, then just leave.
+   Otherwise, if ignoreeof is set, and we haven't done this the
+   required number of times in a row, print a message. */
+static void
+handle_eof_input_unit ()
+{
+  if (interactive)
+    {
+      /* shell.c may use this to decide whether or not to write out the
+        history, among other things.  We use it only for error reporting
+        in this file. */
+      if (EOF_Reached)
+       EOF_Reached = 0;
+
+      /* If the user wants to "ignore" eof, then let her do so, kind of. */
+      if (ignoreeof)
+       {
+         if (eof_encountered < eof_encountered_limit)
+           {
+             fprintf (stderr, "Use \"%s\" to leave the shell.\n",
+                      login_shell ? "logout" : "exit");
+             eof_encountered++;
+             /* Reset the prompt string to be $PS1. */
+             prompt_string_pointer = (char **)NULL;
+             prompt_again ();
+             last_read_token = current_token = '\n';
+             return;
+           } 
+       }
+
+      /* In this case EOF should exit the shell.  Do it now. */
+      reset_parser ();
+      exit_builtin ((WORD_LIST *)NULL);
+    }
+  else
+    {
+      /* We don't write history files, etc., for non-interactive shells. */
+      EOF_Reached = 1;
+    }
+}
diff --git a/parser-built b/parser-built
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/parser.h b/parser.h
new file mode 100644 (file)
index 0000000..247d78e
--- /dev/null
+++ b/parser.h
@@ -0,0 +1,8 @@
+/* parser.h -- Everything you wanted to know about the parser, but were
+   afraid to ask. */
+
+#if !defined (_PARSER_H)
+#  define _PARSER_H
+#  include "command.h"
+#  include "input.h"
+#endif /* _PARSER_H */
diff --git a/portbash/README b/portbash/README
new file mode 100644 (file)
index 0000000..93a9348
--- /dev/null
@@ -0,0 +1 @@
+run sh mkdesc.sh for a first cut at a machines.h entry
diff --git a/portbash/libc.sh b/portbash/libc.sh
new file mode 100644 (file)
index 0000000..28429b3
--- /dev/null
@@ -0,0 +1,172 @@
+#! /bin/sh
+
+CC=cc
+export CC
+
+cat > x.c <<EOF
+extern char *alloca();
+
+main()
+{
+       char *s;
+       s = alloca(20);
+}
+EOF
+
+if ${CC} x.c > /dev/null 2>&1; then
+       :
+else
+       echo '#undef HAVE_ALLOCA'
+fi
+rm -f x.c x.o a.out
+
+cat > x.c << EOF
+#include <sys/types.h>
+#include <sys/param.h>
+extern char *getwd();
+main()
+{
+       getwd();
+}
+EOF
+
+if ${CC} x.c > /dev/null 2>&1; then
+       echo '#define HAVE_GETWD'
+else
+       echo '#undef HAVE_GETWD'
+       rm -f x.c x.o a.out
+
+       cat > x.c << EOF
+extern char *getcwd();
+
+main()
+{
+       getcwd();
+}
+EOF
+
+       if ${CC} x.c >/dev/null 2>&1; then
+               echo '#define HAVE_GETCWD'
+       fi
+fi
+rm -f a.out x.c x.o
+
+cat > x.c << EOF
+/*
+ * exit 0 if we have bcopy in libc and it works as in BSD
+ */
+
+extern int bcopy();
+
+char x[] = "12345";
+char y[] = "67890";
+
+main()
+{
+       bcopy(x, y, 5);
+       exit(strcmp(x, y));
+}
+EOF
+
+if ${CC} x.c > /dev/null 2>&1 && ./a.out ; then
+       BC='-DHAVE_BCOPY'
+fi
+
+rm -f x.c x.o a.out
+
+cat > x.c << EOF
+/*
+ * If this compiles, the system has uid_t and gid_t
+ */
+
+#include <sys/types.h>
+
+uid_t  u;
+gid_t  g;
+
+main()
+{
+       exit(0);
+}
+EOF
+
+if ${CC} x.c > /dev/null 2>&1; then
+       UIDT='-DHAVE_UID_T'
+fi
+
+rm -f x.c x.o a.out
+
+cat > x.c <<EOF
+#include <signal.h>
+
+extern char *sys_siglist[];
+
+main()
+{
+       char *x;
+
+       x = sys_siglist[3];
+       write(2, x, strlen(x));
+       exit(0);
+}
+EOF
+
+if ${CC} ./x.c >/dev/null 2>&1; then
+       echo '#define HAVE_SYS_SIGLIST'
+else
+
+       cat > x.c <<EOF
+#include <signal.h>
+
+extern char *_sys_siglist[];
+
+main()
+{
+       exit(0);
+}
+EOF
+
+       if ${CC} ./x.c >/dev/null 2>&1; then
+               echo '#define HAVE_SYS_SIGLIST'
+               SL='-Dsys_siglist=_sys_siglist'
+       fi
+fi
+
+PG=
+if ${CC} pgrp.c >/dev/null 2>&1; then
+       PG=`./a.out`
+fi
+
+if [ -f /unix ] && [ -f /usr/ccs/lib/libc.so ]; then
+       R4="-DUSGr4"
+fi
+
+touch not_a_directory
+if [ -f /usr/include/dirent.h ]; then
+       d='<dirent.h>'
+else
+       d='<sys/dir.h>'
+fi
+
+cat > x.c << EOF
+/*
+ * exit 0 if opendir does not check whether its argument is a directory
+ */
+
+#include $d
+DIR *dir;
+
+main()
+{
+       dir = opendir("not_a_directory");
+       exit (dir == 0);
+}
+EOF
+
+if ${CC} x.c > /dev/null 2>&1 && ./a.out ; then
+       OD='-DOPENDIR_NOT_ROBUST'
+fi
+
+rm -f x.c x.o a.out pgrp.o not_a_directory
+echo "#define SYSDEP_CFLAGS $BC $UIDT $SL $PG $R4 $OD"
+exit 0
diff --git a/portbash/mkdesc.sh b/portbash/mkdesc.sh
new file mode 100644 (file)
index 0000000..77e8232
--- /dev/null
@@ -0,0 +1,11 @@
+#! /bin/sh
+
+if [ -f /unix ]; then
+       echo '#define M_OS "USG"'
+fi
+
+sh signals.sh
+sh stdio.sh
+sh strings.sh
+sh syscalls.sh
+sh libc.sh
diff --git a/portbash/pgrp.c b/portbash/pgrp.c
new file mode 100644 (file)
index 0000000..5198dd6
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * If this system has a BSD-style getpgrp() call which takes a pid
+ * as an argument, output a -DBSD_GETPGRP.
+ */
+#include <stdio.h>
+#include <sys/types.h>
+
+int     pid;
+int     pg1, pg2, pg3, pg4;
+int     ng, np, s, child;
+
+main()
+{
+       pid = getpid();
+       pg1 = getpgrp(0);
+       pg2 = getpgrp();
+       pg3 = getpgrp(pid);
+       pg4 = getpgrp(1);
+
+       /*
+        * If all of these values are the same, it's pretty sure that
+        * we're on a system that ignores getpgrp's first argument.
+        */
+       if (pg2 == pg4 && pg1 == pg3 && pg2 == pg3)
+               exit(0);
+
+       child = fork();
+       if (child < 0)
+               exit(1);
+       else if (child == 0) {
+               np = getpid();
+               /*
+                * If this is Sys V, this will not work; pgrp will be
+                * set to np because setpgrp just changes a pgrp to be
+                * the same as the pid.
+                */
+               setpgrp(np, pg1);
+               ng = getpgrp(0);        /* Same result for Sys V and BSD */
+               if (ng == pg1) {
+                       printf("-DBSD_GETPGRP\n");
+                       exit(0);
+               } else
+                       exit(1);
+       } else {
+               wait(&s);
+               exit(s>>8);
+       }
+}
diff --git a/portbash/signals.sh b/portbash/signals.sh
new file mode 100644 (file)
index 0000000..bcdb5ff
--- /dev/null
@@ -0,0 +1,64 @@
+#! /bin/sh
+#
+CC=cc
+export CC
+
+cat > x.c <<EOF
+#include <signal.h>
+
+main()
+{
+}
+EOF
+
+${CC} -E x.c > x.i || { rm -f x.c x.i ; exit 1; }
+
+if egrep 'void.*signal' x.i >/dev/null 2>&1
+then
+       echo '#define VOID_SIGHANDLER'
+fi
+rm -f x.c x.i
+
+cat > x.c << EOF
+#include <signal.h>
+sigset_t set, oset;
+main()
+{
+       sigemptyset(&set);
+       sigemptyset(&oset);
+       sigaddset(&set, 2);
+       sigprocmask(SIG_BLOCK, &set, &oset);
+}
+EOF
+if ${CC} x.c >/dev/null 2>&1; then
+       echo '#define HAVE_POSIX_SIGNALS'
+else
+       cat > x.c << EOF
+#include <signal.h>
+main()
+{
+       long omask = sigblock(sigmask(2));
+       sigsetmask(omask);
+}
+EOF
+       if ${CC} x.c >/dev/null 2>&1; then
+               echo '#define HAVE_BSD_SIGNALS'
+       else
+               cat > x.c << EOF
+#include <signal.h>
+main()
+{
+       int n;
+       n = sighold(2);
+       sigrelse(2);
+}
+EOF
+               if ${CC} x.c >/dev/null 2>&1; then
+                       echo '#define HAVE_USG_SIGHOLD'
+               fi
+       fi
+fi
+
+rm -f x.c x.o a.out
+
+exit 0
diff --git a/portbash/stdio.sh b/portbash/stdio.sh
new file mode 100644 (file)
index 0000000..6a1be93
--- /dev/null
@@ -0,0 +1,87 @@
+#! /bin/sh
+#
+# test certain aspects of stdio
+CC=cc
+export CC
+
+cat > x.c << EOF
+#include <stdio.h>
+#include <varargs.h>
+
+xp(va_alist)
+va_dcl
+{
+       va_list args;
+       va_start (args);
+       vfprintf(stdout, "abcde", args);
+}
+
+main()
+{
+       xp();
+       exit(0);
+}
+EOF
+
+if ${CC} x.c >/dev/null 2>&1
+then
+       echo '#define HAVE_VFPRINTF'
+       rm -f x.c x.o a.out
+else
+
+       cat > x.c << EOF
+#include <stdio.h>
+
+main()
+{
+       _doprnt();
+}
+EOF
+
+       if ${CC} x.c >/dev/null 2>&1
+       then
+               echo '#define USE_VFPRINTF_EMULATION'
+               rm -f x.c x.o a.out
+       fi
+fi
+
+cat > x.c << EOF
+#include <stdio.h>
+main()
+{
+       setlinebuf(stdout);
+}
+EOF
+
+if ${CC} x.c > /dev/null 2>&1
+then
+       rm -f x.c x.o a.out
+       echo '#define HAVE_SETLINEBUF'
+else
+       # check for setvbuf
+       # If this compiles, the system has setvbuf.  If this segfaults while
+       # running, non-reversed systems get a seg violation
+
+       cat > x.c << EOF
+#include <stdio.h>
+
+main()
+{
+       setvbuf(stdout, _IOLBF, (char *)0, BUFSIZ);     /* reversed */
+       exit(0);                /* non-reversed systems segv */
+}
+EOF
+
+       if ${CC} x.c >/dev/null 2>&1 ; then
+               echo '#define HAVE_SETVBUF'
+               if a.out; then
+                       :
+               else
+                       rm -f core
+                       echo '#define REVERSED_SETVBUF_ARGS'
+               fi
+       fi
+fi
+
+rm -f x.c x.o a.out
+exit 0
diff --git a/portbash/strings.sh b/portbash/strings.sh
new file mode 100644 (file)
index 0000000..99a686a
--- /dev/null
@@ -0,0 +1,87 @@
+#! /bin/sh
+CC=cc
+export CC
+
+if [ -f /usr/include/string.h ]; then
+       STRINGH='<string.h>'
+elif [ -f /usr/include/strings.h ]; then
+       STRINGH='<strings.h>'
+else
+       exit 1
+fi
+
+cat > x.c << EOF
+#include $STRINGH
+
+#ifndef strchr
+extern char *strchr();
+#endif
+
+char *x = "12345";
+
+main()
+{
+       char    *s;
+
+       s = strchr(x, '2');
+       if (s)
+               exit(0);
+       exit(1);
+}
+EOF
+
+if ${CC} x.c >/dev/null 2>&1
+then
+       if ./a.out
+       then
+               echo '#define HAVE_STRCHR'
+       fi
+fi
+
+rm -f x.c x.o a.out
+
+cat > x.c << EOF
+extern char *strerror();
+
+main()
+{
+       char    *s;
+
+       s = strerror(2);
+       if (s)
+               exit(0);
+       exit(1);
+}
+EOF
+
+if ${CC} x.c >/dev/null 2>&1
+then
+       if ./a.out
+       then
+               echo '#define HAVE_STRERROR'
+       fi
+fi
+
+rm -f x.c x.o a.out
+
+
+cat > x.c << EOF
+
+main()
+{
+       if (strcasecmp("abc", "AbC") == 0)
+               exit(0);
+       exit(1);
+}
+EOF
+
+if ${CC} x.c >/dev/null 2>&1
+then
+       if ./a.out
+       then
+               echo '#define HAVE_STRCASECMP'
+       fi
+fi
+
+rm -f x.c x.o a.out
+exit 0
diff --git a/portbash/syscalls.sh b/portbash/syscalls.sh
new file mode 100644 (file)
index 0000000..e89a742
--- /dev/null
@@ -0,0 +1,80 @@
+#! /bin/sh
+CC=cc
+export CC
+
+cat > x.c << EOF
+/*
+ * exit 0 if we have the getgroups system or library call.
+ */
+
+main()
+{
+       int     g[100], ng;
+
+       ng = getgroups(100, g);
+       if (ng)
+               exit(0);
+       exit(1);
+}
+EOF
+if ${CC} x.c > /dev/null 2>&1 && ./a.out ; then
+       echo '#define HAVE_GETGROUPS'
+fi
+rm -f x.c x.o a.out
+
+cat > x.c << EOF
+extern int dup2();
+main()
+{
+       exit(dup2(1, 2) == -1);
+}
+EOF
+
+if ${CC} x.c > /dev/null 2>&1 && ./a.out ; then
+       echo '#define HAVE_DUP2'
+fi
+rm -f a.out x.c x.o
+
+cat > x.c << EOF
+extern int getpageesize();
+main()
+{
+       int n = getpagesize();
+}
+EOF
+
+if ${CC} x.c > /dev/null 2>&1
+then
+       echo '#define HAVE_GETPAGESIZE'
+fi
+rm -f a.out x.c x.o
+
+cat > x.c << EOF
+extern int getdtablesize();
+main()
+{
+       int n = getdtablesize();
+}
+EOF
+
+if ${CC} x.c > /dev/null 2>&1
+then
+       echo '#define HAVE_GETDTABLESIZE'
+fi
+rm -f a.out x.c x.o
+
+cat > x.c << EOF
+extern int setdtablesize();
+main()
+{
+       int n = setdtablesize(128);
+}
+EOF
+
+if ${CC} x.c > /dev/null 2>&1
+then
+       echo '#define HAVE_SETDTABLESIZE'
+fi
+rm -f a.out x.c x.o
+
+exit 0
diff --git a/posixstat.h b/posixstat.h
new file mode 100644 (file)
index 0000000..7d1cece
--- /dev/null
@@ -0,0 +1,149 @@
+/* posixstat.h -- Posix stat(2) definitions for systems that
+   don't have them. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This file should be included instead of <sys/stat.h>.
+   It relies on the local sys/stat.h to work though. */
+#if !defined (_POSIXSTAT_H)
+#define _POSIXSTAT_H
+
+#include <sys/stat.h>
+
+#if defined (isc386)
+#  if !defined (S_IFDIR)
+#    define S_IFDIR 0040000
+#  endif /* !S_IFDIR */
+#  if !defined (S_IFMT)
+#    define S_IFMT  0170000
+#  endif /* !S_IFMT */
+#endif /* isc386 */
+
+/* This text is taken directly from the Cadmus I was trying to
+   compile on:
+    the following MACROs are defined for X/OPEN compatibility
+    however, is the param correct ??
+   #define S_ISBLK(s) ((s.st_mode & S_IFMT) == S_IFBLK)
+
+  Well, the answer is no.  Thus... */
+#if defined (BrainDeath)
+#  undef S_ISBLK
+#  undef S_ISCHR
+#  undef S_ISDIR
+#  undef S_ISFIFO
+#  undef S_ISREG
+#endif /* BrainDeath */
+
+/* Posix 1003.1 5.6.1.1 <sys/stat.h> file types */
+
+/* Some Posix-wannabe systems define _S_IF* macros instead of S_IF*, but
+   do not provide the S_IS* macros that Posix requires. */
+
+#if defined (_S_IFMT) && !defined (S_IFMT)
+#define S_IFMT _S_IFMT
+#endif
+#if defined (_S_IFIFO) && !defined (S_IFIFO)
+#define S_IFIFO _S_IFIFO
+#endif
+#if defined (_S_IFCHR) && !defined (S_IFCHR)
+#define S_IFCHR _S_IFCHR
+#endif
+#if defined (_S_IFDIR) && !defined (S_IFDIR)
+#define S_IFDIR _S_IFDIR
+#endif
+#if defined (_S_IFBLK) && !defined (S_IFBLK)
+#define S_IFBLK _S_IFBLK
+#endif
+#if defined (_S_IFREG) && !defined (S_IFREG)
+#define S_IFREG _S_IFREG
+#endif
+#if defined (_S_IFLNK) && !defined (S_IFLNK)
+#define S_IFLNK _S_IFLNK
+#endif
+#if defined (_S_IFSOCK) && !defined (S_IFSOCK)
+#define S_IFSOCK _S_IFSOCK
+#endif
+
+/* Test for each symbol individually and define the ones necessary (some
+   systems claiming Posix compatibility define some but not all). */
+
+#if defined (S_IFBLK) && !defined (S_ISBLK)
+#define        S_ISBLK(m)      (((m)&S_IFMT) == S_IFBLK)       /* block device */
+#endif
+
+#if defined (S_IFCHR) && !defined (S_ISCHR)
+#define        S_ISCHR(m)      (((m)&S_IFMT) == S_IFCHR)       /* character device */
+#endif
+
+#if defined (S_IFDIR) && !defined (S_ISDIR)
+#define        S_ISDIR(m)      (((m)&S_IFMT) == S_IFDIR)       /* directory */
+#endif
+
+#if defined (S_IFREG) && !defined (S_ISREG)
+#define        S_ISREG(m)      (((m)&S_IFMT) == S_IFREG)       /* file */
+#endif
+
+#if defined (S_IFIFO) && !defined (S_ISFIFO)
+#define        S_ISFIFO(m)     (((m)&S_IFMT) == S_IFIFO)       /* fifo - named pipe */
+#endif
+
+#if defined (S_IFLNK) && !defined (S_ISLNK)
+#define        S_ISLNK(m)      (((m)&S_IFMT) == S_IFLNK)       /* symbolic link */
+#endif
+
+#if defined (S_IFSOCK) && !defined (S_ISSOCK)
+#define        S_ISSOCK(m)     (((m)&S_IFMT) == S_IFSOCK)      /* socket */
+#endif
+
+/*
+ * POSIX 1003.1 5.6.1.2 <sys/stat.h> File Modes
+ */
+#if !defined (S_IRWXU)
+#  if !defined (S_IREAD)
+#    define S_IREAD    00400
+#    define S_IWRITE   00200
+#    define S_IEXEC    00100
+#  endif /* S_IREAD */
+
+#  if !defined (S_IRUSR)
+#    define S_IRUSR    S_IREAD                 /* read, owner */
+#    define S_IWUSR    S_IWRITE                /* write, owner */
+#    define S_IXUSR    S_IEXEC                 /* execute, owner */
+
+#    define S_IRGRP    (S_IREAD  >> 3)         /* read, group */
+#    define S_IWGRP    (S_IWRITE >> 3)         /* write, group */
+#    define S_IXGRP    (S_IEXEC  >> 3)         /* execute, group */
+
+#    define S_IROTH    (S_IREAD  >> 6)         /* read, other */
+#    define S_IWOTH    (S_IWRITE >> 6)         /* write, other */
+#    define S_IXOTH    (S_IEXEC  >> 6)         /* execute, other */
+#  endif /* !S_IRUSR */
+
+#  define S_IRWXU      (S_IRUSR | S_IWUSR | S_IXUSR)
+#  define S_IRWXG      (S_IRGRP | S_IWGRP | S_IXGRP)
+#  define S_IRWXO      (S_IROTH | S_IWOTH | S_IXOTH)
+#endif /* !S_IRWXU */
+
+/* These are non-standard, but are used in builtins.c$symbolic_umask() */
+#define S_IRUGO                (S_IRUSR | S_IRGRP | S_IROTH)
+#define S_IWUGO                (S_IWUSR | S_IWGRP | S_IWOTH)
+#define S_IXUGO                (S_IXUSR | S_IXGRP | S_IXOTH)
+
+#endif /* _POSIXSTAT_H */
diff --git a/print_cmd.c b/print_cmd.c
new file mode 100644 (file)
index 0000000..b70e8d4
--- /dev/null
@@ -0,0 +1,827 @@
+/* print_command -- A way to make readable commands from a command tree. */
+/* Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#if defined (HAVE_VARARGS_H)
+#  include <varargs.h>
+#endif
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "shell.h"
+#include "y.tab.h"
+#include "stdc.h"
+#include "builtins/common.h"
+
+#if defined (__GNUC__) || defined (ardent)
+extern int printf __P((const char *, ...));    /* Yuck.  Double yuck. */
+#endif
+
+static int indentation = 0;
+static int indentation_amount = 4;
+
+static void cprintf (), newline (), indent (), the_printed_command_resize ();
+static void semicolon ();
+
+static void make_command_string_internal ();
+static void command_print_word_list ();
+static void print_case_clauses ();
+static void print_redirection_list ();
+static void print_redirection ();
+
+static void print_for_command ();
+#if defined (SELECT_COMMAND)
+static void print_select_command ();
+#endif
+static void print_group_command ();
+static void print_case_command ();
+static void print_while_command ();
+static void print_until_command ();
+static void print_until_or_while ();
+static void print_if_command ();
+static void print_function_def ();
+
+#define PRINTED_COMMAND_GROW_SIZE 1024
+
+char *the_printed_command = (char *)NULL;
+int the_printed_command_size = 0;
+int command_string_index = 0;
+
+/* Non-zero means the stuff being printed is inside of a function def. */
+static int inside_function_def = 0;
+static int skip_this_indent = 0;
+
+/* The depth of the group commands that we are currently printing.  This
+   includes the group command that is a function body. */
+static int group_command_nesting = 0;
+
+/* Print COMMAND (a command tree) on standard output. */
+void
+print_command (command)
+     COMMAND *command;
+{
+  command_string_index = 0;
+  printf ("%s", make_command_string (command));
+}
+
+/* Make a string which is the printed representation of the command
+   tree in COMMAND.  We return this string.  However, the string is
+   not consed, so you have to do that yourself if you want it to
+   remain around. */
+char *
+make_command_string (command)
+     COMMAND *command;
+{
+  command_string_index = 0;
+  make_command_string_internal (command);
+  return (the_printed_command);
+}
+
+/* The internal function.  This is the real workhorse. */
+static void
+make_command_string_internal (command)
+     COMMAND *command;
+{
+  if (!command)
+    cprintf ("");
+  else
+    {
+      if (skip_this_indent)
+       skip_this_indent--;
+      else
+       indent (indentation);
+
+      if (command->flags & CMD_WANT_SUBSHELL)
+       cprintf ("( ");
+
+      if (command->flags & CMD_INVERT_RETURN)
+       cprintf ("! ");
+
+      switch (command->type)
+       {
+       case cm_for:
+         print_for_command (command->value.For);
+         break;
+
+#if defined (SELECT_COMMAND)
+       case cm_select:
+         print_select_command (command->value.Select);
+         break;
+#endif
+
+       case cm_case:
+         print_case_command (command->value.Case);
+         break;
+
+       case cm_while:
+         print_while_command (command->value.While);
+         break;
+
+       case cm_until:
+         print_until_command (command->value.While);
+         break;
+
+       case cm_if:
+         print_if_command (command->value.If);
+         break;
+
+       case cm_simple:
+         print_simple_command (command->value.Simple);
+         break;
+
+       case cm_connection: 
+
+         skip_this_indent++;
+         make_command_string_internal (command->value.Connection->first);
+
+         switch (command->value.Connection->connector)
+           {
+           case '&':
+           case '|':
+             {
+               char c = command->value.Connection->connector;
+               cprintf (" %c", c);
+               if (c != '&' || command->value.Connection->second)
+                 {
+                   cprintf (" ");
+                   skip_this_indent++;
+                 }
+             }
+             break;
+
+           case AND_AND:
+             cprintf (" && ");
+             if (command->value.Connection->second)
+               skip_this_indent++;
+             break;
+
+           case OR_OR:
+             cprintf (" || ");
+             if (command->value.Connection->second)
+               skip_this_indent++;
+             break;
+       
+           case ';':
+             cprintf (";");
+
+             if (inside_function_def)
+               cprintf ("\n");
+             else
+               {
+                 cprintf (" ");
+                 if (command->value.Connection->second)
+                   skip_this_indent++;
+               }
+             break;
+
+           default:
+             cprintf ("print_command: bad connector `%d'",
+                      command->value.Connection->connector);
+             break;
+           }
+
+         make_command_string_internal (command->value.Connection->second);
+         break;
+      
+       case cm_function_def:
+         print_function_def (command->value.Function_def);
+         break;
+
+       case cm_group:
+         print_group_command (command->value.Group);
+         break;
+
+       default:
+         programming_error ("print_command: bad command type `%d'", command->type);
+         break;
+       }
+
+      if (command->flags & CMD_WANT_SUBSHELL)
+       cprintf (" )");
+
+      if (command->redirects)
+       print_redirection_list (command->redirects);
+    }
+}
+
+static void
+_print_word_list (list, separator, pfunc)
+     WORD_LIST *list;
+     char *separator;
+     VFunction *pfunc;
+{
+  while (list)
+    {
+      (*pfunc) ("%s", list->word->word);
+      list = list->next;
+      if (list)
+       (*pfunc) ("%s", separator);
+    }
+}
+
+void print_word_list (list, separator)
+     WORD_LIST *list;
+     char *separator;
+{
+  _print_word_list (list, separator, (VFunction *)printf);
+}
+
+static void
+command_print_word_list (list, separator)
+     WORD_LIST *list;
+     char *separator;
+{
+  _print_word_list (list, separator, cprintf);
+}
+
+static void
+print_for_command (for_command)
+     FOR_COM *for_command;
+{
+  cprintf ("for %s in ", for_command->name->word);
+  command_print_word_list (for_command->map_list, " ");
+  cprintf (";");
+  newline ("do\n");
+  indentation += indentation_amount;
+  make_command_string_internal (for_command->action);
+  semicolon ();
+  indentation -= indentation_amount;
+  newline ("done");
+}
+
+#if defined (SELECT_COMMAND)
+static void
+print_select_command (select_command)
+     SELECT_COM *select_command;
+{
+  cprintf ("select %s in ", select_command->name->word);
+  command_print_word_list (select_command->map_list, " ");
+  cprintf (";");
+  newline ("do\n");
+  indentation += indentation_amount;
+  make_command_string_internal (select_command->action);
+  semicolon ();
+  indentation -= indentation_amount;
+  newline ("done");
+}
+#endif /* SELECT_COMMAND */
+
+static void
+print_group_command (group_command)
+     GROUP_COM *group_command;
+{
+  group_command_nesting++;
+  cprintf ("{ ");
+
+  if (!inside_function_def)
+    skip_this_indent++;
+  else
+    {
+      /* This is a group command { ... } inside of a function
+        definition, and should be handled as a `normal' group
+        command, using the current indentation. */
+      cprintf ("\n");
+      indentation += indentation_amount;
+    }
+
+  make_command_string_internal (group_command->command);
+
+  cprintf ("\n");
+
+  if (group_command_nesting)
+    {
+      indentation -= indentation_amount;
+      indent (indentation);
+      if (!indentation)
+       cprintf (" ");
+    }
+      
+  cprintf ("}");
+  group_command_nesting--;
+}
+
+static void
+print_case_command (case_command)
+     CASE_COM *case_command;
+{
+  cprintf ("case %s in ", case_command->word->word);
+  if (case_command->clauses)
+    print_case_clauses (case_command->clauses);
+  newline ("esac");
+}
+
+static void
+print_case_clauses (clauses)
+     PATTERN_LIST *clauses;
+{
+  indentation += indentation_amount;
+  while (clauses)
+    {
+      newline ("");
+      command_print_word_list (clauses->patterns, " | ");
+      cprintf (")\n");
+      indentation += indentation_amount;
+      make_command_string_internal (clauses->action);
+      indentation -= indentation_amount;
+      newline (";;");
+      clauses = clauses->next;
+    }
+  indentation -= indentation_amount;
+}
+
+static void
+print_while_command (while_command)
+     WHILE_COM *while_command;
+{
+  print_until_or_while (while_command, "while");
+}
+
+static void
+print_until_command (while_command)
+     WHILE_COM *while_command;
+{
+  print_until_or_while (while_command, "until");
+}
+
+static void
+print_until_or_while (while_command, which)
+     WHILE_COM *while_command;
+     char *which;
+{
+  cprintf ("%s ", which);
+  skip_this_indent++;
+  make_command_string_internal (while_command->test);
+  semicolon ();
+  cprintf (" do\n");   /* was newline ("do\n"); */
+  indentation += indentation_amount;
+  make_command_string_internal (while_command->action);
+  indentation -= indentation_amount;
+  semicolon ();
+  newline ("done");
+}
+
+static void
+print_if_command (if_command)
+     IF_COM *if_command;
+{
+  cprintf ("if ");
+  skip_this_indent++;
+  make_command_string_internal (if_command->test);
+  semicolon ();
+  cprintf (" then\n");
+  indentation += indentation_amount;
+  make_command_string_internal (if_command->true_case);
+  indentation -= indentation_amount;
+
+  if (if_command->false_case)
+    {
+      semicolon ();
+      newline ("else\n");
+      indentation += indentation_amount;
+      make_command_string_internal (if_command->false_case);
+      indentation -= indentation_amount;
+    }
+  semicolon ();
+  newline ("fi");
+}
+
+void
+print_simple_command (simple_command)
+     SIMPLE_COM *simple_command;
+{
+  command_print_word_list (simple_command->words, " ");
+
+  if (simple_command->redirects)
+    {
+      cprintf (" ");
+      print_redirection_list (simple_command->redirects);
+    }
+}
+
+static void
+print_redirection_list (redirects)
+     REDIRECT *redirects;
+{
+  while (redirects)
+    {
+      print_redirection (redirects);
+      redirects = redirects->next;
+      if (redirects)
+       cprintf (" ");
+    }
+}
+
+static void
+print_redirection (redirect)
+     REDIRECT *redirect;
+{
+  int kill_leading = 0;
+  int redirector = redirect->redirector;
+  WORD_DESC *redirectee = redirect->redirectee.filename;
+  int redir_fd = redirect->redirectee.dest;
+
+  switch (redirect->instruction)
+    {
+    case r_output_direction:
+      if (redirector != 1)
+       cprintf ("%d", redirector);
+      cprintf (">%s", redirectee->word);
+      break;
+
+    case r_input_direction:
+      if (redirector != 0)
+       cprintf ("%d", redirector);
+      cprintf ("<%s", redirectee->word);
+      break;
+
+    case r_inputa_direction:   /* Redirection created by the shell. */
+      cprintf ("&");
+      break;
+
+    case r_appending_to:
+      if (redirector != 1)
+       cprintf ("%d", redirector);
+      cprintf (">>%s", redirectee->word);
+      break;
+
+    case r_deblank_reading_until:
+      kill_leading++;
+      /* ... */
+    case r_reading_until:
+      if (redirector != 0)
+       cprintf ("%d", redirector);
+      /* If the here document delimiter is quoted, single-quote it. */
+      if (redirect->redirectee.filename->quoted)
+        {
+          char *x;
+          x = single_quote (redirect->here_doc_eof);
+         cprintf ("<<%s%s\n", kill_leading? "-" : "", x);
+          free (x);
+        }
+      else
+       cprintf ("<<%s%s\n", kill_leading? "-" : "", redirect->here_doc_eof);
+      cprintf ("%s%s",
+              redirect->redirectee.filename->word, redirect->here_doc_eof);
+      break;
+
+    case r_duplicating_input:
+      cprintf ("%d<&%d", redirector, redir_fd);
+      break;
+
+    case r_duplicating_output:
+      cprintf ("%d>&%d", redirector, redir_fd);
+      break;
+
+    case r_duplicating_input_word:
+      cprintf ("%d<&%s", redirector, redirectee->word);
+      break;
+
+    case r_duplicating_output_word:
+      cprintf ("%d>&%s", redirector, redirectee->word);
+      break;
+
+    case r_close_this:
+      cprintf ("%d>&-", redirector);
+      break;
+
+    case r_err_and_out:
+      cprintf (">&%s", redirectee->word);
+      break;
+
+    case r_input_output:
+      if (redirector != 1)
+       cprintf ("%d", redirector);
+      cprintf ("<>%s", redirectee->word);
+      break;
+
+    case r_output_force:
+      if (redirector != 1)
+       cprintf ("%d", redirector);
+      cprintf (">|%s", redirectee->word);
+      break;
+    }
+}
+
+static void
+reset_locals ()
+{
+  inside_function_def = 0;
+  indentation = 0;
+}
+
+static void
+print_function_def (func)
+     FUNCTION_DEF *func;
+{
+  cprintf ("function %s () \n", func->name->word);
+  add_unwind_protect (reset_locals, 0);
+
+  indent (indentation);
+  cprintf ("{ \n");
+
+  inside_function_def++;
+  indentation += indentation_amount;
+
+  if (func->command->type == cm_group)
+    make_command_string_internal (func->command->value.Group->command);
+  else
+    make_command_string_internal (func->command);
+    
+  remove_unwind_protect ();
+  indentation -= indentation_amount;
+  inside_function_def--;
+
+  newline ("}");
+}
+
+/* Return the string representation of the named function.
+   NAME is the name of the function.
+   COMMAND is the function body.  It should be a GROUP_COM.
+   MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
+  */
+char *
+named_function_string (name, command, multi_line)
+     char *name;
+     COMMAND *command;
+     int multi_line;
+{
+  char *result;
+  int old_indent = indentation, old_amount = indentation_amount;
+
+  command_string_index = 0;
+
+  if (name && *name)
+    cprintf ("%s ", name);
+
+  cprintf ("() ");
+
+  if (!multi_line)
+    {
+      indentation = 1;
+      indentation_amount = 0;
+    }
+  else
+    {
+      cprintf ("\n");
+      indentation += indentation_amount;
+    }
+
+  inside_function_def++;
+
+  if (multi_line)
+    cprintf ("{ \n");
+  else
+    cprintf ("{ ");
+
+  if (command->type == cm_group)
+    make_command_string_internal (command->value.Group->command);
+  else
+    make_command_string_internal (command);
+
+  indentation = old_indent;
+  indentation_amount = old_amount;
+  inside_function_def--;
+
+  newline ("}");
+
+  result = the_printed_command;
+
+  if (!multi_line)
+    {
+#if 0
+      register int i;
+      for (i = 0; result[i]; i++)
+       if (result[i] == '\n')
+         {
+           strcpy (result + i, result + i + 1);
+           --i;
+         }
+#else
+      if (result[2] == '\n')   /* XXX -- experimental */
+        strcpy (result + 2, result + 3);
+#endif
+    }
+
+  return (result);
+}
+
+static void
+newline (string)
+     char *string;
+{
+  cprintf ("\n");
+  indent (indentation);
+  if (string && *string)
+    cprintf ("%s", string);
+}
+
+static void
+indent (amount)
+     int amount;
+{
+  while (amount-- > 0)
+    cprintf (" ");
+}
+
+static void
+semicolon ()
+{
+  if (command_string_index > 0 && the_printed_command[command_string_index - 1] == '&')
+    return;
+  cprintf (";");
+}
+
+#if !defined (HAVE_VARARGS_H)
+/* How to make the string. */
+static void
+cprintf (format, arg1, arg2)
+     char *format, *arg1, *arg2;
+{
+  register char *s;
+  char char_arg[2], *argp, *args[2];
+  int arg_len, c, arg_index;
+
+  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)
+       {
+         argp = s;
+         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':
+             argp = itos (pointer_to_int (args[arg_index]));
+             arg_index++;
+             arg_len = strlen (argp);
+             free_argp = 1;
+             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
+cprintf (va_alist)
+     va_dcl
+{
+  register char *s;
+  char *control, char_arg[2], *argp;
+  int digit_arg, arg_len, c;
+  va_list args;
+
+  va_start (args);
+  control = va_arg (args, char *);
+
+  arg_len = strlen (control);
+  the_printed_command_resize (arg_len + 1);
+
+  char_arg[1] = '\0';
+  s = control;
+  while (s && *s)
+    {
+      int free_argp = 0;
+      c = *s++;
+      if (c != '%' || !*s)
+       {
+         argp = s - 1;
+         arg_len = 1;
+       }
+      else
+       {
+         c = *s++;
+         switch (c)
+           {
+           case '%':
+             char_arg[0] = c;
+             argp = char_arg;
+             arg_len = 1;
+             break;
+
+           case 's':
+             argp = va_arg (args, char *);
+             arg_len = strlen (argp);
+             break;
+
+           case 'd':
+             digit_arg = va_arg (args, int);
+             argp = itos (digit_arg);
+             arg_len = strlen (argp);
+             free_argp = 1;
+             break;
+
+           case 'c':
+             char_arg[0] = va_arg (args, int);
+             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';
+}
+#endif /* HAVE_VARARGS_H */
+
+/* Ensure that there is enough space to stuff LENGTH characters into
+   THE_PRINTED_COMMAND. */
+static void
+the_printed_command_resize (length)
+     int length;
+{
+  if (!the_printed_command)
+    {
+      the_printed_command_size = length + 1;
+      the_printed_command = xmalloc (the_printed_command_size);
+      command_string_index = 0;
+    }
+  else if ((command_string_index + length) >= the_printed_command_size)
+    {
+      int new;
+      new = command_string_index + length + 1;
+      new = new + 2 * PRINTED_COMMAND_GROW_SIZE - 1;
+      new -= new % PRINTED_COMMAND_GROW_SIZE;
+      the_printed_command_size = new;
+      the_printed_command = xrealloc (the_printed_command, the_printed_command_size);
+    }
+}
diff --git a/quit.h b/quit.h
new file mode 100644 (file)
index 0000000..57de7a0
--- /dev/null
+++ b/quit.h
@@ -0,0 +1,33 @@
+/* quit.h -- How to handle SIGINT gracefully. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (__QUIT_H__)
+#define __QUIT_H__
+
+/* Non-zero means SIGINT has already ocurred. */
+extern int interrupt_state;
+
+extern void throw_to_top_level ();
+
+/* Macro to call a great deal.  SIGINT just sets above variable.  When
+   it is safe, put QUIT in the code, and the "interrupt" will take place. */
+#define QUIT if (interrupt_state) throw_to_top_level ()
+
+#endif /* __QUIT_H__ */
diff --git a/sh b/sh
new file mode 120000 (symlink)
index 0000000..5d4150d
--- /dev/null
+++ b/sh
@@ -0,0 +1 @@
+/bin/bash
\ No newline at end of file
diff --git a/shell.c b/shell.c
new file mode 100644 (file)
index 0000000..26b20c0
--- /dev/null
+++ b/shell.c
@@ -0,0 +1,1792 @@
+/* shell.c -- GNU's idea of the POSIX shell specification.
+
+   This file is part of Bash, the Bourne Again SHell.  Bash is free
+   software; no one can prevent you from reading the source code, or
+   giving it to someone else.  This file is copyrighted under the GNU
+   General Public License, which can be found in the file called
+   COPYING.
+
+   Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY.  No author or distributor accepts responsibility to
+   anyone for the consequences of using it or for whether it serves
+   any particular purpose or works at all, unless he says so in
+   writing.  Refer to the GNU Emacs General Public License for full
+   details.
+
+   Everyone is granted permission to copy, modify and redistribute
+   Bash, but only under the conditions described in the GNU General
+   Public License.  A copy of this license is supposed to have been
+   given to you along with GNU Emacs so you can know your rights and
+   responsibilities.  It should be in a file named COPYING.
+
+   Among other things, the copyright notice and this notice must be
+   preserved on all copies.
+
+  Birthdate:
+  Sunday, January 10th, 1988.
+  Initial author: Brian Fox
+*/
+#define INSTALL_DEBUG_MODE
+
+#include "bashtypes.h"
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/file.h>
+#include "filecntl.h"
+#include <pwd.h>
+#include "posixstat.h"
+#include "bashansi.h"
+
+#if defined (HAVE_VARARGS_H)
+#include <varargs.h>
+#endif
+
+#include "shell.h"
+#include "flags.h"
+
+#if defined (JOB_CONTROL)
+#include "jobs.h"
+#endif /* JOB_CONTROL */
+
+#include "input.h"
+#include "execute_cmd.h"
+
+#if defined (HISTORY)
+#  include "bashhist.h"
+#  include <readline/history.h>
+#endif
+
+#include <tilde/tilde.h>
+
+#if defined (USG) && !defined (HAVE_GETPW_DECLS)
+extern struct passwd *getpwuid ();
+#endif /* USG && !HAVE_GETPW_DECLS */
+
+extern int yydebug;
+#if !defined (errno)
+extern int errno;
+#endif
+
+extern char *dist_version;
+extern int patch_level, build_version;
+extern int subshell_environment; /* Found in execute_cmd.c. */
+extern int last_command_exit_value;
+extern int return_catch_flag;
+extern jmp_buf return_catch;
+extern int need_here_doc, current_command_line_count, line_number;
+extern char *ps1_prompt, **prompt_string_pointer;
+extern int loop_level, continuing, breaking;
+extern int parse_and_execute_level;
+extern char *this_command_name;
+
+/* Non-zero means that this shell has already been run; i.e. you should
+   call shell_reinitialize () if you need to start afresh. */
+static int shell_initialized = 0;
+static int sourced_env = 0;
+
+/* The current maintainer of the shell.  You change this in the
+   Makefile. */
+#if !defined (MAINTAINER)
+#define MAINTAINER "bash-maintainers@prep.ai.mit.edu"
+#endif
+
+char *the_current_maintainer = MAINTAINER;
+
+char *primary_prompt = PPROMPT;
+char *secondary_prompt = SPROMPT;
+
+COMMAND *global_command = (COMMAND *)NULL;
+
+/* Non-zero after SIGINT. */
+int interrupt_state = 0;
+
+/* Information about the current user. */
+struct user_info current_user =
+{
+  -1, -1, -1, -1, (char *)NULL, (char *)NULL, (char *)NULL
+};
+
+/* The current host's name. */
+char *current_host_name = (char *)NULL;
+
+/* Non-zero means that this shell is a login shell.
+   Specifically:
+   0 = not login shell.
+   1 = login shell from getty (or equivalent fake out)
+  -1 = login shell from "-login" flag.
+  -2 = both from getty, and from flag.
+ */
+int login_shell = 0;
+
+/* Non-zero means that at this moment, the shell is interactive.  In
+   general, this means that the shell is at this moment reading input
+   from the keyboard. */
+int interactive = 0;
+
+/* Non-zero means that the shell was started as an interactive shell. */
+int interactive_shell = 0;
+
+/* Tells what state the shell was in when it started:
+       0 = non-interactive shell script
+       1 = interactive
+       2 = -c command
+   This is a superset of the information provided by interactive_shell.
+*/
+int startup_state = 0;
+
+/* Special debugging helper. */
+int debugging_login_shell = 0;
+
+/* The environment that the shell passes to other commands. */
+char **shell_environment;
+
+/* Non-zero when we are executing a top-level command. */
+int executing = 0;
+
+/* The number of commands executed so far. */
+int current_command_number = 1;
+
+/* The environment at the top-level REP loop.  We use this in the case of
+   error return. */
+jmp_buf top_level, catch;
+
+#if defined (JOB_CONTROL) || defined (_POSIX_VERSION)
+/* The signal masks that this shell runs with. */
+sigset_t top_level_mask;
+#endif /* JOB_CONTROL */
+
+/* Non-zero is the recursion depth for commands. */
+int indirection_level = 0;
+
+/* The number of times BASH has been executed.  This is set
+   by initialize_variables () in variables.c. */
+int shell_level = 0;
+
+/* The name of this shell, as taken from argv[0]. */
+char *shell_name = (char *)NULL;
+
+/* time in seconds when the shell was started */
+time_t shell_start_time;
+
+/* The name of the .(shell)rc file. */
+static char *bashrc_file = "~/.bashrc";
+
+/* Non-zero means to act more like the Bourne shell on startup. */
+static int act_like_sh = 0;
+
+/* Values for the long-winded argument names. */
+static int debugging = 0;              /* Do debugging things. */
+static int no_rc = 0;                  /* Don't execute ~/.bashrc */
+static int no_profile = 0;             /* Don't execute .profile */
+static int do_version = 0;             /* Display interesting version info. */
+static int quiet = 0;                  /* Be quiet when starting up. */
+static int make_login_shell = 0;       /* Make this shell be a `-bash' shell. */
+
+int no_line_editing = 0;       /* Don't do fancy line editing. */
+int no_brace_expansion = 0;    /* Non-zero means no foo{a,b} -> fooa foob. */
+
+int posixly_correct = 0;       /* Non-zero means posix.2 superset. */
+
+/* Some long-winded argument names.  These are obviously new. */
+#define Int 1
+#define Charp 2
+struct {
+  char *name;
+  int type;
+  int *int_value;
+  char **char_value;
+} long_args[] = {
+  { "debug", Int, &debugging, (char **)0x0 },
+  { "norc", Int, &no_rc, (char **)0x0 },
+  { "noprofile", Int, &no_profile, (char **)0x0 },
+  { "rcfile", Charp, (int *)0x0, &bashrc_file },
+  { "version", Int, &do_version, (char **)0x0 },
+  { "quiet", Int, &quiet, (char **)0x0 },
+  { "login", Int, &make_login_shell, (char **)0x0 },
+  { "nolineediting", Int, &no_line_editing, (char **)0x0 },
+  { "nobraceexpansion", Int, &no_brace_expansion, (char **)0x0 },
+  { "posix", Int, &posixly_correct, (char **)0x0 },
+  { (char *)0x0, Int, (int *)0x0, (char **)0x0 }
+};
+
+/* These are extern so execute_simple_command can set them, and then
+   longjmp back to main to execute a shell script, instead of calling
+   main () again and resulting in indefinite, possibly fatal, stack
+   growth. */
+jmp_buf subshell_top_level;
+int subshell_argc;
+char **subshell_argv;
+char **subshell_envp;
+
+#if defined (BUFFERED_INPUT)
+/* The file descriptor from which the shell is reading input. */
+int default_buffered_input = -1;
+#endif
+
+static int want_pending_command;
+static char *local_pending_command;
+
+static int isnetconn ();
+static void run_startup_files ();
+
+static void shell_initialize ();
+static void shell_reinitialize ();
+static void initialize_signals ();
+static void initialize_terminating_signals ();
+
+main (argc, argv, env)
+     int argc;
+     char **argv, **env;
+{
+  register int i;
+  int arg_index, locally_skip_execution;
+  int top_level_arg_index, read_from_stdin;
+  FILE *default_input;
+
+  /* There is a bug in the NeXT 2.1 rlogind that causes opens
+     of /dev/tty to fail. */
+#if defined (RLOGIN_PGRP_BUG)
+  {
+    int tty_fd;
+
+    tty_fd = open ("/dev/tty", O_RDWR);
+
+    if (tty_fd < 0)
+      {
+       char *tty;
+       tty = (char *)ttyname (fileno (stdin));
+       tty_fd = open (tty, O_RDWR);
+      }
+    close (tty_fd);
+  }
+#endif /* RLOGIN_PGRP_BUG */
+
+  /* Wait forever if we are debugging a login shell. */
+  while (debugging_login_shell);
+
+  current_user.uid = getuid ();
+  current_user.gid = getgid ();
+  current_user.euid = geteuid ();
+  current_user.egid = getegid ();
+
+  /* See whether or not we are running setuid or setgid. */
+  privileged_mode = (current_user.uid != current_user.euid) ||
+                   (current_user.gid != current_user.egid);
+
+  posixly_correct = (getenv ("POSIXLY_CORRECT") != (char *)NULL) ||
+                   (getenv ("POSIX_PEDANTIC") != (char *)NULL);
+
+#if defined (USE_GNU_MALLOC_LIBRARY)
+  mcheck (programming_error, (void (*) ())0);
+#endif /* USE_GNU_MALLOC_LIBRARY */
+
+  if (setjmp (subshell_top_level))
+    {
+      argc = subshell_argc;
+      argv = subshell_argv;
+      env = subshell_envp;
+      sourced_env = 0;
+    }
+
+  /* Initialize local variables for all `invocations' of main (). */
+  arg_index = 1;
+  local_pending_command = (char *)NULL;
+  want_pending_command = 0;
+  locally_skip_execution = 0;
+  read_from_stdin = 0;
+  default_input = stdin;
+#if defined (BUFFERED_INPUT)
+  default_buffered_input = -1;
+#endif
+
+  /* Fix for the `infinite process creation' bug when running shell scripts
+     from startup files on System V. */
+  login_shell = make_login_shell = 0;
+
+  /* If this shell has already been run, then reinitialize it to a
+     vanilla state. */
+  if (shell_initialized || shell_name)
+    {
+      /* Make sure that we do not infinitely recurse as a login shell. */
+      if (*shell_name == '-')
+       shell_name++;
+
+      shell_reinitialize ();
+      if (setjmp (top_level))
+       exit (2);
+    }
+
+  /* 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. */
+  /* XXX - next version - make this be the same as -posix. */
+  shell_name = base_pathname (argv[0]);
+  if (*shell_name == '-')
+    shell_name++;
+  if (shell_name[0] == 's' && shell_name[1] == 'h' && !shell_name[2])
+    act_like_sh++;
+
+  yydebug = 0;
+
+  shell_environment = env;
+  shell_name = argv[0];
+  dollar_vars[0] = savestring (shell_name);
+
+  if (*shell_name == '-')
+    {
+      shell_name++;
+      login_shell++;
+    }
+
+#if defined (JOB_CONTROL)
+  if (act_like_sh)
+    job_control = 0;           /* XXX - not posix */
+#endif /* JOB_CONTROL */
+
+  shell_start_time = NOW;      /* NOW now defined in general.h */
+
+  /* A program may start an interactive shell with
+         "execl ("/bin/bash", "-", NULL)".
+     If so, default the name of this shell to our name. */
+  if (!shell_name || !*shell_name || (shell_name[0] == '-' && !shell_name[1]))
+    shell_name = "bash";
+
+  /* Parse argument flags from the input line. */
+
+  /* Find full word arguments first. */
+  while ((arg_index != argc) && *(argv[arg_index]) == '-')
+    {
+      for (i = 0; long_args[i].name; i++)
+       {
+         if (STREQ (&(argv[arg_index][1]), long_args[i].name))
+           {
+             if (long_args[i].type == Int)
+               *long_args[i].int_value = 1;
+             else
+               {
+                 if (!argv[++arg_index])
+                   {
+                     report_error ("option `%s' expected an argument",
+                                   long_args[i].name);
+                     exit (1);
+                   }
+                 else
+                   *long_args[i].char_value = argv[arg_index];
+               }
+             goto handle_next_arg;
+           }
+       }
+      break;                   /* No such argument.  Maybe flag arg. */
+    handle_next_arg:
+      arg_index++;
+    }
+
+  /* If we're in a strict Posix.2 mode, turn on interactive comments. */
+  if (posixly_correct)
+    interactive_comments = 1;
+
+  /* If user supplied the "-login" flag, then set and invert LOGIN_SHELL. */
+  if (make_login_shell)
+    {
+      login_shell++;
+      login_shell = -login_shell;
+    }
+
+  /* All done with full word options; do standard shell option parsing.*/
+  this_command_name = shell_name;      /* for error reporting */
+  while (arg_index != argc && argv[arg_index] &&
+        (*argv[arg_index] == '-' || *argv[arg_index] == '+'))
+    {
+      /* There are flag arguments, so parse them. */
+      int arg_character, on_or_off, next_arg;
+      char *o_option, *arg_string;
+
+      i = 1;
+      next_arg = arg_index + 1;
+      arg_string = argv[arg_index];
+      on_or_off = arg_string[0];
+
+      /* A single `-' signals the end of options.  From the 4.3 BSD sh.
+        An option `--' means the same thing; this is the standard
+        getopt(3) meaning. */
+      if (arg_string[0] == '-' &&
+          (arg_string[1] == '\0' ||
+            (arg_string[1] == '-' && arg_string[2] == '\0')))
+       {
+         arg_index++;
+         break;
+       }
+
+      while (arg_character = arg_string[i++])
+       {
+         switch (arg_character)
+           {
+           case 'c':
+               want_pending_command = 1;
+               break;
+
+           case 's':
+               read_from_stdin = 1;
+               break;
+
+           case 'o':
+               o_option = argv[next_arg];
+               if (!o_option)
+                 {
+                   list_minus_o_opts ();
+                   break;
+                 }
+               if (set_minus_o_option (on_or_off, o_option) != EXECUTION_SUCCESS)
+                 exit (1);
+               next_arg++;
+               break;
+
+           default:
+             if (change_flag (arg_character, on_or_off) == FLAG_ERROR)
+               {
+                 report_error ("%c%c: bad option", on_or_off, arg_character);
+                 exit (1);
+               }
+
+           }
+       }
+      /* Can't do just a simple increment anymore -- what about
+        "bash -abouo emacs ignoreeof -hP"? */
+      arg_index = next_arg;
+    }
+
+  /* Need to get the argument to a -c option processed in the
+     above loop.  The next arg is a command to execute, and the
+     following args are $0...$n respectively. */
+  if (want_pending_command)
+    {
+      local_pending_command = argv[arg_index];
+      if (!local_pending_command)
+       {
+         report_error ("`-c' requires an argument");
+         exit (1);
+       }
+      arg_index++;
+    }
+  this_command_name = (char *)NULL;      
+
+  /* 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:
+       no -c command
+       no arguments remaining or the -s flag given
+       standard input is a terminal
+       standard output is a terminal
+     Refer to Posix.2, the description of the `sh' utility. */
+
+  if (forced_interactive ||            /* -i flag */
+      (!local_pending_command &&       /* No -c command and ... */
+       ((arg_index == argc) ||         /*   no remaining args or... */
+       read_from_stdin) &&             /*   -s flag with args, and */
+       isatty (fileno (stdin)) &&      /* Input is a terminal and */
+       isatty (fileno (stdout))))      /* output is a terminal. */
+    {
+      interactive_shell = startup_state = interactive = 1;
+    }
+  else
+    {
+#if defined (HISTORY)
+#  if defined (BANG_HISTORY)
+      history_expansion = 0;
+#  endif
+      remember_on_history = 0;
+#endif /* HISTORY */
+      interactive_shell = startup_state = interactive = 0;
+      no_line_editing = 1;
+#if defined (JOB_CONTROL)
+      job_control = 0;
+#endif /* JOB_CONTROL */
+    }
+
+#define CLOSE_FDS_AT_LOGIN
+#if defined (CLOSE_FDS_AT_LOGIN)
+  /*
+   * Some systems have the bad habit of starting login shells with lots of open
+   * file descriptors.  For instance, most systems that have picked up the
+   * pre-4.0 Sun YP code leave a file descriptor open each time you call one
+   * of the getpw* functions, and it's set to be open across execs.  That
+   * means one for login, one for xterm, one for shelltool, etc.
+   */
+  if (login_shell && interactive_shell)
+    {
+      for (i = 3; i < 20; i++)
+       close (i);
+    }
+#endif /* CLOSE_FDS_AT_LOGIN */
+
+  /* From here on in, the shell must be a normal functioning shell.
+     Variables from the environment are expected to be set, etc. */
+  shell_initialize ();
+
+  if (interactive_shell)
+    {
+      char *term = getenv ("TERM");
+      no_line_editing |= term && (STREQ (term, "emacs"));
+    }
+
+  top_level_arg_index = arg_index;
+
+  if (!quiet && do_version)
+    show_shell_version ();
+
+  /* Give this shell a place to longjmp to before executing the
+     startup files.  This allows users to press C-c to abort the
+     lengthy startup. */
+  {
+    int code;
+
+    code = setjmp (top_level);
+
+    if (code)
+      {
+       if (code == EXITPROG)
+         goto exit_shell;
+       else
+         locally_skip_execution++;
+      }
+  }
+
+  arg_index = top_level_arg_index;
+
+  /* Execute the start-up scripts. */
+
+  if (!interactive_shell)
+    {
+      makunbound ("PS1", shell_variables);
+      makunbound ("PS2", shell_variables);
+      interactive = 0;
+    }
+  else
+    {
+      change_flag ('i', FLAG_ON);
+      interactive = 1;
+    }
+
+  if (!locally_skip_execution)
+    run_startup_files ();
+
+#if defined (RESTRICTED_SHELL)
+      /* I turn on the restrictions afterwards because it is explictly
+        stated in the POSIX spec that PATH cannot be set in a restricted
+        shell, except in .profile. */
+    maybe_make_restricted (shell_name);
+#endif /* RESTRICTED_SHELL */
+
+    if (local_pending_command)
+      {
+       /* Bind remaining args to $0 ... $n */
+       WORD_LIST *args = (WORD_LIST *)NULL;
+       while (arg_index != argc)
+         args = make_word_list (make_word (argv[arg_index++]), args);
+       if (args)
+         {
+           args = REVERSE_LIST (args, WORD_LIST *);
+           /* Posix.2 4.56.3 says that the first argument after
+              sh -c command becomes $0, and the rest of the arguments
+              are bound to $1 ... $N. */
+           shell_name = savestring (args->word->word); /* XXX */
+           dollar_vars[0] = savestring (args->word->word);
+           remember_args (args->next, 1);
+           dispose_words (args);
+         }
+
+       startup_state = 2;
+#if defined (ONESHOT)
+       run_one_command (local_pending_command);
+       goto exit_shell;
+#else /* ONESHOT */
+       with_input_from_string (local_pending_command, "-c");
+       goto read_and_execute;
+#endif /* !ONESHOT */
+      }
+
+  /* Do the things that should be done only for interactive shells. */
+  if (interactive_shell)
+    {
+      /* Set up for checking for presence of mail. */
+      remember_mail_dates ();
+      reset_mail_timer ();
+
+#if defined (HISTORY)
+      /* Initialize the interactive history stuff. */
+      if (!shell_initialized)
+       load_history ();
+#endif /* HISTORY */
+
+      /* Initialize terminal state for interactive shells after the
+        .bash_profile and .bashrc are interpreted. */
+      get_tty_state ();
+    }
+
+  /* Get possible input filename. */
+  if ((arg_index != argc) && !read_from_stdin)
+    {
+      int fd;
+      char *filename;
+
+      free (dollar_vars[0]);
+      dollar_vars[0] = savestring (argv[arg_index]);
+      filename = savestring (argv[arg_index]);
+
+      fd = open (filename, O_RDONLY);
+      if ((fd < 0) && (errno == ENOENT) && (absolute_program (filename) == 0))
+       {
+         char *path_filename;
+         /* If it's not in the current directory, try looking through PATH
+            for it. */
+         path_filename = find_path_file (argv[arg_index]);
+         if (path_filename)
+           {
+             free (filename);
+             filename = path_filename;
+             fd = open (filename, O_RDONLY);
+           }
+       }
+
+      arg_index++;
+      if (fd < 0)
+       {
+         file_error (filename);
+         exit (1);
+       }
+
+      /* Only do this with file descriptors we can seek on. */
+      if (lseek (fd, 0L, 1) != -1)
+       {
+         unsigned char sample[80];
+         int sample_len;
+
+         /* Check to see if the `file' in `bash file' is a binary file
+            according to the same tests done by execute_simple_command (),
+            and report an error and exit if it is. */
+         sample_len = read (fd, sample, sizeof (sample));
+         if (sample_len > 0 && (check_binary_file (sample, sample_len)))
+           {
+             report_error ("%s: cannot execute binary file", filename);
+             exit (EX_BINARY_FILE);
+           }
+         /* Now rewind the file back to the beginning. */
+         lseek (fd, 0L, 0);
+       }
+
+#if defined (BUFFERED_INPUT)
+      default_buffered_input = fd;
+      if (default_buffered_input == -1)
+       {
+         file_error (filename);
+         exit (127);
+       }
+      SET_CLOSE_ON_EXEC (default_buffered_input);
+
+#else /* !BUFFERED_INPUT */
+
+      /* Open the script.  But try to move the file descriptor to a randomly
+        large one, in the hopes that any descriptors used by the script will
+        not match with ours. */
+      {
+       int script_fd, nfds;
+
+       nfds = getdtablesize ();
+       if (nfds <= 0)
+         nfds = 20;
+       if (nfds > 256)
+         nfds = 256;
+       script_fd = dup2 (fd, nfds - 1);
+       if (script_fd)
+         {
+           close (fd);
+           fd = script_fd;
+         }
+      }
+
+      default_input = fdopen (fd, "r");
+
+      if (!default_input)
+       {
+         file_error (filename);
+         exit (127);
+       }
+
+      SET_CLOSE_ON_EXEC (fd);
+      if (fileno (default_input) != fd)
+       SET_CLOSE_ON_EXEC (fileno (default_input));
+
+#endif /* !BUFFERED_INPUT */
+
+      if (!interactive_shell || (!isatty (fd)))
+       {
+#if defined (HISTORY)
+#  if defined (BANG_HISTORY)
+         history_expansion = 0;
+#  endif
+         remember_on_history = 0;
+#endif /* HISTORY */
+         interactive = interactive_shell = 0;
+         no_line_editing = 1;
+#if defined (JOB_CONTROL)
+         set_job_control (0);
+#endif /* JOB_CONTROL */
+       }
+      else
+       {
+         /* I don't believe that this code is ever executed, even in
+            the presence of /dev/fd. */
+         dup2 (fd, 0);
+         close (fd);
+         fclose (default_input);
+       }
+    }
+  else if (!interactive)
+    /* In this mode, bash is reading a script from stdin, which is a
+       pipe or redirected file. */
+#if defined (BUFFERED_INPUT)
+    default_buffered_input = fileno (stdin);   /* == 0 */
+#else      
+    setbuf (default_input, (char *)NULL);
+#endif /* !BUFFERED_INPUT */
+
+  /* Bind remaining args to $1 ... $n */
+  {
+    WORD_LIST *args = (WORD_LIST *)NULL;
+    while (arg_index != argc)
+      args = make_word_list (make_word (argv[arg_index++]), args);
+    args = REVERSE_LIST (args, WORD_LIST *);
+    remember_args (args, 1);
+    dispose_words (args);
+  }
+
+#if defined (BUFFERED_INPUT)
+  if (!interactive)
+    unset_nodelay_mode (default_buffered_input);
+  else
+    unset_nodelay_mode (fileno (stdin));
+#else
+  unset_nodelay_mode (fileno (stdin));
+#endif /* !BUFFERED_INPUT */
+
+  /* with_input_from_stdin really means `with_input_from_readline' */
+  if (interactive && !no_line_editing)
+    with_input_from_stdin ();
+  else
+#if defined (BUFFERED_INPUT)
+    {
+      if (!interactive)
+       with_input_from_buffered_stream (default_buffered_input, dollar_vars[0]);
+      else
+       with_input_from_stream (default_input, dollar_vars[0]);
+    }
+#else /* !BUFFERED_INPUT */
+    with_input_from_stream (default_input, dollar_vars[0]);
+#endif /* !BUFFERED_INPUT */
+
+#if !defined (ONESHOT)
+ read_and_execute:
+#endif /* !ONESHOT */
+
+  shell_initialized = 1;
+
+  /* Read commands until exit condition. */
+  reader_loop ();
+
+  exit_shell:
+  /* Do trap[0] if defined. */
+  if (signal_is_trapped (0))
+    last_command_exit_value = run_exit_trap ();
+
+#if defined (PROCESS_SUBSTITUTION)
+  unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+
+#if defined (HISTORY)
+  if (interactive_shell)
+    maybe_save_shell_history ();
+#endif /* HISTORY */
+
+#if defined (JOB_CONTROL)
+  /* If this shell is interactive, terminate all stopped jobs and
+     restore the original terminal process group. */
+  end_job_control ();
+#endif /* JOB_CONTROL */
+
+  /* Always return the exit status of the last command to our parent. */
+  exit (last_command_exit_value);
+}
+
+#if !defined (SYS_PROFILE)
+#  define SYS_PROFILE "/etc/profile"
+#endif /* !SYS_PROFILE */
+
+/* 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
+   names exists, that file is sourced.  The Posix.2 rules are in effect
+   for both interactive and non-interactive shells (section 4.56.5.3) */
+static void
+run_startup_files ()
+{
+  if (!posixly_correct)
+    {
+      if (login_shell)
+       {
+         /* We don't execute .bashrc for login shells. */
+          no_rc++;
+         if (no_profile == 0)
+           maybe_execute_file (SYS_PROFILE, 1);
+        }
+
+      if (login_shell && !no_profile)
+        {
+          if (act_like_sh)
+            maybe_execute_file ("~/.profile", 1);
+          else
+            {
+              if (maybe_execute_file ("~/.bash_profile", 1) == 0)
+               if (maybe_execute_file ("~/.bash_login", 1) == 0)
+                 maybe_execute_file ("~/.profile", 1);
+            }
+        }
+
+      /* Execute ~/.bashrc for most shells.  Never execute it if
+         ACT_LIKE_SH is set, or if NO_RC is set.
+
+         If the executable file "/usr/gnu/src/bash/foo" contains:
+
+           #!/usr/gnu/bin/bash
+           echo hello
+
+         then:
+
+         COMMAND           EXECUTE BASHRC
+         --------------------------------
+         bash -c foo           NO
+         bash foo              NO
+         foo                   NO
+         rsh machine ls                YES (for rsh, which calls `bash -c')
+         rsh machine foo       YES (for shell started by rsh) NO (for foo!)
+         echo ls | bash                NO
+         login                 NO
+         bash                  YES
+      */
+      if (!act_like_sh && !no_rc &&
+          (interactive_shell || (isnetconn (fileno (stdin)) &&
+                                local_pending_command)))
+        maybe_execute_file (bashrc_file, 1);
+    }
+
+   /* Try a TMB suggestion.  If running a script, then execute the
+      file mentioned in the ENV variable. */
+   if (!privileged_mode && sourced_env++ == 0 && act_like_sh == 0 &&
+       (posixly_correct || !interactive_shell))
+    {
+      char *env_file = (char *)NULL;
+
+      if (!posixly_correct)
+       env_file = getenv ("BASH_ENV");
+      if (!env_file)
+       env_file = getenv ("ENV");
+
+      if (env_file && *env_file)
+       {
+         WORD_LIST *list;
+         char *expanded_file_name;
+
+         list = expand_string_unsplit (env_file, 1);
+         if (list)
+           {
+             expanded_file_name = string_list (list);
+             dispose_words (list);
+
+             if (expanded_file_name && *expanded_file_name)
+               maybe_execute_file (expanded_file_name, 1);
+
+             if (expanded_file_name)
+               free (expanded_file_name);
+           }
+       }
+    }
+}
+
+#if defined (RESTRICTED_SHELL)
+/* Perhaps make this shell a `restricted' one, based on NAME.
+   If the basename of NAME is "rbash", then this shell is restricted.
+   In a restricted shell, PATH and SHELL are read-only and non-unsettable.
+   Do this also if `restricted' is already set to 1; maybe the shell was
+   started with -r. */
+maybe_make_restricted (name)
+     char *name;
+{
+  char *temp;
+
+  temp = base_pathname (shell_name);
+  if (restricted || (STREQ (temp, "rbash")))
+    {
+      set_var_read_only ("PATH");
+      non_unsettable ("PATH");
+      set_var_read_only ("SHELL");
+      non_unsettable ("SHELL");
+      restricted++;
+    }
+}
+#endif /* RESTRICTED_SHELL */
+
+/* Try to execute the contents of FNAME.  If FNAME doesn't exist,
+   that is not an error, but other kinds of errors are.  A non-zero
+   FORCE_NONINTERACTIVE means to set the value of `interactive' to
+   0 so things like job control are disabled; the value is unchanged
+   otherwise.  Returns -1 in the case of an error, 0 in the case that
+   the file was not found, and 1 if the file was found and executed. */
+maybe_execute_file (fname, force_noninteractive)
+     char *fname;
+     int force_noninteractive;
+{
+  jmp_buf old_return_catch;
+  int return_val, fd, tresult, old_interactive;
+  char *filename, *string;
+  struct stat file_info;
+
+  filename = tilde_expand (fname);
+  fd = open (filename, O_RDONLY);
+
+  if (fd < 0)
+    {
+file_error_and_exit:
+      if (errno != ENOENT)
+       file_error (filename);
+      free (filename);
+      return ((errno == ENOENT) ? 0 : -1);
+    }
+
+  if (fstat (fd, &file_info) == -1)
+    goto file_error_and_exit;
+
+  if (S_ISDIR (file_info.st_mode))
+    {
+      internal_error ("%s: cannot execute directories", filename);
+      free (filename);
+      return -1;
+    }
+
+  string = (char *)xmalloc (1 + (int)file_info.st_size);
+  tresult = read (fd, string, file_info.st_size);
+
+  {
+    int tt = errno;
+    close (fd);
+    errno = tt;
+  }
+
+  if (tresult != file_info.st_size)
+    {
+      free (string);
+      goto file_error_and_exit;
+    }
+  string[file_info.st_size] = '\0';
+
+  return_catch_flag++;
+  xbcopy ((char *)return_catch, (char *)old_return_catch, sizeof (jmp_buf));
+
+  if (force_noninteractive)
+    {
+      old_interactive = interactive;
+      interactive = 0;
+    }
+
+  return_val = setjmp (return_catch);
+
+  /* If `return' was seen outside of a function, but in the script, then
+     force parse_and_execute () to clean up. */
+  if (return_val)
+    parse_and_execute_cleanup ();
+  else
+    tresult = parse_and_execute (string, filename, -1);
+
+  if (force_noninteractive)
+    interactive = old_interactive;
+
+  return_catch_flag--;
+  xbcopy ((char *)old_return_catch, (char *)return_catch, sizeof (jmp_buf));
+
+  free (filename);
+
+  return (1);
+}
+
+#if defined (ONESHOT)
+/* Run one command, given as the argument to the -c option.  Tell
+   parse_and_execute not to fork for a simple command. */
+run_one_command (command)
+     char *command;
+{
+  int code;
+
+  code = setjmp (top_level);
+
+  if (code != NOT_JUMPED)
+    {
+#if defined (PROCESS_SUBSTITUTION)
+      unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+      switch (code)
+       {
+         /* Some kind of throw to top_level has occured. */
+       case FORCE_EOF:
+         return last_command_exit_value = 127;
+       case EXITPROG:
+         return last_command_exit_value;
+       case DISCARD:
+         return last_command_exit_value = 1;
+       default:
+         programming_error ("Bad jump %d", code);
+       }
+    }
+   return (parse_and_execute (savestring (command), "-c", -1));
+}
+#endif /* ONESHOT */
+
+reader_loop ()
+{
+  int our_indirection_level;
+  COMMAND *current_command = (COMMAND *)NULL;
+
+  our_indirection_level = ++indirection_level;
+
+  while (!EOF_Reached)
+    {
+      int code;
+
+      code = setjmp (top_level);
+
+#if defined (PROCESS_SUBSTITUTION)
+      unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+
+      if (interactive_shell && signal_is_ignored (SIGINT) == 0)
+       set_signal_handler (SIGINT, sigint_sighandler);
+
+      if (code != NOT_JUMPED)
+       {
+         indirection_level = our_indirection_level;
+
+         switch (code)
+           {
+             /* Some kind of throw to top_level has occured. */
+           case FORCE_EOF:
+           case EXITPROG:
+             current_command = (COMMAND *)NULL;
+             EOF_Reached = EOF;
+             goto exec_done;
+
+           case DISCARD:
+             /* Obstack free command elements, etc. */
+             if (current_command)
+               {
+                 dispose_command (current_command);
+                 current_command = (COMMAND *)NULL;
+               }
+             last_command_exit_value = 1;
+             break;
+
+           default:
+             programming_error ("Bad jump %d", code);
+           }
+       }
+
+      executing = 0;
+      dispose_used_env_vars ();
+
+#if (defined (Ultrix) && defined (mips)) || !defined (HAVE_ALLOCA)
+      /* Attempt to reclaim memory allocated with alloca (). */
+      (void) alloca (0);
+#endif
+
+      if (read_command () == 0)
+       {
+         if (global_command)
+           {
+             current_command = global_command;
+
+             current_command_number++;
+
+             /* POSIX spec: "-n: The shell reads commands but does
+                not execute them; this can be used to check for shell
+                script syntax errors.  The shell ignores the -n option
+                for interactive shells. " */
+             if (interactive_shell || !read_but_dont_execute)
+               {
+                 executing = 1;
+                 execute_command (current_command);
+               }
+
+           exec_done:
+             if (current_command)
+               {
+                 dispose_command (current_command);
+                 current_command = (COMMAND *)NULL;
+               }
+             QUIT;
+           }
+       }
+      else
+       {
+         /* Parse error, maybe discard rest of stream if not interactive. */
+         if (!interactive)
+           EOF_Reached = EOF;
+       }
+      if (just_one_command)
+       EOF_Reached = EOF;
+    }
+  indirection_level--;
+}
+
+/* Return a string denoting what our indirection level is. */
+static char indirection_string[100];
+
+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);
+    
+  ps4 = decode_prompt_string (ps4);
+
+  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);
+}
+
+static sighandler 
+alrm_catcher(i)
+     int i;
+{
+  printf ("%ctimed out waiting for input: auto-logout\n", '\07');
+  longjmp (top_level, EXITPROG);
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* !VOID_SIGHANDLER */
+}
+
+parse_command ()
+{
+  int r;
+
+  need_here_doc = 0;
+  run_pending_traps ();
+
+  /* Allow the execution of a random command just before the printing
+     of each primary prompt.  If the shell variable PROMPT_COMMAND
+     is set then the value of it is the command to execute. */
+  if (interactive && bash_input.type != st_string)
+    {
+      char *command_to_execute;
+
+      command_to_execute = get_string_value ("PROMPT_COMMAND");
+      if (command_to_execute)
+       execute_prompt_command (command_to_execute);
+    }
+
+  current_command_line_count = 0;
+  r = yyparse ();
+
+  if (need_here_doc)
+    gather_here_documents ();
+
+  return (r);
+}
+
+read_command ()
+{
+  SHELL_VAR *tmout_var = (SHELL_VAR *)NULL;
+  int tmout_len = 0, result;
+  SigHandler *old_alrm = (SigHandler *)NULL;
+
+  prompt_string_pointer = &ps1_prompt;
+  global_command = (COMMAND *)NULL;
+
+  /* Only do timeouts if interactive. */
+  if (interactive)
+    {
+      tmout_var = find_variable ("TMOUT");
+
+      if (tmout_var && tmout_var->value)
+       {
+         tmout_len = atoi (tmout_var->value);
+         if (tmout_len > 0)
+           {
+             old_alrm = set_signal_handler (SIGALRM, alrm_catcher);
+             alarm (tmout_len);
+           }
+       }
+    }
+
+  QUIT;
+
+  current_command_line_count = 0;
+  result = parse_command ();
+
+  if (interactive && tmout_var && (tmout_len > 0))
+    {
+      alarm(0);
+      set_signal_handler (SIGALRM, old_alrm);
+    }
+  return (result);
+}
+
+/* Cause STREAM to buffer lines as opposed to characters or blocks. */
+static void
+line_buffer_stream (stream)
+     FILE *stream;
+{
+  /* If your machine doesn't have either of setlinebuf or setvbuf,
+     you can just comment out the buffering commands, and the shell
+     will still work.  It will take more cycles, though. */
+#if defined (HAVE_SETLINEBUF)
+  setlinebuf (stream);
+#else
+#  if defined (_IOLBF)
+#    if defined (REVERSED_SETVBUF_ARGS)
+  setvbuf (stream, _IOLBF, (char *)NULL, BUFSIZ);
+#    else /* !REVERSED_SETVBUF_ARGS */
+  setvbuf (stream, (char *)NULL, _IOLBF, BUFSIZ);
+#    endif /* !REVERSED_SETVBUF_ARGS */
+#  endif /* _IOLBF */
+#endif /* !HAVE_SETLINEBUF */
+}
+
+/* Do whatever is necessary to initialize the shell.
+   Put new initializations in here. */
+static void
+shell_initialize ()
+{
+  /* Line buffer output for stderr and stdout. */
+  line_buffer_stream (stderr);
+  line_buffer_stream (stdout);
+
+  /* Sort the array of shell builtins so that the binary search in
+     find_shell_builtin () works correctly. */
+  initialize_shell_builtins ();
+
+  /* Initialize the trap signal handlers before installing our own
+     signal handlers.  traps.c:restore_original_signals () is responsible
+     for restoring the original default signal handlers.  That function
+     is called when we make a new child. */
+  initialize_traps ();
+  initialize_signals ();
+
+  /* Initialize current_user.name and current_host_name. */
+  {
+    struct passwd *entry = getpwuid (current_user.uid);
+    char hostname[256];
+
+    if (gethostname (hostname, 255) < 0)
+      current_host_name = "??host??";
+    else
+      current_host_name = savestring (hostname);
+
+    if (entry)
+      {
+       current_user.user_name = savestring (entry->pw_name);
+       if (entry->pw_shell && entry->pw_shell[0])
+         current_user.shell = savestring (entry->pw_shell);
+       else
+         current_user.shell = savestring ("/bin/sh");
+       current_user.home_dir = savestring (entry->pw_dir);
+      }
+    else
+      {
+       current_user.user_name = savestring ("I have no name!");
+       current_user.shell = savestring ("/bin/sh");
+       current_user.home_dir = savestring ("/");
+      }
+
+    endpwent ();
+  }
+
+  /* Initialize our interface to the tilde expander. */
+  tilde_initialize ();
+
+  /* Initialize internal and environment variables. */
+  initialize_shell_variables (shell_environment);
+
+  /* Initialize filename hash tables. */
+  initialize_filename_hashing ();
+
+  /* Initialize the data structures for storing and running jobs. */
+  initialize_jobs ();
+
+  /* Initialize input streams to null. */
+  initialize_bash_input ();
+}
+
+/* Function called by main () when it appears that the shell has already
+   had some initialization performed.  This is supposed to reset the world
+   back to a pristine state, as if we had been exec'ed. */
+static void
+shell_reinitialize ()
+{
+  /* The default shell prompts. */
+  primary_prompt = PPROMPT;
+  secondary_prompt = SPROMPT;
+
+  /* Things that get 1. */
+  current_command_number = 1;
+
+  /* We have decided that the ~/.bashrc file should not be executed
+     for the invocation of each shell script.  If the variable $ENV
+     (or $BASH_ENV) is set, its value is used as the name of a file
+     to source. */
+  no_rc = no_profile = 1;
+
+  /* Things that get 0. */
+  login_shell = make_login_shell = interactive = executing = 0;
+  debugging = do_version = line_number = last_command_exit_value = 0;
+  forced_interactive = interactive_shell = subshell_environment = 0;
+
+#if defined (HISTORY)
+#  if defined (BANG_HISTORY)
+  history_expansion = 0;
+#  endif
+  remember_on_history = 0;
+#endif /* HISTORY */
+
+#if defined (RESTRICTED_SHELL)
+  restricted = 0;
+#endif /* RESTRICTED_SHELL */
+
+  /* Ensure that the default startup file is used.  (Except that we don't
+     execute this file for reinitialized shells). */
+  bashrc_file = "~/.bashrc";
+
+  /* Delete all variables and functions.  They will be reinitialized when
+     the environment is parsed. */
+
+  delete_all_variables (shell_variables);
+  delete_all_variables (shell_functions);
+
+  /* Pretend the PATH variable has changed. */
+  sv_path ("PATH");
+}
+
+static void
+initialize_signals ()
+{
+  initialize_terminating_signals ();
+  initialize_job_signals ();
+#if defined (INITIALIZE_SIGLIST)
+  initialize_siglist ();
+#endif
+}
+
+void
+reinitialize_signals ()
+{
+  initialize_terminating_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. */
+struct termsig {
+     int signum;
+     SigHandler *orig_handler;
+};
+
+#define NULL_HANDLER (SigHandler *)SIG_DFL
+
+/* The list of signals that would terminate the shell if not caught.
+   We catch them, but just so that we can write the history file,
+   and so forth. */
+static struct termsig terminating_signals[] = {
+#ifdef SIGHUP
+  SIGHUP, NULL_HANDLER,
+#endif
+
+#ifdef SIGINT
+  SIGINT, NULL_HANDLER,
+#endif
+
+#ifdef SIGILL
+  SIGILL, NULL_HANDLER,
+#endif
+
+#ifdef SIGTRAP
+  SIGTRAP, NULL_HANDLER,
+#endif
+
+#ifdef SIGIOT
+  SIGIOT, NULL_HANDLER,
+#endif
+
+#ifdef SIGDANGER
+  SIGDANGER, NULL_HANDLER,
+#endif
+
+#ifdef SIGEMT
+  SIGEMT, NULL_HANDLER,
+#endif
+
+#ifdef SIGFPE
+  SIGFPE, NULL_HANDLER,
+#endif
+
+#ifdef SIGBUS
+  SIGBUS, NULL_HANDLER,
+#endif
+
+#ifdef SIGSEGV
+  SIGSEGV, NULL_HANDLER,
+#endif
+
+#ifdef SIGSYS
+  SIGSYS, NULL_HANDLER,
+#endif
+
+#ifdef SIGPIPE
+  SIGPIPE, NULL_HANDLER,
+#endif
+
+#ifdef SIGALRM
+  SIGALRM, NULL_HANDLER,
+#endif
+
+#ifdef SIGTERM
+  SIGTERM, NULL_HANDLER,
+#endif
+
+#ifdef SIGXCPU
+  SIGXCPU, NULL_HANDLER,
+#endif
+
+#ifdef SIGXFSZ
+  SIGXFSZ, NULL_HANDLER,
+#endif
+
+#ifdef SIGVTALRM
+  SIGVTALRM, NULL_HANDLER,
+#endif
+
+#ifdef SIGPROF
+  SIGPROF, NULL_HANDLER,
+#endif
+
+#ifdef SIGLOST
+  SIGLOST, NULL_HANDLER,
+#endif
+
+#ifdef SIGUSR1
+  SIGUSR1, NULL_HANDLER,
+#endif
+
+#ifdef SIGUSR2
+  SIGUSR2, NULL_HANDLER,
+#endif
+};
+
+#define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
+
+#define XSIG(x) (terminating_signals[x].signum)
+#define XHANDLER(x) (terminating_signals[x].orig_handler)
+
+/* This function belongs here? */
+sighandler
+termination_unwind_protect (sig)
+     int sig;
+{
+  if (sig == SIGINT && signal_is_trapped (SIGINT))
+    run_interrupt_trap ();
+
+#if defined (HISTORY)
+  if (interactive_shell)
+    maybe_save_shell_history ();
+#endif /* HISTORY */
+
+#if defined (JOB_CONTROL)
+  if (interactive && sig == SIGHUP)
+    hangup_all_jobs ();
+  end_job_control ();
+#endif /* JOB_CONTROL */
+
+#if defined (PROCESS_SUBSTITUTION)
+  unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+
+  run_exit_trap ();
+  set_signal_handler (sig, SIG_DFL);
+  kill (getpid (), sig);
+
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* VOID_SIGHANDLER */
+}
+
+/* Initialize signals that will terminate the shell to do some
+   unwind protection. */
+static void
+initialize_terminating_signals ()
+{
+  register int i;
+
+  /* The following code is to avoid an expensive call to
+     set_signal_handler () for each terminating_signals.  Fortunately,
+     this is possible in Posix.  Unfortunately, we have to call signal ()
+     on non-Posix systems for each signal in terminating_signals. */
+#if defined (_POSIX_VERSION)
+  struct sigaction act, oact;
+
+  act.sa_handler = termination_unwind_protect;
+  act.sa_flags = 0;
+  sigemptyset (&act.sa_mask);
+  sigemptyset (&oact.sa_mask);
+  for (i = 0; i < TERMSIGS_LENGTH; i++)
+    sigaddset (&act.sa_mask, XSIG (i));
+  for (i = 0; i < TERMSIGS_LENGTH; i++)
+    {
+      sigaction (XSIG (i), &act, &oact);
+      terminating_signals[i].orig_handler = oact.sa_handler;
+      /* Don't do anything with signals that are ignored at shell entry
+        if the shell is not interactive. */
+      if (!interactive_shell && oact.sa_handler == SIG_IGN)
+        {
+         sigaction (XSIG (i), &oact, &act);
+         set_signal_ignored (XSIG (i));
+        }
+    }
+
+#else /* !_POSIX_VERSION */
+
+  for (i = 0; i < TERMSIGS_LENGTH; i++)
+    {
+      terminating_signals[i].orig_handler =
+       set_signal_handler (XSIG (i), termination_unwind_protect);
+      /* Don't do anything with signals that are ignored at shell entry
+        if the shell is not interactive. */
+      if (!interactive_shell && terminating_signals[i].orig_handler == SIG_IGN)
+       {
+          set_signal_handler (XSIG (i), SIG_IGN);
+          set_signal_ignored (XSIG (i));
+       }
+    }
+
+#endif /* !_POSIX_VERSION */
+
+#if defined (JOB_CONTROL) || defined (_POSIX_VERSION)
+  /* All shells use the signal mask they inherit, and pass it along
+     to child processes.  Children will never block SIGCHLD, though. */
+  sigemptyset (&top_level_mask);
+  sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
+  sigdelset (&top_level_mask, SIGCHLD);
+#endif /* JOB_CONTROL || _POSIX_VERSION */
+
+  /* And, some signals that are specifically ignored by the shell. */
+  set_signal_handler (SIGQUIT, SIG_IGN);
+
+  if (interactive)
+    {
+      set_signal_handler (SIGINT, sigint_sighandler);
+      set_signal_handler (SIGTERM, SIG_IGN);
+    }
+}
+
+void
+reset_terminating_signals ()
+{
+  register int i;
+
+#if defined (_POSIX_VERSION)
+  struct sigaction act;
+
+  act.sa_flags = 0;
+  sigemptyset (&act.sa_mask);
+  for (i = 0; i < TERMSIGS_LENGTH; i++)
+    {
+      /* Skip a signal if it's trapped or handled specially, because the
+        trap code will restore the correct value. */
+      if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
+       continue;
+
+      act.sa_handler = XHANDLER (i);
+      sigaction (XSIG (i), &act, (struct sigaction *) NULL);
+    }
+#else
+  for (i = 0; i < TERMSIGS_LENGTH; i++)
+    {
+      if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
+       continue;
+
+      set_signal_handler (XSIG (i), XHANDLER (i));
+    }
+#endif
+}
+#undef XSIG
+#undef XHANDLER
+
+/* What to do when we've been interrupted, and it is safe to handle it. */
+void
+throw_to_top_level ()
+{
+  int print_newline = 0;
+
+  if (interrupt_state)
+    {
+      print_newline = 1;
+      interrupt_state--;
+    }
+
+  if (interrupt_state)
+    return;
+
+  last_command_exit_value |= 128;
+
+  /* Run any traps set on SIGINT. */
+  run_interrupt_trap ();
+
+  /* Cleanup string parser environment. */
+  while (parse_and_execute_level)
+    parse_and_execute_cleanup ();
+
+#if defined (JOB_CONTROL)
+  give_terminal_to (shell_pgrp);
+#endif /* JOB_CONTROL */
+
+#if defined (JOB_CONTROL) || defined (_POSIX_VERSION)
+  sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
+#endif
+
+  reset_parser ();
+
+#if defined (READLINE)
+  if (interactive)
+    bashline_reinitialize ();
+#endif /* READLINE */
+
+#if defined (PROCESS_SUBSTITUTION)
+  unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+
+  run_unwind_protects ();
+  loop_level = continuing = breaking = 0;
+  return_catch_flag = 0;
+
+  if (interactive && print_newline)
+    {
+      fflush (stdout);
+      fprintf (stderr, "\n");
+      fflush (stderr);
+    }
+
+  /* An interrupted `wait' command in a script does not exit the script. */
+  if (interactive || (interactive_shell && !shell_initialized) ||
+      (print_newline && signal_is_trapped (SIGINT)))
+    longjmp (top_level, DISCARD);
+  else
+    longjmp (top_level, EXITPROG);
+}
+
+/* When non-zero, we throw_to_top_level (). */
+int interrupt_immediately = 0;
+
+/* What we really do when SIGINT occurs. */
+sighandler
+sigint_sighandler (sig)
+     int sig;
+{
+#if defined (USG) && !defined (_POSIX_VERSION)
+  set_signal_handler (sig, sigint_sighandler);
+#endif
+
+  /* interrupt_state needs to be set for the stack of interrupts to work
+     right.  Should it be set unconditionally? */
+  if (!interrupt_state)
+    interrupt_state++;
+
+  if (interrupt_immediately)
+    {
+      interrupt_immediately = 0;
+      throw_to_top_level ();
+    }
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* VOID_SIGHANDLER */
+}
+
+/* Give version information about this shell. */
+char *
+shell_version_string ()
+{
+  static char tt[16] = { '\0' };
+
+  if (!tt[0])
+    sprintf (tt, "%s.%d(%d)", dist_version, patch_level, build_version);
+  return tt;
+}
+
+void
+show_shell_version ()
+{
+  printf ("GNU %s, version %s\n", base_pathname (shell_name),
+    shell_version_string ());
+}
+
+#if !defined (USG) && defined (ENOTSOCK)
+#  if !defined (HAVE_SOCKETS)
+#    define HAVE_SOCKETS
+#  endif
+#endif
+
+#if defined (HAVE_SOCKETS)
+#include <sys/socket.h>
+#endif
+
+/* Is FD a socket or network connection? */
+static int
+isnetconn (fd)
+     int fd;
+{
+#if defined (USGr4) || defined (USGr4_2)
+  /* Sockets on SVR4 and SVR4.2 are character special (streams) devices. */
+  struct stat sb;
+
+  if (fstat (fd, &sb) < 0)
+    return (0);
+  return (S_ISCHR (sb.st_mode));
+#else /* !USGr4 && !USGr4_2 */
+#  if defined (HAVE_SOCKETS)
+  int rv, l;
+  struct sockaddr sa;
+
+  l = sizeof(sa);
+  rv = getpeername(0, &sa, &l);
+  return ((rv < 0 && errno == ENOTSOCK) ? 0 : 1);
+#  else /* !HAVE_SOCKETS */
+#    if defined (S_ISSOCK)
+  struct stat sb;
+
+  if (fstat (fd, &sb) < 0)
+    return (0);
+  return (S_ISSOCK (sb.st_mode));
+#    else /* !S_ISSOCK */
+  return (0);
+#    endif /* !S_ISSOCK */
+#  endif /* !HAVE_SOCKETS */
+#endif /* !USGr4 && !USGr4_2 */
+}
diff --git a/shell.h b/shell.h
new file mode 100644 (file)
index 0000000..b7d3132
--- /dev/null
+++ b/shell.h
@@ -0,0 +1,107 @@
+/* shell.h -- The data structures used by the shell */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "config.h"
+#include "command.h"
+#include "general.h"
+#include "error.h"
+#include "variables.h"
+#include "quit.h"
+#include "maxpath.h"
+#include "unwind_prot.h"
+#include "dispose_cmd.h"
+#include "make_cmd.h"
+#include "subst.h"
+#include "externs.h"
+
+extern int EOF_Reached;
+
+#define NO_PIPE -1
+#define REDIRECT_BOTH -2
+#define IS_DESCRIPTOR -1
+
+#define NO_VARIABLE -1
+
+/* A bunch of stuff for flow of control using setjmp () and longjmp (). */
+#include <setjmp.h>
+extern jmp_buf top_level, catch;
+
+#define NOT_JUMPED 0           /* Not returning from a longjmp. */
+#define FORCE_EOF 1            /* We want to stop parsing. */
+#define DISCARD 2              /* Discard current command. */
+#define EXITPROG 3             /* Unconditionally exit the program now. */
+
+/* Values that can be returned by execute_command (). */
+#define EXECUTION_FAILURE 1
+#define EXECUTION_SUCCESS 0
+
+/* Usage messages by builtins result in a return status of 2. */
+#define EX_USAGE 2
+
+/* Special exit status used when the shell is asked to execute a
+   binary file as a shell script. */
+#define EX_BINARY_FILE 126
+#define EX_NOEXEC 126
+#define EX_NOTFOUND 127
+
+/* The list of characters that are quoted in double-quotes with a
+   backslash.  Other characters following a backslash cause nothing
+   special to happen. */
+#define slashify_in_quotes "\\`$\""
+#define slashify_in_here_document "\\`$"
+
+/* Constants which specify how to handle backslashes and quoting in
+   expand_word_internal ().  Q_DOUBLE_QUOTES means to use the function
+   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. */
+#define Q_DOUBLE_QUOTES  0x1
+#define Q_HERE_DOCUMENT  0x2
+#define Q_KEEP_BACKSLASH 0x4
+
+extern char **shell_environment;
+extern WORD_LIST *rest_of_args;
+
+/* Generalized global variables. */
+extern int executing, login_shell;
+
+/* Structure to pass around that holds a bitmap of file descriptors
+   to close, and the size of that structure.  Used in execute_cmd.c. */
+struct fd_bitmap {
+  long size;
+  char *bitmap;
+};
+
+#define FD_BITMAP_SIZE 32
+
+#define CTLESC '\001'
+#define CTLNUL '\177'
+
+/* Information about the current user. */
+struct user_info {
+  int uid, euid;
+  int gid, egid;
+  char *user_name;
+  char *shell;         /* shell from the password file */
+  char *home_dir;
+};
+
+extern struct user_info current_user;
diff --git a/siglist.c b/siglist.c
new file mode 100644 (file)
index 0000000..7571cf0
--- /dev/null
+++ b/siglist.c
@@ -0,0 +1,219 @@
+/* siglist.c -- signal list for those machines that don't have one. */
+
+/* Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#include "siglist.h"
+
+#if !defined (NSIG)
+#  include "trap.h"
+#endif
+
+char *sys_siglist[NSIG];
+
+extern char *xmalloc (), *malloc ();
+
+void
+initialize_siglist ()
+{
+  register int i;
+
+  for (i = 0; i < NSIG; i++)
+    sys_siglist[i] = (char *)0x0;
+
+  sys_siglist[0] = "Bogus signal";
+
+#if defined (SIGHUP)
+  sys_siglist[SIGHUP] = "Hangup";
+#endif
+
+#if defined (SIGINT)
+  sys_siglist[SIGINT] = "Interrupt";
+#endif
+
+#if defined (SIGQUIT)
+  sys_siglist[SIGQUIT] = "Quit";
+#endif
+
+#if defined (SIGILL)
+  sys_siglist[SIGILL] = "Illegal instruction";
+#endif
+
+#if defined (SIGTRAP)
+  sys_siglist[SIGTRAP] = "BPT trace/trap";
+#endif
+
+#if defined (SIGIOT) && !defined (SIGABRT)
+#define SIGABRT SIGIOT
+#endif
+
+#if defined (SIGABRT)
+  sys_siglist[SIGABRT] = "ABORT instruction";
+#endif
+
+#if defined (SIGEMT)
+  sys_siglist[SIGEMT] = "EMT instruction";
+#endif
+
+#if defined (SIGFPE)
+  sys_siglist[SIGFPE] = "Floating point exception";
+#endif
+
+#if defined (SIGKILL)
+  sys_siglist[SIGKILL] = "Killed";
+#endif
+
+#if defined (SIGBUS)
+  sys_siglist[SIGBUS] = "Bus error";
+#endif
+
+#if defined (SIGSEGV)
+  sys_siglist[SIGSEGV] = "Segmentation fault";
+#endif
+
+#if defined (SIGSYS)
+  sys_siglist[SIGSYS] = "Bad system call";
+#endif
+
+#if defined (SIGPIPE)
+  sys_siglist[SIGPIPE] = "Broken pipe";
+#endif
+
+#if defined (SIGALRM)
+  sys_siglist[SIGALRM] = "Alarm clock";
+#endif
+
+#if defined (SIGTERM)
+  sys_siglist[SIGTERM] = "Terminated";
+#endif
+
+#if defined (SIGURG)
+  sys_siglist[SIGURG] = "Urgent IO condition";
+#endif
+
+#if defined (SIGSTOP)
+  sys_siglist[SIGSTOP] = "Stopped (signal)";
+#endif
+
+#if defined (SIGTSTP)
+  sys_siglist[SIGTSTP] = "Stopped";
+#endif
+
+#if defined (SIGCONT)
+  sys_siglist[SIGCONT] = "Continue";
+#endif
+
+#if !defined (SIGCHLD) && defined (SIGCLD)
+#define SIGCHLD SIGCLD
+#endif
+
+#if defined (SIGCHLD)
+  sys_siglist[SIGCHLD] = "Child death or stop";
+#endif
+
+#if defined (SIGTTIN)
+  sys_siglist[SIGTTIN] = "Stopped (tty input)";
+#endif
+
+#if defined (SIGTTOU)
+  sys_siglist[SIGTTOU] = "Stopped (tty output)";
+#endif
+
+#if defined (SIGIO)
+  sys_siglist[SIGIO] = "I/O ready";
+#endif
+
+#if defined (SIGXCPU)
+  sys_siglist[SIGXCPU] = "CPU limit";
+#endif
+
+#if defined (SIGXFSZ)
+  sys_siglist[SIGXFSZ] = "File limit";
+#endif
+
+#if defined (SIGVTALRM)
+  sys_siglist[SIGVTALRM] = "Alarm (virtual)";
+#endif
+
+#if defined (SIGPROF)
+  sys_siglist[SIGPROF] = "Alarm (profile)";
+#endif
+
+#if defined (SIGWINCH)
+  sys_siglist[SIGWINCH] = "Window changed";
+#endif
+
+#if defined (SIGLOST)
+  sys_siglist[SIGLOST] = "Record lock";
+#endif
+
+#if defined (SIGUSR1)
+  sys_siglist[SIGUSR1] = "User signal 1";
+#endif
+
+#if defined (SIGUSR2)
+  sys_siglist[SIGUSR2] = "User signal 2";
+#endif
+
+#if defined (SIGMSG)
+  sys_siglist[SIGMSG] = "HFT input data pending";
+#endif 
+
+#if defined (SIGPWR)
+  sys_siglist[SIGPWR] = "power failure imminent";
+#endif 
+
+#if defined (SIGDANGER)
+  sys_siglist[SIGDANGER] = "system crash imminent";
+#endif 
+
+#if defined (SIGMIGRATE)
+  sys_siglist[SIGMIGRATE] = "migrate process to another CPU";
+#endif 
+
+#if defined (SIGPRE)
+  sys_siglist[SIGPRE] = "programming error";
+#endif 
+
+#if defined (SIGGRANT)
+  sys_siglist[SIGGRANT] = "HFT monitor mode granted";
+#endif 
+
+#if defined (SIGRETRACT)
+  sys_siglist[SIGRETRACT] = "HFT monitor mode retracted";
+#endif 
+
+#if defined (SIGSOUND)
+  sys_siglist[SIGSOUND] = "HFT sound sequence has completed";
+#endif 
+
+  for (i = 0; i < NSIG; i++)
+    {
+      if (!sys_siglist[i])
+       {
+         sys_siglist[i] =
+           (char *)xmalloc (10 + strlen ("Unknown Signal #"));
+
+         sprintf (sys_siglist[i], "Unknown Signal #%d", i);
+       }
+    }
+}
diff --git a/siglist.h b/siglist.h
new file mode 100644 (file)
index 0000000..b52d7ad
--- /dev/null
+++ b/siglist.h
@@ -0,0 +1,40 @@
+/* siglist.h -- encapsulate various definitions for sys_siglist */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_SIGLIST_H_)
+#define _SIGLIST_H_
+
+#if defined (Solaris) || defined (USGr4_2) || defined (drs6000) || defined (amiga) || defined (Minix)
+#  if !defined (sys_siglist)
+#    define sys_siglist _sys_siglist
+#  endif /* !sys_siglist */
+#endif /* Solaris || USGr4_2 || drs6000 || amiga || Minix */
+
+#if !defined (Solaris) && !defined (Linux) && !defined (__BSD_4_4__) && \
+       !defined (Minix) && !defined (NetBSD) && !defined (FreeBSD) && \
+       !defined (BSD_OS)
+extern char *sys_siglist[];
+#endif /* !Solaris && !Linux && !__BSD_4_4__ && !Minix && !NetBSD && !FreeBSD && !BSD_OS */
+
+#if !defined (strsignal) && !defined (Solaris) && !defined (NetBSD)
+#  define strsignal(sig) (char *)sys_siglist[sig]
+#endif /* !strsignal && !Solaris && !NetBSD */
+
+#endif /* _SIGLIST_H */
diff --git a/signames.c b/signames.c
new file mode 100644 (file)
index 0000000..f5216d5
--- /dev/null
@@ -0,0 +1,297 @@
+/* signames.c -- Create and write `signames.h', which contains an array of
+   signal names. */
+
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 1, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <signal.h>
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if !defined (NSIG)
+#  define NSIG 64
+#endif
+
+char *signal_names[2 * NSIG];
+
+char *progname;
+
+initialize_signames ()
+{
+  register int i;
+
+  for (i = 1; i < sizeof(signal_names)/sizeof(signal_names[0]); i++)
+    signal_names[i] = (char *)NULL;
+
+  /* `signal' 0 is what we do on exit. */
+  signal_names[0] = "EXIT";
+
+  /* Place signal names which can be aliases for more common signal
+     names first.  This allows (for example) SIGEMT to overwrite SIGGRANT. */
+#if defined (SIGGRANT) /* HFT monitor mode granted */
+  signal_names[SIGGRANT] = "SIGGRANT";
+#endif
+
+#if defined (SIGRETRACT) /* HFT monitor mode retracted */
+  signal_names[SIGRETRACT] = "SIGRETRACT";
+#endif
+
+#if defined (SIGHUP)   /* hangup */
+  signal_names[SIGHUP] = "SIGHUP";
+#endif
+
+#if defined (SIGINT)   /* interrupt */
+  signal_names[SIGINT] = "SIGINT";
+#endif
+
+#if defined (SIGQUIT)  /* quit */
+  signal_names[SIGQUIT] = "SIGQUIT";
+#endif
+
+#if defined (SIGILL)   /* illegal instruction (not reset when caught) */
+  signal_names[SIGILL] = "SIGILL";
+#endif
+
+#if defined (SIGTRAP)  /* trace trap (not reset when caught) */
+  signal_names[SIGTRAP] = "SIGTRAP";
+#endif
+
+#if defined (SIGABRT)  /* Cause current process to dump core. */
+  signal_names[SIGABRT] = "SIGABRT";
+#endif
+
+#if defined (SIGIOT)   /* IOT instruction */
+  signal_names[SIGIOT] = "SIGIOT";
+#endif
+
+#if defined (SIGEMT)   /* EMT instruction */
+  signal_names[SIGEMT] = "SIGEMT";
+#endif
+
+#if defined (SIGFPE)   /* floating point exception */
+  signal_names[SIGFPE] = "SIGFPE";
+#endif
+
+#if defined (SIGKILL)  /* kill (cannot be caught or ignored) */
+  signal_names[SIGKILL] = "SIGKILL";
+#endif
+
+#if defined (SIGBUS)   /* bus error */
+  signal_names[SIGBUS] = "SIGBUS";
+#endif
+
+#if defined (SIGSEGV)  /* segmentation violation */
+  signal_names[SIGSEGV] = "SIGSEGV";
+#endif
+
+#if defined (SIGSYS)   /* bad argument to system call */
+  signal_names[SIGSYS] = "SIGSYS";
+#endif
+
+#if defined (SIGPIPE)  /* write on a pipe with no one to read it */
+  signal_names[SIGPIPE] = "SIGPIPE";
+#endif
+
+#if defined (SIGALRM)  /* alarm clock */
+  signal_names[SIGALRM] = "SIGALRM";
+#endif
+
+#if defined (SIGTERM)  /* software termination signal from kill */
+  signal_names[SIGTERM] = "SIGTERM";
+#endif
+
+#if defined (SIGCLD)   /* Like SIGCHLD.  */
+  signal_names[SIGCLD] = "SIGCLD";
+#endif
+
+#if defined (SIGPWR)   /* Magic thing for some machines. */
+  signal_names[SIGPWR] = "SIGPWR";
+#endif
+
+#if defined (SIGPOLL)  /* For keyboard input?  */
+  signal_names[SIGPOLL] = "SIGPOLL";
+#endif
+
+#if defined (SIGURG)   /* urgent condition on IO channel */
+  signal_names[SIGURG] = "SIGURG";
+#endif
+
+#if defined (SIGSTOP)  /* sendable stop signal not from tty */
+  signal_names[SIGSTOP] = "SIGSTOP";
+#endif
+
+#if defined (SIGTSTP)  /* stop signal from tty */
+  signal_names[SIGTSTP] = "SIGTSTP";
+#endif
+
+#if defined (SIGCONT)  /* continue a stopped process */
+  signal_names[SIGCONT] = "SIGCONT";
+#endif
+
+#if defined (SIGCHLD)  /* to parent on child stop or exit */
+  signal_names[SIGCHLD] = "SIGCHLD";
+#endif
+
+#if defined (SIGTTIN)  /* to readers pgrp upon background tty read */
+  signal_names[SIGTTIN] = "SIGTTIN";
+#endif
+
+#if defined (SIGTTOU)  /* like TTIN for output if (tp->t_local&LTOSTOP) */
+  signal_names[SIGTTOU] = "SIGTTOU";
+#endif
+
+#if defined (SIGIO)    /* input/output possible signal */
+  signal_names[SIGIO] = "SIGIO";
+#endif
+
+#if defined (SIGXCPU)  /* exceeded CPU time limit */
+  signal_names[SIGXCPU] = "SIGXCPU";
+#endif
+
+#if defined (SIGXFSZ)  /* exceeded file size limit */
+  signal_names[SIGXFSZ] = "SIGXFSZ";
+#endif
+
+#if defined (SIGVTALRM)        /* virtual time alarm */
+  signal_names[SIGVTALRM] = "SIGVTALRM";
+#endif
+
+#if defined (SIGPROF)  /* profiling time alarm */
+  signal_names[SIGPROF] = "SIGPROF";
+#endif
+
+#if defined (SIGWINCH) /* window changed */
+  signal_names[SIGWINCH] = "SIGWINCH";
+#endif
+
+#if defined (SIGLOST)  /* resource lost (eg, record-lock lost) */
+  signal_names[SIGLOST] = "SIGLOST";
+#endif
+
+#if defined (SIGUSR1)  /* user defined signal 1 */
+  signal_names[SIGUSR1] = "SIGUSR1";
+#endif
+
+#if defined (SIGUSR2)  /* user defined signal 2 */
+  signal_names[SIGUSR2] = "SIGUSR2";
+#endif
+
+#if defined (SIGMSG)   /* HFT input data pending */
+  signal_names[SIGMSG] = "SIGMSG";
+#endif
+
+#if defined (SIGPWR)   /* power failure imminent (save your data) */
+  signal_names[SIGPWR] = "SIGPWR";
+#endif
+
+#if defined (SIGDANGER)        /* system crash imminent */
+  signal_names[SIGDANGER] = "SIGDANGER";
+#endif
+
+#if defined (SIGMIGRATE) /* migrate process to another CPU */
+  signal_names[SIGMIGRATE] = "SIGMIGRATE";
+#endif
+
+#if defined (SIGPRE)   /* programming error */
+  signal_names[SIGPRE] = "SIGPRE";
+#endif
+
+#if defined (SIGSOUND) /* HFT sound sequence has completed */
+  signal_names[SIGSOUND] = "SIGSOUND";
+#endif
+
+#if defined (SIGWINDOW)
+  signal_names[SIGWINDOW] = "SIGWINDOW";
+#endif
+
+#if defined (SIGDIL)
+  signal_names[SIGDIL] = "SIGDIL";
+#endif
+
+#if defined (SIGSAK)   /* Secure Attention Key */
+  signal_names[SIGSAK] = "SIGSAK";
+#endif
+
+  for (i = 0; i < NSIG; i++)
+    if (signal_names[i] == (char *)NULL)
+      {
+       signal_names[i] = (char *)malloc (18);
+       sprintf (signal_names[i], "SIGJUNK(%d)", i);
+      }
+}
+
+write_signames (stream)
+     FILE *stream;
+{
+  register int i;
+
+  fprintf (stream, "/* This file was automatically created by %s.\n",
+          progname);
+  fprintf (stream, "   Do not edit.  Edit signames.c instead. */\n\n");
+  fprintf (stream,
+          "/* A translation list so we can be polite to our users. */\n");
+  fprintf (stream, "char *signal_names[NSIG + 2] = {\n");
+
+  for (i = 0; i < NSIG; i++)
+    fprintf (stream, "    \"%s\",\n", signal_names[i]);
+
+  fprintf (stream, "    (char *)0x0,\n");
+  fprintf (stream, "};\n");
+}
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char *stream_name;
+  FILE *stream;
+
+  progname = argv[0];
+
+  if (argc == 1)
+    {
+      stream_name = "stdout";
+      stream = stdout;
+    }
+  else if (argc == 2)
+    {
+      stream_name = argv[1];
+      stream = fopen (stream_name, "w");
+    }
+  else
+    {
+      fprintf (stderr, "Usage: %s [output-file]\n", progname);
+      exit (1);
+    }
+
+  if (!stream)
+    {
+      fprintf (stderr, "%s: %s Cannot be opened or written to.\n",
+              progname, stream_name);
+      exit (2);
+    }
+
+  initialize_signames ();
+  write_signames (stream);
+  exit (0);
+}
diff --git a/stdc.h b/stdc.h
new file mode 100644 (file)
index 0000000..5dcc32b
--- /dev/null
+++ b/stdc.h
@@ -0,0 +1,78 @@
+/* stdc.h -- macros to make source compile on both ANSI C and K&R C
+   compilers. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (__STDC_H__)
+#define __STDC_H__
+
+/* Adapted from BSD /usr/include/sys/cdefs.h. */
+
+/* A function can be defined using prototypes and compile on both ANSI C
+   and traditional C compilers with something like this:
+       extern char *func __P((char *, char *, int)); */
+#if defined (__STDC__)
+
+#  if !defined (__P)
+#    define __P(protos) protos
+#  endif
+#  define __STRING(x) #x
+
+#  if !defined (__GNUC__)
+#    define inline
+#  endif
+
+#else /* !__STDC__ */
+
+#  if !defined (__P)
+#    define __P(protos) ()
+#  endif
+#  define __STRING(x) "x"
+
+#if defined (__GNUC__)         /* gcc with -traditional */
+#  if !defined (const)
+#    define const  __const
+#  endif
+#  if !defined (inline)
+#    define inline __inline
+#  endif
+#  if !defined (signed)
+#    define signed __signed
+#  endif
+#  if !defined (volatile)
+#    define volatile __volatile
+#  endif
+#else /* !__GNUC__ */
+#  if !defined (const)
+#    define const
+#  endif
+#  if !defined (inline)
+#    define inline
+#  endif
+#  if !defined (signed)
+#    define signed
+#  endif
+#  if !defined (volatile)
+#    define volatile
+#  endif
+#endif /* !__GNUC__ */
+
+#endif /* !__STDC__ */
+
+#endif /* !__STDC_H__ */
diff --git a/subst.c b/subst.c
new file mode 100644 (file)
index 0000000..9dd00a8
--- /dev/null
+++ b/subst.c
@@ -0,0 +1,4867 @@
+/* subst.c -- The part of the shell that does parameter, command, and
+   globbing substitutions. */
+
+/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "bashtypes.h"
+#include <stdio.h>
+#include <pwd.h>
+#include <signal.h>
+#include <errno.h>
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "bashansi.h"
+#include "posixstat.h"
+
+#include "shell.h"
+#include "flags.h"
+#include "jobs.h"
+#include "execute_cmd.h"
+#include "filecntl.h"
+
+#if defined (READLINE)
+#  include <readline/readline.h>
+#else
+#  include <tilde/tilde.h>
+#endif
+
+#if defined (HISTORY)
+#  include "bashhist.h"
+#  include <readline/history.h>
+#endif
+
+#include <glob/fnmatch.h>
+#include "builtins/getopt.h"
+
+/* The size that strings change by. */
+#define DEFAULT_ARRAY_SIZE 512
+
+/* How to quote and determine the quoted state of the character C. */
+static char *make_quoted_char ();
+#define QUOTED_CHAR(c)  ((c) == CTLESC)
+
+/* Process ID of the last command executed within command substitution. */
+pid_t last_command_subst_pid = NO_PID;
+
+/* Extern functions and variables from different files. */
+extern int last_command_exit_value, interactive, interactive_shell;
+extern int subshell_environment;
+extern int dollar_dollar_pid, no_brace_expansion;
+extern int posixly_correct;
+extern int eof_encountered, eof_encountered_limit, ignoreeof;
+extern char *this_command_name;
+extern jmp_buf top_level;
+#if defined (READLINE)
+extern int no_line_editing;
+extern int hostname_list_initialized;
+#endif
+
+#if !defined (USE_POSIX_GLOB_LIBRARY)
+extern int glob_dot_filenames, noglob_dot_filenames;
+extern char *glob_error_return;
+#endif
+
+static WORD_LIST expand_word_error, expand_word_fatal;
+static char expand_param_error, expand_param_fatal;
+
+static WORD_LIST *expand_string_internal ();
+static WORD_LIST *expand_word_internal (), *expand_words_internal ();
+static WORD_LIST *expand_string_leave_quoted ();
+static WORD_LIST *word_list_split ();
+static char *quote_string ();
+static int unquoted_substring (), unquoted_member ();
+static int unquoted_glob_pattern_p ();
+static void quote_list (), dequote_list ();
+static int do_assignment_internal ();
+static char *string_extract_verbatim (), *string_extract ();
+static char *string_extract_double_quoted (), *string_extract_single_quoted ();
+static char *extract_delimited_string ();
+static char *extract_dollar_brace_string ();
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Utility Functions                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* 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 = end - start;
+  register char *result = xmalloc (len + 1);
+
+  strncpy (result, string + start, len);
+  result[len] = '\0';
+  return (result);
+}
+
+/* Conventions:
+
+     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;
+
+  for (s = string; s && *s; s++)
+    {
+      if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
+       strcpy (s, s + 1);      /* XXX - should be memmove */
+    }
+  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. */
+static char *
+quote_escapes (string)
+     char *string;
+{
+  register char *s, *t;
+  char *result;
+
+  result = xmalloc ((strlen (string) * 2) + 1);
+  for (s = string, t = result; s && *s; )
+    {
+      if (*s == CTLESC || *s == CTLNUL)
+       *t++ = CTLESC;
+      *t++ = *s++;
+    }
+  *t = '\0';
+  return (result);
+}      
+
+/* Just like string_extract, but doesn't hack backslashes or any of
+   that other stuff.  Obeys quoting.  Used to do splitting on $IFS. */
+static char *
+string_extract_verbatim (string, sindex, charlist)
+     char *string, *charlist;
+     int *sindex;
+{
+  register int i = *sindex;
+  int c;
+  char *temp;
+
+  if (charlist[0] == '\'' && !charlist[1])
+    {
+      temp = string_extract_single_quoted (string, sindex);
+      i = *sindex - 1;
+      *sindex = i;
+      return (temp);
+    }
+
+  for (i = *sindex; (c = string[i]); i++)
+    {
+      if (c == CTLESC)
+       {
+         i++;
+         continue;
+       }
+
+      if (MEMBER (c, charlist))
+       break;
+    }
+
+  temp = xmalloc (1 + (i - *sindex));
+  strncpy (temp, string + (*sindex), i - (*sindex));
+  temp[i - (*sindex)] = '\0';
+  *sindex = i;
+
+  return (temp);
+}
+
+/* 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. */
+static char *
+string_extract (string, sindex, charlist)
+     char *string, *charlist;
+     int *sindex;
+{
+  register int c, i = *sindex;
+  char *temp;
+
+  while (c = string[i])
+    {
+      if (c == '\\')
+       if (string[i + 1])
+         i++;
+       else
+         break;
+      else
+       if (MEMBER (c, charlist))
+         break;
+      i++;
+    }
+  temp = xmalloc (1 + (i - *sindex));
+  strncpy (temp, string + (*sindex), i - (*sindex));
+  temp[i - (*sindex)] = '\0';
+  *sindex = i;
+  return (temp);
+}
+
+/* Remove backslashes which are quoting backquotes from STRING.  Modifies
+   STRING, and returns a pointer to it. */
+char *
+de_backslash (string)
+     char *string;
+{
+  register int i, l = strlen (string);
+
+  for (i = 0; i < l; i++)
+    if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
+                             string[i + 1] == '$'))
+      strcpy (string + i, string + i + 1);     /* XXX - should be memmove */
+  return (string);
+}
+
+#if 0
+/* Replace instances of \! in a string with !. */
+void
+unquote_bang (string)
+     char *string;
+{
+  register int i, j;
+  register char *temp;
+
+  temp = xmalloc (1 + strlen (string));
+
+  for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
+    {
+      if (string[i] == '\\' && string[i + 1] == '!')
+       {
+         temp[j] = '!';
+         i++;
+       }
+    }
+  strcpy (string, temp);
+  free (temp);
+}
+#endif
+
+/* Extract the $( construct in STRING, and return a new string.
+   Start extracting at (SINDEX) as if we had just seen "$(".
+   Make (SINDEX) get the position just after the matching ")". */
+char *
+extract_command_subst (string, sindex)
+     char *string;
+     int *sindex;
+{
+  return (extract_delimited_string (string, sindex, "$(", "(", ")"));
+}
+
+/* Extract the $[ construct in STRING, and return a new string.
+   Start extracting at (SINDEX) as if we had just seen "$[".
+   Make (SINDEX) get the position just after the matching "]". */
+char *
+extract_arithmetic_subst (string, sindex)
+     char *string;
+     int *sindex;
+{
+  return (extract_delimited_string (string, sindex, "$[", "[", "]"));
+}
+
+#if defined (PROCESS_SUBSTITUTION)
+/* Extract the <( or >( construct in STRING, and return a new string.
+   Start extracting at (SINDEX) as if we had just seen "<(".
+   Make (SINDEX) get the position just after the matching ")". */
+char *
+extract_process_subst (string, starter, sindex)
+     char *string;
+     char *starter;
+     int *sindex;
+{
+  return (extract_delimited_string (string, sindex, starter, "(", ")"));
+}
+#endif /* PROCESS_SUBSTITUTION */
+
+/* Extract and create a new string from the contents of STRING, a
+   character string delimited with OPENER and CLOSER.  SINDEX is
+   the address of an int describing the current offset in STRING;
+   it should point to just after the first OPENER found.  On exit,
+   SINDEX gets the position just after the matching CLOSER.  If
+   OPENER is more than a single character, ALT_OPENER, if non-null,
+   contains a character string that can also match CLOSER and thus
+   needs to be skipped. */
+static char *
+extract_delimited_string (string, sindex, opener, alt_opener, closer)
+     char *string;
+     int *sindex;
+     char *opener, *alt_opener, *closer;
+{
+  register int i, c, l;
+  int pass_character, nesting_level;
+  int delimiter, delimited_nesting_level;
+  int len_closer, len_opener, len_alt_opener;
+  char *result;
+
+  len_opener = STRLEN (opener);
+  len_alt_opener = STRLEN (alt_opener);
+  len_closer = STRLEN (closer);
+
+  pass_character = delimiter = delimited_nesting_level = 0;
+
+  nesting_level = 1;
+
+  for (i = *sindex; c = string[i]; i++)
+    {
+      if (pass_character)
+       {
+         pass_character = 0;
+         continue;
+       }
+
+      if (c == CTLESC)
+       {
+         pass_character++;
+         continue;
+       }
+
+      if (c == '\\')
+       {
+         if ((delimiter == '"') &&
+             (member (string[i + 1], slashify_in_quotes)))
+           {
+             pass_character++;
+             continue;
+           }
+       }
+
+      if (!delimiter || delimiter == '"')
+       {
+         if (STREQN (string + i, opener, len_opener))
+           {
+             if (!delimiter)
+               nesting_level++;
+             else
+               delimited_nesting_level++;
+
+             i += len_opener - 1;
+             continue;
+           }
+
+         if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
+           {
+             if (!delimiter)
+               nesting_level++;
+             else
+               delimited_nesting_level++;
+
+             i += len_alt_opener - 1;
+             continue;
+           }
+
+         if (STREQN (string + i, closer, len_closer))
+           {
+             i += len_closer - 1;
+
+             if (delimiter && delimited_nesting_level)
+               delimited_nesting_level--;
+
+             if (!delimiter)
+               {
+                 nesting_level--;
+                 if (nesting_level == 0)
+                   break;
+               }
+           }
+       }
+
+      if (delimiter)
+       {
+         if (c == delimiter || delimiter == '\\')
+           delimiter = 0;
+         continue;
+       }
+      else
+       {
+         if (c == '"' || c == '\'' || c == '\\')
+           delimiter = c;
+       }
+    }
+
+  l = i - *sindex;
+  result = xmalloc (1 + l);
+  strncpy (result, string + *sindex, l);
+  result[l] = '\0';
+  *sindex = i;
+
+  if (!c && (delimiter || nesting_level))
+    {
+      report_error ("bad substitution: no `%s' in %s", closer, string);
+      free (result);
+      longjmp (top_level, DISCARD);
+    }
+  return (result);
+}
+
+/* Extract a parameter expansion expression within ${ and } from STRING.
+   Obey the Posix.2 rules for finding the ending `}': count braces while
+   skipping over enclosed quoted strings and command substitutions.
+   SINDEX is the address of an int describing the current offset in STRING;
+   it should point to just after the first `{' found.  On exit, SINDEX
+   gets the position just after the matching `}'. */
+/* XXX -- this is very similar to extract_delimited_string -- XXX */
+static char *
+extract_dollar_brace_string (string, sindex)
+     char *string;
+     int *sindex;
+{
+  register int i, c, l;
+  int pass_character, nesting_level;
+  int delimiter, delimited_nesting_level;
+  char *result;
+
+  pass_character = delimiter = delimited_nesting_level = 0;
+
+  nesting_level = 1;
+
+  for (i = *sindex; c = string[i]; i++)
+    {
+      if (pass_character)
+       {
+         pass_character = 0;
+         continue;
+       }
+
+      if (c == CTLESC)
+       {
+         pass_character++;
+         continue;
+       }
+
+      /* Backslashes quote the next character. */
+      if (c == '\\')
+       {
+         if ((delimiter == '"') &&
+             (member (string[i + 1], slashify_in_quotes)))
+           {
+             pass_character++;
+             continue;
+           }
+       }
+
+      if (!delimiter || delimiter == '"')
+       {
+         if (string[i] == '$' && string[i+1] == '{')
+           {
+             if (!delimiter)
+               nesting_level++;
+             else
+               delimited_nesting_level++;
+
+             i++;
+             continue;
+           }
+
+         /* Pass the contents of old-style command substitutions through
+            verbatim. */
+         if (string[i] == '`')
+           {
+             int si;
+             char *t;
+
+             si = i + 1;
+             t = string_extract (string, &si, "`");
+             i = si;
+             free (t);
+             continue;
+           }
+
+         /* Pass the contents of new-style command substitutions through
+            verbatim. */
+         if (string[i] == '$' && string[i+1] == '(')
+           {
+             int si;
+             char *t;
+
+             si = i + 2;
+             t = extract_delimited_string (string, &si, "$(", "(", ")");
+             i = si;
+             free (t);
+             continue;
+           }
+
+         if (string[i] == '{')
+           {
+             if (!delimiter)
+               nesting_level++;
+             else
+               delimited_nesting_level++;
+
+             continue;
+           }
+
+         if (string[i] == '}')
+           {
+             if (delimiter && delimited_nesting_level)
+               delimited_nesting_level--;
+
+             if (!delimiter)
+               {
+                 nesting_level--;
+                 if (nesting_level == 0)
+                   break;
+               }
+           }
+       }
+
+      if (delimiter)
+       {
+         if (c == delimiter || delimiter == '\\')
+           delimiter = 0;
+         continue;
+       }
+      else
+       {
+         if (c == '"' || c == '\'' || c == '\\')
+           delimiter = c;
+       }
+    }
+
+  l = i - *sindex;
+  result = xmalloc (1 + l);
+  strncpy (result, string + *sindex, l);
+  result[l] = '\0';
+  *sindex = i;
+
+  if (!c && (delimiter || nesting_level))
+    {
+      report_error ("bad substitution: no ending `}' in %s", string);
+      free (result);
+      longjmp (top_level, DISCARD);
+    }
+  return (result);
+}
+
+/* Extract the contents of STRING as if it is enclosed in double quotes.
+   SINDEX, when passed in, is the offset of the character immediately
+   following the opening double quote; on exit, SINDEX is left pointing after
+   the closing double quote. */
+static char *
+string_extract_double_quoted (string, sindex)
+     char *string;
+     int *sindex;
+{
+  register int c, j, i;
+  char *temp;                  /* The new string we return. */
+  int pass_next, backquote;    /* State variables for the machine. */
+
+  pass_next = backquote = 0;
+  temp = xmalloc (1 + strlen (string) - *sindex);
+
+  for (j = 0, i = *sindex; c = string[i]; i++)
+    {
+      /* Process a character that was quoted by a backslash. */
+      if (pass_next)
+       {
+         /* Posix.2 sez:
+
+            ``The backslash shall retain its special meaning as an escape
+            character only when followed by one of the characters:
+               $       `       "       \       <newline>''.
+
+            We handle the double quotes here.  expand_word_internal handles
+            the rest. */
+         if (c != '"')
+           temp[j++] = '\\';
+         temp[j++] = c;
+         pass_next = 0;
+         continue;
+       }
+
+      /* A backslash protects the next character.  The code just above
+        handles preserving the backslash in front of any character but
+        a double quote. */
+      if (c == '\\')
+       {
+         pass_next++;
+         continue;
+       }
+
+      /* Inside backquotes, ``the portion of the quoted string from the
+        initial backquote and the characters up to the next backquote
+        that is not preceded by a backslash, having escape characters
+        removed, defines that command''. */
+      if (backquote)
+       {
+         if (c == '`')
+           backquote = 0;
+         temp[j++] = c;
+         continue;
+       }
+
+      if (c == '`')
+       {
+         temp[j++] = c;
+         backquote++;
+         continue;
+       }
+
+      /* Pass everything between `$(' and the matching `)' or a quoted
+        ${ ... } pair through according to the Posix.2 specification. */
+      if (c == '$' && ((string[i + 1] == '(') || (string[i + 1] == '{')))
+       {
+         register int t;
+         int si;
+         char *ret;
+
+         si = i + 2;
+         if (string[i + 1] == '(')
+           ret = extract_delimited_string (string, &si, "$(", "(", ")");
+         else
+           ret = extract_dollar_brace_string (string, &si);
+
+         temp[j++] = '$';
+         temp[j++] = string[i + 1];
+
+         for (t = 0; ret[t]; t++)
+           temp[j++] = ret[t];
+
+         i = si;
+         temp[j++] = string[i];
+         free (ret);
+         continue;
+       }
+
+      /* An unescaped double quote serves to terminate the string. */
+      if (c == '"')
+       break;
+
+      /* Add the character to the quoted string we're accumulating. */
+      temp[j++] = c;
+    }
+  temp[j] = '\0';
+
+  /* Point to after the closing quote. */
+  if (c)
+    i++;
+  *sindex = i;
+
+  return (temp);
+}
+
+/* Extract the contents of STRING as if it is enclosed in single quotes.
+   SINDEX, when passed in, is the offset of the character immediately
+   following the opening single quote; on exit, SINDEX is left pointing after
+   the closing single quote. */
+static char *
+string_extract_single_quoted (string, sindex)
+     char *string;
+     int *sindex;
+{
+  register int i = *sindex;
+  char *temp;
+
+  while (string[i] && string[i] != '\'')
+    i++;
+
+  temp = xmalloc (1 + i - *sindex);
+  strncpy (temp, string + *sindex, i - *sindex);
+  temp[i - *sindex] = '\0';
+
+  if (string[i])
+    i++;
+  *sindex = i;
+
+  return (temp);
+}
+
+/* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
+   an unclosed quoted string), or if the character at EINDEX is quoted
+   by a backslash. */
+int
+char_is_quoted (string, eindex)
+     char *string;
+     int eindex;
+{
+  int i, pass_next, quoted;
+  char *temp;
+
+  for (i = pass_next = quoted = 0; i <= eindex; i++)
+    {
+      if (pass_next)
+       {
+         pass_next = 0;
+         if (i >= eindex)      /* XXX was if (i >= eindex - 1) */
+           return 1;
+         continue;
+       }
+      else if (string[i] == '\'')
+        {
+          i++;
+          temp = string_extract_single_quoted (string, &i);
+          free (temp);
+          if (i > eindex)
+            return 1;
+          i--;
+        }
+      else if (string[i] == '"')
+        {
+          i++;
+          temp = string_extract_double_quoted (string, &i);
+          free (temp);
+          if (i > eindex)
+            return 1;
+          i--;
+        }
+      else if (string[i] == '\\')
+        {
+          pass_next = 1;
+          continue;
+        }
+    }
+  return (0);
+}
+
+#if defined (READLINE)
+int
+unclosed_pair (string, eindex, openstr)
+     char *string;
+     int eindex;
+     char *openstr;
+{
+  int i, pass_next, openc, c, olen;
+  char *temp, *s;
+
+  olen = strlen (openstr);
+  for (i = pass_next = openc = 0; i <= eindex; i++)
+    {
+      if (pass_next)
+       {
+         pass_next = 0;
+         if (i >= eindex)      /* XXX was if (i >= eindex - 1) */
+           return 0;
+         continue;
+       }
+      else if (STREQN (string + i, openstr, olen))
+       {
+         openc = 1 - openc;
+         i += olen - 1;
+       }
+      else if (string[i] == '\'')
+       {
+         i++;
+         temp = string_extract_single_quoted (string, &i);
+         free (temp);
+         if (i > eindex)
+           return 0;
+       }
+      else if (string[i] == '"')
+       {
+         i++;
+         temp = string_extract_double_quoted (string, &i);
+         free (temp);
+         if (i > eindex)
+           return 0;
+       }
+      else if (string[i] == '\\')
+       {
+         pass_next = 1;
+         continue;
+       }
+    }
+  return (openc);
+}
+#endif /* READLINE */
+
+/* Extract the name of the variable to bind to from the assignment string. */
+char *
+assignment_name (string)
+     char *string;
+{
+  int offset = assignment (string);
+  char *temp;
+
+  if (!offset)
+    return (char *)NULL;
+  temp = xmalloc (offset + 1);
+  strncpy (temp, string, offset);
+  temp[offset] = '\0';
+  return (temp);
+}
+
+/* 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 *
+string_list_internal (list, sep)
+     WORD_LIST *list;
+     char *sep;
+{
+  register WORD_LIST *t;
+  char *result, *r;
+  int word_len, sep_len, result_size;
+
+  if (!list)
+    return ((char *)NULL);
+
+  /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
+  sep_len = STRLEN (sep);
+  result_size = 0;
+
+  for (t = list; t; t = t->next)
+    {
+      if (t != list)
+       result_size += sep_len;
+      result_size += strlen (t->word->word);
+    }
+
+  r = result = xmalloc (result_size + 1);
+
+  for (t = list; t; t = t->next)
+    {
+      if (t != list && sep_len)
+       {
+         FASTCOPY (sep, r, sep_len);
+         r += sep_len;
+       }
+
+      word_len = strlen (t->word->word);
+      FASTCOPY (t->word->word, r, word_len);
+      r += word_len;
+    }
+
+  *r = '\0';    
+  return (result);
+}
+
+/* Return a single string of all the words present in LIST, separating
+   each word with a space. */
+char *
+string_list (list)
+     WORD_LIST *list;
+{
+  return (string_list_internal (list, " "));
+}
+
+/* Return a single string of all the words present in LIST, obeying the
+   quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
+   expansion [of $*] appears within a double quoted string, it expands
+   to a single field with the value of each parameter separated by the
+   first character of the IFS variable, or by a <space> if IFS is unset." */
+char *
+string_list_dollar_star (list)
+     WORD_LIST *list;
+{
+  char *ifs = get_string_value ("IFS");
+  char sep[2];
+
+  if (!ifs)
+    sep[0] = ' ';
+  else if (!*ifs)
+    sep[0] = '\0';
+  else
+    sep[0] = *ifs;
+
+  sep[1] = '\0';
+
+  return (string_list_internal (list, sep));
+}
+
+/* Return the list of words present in STRING.  Separate the string into
+   words at any of the characters found in SEPARATORS.  If QUOTED is
+   non-zero then word in the list will have its quoted flag set, otherwise
+   the quoted flag is left as make_word () deemed fit.
+
+   This obeys the P1003.2 word splitting semantics.  If `separators' is
+   exactly <space><tab><newline>, then the splitting algorithm is that of
+   the Bourne shell, which treats any sequence of characters from `separators'
+   as a delimiter.  If IFS is unset, which results in `separators' being set
+   to "", no splitting occurs.  If separators has some other value, the
+   following rules are applied (`IFS white space' means zero or more
+   occurrences of <space>, <tab>, or <newline>, as long as those characters
+   are in `separators'):
+
+       1) IFS white space is ignored at the start and the end of the
+          string.
+       2) Each occurrence of a character in `separators' that is not
+          IFS white space, along with any adjacent occurrences of
+          IFS white space delimits a field.
+       3) Any nonzero-length sequence of IFS white space delimits a field.
+   */
+
+/* BEWARE!  list_string strips null arguments.  Don't call it twice and
+   expect to have "" preserved! */
+
+/* Is the first character of STRING a quoted NULL character? */
+#define QUOTED_NULL(string) ((string)[0] == CTLNUL && (string)[1] == '\0')
+
+/* 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 () simply
+   turns STRING into an empty string iff it only consists of a quoted null. */
+/*
+#define remove_quoted_nulls(string) \
+  do { if (QUOTED_NULL (string)) string[0] ='\0'; } while (0)
+*/
+static void
+remove_quoted_nulls (string)
+     char *string;
+{
+  char *nstr, *s, *p;
+
+  nstr = savestring (string);
+  nstr[0] = '\0';
+  for (p = nstr, s = string; *s; s++)
+    {
+      if (*s == CTLESC)
+       {
+         *p++ = *s++;  /* CTLESC */
+         if (*s == 0)
+           break;
+         *p++ = *s;    /* quoted char */
+         continue;
+       }
+      if (*s == CTLNUL)
+       continue;
+      *p++ = *s;
+    }
+  *p = '\0';
+  strcpy (string, nstr);
+  free (nstr);
+}
+
+/* Perform quoted null character removal on each element of LIST.
+   This modifies LIST. */
+void
+word_list_remove_quoted_nulls (list)
+     WORD_LIST *list;
+{
+  register WORD_LIST *t;
+
+  t = list;
+
+  while (t)
+    {
+      remove_quoted_nulls (t->word->word);
+      t = t->next;
+    }
+}
+
+/* This performs word splitting and quoted null character removal on
+   STRING. */
+
+#define issep(c)       (member ((c), separators))
+
+WORD_LIST *
+list_string (string, separators, quoted)
+     register char *string, *separators;
+     int quoted;
+{
+  WORD_LIST *result = (WORD_LIST *)NULL;
+  char *current_word = (char *)NULL, *s;
+  int sindex = 0;
+  int sh_style_split;
+
+  if (!string || !*string)
+    return ((WORD_LIST *)NULL);
+
+  sh_style_split =
+    separators && *separators && (STREQ (separators, " \t\n"));
+
+  /* Remove sequences of whitespace at the beginning of STRING, as
+     long as those characters appear in IFS.  Do not do this if
+     STRING is quoted or if there are no separator characters. */
+  if (!quoted || !separators || !*separators)
+    {
+      for (s = string; *s && spctabnl (*s) && issep (*s); s++);
+
+      if (!*s)
+       return ((WORD_LIST *)NULL);
+
+      string = s;
+    }
+
+  /* OK, now STRING points to a word that does not begin with white space.
+     The splitting algorithm is:
+       extract a word, stopping at a separator
+       skip sequences of spc, tab, or nl as long as they are separators
+     This obeys the field splitting rules in Posix.2. */
+
+  while (string[sindex])
+    {
+      current_word = string_extract_verbatim (string, &sindex, separators);
+      if (!current_word)
+       break;
+
+      /* If we have a quoted empty string, add a quoted null argument.  We
+        want to preserve the quoted null character iff this is a quoted
+        empty string; otherwise the quoted null characters are removed
+        below. */
+      if (QUOTED_NULL (current_word))
+       {
+         WORD_DESC *t = make_word (" ");
+         t->quoted++;
+         free (t->word);
+         t->word = make_quoted_char ('\0');
+         result = make_word_list (t, result);
+       }
+      else if (strlen (current_word))
+       {
+         /* If we have something, then add it regardless.  However,
+            perform quoted null character removal on the current word. */
+         remove_quoted_nulls (current_word);
+         result = make_word_list (make_word (current_word), result);
+         if (quoted)
+           result->word->quoted = 1;
+       }
+
+      /* If we're not doing sequences of separators in the traditional
+        Bourne shell style, then add a quoted null argument. */
+
+      else if (!sh_style_split && !spctabnl (string[sindex]))
+       {
+         result = make_word_list (make_word (""), result);
+         result->word->quoted = 1;
+       }
+
+      free (current_word);
+
+      /* Move past the current separator character. */
+      if (string[sindex])
+       sindex++;
+
+      /* Now skip sequences of space, tab, or newline characters if they are
+        in the list of separators. */
+      while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
+       sindex++;
+
+    }
+  return (REVERSE_LIST (result, WORD_LIST *));
+}
+
+/* Parse a single word from STRING, using SEPARATORS to separate fields.
+   ENDPTR is set to the first character after the word.  This is used by
+   the `read' builtin.
+   XXX - this function is very similar to list_string; they should be
+        combined - XXX */
+char *
+get_word_from_string (stringp, separators, endptr)
+     char **stringp, *separators, **endptr;
+{
+  register char *s;
+  char *current_word;
+  int sindex, sh_style_split;
+
+  if (!stringp || !*stringp || !**stringp)
+    return ((char *)NULL);
+    
+  s = *stringp;
+
+  sh_style_split =
+    separators && *separators && (STREQ (separators, " \t\n"));
+
+  /* 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++);
+
+      /* If the string is nothing but whitespace, update it and return. */
+      if (!*s)
+       {
+         *stringp = s;
+         if (endptr)
+           *endptr = s;
+         return ((char *)NULL);
+       }
+    }
+
+  /* OK, S points to a word that does not begin with white space.
+     Now extract a word, stopping at a separator, save a pointer to
+     the first character after the word, then skip sequences of spc,
+     tab, or nl as long as they are separators.
+     
+     This obeys the field splitting rules in Posix.2. */
+  sindex = 0;
+  current_word = string_extract_verbatim (s, &sindex, separators);
+
+  /* Set ENDPTR to the first character after the end of the word. */
+  if (endptr)
+    *endptr = s + sindex;
+
+  /* Move past the current separator character. */
+  if (s[sindex])
+    sindex++;
+
+  /* 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]))
+    sindex++;
+
+  /* Update STRING to point to the next field. */
+  *stringp = s + sindex;
+  return (current_word);
+}
+
+/* Remove IFS white space at the end of STRING.  Start at the end
+   of the string and walk backwards until the beginning of the string
+   or we find a character that's not IFS white space and not CTLESC.
+   Only let CTLESC escape a white space character if SAW_ESCAPE is
+   non-zero.  */
+char *
+strip_trailing_ifs_whitespace (string, separators, saw_escape)
+     char *string, *separators;
+     int saw_escape;
+{
+  char *s;
+  
+  s = string + STRLEN (string) - 1;
+  while (s > string && ((spctabnl (*s) && issep (*s)) ||
+                       (saw_escape && *s == CTLESC && spctabnl (s[1]))))
+    s--;
+  *++s = '\0';
+  return string;
+}
+
+#if defined (PROCESS_SUBSTITUTION)
+#define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC)
+#else
+#define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC)
+#endif
+
+/* If there are any characters in STRING that require full expansion,
+   then call FUNC to expand STRING; otherwise just perform quote
+   removal if necessary.  This returns a new string. */
+static char *
+maybe_expand_string (string, quoted, func)
+     char *string;
+     int quoted;
+     WORD_LIST *(*func)();
+{
+  WORD_LIST *list;
+  int i, saw_quote;
+  char *ret;
+     
+  for (i = saw_quote = 0; string[i]; i++)
+    {
+      if (EXP_CHAR (string[i]))
+       break;
+      else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
+       saw_quote = 1;
+    }
+
+  if (string[i])
+    {    
+      list = (*func) (string, quoted);
+      if (list)
+       {
+         ret = string_list (list);
+         dispose_words (list);
+       }
+      else
+       ret = (char *)NULL;
+    }
+  else if (saw_quote && !quoted)
+    ret = string_quote_removal (string, quoted);
+  else
+    ret = savestring (string);
+  return ret;
+}
+
+/* Given STRING, an assignment string, get the value of the right side
+   of the `=', and bind it to the left side.  If EXPAND is true, then
+   perform parameter expansion, command substitution, and arithmetic
+   expansion on the right-hand side.  Perform tilde expansion in any
+   case.  Do not perform word splitting on the result of expansion. */
+static int
+do_assignment_internal (string, expand)
+     char *string;
+     int expand;
+{
+  int offset = assignment (string);
+  char *name = savestring (string);
+  char *value = (char *)NULL;
+  SHELL_VAR *entry = (SHELL_VAR *)NULL;
+
+  if (name[offset] == '=')
+    {
+      char *temp;
+
+      name[offset] = 0;
+      temp = name + offset + 1;
+
+      if (expand && temp[0])
+       {
+         if (strchr (temp, '~') && unquoted_member ('~', temp))
+           temp = tilde_expand (temp);
+         else
+           temp = savestring (temp);
+
+         value = maybe_expand_string (temp, 0, expand_string_unsplit);
+         free (temp);
+       }
+      else
+       value = savestring (temp);
+    }
+
+  if (value == 0)
+    value = savestring ("");
+
+  entry = bind_variable (name, value);
+
+  if (echo_command_at_execute)
+    fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
+
+  stupidly_hack_special_variables (name);
+
+  if (entry)
+    entry->attributes &= ~att_invisible;
+
+  FREE (value);
+  free (name);
+
+  /* Return 1 if the assignment seems to have been performed correctly. */
+  return (entry ? ((entry->attributes & att_readonly) == 0) : 0);
+}
+
+/* Perform the assignment statement in STRING, and expand the
+   right side by doing command and parameter expansion. */
+do_assignment (string)
+     char *string;
+{
+  return do_assignment_internal (string, 1);
+}
+
+/* Given STRING, an assignment string, get the value of the right side
+   of the `=', and bind it to the left side.  Do not do command and
+   parameter substitution on the right hand side. */
+do_assignment_no_expand (string)
+     char *string;
+{
+  return do_assignment_internal (string, 0);
+}
+
+/* Most of the substitutions must be done in parallel.  In order
+   to avoid using tons of unclear goto's, I have some functions
+   for manipulating malloc'ed strings.  They all take INDX, a
+   pointer to an integer which is the offset into the string
+   where manipulation is taking place.  They also take SIZE, a
+   pointer to an integer which is the current length of the
+   character array for this string. */
+
+/* Append SOURCE to TARGET at INDEX.  SIZE is the current amount
+   of space allocated to TARGET.  SOURCE can be NULL, in which
+   case nothing happens.  Gets rid of SOURCE by free ()ing it.
+   Returns TARGET in case the location has changed. */
+inline char *
+sub_append_string (source, target, indx, size)
+     char *source, *target;
+     int *indx, *size;
+{
+  if (source)
+    {
+      int srclen, n;
+
+      srclen = strlen (source);
+      if (srclen >= (int)(*size - *indx))
+       {
+         n = srclen + *indx;
+         n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
+         target = xrealloc (target, (*size = n));
+       }
+
+      FASTCOPY (source, target + *indx, srclen);
+      *indx += srclen;
+      target[*indx] = '\0';
+
+      free (source);
+    }
+  return (target);
+}
+
+/* Append the textual representation of NUMBER to TARGET.
+   INDX and SIZE are as in SUB_APPEND_STRING. */
+char *
+sub_append_number (number, target, indx, size)
+     int number, *indx, *size;
+     char *target;
+{
+  char *temp;
+
+  temp = itos (number);
+  return (sub_append_string (temp, target, indx, size));
+}
+
+/* Return the word list that corresponds to `$*'. */
+WORD_LIST *
+list_rest_of_args ()
+{
+  register WORD_LIST *list = (WORD_LIST *)NULL;
+  register WORD_LIST *args = rest_of_args;
+  int i;
+
+  /* Break out of the loop as soon as one of the dollar variables is null. */
+  for (i = 1; i < 10 && dollar_vars[i]; i++)
+    list = make_word_list (make_word (dollar_vars[i]), list);
+
+  while (args)
+    {
+      list = make_word_list (make_word (args->word->word), list);
+      args = args->next;
+    }
+  return (REVERSE_LIST (list, WORD_LIST *));
+}
+
+/* Make a single large string out of the dollar digit variables,
+   and the rest_of_args.  If DOLLAR_STAR is 1, then obey the special
+   case of "$*" with respect to IFS. */
+char *
+string_rest_of_args (dollar_star)
+     int dollar_star;
+{
+  register WORD_LIST *list = list_rest_of_args ();
+  char *string;
+
+  string = dollar_star ? string_list_dollar_star (list) : string_list (list);
+  dispose_words (list);
+  return (string);
+}
+
+/***************************************************
+ *                                                *
+ *        Functions to Expand a String            *
+ *                                                *
+ ***************************************************/
+/* Call expand_word_internal to expand W and handle error returns.
+   A convenience function for functions that don't want to handle
+   any errors or free any memory before aborting. */
+static WORD_LIST *
+call_expand_word_internal (w, q, c, e)
+     WORD_DESC *w;
+     int q, *c, *e;
+{
+  WORD_LIST *result;
+
+  result = expand_word_internal (w, q, c, e);
+  if (result == &expand_word_error)
+    longjmp (top_level, DISCARD);
+  else if (result == &expand_word_fatal)
+    longjmp (top_level, FORCE_EOF);
+  else
+    return (result);
+}
+
+/* Perform parameter expansion, command substitution, and arithmetic
+   expansion on STRING, as if it were a word.  Leave the result quoted. */
+static WORD_LIST *
+expand_string_internal (string, quoted)
+     char *string;
+     int quoted;
+{
+  WORD_DESC td;
+  WORD_LIST *tresult;
+
+  if (!string || !*string)
+    return ((WORD_LIST *)NULL);
+
+  bzero (&td, sizeof (td));
+  td.word = string;
+  tresult = call_expand_word_internal (&td, quoted, (int *)NULL, (int *)NULL);
+  return (tresult);
+}
+
+/* Expand STRING by performing parameter expansion, command substitution,
+   and arithmetic expansion.  Dequote the resulting WORD_LIST before
+   returning it, but do not perform word splitting.  The call to
+   remove_quoted_nulls () is in here because word splitting normally
+   takes care of quote removal. */
+WORD_LIST *
+expand_string_unsplit (string, quoted)
+     char *string;
+     int quoted;
+{
+  WORD_LIST *value;
+
+  if (!string || !*string)
+    return ((WORD_LIST *)NULL);
+
+  value = expand_string_internal (string, quoted);
+  if (value)
+    {
+      if (value->word)
+       remove_quoted_nulls (value->word->word);
+      dequote_list (value);
+    }
+  return (value);
+}
+
+/* This does not perform word splitting or dequote the WORD_LIST
+   it returns. */
+static WORD_LIST *
+expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
+     char *string;
+     int quoted, *dollar_at_p, *has_dollar_at;
+{
+  WORD_DESC td;
+  WORD_LIST *tresult;
+
+  if (string == 0 || *string == '\0')
+    return (WORD_LIST *)NULL;
+     
+  bzero (&td, sizeof (td));
+  td.word = string; 
+  tresult = call_expand_word_internal (&td, quoted, dollar_at_p, has_dollar_at);
+  return (tresult);
+}
+
+/* Expand STRING just as if you were expanding a word, but do not dequote
+   the resultant WORD_LIST.  This is called only from within this file,
+   and is used to correctly preserve quoted characters when expanding
+   things like ${1+"$@"}.  This does parameter expansion, command
+   subsitution, arithmetic expansion, and word splitting. */
+static WORD_LIST *
+expand_string_leave_quoted (string, quoted)
+     char *string;
+     int quoted;
+{
+  WORD_LIST *tlist;
+  WORD_LIST *tresult;
+
+  if (!string || !*string)
+    return ((WORD_LIST *)NULL);
+
+  tlist = expand_string_internal (string, quoted);
+
+  if (tlist)
+    {
+      tresult = word_list_split (tlist);
+      dispose_words (tlist);
+      return (tresult);
+    }
+  return ((WORD_LIST *)NULL);
+}
+
+/* Expand STRING just as if you were expanding a word.  This also returns
+   a list of words.  Note that filename globbing is *NOT* done for word
+   or string expansion, just when the shell is expanding a command.  This
+   does parameter expansion, command substitution, arithmetic expansion,
+   and word splitting.  Dequote the resultant WORD_LIST before returning. */
+WORD_LIST *
+expand_string (string, quoted)
+     char *string;
+     int quoted;
+{
+  WORD_LIST *result;
+
+  if (!string || !*string)
+    return ((WORD_LIST *)NULL);
+
+  result = expand_string_leave_quoted (string, quoted);
+
+  if (result)
+    dequote_list (result);
+  return (result);
+}
+
+/***************************************************
+ *                                                *
+ *     Functions to handle quoting chars          *
+ *                                                *
+ ***************************************************/
+
+/* I'm going to have to rewrite expansion because filename globbing is
+   beginning to make the entire arrangement ugly.  I'll do this soon. */
+static void
+dequote_list (list)
+     register WORD_LIST *list;
+{
+  register char *s;
+
+  while (list)
+    {
+      s = dequote_string (list->word->word);
+      free (list->word->word);
+      list->word->word = s;
+      list = list->next;
+    }
+}
+
+static char *
+make_quoted_char (c)
+     int c;
+{
+  char *temp;
+
+  temp = xmalloc (3);
+  if (c == 0)
+    {
+      temp[0] = CTLNUL;
+      temp[1] = '\0';
+    }
+  else
+    {
+      temp[0] = CTLESC;
+      temp[1] = c;
+      temp[2] = '\0';
+    }
+  return (temp);
+}
+
+/* Quote STRING.  Return a new string. */
+static char *
+quote_string (string)
+     char *string;
+{
+  char *result;
+
+  if (!*string)
+    {
+      result = xmalloc (2);
+      result[0] = CTLNUL;
+      result[1] = '\0';
+    }
+  else
+    {
+      register char *t;
+
+      result = xmalloc ((strlen (string) * 2) + 1);
+
+      for (t = result; string && *string; )
+       {
+         *t++ = CTLESC;
+         *t++ = *string++;
+       }
+      *t = '\0';
+    }
+  return (result);
+}
+
+/* De-quoted quoted characters in STRING. */
+char *
+dequote_string (string)
+     char *string;
+{
+  register char *t;
+  char *result;
+
+  result = xmalloc (strlen (string) + 1);
+
+  if (QUOTED_NULL (string))
+    {
+      result[0] = '\0';
+      return (result);
+    }
+
+  /* If no character in the string can be quoted, don't bother examining
+     each character.  Just return a copy of the string passed to us. */
+  if (strchr (string, CTLESC) == NULL)         /* XXX */
+    {                                          /* XXX */
+      strcpy (result, string);                 /* XXX */
+      return (result);                         /* XXX */
+    }
+
+  for (t = result; string && *string; string++)
+    {
+      if (*string == CTLESC)
+       {
+         string++;
+
+         if (!*string)
+           break;
+       }
+
+      *t++ = *string;
+    }
+
+  *t = '\0';
+  return (result);
+}
+
+/* Quote the entire WORD_LIST list. */
+static void
+quote_list (list)
+     WORD_LIST *list;
+{
+  register WORD_LIST *w;
+
+  for (w = list; w; w = w->next)
+    {
+      char *t = w->word->word;
+      w->word->word = quote_string (t);
+      free (t);
+      w->word->quoted = 1;
+    }
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                 Functions for Removing Patterns                 */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Remove the portion of PARAM matched by PATTERN according to OP, where OP
+   can have one of 4 values:
+       RP_LONG_LEFT    remove longest matching portion at start of PARAM
+       RP_SHORT_LEFT   remove shortest matching portion at start of PARAM
+       RP_LONG_RIGHT   remove longest matching portion at end of PARAM
+       RP_SHORT_RIGHT  remove shortest matching portion at end of PARAM
+*/
+
+#define RP_LONG_LEFT   1
+#define RP_SHORT_LEFT  2
+#define RP_LONG_RIGHT  3
+#define RP_SHORT_RIGHT 4
+
+static char *
+remove_pattern (param, pattern, op)
+     char *param, *pattern;
+     int op;
+{
+  register int len = param ? strlen (param) : 0;
+  register char *end = param + len;
+  register char *p, *ret, c;
+
+  if (pattern == NULL || *pattern == '\0')     /* minor optimization */
+    return (savestring (param));
+
+  if (param == NULL || *param == '\0')
+    return (param);
+
+  switch (op)
+    {
+      case RP_LONG_LEFT:       /* remove longest match at start */
+       for (p = end; p >= param; p--)
+         {
+           c = *p; *p = '\0';
+           if (fnmatch (pattern, param, 0) != FNM_NOMATCH)
+             {
+               *p = c;
+               return (savestring (p));
+             }
+           *p = c;
+         }
+       break;
+
+      case RP_SHORT_LEFT:      /* remove shortest match at start */
+       for (p = param; p <= end; p++)
+         {
+           c = *p; *p = '\0';
+           if (fnmatch (pattern, param, 0) != FNM_NOMATCH)
+             {
+               *p = c;
+               return (savestring (p));
+             }
+           *p = c;
+         }
+       break;
+
+      case RP_LONG_RIGHT:      /* remove longest match at end */
+       for (p = param; p <= end; p++)
+         {
+           if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
+             {
+               c = *p;
+               *p = '\0';
+               ret = savestring (param);
+               *p = c;
+               return (ret);
+             }
+         }
+       break;
+
+      case RP_SHORT_RIGHT:     /* remove shortest match at end */
+       for (p = end; p >= param; p--)
+         {
+           if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
+             {
+               c = *p;
+               *p = '\0';
+               ret = savestring (param);
+               *p = c;
+               return (ret);
+             }
+         }
+       break;
+    }
+  return (savestring (param)); /* no match, return original string */
+}
+
+/*******************************************
+ *                                        *
+ *     Functions to expand WORD_DESCs     *
+ *                                        *
+ *******************************************/
+
+/* Expand WORD, performing word splitting on the result.  This does
+   parameter expansion, command substitution, arithmetic expansion,
+   word splitting, and quote removal. */
+
+WORD_LIST *
+expand_word (word, quoted)
+     WORD_DESC *word;
+     int quoted;
+{
+  WORD_LIST *result, *tresult;
+
+  tresult = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
+  result = word_list_split (tresult);
+  dispose_words (tresult);
+  if (result)
+    dequote_list (result);
+  return (result);
+}
+
+/* Expand WORD, but do not perform word splitting on the result.  This
+   does parameter expansion, command substitution, arithmetic expansion,
+   and quote removal. */
+WORD_LIST *
+expand_word_no_split (word, quoted)
+     WORD_DESC *word;
+     int quoted;
+{
+  WORD_LIST *result;
+
+  result = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
+  if (result)
+    dequote_list (result);
+  return (result);
+}
+
+/* Perform shell expansions on WORD, but do not perform word splitting or
+   quote removal on the result. */
+WORD_LIST *
+expand_word_leave_quoted (word, quoted)
+     WORD_DESC *word;
+     int quoted;
+{
+  WORD_LIST *result;
+
+  result = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
+  return (result);
+}
+
+/* Return the value of a positional parameter.  This handles values > 10. */
+char *
+get_dollar_var_value (ind)
+     int ind;
+{
+  char *temp;
+
+  if (ind < 10)
+    {
+      if (dollar_vars[ind])
+       temp = savestring (dollar_vars[ind]);
+      else
+       temp = (char *)NULL;
+    }
+  else /* We want something like ${11} */
+    {
+      WORD_LIST *p = rest_of_args;
+
+      ind -= 10;
+      while (p && ind--)
+       p = p->next;
+      if (p)
+       temp = savestring (p->word->word);
+      else
+       temp = (char *)NULL;
+    }
+  return (temp);
+}
+
+#if defined (PROCESS_SUBSTITUTION)
+
+/* **************************************************************** */
+/*                                                               */
+/*                 Hacking Process Substitution                    */
+/*                                                               */
+/* **************************************************************** */
+
+extern struct fd_bitmap *current_fds_to_close;
+extern char *mktemp ();
+
+#if !defined (HAVE_DEV_FD)
+/* Named pipes must be removed explicitly with `unlink'.  This keeps a list
+   of FIFOs the shell has open.  unlink_fifo_list will walk the list and
+   unlink all of them. add_fifo_list adds the name of an open FIFO to the
+   list.  NFIFO is a count of the number of FIFOs in the list. */
+#define FIFO_INCR 20
+
+static char **fifo_list = (char **)NULL;
+static int nfifo = 0;
+static int fifo_list_size = 0;
+
+static void
+add_fifo_list (pathname)
+     char *pathname;
+{
+  if (nfifo >= fifo_list_size - 1)
+    {
+      fifo_list_size += FIFO_INCR;
+      fifo_list = (char **)xrealloc (fifo_list,
+                                    fifo_list_size * sizeof (char *));
+    }
+
+  fifo_list[nfifo++] = savestring (pathname);
+}
+
+void
+unlink_fifo_list ()
+{
+  if (!nfifo)
+    return;
+
+  while (nfifo--)
+    {
+      unlink (fifo_list[nfifo]);
+      free (fifo_list[nfifo]);
+      fifo_list[nfifo] = (char *)NULL;
+    }
+  nfifo = 0;
+}
+
+static char *
+make_named_pipe ()
+{
+  char *tname;
+
+  tname = mktemp (savestring ("/tmp/sh-np-XXXXXX"));
+  if (mkfifo (tname, 0600) < 0)
+    {
+      free (tname);
+      return ((char *)NULL);
+    }
+
+  add_fifo_list (tname);
+  return (tname);
+}
+
+#if !defined (_POSIX_VERSION)
+int
+mkfifo (path, mode)
+     char *path;
+     int mode;
+{
+#if defined (S_IFIFO)
+  return (mknod (path, (mode | S_IFIFO), 0));
+#else /* !S_IFIFO */
+  return (-1);
+#endif /* !S_IFIFO */
+}
+#endif /* !_POSIX_VERSION */
+
+#else /* HAVE_DEV_FD */
+
+/* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
+   has open to children.  NFDS is a count of the number of bits currently
+   set in DEV_FD_LIST.  TOTFDS is a count of the highest possible number
+   of open files. */
+static char *dev_fd_list = (char *)NULL;
+static int nfds = 0;
+static int totfds;     /* The highest possible number of open files. */
+
+static void
+add_fifo_list (fd)
+     int fd;
+{
+  if (!dev_fd_list || fd >= totfds)
+    {
+      int ofds;
+
+      ofds = totfds;
+      totfds = getdtablesize ();
+      if (totfds < 0 || totfds > 256)
+       totfds = 256;
+      if (fd > totfds)
+       totfds = fd + 2;
+
+      dev_fd_list = xrealloc (dev_fd_list, totfds);
+      bzero (dev_fd_list + ofds, totfds - ofds);
+    }
+
+  dev_fd_list[fd] = 1;
+  nfds++;
+}
+
+void
+unlink_fifo_list ()
+{
+  register int i;
+
+  if (!nfds)
+    return;
+
+  for (i = 0; nfds && i < totfds; i++)
+    if (dev_fd_list[i])
+      {
+       close (i);
+       dev_fd_list[i] = 0;
+       nfds--;
+      }
+
+  nfds = 0;
+}
+
+#if defined (NOTDEF)
+print_dev_fd_list ()
+{
+  register int i;
+
+  fprintf (stderr, "pid %d: dev_fd_list:", getpid ());
+  fflush (stderr);
+
+  for (i = 0; i < totfds; i++)
+    {
+      if (dev_fd_list[i])
+       fprintf (stderr, " %d", i);
+    }
+  fprintf (stderr, "\n");
+}
+#endif /* NOTDEF */
+
+static char *
+make_dev_fd_filename (fd)
+     int fd;
+{
+  char *ret;
+
+  ret = xmalloc (16 * sizeof (char));
+  sprintf (ret, "/dev/fd/%d", fd);
+  add_fifo_list (fd);
+  return (ret);
+}
+
+#endif /* HAVE_DEV_FD */
+
+/* Return a filename that will open a connection to the process defined by
+   executing STRING.  HAVE_DEV_FD, if defined, means open a pipe and return
+   a filename in /dev/fd corresponding to a descriptor that is one of the
+   ends of the pipe.  If not defined, we use named pipes on systems that have
+   them.  Systems without /dev/fd and named pipes are out of luck.
+
+   OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
+   use the read end of the pipe and dup that file descriptor to fd 0 in
+   the child.  If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
+   writing or use the write end of the pipe in the child, and dup that
+   file descriptor to fd 1 in the child.  The parent does the opposite. */
+
+static char *
+process_substitute (string, open_for_read_in_child)
+     char *string;
+     int open_for_read_in_child;
+{
+  char *pathname;
+  int fd, result;
+  pid_t old_pid, pid;
+#if defined (HAVE_DEV_FD)
+  int parent_pipe_fd, child_pipe_fd;
+  int fildes[2];
+#endif /* HAVE_DEV_FD */
+#if defined (JOB_CONTROL)
+  pid_t old_pipeline_pgrp;
+#endif  
+
+  if (!string || !*string)
+    return ((char *)NULL);
+
+#if !defined (HAVE_DEV_FD)
+  pathname = make_named_pipe ();
+#else /* HAVE_DEV_FD */
+  if (pipe (fildes) < 0)
+    {
+      internal_error ("can't make pipes for process substitution: %s",
+       strerror (errno));
+      return ((char *)NULL);
+    }
+  /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
+     the pipe in the parent, otherwise the read end. */
+  parent_pipe_fd = fildes[open_for_read_in_child];
+  child_pipe_fd = fildes[1 - open_for_read_in_child];
+  pathname = make_dev_fd_filename (parent_pipe_fd);
+#endif /* HAVE_DEV_FD */
+
+  if (!pathname)
+    {
+      internal_error ("cannot make pipe for process subsitution: %s",
+       strerror (errno));
+      return ((char *)NULL);
+    }
+
+  old_pid = last_made_pid;
+
+#if defined (JOB_CONTROL)
+  old_pipeline_pgrp = pipeline_pgrp;
+  pipeline_pgrp = shell_pgrp;
+  cleanup_the_pipeline ();
+  pid = make_child ((char *)NULL, 1);
+  if (pid == 0)
+    {
+      /* Cancel traps, in trap.c. */
+      restore_original_signals ();
+      setup_async_signals ();
+      subshell_environment++;
+    }
+  set_sigchld_handler ();
+  stop_making_children ();
+  pipeline_pgrp = old_pipeline_pgrp;
+#else /* !JOB_CONTROL */
+  pid = make_child ((char *)NULL, 1);
+  if (pid == 0)
+    {
+      /* Cancel traps, in trap.c. */
+      restore_original_signals ();
+      setup_async_signals ();
+      subshell_environment++;
+    }
+#endif /* !JOB_CONTROL */
+
+  if (pid < 0)
+    {
+      internal_error ("cannot make a child for process substitution: %s",
+       strerror (errno));
+      free (pathname);
+#if defined (HAVE_DEV_FD)
+      close (parent_pipe_fd);
+      close (child_pipe_fd);
+#endif /* HAVE_DEV_FD */
+      return ((char *)NULL);
+    }
+
+  if (pid > 0)
+    {
+      last_made_pid = old_pid;
+
+#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
+      close_pgrp_pipe ();
+#endif /* JOB_CONTROL && PGRP_PIPE */
+
+#if defined (HAVE_DEV_FD)
+      close (child_pipe_fd);
+#endif /* HAVE_DEV_FD */
+
+      return (pathname);
+    }
+
+  set_sigint_handler ();
+
+#if defined (JOB_CONTROL)
+  set_job_control (0);
+#endif /* JOB_CONTROL */
+
+#if !defined (HAVE_DEV_FD)
+  /* Open the named pipe in the child. */
+  fd = open (pathname, open_for_read_in_child ? O_RDONLY : O_WRONLY);
+  if (fd < 0)
+    {
+      internal_error ("cannot open named pipe %s for %s: %s", pathname,
+       open_for_read_in_child ? "reading" : "writing", strerror (errno));
+      exit (127);
+    }
+#else /* HAVE_DEV_FD */
+  fd = child_pipe_fd;
+#endif /* HAVE_DEV_FD */
+
+  if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
+    {
+      internal_error ("cannot duplicate named pipe %s as fd %d: %s",
+       pathname, open_for_read_in_child ? 0 : 1, strerror (errno));
+      exit (127);
+    }
+
+  close (fd);
+
+  /* Need to close any files that this process has open to pipes inherited
+     from its parent. */
+  if (current_fds_to_close)
+    {
+      close_fd_bitmap (current_fds_to_close);
+      current_fds_to_close = (struct fd_bitmap *)NULL;
+    }
+
+#if defined (HAVE_DEV_FD)
+  /* Make sure we close the parent's end of the pipe and clear the slot
+     in the fd list so it is not closed later, if reallocated by, for
+     instance, pipe(2). */
+  close (parent_pipe_fd);
+  dev_fd_list[parent_pipe_fd] = 0;
+#endif /* HAVE_DEV_FD */
+
+  result = parse_and_execute (string, "process substitution", 0);
+
+#if !defined (HAVE_DEV_FD)
+  /* Make sure we close the named pipe in the child before we exit. */
+  close (open_for_read_in_child ? 0 : 1);
+#endif /* !HAVE_DEV_FD */
+
+  exit (result);
+  /*NOTREACHED*/
+}
+#endif /* PROCESS_SUBSTITUTION */
+
+/* Perform command substitution on STRING.  This returns a string,
+   possibly quoted. */
+static char *
+command_substitute (string, quoted)
+     char *string;
+     int quoted;
+{
+  pid_t pid, old_pid;
+  int fildes[2];
+  char *istring = (char *)NULL;
+  int istring_index, istring_size, c = 1;
+  int result;
+
+  istring_index = istring_size = 0;
+
+  /* Don't fork () if there is no need to.  In the case of no command to
+     run, just return NULL. */
+  if (!string || !*string || (string[0] == '\n' && !string[1]))
+    return ((char *)NULL);
+
+  /* Pipe the output of executing STRING into the current shell. */
+  if (pipe (fildes) < 0)
+    {
+      internal_error ("Can't make pipes for command substitution!");
+      goto error_exit;
+    }
+
+  old_pid = last_made_pid;
+#if defined (JOB_CONTROL)
+  {
+    pid_t old_pipeline_pgrp = pipeline_pgrp;
+
+    pipeline_pgrp = shell_pgrp;
+    cleanup_the_pipeline ();
+    pid = make_child ((char *)NULL, 0);
+    if (pid == 0)
+      /* Reset the signal handlers in the child, but don't free the
+        trap strings. */
+      reset_signal_handlers ();
+    set_sigchld_handler ();
+    stop_making_children ();
+    pipeline_pgrp = old_pipeline_pgrp;
+  }
+#else /* !JOB_CONTROL */
+  pid = make_child ((char *)NULL, 0);
+
+  if (pid == 0)
+    /* Reset the signal handlers in the child, but don't free the
+       trap strings. */
+    reset_signal_handlers ();
+#endif /* !JOB_CONTROL */
+
+  if (pid < 0)
+    {
+      internal_error ("Can't make a child for command substitution: %s",
+       strerror (errno));
+    error_exit:
+
+      FREE (istring);
+      close (fildes[0]);
+      close (fildes[1]);
+      return ((char *)NULL);
+    }
+
+  if (pid == 0)
+    {
+      set_sigint_handler ();   /* XXX */
+#if defined (JOB_CONTROL)
+      set_job_control (0);
+#endif
+      if (dup2 (fildes[1], 1) < 0)
+       {
+         internal_error
+           ("command_substitute: cannot duplicate pipe as fd 1: %s",
+            strerror (errno));
+         exit (EXECUTION_FAILURE);
+       }
+
+      /* If standard output is closed in the parent shell
+        (such as after `exec >&-'), file descriptor 1 will be
+        the lowest available file descriptor, and end up in
+        fildes[0].  This can happen for stdin and stderr as well,
+        but stdout is more important -- it will cause no output
+        to be generated from this command. */
+      if ((fildes[1] != fileno (stdin)) &&
+         (fildes[1] != fileno (stdout)) &&
+         (fildes[1] != fileno (stderr)))
+       close (fildes[1]);
+
+      if ((fildes[0] != fileno (stdin)) &&
+         (fildes[0] != fileno (stdout)) &&
+         (fildes[0] != fileno (stderr)))
+       close (fildes[0]);
+
+      /* The currently executing shell is not interactive. */
+      interactive = 0;
+
+      /* Command substitution does not inherit the -e flag. */
+      exit_immediately_on_error = 0;
+
+      remove_quoted_escapes (string);
+
+      /* Give command substitution a place to jump back to on failure,
+        so we don't go back up to main (). */
+      result = setjmp (top_level);
+
+      if (result == EXITPROG)
+       exit (last_command_exit_value);
+      else if (result)
+       exit (EXECUTION_FAILURE);
+      else
+       exit (parse_and_execute (string, "command substitution", -1));
+    }
+  else
+    {
+      FILE *istream;
+
+      istream = fdopen (fildes[0], "r");
+
+#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
+      close_pgrp_pipe ();
+#endif /* JOB_CONTROL && PGRP_PIPE */
+
+      close (fildes[1]);
+
+      if (!istream)
+       {
+         internal_error ("Can't reopen pipe to command substitution (fd %d): %s",
+                       fildes[0], strerror (errno));
+         goto error_exit;
+       }
+
+      /* Read the output of the command through the pipe. */
+      while (1)
+       {
+#if defined (NO_READ_RESTART_ON_SIGNAL)
+         c = getc_with_restart (istream);
+#else
+         c = getc (istream);
+#endif /* !NO_READ_RESTART_ON_SIGNAL */
+
+         if (c == EOF)
+           break;
+
+         /* Add the character to ISTRING. */
+         if (istring_index + 2 >= istring_size)
+           {
+             while (istring_index + 2 >= istring_size)
+               istring_size += DEFAULT_ARRAY_SIZE;
+             istring = xrealloc (istring, istring_size);
+           }
+
+         if (quoted || c == CTLESC || c == CTLNUL)
+           istring[istring_index++] = CTLESC;
+
+         istring[istring_index++] = c;
+         istring[istring_index] = '\0';
+       }
+
+      fclose (istream);
+      close (fildes[0]);
+
+      last_command_exit_value = wait_for (pid);
+      last_command_subst_pid = pid;
+      last_made_pid = old_pid;
+
+#if defined (JOB_CONTROL)
+      /* If last_command_exit_value > 128, then the substituted command
+        was terminated by a signal.  If that signal was SIGINT, then send
+        SIGINT to ourselves.  This will break out of loops, for instance. */
+      if (last_command_exit_value == (128 + SIGINT))
+       kill (getpid (), SIGINT);
+
+      /* wait_for gives the terminal back to shell_pgrp.  If some other
+        process group should have it, give it away to that group here. */
+      if (interactive && pipeline_pgrp != (pid_t)0)
+       give_terminal_to (pipeline_pgrp);
+#endif /* JOB_CONTROL */
+
+      /* If we read no output, just return now and save ourselves some
+        trouble. */
+      if (istring_index == 0)
+       goto error_exit;
+
+      /* Strip trailing newlines from the output of the command. */
+      if (quoted)
+       {
+         while (istring_index > 0)
+           {
+             if (istring[istring_index - 1] == '\n')
+               {
+                 --istring_index;
+
+                 /* If the newline was quoted, remove the quoting char. */
+                 if (istring[istring_index - 1] == CTLESC)
+                   --istring_index;
+               }
+             else
+               break;
+           }
+         istring[istring_index] = '\0';
+       }
+      else
+       strip_trailing (istring, 1);
+
+      return (istring);
+    }
+}
+
+/********************************************************
+ *                                                     *
+ *     Utility functions for parameter expansion       *
+ *                                                     *
+ ********************************************************/
+
+/* 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)
+     char *value, *temp;
+     int c;
+{
+  int pattern_specifier;
+  WORD_LIST *l;
+  char *pattern, *t, *tword;
+
+  if (c == '#')
+    {
+      if (*value == '#')
+       {
+         value++;
+         pattern_specifier = RP_LONG_LEFT;
+       }
+      else
+       pattern_specifier = RP_SHORT_LEFT;
+    }
+  else /* c == '%' */
+    {
+      if (*value == '%')
+       {
+         value++;
+         pattern_specifier = RP_LONG_RIGHT;
+       }
+      else
+       pattern_specifier = RP_SHORT_RIGHT;
+    }
+
+  /* Posix.2 says that the WORD should be run through tilde expansion,
+     parameter expansion, command substitution and arithmetic expansion.
+     This leaves the result quoted, so quote_string_for_globbing () has
+     to be called to fix it up for fnmatch (). */
+  if (strchr (value, '~'))
+    tword = tilde_expand (value);
+  else
+    tword = savestring (value);
+
+  /* expand_string_internal () leaves WORD quoted and does not perform
+     word splitting. */
+  l = expand_string_internal (tword, 0);
+  free (tword);
+  pattern = string_list (l);
+  dispose_words (l);
+
+  if (pattern)
+    {
+      tword = quote_string_for_globbing (pattern, 1);
+      free (pattern);
+      pattern = tword;
+    }
+
+  t = remove_pattern (temp, pattern, pattern_specifier);
+
+  FREE (pattern);
+  return (t);
+}
+
+static int
+valid_brace_expansion_word (name, var_is_special)
+     char *name;
+     int var_is_special;
+{
+  if (digit (*name) && all_digits (name))
+    return 1;
+  else if (var_is_special)
+    return 1;
+  else if (legal_identifier (name))
+    return 1;
+  else
+    return 0;
+}
+/* Parameter expand NAME, and return a new string which is the expansion,
+   or NULL if there was no expansion.
+   VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
+   the shell, e.g., "@", "$", "*", etc.  QUOTED, if non-zero, means that
+   NAME was found inside of a double-quoted expression. */
+static char *
+parameter_brace_expand_word (name, var_is_special, quoted)
+     char *name;
+     int var_is_special, quoted;
+{
+  char *temp = (char *)NULL;
+
+  /* Handle multiple digit arguments, as in ${11}. */
+  if (digit (*name))
+    {
+      int arg_index = atoi (name);
+
+      temp = get_dollar_var_value (arg_index);
+    }
+  else if (var_is_special)      /* ${@} */
+    {
+      char *tt;
+      WORD_LIST *l;
+
+      tt = xmalloc (2 + strlen (name));
+      tt[0] = '$'; tt[1] = '\0';
+      strcpy (tt + 1, name);
+      l = expand_string_leave_quoted (tt, quoted);
+      free (tt);
+      temp = string_list (l);
+      dispose_words (l);
+    }
+  else
+    {
+      SHELL_VAR *var = find_variable (name);
+
+      if (var && !invisible_p (var) && (temp = value_cell (var)))
+       temp = quoted && temp && *temp ? quote_string (temp)
+                                      : quote_escapes (temp);
+    }
+  return (temp);
+}
+
+/* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
+   depending on the value of C, the separating character.  C can be one of
+   "-", "+", or "=". */
+static char *
+parameter_brace_expand_rhs (name, value, c, quoted)
+     char *name, *value;
+     int c, quoted;
+{
+  WORD_LIST *l;
+  char *t, *t1, *temp;
+  int i, lquote, hasdol;
+
+  if (value[0] == '~' ||
+      (strchr (value, '~') && unquoted_substring ("=~", value)))
+    temp = tilde_expand (value);
+  else
+    temp = savestring (value);
+
+  /* This is a hack.  A better fix is coming later. */
+  lquote = 0;
+  if (*temp == '"' && temp[strlen (temp) - 1] == '"')
+    {
+      i = 1;
+      t = string_extract_double_quoted (temp, &i);     /* XXX */
+      free (temp);
+      temp = t;
+      lquote = 1;      /* XXX */
+    }
+  hasdol = 0;
+  /* XXX was quoted not lquote */
+  l = *temp ? expand_string_for_rhs (temp, quoted||lquote, &hasdol, (int *)NULL)
+           : (WORD_LIST *)NULL;
+  free (temp);
+  /* expand_string_for_rhs does not dequote the word list it returns, but
+     there are a few cases in which we need to add quotes. */
+  if (lquote && quoted == 0 && hasdol == 0 && l && l->word->quoted == 0)
+    quote_list (l);
+
+  if (l)
+    {
+      temp = string_list (l);
+      dispose_words (l);
+    }
+  else if (lquote)
+    {
+      temp = xmalloc (2);
+      temp[0] = CTLNUL;
+      temp[1] = '\0';
+    }
+  else
+    temp = (char *)NULL;
+
+  if (c == '-' || c == '+')
+    return (temp);
+
+  /* c == '=' */
+  if (temp)
+    t = savestring (temp);
+  else
+    t = savestring ("");
+  t1 = dequote_string (t);
+  free (t);
+  bind_variable (name, t1);
+  free (t1);
+  return (temp);
+}
+
+/* Deal with the right hand side of a ${name:?value} expansion in the case
+   that NAME is null or not set.  If VALUE is non-null it is expanded and
+   used as the error message to print, otherwise a standard message is
+   printed. */
+static void
+parameter_brace_expand_error (name, value)
+     char *name, *value;
+{
+  if (value && *value)
+    {
+      WORD_LIST *l = expand_string (value, 0);
+      char *temp1 = string_list (l);
+      report_error ("%s: %s", name, temp1 ? temp1 : value);
+      FREE (temp1);
+      dispose_words (l);
+    }
+  else
+    report_error ("%s: parameter null or not set", name);
+
+  /* Free the data we have allocated during this expansion, since we
+     are about to longjmp out. */
+  free (name);
+  FREE (value);
+}
+
+/* Return 1 if NAME is something for which parameter_brace_expand_length is
+   OK to do. */
+static int
+valid_length_expression (name)
+     char *name;
+{
+  return (!name[1] ||                                          /* ${#} */
+         ((name[1] == '@' || name[1] == '*') && !name[2]) ||   /* ${#@}, ${#*} */
+         (digit (name[1]) && all_digits (name + 1)) ||         /* ${#11} */
+         legal_identifier (name + 1));                         /* ${#PS1} */
+}
+
+/* Handle the parameter brace expansion that requires us to return the
+   length of a parameter. */
+static int
+parameter_brace_expand_length (name)
+     char *name;
+{
+  char *t;
+  int number = 0;
+
+  if (name[1] == '\0')                 /* ${#} */
+    {
+      WORD_LIST *l = list_rest_of_args ();
+      number = list_length (l);
+      dispose_words (l);
+    }
+  else if (name[1] != '*' && name[1] != '@')
+    {
+      number = 0;
+
+      if (digit (name[1]))             /* ${#1} */
+       {
+         if (t = get_dollar_var_value (atoi (name + 1)))
+           {
+             number = strlen (t);
+             free (t);
+           }
+       }
+      else                             /* ${#PS1} */
+       {
+         WORD_LIST *list;
+         char *newname;
+
+         newname = savestring (name);
+         newname[0] = '$';
+         list = expand_string (newname, 0);
+         t = string_list (list);
+         free (newname);
+         dispose_words (list);
+
+         if (t)
+           number = strlen (t);
+
+         FREE (t);
+       }
+    }
+  else                                 /* ${#@} and ${#*} */
+    {
+#if !defined (KSH_INCOMPATIBLE)
+      WORD_LIST *l = list_rest_of_args ();
+      number = l ? list_length (l) : 0;
+      dispose_words (l);
+#else
+      if (t = string_rest_of_args (1))
+       {
+         number = strlen (t);
+         free (t);
+       }
+#endif /* KSH_INCOMPATIBLE */
+    }
+  return (number);
+}
+
+/* Make a word list which is the parameter and variable expansion,
+   command substitution, arithmetic substitution, and quote removed
+   expansion of WORD.  Return a pointer to a WORD_LIST which is the
+   result of the expansion.  If WORD contains a null word, the word
+   list returned is also null.
+
+   QUOTED, when non-zero specifies that the text of WORD is treated
+   as if it were surrounded by double quotes.
+   CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
+   they point to an integer value which receives information about expansion.
+   CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
+   EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
+   else zero.
+
+   This only does word splitting in the case of $@ expansion.  In that
+   case, we split on ' '. */
+
+/* Values for the local variable quoted_state. */
+#define UNQUOTED        0
+#define PARTIALLY_QUOTED 1
+#define WHOLLY_QUOTED    2
+
+static WORD_LIST *
+expand_word_internal (word, quoted, contains_dollar_at, expanded_something)
+     WORD_DESC *word;
+     int quoted;
+     int *contains_dollar_at;
+     int *expanded_something;
+{
+  /* The thing that we finally output. */
+  WORD_LIST *result = (WORD_LIST *)NULL;
+
+  /* The intermediate string that we build while expanding. */
+  char *istring = xmalloc (DEFAULT_ARRAY_SIZE);
+
+  /* The current size of the above object. */
+  int istring_size = DEFAULT_ARRAY_SIZE;
+
+  /* Index into ISTRING. */
+  int istring_index = 0;
+
+  /* Temporary string storage. */
+  char *temp = (char *)NULL;
+
+  /* The text of WORD. */
+  register char *string = word->word;
+
+  /* The index into STRING. */
+  int sindex = 0;
+
+  /* This gets 1 if we see a $@ while quoted. */
+  int quoted_dollar_at = 0;
+
+  /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
+     whether WORD contains no quoting characters, a partially quoted
+     string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
+  int quoted_state = UNQUOTED;
+
+  register int c;              /* Current character. */
+  int number;                  /* Temporary number value. */
+  int t_index;                 /* For calls to string_extract_xxx. */
+  char *command_subst_result;  /* For calls to command_substitute (). */
+
+  istring[0] = '\0';
+
+  if (!string) goto final_exit;
+
+  if (contains_dollar_at)
+    *contains_dollar_at = 0;
+
+  /* Begin the expansion. */
+
+  for (;;)
+    {
+      c = string[sindex];
+
+      /* Case on toplevel character. */
+      switch (c)
+       {
+       case '\0':
+         goto finished_with_string;
+
+       case CTLESC:
+         temp = xmalloc (3);
+         temp[0] = CTLESC;
+         temp[1] = c = string[++sindex];
+         temp[2] = '\0';
+
+         if (string[sindex])
+           sindex++;
+
+         goto add_string;
+
+#if defined (PROCESS_SUBSTITUTION)
+         /* Process substitution. */
+       case '<':
+       case '>':
+         {
+           char *temp1;
+           int old_index;
+
+           if (string[++sindex] != '(' || quoted || posixly_correct)
+             {
+               sindex--;
+               goto add_character;
+             }
+           else
+             old_index = ++sindex; /* skip past both '<' and '(' */
+
+           temp1 = extract_process_subst
+             (string, (c == '<') ? "<(" : ">(", &old_index);
+           sindex = old_index;
+
+           /* If the process substitution specification is `<()', we want to
+              open the pipe for writing in the child and produce output; if
+              it is `>()', we want to open the pipe for reading in the child
+              and consume input. */
+           temp = process_substitute (temp1, (c == '>'));
+
+           FREE (temp1);
+
+           goto dollar_add_string;
+         }
+#endif /* PROCESS_SUBSTITUTION */
+
+       /* See about breaking this into a separate function:
+           char *
+           param_expand (string, sindex, quoted, expanded_something,
+                         contains_dollar_at, quoted_dollar_at)
+           char *string;
+           int *sindex, quoted, *expanded_something, *contains_dollar_at;
+           int *quoted_dollar_at;
+       */
+       case '$':
+
+         if (expanded_something)
+           *expanded_something = 1;
+
+         c = string[++sindex];
+
+         /* Do simple cases first. Switch on what follows '$'. */
+         switch (c)
+           {
+             /* $0 .. $9? */
+           case '0':
+           case '1':
+           case '2':
+           case '3':
+           case '4':
+           case '5':
+           case '6':
+           case '7':
+           case '8':
+           case '9':
+             temp = dollar_vars[digit_value (c)];
+             if (unbound_vars_is_error && temp == (char *)NULL)
+               {
+                 report_error ("$%c: unbound variable", c);
+                 free (string);
+                 free (istring);
+                 last_command_exit_value = 1;
+                 return (&expand_word_error);
+               }
+             if (temp)
+               temp = savestring (temp);
+             goto dollar_add_string;
+
+             /* $$ -- pid of the invoking shell. */
+           case '$':
+             number = dollar_dollar_pid;
+
+           add_number:
+             temp = itos (number);
+           dollar_add_string:
+             if (string[sindex]) sindex++;
+
+             /* Add TEMP to ISTRING. */
+           add_string:
+             istring = sub_append_string
+               (temp, istring, &istring_index, &istring_size);
+             temp = (char *)NULL;
+             break;
+
+             /* $# -- number of positional parameters. */
+           case '#':
+             {
+               WORD_LIST *list = list_rest_of_args ();
+               number = list_length (list);
+               dispose_words (list);
+               goto add_number;
+             }
+
+             /* $? -- return value of the last synchronous command. */
+           case '?':
+             number = last_command_exit_value;
+             goto add_number;
+
+             /* $- -- flags supplied to the shell on invocation or
+                by `set'. */
+           case '-':
+             temp = which_set_flags ();
+             goto dollar_add_string;
+
+             /* $! -- Pid of the last asynchronous command. */
+           case '!':
+             number = (int)last_asynchronous_pid;
+
+             /* If no asynchronous pids have been created, echo nothing. */
+             if (number == (int)NO_PID)
+               {
+                 if (string[sindex])
+                   sindex++;
+                 if (expanded_something)
+                   *expanded_something = 0;
+                 break;
+               }
+             goto add_number;
+
+             /* The only difference between this and $@ is when the
+                arg is quoted. */
+           case '*':           /* `$*' */
+             temp = string_rest_of_args (quoted);
+
+             if (quoted && temp && *temp == '\0' /* && istring_index > 0 */)
+               {
+                 free (temp);
+                 temp = (char *)NULL;
+               }
+
+             /* In the case of a quoted string, quote the entire arg-list.
+                "$1 $2 $3". */
+             if (quoted && temp)
+               {
+                 char *james_brown = temp;
+                 temp = quote_string (temp);
+                 free (james_brown);
+               }
+             goto dollar_add_string;
+
+             /* When we have "$@" what we want is "$1" "$2" "$3" ... This
+                means that we have to turn quoting off after we split into
+                the individually quoted arguments so that the final split
+                on the first character of $IFS is still done.  */
+           case '@':           /* `$@' */
+             {
+               WORD_LIST *tlist = list_rest_of_args ();
+               if (quoted && tlist)
+                 quote_list (tlist);
+
+               /* We want to flag the fact that we saw this.  We can't turn
+                  off quoting entirely, because other characters in the
+                  string might need it (consider "\"$@\""), but we need some
+                  way to signal that the final split on the first character
+                  of $IFS should be done, even though QUOTED is 1. */
+               if (quoted)
+                 quoted_dollar_at = 1;
+               if (contains_dollar_at)
+                 *contains_dollar_at = 1;
+               temp = string_list (tlist);
+               dispose_words (tlist);          
+               goto dollar_add_string;
+             }
+
+             /* ${[#]name[[:]#[#]%[%]-=?+[word]]} */
+           case '{':
+             {
+               int check_nullness = 0;
+               int var_is_set = 0;
+               int var_is_null = 0;
+               int var_is_special = 0;
+               char *name, *value;
+
+               t_index = ++sindex;
+               name = string_extract (string, &t_index, "#%:-=?+}");
+               value = (char *)NULL;
+
+               /* If the name really consists of a special variable, then
+                  make sure that we have the entire name. */
+               if (sindex == t_index &&
+                   (string[sindex] == '-' ||
+                    string[sindex] == '?' ||
+                    string[sindex] == '#'))
+                 {
+                   char *tt;
+                   t_index++;
+                   free (name);
+                   tt = string_extract (string, &t_index, "#%:-=?+}");
+                   name = xmalloc (2 + (strlen (tt)));
+                   *name = string[sindex];
+                   strcpy (name + 1, tt);
+                   free (tt);
+                 }
+               sindex = t_index;
+
+               /* Find out what character ended the variable name.  Then
+                  do the appropriate thing. */
+               if (c = string[sindex])
+                 sindex++;
+
+               if (c == ':')
+                 {
+                   check_nullness++;
+                   if (c = string[sindex])
+                     sindex++;
+                 }
+
+               /* Determine the value of this variable. */
+               if ((digit (*name) && all_digits (name)) ||
+                   (strlen (name) == 1 && member (*name, "#-?$!@*")))
+                 var_is_special++;
+
+               /* Check for special expansion things. */
+               if (*name == '#')
+                 {
+                   /* Handle ${#-} and ${#?}.  They return the lengths of
+                      $- and $?, respectively. */
+                   if (string[sindex] == '}' &&
+                       !name[1] &&
+                       !check_nullness &&
+                       (c == '-' || c == '?'))
+                     {
+                       char *s;
+
+                       free (name);
+
+                       if (c == '-')
+                         s = which_set_flags ();
+                       else
+                         s = itos (last_command_exit_value);
+
+                       number = STRLEN (s);
+                       FREE (s);
+                       goto add_number;
+                     }
+
+                   /* Don't allow things like ${#:-foo} to go by; they are
+                      errors.  If we are not pointing at the character just
+                      after the closing brace, then we haven't gotten all of
+                      the name.  Since it begins with a special character,
+                      this is a bad substitution.  Explicitly check for ${#:},
+                      which the rules do not catch. */
+                   if (string[sindex - 1] != '}' || member (c, "?-=+") ||
+                       (string[sindex - 1] == '}' && !name[1] && c == '}' &&
+                        check_nullness))
+                     {
+                       free (name);
+                       name = string;
+                       goto bad_substitution;
+                     }
+
+                   /* Check NAME for validity before trying to go on. */
+                   if (!valid_length_expression (name))
+                     {
+                       free (name);
+                       name = string;
+                       goto bad_substitution;
+                     }
+
+                   number = parameter_brace_expand_length (name);
+                   free (name);
+                   /* We are pointing one character after the brace which
+                      closes this expression.  Since the code at add_number
+                      increments SINDEX, we back up a single character. */
+                   sindex--;
+                   goto add_number;
+                 }
+
+               /* ${@} is identical to $@. */
+               if (name[0] == '@' && name[1] == '\0')
+                 {
+                   if (quoted)
+                     quoted_dollar_at = 1;
+
+                   if (contains_dollar_at)
+                     *contains_dollar_at = 1;
+                 }
+
+               /* Make sure that NAME is valid before trying to go on. */
+               if (!valid_brace_expansion_word (name, var_is_special))
+                 {
+                   free (name);
+                   name = string;
+                   goto bad_substitution;
+                 }
+
+               temp =
+                 parameter_brace_expand_word (name, var_is_special, quoted);
+
+               if (temp)
+                 var_is_set++;
+
+               if (!var_is_set || !temp || !*temp)
+                 var_is_null++;
+
+               if (!check_nullness)
+                 var_is_null = 0;
+
+               /* Get the rest of the stuff inside the braces. */
+               if (c && c != '}')
+                 {
+                   /* Extract the contents of the ${ ... } expansion
+                      according to the Posix.2 rules.  It's much less of
+                      a hack that the former extract_delimited_string ()
+                      scheme. */
+                   value = extract_dollar_brace_string (string, &sindex);
+
+                   if (string[sindex] == '}')
+                     sindex++;
+                   else
+                     {
+                       free (name);
+                       name = string;
+                       goto bad_substitution;
+                     }
+                 }
+               else
+                 value = (char *)NULL;
+
+               /* Do the right thing based on which character ended the
+                  variable name. */
+               switch (c)
+                 {
+                 default:
+                   free (name);
+                   name = string;
+                   /* FALL THROUGH */
+
+                 case '\0':
+                 bad_substitution:
+                   report_error ("%s: bad substitution", name ? name : "??");
+                   FREE (value);
+                   free (temp);
+                   free (name);
+                   free (istring);
+                   return &expand_word_error;
+
+                 case '}':
+                   if (!var_is_set && unbound_vars_is_error)
+                     {
+                       report_error ("%s: unbound variable", name);
+                       FREE (value);
+                       free (temp);
+                       free (name);
+                       free (string);
+                       last_command_exit_value = 1;
+                       free (istring);
+                       return &expand_word_error;
+                     }
+                   break;
+
+                 case '#':     /* ${param#[#]pattern} */
+                 case '%':     /* ${param%[%]pattern} */
+                   {
+                     char *t;
+                     if (!value || !*value || !temp || !*temp)
+                       break;
+                     if (quoted)
+                       {
+                         t = dequote_string (temp);
+                         free (temp);
+                         temp = t;
+                       }
+                     t = parameter_brace_remove_pattern (value, temp, c);
+                     free (temp);
+                     free (value);
+                     temp = t;
+                   }
+                   break;
+
+                 case '-':
+                 case '=':
+                 case '?':
+                 case '+':
+                   if (var_is_set && !var_is_null)
+                     {
+                       /* We don't want the value of the named variable for
+                          anything, just the value of the right hand side. */
+                       if (c == '+')
+                         {
+                           FREE (temp);
+                           if (value)
+                             {
+                               temp = parameter_brace_expand_rhs
+                                 (name, value, c, quoted);
+                               /* XXX - this is a hack.  A better fix is
+                                        coming later. */
+                               if ((value[0] == '$' && value[1] == '@') ||
+                                   (value[0] == '"' && value[1] == '$' && value[2] == '@'))
+                                 {
+                                   if (quoted)
+                                     quoted_dollar_at++;
+                                   if (contains_dollar_at)
+                                     *contains_dollar_at = 1;
+                                 }
+                               free (value);
+                             }
+                           else
+                             temp = (char *)NULL;
+                         }
+                       else
+                         {
+                           FREE (value);
+                         }
+                       /* Otherwise do nothing; just use the value in TEMP. */
+                     }
+                   else        /* VAR not set or VAR is NULL. */
+                     {
+                       FREE (temp);
+                       temp = (char *)NULL;
+                       if (c == '=' && var_is_special)
+                         {
+                           report_error
+                             ("$%s: cannot assign in this way", name);
+                           free (name);
+                           free (value);
+                           free (string);
+                           free (istring);
+                           return &expand_word_error;
+                         }
+                       else if (c == '?')
+                         {
+                           free (string);
+                           free (istring);
+                           parameter_brace_expand_error (name, value);
+                           if (!interactive)
+                             return &expand_word_fatal;
+                           else
+                             return &expand_word_error;
+                         }
+                       else if (c != '+')
+                         temp = parameter_brace_expand_rhs
+                           (name, value, c, quoted);
+                       free (value);
+                     }
+                   break;
+                 }             /* end case on closing character. */
+               free (name);
+               goto add_string;
+             }                 /* end case '{' */
+             /* break; */
+
+             /* Do command or arithmetic substitution. */
+           case '(':
+             /* We have to extract the contents of this paren substitution. */
+             {
+               int old_index = ++sindex;
+
+               temp = extract_command_subst (string, &old_index);
+               sindex = old_index;
+
+               /* For Posix.2-style `$(( ))' arithmetic substitution,
+                  extract the expression and pass it to the evaluator. */
+               if (temp && *temp == '(')
+                 {
+                   char *t = temp + 1;
+                   int last = strlen (t) - 1;
+
+                   if (t[last] != ')')
+                     {
+                       report_error ("%s: bad arithmetic substitution", temp);
+                       free (temp);
+                       free (string);
+                       free (istring);
+                       return &expand_word_error;
+                     }
+
+                   /* Cut off ending `)' */
+                   t[last] = '\0';
+
+                   /* Expand variables found inside the expression. */
+                   {
+                     WORD_LIST *l;
+
+                     l = expand_string (t, 1);
+                     t = string_list (l);
+                     dispose_words (l);
+                   }
+
+                   /* No error messages. */
+                   this_command_name = (char *)NULL;
+
+                   number = evalexp (t);
+                   free (temp);
+                   free (t);
+
+                   goto add_number;
+                 }
+
+               goto handle_command_substitution;
+             }
+
+             /* Do straight arithmetic substitution. */
+           case '[':
+             /* We have to extract the contents of this
+                arithmetic substitution. */
+             {
+               char *t;
+               int old_index = ++sindex;
+               WORD_LIST *l;
+
+               temp = extract_arithmetic_subst (string, &old_index);
+               sindex = old_index;
+
+               /* Do initial variable expansion. */
+               l = expand_string (temp, 1);
+               t = string_list (l);
+               dispose_words (l);
+
+               /* No error messages. */
+               this_command_name = (char *)NULL;
+               number = evalexp (t);
+               free (t);
+               free (temp);
+
+               goto add_number;
+             }
+
+           default:
+             {
+               /* Find the variable in VARIABLE_LIST. */
+               int old_index;
+               char *name;
+               SHELL_VAR *var;
+
+               temp = (char *)NULL;
+
+               for (old_index = sindex;
+                    (c = string[sindex]) &&
+                    (isletter (c) || digit (c) || c == '_');
+                    sindex++);
+               name = substring (string, old_index, sindex);
+
+               /* If this isn't a variable name, then just output the `$'. */
+               if (!name || !*name)
+                 {
+                   FREE (name);
+                   temp = savestring ("$");
+                   if (expanded_something)
+                     *expanded_something = 0;
+                   goto add_string;
+                 }
+
+               /* If the variable exists, return its value cell. */
+               var = find_variable (name);
+
+               if (var && !invisible_p (var) && value_cell (var))
+                 {
+                   temp = value_cell (var);
+                   temp = quoted && temp && *temp ? quote_string (temp)
+                                                  : quote_escapes (temp);
+                   free (name);
+                   goto add_string;
+                 }
+               else
+                 temp = (char *)NULL;
+
+               if (unbound_vars_is_error)
+                 report_error ("%s: unbound variable", name);
+               else
+                 {
+                   free (name);
+                   goto add_string;
+                 }
+
+               free (name);
+               free (string);
+               last_command_exit_value = 1;
+               free (istring);
+               return &expand_word_error;
+             }
+           }
+         break;                /* End case '$': */
+
+       case '`':               /* Backquoted command substitution. */
+         {
+           sindex++;
+
+           if (expanded_something)
+             *expanded_something = 1;
+
+           temp = string_extract (string, &sindex, "`");
+           de_backslash (temp);
+
+         handle_command_substitution:
+           command_subst_result = command_substitute (temp, quoted);
+
+           FREE (temp);
+
+           temp = command_subst_result;
+
+           if (string[sindex])
+             sindex++;
+
+           goto add_string;
+         }
+
+       case '\\':
+         if (string[sindex + 1] == '\n')
+           {
+             sindex += 2;
+             continue;
+           }
+         else
+           {
+             char *slashify_chars = "";
+
+             c = string[++sindex];
+
+             if (quoted == Q_HERE_DOCUMENT)
+               slashify_chars = slashify_in_here_document;
+             else if (quoted == Q_DOUBLE_QUOTES)
+               slashify_chars = slashify_in_quotes;
+
+             if (quoted && !member (c, slashify_chars))
+               {
+                 temp = xmalloc (3);
+                 temp[0] = '\\'; temp[1] = c; temp[2] = '\0';
+                 if (c)
+                   sindex++;
+                 goto add_string;
+               }
+             else
+               {
+                 /* This character is quoted, so add it in quoted mode. */
+                 temp = make_quoted_char (c);
+                 if (c)
+                   sindex++;
+                 goto add_string;
+               }
+           }
+
+       case '"':
+         if (quoted)
+           goto add_character;
+         sindex++;
+         {
+           WORD_LIST *tresult = (WORD_LIST *)NULL;
+
+           t_index = sindex;
+           temp = string_extract_double_quoted (string, &sindex);
+
+           /* If the quotes surrounded the entire string, then the
+              whole word was quoted. */
+           if (t_index == 1 && !string[sindex])
+             quoted_state = WHOLLY_QUOTED;
+           else
+             quoted_state = PARTIALLY_QUOTED;
+
+           if (temp && *temp)
+             {
+               int dollar_at_flag;
+               int quoting_flags = Q_DOUBLE_QUOTES;
+               WORD_DESC *temp_word = make_word (temp);
+
+               free (temp);
+
+               tresult = expand_word_internal
+                 (temp_word, quoting_flags, &dollar_at_flag, (int *)NULL);
+
+               if (tresult == &expand_word_error || tresult == &expand_word_fatal)
+                 {
+                   free (istring);
+                   free (string);
+                   /* expand_word_internal has already freed temp_word->word
+                      for us because of the way it prints error messages. */
+                   temp_word->word = (char *)NULL;
+                   dispose_word (temp_word);
+                   return tresult;
+                 }
+
+               dispose_word (temp_word);
+
+               /* "$@" (a double-quoted dollar-at) expands into nothing,
+                  not even a NULL word, when there are no positional
+                  parameters. */
+               if (!tresult && dollar_at_flag)
+                 {
+                   quoted_dollar_at++;
+                   break;
+                 }
+
+               /* If we get "$@", we know we have expanded something, so we
+                  need to remember it for the final split on $IFS.  This is
+                  a special case; it's the only case where a quoted string
+                  can expand into more than one word.  It's going to come back
+                  from the above call to expand_word_internal as a list with
+                  a single word, in which all characters are quoted and
+                  separated by blanks.  What we want to do is to turn it back
+                  into a list for the next piece of code. */
+               dequote_list (tresult);
+
+               if (dollar_at_flag)
+                 {
+                   quoted_dollar_at++;
+                   if (expanded_something)
+                     *expanded_something = 1;
+                 }
+             }
+           else
+             {
+               /* What we have is "".  This is a minor optimization. */
+               free (temp);
+               tresult = (WORD_LIST *)NULL;
+             }
+
+           /* The code above *might* return a list (consider the case of "$@",
+              where it returns "$1", "$2", etc.).  We can't throw away the
+              rest of the list, and we have to make sure each word gets added
+              as quoted.  We test on tresult->next:  if it is non-NULL, we
+              quote the whole list, save it to a string with string_list, and
+              add that string. We don't need to quote the results of this
+              (and it would be wrong, since that would quote the separators
+              as well), so we go directly to add_string. */
+           if (tresult)
+             {
+               if (tresult->next)
+                 {
+                   quote_list (tresult);
+                   temp = string_list (tresult);
+                   dispose_words (tresult);
+                   goto add_string;
+                 }
+               else
+                 {
+                   temp = savestring (tresult->word->word);
+                   dispose_words (tresult);
+                 }
+             }
+           else
+             temp = (char *)NULL;
+
+           /* We do not want to add quoted nulls to strings that are only
+              partially quoted; we can throw them away. */
+           if (!temp && (quoted_state == PARTIALLY_QUOTED))
+             continue;
+
+         add_quoted_string:
+
+           if (temp)
+             {
+               char *t = temp;
+               temp = quote_string (temp);
+               free (t);
+             }
+           else
+             {
+               /* Add NULL arg. */
+               temp = xmalloc (2);
+               temp[0] = CTLNUL;
+               temp[1] = '\0';
+             }
+           goto add_string;
+         }
+         /* break; */
+
+       case '\'':
+         {
+           if (!quoted)
+             {
+               sindex++;
+
+               t_index = sindex;
+               temp = string_extract_single_quoted (string, &sindex);
+
+               /* If the entire STRING was surrounded by single quotes,
+                  then the string is wholly quoted. */
+               if (t_index == 1 && !string[sindex])
+                 quoted_state = WHOLLY_QUOTED;
+               else
+                 quoted_state = PARTIALLY_QUOTED;
+
+               /* If all we had was '', it is a null expansion. */
+               if (!*temp)
+                 {
+                   free (temp);
+                   temp = (char *)NULL;
+                 }
+               else
+                 remove_quoted_escapes (temp);
+
+               /* We do not want to add quoted nulls to strings that are only
+                  partially quoted; such nulls are discarded. */
+               if (!temp && (quoted_state == PARTIALLY_QUOTED))
+                 continue;
+
+               goto add_quoted_string;
+             }
+           else
+             goto add_character;
+
+           break;
+         }
+
+       default:
+
+         /* This is the fix for " $@ " */
+         if (quoted)
+           {
+             temp = make_quoted_char (c);
+             if (string[sindex])
+               sindex++;
+             goto add_string;
+           }
+
+       add_character:
+         if (istring_index + 1 >= istring_size)
+           {
+             while (istring_index + 1 >= istring_size)
+               istring_size += DEFAULT_ARRAY_SIZE;
+             istring = xrealloc (istring, istring_size);
+           }
+         istring[istring_index++] = c;
+         istring[istring_index] = '\0';
+
+         /* Next character. */
+         sindex++;
+       }
+    }
+
+finished_with_string:
+final_exit:
+  /* OK, we're ready to return.  If we have a quoted string, and
+     quoted_dollar_at is not set, we do no splitting at all; otherwise
+     we split on ' '.  The routines that call this will handle what to
+     do if nothing has been expanded. */
+  if (istring)
+    {
+      WORD_LIST *temp_list;
+
+      /* Partially and wholly quoted strings which expand to the empty
+        string are retained as an empty arguments.  Unquoted strings
+        which expand to the empty string are discarded.  The single
+        exception is the case of expanding "$@" when there are no
+        positional parameters.  In that case, we discard the expansion. */
+
+      /* Because of how the code that handles "" and '' in partially
+        quoted strings works, we need to make ISTRING into a QUOTED_NULL
+        if we saw quoting characters, but the expansion was empty.
+        "" and '' are tossed away before we get to this point when
+        processing partially quoted strings.  This makes "" and $xxx""
+        equivalent when xxx is unset. */
+      if (!*istring && quoted_state == PARTIALLY_QUOTED)
+       {
+         if (istring_size < 2)
+           istring = xrealloc (istring, istring_size += 2);
+         istring[0] = CTLNUL;
+         istring[1] = '\0';
+       }
+
+      /* If we expand to nothing and there were no single or double quotes
+        in the word, we throw it away.  Otherwise, we return a NULL word.
+        The single exception is for $@ surrounded by double quotes when
+        there are no positional parameters.  In that case, we also throw
+        the word away. */
+      if (!*istring)
+       {
+         if (quoted_state == UNQUOTED ||
+             (quoted_dollar_at && quoted_state == WHOLLY_QUOTED))
+           temp_list = (WORD_LIST *)NULL;
+         else
+           {
+             temp_list = make_word_list
+               (make_word (istring), (WORD_LIST *)NULL);
+             temp_list->word->quoted = quoted;
+           }
+       }
+      else if (word->assignment)
+       {
+         temp_list = make_word_list (make_word (istring), (WORD_LIST *)NULL);
+         temp_list->word->quoted = quoted;
+         temp_list->word->assignment = assignment (temp_list->word->word);
+       }
+      else
+       {
+         char *ifs_chars = (char *)NULL;
+
+         if (quoted_dollar_at)
+           {
+             SHELL_VAR *ifs = find_variable ("IFS");     
+             if (ifs)
+               ifs_chars = value_cell (ifs);
+             else
+               ifs_chars = " \t\n";
+           }
+
+         /* According to Posix.2, "$@" expands to a single word if
+            IFS="" and the positional parameters are not empty. */
+         if (quoted_dollar_at && ifs_chars && *ifs_chars)
+           {
+             temp_list = list_string (istring, " ", 1);
+#if 0
+             /* This turns quoted null strings back into CTLNULs */
+             dequote_list (temp_list);
+             quote_list (temp_list);
+#endif
+           }
+         else
+           {
+             WORD_DESC *tword;
+             tword = make_word (istring);
+             temp_list = make_word_list (tword, (WORD_LIST *)NULL);
+             tword->quoted = quoted || (quoted_state == WHOLLY_QUOTED);
+             tword->assignment = word->assignment;
+           }
+       }
+
+      free (istring);
+      result = (WORD_LIST *)
+       list_append (REVERSE_LIST (result, WORD_LIST *), temp_list);
+    }
+  else
+    result = (WORD_LIST *)NULL;
+
+  return (result);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                Functions for Quote Removal                      */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Perform quote removal on STRING.  If QUOTED > 0, assume we are obeying the
+   backslash quoting rules for within double quotes. */
+char *
+string_quote_removal (string, quoted)
+     char *string;
+     int quoted;
+{
+  char *r, *result_string, *temp, *temp1;
+  int sindex, tindex, c, dquote;
+
+  /* The result can be no longer than the original string. */
+  r = result_string = xmalloc (strlen (string) + 1);
+
+  for (sindex = dquote = 0; c = string[sindex];)
+    {
+      switch (c)
+       {
+       case '\\':
+         c = string[++sindex];
+         if ((quoted || dquote) && !member (c, slashify_in_quotes))
+           *r++ = '\\';
+
+       default:
+         *r++ = c;
+         sindex++;
+         break;
+
+       case '\'':
+         if (quoted || dquote)
+           {
+             *r++ = c;
+             sindex++;
+           }
+         else
+           {
+             tindex = ++sindex;
+             temp = string_extract_single_quoted (string, &tindex);
+             sindex = tindex;
+
+             if (temp)
+               {
+                 strcpy (r, temp);
+                 r += strlen (r);
+                 free (temp);
+               }
+           }
+         break;
+
+       case '"':
+         dquote = 1 - dquote;
+         sindex++;
+         break;
+       }
+    }
+    *r = '\0';
+    return (result_string);
+}
+
+/* Perform quote removal on word WORD.  This allocates and returns a new
+   WORD_DESC *. */
+WORD_DESC *
+word_quote_removal (word, quoted)
+     WORD_DESC *word;
+     int quoted;
+{
+  WORD_DESC *w;
+  char *t;
+
+  t = string_quote_removal (word->word, quoted);
+  w = make_word (t);
+  return (w);
+}
+
+/* Perform quote removal on all words in LIST.  If QUOTED is non-zero,
+   the members of the list are treated as if they are surrounded by
+   double quotes.  Return a new list, or NULL if LIST is NULL. */
+WORD_LIST *
+word_list_quote_removal (list, quoted)
+     WORD_LIST *list;
+     int quoted;
+{
+  WORD_LIST *result = (WORD_LIST *)NULL, *t, *tresult;
+
+  t = list;
+  while (t)
+    {
+      tresult = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
+      tresult->word = word_quote_removal (t->word, quoted);
+      tresult->next = (WORD_LIST *)NULL;
+      result = (WORD_LIST *) list_append (result, tresult);
+      t = t->next;
+    }
+  return (result);
+}
+
+/* Return 1 if CHARACTER appears in an unquoted portion of
+   STRING.  Return 0 otherwise. */
+static int
+unquoted_member (character, string)
+     int character;
+     char *string;
+{
+  int sindex, tindex, c;
+  char *temp;
+
+  sindex = 0;
+
+  while (c = string[sindex])
+    {
+      if (c == character)
+       return (1);
+
+      switch (c)
+       {
+         case '\\':
+           sindex++;
+           if (string[sindex])
+             sindex++;
+           break;
+
+         case '"':
+         case '\'':
+
+           tindex = ++sindex;
+           if (c == '"')
+             temp = string_extract_double_quoted (string, &tindex);
+           else
+             temp = string_extract_single_quoted (string, &tindex);
+           sindex = tindex;
+
+           FREE (temp);
+           break;
+
+         default:
+           sindex++;
+           break;
+       }
+    }
+  return (0);
+}
+
+/* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
+static int
+unquoted_substring (substr, string)
+     char *substr, *string;
+{
+  int sindex, tindex, c, sublen;
+  char *temp;
+
+  if (!substr || !*substr)
+    return (0);
+
+  sublen = strlen (substr);
+  sindex = 0;
+
+  while (c = string[sindex])
+    {
+      if (STREQN (string + sindex, substr, sublen))
+       return (1);
+
+      switch (c)
+       {
+         case '\\':
+           sindex++;
+
+           if (string[sindex])
+             sindex++;
+           break;
+
+         case '"':
+         case '\'':
+
+           tindex = ++sindex;
+
+           if (c == '"')
+             temp = string_extract_double_quoted (string, &tindex);
+           else
+             temp = string_extract_single_quoted (string, &tindex);
+           sindex = tindex;
+
+           FREE (temp);
+
+           break;
+
+         default:
+           sindex++;
+           break;
+       }
+    }
+  return (0);
+}
+
+/*******************************************
+ *                                        *
+ *    Functions to perform word splitting  *
+ *                                        *
+ *******************************************/
+
+/* 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_DESC *w;
+{
+  WORD_LIST *result;
+
+  if (w)
+    {
+      SHELL_VAR *ifs = find_variable ("IFS");
+      char *ifs_chars;
+
+      /* If IFS is unset, it defaults to " \t\n". */
+      if (ifs)
+       ifs_chars = value_cell (ifs);
+      else
+       ifs_chars = " \t\n";
+
+      if (w->quoted || !ifs_chars)
+       ifs_chars = "";
+
+#ifdef NOT_YET_MAYBE_LATER
+      if (!*ifs)
+       {
+         /* No splitting done if word quoted or ifs set to "". */
+         WORD_DESC *wtemp;
+         wtemp = make_word (w->word);
+         wtemp->quoted = w->quoted;
+         result = make_word_list (wtemp);
+       }
+      else
+#endif
+      result = list_string (w->word, ifs_chars, w->quoted);
+    }
+  else
+    result = (WORD_LIST *)NULL;
+  return (result);
+}
+
+/* Perform word splitting on LIST and return the RESULT.  It is possible
+   to return (WORD_LIST *)NULL. */
+static WORD_LIST *
+word_list_split (list)
+     WORD_LIST *list;
+{
+  WORD_LIST *result = (WORD_LIST *)NULL, *t, *tresult;
+
+  t = list;
+  while (t)
+    {
+      tresult = word_split (t->word);
+      result = (WORD_LIST *) list_append (result, tresult);
+      t = t->next;
+    }
+  return (result);
+}
+
+/**************************************************
+ *                                               *
+ *     Functions to expand an entire WORD_LIST   *
+ *                                               *
+ **************************************************/
+
+static WORD_LIST *varlist = (WORD_LIST *)NULL;
+
+/* Separate out any initial variable assignments from TLIST.  If set -k has
+   been executed, remove all assignment statements from TLIST.  Initial
+   variable assignments and other environment assignments are placed
+   on VARLIST. */
+static WORD_LIST *
+separate_out_assignments (tlist)
+     WORD_LIST *tlist;
+{
+  register WORD_LIST *vp, *lp;
+
+  if (!tlist)
+    return ((WORD_LIST *)NULL);
+
+  varlist = (WORD_LIST *)NULL;
+  vp = lp = tlist;
+
+  /* Separate out variable assignments at the start of the command.
+     Loop invariant: vp->next == lp
+     Loop postcondition:
+       lp = list of words left after assignment statements skipped
+       tlist = original list of words
+  */
+  while (lp && lp->word->assignment)
+    {
+      vp = lp;
+      lp = lp->next;
+    }
+
+  /* If lp != tlist, we have some initial assignment statements. */
+  /* We make VARLIST point to the list of assignment words and
+     TLIST point to the remaining words.  */
+  if (lp != tlist)
+    {
+      varlist = tlist;
+      /* ASSERT(vp->next == lp); */
+      vp->next = (WORD_LIST *)NULL;    /* terminate variable list */
+      tlist = lp;                      /* remainder of word list */
+    }
+
+  /* vp == end of variable list */
+  /* tlist == remainder of original word list without variable assignments */
+  if (!tlist)
+    /* All the words in tlist were assignment statements */
+    return ((WORD_LIST *)NULL);
+
+  /* ASSERT(tlist != NULL); */
+  /* ASSERT(tlist->word->assignment == 0); */
+
+  /* If the -k option is in effect, we need to go through the remaining
+     words, separate out the assignment words, and place them on VARLIST. */
+  if (place_keywords_in_env)
+    {
+      WORD_LIST *tp;   /* tp == running pointer into tlist */
+
+      tp = tlist;
+      lp = tlist->next;
+
+      /* Loop Invariant: tp->next == lp */
+      /* Loop postcondition: tlist == word list without assignment statements */
+      while (lp)
+       {
+         if (lp->word->assignment)
+           {
+             /* Found an assignment statement, add this word to end of
+                varlist (vp). */
+             if (!varlist)
+               varlist = vp = lp;
+             else
+               {
+                 vp->next = lp;
+                 vp = lp;
+               }
+
+             /* Remove the word pointed to by LP from TLIST. */
+             tp->next = lp->next;
+             /* ASSERT(vp == lp); */
+             lp->next = (WORD_LIST *)NULL;
+             lp = tp->next;
+           }
+         else
+           {
+             tp = lp;
+             lp = lp->next;
+           }
+       }
+    }
+  return (tlist);
+}
+
+/* Take the list of words in LIST and do the various substitutions.  Return
+   a new list of words which is the expanded list, and without things like
+   variable assignments. */
+
+WORD_LIST *
+expand_words (list)
+     WORD_LIST *list;
+{
+  return (expand_words_internal (list, 1));
+}
+
+/* Same as expand_words (), but doesn't hack variable or environment
+   variables. */
+WORD_LIST *
+expand_words_no_vars (list)
+     WORD_LIST *list;
+{
+  return (expand_words_internal (list, 0));
+}
+
+/* Non-zero means to allow unmatched globbed filenames to expand to
+   a null file. */
+static int allow_null_glob_expansion = 0;
+
+/* The workhorse for expand_words () and expand_words_no_var ().
+   First arg is LIST, a WORD_LIST of words.
+   Second arg DO_VARS is non-zero if you want to do environment and
+   variable assignments, else zero.
+
+   This does all of the substitutions: brace expansion, tilde expansion,
+   parameter expansion, command substitution, arithmetic expansion,
+   process substitution, word splitting, and pathname expansion.
+   Words with the `quoted' or `assignment' bits set, or for which no
+   expansion is done, do not undergo word splitting.  Words with the
+   `assignment' but set do not undergo pathname expansion. */
+static WORD_LIST *
+expand_words_internal (list, do_vars)
+     WORD_LIST *list;
+     int do_vars;
+{
+  register WORD_LIST *tlist, *new_list = (WORD_LIST *)NULL;
+  WORD_LIST *orig_list;
+
+  if (!list)
+    return ((WORD_LIST *)NULL);
+
+  tlist = copy_word_list (list);
+
+  if (do_vars)
+    {
+      tlist = separate_out_assignments (tlist);
+      if (!tlist)
+       {
+         if (varlist)
+           {
+             /* All the words were variable assignments, so they are placed
+                into the shell's environment. */
+             register WORD_LIST *lp;
+             for (lp = varlist; lp; lp = lp->next)
+               do_assignment (lp->word->word);
+             dispose_words (varlist);
+             varlist = (WORD_LIST *)NULL;
+           }
+         return ((WORD_LIST *)NULL);
+       }
+    }
+
+  /* Begin expanding the words that remain.  The expansions take place on
+     things that aren't really variable assignments. */
+
+#if defined (BRACE_EXPANSION)
+  /* Do brace expansion on this word if there are any brace characters
+     in the string. */
+  if (!no_brace_expansion)
+    {
+      register char **expansions;
+      WORD_LIST *braces = (WORD_LIST *)NULL, *disposables = (WORD_LIST *)NULL;
+      int eindex;
+
+      while (tlist)
+       {
+         WORD_LIST *next;
+
+         next = tlist->next;
+
+         /* 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
+            basically a reversal of TLIST into BRACES, which is corrected
+            by a call to reverse_list () on BRACES when the end of TLIST
+            is reached. */
+         if (strchr (tlist->word->word, '{'))
+           {
+             expansions = brace_expand (tlist->word->word);
+
+             for (eindex = 0; expansions[eindex]; eindex++)
+               {
+                 braces = make_word_list (make_word (expansions[eindex]),
+                                          braces);
+                 free (expansions[eindex]);
+               }
+             free (expansions);
+
+             /* Add TLIST to the list of words to be freed after brace
+                expansion has been performed. */
+             tlist->next = disposables;
+             disposables = tlist;
+           }
+         else
+           {
+             tlist->next = braces;
+             braces = tlist;
+           }
+
+         tlist = next;
+       }
+
+      dispose_words (disposables);
+      tlist = REVERSE_LIST (braces, WORD_LIST *);
+    }
+#endif /* BRACE_EXPANSION */
+
+  orig_list = tlist;
+
+  /* We do tilde expansion all the time.  This is what 1003.2 says. */
+  while (tlist)
+    {
+      register char *current_word;
+      WORD_LIST *expanded, *t, *reversed, *next;
+      int expanded_something = 0;
+
+      current_word = tlist->word->word;
+
+      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. */
+      if (current_word[0] == '~' ||
+         (!posixly_correct && strchr (current_word, '~') &&
+          unquoted_substring ("=~", current_word)))
+       {
+         char *tt;
+
+         tt = tlist->word->word;
+         tlist->word->word = tilde_expand (tt);
+         free (tt);
+       }
+
+      expanded = expand_word_internal
+       (tlist->word, 0, (int *)NULL, &expanded_something);
+
+      if (expanded == &expand_word_error || expanded == &expand_word_fatal)
+       {
+         /* By convention, each time this error is returned,
+            tlist->word->word has already been freed. */
+         tlist->word->word = (char *)NULL;
+         
+         /* Dispose our copy of the original list. */
+         dispose_words (orig_list);
+         /* Dispose the  new list we're building. */
+         dispose_words (new_list);
+
+         if (expanded == &expand_word_error)
+           longjmp (top_level, DISCARD);
+         else
+           longjmp (top_level, FORCE_EOF);
+       }
+
+      /* Don't split assignment words, even when they do not precede a
+        command name. */
+      if (expanded_something && tlist->word->assignment == 0)
+       {
+         t = word_list_split (expanded);
+         dispose_words (expanded);
+       }
+      else
+       {
+         /* If no parameter expansion, command substitution, process
+            substitution, or arithmetic substitution took place, then
+            do not do word splitting.  We still have to remove quoted
+            null characters from the result. */
+         word_list_remove_quoted_nulls (expanded);
+         t = expanded;
+       }
+
+      /* In the most common cases, t will be a list containing only one
+        element, so the call to reverse_list would be wasted. */
+      reversed = REVERSE_LIST (t, WORD_LIST *);
+      new_list = (WORD_LIST *)list_append (reversed, new_list);
+
+      tlist = next;
+    }
+
+  new_list = REVERSE_LIST (new_list, WORD_LIST *);
+
+  dispose_words (orig_list);
+
+#if defined (USE_POSIX_GLOB_LIBRARY)
+#  define GLOB_FAILED(glist)   !(glist)
+#else /* !USE_POSIX_GLOB_LIBRARY */
+#  define GLOB_FAILED(glist)   (glist) == (char **)&glob_error_return
+#endif /* !USE_POSIX_GLOB_LIBRARY */
+
+  /* Okay, we're almost done.  Now let's just do some filename
+     globbing. */
+  if (new_list)
+    {
+      char **temp_list = (char **)NULL;
+      register int list_index;
+      WORD_LIST *glob_list, *disposables;
+
+      orig_list = disposables = (WORD_LIST *)NULL;
+      tlist = new_list;
+
+      /* orig_list == output list, despite the name. */
+      if (!disallow_filename_globbing)
+       {
+         while (tlist)
+           {
+             /* For each word, either globbing is attempted or the word is
+                added to orig_list.  If globbing succeeds, the results are
+                added to orig_list and the word (tlist) is added to the list
+                of disposable words.  If globbing fails and failed glob
+                expansions are left unchanged (the shell default), the
+                original word is added to orig_list.  If globbing fails and
+                failed glob expansions are removed, the original word is
+                added to the list of disposable words.  orig_list ends up
+                in reverse order and requires a call to reverse_list to
+                be set right.  After all words are examined, the disposable
+                words are freed. */
+             WORD_LIST *next;
+
+             next = tlist->next;
+
+             /* If the word isn't quoted and there is an unquoted pattern
+                matching character in the word, then glob it. */
+             if (!tlist->word->quoted && !tlist->word->assignment &&
+                 unquoted_glob_pattern_p (tlist->word->word))
+               {
+                 temp_list = shell_glob_filename (tlist->word->word);
+
+                 /* Handle error cases.
+                    I don't think we should report errors like "No such file
+                    or directory".  However, I would like to report errors
+                    like "Read failed". */
+
+                 if (GLOB_FAILED (temp_list))
+                   {
+                     temp_list = (char **) xmalloc (sizeof (char *));
+                     temp_list[0] = (char *)NULL;
+                   }
+
+                 /* Dequote the current word in case we have to use it. */
+                 if (!temp_list[0])
+                   {
+                     register char *t = dequote_string (tlist->word->word);
+                     free (tlist->word->word);
+                     tlist->word->word = t;
+                   }
+
+                 /* Make the array into a word list. */
+                 glob_list = (WORD_LIST *)NULL;
+                 for (list_index = 0; temp_list[list_index]; list_index++)
+                   glob_list = make_word_list
+                     (make_word (temp_list[list_index]), glob_list);
+
+                 if (glob_list)
+                   {
+                     orig_list = (WORD_LIST *)list_append
+                       (glob_list, orig_list);
+                     tlist->next = disposables;
+                     disposables = tlist;
+                   }
+                 else
+                   if (!allow_null_glob_expansion)
+                     {
+                       /* Failed glob expressions are left unchanged. */
+                       tlist->next = orig_list;
+                       orig_list = tlist;
+                     }
+                   else
+                     {
+                       /* Failed glob expressions are removed. */
+                       tlist->next = disposables;
+                       disposables = tlist;
+                     }
+               }
+             else
+               {
+                 /* Dequote the string. */
+                 register char *t = dequote_string (tlist->word->word);
+                 free (tlist->word->word);
+                 tlist->word->word = t;
+                 tlist->next = orig_list;
+                 orig_list = tlist;
+               }
+
+             free_array (temp_list);
+             temp_list = (char **)NULL;
+
+             tlist = next;
+           }
+
+         if (disposables)
+           dispose_words (disposables);
+
+         new_list = REVERSE_LIST (orig_list, WORD_LIST *);
+       }
+      else
+       {
+         /* Dequote the words, because we're not performing globbing. */
+         register WORD_LIST *wl = new_list;
+         register char *wp;
+         while (wl)
+           {
+             wp = dequote_string (wl->word->word);
+             free (wl->word->word);
+             wl->word->word = wp;
+             wl = wl->next;
+           }
+       }
+    }
+
+  if (do_vars)
+    {
+      register WORD_LIST *lp;
+      Function *assign_func;
+
+      /* If the remainder of the words expand to nothing, Posix.2 requires
+        that the variable and environment assignments affect the shell's
+        environment. */
+      assign_func = new_list ? assign_in_env : do_assignment;
+
+      for (lp = varlist; lp; lp = lp->next)
+       (*assign_func) (lp->word->word);
+
+      dispose_words (varlist);
+      varlist = (WORD_LIST *)NULL;
+    }
+
+  return (new_list);
+}
+
+/* Return nonzero if S has any unquoted special globbing chars in it.  */
+static int
+unquoted_glob_pattern_p (string)
+     register char *string;
+{
+  register int c;
+  int open = 0;
+
+  while (c = *string++)
+    {
+      switch (c)
+       {
+       case '?':
+       case '*':
+         return (1);
+
+       case '[':
+         open++;
+         continue;
+
+       case ']':
+         if (open)
+           return (1);
+         continue;
+
+       case CTLESC:
+       case '\\':
+         if (*string++ == '\0')
+           return (0);
+       }
+    }
+  return (0);
+}
+
+/* PATHNAME can contain characters prefixed by CTLESC; this indicates
+   that the character is to be quoted.  We quote it here in the style
+   that the glob library recognizes.  If CONVERT_QUOTED_NULLS is non-zero,
+   we change quoted null strings (pathname[0] == CTLNUL) into empty
+   strings (pathname[0] == 0).  If this is called after quote removal
+   is performed, CONVERT_QUOTED_NULLS should be 0; if called when quote
+   removal has not been done (for example, before attempting to match a
+   pattern while executing a case statement), CONVERT_QUOTED_NULLS should
+   be 1. */
+char *
+quote_string_for_globbing (pathname, convert_quoted_nulls)
+     char *pathname;
+     int convert_quoted_nulls;
+{
+  char *temp;
+  register int i;
+
+  temp = savestring (pathname);
+
+  if (convert_quoted_nulls && QUOTED_NULL (pathname))
+    {
+      temp[0] = '\0';
+      return temp;
+    }
+
+  for (i = 0; temp[i]; i++)
+    {
+      if (temp[i] == CTLESC)
+       temp[i++] = '\\';
+    }
+
+  return (temp);
+}
+
+/* Call the glob library to do globbing on PATHNAME. */
+char **
+shell_glob_filename (pathname)
+     char *pathname;
+{
+#if defined (USE_POSIX_GLOB_LIBRARY)
+  extern int glob_dot_filenames;
+  register int i;
+  char *temp, **return_value;
+  glob_t filenames;
+  int glob_flags;
+
+  temp = quote_string_for_globbing (pathname, 0);
+
+  filenames.gl_offs = 0;
+
+  glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
+  glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
+
+  i = glob (temp, glob_flags, (Function *)NULL, &filenames);
+
+  free (temp);
+
+  if (i == GLOB_NOSPACE || i == GLOB_ABEND)
+    return ((char **)NULL);
+
+  if (i == GLOB_NOMATCH)
+    filenames.gl_pathv[0] = (char *)NULL;
+
+  return (filenames.gl_pathv);
+
+#else /* !USE_POSIX_GLOB_LIBRARY */
+
+  char *temp, **results;
+
+  noglob_dot_filenames = !glob_dot_filenames;
+
+  temp = quote_string_for_globbing (pathname, 0);
+
+  results = glob_filename (temp);
+  free (temp);
+
+  if (results && !(GLOB_FAILED(results)))
+    sort_char_array (results);
+
+  return (results);
+#endif /* !USE_POSIX_GLOB_LIBRARY */
+}
+
+/*************************************************
+ *                                              *
+ *     Functions to manage special variables    *
+ *                                              *
+ *************************************************/
+
+/* An alist of name.function for each special variable.  Most of the
+   functions don't do much, and in fact, this would be faster with a
+   switch statement, but by the end of this file, I am sick of switch
+   statements. */
+
+/* The functions that get called. */
+void
+  sv_path (), sv_mail (), sv_uids (), sv_ignoreeof (),
+  sv_glob_dot_filenames (), sv_nolinks (),
+  sv_noclobber (), sv_allow_null_glob_expansion (), sv_strict_posix ();
+
+#if defined (READLINE)
+void sv_terminal (), sv_hostname_completion_file ();
+#endif
+
+#if defined (HISTORY)
+void sv_histsize (), sv_histfilesize (),
+     sv_history_control (), sv_command_oriented_history ();
+#  if defined (BANG_HISTORY)
+void sv_histchars ();
+#  endif
+#endif /* HISTORY */
+
+#if defined (GETOPTS_BUILTIN)
+void sv_optind (), sv_opterr ();
+#endif /* GETOPTS_BUILTIN */
+
+#if defined (JOB_CONTROL)
+void sv_notify ();
+#endif
+
+#define SET_INT_VAR(name, intvar)  intvar = find_variable (name) != 0
+
+struct name_and_function {
+  char *name;
+  VFunction *function;
+} special_vars[] = {
+  { "PATH", sv_path },
+  { "MAIL", sv_mail },
+  { "MAILPATH", sv_mail },
+  { "MAILCHECK", sv_mail },
+
+  { "POSIXLY_CORRECT", sv_strict_posix },
+  { "POSIX_PEDANTIC", sv_strict_posix },
+  /* Variables which only do something special when READLINE is defined. */
+#if defined (READLINE)
+  { "TERM", sv_terminal },
+  { "TERMCAP", sv_terminal },
+  { "TERMINFO", sv_terminal },
+  { "hostname_completion_file", sv_hostname_completion_file },
+  { "HOSTFILE", sv_hostname_completion_file },
+#endif /* READLINE */
+
+  /* Variables which only do something special when HISTORY is defined. */
+#if defined (HISTORY)
+  { "HISTSIZE", sv_histsize },
+  { "HISTFILESIZE", sv_histfilesize },
+  { "command_oriented_history", sv_command_oriented_history },
+#  if defined (BANG_HISTORY)
+  { "histchars", sv_histchars },
+#  endif
+  { "history_control", sv_history_control },
+  { "HISTCONTROL", sv_history_control },
+#endif /* HISTORY */
+
+  { "EUID", sv_uids},
+  { "UID", sv_uids},
+  { "IGNOREEOF", sv_ignoreeof },
+  { "ignoreeof", sv_ignoreeof },
+
+#if defined (GETOPTS_BUILTIN)
+  { "OPTIND", sv_optind },
+  { "OPTERR", sv_opterr },
+#endif /* GETOPTS_BUILTIN */
+
+#if defined (JOB_CONTROL)
+  { "notify", sv_notify },
+#endif  /* JOB_CONTROL */
+
+  { "glob_dot_filenames", sv_glob_dot_filenames },
+  { "allow_null_glob_expansion", sv_allow_null_glob_expansion },
+  { "noclobber", sv_noclobber },
+  { "nolinks", sv_nolinks },
+  { (char *)0x00, (VFunction *)0x00 }
+};
+
+/* 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;
+{
+  int i = 0;
+
+  while (special_vars[i].name)
+    {
+      if (STREQ (special_vars[i].name, name))
+       {
+         (*(special_vars[i].function)) (name);
+         return;
+       }
+      i++;
+    }
+}
+
+/* Set/unset noclobber. */
+void
+sv_noclobber (name)
+     char *name;
+{
+  SET_INT_VAR (name, noclobber);
+}
+
+/* What to do just after the PATH variable has changed. */
+void
+sv_path (name)
+     char *name;
+{
+  /* hash -r */
+  WORD_LIST *args;
+
+  args = make_word_list (make_word ("-r"), NULL);
+  hash_builtin (args);
+  dispose_words (args);
+}
+
+/* What to do just after one of the MAILxxxx variables has changed.  NAME
+   is the name of the variable.  This is called with NAME set to one of
+   MAIL, MAILCHECK, or MAILPATH.  */
+void
+sv_mail (name)
+     char *name;
+{
+  /* If the time interval for checking the files has changed, then
+     reset the mail timer.  Otherwise, one of the pathname vars
+     to the users mailbox has changed, so rebuild the array of
+     filenames. */
+  if (name[4] == 'C')  /* if (strcmp (name, "MAILCHECK") == 0) */
+    reset_mail_timer ();
+  else
+    {
+      free_mail_files ();
+      remember_mail_dates ();
+    }
+}
+
+#if defined (READLINE)
+/* What to do just after one of the TERMxxx variables has changed.
+   If we are an interactive shell, then try to reset the terminal
+   information in readline. */
+void
+sv_terminal (name)
+     char *name;
+{
+  if (interactive_shell && !no_line_editing)
+    rl_reset_terminal (get_string_value ("TERM"));
+}
+
+void
+sv_hostname_completion_file (name)
+     char *name;
+{
+  hostname_list_initialized = 0;
+}
+#endif /* READLINE */
+
+#if defined (HISTORY)
+/* What to do after the HISTSIZE variable changes.
+   If there is a value for this variable (and it is numeric), then stifle
+   the history.  Otherwise, if there is NO value for this variable,
+   unstifle the history. */
+void
+sv_histsize (name)
+     char *name;
+{
+  char *temp = get_string_value (name);
+
+  if (temp && *temp)
+    {
+      int num;
+      if (sscanf (temp, "%d", &num) == 1)
+       {
+         stifle_history (num);
+         if (history_lines_this_session > where_history ())
+           history_lines_this_session = where_history ();
+       }
+    }
+  else
+    unstifle_history ();
+}
+
+/* What to do if the HISTFILESIZE variable changes. */
+void
+sv_histfilesize (name)
+     char *name;
+{
+  char *temp = get_string_value (name);
+
+  if (temp && *temp)
+    {
+      int num;
+      if (sscanf (temp, "%d", &num) == 1)
+       {
+         history_truncate_file (get_string_value ("HISTFILE"), num);
+         if (num <= history_lines_in_file)
+           history_lines_in_file = num;
+       }
+    }
+}
+
+/* What to do after the HISTORY_CONTROL variable changes. */
+void
+sv_history_control (name)
+     char *name;
+{
+  char *temp = get_string_value (name);
+
+  history_control = 0;
+
+  if (temp && *temp)
+    {
+      if (strcmp (temp, "ignorespace") == 0)
+       history_control = 1;
+      else if (strcmp (temp, "ignoredups") == 0)
+       history_control = 2;
+      else if (strcmp (temp, "ignoreboth") == 0)
+       history_control = 3;
+    }
+}
+
+/* What to do after the COMMAND_ORIENTED_HISTORY variable changes. */
+void
+sv_command_oriented_history (name)
+     char *name;
+{
+  SET_INT_VAR (name, command_oriented_history);
+}
+
+#  if defined (BANG_HISTORY)
+/* Setting/unsetting of the history expansion character. */
+
+void
+sv_histchars (name)
+     char *name;
+{
+  char *temp = get_string_value (name);
+
+  if (temp)
+    {
+      history_expansion_char = *temp;
+      if (temp[0] && temp[1])
+       {
+         history_subst_char = temp[1];
+         if (temp[2])
+             history_comment_char = temp[2];
+       }
+    }
+  else
+    {
+      history_expansion_char = '!';
+      history_subst_char = '^';
+      history_comment_char = '#';
+    }
+}
+#  endif /* BANG_HISTORY */
+#endif /* HISTORY */
+
+void
+sv_allow_null_glob_expansion (name)
+     char *name;
+{
+  SET_INT_VAR (name, allow_null_glob_expansion);
+}
+
+/* If the variable exists, then the value of it can be the number
+   of times we actually ignore the EOF.  The default is small,
+   (smaller than csh, anyway). */
+void
+sv_ignoreeof (name)
+     char *name;
+{
+  SHELL_VAR *tmp_var;
+  char *temp;
+  int new_limit;
+
+  eof_encountered = 0;
+
+  tmp_var = find_variable (name);
+  ignoreeof = tmp_var != 0;
+  temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
+  if (temp)
+    {
+      if (sscanf (temp, "%d", &new_limit) == 1)
+       eof_encountered_limit = new_limit;
+      else
+       eof_encountered_limit = 10; /* csh uses 26. */
+    }
+}
+
+/* Control whether * matches .files in globbing.  Yechh. */
+int glob_dot_filenames = 0;
+
+void
+sv_glob_dot_filenames (name)
+     char *name;
+{
+  SET_INT_VAR (name, glob_dot_filenames);
+}
+
+#if defined (JOB_CONTROL)
+/* Job notification feature desired? */
+void
+sv_notify (name)
+     char *name;
+{
+  SET_INT_VAR (name, asynchronous_notification);
+}
+#endif  /* JOB_CONTROL */
+
+/* If the variable `nolinks' exists, it specifies that symbolic links are
+   not to be followed in `cd' commands. */
+void
+sv_nolinks (name)
+     char *name;
+{
+  SET_INT_VAR (name, no_symbolic_links);
+}
+
+/* Don't let users hack the user id variables. */
+void
+sv_uids (name)
+     char *name;
+{
+  char *buff;
+  register SHELL_VAR *v;
+
+  buff = itos (current_user.uid);
+  v = find_variable ("UID");
+  if (v)
+    v->attributes &= ~att_readonly;
+
+  v = bind_variable ("UID", buff);
+  v->attributes |= (att_readonly | att_integer);
+  free (buff);
+
+  buff = itos (current_user.euid);
+  v = find_variable ("EUID");
+  if (v)
+    v->attributes &= ~att_readonly;
+
+  v = bind_variable ("EUID", buff);
+  v->attributes |= (att_readonly | att_integer);
+  free (buff);
+}
+
+#if defined (GETOPTS_BUILTIN)
+void
+sv_optind (name)
+     char *name;
+{
+  char *tt = get_string_value ("OPTIND");
+  int s = 0;
+
+  if (tt && *tt)
+    {
+      s = atoi (tt);
+
+      /* According to POSIX, setting OPTIND=1 resets the internal state
+        of getopt (). */
+      if (s < 0 || s == 1)
+       s = 0;
+    }
+  getopts_reset (s);
+}
+
+void
+sv_opterr (name)
+     char *name;
+{
+  char *tt = get_string_value ("OPTERR");
+  int s = 1;
+
+  if (tt && *tt)
+    s = atoi (tt);
+  sh_opterr = s;
+}
+#endif /* GETOPTS_BUILTIN */
+
+void
+sv_strict_posix (name)
+     char *name;
+{
+  SET_INT_VAR (name, posixly_correct);
+  if (posixly_correct)
+    interactive_comments = 1;
+#if defined (READLINE)
+  posix_readline_initialize (posixly_correct);
+#endif /* READLINE */
+}
diff --git a/subst.h b/subst.h
new file mode 100644 (file)
index 0000000..6584ef9
--- /dev/null
+++ b/subst.h
@@ -0,0 +1,181 @@
+/* subst.h -- Names of externally visible functions in subst.c. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_SUBST_H_)
+#define _SUBST_H_
+
+#include "stdc.h"
+
+/* 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 *));
+
+/* Replace instances of \! in a string with !. */
+extern void unquote_bang __P((char *));
+
+/* Extract the $( construct in STRING, and return a new string.
+   Start extracting at (SINDEX) as if we had just seen "$(".
+   Make (SINDEX) get the position just after the matching ")". */
+extern char *extract_command_subst __P((char *, int *));
+
+/* Extract the $[ construct in STRING, and return a new string.
+   Start extracting at (SINDEX) as if we had just seen "$[".
+   Make (SINDEX) get the position just after the matching "]". */
+extern char *extract_arithmetic_subst __P((char *, int *));
+
+#if defined (PROCESS_SUBSTITUTION)
+/* Extract the <( or >( construct in STRING, and return a new string.
+   Start extracting at (SINDEX) as if we had just seen "<(".
+   Make (SINDEX) get the position just after the matching ")". */
+extern char *extract_process_subst __P((char *, char *, int *));
+#endif /* PROCESS_SUBSTITUTION */
+
+/* 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 a space. */
+extern char *string_list __P((WORD_LIST *));
+
+/* Return a single string of all the words present in LIST, obeying the
+   quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
+   expansion [of $*] appears within a double quoted string, it expands
+   to a single field with the value of each parameter separated by the
+   first character of the IFS variable, or by a <space> if IFS is unset." */
+extern char *string_list_dollar_star __P((WORD_LIST *));
+
+/* Perform quoted null character removal on each element of LIST.
+   This modifies LIST. */
+extern void word_list_remove_quoted_nulls __P((WORD_LIST *));
+
+/* This performs word splitting and quoted null character removal on
+   STRING. */
+extern WORD_LIST *list_string __P((char *, char *, int));
+
+extern char *get_word_from_string __P((char **, char *, char **));
+extern char *strip_trailing_ifs_whitespace __P((char *, char *, int));
+
+/* Given STRING, an assignment string, get the value of the right side
+   of the `=', and bind it to the left side.  If EXPAND is true, then
+   perform parameter expansion, command substitution, and arithmetic
+   expansion on the right-hand side.  Perform tilde expansion in any
+   case.  Do not perform word splitting on the result of expansion. */
+extern int do_assignment __P((char *));
+extern int do_assignment_no_expand __P((char *));
+
+/* Append SOURCE to TARGET at INDEX.  SIZE is the current amount
+   of space allocated to TARGET.  SOURCE can be NULL, in which
+   case nothing happens.  Gets rid of SOURCE by free ()ing it.
+   Returns TARGET in case the location has changed. */
+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((int, char *, int *, int *));
+
+/* Return the word list that corresponds to `$*'. */
+extern WORD_LIST *list_rest_of_args __P((void));
+
+/* Make a single large string out of the dollar digit variables,
+   and the rest_of_args.  If DOLLAR_STAR is 1, then obey the special
+   case of "$*" with respect to IFS. */
+extern char *string_rest_of_args __P((int));
+
+/* Expand STRING by performing parameter expansion, command substitution,
+   and arithmetic expansion.  Dequote the resulting WORD_LIST before
+   returning it, but do not perform word splitting.  The call to
+   remove_quoted_nulls () is in here because word splitting normally
+   takes care of quote removal. */
+extern WORD_LIST *expand_string_unsplit __P((char *, int));
+
+/* Expand STRING just as if you were expanding a word.  This also returns
+   a list of words.  Note that filename globbing is *NOT* done for word
+   or string expansion, just when the shell is expanding a command.  This
+   does parameter expansion, command substitution, arithmetic expansion,
+   and word splitting.  Dequote the resultant WORD_LIST before returning. */
+extern WORD_LIST *expand_string __P((char *, int));
+
+/* De-quoted quoted characters in STRING. */
+extern char *dequote_string __P((char *));
+
+/* Expand WORD, performing word splitting on the result.  This does
+   parameter expansion, command substitution, arithmetic expansion,
+   word splitting, and quote removal. */
+extern WORD_LIST *expand_word __P((WORD_DESC *, int));
+
+/* Expand WORD, but do not perform word splitting on the result.  This
+   does parameter expansion, command substitution, arithmetic expansion,
+   and quote removal. */
+extern WORD_LIST *expand_word_no_split __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((int));
+
+/* Perform quote removal on STRING.  If QUOTED > 0, assume we are obeying the
+   backslash quoting rules for within double quotes. */
+extern char *string_quote_removal __P((char *, int));
+
+/* Perform quote removal on word WORD.  This allocates and returns a new
+   WORD_DESC *. */
+extern WORD_DESC *word_quote_removal __P((WORD_DESC *, int));
+
+/* Perform quote removal on all words in LIST.  If QUOTED is non-zero,
+   the members of the list are treated as if they are surrounded by
+   double quotes.  Return a new list, or NULL if LIST is NULL. */
+extern WORD_LIST *word_list_quote_removal __P((WORD_LIST *, int));
+
+/* 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 *));
+
+/* Take the list of words in LIST and do the various substitutions.  Return
+   a new list of words which is the expanded list, and without things like
+   variable assignments. */
+extern WORD_LIST *expand_words __P((WORD_LIST *));
+
+/* Same as expand_words (), but doesn't hack variable or environment
+   variables. */
+extern WORD_LIST *expand_words_no_vars __P((WORD_LIST *));
+
+/* PATHNAME can contain characters prefixed by CTLESC;; this indicates
+   that the character is to be quoted.  We quote it here in the style
+   that the glob library recognizes.  If CONVERT_QUOTED_NULLS is non-zero,
+   we change quoted null strings (pathname[0] == CTLNUL) into empty
+   strings (pathname[0] == 0).  If this is called after quote removal
+   is performed, CONVERT_QUOTED_NULLS should be 0; if called when quote
+   removal has not been done (for example, before attempting to match a
+   pattern while executing a case statement), CONVERT_QUOTED_NULLS should
+   be 1. */
+extern char *quote_string_for_globbing __P((char *, int));
+
+/* Call the glob library to do globbing on PATHNAME. */
+extern char **shell_glob_filename __P((char *));
+
+/* 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. */
+extern void stupidly_hack_special_variables __P((char *));
+
+#endif /* !_SUBST_H_ */
diff --git a/support/PORTING b/support/PORTING
new file mode 100644 (file)
index 0000000..1869472
--- /dev/null
@@ -0,0 +1,22 @@
+if _mkfifo cannot be found, add "-DMKFIFO_MISSING" to SYSDEP_CFLAGS in
+your machine's entry in machines.h.
+
+If bash compiles, but hangs when executing a non-builtin, there is a
+problem with the defines in your /usr/include/sys/wait.h.  If you
+don't have one, there is a problem in our defines.  At any rate,
+perhaps you have a partially POSIX system, instead of a fully
+operational one.  Try defining _POSIX_SOURCE just before the inclusion
+of <sys/wait.h> in jobs.h, and then undefining it immediately after
+the inclusion.
+
+Finding out if your system has something (like setpgid, for example)
+You can always do "nm -o /lib/*.a | grep setpgid".  If an entry for
+the function appears, you have it, and you might have to link with
+that library by adding "#defined REQUIRED_LIBRARIES -lfoo" to the
+entry in machines.h.
+
+If you seem to be going around in circles, and they are related to
+job control and posixness, try #undef HAVE_UNISTD_H in the entry for
+your machine in machines.h.  This can work by keeping unistd.h from
+defining _POSIX_VERSION, which in turn prevents bash from assuming
+full Posix semantics.
diff --git a/support/SYMLINKS b/support/SYMLINKS
new file mode 100644 (file)
index 0000000..bd36b7e
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# symlink map for bash source tree
+#
+#      link name               link target
+#
+lib/readline/doc/texindex.c    ../../doc-support/texindex.c
+#
+lib/readline/tilde.c           ../tilde/tilde.c
+lib/readline/tilde.h           ../tilde/tilde.h
+lib/readline/posixstat.h       ../posixheaders/posixstat.h
+lib/readline/ansi_stdlib.h     ../posixheaders/ansi_stdlib.h
+lib/readline/memalloc.h                ../posixheaders/memalloc.h
+lib/readline/xmalloc.c         ../malloc/xmalloc.c
+#
+lib/tilde/memalloc.h           ../posixheaders/memalloc.h
+#
+lib/doc-support/getopt.h       ../../builtins/getopt.h
+#
+posixstat.h                    lib/posixheaders/posixstat.h
+ansi_stdlib.h                  lib/posixheaders/ansi_stdlib.h
+stdc.h                         lib/posixheaders/stdc.h
+memalloc.h                     lib/posixheaders/memalloc.h
+filecntl.h                     lib/posixheaders/filecntl.h
diff --git a/support/bash.xbm b/support/bash.xbm
new file mode 100644 (file)
index 0000000..5c32613
--- /dev/null
@@ -0,0 +1,59 @@
+From: Simon Marshall <sm2@sequent.cc.hull.ac.uk>
+Date: Wed, 8 May 91 17:15:58 +0100
+To: bug-bash@ai.mit.edu
+Subject: X bitmap for bash
+
+        Since other GNU software comes with its very own X bitmap, I
+     thought it was about time bash had one too & here it is!  To use,
+     stick the stuff after my signature in a file <path>/bash.xbm.  If
+     using a twm window manager, insert the lines:
+
+IconDirectory           "<path>"
+Icons {
+        "<xterm title>" "bash.xbm"
+}
+        in your ~/.twmrc file.  The <xterm title> can be a prefix, so if
+     you have titles "bash@machine", the prefix "bash" will do.  I'm not
+     familiar enough with other window managers, but they should be
+     similar.
+
+        If you like it, you're welcome to it...
+
+        Simon.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#define bash_width 64
+#define bash_height 48
+static char bash_bits[] = {
+   0x00, 0x60, 0x06, 0x30, 0x04, 0x00, 0x00, 0x00, 0x60, 0x98, 0x01, 0x40,
+   0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0xa0, 0x80, 0x80, 0xff, 0x00, 0x00,
+   0x06, 0x00, 0x1c, 0x03, 0xe1, 0x5f, 0x03, 0x00, 0x02, 0x00, 0x22, 0x0c,
+   0x5d, 0xf4, 0x0e, 0x00, 0xe1, 0x02, 0x09, 0x19, 0x17, 0x91, 0x3d, 0x00,
+   0xf8, 0x87, 0x40, 0x90, 0x88, 0x88, 0x6e, 0x00, 0x8e, 0x9b, 0x04, 0x62,
+   0x22, 0x22, 0xd6, 0x00, 0x02, 0xee, 0x4c, 0x68, 0x44, 0x44, 0x6c, 0x01,
+   0x02, 0xf8, 0xa1, 0x4a, 0x11, 0x11, 0xb1, 0x02, 0x05, 0xa0, 0x22, 0xe0,
+   0x88, 0x88, 0x68, 0x03, 0x42, 0x50, 0x5d, 0x40, 0x22, 0x22, 0xa2, 0x05,
+   0x11, 0x81, 0x00, 0x44, 0x44, 0x44, 0x44, 0x07, 0x02, 0x20, 0x84, 0x60,
+   0x11, 0x11, 0xd1, 0x0d, 0x02, 0x0a, 0x02, 0xc0, 0x88, 0x88, 0x48, 0x0b,
+   0x44, 0x40, 0x00, 0x42, 0x22, 0x22, 0xa2, 0x1d, 0x24, 0x08, 0x02, 0x64,
+   0x44, 0x44, 0xc4, 0x1a, 0x08, 0x00, 0x20, 0x20, 0x11, 0x11, 0x91, 0x15,
+   0x88, 0x00, 0x00, 0xe1, 0xff, 0xff, 0xff, 0x1a, 0x10, 0x08, 0x22, 0x10,
+   0x00, 0x00, 0xc0, 0x15, 0x31, 0x40, 0x00, 0xf2, 0x03, 0xc0, 0xc1, 0x1a,
+   0x41, 0x24, 0x48, 0x6c, 0x06, 0x80, 0xc1, 0x15, 0x82, 0x01, 0x00, 0x66,
+   0x06, 0x80, 0xc1, 0x1a, 0x04, 0x22, 0x12, 0x67, 0x06, 0x80, 0xc1, 0x15,
+   0x0a, 0x04, 0xe0, 0x66, 0xe6, 0xb8, 0xc7, 0x1a, 0x09, 0xf0, 0x17, 0xee,
+   0xb3, 0xa5, 0xcf, 0x15, 0x30, 0x00, 0x00, 0x6e, 0x86, 0x8d, 0xcd, 0x1a,
+   0x00, 0x01, 0x80, 0x67, 0xe6, 0xbd, 0xcd, 0x15, 0x00, 0x46, 0x40, 0x66,
+   0xb6, 0xb1, 0xcd, 0x1a, 0x00, 0x38, 0x3c, 0x66, 0xb6, 0xa5, 0xcd, 0x15,
+   0x00, 0x00, 0x02, 0xf6, 0xe3, 0x9d, 0xdd, 0x1a, 0x00, 0x04, 0x60, 0x06,
+   0x00, 0x00, 0xc0, 0x15, 0x00, 0x04, 0x40, 0xfe, 0xff, 0xff, 0xff, 0x1a,
+   0x00, 0x02, 0x80, 0x12, 0x11, 0x11, 0x91, 0x15, 0x00, 0x00, 0x00, 0x8a,
+   0x88, 0x88, 0x88, 0x1a, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0xa2, 0x15,
+   0x00, 0x00, 0x00, 0x46, 0x44, 0x44, 0xc4, 0x9a, 0x00, 0x00, 0x00, 0x12,
+   0x11, 0x11, 0x91, 0xb5, 0x00, 0x00, 0x10, 0x8a, 0x88, 0x88, 0x88, 0xba,
+   0x00, 0x00, 0x10, 0x22, 0x22, 0x22, 0xa2, 0xd5, 0x00, 0x00, 0x30, 0xc6,
+   0x44, 0x44, 0xcc, 0xdf, 0x00, 0x20, 0x39, 0x96, 0x15, 0x51, 0x99, 0xf5,
+   0x80, 0xf2, 0x56, 0x8b, 0x9a, 0xea, 0x9b, 0xff, 0xc1, 0xad, 0x5e, 0xaf,
+   0xbb, 0xfa, 0xba, 0xdf, 0x22, 0x9b, 0xae, 0xd7, 0x54, 0x5d, 0xd7, 0xbf,
+   0x3b, 0x32, 0xce, 0xff, 0xff, 0xff, 0xff, 0xab, 0xae, 0x2b, 0x59, 0xaf,
+   0xd4, 0xae, 0x2e, 0xc3, 0xdd, 0x43, 0xa9, 0xd1, 0xba, 0xae, 0x2c, 0xcd};
diff --git a/support/bashbug.sh b/support/bashbug.sh
new file mode 100644 (file)
index 0000000..fb5600b
--- /dev/null
@@ -0,0 +1,84 @@
+#!/bin/sh -
+#
+# bashbug - create a bug report and mail it to bug-bash@prep.ai.mit.edu
+#
+# configuration section:
+#      these variables are filled in by the make target in cpp-Makefile
+#
+MACHINE="@MACHINE@"
+OS="@OS@"
+CC="@CC@"
+CFLAGS="@CFLAGS@"
+RELEASE="@RELEASE@"
+PATCHLEVEL="@PATCHLEVEL@"
+
+PATH=/bin:/usr/bin:usr/local/bin:$PATH
+export PATH
+
+TEMP=/tmp/bashbug.$$
+
+BUGADDR=${1-bug-bash@prep.ai.mit.edu}
+
+: ${EDITOR=emacs}
+
+trap 'rm -f $TEMP $TEMP.x; exit 1' 1 2 3 13 15
+trap 'rm -f $TEMP $TEMP.x' 0
+
+UN=
+if (uname) >/dev/null 2>&1; then
+       UN=`uname -a`
+fi
+
+if [ -f /usr/lib/sendmail ] ; then
+       RMAIL="/usr/lib/sendmail"
+elif [ -f /usr/sbin/sendmail ] ; then
+       RMAIL="/usr/sbin/sendmail"
+else
+       RMAIL=rmail
+fi
+
+cat > $TEMP <<EOF
+From: ${USER}
+To: ${BUGADDR}
+Subject: [50 character or so descriptive subject here (for reference)]
+
+Configuration Information [Automatically generated, do not change]:
+Machine: $MACHINE
+OS: $OS
+Compiler: $CC
+Compilation CFLAGS: $CFLAGS
+uname output: $UN
+
+Bash Version: $RELEASE
+Patch Level: $PATCHLEVEL
+
+Description:
+        [Detailed description of the problem, suggestion, or complaint.]
+
+Repeat-By:
+        [Describe the sequence of events that causes the problem
+        to occur.]
+
+Fix:
+        [Description of how to fix the problem.  If you don't know a
+        fix for the problem, don't include this section.]
+EOF
+
+chmod u+w $TEMP
+cp $TEMP $TEMP.x
+
+if $EDITOR $TEMP
+then
+       if cmp -s $TEMP $TEMP.x
+       then
+               echo "File not changed, no bug report submitted."
+               exit
+       fi
+
+       ${RMAIL} $BUGADDR < $TEMP || {
+               cat $TEMP >> $HOME/dead.bashbug
+               echo "$0: mail failed: report saved in $HOME/dead.bashbug" >&2
+       }
+fi
+
+exit 0
diff --git a/support/cat-s b/support/cat-s
new file mode 100644 (file)
index 0000000..87ba163
--- /dev/null
@@ -0,0 +1,16 @@
+# This awk script is called from within Makefile to strip multiple blank
+# lines from stdin.
+BEGIN { newlines = 0 }
+{
+  if (NF == 0)
+    newlines = 1;
+  else
+    {
+      if (newlines)
+       {
+         printf "\n";
+         newlines = 0;
+       }
+      print $0;
+    }
+}
diff --git a/support/clone-bash b/support/clone-bash
new file mode 100755 (executable)
index 0000000..89e0752
--- /dev/null
@@ -0,0 +1,95 @@
+#! /bin/sh
+#
+#
+src=src
+case "$1" in
+-s)    shift; src=$1; shift ;;
+esac
+
+if [ ! -d $1 ]; then
+       mkdir $1
+fi
+
+prog=`basename $0`
+
+echo "${prog}: creating clone of bash source tree (from $src) in $1"
+
+case $src in
+/*)    abs=yes ;;
+esac
+
+d=${PWD-`pwd`}
+
+cd $1 || { echo "$0: cannot cd to $1" ; exit 1; }
+
+d=$d/$1
+
+SUBDIRS="CWRU builtins documentation examples support tests"
+LIBDIRS="malloc termcap glob readline tilde malloclib posixheaders doc-support"
+CWRUDIRS="misc"
+
+mkdir $SUBDIRS
+for i in $SUBDIRS
+do
+       cd $i
+       case "$abs" in
+       yes)    ln -s $src/$i/* . ;;
+       *)      ln -s ../../$src/$i/* . ;;
+       esac
+       echo -n $i..
+       cd ..
+done
+cd $d
+
+cd CWRU
+for i in $CWRUDIRS
+do
+       rm -f $i
+       mkdir $i
+       cd $i
+       case "$abs" in
+       yes)    ln -s $src/CWRU/$i/* . ;;
+       *)      ln -s ../../../$src/CWRU/$i/* . ;;
+       esac
+       echo -n "CWRU/$i.."
+       cd ..
+done
+cd $d
+
+if [ ! -d lib ] ; then
+       mkdir lib
+fi
+
+cd lib
+mkdir $LIBDIRS
+
+for i in $LIBDIRS
+do
+       cd $i
+       case "$abs" in
+       yes)    ln -s $src/lib/$i/* . ;;
+       *)      ln -s ../../../$src/lib/$i/* . ;;
+       esac
+       echo -n "lib/$i.."
+       cd ..
+done
+
+cd $d
+
+case "$abs" in
+yes)   ln -s $src/.[a-z]* . ; ln -s $src/* . 2>&1 | grep -v exists ;;
+*)     ln -s ../$src/.[a-z]* . ; ln -s ../$src/* . 2>&1 | grep -v exists ;;
+esac
+
+echo -n src..
+
+SPECIAL="parser-built y.tab.h y.tab.c"
+for x in $SPECIAL
+do
+       rm -f $x
+       cp ../$src/$x .
+done
+
+echo special
+
+exit 0
diff --git a/support/cppmagic b/support/cppmagic
new file mode 100755 (executable)
index 0000000..b0a951c
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/sh
+# Return a full cpp specification, complete with system dependent flags.
+#
+# Syntax: cppmagic [ program-to-generate-flags [ guessed-cpp ]]
+#
+# If only one arg is present it is the name of a program to invoke
+# which should generate -Dfoo defines.
+#
+# If two args are present the second arg is the name of the C
+# preprocessor to use.
+#
+# Invoked with no args, provides a C preprocessor name and
+# -traditional flag if that is appropriate.
+#
+#  ../Makefile calls this file thusly: "cppmagic getcppsyms".
+#
+#  Typical output:
+#
+#    /lib/cpp -Dunix -Dm68k
+#
+
+Cpp=
+
+if [ "$2" ]; then
+   Cpp=$2
+else
+   for cpp in /lib/cpp /usr/lib/cpp /usr/ccs/lib/cpp; do
+      if [ -f $cpp ]; then
+        Cpp=$cpp
+      fi
+   done
+   if [ "$Cpp" = "" ]; then
+      Cpp=cpp
+   fi
+fi
+
+TRADITIONAL=
+FLAGS=
+
+# First flag might be `-traditional' if this is Gnu Cpp.
+unknown_flag=`$Cpp -traditional /dev/null 2>&1 |
+               egrep 'known|recognized|valid|bad|legal'`
+if [ "$unknown_flag" = "" ]; then
+  TRADITIONAL=-traditional
+fi
+
+if [ "$1" ]; then
+   FLAGS=`$1`
+fi
+
+echo $Cpp $TRADITIONAL $FLAGS
diff --git a/support/fixlinks b/support/fixlinks
new file mode 100755 (executable)
index 0000000..b82ca4d
--- /dev/null
@@ -0,0 +1,61 @@
+#! /bin/sh
+#
+# fixlinks - make symlinks in the bash source tree so that there is
+#           exactly one version of any given source file.
+#
+#
+
+SRCDIR=.
+while [ $# -gt 0 ]; do
+       case "$1" in
+       -s)     shift; SRCDIR=$1 ;;
+       -u)     unfix=yes ;;
+       -*)     echo "$0: $1: bad option" 1>&2
+               echo "$0: usage: $0 [-u] [-s srcdir] [linkmap]" 1>&2
+               exit 1;;
+       *)      break ;;
+       esac
+       shift
+done
+
+if [ ! -d $SRCDIR/builtins ]; then
+       echo "$0: must be run with valid -s argument or from source directory" 1>&2
+       exit 1
+fi
+
+if [ $# -eq 0 ]; then
+       linkfile=$SRCDIR/support/SYMLINKS
+else
+       linkfile=$1     
+fi
+
+if [ ! -f "$linkfile" ]; then
+       echo "$0: symlink map file \`$linkfile' does not exist"
+       exit 1
+fi
+
+rm -f /tmp/z
+if (ln -s /dev/null /tmp/z) >/dev/null 2>&1; then
+       LN="ln -s"
+else
+       LN=ln
+fi
+
+while read name target
+do
+       case "$name" in
+       \#*)    continue;;
+       esac
+
+       rm -f $name
+       case "$unfix" in
+       yes)    dirname=`expr "$name" ':' '^\(.*\)/[^/]*'`
+               [ -z "$dirname" ] && dirname=.
+               cp $dirname/$target $name
+               echo $target copied to $name ;;
+       *)      $LN $target $name ; echo "$name -> $target" ;;
+       esac
+
+done < $linkfile
+
+exit 0
diff --git a/support/getcppsyms.c b/support/getcppsyms.c
new file mode 100644 (file)
index 0000000..eb4c72d
--- /dev/null
@@ -0,0 +1,428 @@
+/* getcppsyms.c - Find unique compiler symbols. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Some cpp's do not define any symbols, but instead let /bin/cc do it
+   for them.  For such machines, running this file may prove useful.  It
+   outputs the list of symbols which /bin/cc or /lib/cpp define and which
+   we had the foresight to guess at. */
+
+#include <stdio.h>
+main ()
+{
+#if defined (__BSD_4_4__)
+  printf ("-D__BSD_4_4__");
+#endif /* __BSD_4_4__ */
+#if defined (CMU)
+  printf (" -DCMU");
+#endif /* CMU */
+#if defined (_COFF)
+  printf (" -D_COFF");
+#endif /* _COFF */
+#if defined (DGUX)
+  printf (" -DDGUX");
+#endif /* DGUX */
+#if defined (GOULD_PN)
+  printf (" -DGOULD_PN");
+#endif /* GOULD_PN */
+#if defined (MACH)
+  printf (" -DMACH");
+#endif /* MACH */
+#if defined (MIPSEB)
+  printf (" -DMIPSEB");
+#endif /* MIPSEB */
+#if defined (MIPSEL)
+  printf (" -DMIPSEL");
+#endif /* MIPSEL */
+#if defined (MULTIMAX)
+  printf (" -DMULTIMAX");
+#endif /* MULTIMAX */
+#if defined (M_UNIX)
+  printf (" -DM_UNIX");
+#endif /* M_UNIX */
+#if defined (M_XENIX)
+  printf (" -DM_XENIX");
+#endif /* M_XENIX */
+#if defined (_M_XENIX)
+  printf (" -D_M_XENIX");
+#endif /* _M_XENIX */
+#if defined (NeXT)
+  printf (" -DNeXT");
+#endif /* NeXT */
+#if defined (__PARAGON__)
+  printf (" -D__PARAGON__");
+#endif /* __PARAGON__ */
+#if defined (_PGC_)
+  printf (" -D_PGC_");
+#endif /* _PGC_ */
+#if defined (__PGC__)
+  printf (" -D__PGC__");
+#endif /* __PGC__ */
+#if defined (RES)
+  printf (" -DRES");
+#endif /* RES */
+#if defined (RISC6000)
+  printf (" -DRISC6000");
+#endif /* RISC6000 */
+#if defined (RT)
+  printf (" -DRT");
+#endif /* RT */
+#if defined (SYSTYPE_BSD)
+  printf (" -DSYSTYPE_BSD");
+#endif /* SYSTYPE_BSD */
+#if defined (SYSTYPE_SYSV)
+  printf (" -DSYSTYPE_SYSV");
+#endif /* SYSTYPE_SYSV */
+#if defined (Sun386i)
+  printf (" -DSun386i");
+#endif /* Sun386i */
+#if defined (Tek4132)
+  printf (" -DTek4132");
+#endif /* Tek4132 */
+#if defined (Tek4300)
+  printf (" -DTek4300");
+#endif /* Tek4300 */
+#if defined (UMAXV)
+  printf (" -DUMAXV");
+#endif /* UMAXV */
+#if defined (USGr4)
+  printf (" -DUSGr4");
+#endif /* USGr4 */
+#if defined (USGr4_2)
+  printf (" -DUSGr4_2");
+#endif /* USGr4_2 */
+#if defined (__SVR4_2__)
+  printf (" -D__SVR4_2__");
+#endif /* __SVR4_2__ */
+#if defined (Xenix286)
+  printf (" -DXenix286");
+#endif /* Xenix286 */
+#if defined (_AIX)
+  printf (" -D_AIX");
+#endif /* _AIX */
+#if defined (_AIX370)
+  printf (" -D_AIX370");
+#endif /* _AIX370 */
+#if defined (_IBMESA)
+  printf (" -D_IBMESA");
+#endif /* _IBMESA */
+#if defined (__ibmesa)
+  printf (" -D__ibmesa");
+#endif /* __ibmesa */
+#if defined (_U370)
+  printf (" -D_U370");
+#endif /* _U370 */
+#if defined (_NLS)
+  printf (" -D_NLS");
+#endif /* _NLS */
+#if defined (_CX_UX)
+  printf (" -D_CX_UX");
+#endif /* _CX_UX */
+#if defined (_IBMR2)
+  printf (" -D_IBMR2");
+#endif /* _IBMR2 */
+#if defined (_M88K)
+  printf (" -D_M88K");
+#endif /* _M88K */
+#if defined (_M88KBCS_TARGET)
+  printf (" -D_M88KBCS_TARGET");
+#endif /* _M88KBCS_TARGET */
+#if defined (__DGUX__)
+  printf (" -D__DGUX__");
+#endif /* __DGUX__ */
+#if defined (__UMAXV__)
+  printf (" -D__UMAXV__");
+#endif /* __UMAXV__ */
+#if defined (__m88k)
+  printf (" -D__m88k");
+#endif /* __m88k */
+#if defined (__uxpm__)
+  printf (" -DUSGr4 -Du370 -D__uxpm__");
+#endif /* __uxpm__ */
+#if defined (__uxps__)
+  printf (" -D__svr4__ -D__uxps__");
+#endif /* __uxps__ */
+#if defined (alliant)
+  printf (" -Dalliant");
+#endif /* alliant */
+#if defined (alpha)
+  printf (" -Dalpha");
+#endif /* alpha */
+#if defined (__alpha)
+  printf (" -D__alpha");
+#endif /* __alpha */
+#if defined (aix)
+  printf (" -Daix");
+#endif /* aix */
+#if defined (aixpc)
+  printf (" -Daixpc");
+#endif /* aixpc */
+#if defined (apollo)
+  printf (" -Dapollo");
+#endif /* apollo */
+#if defined (ardent)
+  printf (" -Dardent");
+#endif /* ardent */
+#if defined (att386)
+  printf (" -Datt386");
+#endif /* att386 */
+#if defined (att3b)
+  printf (" -Datt3b");
+#endif /* att3b */
+#if defined (bsd4_2)
+  printf (" -Dbsd4_2");
+#endif /* bsd4_2 */
+#if defined (bsd4_3)
+  printf (" -Dbsd4_3");
+#endif /* bsd4_3 */
+#if defined (__bsdi__)
+  printf (" -D__bsdi__");
+#endif /* __bsdi__ */
+#if defined (bsdi)
+  printf (" -Dbsdi");
+#endif /* bsdi */
+#if defined (__386BSD__)
+  printf (" -D__386BSD__");
+#endif /* __386BSD__ */
+#if defined (cadmus)
+  printf (" -Dcadmus");
+#endif /* cadmus */
+#if defined (clipper)
+  printf (" -Dclipper");
+#endif /* clipper */
+#if defined (concurrent)
+  printf (" -Dconcurrent");
+#endif /* concurrent */
+#if defined (convex) || defined (__convex__) || defined (__convexc__)
+#  if !defined (__GNUC__)
+  printf (" -pcc");
+#  endif /* !__GNUC__ */
+  printf (" -Dconvex");
+#endif /* convex */
+#if defined (dmert)
+  printf (" -Ddmert");
+#endif /* dmert */
+#if defined (gcos)
+  printf (" -Dgcos");
+#endif /* gcos */
+#if defined (gcx)
+  printf (" -Dgcx");
+#endif /* gcx */
+#if defined (gould)
+  printf (" -Dgould");
+#endif /* gould */
+#if defined (hbullx20)
+  printf (" -Dhbullx20");
+#endif /* hbullx20 */
+#if defined (hcx)
+  printf (" -Dhcx");
+#endif /* hcx */
+#if defined (host_mips)
+  printf (" -Dhost_mips");
+#endif /* host_mips */
+#if defined (hp9000) || defined (__hp9000)
+  printf (" -Dhp9000");
+#endif /* hp9000 || __hp9000 */
+#if defined (hp9000s200) || defined (__hp9000s200)
+  printf (" -Dhp9000s200");
+#endif /* hp9000s200 || __hp9000s200 */
+#if defined (hp9000s300) || defined (__hp9000s300)
+  printf (" -Dhp9000s300");
+#endif /* hp9000s300 || __hp9000s300 */
+#if defined (hp9000s500) || defined (__hp9000s500)
+  printf (" -Dhp9000s500");
+#endif /* hp9000s500 || __hp9000s500 */
+#if defined (hp9000s700) || defined (__hp9000s700)
+  printf (" -Dhp9000s700");
+#endif /* hp9000s700 || __hp9000s700 */
+#if defined (hp9000s800) || defined (__hp9000s800)
+  printf (" -Dhp9000s800");
+#endif /* hp9000s800 || __hp9000s800 */
+#if defined (hppa) || defined (__hppa)
+  printf (" -Dhppa");
+#endif /* hppa || __hppa */
+#if defined (hpux) || defined (__hpux)
+  printf (" -Dhpux");
+#endif /* hpux */
+#if defined (__hp_osf)
+  printf (" -D__hp_osf");
+#endif /* __hp_osf */
+#if defined (i386)
+  printf (" -Di386");
+#endif /* i386 */
+#if defined (__i386__)
+  printf (" -D__i386__");
+#endif
+#if defined (__i860)
+  printf(" -D__i860");
+#endif /* __i860 */
+#if defined (__i860__)
+  printf(" -D__i860__");
+#endif /* __i860__ */
+#if defined (ibm)
+  printf (" -Dibm");
+#endif /* ibm */
+#if defined (ibm032)
+  printf (" -Dibm032");
+#endif /* ibm032 */
+#if defined (ibmrt)
+  printf (" -Dibmrt");
+#endif /* ibmrt */
+#if defined (interdata)
+  printf (" -Dinterdata");
+#endif /* interdata */
+#if defined (is68k)
+  printf (" -Dis68k");
+#endif /* is68k */
+#if defined (ksr1)
+  printf (" -Dksr1");
+#endif /* ksr1 */
+#if defined (__ksr1__)
+  printf (" -D__ksr1__");
+#endif /* __ksr1__ */
+#if defined (linux)
+  printf (" -Dlinux");
+#endif /* linux */
+#if defined (__linux__)
+  printf (" -D__linux__");
+#endif /* __linux__ */
+#if defined (luna88k)
+  printf (" -Dluna88k");
+#endif /* luna88k */
+#if defined (m68k)
+  printf (" -Dm68k");
+#endif /* m68k */
+#if defined (m88k)
+  printf (" -Dm88k");
+#endif /* m88k */
+#if defined (mc68010)
+  printf (" -Dmc68010");
+#endif /* mc68010 */
+#if defined (mc68020)
+  printf (" -Dmc68020");
+#endif /* mc68020 */
+#if defined (mc68030)
+  printf (" -Dmc68030");
+#endif /* mc68030 */
+#if defined (mc68040)
+  printf (" -Dmc68040");
+#endif /* mc68040 */
+#if defined (mc68k32)
+  printf (" -Dmc68k32");
+#endif /* mc68k32 */
+#if defined (mips)
+  printf (" -Dmips");
+#endif /* mips */
+#if defined (n16)
+  printf (" -Dn16");
+#endif /* n16 */
+#if defined __nonstopux
+  printf (" -D__nonstopux");
+#endif
+#if defined (ns32000)
+  printf (" -Dns32000");
+#endif /* ns32000 */
+#if defined (os)
+  printf (" -Dos");
+#endif /* os */
+#if defined (osf)
+  printf (" -Dosf");
+#endif /* osf */
+#if defined (__osf__)
+  printf (" -D__osf__");
+#endif /* __osf__ */
+#if defined (__OSF1__)
+  printf(" -D__OSF1__");
+#endif /* __OSF1__ */
+#if defined (pdp11)
+  printf (" -Dpdp11");
+#endif /* pdp11 */
+#if defined (plexus)
+  printf (" -Dplexus")
+#endif /* plexus */
+#if defined (pyr)
+  printf (" -Dpyr");
+#endif /* pyr */
+#if defined (scs)
+  printf (" -Dscs");
+#endif /* scs */
+#if defined (sequent)
+  printf (" -Dsequent");
+#endif /* sequent */
+#if defined (sgi)
+  printf (" -Dsgi");
+#endif /* sgi */
+#if defined (sony)
+  printf (" -Dsony");
+#endif /* sony */
+#if defined (sparc)
+  printf (" -Dsparc");
+#endif /* sparc */
+#if defined (stardent)
+  printf (" -Dstardent");
+#endif /* stardent */
+#if defined (sun)
+  printf (" -Dsun");
+#endif /* sun */
+#if defined (sun2)
+  printf (" -Dsun2");
+#endif /* sun2 */
+#if defined (sun3)
+  printf (" -Dsun3");
+#endif /* sun3 */
+#if defined (sun4)
+  printf (" -Dsun4");
+#endif /* sun4 */
+#if defined (__svr4__)
+  printf (" -D__svr4__");
+#endif /* __svr4__ */
+#if defined (tower32)
+  printf (" -Dtower32");
+#endif /* tower32 */
+#if defined (tss)
+  printf (" -Dtss");
+#endif /* tss */
+#if defined (u370)
+  printf (" -Du370");
+#endif /* u370 */
+#if defined (u3b)
+  printf (" -Du3b");
+#endif /* u3b */
+#if defined (u3b2)
+  printf (" -Du3b2");
+#endif /* u3b2 */
+#if defined (u3b20d)
+  printf (" -Du3b20d");
+#endif /* u3b20d */
+#if defined (u3b5)
+  printf (" -Du3b5");
+#endif /* u3b5 */
+#if defined (ultrix)
+  printf (" -Dultrix");
+#endif /* ultrix */
+#if defined (unix)
+  printf (" -Dunix");
+#endif /* unix */
+#if defined (vax)
+  printf (" -Dvax");
+#endif /* vax */
+
+  printf ("\n");
+  exit (0);
+}
diff --git a/support/inpath b/support/inpath
new file mode 100755 (executable)
index 0000000..95f28bc
--- /dev/null
@@ -0,0 +1,19 @@
+#! /bin/sh
+#
+# Search $PATH for a file the same name as $1; return TRUE if found.
+#
+
+command=$1
+[ -n "$command" ] || exit 1
+
+set `echo $PATH | sed 's/^:/.:/
+                       s/::/:.:/g
+                       s/:$/:./
+                       s/:/ /g'`
+       
+while [ $# -ne 0 ] ; do
+       [ -f $1/$command ] && exit 0    # test -x not universal
+       shift
+done
+
+exit 1
diff --git a/support/install.sh b/support/install.sh
new file mode 100755 (executable)
index 0000000..ea88212
--- /dev/null
@@ -0,0 +1,235 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/support/mkdirs b/support/mkdirs
new file mode 100755 (executable)
index 0000000..52228d1
--- /dev/null
@@ -0,0 +1,29 @@
+#! /bin/sh
+#
+# mkdirs - a work-alike for `mkdir -p'
+#
+# Chet Ramey
+# chet@po.cwru.edu
+
+for dir
+do
+
+       [ -d "$dir" ] && continue
+
+       tomake=$dir
+       while [ "$dir" ]; do
+               # dir=${dir%/*}
+               # dir=`expr "$dir" ':' '^\(/.*\)/[^/]*'`
+               dir=`expr "$dir" ':' '^\(.*\)/[^/]*'`
+               tomake="$dir $tomake"
+       done
+
+       for d in $tomake
+       do
+               [ -d $d ] && continue
+               echo mkdir $d
+               mkdir $d
+       done
+done
+
+exit 0
diff --git a/support/mklinks b/support/mklinks
new file mode 100755 (executable)
index 0000000..612aa99
--- /dev/null
@@ -0,0 +1,41 @@
+
+# Yet another script which requires an already built Bash.
+#
+# This makes links in the current directory to the directory specified as
+# the first argument.
+#
+
+topdir=$1
+
+if [ ! "$topdir" ]; then
+  echo "No directory specified.  Read the script $0."
+  exit 1
+fi
+
+function clone_files ()
+{
+  local dir=$1;
+  local files;
+
+  files=$(cd $dir; echo *);
+
+  if [ ! "$files" ]; then
+    return 0;
+  fi
+
+  for filename in $files; do
+    if [ -d $dir/$filename ]; then
+      # If the file to clone is this directory, then skip it.
+      if [ $(cd $dir/$filename; pwd) = $(pwd) ]; then
+       continue;
+      fi
+      mkdir $filename;
+      (cd $filename; clone_files ../$dir/$filename)
+    else
+      ln -s $dir/$filename .;
+    fi
+  done
+  rm -f \#* *~ .*~ *.bak .*.bak  *.tmp .*.tmp *.o core a.out;
+}
+
+clone_files $topdir
diff --git a/support/mkmachtype b/support/mkmachtype
new file mode 100755 (executable)
index 0000000..00b7403
--- /dev/null
@@ -0,0 +1,279 @@
+#!/bin/sh
+# This script attempts to guess a canonical system name.
+#   Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+#
+# 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
+# (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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#
+# 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).
+#
+
+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_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    alpha:OSF1:1.*:*)
+       # 1.2 uses "1.2" for uname -r.
+       echo alpha-dec-osf${UNAME_RELEASE}
+        exit 0 ;;
+    alpha:OSF1:V1.*:*)
+       # 1.3 uses "V1.3" for uname -r.
+       echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^V//'`
+       exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit 0;;
+    sun4*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:6*:*)
+       # According to config.sub, this is the proper way to canonicalize
+       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+       # it's likely to be more like Solaris than SunOS4.
+       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:*:*)
+       echo sparc-sun-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    mips:*:5*:RISCos)
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit 0 ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit 0 ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    AViiON:dgux:*:*)
+       echo m88k-dg-dgux${UNAME_RELEASE}
+       exit 0 ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    *:IRIX:*:*)
+       echo mips-sgi-irix${UNAME_RELEASE}
+       exit 0 ;;
+    i[34]86:AIX:*:*)
+       echo i386-ibm-aix
+       exit 0 ;;
+    *:AIX:2:3)
+       echo rs6000-ibm-aix3.2
+       exit 0 ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit 0 ;;
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit 0 ;;
+    9000/31?:HP-UX:*:*)
+       echo m68000-hp-hpux
+       exit 0 ;;
+    9000/[34]??:HP-UX:*:*)
+       echo m68k-hp-hpux
+       exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit 0 ;;
+    9000/7??:HP-UX:*:* | 9000/8?7:HP-UX:*:* )
+       echo hppa1.1-hp-hpux
+       exit 0 ;;
+    9000/8??:HP-UX:*:*)
+       echo hppa1.0-hp-hpux
+       exit 0 ;;
+    3050*:HI-UX:*:*)
+       sed 's/^        //' << EOF >dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+       rm -f dummy.c dummy
+       echo unknown-hitachi-hiuxwe2
+       exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?7:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit 0 ;;
+    C1*:ConvexOS:*:*)
+       echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:*)
+       echo c2-convex-bsd
+        exit 0 ;;
+    CRAY*X-MP:UNICOS:*:*)
+       echo xmp-cray-unicos
+        exit 0 ;;
+    CRAY*Y-MP:UNICOS:*:*)
+       echo ymp-cray-unicos
+        exit 0 ;;
+    CRAY-2:UNICOS:*:*)
+       echo cray2-cray-unicos
+        exit 0 ;;
+    hp3[0-9][05]:NetBSD:*:*)
+       echo m68k-hp-netbsd${UNAME_RELEASE}
+       exit 0 ;;
+    i[34]86:NetBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-netbsd${UNAME_RELEASE}
+       exit 0 ;;
+    i[34]86:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux
+       exit 0 ;;
+    i[34]86:UNIX_SV:4.*:*)
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+       else
+               echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}
+       fi
+       exit 0 ;;
+    i[34]86:*:3.2:*)
+       if /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+               echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-unknown-sysv3.2
+       fi
+       exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit 0 ;;
+    M680[234]0:*:R3V[567]*:*)
+       test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:*)
+       uname -p 2>/dev/null | grep 86 >/dev/null \
+         && echo i486-ncr-sysv4 && exit 0 ;;
+    m680[234]0:LynxOS:2.2*:*)
+       echo m68k-lynx-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    i[34]86:LynxOS:2.2*:*)
+       echo i386-lynx-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    TSUNAMI:LynxOS:2.2*:*)
+       echo sparc-lynx-lynxos${UNAME_RELEASE}
+       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
+
+cat >dummy.c <<EOF
+main()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+#else
+  printf("m68k-sony-newsos\n"); exit(0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined(hp300) && !defined(hpux)
+  printf("m68k-hp-bsd\n"); exit(0);
+#endif
+
+#if defined(NeXT)
+  printf("m68k-next-bsd\n"); exit(0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf("ns32k-encore-sysv\n"); exit(0);
+#else
+#if defined (CMU)
+  printf("ns32k-encore-mach\n"); exit(0);
+#else
+  printf("ns32k-encore-bsd\n"); exit(0);
+#endif
+#endif
+#endif
+
+#if defined(__386BSD__) || (defined(__bsdi__) && defined(__i386__))
+  printf("i386-unknown-bsd\n"); exit(0);
+#endif
+
+#if defined(sequent)
+#if defined(i386)
+  printf("i386-sequent-dynix\n"); exit(0);
+#endif
+#if defined (ns32000)
+  printf("ns32k-sequent-dynix\n"); exit(0);
+#endif
+#endif
+
+#if defined(_SEQUENT_)
+  printf("i386-sequent-ptx\n"); exit(0);
+#endif
+
+  exit (1);
+}
+EOF
+
+${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
diff --git a/support/mksysdefs b/support/mksysdefs
new file mode 100755 (executable)
index 0000000..37b188e
--- /dev/null
@@ -0,0 +1,497 @@
+#!/bin/sh
+#
+# This file creates a file called "sysdefs.h" which contains CPP defines
+# helping to describe the operating system features.  We just take guesses
+# by looking at random files.
+
+# Removes any inherited definitions.
+SYSDEF=
+MAKE_ANSI=
+
+while [ $# -gt 0 ]; do
+       case "$1" in
+       -s)     shift; srcdir=$1; shift ;;
+       -i)     shift; incdir="$1"; shift ;;
+       -A)     shift; MAKE_ANSI=true ;;
+       *)      break ;;
+       esac
+done
+
+if [ -n "$1" ]; then
+  sysdefs=$1
+else
+  sysdefs=./sysdefs.h
+fi
+
+if [ -z "$srcdir" ]; then
+       srcdir=.
+fi
+
+rm -f $sysdefs
+
+echo "/* sysdefs.h -- #defines for your system created by $0."    >>$sysdefs
+echo "   Do NOT EDIT this file, since any changes will disappear." >>$sysdefs
+echo "   Instead, edit $0, or config.h, or machines.h. */"        >>$sysdefs
+echo ""                                                                   >>$sysdefs
+echo "#if !defined (_SYSDEFS_H_)"                                 >>$sysdefs
+echo "#  define _SYSDEFS_H_"                                      >>$sysdefs
+
+# was if [ -f /usr/bin/uname ] || [ -f /bin/uname ]
+if ( uname >/dev/null 2>&1 ) 2>/dev/null
+then
+       UNAME=`uname`
+       UNAME_R=`uname -r 2>/dev/null`
+       UNAME_M=`uname -m 2>/dev/null`
+       UNAME_V=`uname -v 2>/dev/null`
+       UNAME_S=`uname -s 2>/dev/null`
+       RELEASE=`expr "$UNAME_R" : '[^0-9]*\([0-9]*\)'`
+       case "$RELEASE" in
+       "")     RELEASE=0 ;;
+       *)      RELEASE=`expr "$RELEASE" + 0` ;;
+       esac
+       LEVEL=`expr "$UNAME_R" : '[^0-9]*[0-9]*.\([0-9]*\)'`
+fi
+
+# check for versions of SunOS and BSD/OS
+case "${UNAME}${RELEASE}" in
+SunOS4*) SYSDEF=SunOS4 ;;
+SunOS5*) SYSDEF=SunOS5 ;;
+BSD/OS2*) SYSDEF=BSDI2 ;;
+esac
+
+# Test for NeXT
+if [ -d /NextLibrary ]; then
+       MAKE_ANSI=true
+fi
+
+# Intel Paragon
+case "$UNAME_M" in
+paragon) MAKE_ANSI=true ;;
+esac
+
+# Test for shared libraries (this is pretty sVr4ish).
+if [ -f /usr/ccs/lib/libc.so ]; then
+  SYSDEF=USGr4
+fi
+
+# 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
+
+# (sound of teeth grinding...)
+if [ "$UNAME" = "UNIX_SV" ] && [ "$UNAME_R" != "4.2" ] && [ "$RELEASE"."$LEVEL" = "4.2" ]; then
+       UNAME_R="4.2"
+fi
+
+# another check for SVR4 on 386 or 486 machines
+case "${UNAME_M}:${UNAME}:${UNAME_R}" in
+i[34]86:UNIX_SV:4.*)   SYSDEF=USGr4 ;;
+esac
+
+# A check for Mips RISCos
+case "$UNAME_V" in
+UMIPS|RISCos) SYSDEF=RISCos_${RELEASE}_${LEVEL} ;;
+esac
+
+# A check for Amdahl UTS
+case "$UNAME" in
+uts) SYSDEF=UTS ;;
+esac
+
+# Look for an error message when trying to exec bison.  If we find
+# what we're looking for, then we don't have it.  If we get something
+# else (like an error message about no grammar file), then we have
+# it.
+HAVE_BISON=
+if ( cd /tmp ; bison /dev/null 2>&1 >/dev/null | grep 'no input grammar' >/dev/null 2>&1 ) 2>/dev/null
+then
+  HAVE_BISON=yes
+fi
+
+# Try to locate ranlib.  I think this is a bad idea.
+if sh ${srcdir}/support/inpath ranlib; then
+        RANLIB_LOCATION=ranlib
+elif [ -f /usr/bin/ranlib ]; then
+       RANLIB_LOCATION=/usr/bin/ranlib;
+elif [ -f /bin/ranlib ]; then
+       RANLIB_LOCATION=/bin/ranlib;
+elif [ -f /usr/local/bin/ranlib ]; then
+       RANLIB_LOCATION=/usr/local/bin/ranlib;
+elif [ -f /usr/local/gnubin/ranlib ]; then
+       RANLIB_LOCATION=/usr/local/gnubin/ranlib;
+else
+       RANLIB_LOCATION=:       # XXX
+fi
+
+if [ -n "${RANLIB_LOCATION}" ]; then
+  echo ""                                              >>$sysdefs
+  echo "#if !defined (RANLIB_LOCATION)"                >>$sysdefs
+  echo "#  define RANLIB_LOCATION ${RANLIB_LOCATION}"  >>$sysdefs
+  echo "#endif /* RANLIB_LOCATION */"                  >>$sysdefs
+fi
+
+#
+# Is this a Xenix system?
+#
+if [ -f /xenix ]; then
+  SYSDEF="Xenix"
+  case "`/bin/uname -p`" in
+    *286) SYSDEF="Xenix286" ;;
+    *386) SYSDEF="Xenix386" ;;
+  esac
+
+  # make sure that `i386' is defined for machines.h
+  if [ "$SYSDEF" = "Xenix386" ]; then
+    echo ""                            >>$sysdefs
+    echo "#if !defined (i386)"         >>$sysdefs
+    echo "#  define i386"              >>$sysdefs
+    echo "#endif /* !i386 */"          >>$sysdefs      
+  fi
+
+  # Pass the release number of the OS through to the machine descriptions
+  # in machines.h.
+  if [ -f /etc/perms/soft ]; then
+    rel=`grep rel= /etc/perms/soft`
+    case "$rel" in
+      *2.2.*) XREL=XENIX_22 ;;
+      *2.3.*) XREL=XENIX_23 ;;
+      *3.2.*) XREL=XENIX_32 ;;
+      *) XREL= ;;
+    esac
+
+    if [ "$XREL" ]; then
+      echo ""                          >>$sysdefs
+      echo "#if !defined ($XREL)"      >>$sysdefs
+      echo "#  define $XREL"           >>$sysdefs
+      echo "#endif /* !$XREL */"       >>$sysdefs
+    fi
+  fi
+fi
+
+#
+# Is this some kind of Sys Vish system?
+#
+if [ -f /unix ]; then
+  if [ -d /generic ]; then   # This is an AIX system.
+    SYSDEF="aixpc"
+    MAKE_ANSI=true
+  elif [ -d /etc/conf/kconfig.d ] && [ -f /usr/include/sys/limits.h ]; then
+    SYSDEF="isc386"                    # This is a 386 running ISC?
+    ISCREL="ISC_$RELEASE"
+    echo "#if !defined ($ISCREL)"      >>$sysdefs
+    echo "#  define $ISCREL"           >>$sysdefs
+    echo "#endif /* $ISCREL */"                >>$sysdefs
+  elif [ -f /etc/xlc.cfg ]; then
+    if fgrep _IBMR2 /etc/xlc.cfg >/dev/null 2>&1; then
+      SYSDEF=RISC6000
+      MAKE_ANSI=true
+    fi
+  elif [ -f /bin/4d -a -f /bin/uname ]; then
+    case "$UNAME_R" in
+      3.*) SYSDEF="Irix3" ;;
+      4.*) SYSDEF="Irix4" ;;
+      5.*) SYSDEF="Irix5" ;;
+      6.*) SYSDEF="Irix6" ;;
+      *)   SYSDEF="Irix3" ;;
+    esac
+  elif [ -d /usr/amiga ]; then
+    SYSDEF="amiga"             # An Amiga running V.4.
+  elif [ -f /bin/fxc.info ]; then
+    SYSDEF="alliant"
+  fi
+fi
+
+# Is this a Unicos system?
+if [ -f /unicos ]; then
+   MAKE_ANSI=true
+   UnicosMachine=
+
+   # Test for the variaous flavors of Cray machines.
+   if [ -x /bin/cray1 ] && /bin/cray1 2>/dev/null; then
+      UnicosMachine=Cray1
+   fi
+
+   if [ -x /bin/cray2 ] && /bin/cray2 2>/dev/null; then
+      UnicosMachine=Cray2
+   fi
+
+   if [ -x /bin/crayxmp ] && /bin/crayxmp 2>/dev/null; then
+      UnicosMachine=CrayXMP
+   fi
+   if [ -x /bin/crayymp ] && /bin/crayymp 2>/dev/null; then
+      UnicosMachine=CrayYMP
+   fi
+
+   if [ "$UnicosMachine" ]; then
+      echo "#if !defined ($UnicosMachine)"     >>$sysdefs
+      echo "#  define $UnicosMachine"          >>$sysdefs
+      echo "#endif /* !$UnicosMachine */"      >>$sysdefs
+   fi
+fi
+
+# Is this (and what kind of) a HPUX system?
+if [ -f /hp-ux ]; then
+  SYSDEF=HPUX_${RELEASE}
+  if [ "$RELEASE" = 6 -a "$LEVEL" -lt 2 ]; then
+    SYSDEF=HPUX_USG
+  fi
+fi
+
+if [ "$SYSDEF" = "" ]; then
+       case "$UNAME_M" in
+       ESA) SYSDEF=AIXESA ;;    
+       XD88*) SYSDEF=XD88 ;;
+       M88100) SYSDEF=M88100 ;;        # Motorola Delta 88K
+       esac
+fi
+
+if [ "$SYSDEF" = "" ]; then
+       case "$UNAME_V" in
+       V[0-9]*L[0-9]*) SYSDEF=UXP ;;   # Fujitsu DS/90
+       esac
+fi
+
+# What release of SCO Unix is this?
+if [ "$SYSDEF" = "" -a -f /bin/uname ]; then
+  case `/bin/uname -X 2>/dev/null | grep '^Release' 2>/dev/null` in
+    *3.2v4.*) SYSDEF=SCOv4 ;;
+    *3.2v5.*) SYSDEF=SCOv5 ;;
+          *) SYSDEF=SCO ;;
+  esac
+fi
+
+#
+# Default to cadmus for unknown SysVish systems
+#
+if [ -f /unix ] && [ "$SYSDEF" = "" ]; then
+  SYSDEF="cadmus"
+fi
+
+if [ "$SYSDEF" != "" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined ($SYSDEF)"                        >>$sysdefs
+  echo "#  define $SYSDEF"                     >>$sysdefs
+  echo "#endif /* $SYSDEF */"                  >>$sysdefs
+fi
+
+# Now look for certain include files in a list of directories
+# Poor substitute for autoconf
+
+# Add any other directories where include files are found to this list or
+# create another case
+if [ -n "$incdir" ]; then
+       dirlist="$incdir"
+else
+       case "$SYSDEF" in
+       RISCos*) dirlist="/bsd43/usr/include";;
+       *) dirlist="/usr/include /usr/include/bsd /usr/include/ansi" ;;
+       esac
+fi
+
+# Code fragment to be executed to find a particular include file.  Make sure
+# to set `file' to the pathname of the file you want, relative to /usr/include,
+# before calling `eval $findf'.
+findf="
+found='';
+for d in \$dirlist;
+do
+       if test -f \$d/\$file;
+       then
+               found=yes;
+               break;
+       fi;
+done
+"
+
+found=
+file=sys/stream.h
+eval $findf
+if [ -n "$found" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_SYS_STREAM_H)"      >>$sysdefs
+  echo "#  define HAVE_SYS_STREAM_H"           >>$sysdefs
+  echo "#endif /* HAVE_SYS_STREAM_H */"                >>$sysdefs
+fi
+
+found=
+file=sys/ptem.h
+eval $findf
+if [ -n "$found" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_SYS_PTEM_H)"                >>$sysdefs
+  echo "#  define HAVE_SYS_PTEM_H"             >>$sysdefs
+  echo "#endif /* HAVE_SYS_PTEM_H */"          >>$sysdefs
+fi
+
+file=sys/pte.h
+eval $findf
+if [ -n "$found" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_SYS_PTE_H)"         >>$sysdefs
+  echo "#  define HAVE_SYS_PTE_H"              >>$sysdefs
+  echo "#endif /* HAVE_SYS_PTE_H */"           >>$sysdefs
+fi
+
+file=sys/wait.h
+eval $findf
+if [ -n "$found" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_WAIT_H)"            >>$sysdefs
+  echo "#  define HAVE_WAIT_H"                 >>$sysdefs
+  echo "#endif /* HAVE_WAIT_H */"              >>$sysdefs
+fi
+
+file=sys/resource.h
+eval $findf
+if [ -n "$found" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_RESOURCE)"          >>$sysdefs
+  echo "#  define HAVE_RESOURCE"               >>$sysdefs
+  echo "#endif /* HAVE_RESOURCE */"            >>$sysdefs
+fi
+
+file=sys/param.h
+eval $findf
+if [ -n "$found" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_SYS_PARAM)"         >>$sysdefs
+  echo "#  define HAVE_SYS_PARAM"              >>$sysdefs
+  echo "#endif /* HAVE_SYS_PARAM */"           >>$sysdefs
+fi
+
+file=unistd.h
+eval $findf
+if [ -n "$found" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_UNISTD_H)"          >>$sysdefs
+  echo "#  define HAVE_UNISTD_H"               >>$sysdefs
+  echo "#endif /* HAVE_UNISTD_H */"            >>$sysdefs
+fi
+
+file=stdlib.h
+eval $findf
+if [ -n "$found" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_STDLIB_H)"          >>$sysdefs
+  echo "#  define HAVE_STDLIB_H"               >>$sysdefs
+  echo "#endif /* HAVE_STDLIB_H */"            >>$sysdefs
+fi
+
+file=limits.h
+eval $findf
+if [ -n "$found" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_LIMITS_H)"          >>$sysdefs
+  echo "#  define HAVE_LIMITS_H"               >>$sysdefs
+  echo "#endif /* HAVE_LIMITS_H */"            >>$sysdefs
+fi
+
+file=alloca.h
+eval $findf
+if [ -f /usr/include/alloca.h ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_ALLOCA_H)"          >>$sysdefs
+  echo "#  define HAVE_ALLOCA_H"               >>$sysdefs
+  echo "#endif /* HAVE_ALLOCA_H */"            >>$sysdefs
+fi
+
+file=dirent.h
+eval $findf
+if [ -n "$found" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_DIRENT_H)"          >>$sysdefs
+  echo "#  define HAVE_DIRENT_H"               >>$sysdefs
+  echo "#endif /* HAVE_DIRENT_H */"            >>$sysdefs
+fi
+
+file=string.h
+eval $findf
+if [ -n "$found" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_STRING_H)"          >>$sysdefs
+  echo "#  define HAVE_STRING_H"               >>$sysdefs
+  echo "#endif /* HAVE_STRING_H */"            >>$sysdefs
+fi
+
+file=varargs.h
+eval $findf
+if [ -n "$found" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_VARARGS_H)"         >>$sysdefs
+  echo "#  define HAVE_VARARGS_H"              >>$sysdefs
+  echo "#endif /* HAVE_VARARGS_H */"           >>$sysdefs
+fi
+
+# Does the system have a /dev/fd directory?
+if [ -d /dev/fd ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_DEV_FD)"            >>$sysdefs
+  echo "#  define HAVE_DEV_FD"                 >>$sysdefs
+  echo "#endif /* HAVE_DEV_FD */"              >>$sysdefs
+fi
+
+# Is this SVR4.2?  It's subtly different from USGr4
+if [ "$UNAME" = "UNIX_SV" ] && [ "$UNAME_R" = "4.2" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (USGr4_2)"                >>$sysdefs
+  echo "#  define USGr4_2"             >>$sysdefs
+  echo "#endif /* USGr4_2 */"          >>$sysdefs
+fi
+
+# Is this AIX PS/2 1.3?  Yuck.
+if [ "$UNAME" = "AIX" ] && [ "$UNAME_V" = "1" ] && [ "$RELEASE" = "3" ]; then
+  case "$UNAME_M" in
+  i386|i486)
+       echo ""                                 >>$sysdefs
+       echo "#if !defined (AIX_13)"            >>$sysdefs
+       echo "#  define AIX_13"                 >>$sysdefs
+       echo "#endif /* AIX_13 */"              >>$sysdefs
+       ;;
+  esac
+fi
+
+if [ -n "$HAVE_BISON" ]; then
+  echo ""                                      >>$sysdefs
+  echo "#if !defined (HAVE_BISON)"             >>$sysdefs
+  echo "#  define HAVE_BISON"                  >>$sysdefs
+  echo "#endif /* HAVE_BISON */"               >>$sysdefs
+fi
+
+# Functions to test for a la autoconf
+#      getwd
+#      getcwd
+#      strchr
+#      strcasecmp
+#      getgroups
+#      setlinebuf
+#      strerror
+#      vfprintf
+#      bcopy
+#      getdtablesize
+#      setdtablesize
+#      alloca
+#      gethostname
+#      memmove (missing)
+#      mkfifo (missing)
+#
+# Other things to test
+#      opendir robustness
+#      dup2 working
+#      void sighandler
+#      sys_siglist[]
+#      uid_t, gid_t
+#      have_getpw_decls
+#      reversed setvbuf args
+#      int getgroups
+
+# If this system's cpp might not like `/**/#' in cpp-Makefile, make an
+# alternate ansi-style cpp-Makefile.
+if [ -n "$MAKE_ANSI" ]; then
+   grep -v '/\*\*/' ${srcdir}/cpp-Makefile >ansi-Makefile
+fi
+
+# These should be the last 2 lines in this file!
+echo ""                                                >>$sysdefs
+echo "#endif /* _SYSDEFS_H_ */"                        >>$sysdefs
diff --git a/support/printenv b/support/printenv
new file mode 100755 (executable)
index 0000000..8aebd43
--- /dev/null
@@ -0,0 +1,11 @@
+#! /bin/sh -
+
+if [ $# -eq 0 ]; then
+       env
+       exit
+elif eval [ "\${$1-unset}" = "unset" ]; then
+       exit 1
+else
+       eval echo \$$1
+       exit 0
+fi
diff --git a/support/recho.c b/support/recho.c
new file mode 100644 (file)
index 0000000..b9dc00b
--- /dev/null
@@ -0,0 +1,32 @@
+#include <stdio.h>
+
+main(argc, argv)
+int    argc;
+char   **argv;
+{
+       register int    i;
+
+       for (i = 1; i < argc; i++) {
+               printf("argv[%d] = <", i);
+               strprint(argv[i]);
+               printf(">\n");
+       }
+}
+
+strprint(str)
+char   *str;
+{
+       register char *s;
+       int     c;
+
+       for (s = str; s && *s; s++) {
+               if (*s < ' ') {
+                       putchar('^');
+                       putchar(*s+64);
+               } else if (*s == 127) {
+                       putchar('^');
+                       putchar('?');
+               } else
+                       putchar(*s);
+       }
+}
diff --git a/support/srcdir b/support/srcdir
new file mode 100755 (executable)
index 0000000..9d8ccd7
--- /dev/null
@@ -0,0 +1,13 @@
+#! /bin/sh
+#
+# srcdir - print out the absolute pathname of the top of the bash source
+#         tree.  Used for getting the right value to makes in subdirectories
+#
+
+case "$1" in
+'.'|./)        pwd ;;
+./*|..*)       echo `pwd`/"$1" ;;
+*)     echo "$1" ;;
+esac
+
+exit 0
diff --git a/support/texi2dvi b/support/texi2dvi
new file mode 100755 (executable)
index 0000000..12281e5
--- /dev/null
@@ -0,0 +1,263 @@
+#!/bin/sh
+# texi2dvi -- smartly produce DVI files from texinfo sources
+#
+# Copyright (C) 1992, 1993 Free Software Foundation.
+#
+# 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, you can either send email to this
+# program's author (see below) or write to:
+#
+#              Free Software Foundation, Inc.
+#              675 Mass Ave.
+#              Cambridge, MA 02139, USA. 
+#
+# Please send bug reports, etc. to bug-texinfo@prep.ai.mit.edu
+# If possible, please send a copy of the output of the script called with
+# the `--debug' option when making a bug report. 
+#
+# Version 0.4
+# Last modified 26-Mar-93
+#
+
+# Please note that in the interest of general portability, some common
+# bourne shell constructs were avoided because they weren't guaranteed to
+# be available in some earlier implementations.  I've tried to make this as
+# portable as possible. 
+#
+# Among the more interesting lossages I noticed with some bourne shells
+# are:
+#       1) Some don't have an `unset' builtin 
+#       2) In some implementations the `shift' builtin can't take a
+#          numerical argument. 
+
+progname=`basename $0`
+
+usage="Usage: ${progname} {-D} {-h} [file1] {file2} {...}
+       {--debug} {--help}
+
+   Options in braces are optional.  Those in brackets are required. 
+"
+
+if test $# -eq 0 ; then
+   echo "${usage}" 1>&2;
+   exit 1
+fi
+
+backup_extension=".bak"
+texindex="texindex"
+tex="tex"
+bq="\`"  # To prevent hairy quoting and escaping later.
+eq="'"
+orig_pwd="`pwd`"
+
+if test "z${TEXINDEX}" != "z" ; then
+   texindex="${TEXINDEX}"
+fi
+
+if test "z${TEX}" != "z" ; then
+   tex="${TEX}"
+fi
+
+# Save this so we can construct a new TEXINPUTS path for each file to be
+# processed.
+TEXINPUTS_orig="${TEXINPUTS}"
+export TEXINPUTS
+
+# Parse command line options
+
+# "unset" option variables to make sure they weren't accidentally
+# exported
+debug=""
+
+# If you add new commands be sure to change the wildcards below to make
+# sure they are unambiguous (i.e. only match one possible long option)
+# Be sure to show at least one instance of the full long option name to
+# document what the long option is canonically called. 
+while test $# -gt 0 ; do
+   case z$1 in
+      z-D | z--debug | z--d* )
+         debug="t"
+         shift
+        ;;
+      z-h | z--help | z--h* )
+         echo "${usage}" 1>&2
+         exit 1
+        ;;
+      z-- )
+         shift
+         break 
+        ;;
+      z-* )
+         echo "${progname}: ${bq}${1}${eq} is not a valid option." 1>&2
+         echo "" 1>&2
+         echo "${usage}" 1>&2
+         exit 1
+        ;;
+      * )
+         break 
+        ;;
+   esac
+done
+
+# See if there are any command line args left (which will be interpreted as
+# filename arguments)
+if test $# -eq 0 ; then
+   echo "${progname}: at least one file name is required as an argument." 1>&2
+   echo "" 1>&2
+   echo "${usage}" 1>&2
+   exit 1
+fi
+
+test "z${debug}" = "zt" && set -x
+
+# Texify files
+for command_line_filename in ${1+"$@"} ; do
+   # Roughly equivalent to `dirname ...`, but more portable
+   directory="`echo ${command_line_filename} | sed 's/\/[^\/]*$//'`"
+   filename_texi="`basename ${command_line_filename}`"
+   # Strip off the last extension part (probably .texinfo or .texi)
+   filename_noext="`echo ${filename_texi} | sed 's/\.[^.]*$//'`"
+
+   # If directory and file are the same, then it's probably because there's
+   # no pathname component.  Set dirname to `.', the current directory.
+   if test "z${directory}" = "z${command_line_filename}" ; then
+      directory="."
+   fi
+
+   # Source file might @include additional texinfo sources.  Put `.' and
+   # directory where source file(s) reside in TEXINPUTS before anything
+   # else.  `.' goes first to ensure that any old .aux, .cps, etc. files in
+   # ${directory} don't get used in preference to fresher files in `.'. 
+   TEXINPUTS=".:${directory}:${TEXINPUTS_orig}"
+
+   # "Unset" variables that might have values from previous iterations and
+   # which won't be completely reset later.
+   definite_index_files=""
+
+   # See if file exists here.  If it doesn't we're in trouble since, even
+   # though the user may be able to reenter a valid filename at the tex
+   # prompt (assuming they're attending the terminal), this script won't be
+   # able to find the right index files and so forth.
+   if test ! -r "${command_line_filename}" ; then
+      echo "${progname}: ${command_line_filename}: No such file or permission denied." 1>&2
+      continue; 
+   fi
+
+   # Find all files having root filename with a two-letter extension,
+   # determine whether they're really index files, and save them.  Foo.aux
+   # is actually the cross-references file, but we need to keep track of
+   # that too.
+   possible_index_files="`eval echo ${filename_noext}.?? ${filename_noext}.aux`"
+   for this_file in ${possible_index_files} ; do
+      # If file is empty, forget it.  
+      if test ! -s "${this_file}" ; then
+         continue;
+      fi
+
+      # Examine first character of file.  If it's not a backslash or
+      # single quote, then it's definitely not an index or xref file.
+      first_character="`sed -n '1s/^\(.\).*$/\1/p;q' ${this_file}`"
+      if test "${first_character}" = "\\" -o "${first_character}" = "'" ; then
+         definite_index_files="${definite_index_files} ${this_file}"
+      fi
+   done
+   orig_index_files="${definite_index_files}"
+   orig_index_files_sans_aux="`echo ${definite_index_files} \
+                                | sed 's/'${filename_noext}'\.aux//;
+                                       s/^[ ]*//;s/[ ]*$//;'`"
+
+   # Now save copies of original index files so we have some means of
+   # comparison later. 
+   for index_file_to_save in ${orig_index_files} ; do
+       cp "${index_file_to_save}" "${index_file_to_save}${backup_extension}"
+   done
+
+   # Run texindex on current index files.  If they already exist, and
+   # after running TeX a first time the index files don't change, then
+   # there's no reason to run TeX again.  But we won't know that if the
+   # index files are out of date or nonexistent.
+   if test "${orig_index_files_sans_aux}" ; then
+      ${texindex} ${orig_index_files_sans_aux}
+   fi
+
+   if ${tex} ${command_line_filename} ; then           # TeX run first time
+      definite_index_files=""
+      # Get list of new index files
+      possible_index_files="`eval echo ${filename_noext}.?? ${filename_noext}.aux`"
+      for this_file in ${possible_index_files} ; do
+         # If file is empty, forget it.
+         if test ! -s ${this_file} ; then
+            continue;
+         fi
+
+         # Examine first character of file.  If it's not a backslash or
+         # single quote, then it's definitely not an index or xref file.
+         first_character="`sed -n '1s/^\(.\).*$/\1/p;q' ${this_file}`"
+         if test "${first_character}" = "\\" -o "${first_character}" = "'" ; then
+            definite_index_files="${definite_index_files} ${this_file}"
+         fi
+      done
+      new_index_files="${definite_index_files}"
+      new_index_files_sans_aux="`echo ${definite_index_files} \
+                                  | sed 's/'${filename_noext}'\.aux//;
+                                         s/^[ ]*//;s/[ ]*$//;'`"
+
+      # If old and new list don't at least have the same file list, then one
+      # file or another has definitely changed.  
+      if test "${orig_index_files}" != "${new_index_files}" ; then
+         index_files_changed_p=t
+      else
+         # File list is the same.  We must compare each file until we find a
+         # difference.  
+         index_files_changed_p=""
+         for this_file in ${new_index_files} ; do
+            # cmp -s will return nonzero exit status if files differ. 
+            cmp -s "${this_file}" "${this_file}${backup_extension}"
+            if test $? -ne 0  ; then
+               # We only need to keep comparing until we find *one* that
+               # differs, because we'll have to run texindex & tex no
+               # matter what. 
+               index_files_changed_p=t
+               break
+            fi
+         done
+      fi
+
+      # If index files have changed since TeX has been run, or if the aux
+      # file wasn't present originally, run texindex and TeX again.
+      if test "${index_files_changed_p}"  ; then
+         retval=0
+         if test "${new_index_files_sans_aux}" ; then
+            ${texindex} ${new_index_files_sans_aux} 
+            retval=$?
+         fi
+         if test ${retval} -eq 0 ; then
+            ${tex} "${command_line_filename}"
+         fi
+      fi
+   fi
+
+   # Generate list of files to delete, then call rm once with the entire
+   # list.  This is significantly faster than multiple executions of rm. 
+   file_list=""
+   for file in ${orig_index_files} ; do
+       file_list="${file_list} ${file}${backup_extension}"
+   done
+   if test "${file_list}" ; then
+      rm -f ${file_list}
+   fi
+done
+
+#
+# eof
+#
diff --git a/test.c b/test.c
new file mode 100644 (file)
index 0000000..d8356f1
--- /dev/null
+++ b/test.c
@@ -0,0 +1,1132 @@
+/* GNU test program (ksb and mjb) */
+
+/* Modified to run with the GNU shell Apr 25, 1988 by bfox. */
+
+/* Copyright (C) 1987, 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Define STANDALONE to get the /bin/test version.  Otherwise, you get 
+   the shell builtin version. */
+/* #define STANDALONE */
+
+#include <stdio.h>
+#include "bashtypes.h"
+
+#if !defined (STANDALONE)
+#  if !defined (_POSIX_VERSION)
+#    include <sys/file.h>
+#  endif /* !_POSIX_VERSION */
+#  include "posixstat.h"
+#  include "filecntl.h"
+#  include "shell.h"
+#else /* STANDALONE */
+#  include "system.h"
+#  if !defined (S_IXUGO)
+#    define S_IXUGO 0111
+#  endif
+#  if defined (HAVE_UNISTD_H)
+#    include <unistd.h>
+#  endif /* HAVE_UNISTD_H */
+#  define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#  define digit(c)  ((c) >= '0' && (c) <= '9')
+#  define digit_value(c) ((c) - '0')
+#endif /* STANDALONE */
+
+#if !defined (STRLEN)
+#  define STRLEN(s) ((s)[0] ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 0)
+#endif
+
+#include <errno.h>
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#if !defined (STREQ)
+#  define STREQ(a, b) ((a)[0] == (b)[0] && strcmp (a, b) == 0)
+#endif /* !STREQ */
+
+#if !defined (member)
+#  define member(c, s) (int)((c) ? (char *)strchr ((s), (c)) : 0)
+#endif /* !member */
+
+/* Make gid_t and uid_t mean something for non-posix systems. */
+#if !defined (_POSIX_VERSION) && !defined (HAVE_UID_T)
+#  if !defined (gid_t)
+#    define gid_t int
+#  endif
+#  if !defined (uid_t)
+#    define uid_t int
+#  endif
+#endif /* !_POSIX_VERSION */
+
+/* What type are the user and group ids?  GID_T is actually the type of
+   the members of the array that getgroups(3) fills in from its second
+   argument. */
+#if defined (INT_GROUPS_ARRAY)
+#  define GID_T int
+#  define UID_T int
+#else /* !INT_GROUPS_ARRAY */
+#  define GID_T gid_t
+#  define UID_T uid_t
+#endif /* !INT_GROUPS_ARRAY */
+
+#if !defined (Linux) && !defined (USGr4_2) && !defined (SunOS5)
+extern gid_t getegid ();
+extern uid_t geteuid ();
+#  if !defined (sony)
+extern gid_t getgid ();
+#  endif /* !sony */
+#endif /* !Linux && !USGr4_2 && !SunOS5 */
+
+#if !defined (R_OK)
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#define F_OK 0
+#endif /* R_OK */
+
+/* The following few defines control the truth and false output of each stage.
+   TRUE and FALSE are what we use to compute the final output value.
+   SHELL_BOOLEAN is the form which returns truth or falseness in shell terms.
+   TRUTH_OR is how to do logical or with TRUE and FALSE.
+   TRUTH_AND is how to do logical and with TRUE and FALSE..
+   Default is TRUE = 1, FALSE = 0, TRUTH_OR = a | b, TRUTH_AND = a & b,
+    SHELL_BOOLEAN = (!value). */
+#define TRUE 1
+#define FALSE 0
+#define SHELL_BOOLEAN(value) (!(value))
+#define TRUTH_OR(a, b) ((a) | (b))
+#define TRUTH_AND(a, b) ((a) & (b))
+
+#if defined (STANDALONE)
+#  define test_exit(val) exit (val)
+#else
+   static jmp_buf test_exit_buf;
+   static int test_error_return = 0;
+#  define test_exit(val) \
+       do { test_error_return = val; longjmp (test_exit_buf, 1); } while (0)
+#endif /* STANDALONE */
+
+#if defined (AFS)
+  /* We have to use access(2) for machines running AFS, because it's
+     not a Unix file system.  This may produce incorrect answers for
+     non-AFS files.  I hate AFS. */
+#  define EACCESS(path, mode)  access(path, mode)
+#else
+#  define EACCESS(path, mode)  eaccess(path, mode)
+#endif /* AFS */
+
+static int pos;                /* The offset of the current argument in ARGV. */
+static int argc;       /* The number of arguments present in ARGV. */
+static char **argv;    /* The argument list. */
+static int noeval;
+
+static int isint ();
+static int unop ();
+static int binop ();
+static int unary_operator ();
+static int binary_operator ();
+static int two_arguments ();
+static int three_arguments ();
+static int posixtest ();
+
+static int expr ();
+static int term ();
+static int and ();
+static int or ();
+
+static void
+test_syntax_error (format, arg)
+     char *format, *arg;
+{
+#if !defined (STANDALONE)
+  extern int interactive_shell;
+  extern char *get_name_for_error ();
+  if (!interactive_shell)
+    fprintf (stderr, "%s: ", get_name_for_error ());
+#endif
+  fprintf (stderr, "%s: ", argv[0]);
+  fprintf (stderr, format, arg);
+  fflush (stderr);
+  test_exit (SHELL_BOOLEAN (FALSE));
+}
+
+/* A wrapper for stat () which disallows pathnames that are empty strings
+   and handles /dev/fd emulation on systems that don't have it. */
+static int
+test_stat (path, finfo)
+     char *path;
+     struct stat *finfo;
+{
+  if (*path == '\0')
+    {
+      errno = ENOENT;
+      return (-1);
+    }
+#if !defined (HAVE_DEV_FD)
+  if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
+    {
+      int fd;
+      if (isint (path + 8, &fd))
+       return (fstat (fd, finfo));
+      else
+       {
+         errno = EBADF;
+         return (-1);
+       }
+    }
+#endif /* !HAVE_DEV_FD */
+  return (stat (path, finfo));
+}
+
+/* Do the same thing access(2) does, but use the effective uid and gid,
+   and don't make the mistake of telling root that any file is
+   executable. */
+static int
+eaccess (path, mode)
+     char *path;
+     int mode;
+{
+  struct stat st;
+  static int euid = -1;
+
+  if (test_stat (path, &st) < 0)
+    return (-1);
+
+  if (euid == -1)
+#if defined (SHELL)
+    euid = current_user.euid;
+#else
+    euid = geteuid ();
+#endif
+
+  if (euid == 0)
+    {
+      /* Root can read or write any file. */
+      if (mode != X_OK)
+       return (0);
+
+      /* Root can execute any file that has any one of the execute
+        bits set. */
+      if (st.st_mode & S_IXUGO)
+       return (0);
+    }
+
+  if (st.st_uid == euid)        /* owner */
+    mode <<= 6;
+  else if (group_member (st.st_gid))
+    mode <<= 3;
+
+  if (st.st_mode & mode)
+    return (0);
+
+  return (-1);
+}
+
+#if defined (HAVE_GETGROUPS)
+/* The number of groups that this user is a member of. */
+static int ngroups = 0;
+static GID_T *group_array = (GID_T *)NULL;
+static int default_group_array_size = 0;
+#endif /* HAVE_GETGROUPS */
+
+#if !defined (NOGROUP)
+#  define NOGROUP (GID_T) -1
+#endif
+
+/* Return non-zero if GID is one that we have in our groups list. */
+int
+group_member (gid)
+     GID_T gid;
+{
+  static GID_T pgid = (GID_T)NOGROUP;
+  static GID_T egid = (GID_T)NOGROUP;
+
+  if (pgid == (GID_T)NOGROUP)
+#if defined (SHELL)
+    pgid = (GID_T) current_user.gid;
+#else /* !SHELL */
+    pgid = (GID_T) getgid ();
+#endif /* !SHELL */
+
+  if (egid == (GID_T)NOGROUP)
+#if defined (SHELL)
+    egid = (GID_T) current_user.egid;
+#else /* !SHELL */
+    egid = (GID_T) getegid ();
+#endif /* !SHELL */
+
+  if (gid == pgid || gid == egid)
+    return (1);
+
+#if defined (HAVE_GETGROUPS)
+  /* getgroups () returns the number of elements that it was able to
+     place into the array.  We simply continue to call getgroups ()
+     until the number of elements placed into the array is smaller than
+     the physical size of the array. */
+
+  while (ngroups == default_group_array_size)
+    {
+      default_group_array_size += 64;
+
+      group_array = (GID_T *)
+       xrealloc (group_array, default_group_array_size * sizeof (GID_T));
+
+      ngroups = getgroups (default_group_array_size, group_array);
+    }
+
+  /* In case of error, the user loses. */
+  if (ngroups < 0)
+    return (0);
+
+  /* Search through the list looking for GID. */
+  {
+    register int i;
+
+    for (i = 0; i < ngroups; i++)
+      if (gid == group_array[i])
+       return (1);
+  }
+#endif /* HAVE_GETGROUPS */
+
+  return (0);
+}
+
+/* Increment our position in the argument list.  Check that we're not
+   past the end of the argument list.  This check is supressed if the
+   argument is FALSE.  Made a macro for efficiency. */
+#if !defined (lint)
+#define advance(f) do { ++pos; if (f && pos >= argc) beyond (); } while (0)
+#endif
+
+#if !defined (advance)
+static int
+advance (f)
+     int f;
+{
+  ++pos;
+
+  if (f && pos >= argc)
+    beyond ();
+}
+#endif /* advance */
+
+#define unary_advance() do { advance (1); ++pos; } while (0)
+
+/*
+ * beyond - call when we're beyond the end of the argument list (an
+ *     error condition)
+ */
+static int
+beyond ()
+{
+  test_syntax_error ("argument expected\n", (char *)NULL);
+}
+
+/* Syntax error for when an integer argument was expected, but
+   something else was found. */
+static void
+integer_expected_error (pch)
+     char *pch;
+{
+  test_syntax_error ("integer expression expected %s\n", pch);
+}
+
+/* Return non-zero if the characters pointed to by STRING constitute a
+   valid number.  Stuff the converted number into RESULT if RESULT is
+   a non-null pointer to a long. */
+static int
+isint (string, result)
+     register char *string;
+     long *result;
+{
+  int sign;
+  long value;
+
+  sign = 1;
+  value = 0;
+
+  if (result)
+    *result = 0;
+
+  /* Skip leading whitespace characters. */
+  while (whitespace (*string))
+    string++;
+
+  if (!*string)
+    return (0);
+
+  /* We allow leading `-' or `+'. */
+  if (*string == '-' || *string == '+')
+    {
+      if (!digit (string[1]))
+       return (0);
+
+      if (*string == '-')
+       sign = -1;
+
+      string++;
+    }
+
+  while (digit (*string))
+    {
+      if (result)
+       value = (value * 10) + digit_value (*string);
+      string++;
+    }
+
+  /* Skip trailing whitespace, if any. */
+  while (whitespace (*string))
+    string++;
+
+  /* Error if not at end of string. */
+  if (*string)
+    return (0);
+
+  if (result)
+    {
+      value *= sign;
+      *result = value;
+    }
+
+  return (1);
+}
+
+/* Find the modification time of FILE, and stuff it into AGE, a pointer
+   to a long.  Return non-zero if successful, else zero. */
+static int
+age_of (filename, age)
+     char *filename;
+     long *age;
+{
+  struct stat finfo;
+
+  if (test_stat (filename, &finfo) < 0)
+    return (0);
+
+  if (age)
+    *age = finfo.st_mtime;
+
+  return (1);
+}
+
+/*
+ * term - parse a term and return 1 or 0 depending on whether the term
+ *     evaluates to true or false, respectively.
+ *
+ * term ::=
+ *     '-'('h'|'d'|'f'|'r'|'s'|'w'|'c'|'b'|'p'|'u'|'g'|'k') filename
+ *     '-'('L'|'x') filename
+ *     '-t' [ int ]
+ *     '-'('z'|'n') string
+ *     string
+ *     string ('!='|'=') string
+ *     <int> '-'(eq|ne|le|lt|ge|gt) <int>
+ *     file '-'(nt|ot|ef) file
+ *     '(' <expr> ')'
+ * int ::=
+ *     '-l' string
+ *     positive and negative integers
+ */
+static int
+term ()
+{
+  int value;
+
+  if (pos >= argc)
+    beyond ();
+
+  /* Deal with leading "not"'s. */
+  if ('!' == argv[pos][0] && '\000' == argv[pos][1])
+    {
+      value = FALSE;
+      while (pos < argc && '!' == argv[pos][0] && '\000' == argv[pos][1])
+       {
+         advance (1);
+         value ^= (TRUE);
+       }
+
+      return (value ^ (term ()));
+    }
+
+  /* A paren-bracketed argument. */  
+  if (argv[pos][0] == '(' && !argv[pos][1])
+    {
+      advance (1);
+      value = expr ();
+      if (argv[pos] == 0)
+        test_syntax_error ("`)' expected\n");
+      else if (argv[pos][0] != ')' || argv[pos][1])
+       test_syntax_error ("`)' expected, found %s\n", argv[pos]);
+      advance (0);
+      return (TRUE == (value));
+    }
+
+  /* are there enough arguments left that this could be dyadic? */
+  if (((pos + 3 <= argc) && binop (argv[pos + 1])) ||
+      ((pos + 4 <= argc && STREQ (argv[pos], "-l") && binop (argv[pos + 2]))))
+    value = binary_operator ();
+
+  /* Might be a switch type argument */
+  else if ('-' == argv[pos][0] && 0 == argv[pos][2])
+    {
+      if (unop (argv[pos][1]))
+       value = unary_operator ();
+      else
+       test_syntax_error ("%s: unary operator expected\n", argv[pos]);
+    }
+  else
+    {
+      value = (argv[pos][0] != '\0');
+      advance (0);
+    }
+
+  return (value);
+}
+
+static int
+binary_operator ()
+{
+  register int op;
+  struct stat stat_buf, stat_spare;
+  long int l, r, value;
+  /* Are the left and right integer expressions of the form '-l string'? */
+  int l_is_l, r_is_l;
+
+  if (argv[pos][0] == '-' && argv[pos][1] == 'l' && !argv[pos][2])
+    {
+      l_is_l = 1;
+      op = pos + 2;
+
+      /* Make sure that OP is still a valid binary operator. */
+      if ((op >= argc - 1) || (binop (argv[op]) == 0))
+       test_syntax_error ("%s: binary operator expected\n", argv[op]);
+
+      advance (0);
+    }
+  else
+    {
+      l_is_l = 0;
+      op = pos + 1;
+    }
+
+  if ((op < argc - 2) &&
+      (argv[op + 1][0] == '-' && argv[op + 1][1] == 'l' && !argv[op + 1][2]))
+    {
+      r_is_l = 1;
+      advance (0);
+    }
+  else
+    r_is_l = 0;
+
+  if (argv[op][0] == '-')
+    {
+      /* check for eq, nt, and stuff */
+      switch (argv[op][1])
+       {
+       default:
+         break;
+
+       case 'l':
+         if (argv[op][2] == 't' && !argv[op][3])
+           {
+             /* lt */
+             if (l_is_l)
+               l = strlen (argv[op - 1]);
+             else
+               {
+                 if (!isint (argv[op - 1], &l))
+                   integer_expected_error ("before -lt");
+               }
+
+             if (r_is_l)
+               r = strlen (argv[op + 2]);
+             else
+               {
+                 if (!isint (argv[op + 1], &r))
+                   integer_expected_error ("after -lt");
+               }
+             pos += 3;
+             return (TRUE == (l < r));
+           }
+
+         if (argv[op][2] == 'e' && !argv[op][3])
+           {
+             /* le */
+             if (l_is_l)
+               l = strlen (argv[op - 1]);
+             else
+               {
+                 if (!isint (argv[op - 1], &l))
+                   integer_expected_error ("before -le");
+               }
+             if (r_is_l)
+               r = strlen (argv[op + 2]);
+             else
+               {
+                 if (!isint (argv[op + 1], &r))
+                   integer_expected_error ("after -le");
+               }
+             pos += 3;
+             return (TRUE == (l <= r));
+           }
+         break;
+
+       case 'g':
+         if (argv[op][2] == 't' && !argv[op][3])
+           {
+             /* gt integer greater than */
+             if (l_is_l)
+               l = strlen (argv[op - 1]);
+             else
+               {
+                 if (!isint (argv[op - 1], &l))
+                   integer_expected_error ("before -gt");
+               }
+             if (r_is_l)
+               r = strlen (argv[op + 2]);
+             else
+               {
+                 if (!isint (argv[op + 1], &r))
+                   integer_expected_error ("after -gt");
+               }
+             pos += 3;
+             return (TRUE == (l > r));
+           }
+
+         if (argv[op][2] == 'e' && !argv[op][3])
+           {
+             /* ge - integer greater than or equal to */
+             if (l_is_l)
+               l = strlen (argv[op - 1]);
+             else
+               {
+                 if (!isint (argv[op - 1], &l))
+                   integer_expected_error ("before -ge");
+               }
+             if (r_is_l)
+               r = strlen (argv[op + 2]);
+             else
+               {
+                 if (!isint (argv[op + 1], &r))
+                   integer_expected_error ("after -ge");
+               }
+             pos += 3;
+             return (TRUE == (l >= r));
+           }
+         break;
+
+       case 'n':
+         if (argv[op][2] == 't' && !argv[op][3])
+           {
+             /* nt - newer than */
+             pos += 3;
+             if (l_is_l || r_is_l)
+               test_syntax_error ("-nt does not accept -l\n", (char *)NULL);
+             if (age_of (argv[op - 1], &l) && age_of (argv[op + 1], &r))
+               return (TRUE == (l > r));
+             else
+               return (FALSE);
+           }
+
+         if (argv[op][2] == 'e' && !argv[op][3])
+           {
+             /* ne - integer not equal */
+             if (l_is_l)
+               l = strlen (argv[op - 1]);
+             else
+               {
+                 if (!isint (argv[op - 1], &l))
+                   integer_expected_error ("before -ne");
+               }
+             if (r_is_l)
+               r = strlen (argv[op + 2]);
+             else
+               {
+                 if (!isint (argv[op + 1], &r))
+                   integer_expected_error ("after -ne");
+               }
+             pos += 3;
+             return (TRUE == (l != r));
+           }
+         break;
+
+       case 'e':
+         if (argv[op][2] == 'q' && !argv[op][3])
+           {
+             /* eq - integer equal */
+             if (l_is_l)
+               l = strlen (argv[op - 1]);
+             else
+               {
+                 if (!isint (argv[op - 1], &l))
+                   integer_expected_error ("before -eq");
+               }
+             if (r_is_l)
+               r = strlen (argv[op + 2]);
+             else
+               {
+                 if (!isint (argv[op + 1], &r))
+                   integer_expected_error ("after -eq");
+               }
+             pos += 3;
+             return (TRUE == (l == r));
+           }
+
+         if (argv[op][2] == 'f' && !argv[op][3])
+           {
+             /* ef - hard link? */
+             pos += 3;
+             if (l_is_l || r_is_l)
+               test_syntax_error ("-ef does not accept -l\n", (char *)NULL);
+             if (test_stat (argv[op - 1], &stat_buf) < 0)
+               return (FALSE);
+             if (test_stat (argv[op + 1], &stat_spare) < 0)
+               return (FALSE);
+             return (TRUE ==
+                     (stat_buf.st_dev == stat_spare.st_dev &&
+                      stat_buf.st_ino == stat_spare.st_ino));
+           }
+         break;
+
+       case 'o':
+         if ('t' == argv[op][2] && '\000' == argv[op][3])
+           {
+             /* ot - older than */
+             pos += 3;
+             if (l_is_l || r_is_l)
+               test_syntax_error ("-nt does not accept -l\n", (char *)NULL);
+             if (age_of (argv[op - 1], &l) && age_of (argv[op + 1], &r))
+               return (TRUE == (l < r));
+             return (FALSE);
+           }
+         break;
+       }
+      test_syntax_error ("%s: unknown binary operator", argv[op]);
+    }
+
+  if (argv[op][0] == '=' && !argv[op][1])
+    {
+      value = (argv[pos][0] == argv[pos+2][0]) &&
+             (strcmp (argv[pos], argv[pos + 2]) == 0);
+      pos += 3;
+      return (TRUE == value);
+    }
+
+  if (argv[op][0] == '!' && argv[op][1] == '=' && !argv[op][2])
+    {
+      value = (argv[pos][0] != argv[pos + 2][0]) ||
+             (strcmp (argv[pos], argv[pos + 2]) != 0);
+      pos += 3;
+      return (TRUE == value);
+    }
+  return (FALSE);
+}
+
+static int
+unary_operator ()
+{
+  long r, value;
+  struct stat stat_buf;
+
+  switch (argv[pos][1])
+    {
+    default:
+      return (FALSE);
+
+      /* All of the following unary operators use unary_advance (), which
+        checks to make sure that there is an argument, and then advances
+        pos right past it.  This means that pos - 1 is the location of the
+        argument. */
+
+    case 'a':                  /* file exists in the file system? */
+    case 'e':
+      unary_advance ();
+      value = -1 != test_stat (argv[pos - 1], &stat_buf);
+      return (TRUE == value);
+
+    case 'r':                  /* file is readable? */
+      unary_advance ();
+      value = -1 != EACCESS (argv[pos - 1], R_OK);
+      return (TRUE == value);
+
+    case 'w':                  /* File is writeable? */
+      unary_advance ();
+      value = -1 != EACCESS (argv[pos - 1], W_OK);
+      return (TRUE == value);
+
+    case 'x':                  /* File is executable? */
+      unary_advance ();
+      value = -1 != EACCESS (argv[pos - 1], X_OK);
+      return (TRUE == value);
+
+    case 'O':                  /* File is owned by you? */
+      unary_advance ();
+      if (test_stat (argv[pos - 1], &stat_buf) < 0)
+       return (FALSE);
+
+#if defined (SHELL)
+      return (TRUE == ((UID_T) current_user.euid == (UID_T) stat_buf.st_uid));
+#else
+      return (TRUE == ((UID_T) geteuid () == (UID_T) stat_buf.st_uid));
+#endif /* !SHEL */
+
+    case 'G':                  /* File is owned by your group? */
+      unary_advance ();
+      if (test_stat (argv[pos - 1], &stat_buf) < 0)
+       return (FALSE);
+
+      return (TRUE == ((GID_T) getegid () == (GID_T) stat_buf.st_gid));
+
+    case 'f':                  /* File is a file? */
+      unary_advance ();
+      if (test_stat (argv[pos - 1], &stat_buf) < 0)
+       return (FALSE);
+
+      /* Under POSIX, -f is true if the given file exists
+        and is a regular file. */
+#if defined (S_IFMT)
+      return (TRUE == ((S_ISREG (stat_buf.st_mode)) ||
+                      (0 == (stat_buf.st_mode & S_IFMT))));
+#else
+      return (TRUE == (S_ISREG (stat_buf.st_mode)));
+#endif /* !S_IFMT */
+
+    case 'd':                  /* File is a directory? */
+      unary_advance ();
+      if (test_stat (argv[pos - 1], &stat_buf) < 0)
+       return (FALSE);
+
+      return (TRUE == (S_ISDIR (stat_buf.st_mode)));
+
+    case 's':                  /* File has something in it? */
+      unary_advance ();
+      if (test_stat (argv[pos - 1], &stat_buf) < 0)
+       return (FALSE);
+
+      return (TRUE == (stat_buf.st_size > (off_t) 0));
+
+    case 'S':                  /* File is a socket? */
+#if !defined (S_ISSOCK)
+      return (FALSE);
+#else
+      unary_advance ();
+
+      if (test_stat (argv[pos - 1], &stat_buf) < 0)
+       return (FALSE);
+
+      return (TRUE == (S_ISSOCK (stat_buf.st_mode)));
+#endif                         /* S_ISSOCK */
+
+    case 'c':                  /* File is character special? */
+      unary_advance ();
+      if (test_stat (argv[pos - 1], &stat_buf) < 0)
+       return (FALSE);
+
+      return (TRUE == (S_ISCHR (stat_buf.st_mode)));
+
+    case 'b':                  /* File is block special? */
+      unary_advance ();
+      if (test_stat (argv[pos - 1], &stat_buf) < 0)
+       return (FALSE);
+
+      return (TRUE == (S_ISBLK (stat_buf.st_mode)));
+
+    case 'p':                  /* File is a named pipe? */
+      unary_advance ();
+#ifndef S_ISFIFO
+      return (FALSE);
+#else
+      if (test_stat (argv[pos - 1], &stat_buf) < 0)
+       return (FALSE);
+      return (TRUE == (S_ISFIFO (stat_buf.st_mode)));
+#endif                         /* S_ISFIFO */
+
+    case 'L':                  /* Same as -h  */
+      /*FALLTHROUGH*/
+
+    case 'h':                  /* File is a symbolic link? */
+      unary_advance ();
+#ifndef S_ISLNK
+      return (FALSE);
+#else
+      /* An empty filename is not a valid pathname. */
+      if ((argv[pos - 1][0] == '\0') ||
+         (lstat (argv[pos - 1], &stat_buf) < 0))
+       return (FALSE);
+
+      return (TRUE == (S_ISLNK (stat_buf.st_mode)));
+#endif                         /* S_IFLNK */
+
+    case 'u':                  /* File is setuid? */
+      unary_advance ();
+      if (test_stat (argv[pos - 1], &stat_buf) < 0)
+       return (FALSE);
+
+      return (TRUE == (0 != (stat_buf.st_mode & S_ISUID)));
+
+    case 'g':                  /* File is setgid? */
+      unary_advance ();
+      if (test_stat (argv[pos - 1], &stat_buf) < 0)
+       return (FALSE);
+
+      return (TRUE == (0 != (stat_buf.st_mode & S_ISGID)));
+
+    case 'k':                  /* File has sticky bit set? */
+      unary_advance ();
+      if (test_stat (argv[pos - 1], &stat_buf) < 0)
+       return (FALSE);
+#if !defined (S_ISVTX)
+      /* This is not Posix, and is not defined on some Posix systems. */
+      return (FALSE);
+#else
+      return (TRUE == (0 != (stat_buf.st_mode & S_ISVTX)));
+#endif
+
+    case 't':  /* File (fd) is a terminal?  (fd) defaults to stdout. */
+      advance (0);
+      if (pos < argc && isint (argv[pos], &r))
+       {
+         advance (0);
+         return (TRUE == (isatty ((int) r)));
+       }
+      return (TRUE == (isatty (1)));
+
+    case 'n':                  /* True if arg has some length. */
+      unary_advance ();
+      return (TRUE == (argv[pos - 1][0] != 0));
+
+    case 'z':                  /* True if arg has no length. */
+      unary_advance ();
+      return (TRUE == (argv[pos - 1][0] == '\0'));
+    }
+}
+       
+/*
+ * and:
+ *     term
+ *     term '-a' and
+ */
+static int
+and ()
+{
+  int value;
+
+  value = term ();
+  while (pos < argc && argv[pos][0] == '-' && argv[pos][1] == 'a' && !argv[pos][2])
+    {
+      advance (0);
+      value = TRUTH_AND (value, and ());
+    }
+  return (TRUE == value);
+}
+
+/*
+ * or:
+ *     and
+ *     and '-o' or
+ */
+static int
+or ()
+{
+  int value;
+
+  value = and ();
+
+  while (pos < argc && argv[pos][0] == '-' && argv[pos][1] == 'o' && !argv[pos][2])
+    {
+      advance (0);
+      value = TRUTH_OR (value, or ());
+    }
+
+  return (TRUE == value);
+}
+
+/*
+ * expr:
+ *     or
+ */
+static int
+expr ()
+{
+  if (pos >= argc)
+    beyond ();
+
+  return (FALSE ^ (or ()));            /* Same with this. */
+}
+
+/* Return TRUE if S is one of the test command's binary operators. */
+static int
+binop (s)
+     char *s;
+{
+  return ((STREQ (s,   "=")) || (STREQ (s,  "!=")) || (STREQ (s, "-nt")) ||
+         (STREQ (s, "-ot")) || (STREQ (s, "-ef")) || (STREQ (s, "-eq")) ||
+         (STREQ (s, "-ne")) || (STREQ (s, "-lt")) || (STREQ (s, "-le")) ||
+         (STREQ (s, "-gt")) || (STREQ (s, "-ge")));
+}
+
+/* Return non-zero if OP is one of the test command's unary operators. */
+static int
+unop (op)
+     int op;
+{
+  return (member (op, "abcdefgkLhprsStuwxOGnz"));
+}
+
+static int
+two_arguments ()
+{
+  int value;
+
+  if (argv[pos][0] == '!' && !argv[pos][1])
+    value = argv[pos + 1][0] == '\0';
+  else if ((argv[pos][0] == '-') && (argv[pos][2] == '\0'))
+    {
+      if (unop (argv[pos][1]))
+       value = unary_operator ();
+      else
+       test_syntax_error ("%s: unary operator expected\n", argv[pos]);
+    }
+  else
+    test_syntax_error ("%s: unary operator expected\n", argv[pos]);
+
+  return (value);
+}
+
+static int
+three_arguments ()
+{
+  int value;
+
+  if (argv[pos][0] == '!' && !argv[pos][1])
+    {
+      advance (1);
+      value = !two_arguments ();
+    }
+  else if (binop (argv[pos+1]))
+    {
+      value = binary_operator ();
+      pos = argc;
+    }
+  /* Check for -a or -o or a parenthesized subexpression. */
+  else if ((argv[pos+1][0] == '-' && !argv[pos+1][2] &&
+               (argv[pos+1][1] == 'a' || argv[pos+1][1] == 'o')) ||
+          (argv[pos][0] == '('))
+    value = expr ();
+  else
+    test_syntax_error ("%s: binary operator expected\n", argv[pos+1]);
+  return (value);
+}
+
+/* This is an implementation of a Posix.2 proposal by David Korn. */
+static int
+posixtest ()
+{
+  int value;
+
+  switch (argc - 1)    /* one extra passed in */
+    {
+      case 0:
+       value = FALSE;
+       pos = argc;
+       break;
+
+      case 1:
+       value = argv[1][0] != '\0';
+       pos = argc;
+       break;
+
+      case 2:
+       value = two_arguments ();
+       pos = argc;
+       break;
+
+      case 3:
+       value = three_arguments ();
+       break;
+
+      case 4:
+       if (STREQ (argv[pos], "!"))
+         {
+           advance (1);
+           value = !three_arguments ();
+           break;
+         }
+       /* FALLTHROUGH */
+      case 5:
+      default:
+       value = expr ();
+    }
+
+  return (value);
+}
+
+/*
+ * [:
+ *     '[' expr ']'
+ * test:
+ *     test expr
+ */
+int
+#if defined (STANDALONE)
+main (margc, margv)
+#else
+test_command (margc, margv)
+#endif /* STANDALONE */
+     int margc;
+     char **margv;
+{
+  int value;
+
+#if !defined (STANDALONE)
+  int code;
+
+  code = setjmp (test_exit_buf);
+
+  if (code)
+    return (test_error_return);
+#endif /* STANDALONE */
+
+  argv = margv;
+
+  if (margv[0] && margv[0][0] == '[' && !margv[0][1])
+    {
+      --margc;
+
+      if (margc < 2)
+       test_exit (SHELL_BOOLEAN (FALSE));
+
+      if (margv[margc] && (margv[margc][0] != ']' || margv[margc][1]))
+       test_syntax_error ("missing `]'\n", (char *)NULL);
+    }
+
+  argc = margc;
+  pos = 1;
+
+  if (pos >= argc)
+    test_exit (SHELL_BOOLEAN (FALSE));
+
+  noeval = 0;
+  value = posixtest ();
+
+  if (pos != argc)
+    test_syntax_error ("too many arguments\n", (char *)NULL);
+
+  test_exit (SHELL_BOOLEAN (value));
+}
diff --git a/tests/README b/tests/README
new file mode 100644 (file)
index 0000000..a1a081b
--- /dev/null
@@ -0,0 +1 @@
+Type `sh run-all'.
diff --git a/tests/dollar-at.sh b/tests/dollar-at.sh
new file mode 100755 (executable)
index 0000000..c3004d5
--- /dev/null
@@ -0,0 +1 @@
+recho "$@"
diff --git a/tests/dollar-star.sh b/tests/dollar-star.sh
new file mode 100755 (executable)
index 0000000..982f04c
--- /dev/null
@@ -0,0 +1 @@
+recho "$*"
diff --git a/tests/dollar.right b/tests/dollar.right
new file mode 100644 (file)
index 0000000..4d9b746
--- /dev/null
@@ -0,0 +1,3 @@
+argv[1] = <a b>
+argv[1] = <a>
+argv[2] = <b>
diff --git a/tests/exp-tests b/tests/exp-tests
new file mode 100644 (file)
index 0000000..d45b702
--- /dev/null
@@ -0,0 +1,326 @@
+#
+# A suite of tests for bash word expansions
+#
+# This tests parameter and variable expansion, with an empahsis on
+# proper quoting behavior.
+#
+# Chet Ramey
+
+#
+# If you comment out the body of this function, you can do a diff against
+# `expansion-tests.right' to see if the shell is behaving correctly
+#
+expect()
+{
+       echo expect "$@"
+}
+
+# Test the substitution quoting characters (CTLESC and CTLNUL) in different
+# combinations
+
+expect "<^A>"
+recho `echo '\ 1'`
+expect "<^A>"
+recho `echo "\ 1"`
+expect "<^B>"
+recho `echo '\ 2'`
+expect "<^B>"
+recho `echo "\ 2"`
+expect "<^A>"
+recho `echo \ 1`
+expect "<^B>"
+recho `echo \ 2`
+
+# Test null strings without variable expansion
+expect "<abcdefgh>"
+recho abcd""efgh
+expect "<abcdefgh>"
+recho abcd''efgh
+expect "<abcdefgh>"
+recho ""abcdefgh
+expect "<abcdefgh>"
+recho ''abcdefgh
+expect "<abcd>"
+recho abcd""
+expect "<abcd>"
+recho abcd''
+
+# Test the quirky behavior of $@ in ""
+expect nothing
+recho "$@"
+expect "< >"
+recho " $@"
+expect "<-->"
+recho "-${@}-"
+
+# Test null strings with variable expansion that fails
+expect '<>'
+recho $xxx""
+expect '<>'
+recho ""$xxx
+expect '<>'
+recho $xxx''
+expect '<>'
+recho ''$xxx
+expect '<>'
+recho $xxx""$yyy
+expect '<>'
+recho $xxx''$yyy
+
+# Test null strings with variable expansion that succeeds
+xxx=abc
+yyy=def
+
+expect '<abc>'
+recho $xxx""
+expect '<abc>'
+recho ""$xxx
+expect '<abc>'
+recho $xxx''
+expect '<abc>'
+recho ''$xxx
+expect '<abcdef>'
+recho $xxx""$yyy
+expect '<abcdef>'
+recho $xxx''$yyy
+
+unset xxx yyy
+
+# Test the unquoted special quoting characters
+expect "<^A>"
+recho \ 1
+expect "<^B>"
+recho \ 2
+expect "<^A>"
+recho "\ 1"
+expect "<^B>"
+recho "\ 2"
+expect "<^A>"
+recho '\ 1'
+expect "<^B>"
+recho '\ 2'
+
+# Test expansion of a variable that is unset
+expect nothing
+recho $xxx
+expect '<>'
+recho "$xxx"
+
+expect nothing
+recho "$xxx${@}"
+
+# Test empty string expansion
+expect '<>'
+recho ""
+expect '<>'
+recho ''
+
+# Test command substitution with (disabled) history substitution
+expect '<Hello World!>'
+# set +H
+recho "`echo \"Hello world!\"`"
+
+# Test some shell special characters
+expect '<`>'
+recho "\`"
+expect '<">'
+recho "\""
+expect '<\^A>'
+recho "\\ 1"
+
+expect '<\$>'
+recho "\\$"
+
+expect '<\\>'
+recho "\\\\"
+
+# This should give argv[1] = a argv[2] = b
+expect '<a> <b>'
+FOO=`echo 'a b' | tr ' ' '\012'`
+recho $FOO
+
+# This should give argv[1] = ^A argv[2] = ^B
+expect '<^A> <^B>'
+FOO=`echo '\ 1 \ 2' | tr ' ' '\012'`
+recho $FOO
+
+# Test quoted and unquoted globbing characters
+expect '<**>'
+recho "*"*
+
+expect '<\.\./*/>'
+recho "\.\./*/"
+
+# Test patterns that come up when the shell quotes funny character
+# combinations
+expect '<^A^B^A^B>'
+recho '\ 1\ 2\ 1\ 2'
+expect '<^A^A>'
+recho '\ 1\ 1'
+expect '<^A^B>'
+recho '\ 1\ 2'
+expect '<^A^A^B>'
+recho '\ 1\ 1\ 2'
+
+# More tests of "$@"
+expect '<  abc> <def> <ghi> <jkl  >'
+set abc def ghi jkl
+recho "  $@  "
+
+expect '<--abc> <def> <ghi> <jkl-->'
+set abc def ghi jkl
+recho "--$@--"
+
+expect '<  >'
+recho "  "
+expect '< - >'
+recho " - "
+
+# Test combinations of different types of quoting in a fully-quoted string
+# (so the WHOLLY_QUOTED tests fail and it doesn't get set)
+expect '</^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/>'
+recho "/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*"'$'"/\1/"
+
+# Test the various Posix parameter expansions
+
+expect '<foo bar>'
+recho "${x:-$(echo "foo bar")}"
+expect '<foo> <bar>'
+recho ${x:-$(echo "foo bar")}
+
+unset X
+expect '<abc>'
+recho ${X:=abc}
+expect '<abc>'
+recho $X
+
+set a b c
+expect '<posix>'
+recho ${3:+posix}
+
+POSIX=/usr/posix
+expect '<10>'
+recho ${#POSIX}
+
+# remove shortest trailing match
+x=file.c
+expect '<file.o>'
+recho ${x%.c}.o
+
+# remove longest trailing match
+x=posix/src/std
+expect '<posix>'
+recho ${x%%/*}
+
+# remove shortest leading pattern
+x=$HOME/src/cmd
+expect '</src/cmd>'
+recho ${x#$HOME}
+
+# remove longest leading pattern
+x=/one/two/three
+expect '<three>'
+recho ${x##*/}
+
+# Command substitution and the quirky differences between `` and $()
+
+expect '<\$x>'
+recho '\$x'
+
+expect '<$x>'
+recho `echo '\$x'`
+
+expect '<\$x>'
+recho $(echo '\$x')
+
+# The difference between $* "$*" and "$@"
+
+set "abc" "def ghi" "jkl"
+
+expect '<abc> <def> <ghi> <jkl>'
+recho $*
+
+expect '<abc def ghi jkl>'
+recho "$*"
+
+OIFS="$IFS"
+IFS=":$IFS"
+
+# The special behavior of "$*", using the first character of $IFS as separator
+expect '<abc:def ghi:jkl>'
+recho "$*"
+
+IFS="$OIFS"
+
+expect '<abc> <def ghi> <jkl>'
+recho "$@"
+
+expect '<xxabc> <def ghi> <jklyy>'
+recho "xx$@yy"
+
+expect '<abc> <def ghi> <jklabc> <def ghi> <jkl>'
+recho "$@$@"
+
+foo=abc
+bar=def
+
+expect '<abcdef>'
+recho "$foo""$bar"
+
+unset foo
+set $foo bar '' xyz "$foo" abc
+
+expect '<bar> <> <xyz> <> <abc>'
+recho "$@"
+
+# More tests of quoting and deferred evaluation
+
+foo=10 x=foo
+y='$'$x
+expect '<$foo>'
+recho $y
+eval y='$'$x
+expect '<10>'
+recho $y
+
+# case statements
+
+NL='
+'
+x='ab
+cd'
+
+expect '<newline expected>'
+case "$x" in
+*$NL*) recho "newline expected" ;;
+esac
+
+expect '<got it>'
+case \? in
+*"?"*) recho "got it" ;;
+esac
+
+expect '<got it>'
+case \? in
+*\?*) recho "got it" ;;
+esac
+
+set one two three four five
+expect '<one> <three> <five>'
+recho $1 $3 ${5} $8 ${9}
+expect '<5> <5>'
+recho $# ${#}
+
+expect '<42>'
+recho $((28 + 14))
+expect '<26>'
+recho $[ 13 * 2 ]
+
+expect '<\>'
+recho `echo \\\\`
+
+expect '<~>'
+recho '~'
+
+expect nothing
+recho $!
diff --git a/tests/exp.right b/tests/exp.right
new file mode 100644 (file)
index 0000000..f34e88a
--- /dev/null
@@ -0,0 +1,113 @@
+argv[1] = <^A>
+argv[1] = <^A>
+argv[1] = <^B>
+argv[1] = <^B>
+argv[1] = <^A>
+argv[1] = <^B>
+argv[1] = <abcdefgh>
+argv[1] = <abcdefgh>
+argv[1] = <abcdefgh>
+argv[1] = <abcdefgh>
+argv[1] = <abcd>
+argv[1] = <abcd>
+argv[1] = < >
+argv[1] = <-->
+argv[1] = <>
+argv[1] = <>
+argv[1] = <>
+argv[1] = <>
+argv[1] = <>
+argv[1] = <>
+argv[1] = <abc>
+argv[1] = <abc>
+argv[1] = <abc>
+argv[1] = <abc>
+argv[1] = <abcdef>
+argv[1] = <abcdef>
+argv[1] = <^A>
+argv[1] = <^B>
+argv[1] = <^A>
+argv[1] = <^B>
+argv[1] = <^A>
+argv[1] = <^B>
+argv[1] = <>
+argv[1] = <>
+argv[1] = <>
+argv[1] = <Hello world!>
+argv[1] = <`>
+argv[1] = <">
+argv[1] = <\^A>
+argv[1] = <\$>
+argv[1] = <\\>
+argv[1] = <a>
+argv[2] = <b>
+argv[1] = <^A>
+argv[2] = <^B>
+argv[1] = <**>
+argv[1] = <\.\./*/>
+argv[1] = <^A^B^A^B>
+argv[1] = <^A^A>
+argv[1] = <^A^B>
+argv[1] = <^A^A^B>
+argv[1] = <  abc>
+argv[2] = <def>
+argv[3] = <ghi>
+argv[4] = <jkl  >
+argv[1] = <--abc>
+argv[2] = <def>
+argv[3] = <ghi>
+argv[4] = <jkl-->
+argv[1] = <  >
+argv[1] = < - >
+argv[1] = </^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/>
+argv[1] = <foo bar>
+argv[1] = <foo>
+argv[2] = <bar>
+argv[1] = <abc>
+argv[1] = <abc>
+argv[1] = <posix>
+argv[1] = <10>
+argv[1] = <file.o>
+argv[1] = <posix>
+argv[1] = </src/cmd>
+argv[1] = <three>
+argv[1] = <\$x>
+argv[1] = <$x>
+argv[1] = <\$x>
+argv[1] = <abc>
+argv[2] = <def>
+argv[3] = <ghi>
+argv[4] = <jkl>
+argv[1] = <abc def ghi jkl>
+argv[1] = <abc:def ghi:jkl>
+argv[1] = <abc>
+argv[2] = <def ghi>
+argv[3] = <jkl>
+argv[1] = <xxabc>
+argv[2] = <def ghi>
+argv[3] = <jklyy>
+argv[1] = <abc>
+argv[2] = <def ghi>
+argv[3] = <jklabc>
+argv[4] = <def ghi>
+argv[5] = <jkl>
+argv[1] = <abcdef>
+argv[1] = <bar>
+argv[2] = <>
+argv[3] = <xyz>
+argv[4] = <>
+argv[5] = <abc>
+argv[1] = <$foo>
+argv[1] = <10>
+argv[1] = <newline expected>
+argv[1] = <got it>
+argv[1] = <got it>
+argv[1] = <one>
+argv[2] = <three>
+argv[3] = <five>
+argv[1] = <5>
+argv[2] = <5>
+argv[1] = <42>
+argv[1] = <26>
+argv[1] = <\>
+argv[1] = <~>
diff --git a/tests/glob-test b/tests/glob-test
new file mode 100644 (file)
index 0000000..e8c1c70
--- /dev/null
@@ -0,0 +1,179 @@
+#
+# test the shell globbing
+#
+expect()
+{
+       echo expect "$@"
+}
+
+TESTDIR=/tmp/glob-test
+rm -rf $TESTDIR
+mkdir $TESTDIR
+builtin cd $TESTDIR
+
+touch a b c d abc abd abe bb bcd ca cb dd de
+mkdir bdir
+
+# see if `regular' globbing works right
+expect '<a> <abc> <abd> <abe> <X*>'
+recho a* X*
+
+expect '<a> <abc> <abd> <abe>'
+recho \a*
+
+# see if null glob expansion works
+allow_null_glob_expansion=
+
+expect '<a> <abc> <abd> <abe>'
+recho a* X*
+
+unset allow_null_glob_expansion
+
+# see if the code that expands directories only works
+expect '<bdir/>'
+recho b*/
+
+# Test quoted and unquoted globbing characters
+expect '<*>'
+recho \*
+
+expect '<a*>'
+recho 'a*'
+
+expect '<a*>'
+recho a\*
+
+expect '<c> <ca> <cb> <a*> <*q*>'
+recho c* a\* *q*
+
+expect '<**>'
+recho "*"*
+
+expect '<**>'
+recho \**
+
+expect '<\.\./*/>'
+recho "\.\./*/"
+
+expect '<s/\..*//>'
+recho 's/\..*//'
+
+# Pattern from Larry Wall's Configure that caused bash to blow up
+expect '</^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/>'
+recho "/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*"'$'"/\1/"
+
+# Make sure character classes work properly
+
+expect '<abc> <abd> <abe> <bb> <cb>'
+recho [a-c]b*
+
+expect '<abd> <abe> <bb> <bcd> <bdir> <ca> <cb> <dd> <de>'
+recho [a-y]*[^c]
+
+expect '<abd> <abe>'
+recho a*[^c]
+
+touch a-b aXb
+expect '<a-b> <aXb>'
+recho a[X-]b
+
+touch .x .y
+expect '<d> <dd> <de>'
+recho [^a-c]*
+
+# Make sure that filenames with embedded globbing characters are handled
+# properly
+mkdir a\*b
+> a\*b/ooo
+
+expect '<a*b/ooo>'
+recho a\*b/*
+
+expect '<a*b/ooo>'
+recho a\*?/*
+
+expect '<no match>'
+cmd='echo !7'
+case "$cmd" in
+*\\!*) echo match ;;
+*) echo no match ;;
+esac
+
+expect '<not there>'
+file='r.*'
+case $file in
+*.\*) echo not there ;;
+*) echo there ;;
+esac
+
+# examples from the Posix.2 spec (d11.2, p. 243)
+expect '<abc>'
+recho a[b]c
+
+expect '<abc>'
+recho a["b"]c
+
+expect '<abc>'
+recho a[\b]c
+
+expect '<abc>'
+recho a?c
+
+expect '<match>'
+case abc in
+a"b"c) echo match
+       ;;
+*)     echo BAD
+       ;;
+esac
+
+expect '<match>'
+case abc in
+a*c)   echo match
+       ;;
+*)     echo BAD
+       ;;
+esac
+
+expect '<ok>'
+case abc in
+"a?c") echo bad
+       ;;
+*)     echo ok
+       ;;
+esac
+
+expect '<ok>'
+case abc in
+a\*c)  echo bad
+       ;;
+*)     echo ok
+       ;;
+esac
+
+expect '<ok>'
+case abc in
+a\[b]c)        echo bad
+       ;;
+*)     echo ok
+       ;;
+esac
+
+expect '<ok>'
+case "$nosuchvar" in
+"")    echo ok ;;
+*)     echo bad ;;
+esac
+
+# This is very odd, but sh and ksh seem to agree
+expect '<ok>'
+case abc in
+a["\b"]c) echo ok
+       ;;
+*)     echo bad
+       ;;
+esac
+
+builtin cd /
+rm -rf $TESTDIR
+exit 0
diff --git a/tests/glob.right b/tests/glob.right
new file mode 100644 (file)
index 0000000..4f2acbb
--- /dev/null
@@ -0,0 +1,63 @@
+argv[1] = <a>
+argv[2] = <abc>
+argv[3] = <abd>
+argv[4] = <abe>
+argv[5] = <X*>
+argv[1] = <a>
+argv[2] = <abc>
+argv[3] = <abd>
+argv[4] = <abe>
+argv[1] = <a>
+argv[2] = <abc>
+argv[3] = <abd>
+argv[4] = <abe>
+argv[1] = <bdir/>
+argv[1] = <*>
+argv[1] = <a*>
+argv[1] = <a*>
+argv[1] = <c>
+argv[2] = <ca>
+argv[3] = <cb>
+argv[4] = <a*>
+argv[5] = <*q*>
+argv[1] = <**>
+argv[1] = <**>
+argv[1] = <\.\./*/>
+argv[1] = <s/\..*//>
+argv[1] = </^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/>
+argv[1] = <abc>
+argv[2] = <abd>
+argv[3] = <abe>
+argv[4] = <bb>
+argv[5] = <cb>
+argv[1] = <abd>
+argv[2] = <abe>
+argv[3] = <bb>
+argv[4] = <bcd>
+argv[5] = <bdir>
+argv[6] = <ca>
+argv[7] = <cb>
+argv[8] = <dd>
+argv[9] = <de>
+argv[1] = <abd>
+argv[2] = <abe>
+argv[1] = <a-b>
+argv[2] = <aXb>
+argv[1] = <d>
+argv[2] = <dd>
+argv[3] = <de>
+argv[1] = <a*b/ooo>
+argv[1] = <a*b/ooo>
+no match
+not there
+argv[1] = <abc>
+argv[1] = <abc>
+argv[1] = <abc>
+argv[1] = <abc>
+match
+match
+ok
+ok
+ok
+ok
+ok
diff --git a/tests/ifs-test-1.sh b/tests/ifs-test-1.sh
new file mode 100644 (file)
index 0000000..a153ce9
--- /dev/null
@@ -0,0 +1,5 @@
+OIFS="$IFS"
+IFS=":$IFS"
+eval foo="a:b:c"
+IFS="$OIFS"
+echo $foo
diff --git a/tests/ifs-test-2.sh b/tests/ifs-test-2.sh
new file mode 100644 (file)
index 0000000..3249f1b
--- /dev/null
@@ -0,0 +1,9 @@
+OIFS=$IFS
+IFS=":$IFS"
+foo=$(echo a:b:c)
+IFS=$OIFS
+
+for i in $foo
+do
+       echo $i
+done
diff --git a/tests/ifs-test-3.sh b/tests/ifs-test-3.sh
new file mode 100644 (file)
index 0000000..4693792
--- /dev/null
@@ -0,0 +1,9 @@
+OIFS=$IFS
+IFS=":$IFS"
+foo=`echo a:b:c`
+IFS=$OIFS
+
+for i in $foo
+do
+       echo $i
+done
diff --git a/tests/ifs.1.right b/tests/ifs.1.right
new file mode 100644 (file)
index 0000000..af0abb2
--- /dev/null
@@ -0,0 +1 @@
+a:b:c
diff --git a/tests/ifs.2.right b/tests/ifs.2.right
new file mode 100644 (file)
index 0000000..af0abb2
--- /dev/null
@@ -0,0 +1 @@
+a:b:c
diff --git a/tests/ifs.3.right b/tests/ifs.3.right
new file mode 100644 (file)
index 0000000..af0abb2
--- /dev/null
@@ -0,0 +1 @@
+a:b:c
diff --git a/tests/input-line.sh b/tests/input-line.sh
new file mode 100644 (file)
index 0000000..086d7e3
--- /dev/null
@@ -0,0 +1,4 @@
+echo before calling input-line.sub
+../bash ./input-line.sub
+this line for input-line.sub
+echo finished with input-line.sub
diff --git a/tests/input-line.sub b/tests/input-line.sub
new file mode 100644 (file)
index 0000000..7bc8df2
--- /dev/null
@@ -0,0 +1,2 @@
+read line
+echo line read by $0 was \`$line\'
diff --git a/tests/input.right b/tests/input.right
new file mode 100644 (file)
index 0000000..8733feb
--- /dev/null
@@ -0,0 +1,3 @@
+before calling input-line.sub
+line read by ./input-line.sub was `this line for input-line.sub'
+finished with input-line.sub
diff --git a/tests/minus-e b/tests/minus-e
new file mode 100644 (file)
index 0000000..be67ec5
--- /dev/null
@@ -0,0 +1,6 @@
+set -e
+if set +e
+then
+       false
+fi
+echo hi
diff --git a/tests/minus-e.right b/tests/minus-e.right
new file mode 100644 (file)
index 0000000..45b983b
--- /dev/null
@@ -0,0 +1 @@
+hi
diff --git a/tests/misc/chld-trap.sh b/tests/misc/chld-trap.sh
new file mode 100755 (executable)
index 0000000..89b342d
--- /dev/null
@@ -0,0 +1,14 @@
+#! /bin/sh
+#
+# show that setting a trap on SIGCHLD is not disastrous.
+#
+
+trap 'echo caught a child death' SIGCHLD
+
+sleep 5 &
+sleep 5 &
+sleep 5 &
+
+wait
+
+exit 0
diff --git a/tests/misc/dot-test-1.sh b/tests/misc/dot-test-1.sh
new file mode 100644 (file)
index 0000000..eab465e
--- /dev/null
@@ -0,0 +1,3 @@
+echo this is $0
+. ./dot-test-1.sub
+echo after . dot-test-1.sub
diff --git a/tests/misc/dot-test-1.sub b/tests/misc/dot-test-1.sub
new file mode 100644 (file)
index 0000000..58df5f4
--- /dev/null
@@ -0,0 +1 @@
+echo this is dot-test-1.sub
diff --git a/tests/misc/gotest b/tests/misc/gotest
new file mode 100644 (file)
index 0000000..df0a342
--- /dev/null
@@ -0,0 +1,26 @@
+aflag=
+bflag=
+
+while getopts ab: name
+do
+       case $name in
+       a)      aflag=1 ;;
+       b)      bflag=1
+               bval=$OPTARG;;
+       ?)      echo Usage: $0 [-a] [-b value] args
+               exit 2;;
+       esac
+
+done
+
+if [ ! -z "$aflag" ] ; then echo -a specified ; fi
+if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi
+
+if [ "$OPTIND" -gt 1 ]
+then
+       shift $(( $OPTIND - 1 ))
+fi
+
+echo remaining args: "$*"
+
+exit 0
diff --git a/tests/misc/perf-script b/tests/misc/perf-script
new file mode 100644 (file)
index 0000000..e1172a9
--- /dev/null
@@ -0,0 +1,81 @@
+#!/bin/bash
+
+typeset -i m2 m1 M n2 n1 N m n
+typeset -i MM=5 NN=5
+
+case $# in
+  0) :
+  ;;
+  1) MM=$1; NN=$1
+  ;;
+  2) MM=$1; NN=$2
+  ;;
+  *) echo 1>&2 "Usage: $0 [m [n]]"
+  ;;
+esac
+
+EMPTYLINE=:  # echo
+echo 'a = { '    # mathematica
+
+let "M=1"                   # for (M=1; M<=MM; M++)
+while let "M <= MM"; do
+  let "N=1"                 # for (N=1; N<=NN; N++)
+  while let "N <= NN"; do
+
+    let "m1 = M - 1"
+    let "m2 =  M + 1"
+    let "n1 = N - 1"
+    let "n2 =  N + 1"
+
+
+    echo -n '{ '  # math
+    let "m=1"               # for(m=1; m<=MM; m++)
+    while let "m <= MM"; do
+      let "n=1"              # for(n=1; n<=NN; n++)
+      while let "n <= NN"; do
+
+        let "x = (m-m1)*(m-M)*(m-m2)"
+        let "y = (n-n1)*(n-N)*(n-n2)"
+
+        if let "(x*x + (n-N)*(n-N)) * ((m-M)*(m-M) + y*y)"; then
+         echo -n "0,"
+        else  # neighbour
+         echo -n "1,"
+        fi
+
+       let "n=n+1"
+      done
+      echo -n " "; let "m=m+1"     # ". "
+    done
+    echo '},'
+
+
+    let "N=N+1"
+    $EMPTYLINE  
+  done
+  $EMPTYLINE  
+  let "M=M+1"
+done
+
+echo '}'
+
+
+
+echo -n 'o = { '
+let "m=1"
+while let "m <= MM"; do
+  let "n=1"
+  while let "n <= NN"; do
+    echo -n "1,"
+    let "n=n+1"
+  done
+  let "m=m+1"
+done
+echo " }"
+
+
+echo 'x = LinearSolve[a,o]  '
+
+exit 0
+
+
diff --git a/tests/misc/redir.t1.sh b/tests/misc/redir.t1.sh
new file mode 100644 (file)
index 0000000..0ea00f9
--- /dev/null
@@ -0,0 +1,26 @@
+read line1
+
+echo read line1 \"$line1\"
+
+exec 4</etc/passwd
+
+exec 5<&0
+exec 0<&4
+
+read line2
+
+echo read line2 \"$line2\"
+
+exec 0<&5
+
+read line3
+
+echo read line3 \"$line3\"
+
+exec 0<&4
+
+read line4
+
+echo read line4 \"$line4\"
+
+exec 4<&-
diff --git a/tests/misc/redir.t2.sh b/tests/misc/redir.t2.sh
new file mode 100644 (file)
index 0000000..44b2624
--- /dev/null
@@ -0,0 +1,17 @@
+read line1
+
+echo read line 1 \"$line1\"
+
+exec 4<&0
+
+exec 0</dev/tty
+
+read line2
+
+echo line read from tty = \"$line2\"
+
+exec 0<&4
+
+read line3
+
+echo read line 3 \"$line3\"
diff --git a/tests/misc/redir.t3.sh b/tests/misc/redir.t3.sh
new file mode 100755 (executable)
index 0000000..9fd42c7
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Test the effect of input buffering on the shell's input
+#
+echo this is redir.t3.sh
+
+exec 0< redir.t3.sub
+
+echo after exec in redir.t3.sh
diff --git a/tests/misc/redir.t3.sub b/tests/misc/redir.t3.sub
new file mode 100644 (file)
index 0000000..b32fbaa
--- /dev/null
@@ -0,0 +1 @@
+echo this is redir-test-3.sub
diff --git a/tests/misc/redir.t4.sh b/tests/misc/redir.t4.sh
new file mode 100644 (file)
index 0000000..861acdd
--- /dev/null
@@ -0,0 +1,12 @@
+echo "Point 1"
+exec 3</etc/passwd
+exec 4>a
+exec 5>b
+echo "Point 2"
+echo to a 1>&4
+echo to b 1>&5
+exec 11</etc/printcap
+echo "Point 3"
+echo to a 1>&4
+echo to b 1>&5
+exit 0
diff --git a/tests/misc/run.r1.sh b/tests/misc/run.r1.sh
new file mode 100755 (executable)
index 0000000..bf22fe3
--- /dev/null
@@ -0,0 +1 @@
+../../bash redir.t1.sh
diff --git a/tests/misc/run.r2.sh b/tests/misc/run.r2.sh
new file mode 100755 (executable)
index 0000000..3b24701
--- /dev/null
@@ -0,0 +1 @@
+../../bash ./redir.t2.sh < /etc/passwd
diff --git a/tests/misc/run.r3.sh b/tests/misc/run.r3.sh
new file mode 100755 (executable)
index 0000000..b413674
--- /dev/null
@@ -0,0 +1,3 @@
+#
+# the `after exec in ...' should not be echoed
+../../bash < redir.t3.sh
diff --git a/tests/misc/sigint.t1.sh b/tests/misc/sigint.t1.sh
new file mode 100755 (executable)
index 0000000..7b74c30
--- /dev/null
@@ -0,0 +1,9 @@
+echo before trap
+trap 'echo caught sigint' 2
+echo after trap
+
+for i in 1 2 3
+do
+       echo $i
+       sleep 5
+done
diff --git a/tests/misc/sigint.t2.sh b/tests/misc/sigint.t2.sh
new file mode 100755 (executable)
index 0000000..69eaf56
--- /dev/null
@@ -0,0 +1,7 @@
+echo before loop
+
+for i in 1 2 3
+do
+       echo $i
+       sleep 5
+done
diff --git a/tests/misc/sigint.t3.sh b/tests/misc/sigint.t3.sh
new file mode 100755 (executable)
index 0000000..2627fe6
--- /dev/null
@@ -0,0 +1,11 @@
+sleep 5 &
+sleep 5 &
+sleep 5 &
+
+echo wait 1
+wait
+
+echo wait 2
+wait
+
+exit
diff --git a/tests/misc/sigint.t4.sh b/tests/misc/sigint.t4.sh
new file mode 100755 (executable)
index 0000000..587dd26
--- /dev/null
@@ -0,0 +1,13 @@
+trap 'echo sigint' 2
+
+sleep 5 &
+sleep 5 &
+sleep 5 &
+
+echo wait 1
+wait
+
+echo wait 2
+wait
+
+exit
diff --git a/tests/misc/test-minus-e.1 b/tests/misc/test-minus-e.1
new file mode 100644 (file)
index 0000000..03d7ecf
--- /dev/null
@@ -0,0 +1,12 @@
+touch .file
+while set -e ; test -r .file ; do
+       echo -n "stop loop? "
+       read reply
+       case "$reply" in
+       y*)     rm .file non-dash-file ;;
+       esac
+       set +e
+done
+
+       
+       
diff --git a/tests/misc/test-minus-e.2 b/tests/misc/test-minus-e.2
new file mode 100644 (file)
index 0000000..ad6a0c8
--- /dev/null
@@ -0,0 +1,14 @@
+touch .file
+set -e
+while set +e ; test -r .file ; do
+       echo -n "stop loop? [yes to quit] "
+       read reply
+       if [ "$reply" = yes ] ; then
+               rm .file non-dash-file
+       fi
+       set -e
+done
+rm -f .file
+
+       
+       
diff --git a/tests/new-exp.right b/tests/new-exp.right
new file mode 100644 (file)
index 0000000..07e2e9c
--- /dev/null
@@ -0,0 +1,33 @@
+argv[1] = <foo bar>
+argv[1] = <foo>
+argv[1] = </usr/homes/chet>
+argv[1] = </usr/homes/chet>
+argv[1] = </usr/homes/chet>
+./new-exp.tests: ${HOME:`echo }`}: bad substitution
+./new-exp.tests: ${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]}: bad substitution
+argv[1] = </usr/homes/chet>
+argv[1] = </usr/homes/chet>
+argv[1] = </usr/homes/chet>
+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] = <-abcd>
+argv[2] = <->
+argv[1] = <-abcd>
+argv[2] = <->
+argv[1] = <-abcd->
+argv[1] = <a b c d e>
+bar foo
+bar foo
+bar foo
+bar foo
+bar foo
+./new-exp.tests: ABX: unbound variable
+./new-exp.tests: $6: cannot assign in this way
+
+./new-exp.tests: ABXD: parameter unset
diff --git a/tests/new-exp.tests b/tests/new-exp.tests
new file mode 100644 (file)
index 0000000..f19ecf6
--- /dev/null
@@ -0,0 +1,95 @@
+expect()
+{
+        echo expect "$@"
+}
+
+HOME=/usr/homes/chet   # to make the check against new-exp.right work
+expect '<foo bar>'
+recho "${undef-"foo bar"}"     # should be foo bar
+expect '<foo>'
+recho "${und="foo"}"           # should be foo
+
+expect "<$HOME>"
+recho ${HOME-"}"}
+expect "<$HOME>"
+recho "${HOME-'}'}"
+expect "<$HOME>"
+recho "${HOME-"}"}"
+
+expect $0: '${HOME:`echo }`}: bad substitution'
+recho "${HOME:`echo }`}"       # should be an error -- bad substitution
+
+expect $0: '${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]}: bad substitution'
+x=${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]}    # memory leak
+
+expect "<$HOME>"
+recho ${HOME}
+expect "<$HOME>"
+recho ${HOME:-`echo }`}
+expect "<$HOME>"
+recho ${HOME:-`echo "}"`}
+expect "<$HOME>"
+recho "${HOME:-`echo "}"`}"
+expect "<$HOME>"
+recho "$(echo "${HOME}")"
+expect "<$HOME>"
+recho "$(echo "$(echo ${HOME})")"
+expect "<$HOME>"
+recho "$(echo "$(echo "${HOME}")")"
+
+P=*@*
+expect '<*@>'
+recho "${P%"*"}"         # should be *@
+expect '<@*>'
+recho "${P#\*}"                # should be @*
+
+expect '<)>'
+recho "$(echo ")")"    # should be )
+expect '<")">'
+recho "$(echo "\")\"")"        # should be ")"
+
+foo='abcd   '
+expect '<-abcd> <->'
+recho -${foo}-         # should be -abcd -
+expect '<-abcd> <->'
+recho -${foo% *}-      # should be -abcd -
+expect '<-abcd->'
+recho -${foo%% *}-     # should be -abcd-
+
+set a b c d e
+expect '<a b c d e>'
+IFS=""
+recho "$@"
+IFS='  
+'
+
+foo=bar
+expect '<bar foo>'
+echo -n $foo' ' ; echo foo
+
+expect '<bar foo>'
+echo -n $foo" " ; echo foo
+
+expect '<bar foo>'
+echo -n "$foo " ; echo foo
+
+expect '<bar foo>'
+echo -e "$foo\c " ; echo foo
+
+expect '<bar foo>'
+echo -e $foo"\c " ; echo foo
+
+set -u
+expect $0: ABX: unbound variable
+recho ${ABX}
+set +u
+
+expect $0: '$6: cannot assign in this way'
+recho ${6="arg6"}
+
+expect a newline
+echo $abmcde
+
+# this must be last!
+expect $0: 'ABXD: parameter unset'
+recho ${ABXD:?"parameter unset"}
diff --git a/tests/prec.right b/tests/prec.right
new file mode 100644 (file)
index 0000000..e6af552
--- /dev/null
@@ -0,0 +1,28 @@
+`Say' echos its argument. Its return value is of no interest.
+`Truth' echos its argument and returns a TRUE result.
+`False' echos its argument and returns a FALSE result.
+
+  Truth 1 && Truth 2   || Say 3   output=12
+( Truth 1 && Truth 2 ) || Say 3   output=12
+
+  Truth 1 && False 2   || Say 3   output=123
+( Truth 1 && False 2 ) || Say 3   output=123
+
+  False 1 && Truth 2   || Say 3   output=13
+( False 1 && Truth 2 ) || Say 3   output=13
+
+  False 1 && False 2   || Say 3   output=13
+( False 1 && False 2 ) || Say 3   output=13
+
+Truth 1 ||   Truth 2 && Say 3     output=13
+Truth 1 || ( Truth 2 && Say 3 )   output=1
+
+Truth 1 ||   False 2 && Say 3     output=13
+Truth 1 || ( False 2 && Say 3 )   output=1
+
+False 1 ||   Truth 2 && Say 3     output=123
+False 1 || ( Truth 2 && Say 3 )   output=123
+
+False 1 ||   False 2 && Say 3     output=12
+False 1 || ( False 2 && Say 3 )   output=12
+
diff --git a/tests/precedence b/tests/precedence
new file mode 100755 (executable)
index 0000000..9bbdb97
--- /dev/null
@@ -0,0 +1,75 @@
+# @(#)precedence_test 1.0 91/07/24 Maarten Litmaath
+# test of relative precedences for `&&' and `||' operators
+
+echo "\`Say' echos its argument. Its return value is of no interest."
+case `echo -n` in
+  '') Say () { echo -n "$*" ; } ;;
+   *) Say () { echo "$*\c" ; } ;;
+esac
+
+echo "\`Truth' echos its argument and returns a TRUE result."
+Truth () {
+  Say $1;
+  return 0;
+}
+
+echo "\`False' echos its argument and returns a FALSE result."
+False () {
+  Say $1;
+  return 1;
+}
+
+echo ""
+
+cmd1='$open $test1 && $test2 $close || $test3'
+cmd2='$test1 || $open $test2 && $test3 $close'
+
+grouping_sh=
+grouping_C='( )'
+
+test3='Say 3'
+
+for i in 1 2
+do
+   eval proto=\$cmd$i
+
+   for test1 in 'Truth 1' 'False 1'
+   do
+      for test2 in 'Truth 2' 'False 2'
+      do
+        for precedence in sh C
+        do
+           eval set x \$grouping_$precedence
+           shift
+           open=${1-' '}
+           close=${2-' '}
+           eval cmd=\""$proto"\"
+           Say "$cmd   output="
+           output=`eval "$cmd"`
+           Say "$output"
+           read correct || { echo 'Input fubar.  Abort.' >&2; exit 1; }
+           test "X$output" = "X$correct" || echo "   correct=$correct"
+           echo ''
+        done
+
+        echo ''
+      done
+   done
+done << EOF
+12
+12
+123
+123
+13
+13
+13
+13
+13
+1
+13
+1
+123
+123
+12
+12
+EOF
diff --git a/tests/run-all b/tests/run-all
new file mode 100755 (executable)
index 0000000..7add688
--- /dev/null
@@ -0,0 +1,17 @@
+#! /bin/sh
+
+PATH=.:$PATH                   # just to get the right version of printenv
+export PATH
+unset ENV
+
+echo Any output from any test indicates an anomaly worth investigating
+for x in run-*
+do
+       case $x in
+       $0)     ;;
+       *.orig|*~) ;;
+       *)      echo $x ; sh $x ;;
+       esac
+done
+
+exit 0
diff --git a/tests/run-dollars b/tests/run-dollars
new file mode 100755 (executable)
index 0000000..00ad7f1
--- /dev/null
@@ -0,0 +1,3 @@
+../bash ./dollar-star.sh a b > x 2>&1
+../bash ./dollar-at.sh a b >>x 2>&1
+diff x dollar.right && rm -f x
diff --git a/tests/run-exp-tests b/tests/run-exp-tests
new file mode 100755 (executable)
index 0000000..b95f603
--- /dev/null
@@ -0,0 +1,2 @@
+../bash ./exp-tests | grep -v '^expect' > xx
+diff xx exp.right && rm -f xx
diff --git a/tests/run-glob-test b/tests/run-glob-test
new file mode 100755 (executable)
index 0000000..1e598dc
--- /dev/null
@@ -0,0 +1,4 @@
+PATH=$PATH:`pwd`
+export PATH
+../bash ./glob-test | grep -v '^expect' > xx
+diff xx glob.right && rm -f xx
diff --git a/tests/run-ifs-tests b/tests/run-ifs-tests
new file mode 100755 (executable)
index 0000000..1f9c8c0
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# show that IFS is only applied to the result of expansions
+#
+../bash ifs-test-1.sh > xx
+diff xx ./ifs.1.right
+
+../bash ifs-test-2.sh > xx
+diff xx ./ifs.2.right
+
+../bash ifs-test-3.sh > xx
+diff xx ./ifs.3.right
+
+rm -f xx
diff --git a/tests/run-input-test b/tests/run-input-test
new file mode 100755 (executable)
index 0000000..25d63a0
--- /dev/null
@@ -0,0 +1,2 @@
+../bash < ./input-line.sh > xx
+diff xx input.right && rm -f xx
diff --git a/tests/run-minus-e b/tests/run-minus-e
new file mode 100755 (executable)
index 0000000..51d3229
--- /dev/null
@@ -0,0 +1,2 @@
+../bash ./minus-e > xx
+diff xx minus-e.right && rm -f xx
diff --git a/tests/run-new-exp b/tests/run-new-exp
new file mode 100755 (executable)
index 0000000..ef57d32
--- /dev/null
@@ -0,0 +1,2 @@
+../bash ./new-exp.tests 2>&1 | grep -v '^expect' > xx
+diff xx new-exp.right && rm -f xx
diff --git a/tests/run-precedence b/tests/run-precedence
new file mode 100755 (executable)
index 0000000..9303e87
--- /dev/null
@@ -0,0 +1,2 @@
+../bash ./precedence > xx
+diff xx prec.right && rm -f xx
diff --git a/tests/run-set-e-test b/tests/run-set-e-test
new file mode 100755 (executable)
index 0000000..1afef16
--- /dev/null
@@ -0,0 +1,2 @@
+../bash ./set-e-test > xx
+diff xx set-e.right && rm -f xx
diff --git a/tests/run-strip b/tests/run-strip
new file mode 100755 (executable)
index 0000000..8c97f6f
--- /dev/null
@@ -0,0 +1,2 @@
+../bash ./strip.tests > xx
+diff xx strip.right && rm -f xx
diff --git a/tests/run-varenv b/tests/run-varenv
new file mode 100755 (executable)
index 0000000..04aece9
--- /dev/null
@@ -0,0 +1,2 @@
+../bash ./varenv.sh | grep -v '^expect' > xx
+diff xx varenv.right && rm -f xx
diff --git a/tests/set-e-test b/tests/set-e-test
new file mode 100644 (file)
index 0000000..ce3feb0
--- /dev/null
@@ -0,0 +1,16 @@
+if : ; then
+       set -e
+       N=95
+       while :; do
+               # expr returns 1 if expression is null or 0
+               set +e
+               N_MOD_100=`expr $N % 100`
+               set -e
+               echo $N_MOD_100
+               N=`expr $N + 1`
+               if [ $N -eq 110 ]; then
+                       break
+               fi
+       done
+       set +e
+fi
diff --git a/tests/set-e.right b/tests/set-e.right
new file mode 100644 (file)
index 0000000..92cb7af
--- /dev/null
@@ -0,0 +1,15 @@
+95
+96
+97
+98
+99
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
diff --git a/tests/strip.right b/tests/strip.right
new file mode 100644 (file)
index 0000000..dfab897
--- /dev/null
@@ -0,0 +1,12 @@
+''
+' ab '
+' '
+''
+''
+''
+'ababababababab'
+'ababababababab  '
+'ababababababab  '
+'abababa
+bababab  '
+''
diff --git a/tests/strip.tests b/tests/strip.tests
new file mode 100644 (file)
index 0000000..b669b52
--- /dev/null
@@ -0,0 +1,22 @@
+v=`echo "" ; echo "" ; echo ""`
+echo "'$v'"
+v=`echo -n " ab "`
+echo "'$v'"
+v=`echo -n " "`
+echo "'$v'"
+v=`echo -n ""`
+echo "'$v'"
+v=`echo ""`
+echo "'$v'"
+v=`echo`
+echo "'$v'"
+v=`echo ababababababab`
+echo "'$v'"
+v=`echo "ababababababab  "`
+echo "'$v'"
+v=`echo -n "ababababababab  "`
+echo "'$v'"
+v=`echo -ne "abababa\nbababab  "`
+echo "'$v'"
+v="`echo -e '\n\n\n\n'`"
+echo "'$v'"
diff --git a/tests/tilde-tests b/tests/tilde-tests
new file mode 100644 (file)
index 0000000..a510751
--- /dev/null
@@ -0,0 +1,16 @@
+HOME=/usr/xyz
+set -v
+echo ~chet
+echo ~ch\et
+echo ~chet/"foo"
+echo "~chet"/"foo"
+echo \~chet/"foo"
+echo \~chet/bar
+echo ~\chet/bar
+echo ~chet""/bar
+echo ":~chet/"
+echo abcd~chet
+echo "SHELL=~/bash"
+echo SHELL=~/bash
+echo abcd:~chet
+echo PATH=/usr/ucb:/bin:~/bin:~/tmp/bin:/usr/bin
diff --git a/tests/tilde.right b/tests/tilde.right
new file mode 100644 (file)
index 0000000..2920187
--- /dev/null
@@ -0,0 +1,14 @@
+/usr/homes/chet
+~chet
+/usr/homes/chet/foo
+~chet/foo
+~chet/foo
+~chet/bar
+~chet/bar
+~chet/bar
+:~chet/
+abcd~chet
+SHELL=~/bash
+SHELL=/usr/xyz/bash
+abcd:~chet
+PATH=/usr/ucb:/bin:~/bin:~/tmp/bin:/usr/bin
diff --git a/tests/varenv.right b/tests/varenv.right
new file mode 100644 (file)
index 0000000..74ce5d3
--- /dev/null
@@ -0,0 +1,14 @@
+3 4
+5 6 7 8 9
+7 8 9
+/usr/chet
+/usr/chet
+/usr/chet
+/a/b/c
+/usr/chet
+/usr/chet 7
+/a/b/c 9 /a/b/c
+/a/b/c 9 /a/b/c
+/a/b/c /a/b/c
+1 2
+1 1
diff --git a/tests/varenv.sh b/tests/varenv.sh
new file mode 100644 (file)
index 0000000..d6bd4e5
--- /dev/null
@@ -0,0 +1,94 @@
+#
+# varenv.sh
+#
+# Test the behavior of the shell with respect to variable and environment
+# assignments
+#
+expect()
+{
+       echo expect "$@"
+}
+
+a=1
+b=2
+c=3
+d=4
+e=5
+f=6 g=7 h=8
+
+a=3 b=4 $CHMOD $MODE $FN
+
+# This should echo "3 4" according to Posix.2
+expect "3 4"
+echo $a $b
+
+set -k
+
+# Assignment statements made when no words are left affect the shell's
+# environment
+a=5 b=6 $CHMOD c=7 $MODE d=8 $FN e=9
+
+expect "5 6 7 8 9"
+echo $a $b $c $d $e
+
+$CHMOD f=7 $MODE g=8 $FN h=9
+expect "7 8 9"
+echo $f $g $h
+
+set +k
+
+# The temporary environment does not affect variable expansion, only the
+# environment given to the command
+
+export HOME=/usr/chet
+expect $HOME
+echo $HOME
+
+expect $HOME
+HOME=/a/b/c /bin/echo $HOME
+
+expect $HOME
+echo $HOME
+
+# This should echo /a/b/c
+expect /a/b/c
+HOME=/a/b/c printenv HOME
+
+set -k
+
+# This should echo $HOME 9, NOT /a/b/c 9
+
+expect "$HOME"
+HOME=/a/b/c /bin/echo $HOME c=9
+expect "$HOME 7"
+echo $HOME $c
+
+# I claim the next two echo calls should give identical output.
+# ksh agrees, the System V.3 sh does not
+
+expect "/a/b/c 9 /a/b/c"
+HOME=/a/b/c $ECHO a=$HOME c=9
+echo $HOME $c $a
+
+expect "/a/b/c 9 /a/b/c"
+HOME=/a/b/c a=$HOME c=9
+echo $HOME $c $a
+set +k
+
+# How do assignment statements affect subsequent assignments on the same
+# line?
+expect "/a/b/c /a/b/c"
+HOME=/a/b/c a=$HOME
+echo $HOME $a
+
+# The system V.3 sh does this wrong; the last echo should output "1 1",
+# but the system V.3 sh has it output "2 2".  Posix.2 says the assignment
+# statements are processed left-to-right.  bash and ksh output the right
+# thing
+c=1
+d=2
+expect "1 2"
+echo $c $d
+d=$c c=$d
+expect "1 1"
+echo $c $d
diff --git a/trap.c b/trap.c
new file mode 100644 (file)
index 0000000..c2b951b
--- /dev/null
+++ b/trap.c
@@ -0,0 +1,672 @@
+/* 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.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 1, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#include "bashtypes.h"
+#include "trap.h"
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "shell.h"
+#include "signames.h"
+
+/* Flags which describe the current handling state of a signal. */
+#define SIG_INHERITED   0x0    /* Value inherited from parent. */
+#define SIG_TRAPPED     0x1    /* Currently trapped. */
+#define SIG_HARD_IGNORE 0x2    /* Signal was ignored on shell entry. */
+#define SIG_SPECIAL     0x4    /* Treat this signal specially. */
+#define SIG_NO_TRAP     0x8    /* Signal cannot be trapped. */
+#define SIG_INPROGRESS  0x10   /* Signal handler currently executing. */
+#define SIG_CHANGED     0x20   /* Trap value changed in trap handler. */
+#define SIG_IGNORED     0x40   /* The signal is currently being ignored. */
+
+/* An array of such flags, one for each signal, describing what the
+   shell will do with a signal. */
+static int sigmodes[NSIG];
+
+static void change_signal (), restore_signal ();
+
+/* Variables used here but defined in other files. */
+extern int interactive_shell, interactive;
+extern int interrupt_immediately;
+extern int last_command_exit_value;
+
+/* The list of things to do originally, before we started trapping. */
+SigHandler *original_signals[NSIG];
+
+/* For each signal, a slot for a string, which is a command to be
+   executed when that signal is recieved.  The slot can also contain
+   DEFAULT_SIG, which means do whatever you were going to do before
+   you were so rudely interrupted, or IGNORE_SIG, which says ignore
+   this signal. */
+char *trap_list[NSIG];
+
+/* A bitmap of signals received for which we have trap handlers. */
+int pending_traps[NSIG];
+
+/* A value which can never be the target of a trap handler. */
+#define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
+
+void
+initialize_traps ()
+{
+  register int i;
+
+  trap_list[0] = (char *)NULL;
+  sigmodes[0] = SIG_INHERITED; /* On EXIT trap handler. */
+
+  for (i = 1; i < NSIG; i++)
+    {
+      pending_traps[i] = 0;
+      trap_list[i] = (char *)DEFAULT_SIG;
+      sigmodes[i] = SIG_INHERITED;
+      original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
+    }
+
+  /* Show which signals are treated specially by the shell. */
+#if defined (SIGCHLD)
+  original_signals[SIGCHLD] = (SigHandler *) set_signal_handler (SIGCHLD, SIG_DFL);
+  set_signal_handler (SIGCHLD, original_signals[SIGCHLD]);
+  sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
+#endif /* SIGCHLD */
+
+  original_signals[SIGINT] =
+    (SigHandler *) set_signal_handler (SIGINT, SIG_DFL);
+  set_signal_handler (SIGINT, original_signals[SIGINT]);
+  sigmodes[SIGINT] |= SIG_SPECIAL;
+
+  original_signals[SIGQUIT] =
+    (SigHandler *) set_signal_handler (SIGQUIT, SIG_DFL);
+  set_signal_handler (SIGQUIT, original_signals[SIGQUIT]);
+  sigmodes[SIGQUIT] |= SIG_SPECIAL;
+
+  if (interactive)
+    {
+      original_signals[SIGTERM] = (SigHandler *)set_signal_handler (SIGTERM, SIG_DFL);
+      set_signal_handler (SIGTERM, original_signals[SIGTERM]);
+      sigmodes[SIGTERM] |= SIG_SPECIAL;
+    }
+}
+
+/* Return the print name of this signal. */
+char *
+signal_name (sig)
+     int sig;
+{
+  if (sig >= NSIG || sig < 0)
+    return ("bad signal number");
+  else
+    return (signal_names[sig]);
+}
+
+/* Turn a string into a signal number, or a number into
+   a signal number.  If STRING is "2", "SIGINT", or "INT",
+   then (int)2 is returned.  Return NO_SIG if STRING doesn't
+   contain a valid signal descriptor. */
+int
+decode_signal (string)
+     char *string;
+{
+  int sig;
+
+  if (sscanf (string, "%d", &sig) == 1)
+    {
+      if (sig < NSIG && sig >= 0)
+       return (sig);
+      else
+       return (NO_SIG);
+    }
+
+  for (sig = 0; sig < NSIG; sig++)
+    if (STREQ (string, signal_names[sig]) ||
+       STREQ (string, &(signal_names[sig])[3]))
+      return (sig);
+
+  return (NO_SIG);
+}
+
+/* Non-zero when we catch a trapped signal. */
+static int catch_flag = 0;
+
+#if !defined (USG) && !defined (USGr4)
+#define HAVE_BSD_SIGNALS
+#endif
+
+void
+run_pending_traps ()
+{
+  register int sig;
+  int old_exit_value;
+
+  if (catch_flag == 0)         /* simple optimization */
+    return;
+
+  catch_flag = 0;
+
+  /* Preserve $? when running trap. */
+  old_exit_value = last_command_exit_value;
+
+  for (sig = 1; sig < NSIG; sig++)
+    {
+      /* XXX this could be made into a counter by using
+         while (pending_traps[sig]--) instead of the if statement. */
+      if (pending_traps[sig])
+       {
+#if defined (_POSIX_VERSION)
+         sigset_t set, oset;
+
+         sigemptyset (&set);
+         sigemptyset (&oset);
+
+         sigaddset (&set, sig);
+         sigprocmask (SIG_BLOCK, &set, &oset);
+#else
+#  if defined (HAVE_BSD_SIGNALS)
+         int oldmask = sigblock (sigmask (sig));
+#  endif
+#endif /* POSIX_VERSION */
+
+         if (sig == SIGINT)
+           {
+             run_interrupt_trap ();
+             interrupt_state = 0;
+           }
+         else
+           parse_and_execute (savestring (trap_list[sig]), "trap", 0);
+
+         pending_traps[sig] = 0;
+
+#if defined (_POSIX_VERSION)
+         sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+#else
+#  if defined (HAVE_BSD_SIGNALS)
+         sigsetmask (oldmask);
+#  endif
+#endif /* POSIX_VERSION */
+       }
+    }
+
+  last_command_exit_value = old_exit_value;
+}
+
+sighandler
+trap_handler (sig)
+     int sig;
+{
+  if ((sig >= NSIG) ||
+      (trap_list[sig] == (char *)DEFAULT_SIG) ||
+      (trap_list[sig] == (char *)IGNORE_SIG))
+    programming_error ("trap_handler: Bad signal %d", sig);
+  else
+    {
+#if defined (USG) && !defined (HAVE_BSD_SIGNALS) && !defined (_POSIX_VERSION)
+      set_signal_handler (sig, trap_handler);
+#endif /* USG && !HAVE_BSD_SIGNALS && !_POSIX_VERSION */
+
+      catch_flag = 1;
+      pending_traps[sig]++;
+
+      if (interrupt_immediately)
+       run_pending_traps ();
+    }
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* VOID_SIGHANDLER */
+}
+
+#if defined (JOB_CONTROL) && defined (SIGCHLD)
+/* Make COMMAND_STRING be executed when SIGCHLD is caught. */
+void
+set_sigchld_trap (command_string)
+     char *command_string;
+{
+  void set_signal ();
+
+  set_signal (SIGCHLD, command_string);
+}
+
+/* Make COMMAND_STRING be executed when SIGCHLD is caught iff the current
+   SIGCHLD trap handler is DEFAULT_SIG. */
+void
+maybe_set_sigchld_trap (command_string)
+     char *command_string;
+{
+  void set_signal ();
+
+  if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0)
+    set_signal (SIGCHLD, command_string);
+}
+#endif /* JOB_CONTROL && SIGCHLD */
+
+static void
+set_sigint_trap (command)
+     char *command;
+{
+  void set_signal ();
+
+  set_signal (SIGINT, command);
+}
+
+/* Reset the SIGINT handler so that subshells that are doing `shellsy'
+   things, like waiting for command substitution or executing commands
+   in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
+SigHandler *
+set_sigint_handler ()
+{
+  if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
+    return ((SigHandler *)SIG_IGN);
+
+  else if (sigmodes[SIGINT] & SIG_IGNORED)
+    return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN));
+    
+  else if (sigmodes[SIGINT] & SIG_TRAPPED)
+    return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
+
+  /* The signal is not trapped, so set the handler to the shell's special
+     interrupt handler. */
+  else if (interactive)        /* XXX - was interactive_shell */
+    return (set_signal_handler (SIGINT, sigint_sighandler));
+  else
+    return (set_signal_handler (SIGINT, termination_unwind_protect));
+}
+
+/* Set SIG to call STRING as a command. */
+void
+set_signal (sig, string)
+     int sig;
+     char *string;
+{
+  /* A signal ignored on entry to the shell cannot be trapped or reset, but
+     no error is reported when attempting to do so.  -- Posix.2 */
+  if (sigmodes[sig] & SIG_HARD_IGNORE)
+    return;
+
+  /* Make sure we have original_signals[sig] if the signal has not yet
+     been trapped. */
+  if ((sigmodes[sig] & SIG_TRAPPED) == 0)
+    {
+      /* If we aren't sure of the original value, check it. */
+      if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
+       {
+         original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL);
+         set_signal_handler (sig, original_signals[sig]);
+       }
+
+      /* Signals ignored on entry to the shell cannot be trapped or reset. */
+      if (original_signals[sig] == SIG_IGN)
+       {
+         sigmodes[sig] |= SIG_HARD_IGNORE;
+         return;
+       }
+    }
+
+  /* Only change the system signal handler if SIG_NO_TRAP is not set.
+     The trap command string is changed in either case.  The shell signal
+     handlers for SIGINT and SIGCHLD run the user specified traps in an
+     environment in which it is safe to do so. */
+  if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
+    {
+      set_signal_handler (sig, SIG_IGN);
+      change_signal (sig, savestring (string));
+      set_signal_handler (sig, trap_handler);
+    }
+  else
+    change_signal (sig, savestring (string));
+}
+
+static void
+free_trap_command (sig)
+     int sig;
+{
+  if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
+      (trap_list[sig] != (char *)IGNORE_SIG) &&
+      (trap_list[sig] != (char *)DEFAULT_SIG) &&
+      (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
+    free (trap_list[sig]);
+}
+     
+/* If SIG has a string assigned to it, get rid of it.  Then give it
+   VALUE. */
+static void
+change_signal (sig, value)
+     int sig;
+     char *value;
+{
+  free_trap_command (sig);
+  trap_list[sig] = value;
+
+  sigmodes[sig] |= SIG_TRAPPED;
+  if (value == (char *)IGNORE_SIG)
+    sigmodes[sig] |= SIG_IGNORED;
+  else
+    sigmodes[sig] &= ~SIG_IGNORED;
+  if (sigmodes[sig] & SIG_INPROGRESS)
+    sigmodes[sig] |= SIG_CHANGED;
+}
+
+#define GET_ORIGINAL_SIGNAL(sig) \
+  if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
+    get_original_signal (sig)
+
+static void
+get_original_signal (sig)
+     int sig;
+{
+  /* If we aren't sure the of the original value, then get it. */
+  if (original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
+    {
+      original_signals[sig] =
+       (SigHandler *) set_signal_handler (sig, SIG_DFL);
+      set_signal_handler (sig, original_signals[sig]);
+
+      /* Signals ignored on entry to the shell cannot be trapped. */
+      if (original_signals[sig] == SIG_IGN)
+       sigmodes[sig] |= SIG_HARD_IGNORE;
+    }
+}
+
+/* Restore the default action for SIG; i.e., the action the shell
+   would have taken before you used the trap command.  This is called
+   from trap_builtin (), which takes care to restore the handlers for
+   the signals the shell treats specially. */
+void
+restore_default_signal (sig)
+     int sig;
+{
+  if (sig == 0)
+    {
+      free_trap_command (sig);
+      trap_list[sig] = (char *)NULL;
+      sigmodes[sig] &= ~SIG_TRAPPED;
+      return;
+    }
+
+  GET_ORIGINAL_SIGNAL (sig);
+
+  /* A signal ignored on entry to the shell cannot be trapped or reset, but
+     no error is reported when attempting to do so.  Thanks Posix.2. */
+  if (sigmodes[sig] & SIG_HARD_IGNORE)
+    return;
+
+  /* If we aren't trapping this signal, don't bother doing anything else. */
+  if (!(sigmodes[sig] & SIG_TRAPPED))
+    return;
+
+  /* Only change the signal handler for SIG if it allows it. */
+  if (!(sigmodes[sig] & SIG_NO_TRAP))
+    set_signal_handler (sig, original_signals[sig]);
+
+  /* Change the trap command in either case. */
+  change_signal (sig, (char *)DEFAULT_SIG);
+
+  /* Mark the signal as no longer trapped. */
+  sigmodes[sig] &= ~SIG_TRAPPED;
+}
+
+/* Make this signal be ignored. */
+void
+ignore_signal (sig)
+     int sig;
+{
+  GET_ORIGINAL_SIGNAL (sig);
+
+  /* A signal ignored on entry to the shell cannot be trapped or reset.
+     No error is reported when the user attempts to do so.
+     Thanks to Posix.2. */
+  if (sigmodes[sig] & SIG_HARD_IGNORE)
+    return;
+
+  /* If already trapped and ignored, no change necessary. */
+  if ((sigmodes[sig] & SIG_TRAPPED) && (trap_list[sig] == (char *)IGNORE_SIG))
+    return;
+
+  /* Only change the signal handler for SIG if it allows it. */
+  if (!(sigmodes[sig] & SIG_NO_TRAP))
+    set_signal_handler (sig, SIG_IGN);
+
+  /* Change the trap command in either case. */
+  change_signal (sig, (char *)IGNORE_SIG);
+}
+
+/* Handle the calling of "trap 0".  The only sticky situation is when
+   the command to be executed includes an "exit".  This is why we have
+   to provide our own place for top_level to jump to. */
+int
+run_exit_trap ()
+{
+  int old_exit_value;
+
+  old_exit_value = last_command_exit_value;
+
+  /* Run the trap only if signal 0 is trapped and not ignored. */
+  if ((sigmodes[0] & SIG_TRAPPED) &&
+      (trap_list[0] != (char *)IGNORE_SIG) &&
+      (sigmodes[0] & SIG_INPROGRESS) == 0)
+    {
+      char *trap_command;
+      int code;
+
+      trap_command= savestring (trap_list[0]);
+      sigmodes[0] &= ~SIG_TRAPPED;
+      sigmodes[0] |= SIG_INPROGRESS;
+
+      code = setjmp (top_level);
+
+      if (code == 0)
+       parse_and_execute (trap_command, "trap", 0);
+      else if (code == EXITPROG)
+       return (last_command_exit_value);
+      else
+       return (old_exit_value);
+    }
+
+  return (old_exit_value);
+}
+
+/* Set the handler signal SIG to the original and free any trap
+   command associated with it. */     
+static void
+restore_signal (sig)
+     int sig;
+{
+  set_signal_handler (sig, original_signals[sig]);
+  change_signal (sig, (char *)DEFAULT_SIG);
+  sigmodes[sig] &= ~SIG_TRAPPED;
+}
+
+/* Free all the allocated strings in the list of traps and reset the trap
+   values to the default. */
+void
+free_trap_strings ()
+{
+  register int i;
+
+  for (i = 0; i < NSIG; i++)
+    {
+      free_trap_command (i);
+      trap_list[i] = (char *)DEFAULT_SIG;
+      sigmodes[i] &= ~SIG_TRAPPED;
+    }
+}
+
+/* Reset the handler for SIG to the original value. */
+static void
+reset_signal (sig)
+     int sig;
+{
+  set_signal_handler (sig, original_signals[sig]);
+}
+
+/* Reset the handlers for all trapped signals to the values they had when
+   the shell was started. */
+void
+reset_signal_handlers ()
+{
+  register int i;
+
+  if (sigmodes[0] & SIG_TRAPPED)
+    {
+      free_trap_command (0);
+      trap_list[0] = (char *)NULL;
+      sigmodes[0] &= ~SIG_TRAPPED;
+    }
+
+  for (i = 1; i < NSIG; i++)
+    {
+      if (sigmodes[i] & SIG_SPECIAL)
+       reset_signal (i);
+      else if (sigmodes[i] & SIG_TRAPPED)
+       {
+         if (trap_list[i] == (char *)IGNORE_SIG)
+           set_signal_handler (i, SIG_IGN);
+         else
+           reset_signal (i);
+       }
+    }
+}
+
+/* Reset all trapped signals to their original values.  Signals set to be
+   ignored with trap '' SIGNAL should be ignored, so we make sure that they
+   are.  Called by child processes after they are forked. */
+void
+restore_original_signals ()
+{
+  register int i;
+
+  reset_terminating_signals ();                /* in shell.c */
+
+  if (sigmodes[0] & SIG_TRAPPED)
+    {
+      free_trap_command (0);
+      trap_list[0] = (char *)NULL;
+      sigmodes[0] &= ~SIG_TRAPPED;
+    }
+
+  for (i = 1; i < NSIG; i++)
+    {
+      if (sigmodes[i] & SIG_SPECIAL)
+       restore_signal (i);
+      else if (sigmodes[i] & SIG_TRAPPED)
+       {
+         if (trap_list[i] == (char *)IGNORE_SIG)
+           set_signal_handler (i, SIG_IGN);
+         else
+           restore_signal (i);
+       }
+    }
+}
+
+/* Run a trap set on SIGINT.  This is called from throw_to_top_level (), and
+   declared here to localize the trap functions. */
+void
+run_interrupt_trap ()
+{
+  char *command, *saved_command;
+  int old_exit_value;
+
+  /* Run the interrupt trap if SIGINT is trapped and not ignored, and if
+     we are not currently running in the interrupt trap handler. */
+  if ((sigmodes[SIGINT] & SIG_TRAPPED) &&
+      (trap_list[SIGINT] != (char *)IGNORE_SIG) &&
+      (trap_list[SIGINT] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
+      ((sigmodes[SIGINT] & SIG_INPROGRESS) == 0))
+    {
+      saved_command = trap_list[SIGINT];
+      sigmodes[SIGINT] |= SIG_INPROGRESS;
+      sigmodes[SIGINT] &= ~SIG_CHANGED;
+
+      command = savestring (saved_command);
+
+      old_exit_value = last_command_exit_value;
+      parse_and_execute (command, "interrupt trap", 0);
+      last_command_exit_value = old_exit_value;
+
+      sigmodes[SIGINT] &= ~SIG_INPROGRESS;
+
+      if (sigmodes[SIGINT] & SIG_CHANGED)
+       {
+         free (saved_command);
+         sigmodes[SIGINT] &= ~SIG_CHANGED;
+       }
+    }
+}
+
+/* If a trap handler exists for signal SIG, then call it; otherwise just
+   return failure. */
+int
+maybe_call_trap_handler (sig)
+     int sig;
+{
+  /* Call the trap handler for SIG if the signal is trapped and not ignored. */
+  if ((sigmodes[sig] & SIG_TRAPPED) &&
+      (trap_list[sig] != (char *)IGNORE_SIG))
+    {
+      switch (sig)
+       {
+       case SIGINT:
+         run_interrupt_trap ();
+         break;
+       case 0:
+         run_exit_trap ();
+         break;
+       default:
+         trap_handler (sig);
+         break;
+       }
+      return (1);
+    }
+  else
+    return (0);
+}
+
+int
+signal_is_trapped (sig)
+     int sig;
+{
+  return (sigmodes[sig] & SIG_TRAPPED);
+}
+
+int
+signal_is_special (sig)
+     int sig;
+{
+  return (sigmodes[sig] & SIG_SPECIAL);
+}
+
+int
+signal_is_ignored (sig)
+     int sig;
+{
+  return (sigmodes[sig] & SIG_IGNORED);
+}
+
+void
+set_signal_ignored (sig)
+     int sig;
+{
+  sigmodes[sig] |= SIG_HARD_IGNORE;
+  original_signals[sig] = SIG_IGN; 
+}
diff --git a/trap.h b/trap.h
new file mode 100644 (file)
index 0000000..1670231
--- /dev/null
+++ b/trap.h
@@ -0,0 +1,65 @@
+/* trap.h -- data structures used in the trap mechanism. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (__TRAP_H__)
+#define __TRAP_H__
+
+#include "stdc.h"
+
+#if !defined (SIG_DFL)
+#include <sys/types.h>
+#include <signal.h>
+#endif /* SIG_DFL */
+
+#if !defined (NSIG)
+#define NSIG 64
+#endif /* !NSIG */
+
+#define NO_SIG -1
+#define DEFAULT_SIG SIG_DFL
+#define IGNORE_SIG  SIG_IGN
+
+#define signal_object_p(x) (decode_signal (x) != NO_SIG)
+
+extern char *trap_list[NSIG];
+
+/* Externally-visible functions declared in trap.c. */
+extern void initialize_traps __P((void));
+extern void run_pending_traps __P((void));
+extern void maybe_set_sigchld_trap __P((char *));
+extern void set_sigchld_trap __P((char *));
+extern void set_signal __P((int, char *));
+extern void restore_default_signal __P((int));
+extern void ignore_signal __P((int));
+extern int run_exit_trap __P((void));
+extern void free_trap_strings __P((void));
+extern void reset_signal_handlers __P((void));
+extern void restore_original_signals __P((void));
+
+extern char *signal_name __P((int));
+
+extern int decode_signal __P((char *));
+extern void run_interrupt_trap __P((void));
+extern int maybe_call_trap_handler __P((int));
+extern int signal_is_trapped __P((int));
+extern int signal_is_special __P((int));
+extern int signal_is_ignored __P((int));
+
+#endif /* __TRAP_H__ */
diff --git a/unwind_prot.c b/unwind_prot.c
new file mode 100644 (file)
index 0000000..d9399d7
--- /dev/null
@@ -0,0 +1,272 @@
+/* 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.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                   Unwind Protection Scheme for Bash             */
+/*                                                                 */
+/* **************************************************************** */
+#include "bashtypes.h"
+#include <signal.h>
+#include "config.h"
+#include "command.h"
+#include "general.h"
+#include "unwind_prot.h"
+#include "quit.h"
+
+/* If CLEANUP is null, then ARG contains a tag to throw back to. */
+typedef struct _uwp {
+  struct _uwp *next;
+  Function *cleanup;
+  char *arg;
+} UNWIND_ELT;
+
+static void
+  unwind_frame_discard_internal (), unwind_frame_run_internal (),
+  add_unwind_protect_internal (), remove_unwind_protect_internal (),
+  run_unwind_protects_internal (), without_interrupts ();
+
+static UNWIND_ELT *unwind_protect_list = (UNWIND_ELT *)NULL;
+
+extern int interrupt_immediately;
+
+/* Run a function without interrupts.  This relies on the fact that the
+   FUNCTION cannot change the value of interrupt_immediately.  (I.e., does
+   not call QUIT (). */
+static void
+without_interrupts (function, arg1, arg2)
+     VFunction *function;
+     char *arg1, *arg2;
+{
+  int old_interrupt_immediately;
+
+  old_interrupt_immediately = interrupt_immediately;
+  interrupt_immediately = 0;
+
+  (*function)(arg1, arg2);
+
+  interrupt_immediately = old_interrupt_immediately;
+}
+
+/* Start the beginning of a region. */
+void
+begin_unwind_frame (tag)
+     char *tag;
+{
+  add_unwind_protect ((Function *)NULL, tag);
+}
+
+/* Discard the unwind protects back to TAG. */
+void
+discard_unwind_frame (tag)
+     char *tag;
+{
+  if (unwind_protect_list)
+    without_interrupts (unwind_frame_discard_internal, tag, (char *)NULL);
+}
+
+/* Run the unwind protects back to TAG. */
+void
+run_unwind_frame (tag)
+     char *tag;
+{
+  if (unwind_protect_list)
+    without_interrupts (unwind_frame_run_internal, tag, (char *)NULL);
+}
+
+/* Add the function CLEANUP with ARG to the list of unwindable things. */
+void
+add_unwind_protect (cleanup, arg)
+     Function *cleanup;
+     char *arg;
+{
+  without_interrupts (add_unwind_protect_internal, (char *)cleanup, arg);
+}
+
+/* Remove the top unwind protect from the list. */
+void
+remove_unwind_protect ()
+{
+  if (unwind_protect_list)
+    without_interrupts
+      (remove_unwind_protect_internal, (char *)NULL, (char *)NULL);
+}
+
+/* Run the list of cleanup functions in unwind_protect_list. */
+void
+run_unwind_protects ()
+{
+  if (unwind_protect_list)
+    without_interrupts
+      (run_unwind_protects_internal, (char *)NULL, (char *)NULL);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                        The Actual Functions                             */
+/*                                                                 */
+/* **************************************************************** */
+
+static void
+add_unwind_protect_internal (cleanup, arg)
+     Function *cleanup;
+     char *arg;
+{
+  UNWIND_ELT *elt;
+
+  elt = (UNWIND_ELT *)xmalloc (sizeof (UNWIND_ELT));
+  elt->cleanup = cleanup;
+  elt->arg = arg;
+  elt->next = unwind_protect_list;
+  unwind_protect_list = elt;
+}
+
+static void
+remove_unwind_protect_internal ()
+{
+  UNWIND_ELT *elt = unwind_protect_list;
+
+  if (elt)
+    {
+      unwind_protect_list = unwind_protect_list->next;
+      free (elt);
+    }
+}
+
+static void
+run_unwind_protects_internal ()
+{
+  UNWIND_ELT *t, *elt = unwind_protect_list;
+
+  while (elt)
+   {
+      /* This function can be run at strange times, like when unwinding
+       the entire world of unwind protects.  Thus, we may come across
+        an element which is simply a label for a catch frame.  Don't call
+        the non-existant function. */
+      if (elt->cleanup)
+       (*(elt->cleanup)) (elt->arg);
+
+      t = elt;
+      elt = elt->next;
+      free (t);
+    }
+  unwind_protect_list = elt;
+}
+
+static void
+unwind_frame_discard_internal (tag)
+     char *tag;
+{
+  UNWIND_ELT *elt;
+
+  while (elt = unwind_protect_list)
+    {
+      unwind_protect_list = unwind_protect_list->next;
+      if (!elt->cleanup && (STREQ (elt->arg, tag)))
+       {
+         free (elt);
+         break;
+       }
+      else
+       free (elt);
+    }
+}
+
+static void
+unwind_frame_run_internal (tag)
+     char *tag;
+{
+  UNWIND_ELT *elt;
+
+  while (elt = unwind_protect_list)
+    {
+      unwind_protect_list = elt->next;
+
+      /* If tag, then compare. */
+      if (!elt->cleanup)
+       {
+         if (STREQ (elt->arg, tag))
+           {
+             free (elt);
+             break;
+           }
+         free (elt);
+         continue;
+       }
+      else
+       {
+         (*(elt->cleanup)) (elt->arg);
+         free (elt);
+       }
+    }
+}
+
+/* Structure describing a saved variable and the value to restore it to. */
+typedef struct {
+  int *variable;
+  char *desired_setting;
+  int size;
+} SAVED_VAR;
+
+/* Restore the value of a variable, based on the contents of SV.  If
+   sv->size is greater than sizeof (int), sv->desired_setting points to
+   a block of memory SIZE bytes long holding the value, rather than the
+   value itself.  This block of memory is copied back into the variable. */
+static void
+restore_variable (sv)
+     SAVED_VAR *sv;
+{
+  if (sv->size > sizeof (int))
+    {
+      bcopy ((char *)sv->desired_setting, (char *)sv->variable, sv->size);
+      free (sv->desired_setting);
+    }
+  else
+    *(sv->variable) = (int)sv->desired_setting;
+
+  free (sv);
+}
+
+/* Save the value of a variable so it will be restored when unwind-protects
+   are run.  VAR is a pointer to the variable.  VALUE is the value to be
+   saved.  SIZE is the size in bytes of VALUE.  If SIZE is bigger than what
+   can be saved in an int, memory will be allocated and the value saved
+   into that using bcopy (). */
+void
+unwind_protect_var (var, value, size)
+     int *var;
+     char *value;
+     int size;
+{
+  SAVED_VAR *s = (SAVED_VAR *)xmalloc (sizeof (SAVED_VAR));
+
+  s->variable = var;
+  if (size > sizeof (int))
+    {
+      s->desired_setting = (char *)xmalloc (size);
+      bcopy (value, (char *)s->desired_setting, size);
+    }
+  else
+    s->desired_setting = value;
+  s->size = size;
+  add_unwind_protect ((Function *)restore_variable, (char *)s);
+}
diff --git a/unwind_prot.h b/unwind_prot.h
new file mode 100644 (file)
index 0000000..e013631
--- /dev/null
@@ -0,0 +1,47 @@
+/* unwind_prot.h - Macros and functions for hacking unwind protection. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_UNWIND_PROT_H)
+#define _UNWIND_PROT_H
+
+/* Run a function without interrupts. */
+void
+  begin_unwind_frame (), discard_unwind_frame (),
+  run_unwind_frame (), add_unwind_protect (), remove_unwind_protect (),
+  run_unwind_protects ();
+
+/* Define for people who like their code to look a certain way. */
+#define end_unwind_frame()
+
+/* How to protect an integer. */
+#define unwind_protect_int(X) unwind_protect_var (&(X), (char *)(X), sizeof (int))
+
+/* How to protect a pointer to a string. */
+#define unwind_protect_string(X) \
+  unwind_protect_var ((int *)&(X), (X), sizeof (char *))
+
+/* How to protect any old pointer. */
+#define unwind_protect_pointer(X) unwind_protect_string (X)
+
+/* How to protect the contents of a jmp_buf. */
+#define unwind_protect_jmp_buf(X) \
+  unwind_protect_var ((int *)(X), (char *)(X), sizeof (jmp_buf))
+
+#endif /* _UNWIND_PROT_H */
diff --git a/variables.c b/variables.c
new file mode 100644 (file)
index 0000000..2c911c2
--- /dev/null
@@ -0,0 +1,1804 @@
+/* variables.c -- Functions for hacking shell variables. */
+
+/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "bashtypes.h"
+#include "posixstat.h"
+#include <ctype.h>
+#include <pwd.h>
+
+#include "bashansi.h"
+#include "shell.h"
+#include "hash.h"
+#include "flags.h"
+#include "execute_cmd.h"
+
+#include "builtins/common.h"
+#include <tilde/tilde.h>
+
+/* Variables used here and defined in other files. */
+extern int posixly_correct;
+extern int variable_context, line_number;
+extern int interactive, interactive_shell, login_shell, shell_level;
+extern int subshell_environment;
+extern int build_version;
+extern char *dist_version;
+extern char *shell_name;
+extern char *primary_prompt, *secondary_prompt;
+extern Function *this_shell_builtin;
+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 functions that the user has created, or that came from
+   the environment. */
+HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
+
+/* The current variable context.  This is really a count of how deep into
+   executing functions we are. */
+int variable_context = 0;
+
+/* The array 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., "source"). */
+char **builtin_env = (char **)NULL;
+
+/* Some funky variables which are known about specially.  Here is where
+   "$*", "$1", and all the cruft is kept. */
+char *dollar_vars[10];
+WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
+
+/* The value of $$. */
+int dollar_dollar_pid;
+
+/* An array which is passed to commands as their environment.  It is
+   manufactured from the overlap of the initial environment and the
+   shell variables that are marked for export. */
+char **export_env = (char **)NULL;
+
+/* Non-zero means that we have to remake EXPORT_ENV. */
+int array_needs_making = 1;
+
+/* The list of variables that may not be unset in this shell. */
+char **non_unsettable_vars = (char **)NULL;
+
+static char *have_local_variables;             /* XXX */
+static int local_variable_stack_size = 0;      /* XXX */
+
+/* Some forward declarations. */
+static void initialize_dynamic_variables ();
+static void sbrand ();         /* set bash random number generator. */
+static int qsort_var_comp ();
+
+/* 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)
+
+#if defined (HISTORY)
+#  include "bashhist.h"
+#endif /* HISTORY */
+
+/* Initialize the shell variables from the current environment. */
+void
+initialize_shell_variables (env)
+     char **env;
+{
+  char *name, *string, *current_dir;
+  int c, char_index;
+  int string_index = 0;
+  SHELL_VAR *temp_var;
+
+  if (!shell_variables)
+    shell_variables = make_hash_table (0);
+
+  if (!shell_functions)
+    shell_functions = make_hash_table (0);
+
+  while (string = env[string_index++])
+    {
+      int string_length;
+
+      char_index = 0;
+
+      string_length = strlen (string);
+      name = xmalloc (1 + string_length);
+
+      while ((c = *string++) && c != '=')
+       name[char_index++] = c;
+
+      name[char_index] = '\0';
+
+      /* If exported function, define it now. */
+      if (!privileged_mode && STREQN ("() {", string, 4))
+       {
+         SHELL_VAR *f;
+         char *eval_string;
+
+         eval_string = xmalloc (3 + string_length + strlen (name));
+         sprintf (eval_string, "%s %s", name, string);
+
+         parse_and_execute (eval_string, name, 0);
+
+         if (name[char_index - 1] == ')')
+           name[char_index - 2] = '\0';
+
+         if (f = find_function (name))
+           {
+             f->attributes |= (att_exported | att_imported);
+             array_needs_making = 1;
+           }
+         else
+           report_error ("error importing function definition for `%s'", name);
+       }
+      else
+       {
+         SHELL_VAR *v;
+
+         v = bind_variable (name, string);
+         v->attributes |= (att_exported | att_imported);
+         array_needs_making = 1;
+       }
+      free (name);
+    }
+
+  /* If we got PWD from the environment, update our idea of the current
+     working directory.  In any case, make sure that PWD exists before
+     checking it.  It is possible for getwd () to fail on shell startup,
+     and in that case, PWD would be undefined. */
+  temp_var = find_variable ("PWD");
+  if (temp_var && imported_p (temp_var) &&
+      (current_dir = value_cell (temp_var)) &&
+      same_file (current_dir, ".", (struct stat *)NULL, (struct stat *)NULL))
+    set_working_directory (current_dir);
+  else
+    {
+      current_dir = get_working_directory ("shell-init");
+      if (current_dir)
+        {
+         bind_variable ("PWD", current_dir);
+         free (current_dir);
+        }
+    }
+
+  /* Remember this pid. */
+  dollar_dollar_pid = (int)getpid ();
+
+  /* Now make our own defaults in case the vars that we think are
+     important are missing. */
+  temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
+  set_auto_export (temp_var);
+
+  temp_var = set_if_not ("TERM", "dumb");
+  set_auto_export (temp_var);
+
+  if (interactive_shell)
+    {
+      set_if_not ("PS1", primary_prompt);
+      set_if_not ("PS2", secondary_prompt);
+    }
+  set_if_not ("PS4", "+ ");
+
+#if defined (INSECURITY)
+  set_if_not ("IFS", " \t\n");
+#else
+  bind_variable ("IFS", " \t\n");
+#endif /* INSECURITY */
+
+  /* Magic machine types.  Pretty convenient. */
+  temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
+  set_auto_export (temp_var);
+  temp_var = set_if_not ("OSTYPE", OSTYPE);
+  set_auto_export (temp_var);
+
+  /* Default MAILCHECK for interactive shells. */
+  if (interactive_shell)
+    set_if_not ("MAILCHECK", "60");
+
+  /* Do some things with shell level. */
+  temp_var = set_if_not ("SHLVL", "0");
+  set_auto_export (temp_var);
+  adjust_shell_level (1);
+
+  /* Make a variable $PPID, which holds the pid of the shell's parent.  */
+  {
+    char *ppid;
+    SHELL_VAR *v;
+
+    ppid = itos ((int) getppid ());
+    v = find_variable ("PPID");
+
+    if (v)
+      v->attributes &= ~(att_readonly | att_exported);
+
+    v = bind_variable ("PPID", ppid);
+    v->attributes |= (att_readonly | att_integer);
+
+    non_unsettable ("PPID");
+    free (ppid);
+  }
+
+#if defined (GETOPTS_BUILTIN)
+  /* Initialize the `getopts' stuff. */
+  bind_variable ("OPTIND", "1");
+  bind_variable ("OPTERR", "1");
+#endif /* GETOPTS_BUILTIN */
+
+  /* Get the full pathname to THIS shell, and set the BASH variable
+     to it. */
+  {
+    char *tname;
+
+    if ((login_shell == 1) && (*shell_name != '/'))
+      {
+       /* If HOME doesn't exist, set it. */
+       temp_var = set_if_not ("HOME", current_user.home_dir);
+       temp_var->attributes |= att_exported;
+
+       name = savestring (current_user.shell);
+      }
+    else if (*shell_name == '/')
+      name = savestring (shell_name);
+    else
+      {
+       int s;
+
+       tname = find_user_command (shell_name);
+       if (tname == 0)
+         {
+           /* Try the current directory.  If there is not an executable
+              there, just punt and use the login shell. */
+           s = file_status (shell_name);
+           if (s & FS_EXECABLE)
+             {
+               tname = make_absolute (shell_name, get_string_value ("PWD"));
+               if (*shell_name == '.')
+                 {
+                   name = canonicalize_pathname (tname);
+                   free (tname);
+                 }
+               else
+                 name = tname;
+             }
+           else
+             name = savestring (current_user.shell);
+         }
+       else
+         {
+           name = full_pathname (tname);
+           free (tname);
+         }
+      }
+
+    /* Make the exported environment variable SHELL be the user's login
+       shell.  Note that the `tset' command looks at this variable
+       to determine what style of commands to output; if it ends in "csh",
+       then C-shell commands are output, else Bourne shell commands. */
+    temp_var = set_if_not ("SHELL", current_user.shell);
+    set_auto_export (temp_var);
+
+    /* Make a variable called BASH, which is the name of THIS shell. */
+    temp_var = bind_variable ("BASH", name);
+
+    free (name);
+  }
+
+  /* Make a variable called BASH_VERSION which contains the version info. */
+  bind_variable ("BASH_VERSION", shell_version_string ());
+
+  /* Find out if we're supposed to be in Posix.2 mode via an
+     environment variable. */
+  temp_var = find_variable ("POSIXLY_CORRECT");
+  if (!temp_var)
+    temp_var = find_variable ("POSIX_PEDANTIC");
+  if (temp_var && imported_p (temp_var))
+    sv_strict_posix (temp_var->name);
+
+#if defined (HISTORY)
+  /* Set history variables to defaults, and then do whatever we would
+     do if the variable had just been set.  Do this only in the case
+     that we are remembering commands on the history list. */
+  if (remember_on_history)
+    {
+      if (posixly_correct)
+       name = tilde_expand ("~/.sh_history");
+      else
+       name = tilde_expand ("~/.bash_history");
+
+      set_if_not ("HISTFILE", name);
+      free (name);
+
+      set_if_not ("HISTSIZE", "500");
+      sv_histsize ("HISTSIZE");
+    }
+#endif /* HISTORY */
+
+  /* Seed the random number generator. */
+  sbrand (dollar_dollar_pid);
+
+  /* Handle some "special" variables that we may have inherited from a
+     parent shell. */
+
+  noclobber = find_variable ("noclobber") != (SHELL_VAR *)NULL;
+
+  temp_var = find_variable ("IGNOREEOF");
+  if (!temp_var)
+    temp_var = find_variable ("ignoreeof");
+  if (temp_var && imported_p (temp_var))
+    sv_ignoreeof (temp_var->name);
+
+#if defined (HISTORY)
+  if (interactive_shell && remember_on_history)
+    {
+      sv_command_oriented_history ("command_oriented_history");
+      if (find_variable ("history_control"))
+       sv_history_control ("history_control"); /* gone in next release */
+      else
+       sv_history_control ("HISTCONTROL");
+    }
+#endif /* HISTORY */
+
+  /* Initialize the dynamic variables, and seed their values. */
+  initialize_dynamic_variables ();
+
+  non_unsettable ("PATH");
+  non_unsettable ("IFS");
+
+  if (interactive_shell)
+    {
+      non_unsettable ("PS1");
+      non_unsettable ("PS2");
+    }
+
+  /* Get the users real user id, and save that in a readonly variable.
+     To make the variable *really* readonly, we have added it to a special
+     list of vars. */
+
+  sv_uids ();
+  set_var_read_only ("UID");
+  set_var_read_only ("EUID");
+
+  non_unsettable ("EUID");
+  non_unsettable ("UID");
+}
+
+void
+adjust_shell_level (change)
+     int change;
+{
+  char *new_level, *old_SHLVL;
+  int old_level;
+
+  old_SHLVL = get_string_value ("SHLVL");
+  if (old_SHLVL)
+    old_level = atoi (old_SHLVL);
+  else
+    old_level = 0;
+
+  shell_level = old_level + change;
+  if (shell_level < 0)
+    shell_level = 0;
+  new_level = itos (shell_level);
+  bind_variable ("SHLVL", new_level);
+  free (new_level);
+}
+
+/* Add NAME to the list of variables that cannot be unset
+   if it isn't already there. */
+void
+non_unsettable (name)
+     char *name;
+{
+  register int i;
+
+  if (!non_unsettable_vars)
+    {
+      non_unsettable_vars = (char **)xmalloc (1 * sizeof (char *));
+      non_unsettable_vars[0] = (char *)NULL;
+    }
+
+  for (i = 0; non_unsettable_vars[i]; i++)
+    if (STREQ (non_unsettable_vars[i], name))
+      return;
+
+  non_unsettable_vars = (char **)
+    xrealloc (non_unsettable_vars, (2 + i) * sizeof (char *));
+  non_unsettable_vars[i] = savestring (name);
+  non_unsettable_vars[i + 1] = (char *)NULL;
+}
+
+/* Set NAME to VALUE if NAME has no value. */
+SHELL_VAR *
+set_if_not (name, value)
+     char *name, *value;
+{
+  SHELL_VAR *v = find_variable (name);
+
+  if (!v)
+    v = bind_variable (name, value);
+  return (v);
+}
+
+/* Map FUNCTION over the variables in VARIABLES.  Return an array of the
+   variables that satisfy FUNCTION.  Satisfy means that FUNCTION returns
+   a non-zero value for.  A NULL value for FUNCTION means to use all
+   variables. */
+SHELL_VAR **
+map_over (function, var_hash_table)
+     Function *function;
+     HASH_TABLE* var_hash_table;
+{
+  register int i;
+  register BUCKET_CONTENTS *tlist;
+  SHELL_VAR *var, **list = (SHELL_VAR **)NULL;
+  int list_index = 0, list_size = 0;
+
+  for (i = 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 *), 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 ((Function *)NULL, table);
+  if (list)
+    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));
+}
+
+/* Print VARS to stdout in such a way that they can be read back in. */
+void
+print_var_list (list)
+     register SHELL_VAR **list;
+{
+  register int i;
+  register SHELL_VAR *var;
+
+  for (i = 0; list && (var = list[i]); i++)
+    if (!invisible_p (var))
+      print_assignment (var);
+}
+
+#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. */
+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. */
+void
+print_assignment (var)
+     SHELL_VAR *var;
+{
+  if (function_p (var) && var->value)
+    {
+      printf ("%s=", var->name);
+      print_var_function (var);
+      printf ("\n");
+    }
+  else if (var->value)
+    {
+      printf ("%s=", var->name);
+      print_var_value (var);
+      printf ("\n");
+    }
+}
+
+/* Print the value cell of VAR, a shell variable.  Do not print
+   the name, nor leading/trailing newline. */
+void
+print_var_value (var)
+     SHELL_VAR *var;
+{
+  if (var->value)
+    printf ("%s", var->value);
+}
+
+/* Print the function cell of VAR, a shell variable.  Do not
+   print the name, nor leading/trailing newline. */
+void
+print_var_function (var)
+     SHELL_VAR *var;
+{
+  if (function_p (var) && var->value)
+    printf ("%s", named_function_string ((char *)NULL, function_cell(var), 1));
+}
+
+/* **************************************************************** */
+/*                                                                  */
+/*                 Dynamic Variable Extension                       */
+/*                                                                  */
+/* **************************************************************** */
+
+/* DYNAMIC VARIABLES
+   
+   These are variables whose values are generated anew each time they are
+   referenced.  These are implemented using a pair of function pointers
+   in the struct variable: assign_func, which is called from bind_variable,
+   and 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)
+   and the (SHELL_VAR *)temp is returned as the value of bind_variable.  It
+   is usually ENTRY (self).
+   
+   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);
+   
+   Sometimes `tempvar' will replace the value of `var'.  Other times, the
+   shell will simply use the string value.  Pretty object-oriented, huh?
+   
+   Be warned, though: if you `unset' a special variable, it loses its
+   special meaning, even if you subsequently set it.
+   
+   The special assignment code would probably have been better put in
+   subst.c: do_assignment, in the same style as
+   stupidly_hack_special_variables, but I wanted the changes as
+   localized as possible.  */
+
+/* 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 = (long)0;
+
+static SHELL_VAR *
+assign_seconds (self, value)
+     SHELL_VAR *self;
+     char *value;
+{
+  seconds_value_assigned = atol (value);
+  shell_start_time = NOW;
+  return (self);
+}
+
+static SHELL_VAR *
+get_seconds (var)
+     SHELL_VAR *var;
+{
+  time_t time_since_start;
+  char *p;
+
+  time_since_start = NOW - shell_start_time;
+  p = itos((int) seconds_value_assigned + time_since_start);
+
+  FREE (var->value);
+
+  var->attributes |= att_integer;
+  var->value = p;
+  return (var);
+}
+
+/* The random number seed.  You can change this by setting RANDOM. */
+static unsigned long rseed = 1;
+
+/* A linear congruential random number generator based on the ANSI
+   C standard.  A more complicated one is overkill.  */
+
+/* Returns a pseudo-random number between 0 and 32767. */
+static int
+brand ()
+{
+  rseed = rseed * 1103515245 + 12345;
+  return ((unsigned int)(rseed / 65536) % 32768);
+}
+
+/* Set the random number generator seed to SEED. */
+static void
+sbrand (seed)
+     int seed;
+{
+  rseed = seed;
+}
+
+static SHELL_VAR *
+assign_random (self, value)
+     SHELL_VAR *self;
+     char *value;
+{
+  int s = atoi (value);
+
+  sbrand (s);
+  return (self);
+}
+
+static SHELL_VAR *
+get_random (var)
+     SHELL_VAR *var;
+{
+  int rv;
+  char *p;
+
+  rv = brand ();
+  p = itos ((int)rv);
+
+  FREE (var->value);
+
+  var->attributes |= att_integer;
+  var->value = p;
+  return (var);
+}
+
+/* Function which returns the current line number. */
+static SHELL_VAR *
+get_lineno (var)
+     SHELL_VAR *var;
+{
+  char *p;
+
+  p = itos (line_number);
+  FREE (var->value);
+  var->value = p;
+  return (var);
+}
+
+#if defined (HISTORY)
+static SHELL_VAR *
+get_histcmd (var)
+     SHELL_VAR *var;
+{
+  char *p;
+
+  p = itos (history_number ());
+  FREE (var->value);
+  var->value = p;
+  return (var);
+}
+#endif
+
+static void
+initialize_dynamic_variables ()
+{
+  SHELL_VAR *v;
+
+  v = bind_variable ("SECONDS", (char *)NULL);
+  v->dynamic_value = get_seconds;
+  v->assign_func = assign_seconds;
+
+  v = bind_variable ("RANDOM", (char *)NULL);
+  v->dynamic_value = get_random;
+  v->assign_func = assign_random;
+
+  v = bind_variable ("LINENO", (char *)NULL);
+  v->dynamic_value = get_lineno;
+  v->assign_func = (DYNAMIC_FUNC *)NULL;
+
+#if defined (HISTORY)
+  v = bind_variable ("HISTCMD", (char *)NULL);
+  v->dynamic_value = get_histcmd;
+  v->assign_func = (DYNAMIC_FUNC *)NULL;
+#endif
+}
+
+/* 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)
+     char *name;
+     HASH_TABLE *hashed_vars;
+{
+  BUCKET_CONTENTS *bucket;
+
+  bucket = find_hash_item (name, hashed_vars);
+
+  if (bucket)
+    return ((SHELL_VAR *)bucket->data);
+  else
+    return ((SHELL_VAR *)NULL);
+}
+
+/* Look up the variable entry named NAME.  If SEARCH_TEMPENV is non-zero,
+   then also search the temporarily built list of exported variables. */
+SHELL_VAR *
+find_variable_internal (name, search_tempenv)
+     char *name;
+     int search_tempenv;
+{
+  SHELL_VAR *var = (SHELL_VAR *)NULL;
+
+  /* If explicitly requested, first look in the temporary environment for
+     the variable.  This allows constructs such as "foo=x eval 'echo $foo'"
+     to get the `exported' value of $foo.  This happens if we are executing
+     a function or builtin, or if we are looking up a variable in a
+     "subshell environment". */
+  if ((search_tempenv || subshell_environment) &&
+      (temporary_env || builtin_env || function_env))
+    var = find_tempenv_variable (name);
+
+  if (!var)
+    var = var_lookup (name, shell_variables);
+
+  if (!var)
+    return ((SHELL_VAR *)NULL);
+
+  if (var->dynamic_value)
+    return ((*(var->dynamic_value)) (var));
+  else
+    return (var);
+}
+
+/* Look up the variable entry named NAME.  Returns the entry or NULL. */
+SHELL_VAR *
+find_variable (name)
+     char *name;
+{
+  return (find_variable_internal
+         (name, (variable_context || this_shell_builtin || builtin_env)));
+}
+
+/* Look up the function entry whose name matches STRING.
+   Returns the entry or NULL. */
+SHELL_VAR *
+find_function (name)
+     char *name;
+{
+  return (var_lookup (name, shell_functions));
+}
+
+/* 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. */
+char *
+get_string_value (var_name)
+     char *var_name;
+{
+  SHELL_VAR *var = find_variable (var_name);
+
+  if (!var)
+    return (char *)NULL;
+  else
+    return (var->value);
+}
+
+/* Create a local variable referenced by NAME. */
+SHELL_VAR *
+make_local_variable (name)
+     char *name;
+{
+  SHELL_VAR *new_var, *old_var;
+  BUCKET_CONTENTS *elt;
+
+  /* local foo; local foo;  is a no-op. */
+  old_var = find_variable (name);
+  if (old_var && old_var->context == variable_context)
+    return (old_var);
+
+  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)
+    {
+      new_var = bind_variable (name, "");
+    }
+  else
+    {
+      new_var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
+
+      new_var->name = savestring (name);
+      new_var->value = savestring ("");
+
+      new_var->dynamic_value = (DYNAMIC_FUNC *)NULL;
+      new_var->assign_func = (DYNAMIC_FUNC *)NULL;
+
+      new_var->attributes = 0;
+
+      if (exported_p (old_var))
+       new_var->attributes |= att_exported;
+
+      new_var->prev_context = old_var;
+      elt = add_hash_item (savestring (name), shell_variables);
+      elt->data = (char *)new_var;
+    }
+
+  new_var->context = variable_context;
+
+  /* XXX */
+  if (local_variable_stack_size <= variable_context)
+    {
+      int old_size = local_variable_stack_size;
+      while (local_variable_stack_size <= variable_context)
+        local_variable_stack_size += 8;
+      have_local_variables =
+        xrealloc (have_local_variables, local_variable_stack_size);
+      bzero ((char *)have_local_variables + old_size,
+            local_variable_stack_size - old_size);
+    }
+  have_local_variables[variable_context] = 1;          /* XXX */
+
+  return (new_var);
+}
+
+/* Bind a variable NAME to VALUE.  This conses up the name
+   and value strings. */
+SHELL_VAR *
+bind_variable (name, value)
+     char *name, *value;
+{
+  SHELL_VAR *entry = var_lookup (name, shell_variables);
+  BUCKET_CONTENTS *elt;
+
+  if (!entry)
+    {
+      /* Make a new entry for this variable.  Then do the binding. */
+      entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
+
+      entry->attributes = 0;
+      entry->name = savestring (name);
+
+      if (value)
+       {
+         if (*value)
+           entry->value = savestring (value);
+         else
+           {
+             entry->value = xmalloc (1);
+             entry->value[0] = '\0';
+           }
+       }
+      else
+       entry->value = (char *)NULL;
+
+      entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
+      entry->assign_func = (DYNAMIC_FUNC *)NULL;
+
+      /* 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;
+
+      elt = add_hash_item (savestring (name), shell_variables);
+      elt->data = (char *)entry;
+    }
+  else if (entry->assign_func)
+    return ((*(entry->assign_func)) (entry, value));
+  else
+    {
+      if (readonly_p (entry))
+       {
+         report_error ("%s: read-only variable", name);
+         return (entry);
+       }
+
+      /* Variables which are bound are visible. */
+      entry->attributes &= ~att_invisible;
+
+      /* If this variable has had its type set to integer (via `declare -i'),
+        then do expression evaluation on it and store the result.  The
+        functions in expr.c (evalexp and bind_int_variable) are responsible
+        for turning off the integer flag if they don't want further
+        evaluation done. */
+      if (integer_p (entry))
+       {
+         long val;
+
+         val = evalexp (value);
+         /* We cannot free () entry->value before this; what if the string
+            we are working is `even=even+2'?  We need the original value
+            around while we are doing the evaluation to handle any possible
+            recursion. */
+         FREE (entry->value);
+         entry->value = itos (val);
+       }
+      else
+       {
+         FREE (entry->value);
+
+         if (value)
+           {
+             if (*value)
+               entry->value = savestring (value);
+             else
+               {
+                 entry->value = xmalloc (1);
+                 entry->value[0] = '\0';
+               }
+           }
+         else
+           entry->value = (char *)NULL;
+       }
+    }
+
+  if (mark_modified_vars)
+    entry->attributes |= att_exported;
+
+  if (exported_p (entry))
+    array_needs_making = 1;
+
+  return (entry);
+}
+
+/* Dispose of the information attached to VAR. */
+void
+dispose_variable (var)
+     SHELL_VAR *var;
+{
+  if (!var)
+    return;
+
+  if (function_p (var))
+    dispose_command ((COMMAND *)var->value);
+  else if (var->value)
+    free (var->value);
+
+  free (var->name);
+
+  if (exported_p (var))
+    array_needs_making = 1;
+
+  free (var);
+}
+
+/* Unset the variable referenced by NAME. */
+unbind_variable (name)
+     char *name;
+{
+  SHELL_VAR *var = find_variable (name);
+
+  if (!var)
+    return (-1);
+
+  if (var->value)
+    {
+      free (var->value);
+      var->value = (char *)NULL;
+    }
+
+  makunbound (name, shell_variables);
+
+  return (0);
+}
+
+/* Make the variable associated with NAME go away.  HASH_LIST is the
+   hash table from which this variable should be deleted (either
+   shell_variables or shell_functions).
+   Returns non-zero if the variable couldn't be found. */
+makunbound (name, hash_list)
+     char *name;
+     HASH_TABLE *hash_list;
+{
+  BUCKET_CONTENTS *elt;
+  SHELL_VAR *old_var, *new_var;
+  char *t;
+
+  elt = remove_hash_item (name, hash_list);
+
+  if (!elt)
+    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 (new_var)
+    {
+      /* Has to be a variable, functions don't have previous contexts. */
+      BUCKET_CONTENTS *new_elt;
+
+      new_elt = add_hash_item (savestring (new_var->name), hash_list);
+      new_elt->data = (char *)new_var;
+
+      if (exported_p (new_var))
+       set_var_auto_export (new_var->name);
+    }
+
+  /* Have to save a copy of name here, because it might refer to
+     old_var->name.  If so, stupidly_hack_special_variables will
+     reference freed memory. */
+  t = savestring (name);
+
+  free (elt->key);
+  free (elt);
+
+  dispose_variable (old_var);
+  stupidly_hack_special_variables (t);
+  free (t);
+  return (0);
+}
+
+/* Remove the variable with NAME if it is a local variable in the
+   current context. */
+kill_local_variable (name)
+     char *name;
+{
+  SHELL_VAR *temp = find_variable (name);
+
+  if (temp && (temp->context == variable_context))
+    {
+      makunbound (name, shell_variables);
+      return (0);
+    }
+  return (-1);
+}
+
+/* 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;
+
+  /* XXX */
+  if (!have_local_variables || 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++)
+           makunbound (var->name, varlist);
+
+         free (list);
+       }
+    }
+
+  have_local_variables[variable_context] = 0;          /* XXX */
+}
+
+/* Delete the entire contents of the hash table. */
+void
+delete_all_variables (hashed_vars)
+     HASH_TABLE *hashed_vars;
+{
+  register int i;
+  register BUCKET_CONTENTS *bucket;
+
+  for (i = 0; i < hashed_vars->nbuckets; i++)
+    {
+      bucket = hashed_vars->bucket_array[i];
+
+      while (bucket)
+       {
+         BUCKET_CONTENTS *temp = bucket;
+         SHELL_VAR *var, *prev;
+
+         bucket = bucket->next;
+
+         var = (SHELL_VAR *)temp->data;
+
+         while (var)
+           {
+             prev = var->prev_context;
+             dispose_variable (var);
+
+             var = prev;
+           }
+
+         free (temp->key);
+         free (temp);
+       }
+      hashed_vars->bucket_array[i] = (BUCKET_CONTENTS *)NULL;
+    }
+}
+
+static SHELL_VAR *
+new_shell_variable (name)
+     char *name;
+{
+  SHELL_VAR *var;
+
+  var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
+
+  bzero ((char *)var, sizeof (SHELL_VAR));
+  var->name = savestring (name);
+  return (var);
+}
+
+/* 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)
+     char *name;
+     COMMAND *value;
+{
+  SHELL_VAR *entry = find_function (name);
+
+  if (!entry)
+    {
+      BUCKET_CONTENTS *elt;
+
+      elt = add_hash_item (savestring (name), shell_functions);
+
+      elt->data = (char *)new_shell_variable (name);
+      entry = (SHELL_VAR *)elt->data;
+      entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
+      entry->assign_func = (DYNAMIC_FUNC *)NULL;
+
+      /* Functions are always made at the top level.  This allows a
+        function to define another function (like autoload). */
+      entry->context = 0;
+    }
+
+  if (entry->value)
+    dispose_command ((COMMAND *)entry->value);
+
+  if (value)   /* I don't think this can happen anymore */
+    entry->value = (char *)copy_command (value);
+  else
+    entry->value = (char *)NULL;
+
+  entry->attributes |= att_function;
+
+  if (mark_modified_vars)
+    entry->attributes |= att_exported;
+
+  entry->attributes &= ~att_invisible; /* Just to be sure */
+
+  array_needs_making = 1;
+
+  return (entry);
+}
+
+/* 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 ((COMMAND *)var->value);
+      else if (var->value)
+       copy->value = savestring (var->value);
+      else
+       copy->value = (char *)NULL;
+
+      copy->dynamic_value = var->dynamic_value;
+      copy->assign_func = var->assign_func;
+
+      copy->context = var->context;
+
+      /* Don't bother copying previous contexts along with this variable. */
+      copy->prev_context = (SHELL_VAR *)NULL;
+    }
+  return (copy);
+}
+
+/* Make the variable associated with NAME be read-only.
+   If NAME does not exist yet, create it. */
+void
+set_var_read_only (name)
+     char *name;
+{
+  SHELL_VAR *entry = find_variable (name);
+
+  if (!entry)
+    {
+      entry = bind_variable (name, "");
+      if (!no_invisible_vars)
+       entry->attributes |= att_invisible;
+    }
+  entry->attributes |= att_readonly;
+}
+
+/* Make the function associated with NAME be read-only.
+   If NAME does not exist, we just punt, like auto_export code below. */
+void
+set_func_read_only (name)
+     char *name;
+{
+  SHELL_VAR *entry = find_function (name);
+
+  if (entry)
+    entry->attributes |= att_readonly;
+}
+
+/* Make the variable associated with NAME be auto-exported.
+   If NAME does not exist yet, create it. */
+void
+set_var_auto_export (name)
+     char *name;
+{
+  SHELL_VAR *entry = find_variable (name);
+
+  if (!entry)
+    {
+      entry = bind_variable (name, "");
+      if (!no_invisible_vars)
+       entry->attributes |= att_invisible;
+    }
+
+  set_auto_export (entry);
+}
+
+/* Make the function associated with NAME be auto-exported. */
+void
+set_func_auto_export (name)
+     char *name;
+{
+  SHELL_VAR *entry = find_function (name);
+
+  if (entry)
+    {
+      entry->attributes |= att_exported;
+      array_needs_making = 1;
+    }
+}
+
+/* Returns non-zero if STRING is an assignment statement.  The returned value
+   is the index of the `=' sign. */
+assignment (string)
+     char *string;
+{
+  register int c, indx = 0;
+
+  c = string[indx];
+
+  if (!isletter (c) && c != '_')
+    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 (!isletter (c) && !digit (c) && c != '_')
+       return (0);
+
+      indx++;
+    }
+  return (0);
+}
+
+static int
+visible_var (var)
+     SHELL_VAR *var;
+{
+  return (!invisible_p (var));
+}
+
+SHELL_VAR **
+all_visible_variables ()
+{
+  SHELL_VAR **list;
+
+  list = map_over (visible_var, shell_variables);
+
+  if (list)
+    sort_variables (list);
+
+  return (list);
+}
+
+SHELL_VAR **
+all_visible_functions ()
+{
+  SHELL_VAR **list;
+
+  list = map_over (visible_var, shell_functions);
+
+  if (list)
+    sort_variables (list);
+
+  return (list);
+}
+
+/* Return non-zero if the variable VAR is visible and exported. */
+static int
+visible_and_exported (var)
+     SHELL_VAR *var;
+{
+  return (!invisible_p (var) && exported_p (var));
+}
+
+/* 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;
+{
+  register int i, list_index;
+  register SHELL_VAR *var;
+  char **list = (char **)NULL;
+  SHELL_VAR **vars;
+
+  vars = map_over (visible_and_exported, hashed_vars);
+
+  if (!vars)
+    return (char **)NULL;
+
+  list = (char **)xmalloc ((1 + array_len ((char **)vars)) * sizeof (char *));
+
+  for (i = 0, list_index = 0; var = vars[i]; i++)
+    {
+      char *value;
+
+      if (function_p (var))
+       value = named_function_string
+         ((char *)NULL, (COMMAND *)function_cell (var), 0);
+      else
+       value = value_cell (var);
+
+      if (value)
+       {
+         int name_len = strlen (var->name);
+         int value_len = strlen (value);
+         char  *p;
+
+         p = list[list_index] = xmalloc (2 + name_len + value_len);
+         strcpy (p, var->name);
+         p[name_len] = '=';
+         strcpy (p + name_len + 1, value);
+         list_index++;
+       }
+    }
+
+  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.  */
+assign_in_env (string)
+     char *string;
+{
+  int size;
+
+  int offset = assignment (string);
+  char *name = savestring (string);
+  char *temp, *value = (char *)NULL;
+  int nlen, vlen;
+
+  if (name[offset] == '=')
+    {
+      WORD_LIST *list;
+
+      name[offset] = 0;
+      temp = name + offset + 1;
+      temp = tilde_expand (temp);
+
+      list = expand_string_unsplit (temp, 0);
+      value = string_list (list);
+
+      if (list)
+       dispose_words (list);
+
+      free (temp);
+    }
+
+  if (!value)
+    value = savestring ("");
+
+  nlen = strlen (name);
+  vlen = strlen (value);
+  temp = xmalloc (2 + nlen + vlen);
+  strcpy (temp, name);
+  temp[nlen] = '=';
+  strcpy (temp + nlen + 1, value);
+  free (name);
+  free (value);
+
+  if (!temporary_env)
+    {
+      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 K*rn 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;
+}
+
+/* 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)
+     char *name;
+     char **array;
+{
+  register int i, l = strlen (name);
+
+  if (!array)
+    return ((SHELL_VAR *)NULL);
+
+  for (i = 0; array[i]; i++)
+    {
+      if (STREQN (array[i], name, l) && array[i][l] == '=')
+       {
+         SHELL_VAR *temp;
+
+         temp = new_shell_variable (name);
+
+         if (array[i][l + 1])
+           temp->value = savestring (&array[i][l + 1]);
+         else
+           temp->value = (char *) NULL;
+
+         temp->attributes = att_exported;
+         temp->context = 0;
+         temp->prev_context = (SHELL_VAR *)NULL;
+
+         temp->dynamic_value = (DYNAMIC_FUNC *)NULL;
+         temp->assign_func = (DYNAMIC_FUNC *)NULL;
+
+         return (temp);
+       }
+    }
+  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)
+     char *name;
+{
+  SHELL_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 ()
+{
+  dispose_temporary_vars (&function_env);
+}
+
+/* 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);
+}
+
+/* Sort ARRAY, a null terminated array of pointers to strings. */
+void
+sort_char_array (array)
+     char **array;
+{
+  qsort (array, array_len (array), sizeof (char *),
+        (Function *)qsort_string_compare);
+}
+
+#define ISFUNC(s, o) ((s[o + 1] == '(')  && (s[o + 2] == ')'))
+
+/* Add ASSIGN to ARRAY, or supercede a previous assignment in the
+   array with the same left-hand side.  Return the new array. */
+char **
+add_or_supercede (assign, array)
+     char *assign;
+     register char **array;
+{
+  register int i;
+  int equal_offset = assignment (assign);
+
+  if (!equal_offset)
+    return (array);
+
+  /* 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++;
+
+  for (i = 0; array && array[i]; i++)
+    {
+      if (STREQN (assign, array[i], equal_offset + 1))
+       {
+         free (array[i]);
+         array[i] = savestring (assign);
+         return (array);
+       }
+    }
+  array = (char **)xrealloc (array, ((2 + i) * sizeof (char *)));
+  array[i++] = savestring (assign);
+  array[i] = (char *)NULL;
+  return (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++'. */
+void
+maybe_make_export_env ()
+{
+  register int i;
+  register char **temp_array;
+
+  if (array_needs_making)
+    {
+      if (export_env)
+       free_array (export_env);
+
+#ifdef SHADOWED_ENV
+      export_env =
+       (char **)xmalloc ((1 + array_len (shell_environment)) * sizeof (char *));
+
+      for (i = 0; shell_environment[i]; i++)
+       export_env[i] = savestring (shell_environment[i]);
+      export_env[i] = (char *)NULL;
+
+#else /* !SHADOWED_ENV */
+
+      export_env = (char **)xmalloc (sizeof (char *));
+      export_env[0] = (char *)NULL;
+
+#endif /* SHADOWED_ENV */
+
+      temp_array = make_var_array (shell_variables);
+      for (i = 0; temp_array && temp_array[i]; i++)
+       export_env = add_or_supercede (temp_array[i], export_env);
+      free_array (temp_array);
+
+      temp_array = make_var_array (shell_functions);
+      for (i = 0; temp_array && temp_array[i]; i++)
+       export_env = add_or_supercede (temp_array[i], export_env);
+      free_array (temp_array);
+
+      if (function_env)
+       for (i = 0; function_env[i]; i++)
+         export_env = add_or_supercede (function_env[i], export_env);
+
+      if (temporary_env)
+       for (i = 0; temporary_env[i]; i++)
+         export_env = add_or_supercede (temporary_env[i], export_env);
+
+      /* If we changed the array, then sort it alphabetically. */
+      if (temporary_env || function_env)
+       sort_char_array (export_env);
+
+      array_needs_making = 0;
+    }
+}
+
+/* We always put _ in the environment as the name of this command. */
+void
+put_command_name_into_env (command_name)
+     char *command_name;
+{
+  char *dummy;
+
+  dummy = xmalloc (4 + strlen (command_name));
+
+  /* These three statements replace a call to sprintf */
+  dummy[0] = '_';
+  dummy[1] = '=';
+  strcpy (dummy + 2, command_name);
+  export_env = add_or_supercede (dummy, export_env);
+  free (dummy);
+}
+
+/* We supply our own version of getenv () because we want library
+   routines to get the changed values of exported variables. */
+
+/* The NeXT C library has getenv () defined and used in the same file.
+   This screws our scheme.  However, Bash will run on the NeXT using
+   the C library getenv (), since right now the only environment variable
+   that we care about is HOME, and that is already defined.  */
+#if !defined (NeXT) && !defined (HPOSF1)
+static char *last_tempenv_value = (char *)NULL;
+extern char **environ;
+
+char *
+getenv (name)
+#if defined (Linux) || defined (__bsdi__) || defined (convex)
+     const char *name;
+#else
+     char const *name;
+#endif /* !Linux */
+{
+  SHELL_VAR *var = find_tempenv_variable ((char *)name);
+
+  if (var)
+    {
+      FREE (last_tempenv_value);
+
+      last_tempenv_value = savestring (value_cell (var));
+      dispose_variable (var);
+      return (last_tempenv_value);
+    }
+  else if (shell_variables)
+    {
+      var = find_variable ((char *)name);
+      if (var && exported_p (var))
+       return (value_cell (var));
+    }
+  else
+    {
+      register int i, len = strlen (name);
+
+      /* In some cases, s5r3 invokes getenv() before main(); BSD systems
+         using gprof also exhibit this behavior.  This means that
+         shell_variables will be 0 when this is invoked.  We look up the
+        variable in the real environment in that case. */
+
+      for (i = 0; environ[i]; i++)
+       {
+         if ((STREQN (environ[i], name, len)) && (environ[i][len] == '='))
+           return (environ[i] + len + 1);
+       }
+    }
+
+  return ((char *)NULL);
+}
+#endif /* !NeXT && !HPOSF1 */
diff --git a/variables.h b/variables.h
new file mode 100644 (file)
index 0000000..8f4ef3e
--- /dev/null
@@ -0,0 +1,108 @@
+/* variables.h -- data structures for shell variables. */
+
+#if !defined (_VARIABLES_H_)
+#define _VARIABLES_H_
+
+#include "stdc.h"
+
+/* Shell variables and functions are stored in hash tables. */
+#include "hash.h"
+
+/* What a shell variable looks like. */
+
+typedef struct variable *DYNAMIC_FUNC ();
+
+typedef struct variable {
+  char *name;                  /* Symbol that the user types. */
+  char *value;                 /* Value that is returned. */
+  DYNAMIC_FUNC *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
+                                  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;
+
+/* The various attributes that a given variable can have.
+   We only reserve one byte of the INT. */
+#define att_exported  0x01     /* %00000001 (export to environment) */
+#define att_readonly  0x02     /* %00000010 (cannot change)         */
+#define att_invisible 0x04     /* %00000100 (cannot see)            */
+#define att_array     0x08     /* %00001000 (value is an array)     */
+#define att_nounset   0x10     /* %00010000 (cannot unset)          */
+#define att_function  0x20     /* %00100000 (value is a function)   */
+#define att_integer   0x40     /* %01000000 (internal rep. is int)  */
+#define att_imported  0x80     /* %10000000 (came from environment) */
+
+#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 function_p(var)                ((((var)->attributes) & (att_function)))
+#define integer_p(var)         ((((var)->attributes) & (att_integer)))
+#define imported_p(var)         ((((var)->attributes) & (att_imported)))
+
+#define value_cell(var) ((var)->value)
+#define function_cell(var) (COMMAND *)((var)->value)
+
+/* Stuff for hacking variables. */
+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 **));
+
+extern SHELL_VAR *find_function __P((char *));
+extern SHELL_VAR *find_variable __P((char *));
+extern SHELL_VAR *find_variable_internal __P((char *, int));
+extern SHELL_VAR *find_tempenv_variable __P((char *));
+extern SHELL_VAR *copy_variable __P((SHELL_VAR *));
+extern SHELL_VAR *set_if_not __P((char *, char *));
+extern SHELL_VAR *make_local_variable __P((char *));
+extern SHELL_VAR *bind_variable __P((char *, char *));
+extern SHELL_VAR *bind_function __P((char *, COMMAND *));
+extern SHELL_VAR **map_over __P((Function *, HASH_TABLE *));
+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 char **make_var_array __P((HASH_TABLE *));
+extern char **add_or_supercede __P((char *, char **));
+
+extern char *get_string_value __P((char *));
+
+extern int assignment __P((char *));
+extern int variable_in_context __P((SHELL_VAR *));
+extern int assign_in_env __P((char *));
+extern int unbind_variable __P((char *));
+extern int makunbound __P((char *, HASH_TABLE *));
+extern int kill_local_variable __P((char *));
+extern void delete_all_variables __P((HASH_TABLE *));
+
+extern void adjust_shell_level __P((int));
+extern void non_unsettable __P((char *));
+extern void dispose_variable __P((SHELL_VAR *));
+extern void dispose_function_env __P((void));
+extern void dispose_builtin_env __P((void));
+extern void dispose_used_env_vars __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((char *));
+extern void set_var_auto_export __P((char *));
+extern void set_func_auto_export __P((char *));
+extern void sort_char_array __P((char **));
+extern void sort_variables __P((SHELL_VAR **));
+extern void maybe_make_export_env __P((void));
+extern void put_command_name_into_env __P((char *));
+extern void print_var_list __P((SHELL_VAR **));
+extern void print_assignment __P((SHELL_VAR *));
+extern void print_var_value __P((SHELL_VAR *));
+extern void print_var_function __P((SHELL_VAR *));
+
+#endif /* !_VARIABLES_H_ */
diff --git a/version.c b/version.c
new file mode 100644 (file)
index 0000000..8ba1db7
--- /dev/null
+++ b/version.c
@@ -0,0 +1,26 @@
+/* version.c -- distribution and version numbers. */
+
+/* Copyright (C) 1989 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 1, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "version.h"
+
+char *dist_version = DISTVERSION;
+int patch_level = PATCHLEVEL;
+int build_version = BUILDVERSION;
+char *sccs_version = SCCSVERSION;
diff --git a/vprint.c b/vprint.c
new file mode 100644 (file)
index 0000000..9907936
--- /dev/null
+++ b/vprint.c
@@ -0,0 +1,80 @@
+/* vprint.c -- v[fs]printf() for 4.[23] BSD systems. */
+
+/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#if !defined (NULL)
+#  if defined (__STDC__)
+#    define NULL ((void *)0) 
+#  else
+#    define NULL 0x0
+#  endif /* __STDC__ */
+#endif /* !NULL */
+
+/*
+ * Beware!  Don't trust the value returned by either of these functions; it
+ * seems that pre-4.3-tahoe implementations of _doprnt () return the first
+ * argument, i.e. a char *.
+ */
+#include <varargs.h>
+
+int
+vfprintf (iop, fmt, ap)
+     FILE *iop;
+     char *fmt;
+     va_list ap;
+{
+  int len;
+  char localbuf[BUFSIZ];
+
+  if (iop->_flag & _IONBF)
+    {
+      iop->_flag &= ~_IONBF;
+      iop->_ptr = iop->_base = localbuf;
+      len = _doprnt (fmt, ap, iop);
+      (void) fflush (iop);
+      iop->_flag |= _IONBF;
+      iop->_base = NULL;
+      iop->_bufsiz = 0;
+      iop->_cnt = 0;
+    }
+  else
+    len = _doprnt (fmt, ap, iop);
+  return (ferror (iop) ? EOF : len);
+}
+
+/*
+ * Ditto for vsprintf
+ */
+int
+vsprintf (str, fmt, ap)
+     char *str, *fmt;
+     va_list ap;
+{
+  FILE f;
+  int len;
+
+  f._flag = _IOWRT|_IOSTRG;
+  f._ptr = str;
+  f._cnt = 32767;
+  len = _doprnt (fmt, ap, &f);
+  *f._ptr = 0;
+  return (len);
+}
diff --git a/y.tab.c b/y.tab.c
new file mode 100644 (file)
index 0000000..0b1fd09
--- /dev/null
+++ b/y.tab.c
@@ -0,0 +1,4205 @@
+
+/*  A Bison parser, made from ./parse.y
+ by  GNU Bison version 1.25
+  */
+
+#define YYBISON 1  /* Identify Bison output.  */
+
+#define        IF      258
+#define        THEN    259
+#define        ELSE    260
+#define        ELIF    261
+#define        FI      262
+#define        CASE    263
+#define        ESAC    264
+#define        FOR     265
+#define        SELECT  266
+#define        WHILE   267
+#define        UNTIL   268
+#define        DO      269
+#define        DONE    270
+#define        FUNCTION        271
+#define        IN      272
+#define        BANG    273
+#define        WORD    274
+#define        ASSIGNMENT_WORD 275
+#define        NUMBER  276
+#define        AND_AND 277
+#define        OR_OR   278
+#define        GREATER_GREATER 279
+#define        LESS_LESS       280
+#define        LESS_AND        281
+#define        GREATER_AND     282
+#define        SEMI_SEMI       283
+#define        LESS_LESS_MINUS 284
+#define        AND_GREATER     285
+#define        LESS_GREATER    286
+#define        GREATER_BAR     287
+#define        yacc_EOF        288
+
+#line 21 "./parse.y"
+
+#include <stdio.h>
+#include "bashtypes.h"
+#include <signal.h>
+#include "bashansi.h"
+#include "shell.h"
+#include "flags.h"
+#include "input.h"
+
+#if defined (READLINE)
+#  include <readline/readline.h>
+#endif /* READLINE */
+
+#if defined (HISTORY)
+#  include "bashhist.h"
+#  include <readline/history.h>
+#endif /* HISTORY */
+
+#if defined (JOB_CONTROL)
+#  include "jobs.h"
+#endif /* JOB_CONTROL */
+
+#if defined (ALIAS)
+#  include "alias.h"
+#endif /* ALIAS */
+
+#if defined (PROMPT_STRING_DECODE)
+#include <sys/param.h>
+#include <time.h>
+#include "maxpath.h"
+#endif /* PROMPT_STRING_DECODE */
+
+#define YYDEBUG 1
+extern int eof_encountered;
+extern int no_line_editing;
+extern int current_command_number;
+extern int interactive, interactive_shell, login_shell;
+extern int posixly_correct;
+extern int last_command_exit_value;
+extern int interrupt_immediately;
+extern char *shell_name, *current_host_name;
+extern Function *last_shell_builtin, *this_shell_builtin;
+#if defined (READLINE)
+extern int bash_readline_initialized;
+#endif
+#if defined (BUFFERED_INPUT)
+extern int bash_input_fd_changed;
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*                 "Forward" declarations                          */
+/*                                                                 */
+/* **************************************************************** */
+
+/* This is kind of sickening.  In order to let these variables be seen by
+   all the functions that need them, I am forced to place their declarations
+   far away from the place where they should logically be found. */
+
+static int reserved_word_acceptable ();
+static int read_token ();
+
+static void report_syntax_error ();
+static void handle_eof_input_unit ();
+static void prompt_again ();
+static void reset_readline_prompt ();
+static void print_prompt ();
+
+/* PROMPT_STRING_POINTER points to one of these, never to an actual string. */
+char *ps1_prompt, *ps2_prompt;
+
+/* Handle on the current prompt string.  Indirectly points through
+   ps1_ or ps2_prompt. */
+char **prompt_string_pointer = (char **)NULL;
+char *current_prompt_string;
+
+/* The decoded prompt string.  Used if READLINE is not defined or if
+   editing is turned off.  Analogous to current_readline_prompt. */
+static char *current_decoded_prompt;
+
+/* The number of lines read from input while creating the current command. */
+int current_command_line_count = 0;
+
+/* Variables to manage the task of reading here documents, because we need to
+   defer the reading until after a complete command has been collected. */
+static REDIRECT *redir_stack[10];
+int need_here_doc = 0;
+
+/* Where shell input comes from.  History expansion is performed on each
+   line when the shell is interactive. */
+static char *shell_input_line = (char *)NULL;
+static int shell_input_line_index = 0;
+static int shell_input_line_size = 0;  /* Amount allocated for shell_input_line. */
+static int shell_input_line_len = 0;   /* strlen (shell_input_line) */
+
+/* Either zero or EOF. */
+static int shell_input_line_terminator = 0;
+
+static REDIRECTEE redir;
+
+#line 122 "./parse.y"
+typedef union {
+  WORD_DESC *word;             /* the word that we read. */
+  int number;                  /* the number that we read. */
+  WORD_LIST *word_list;
+  COMMAND *command;
+  REDIRECT *redirect;
+  ELEMENT element;
+  PATTERN_LIST *pattern;
+} YYSTYPE;
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define        YYFINAL         258
+#define        YYFLAG          -32768
+#define        YYNTBASE        45
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 288 ? yytranslate[x] : 73)
+
+static const char yytranslate[] = {     0,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,    35,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,    33,     2,    43,
+    44,     2,     2,     2,    40,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,    34,    39,
+     2,    38,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     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,    37,    42,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     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,     2,     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,    36
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = {     0,
+     0,     3,     5,     8,    10,    11,    14,    17,    20,    24,
+    28,    31,    35,    38,    42,    45,    49,    52,    56,    59,
+    63,    66,    70,    73,    77,    80,    84,    87,    91,    94,
+    98,   101,   104,   108,   110,   112,   114,   116,   119,   121,
+   124,   126,   128,   130,   133,   140,   147,   155,   163,   174,
+   185,   192,   200,   207,   213,   219,   221,   223,   225,   227,
+   229,   236,   243,   251,   259,   270,   281,   287,   294,   301,
+   309,   314,   320,   324,   330,   338,   345,   349,   354,   361,
+   367,   369,   372,   377,   382,   388,   394,   396,   399,   405,
+   411,   418,   425,   427,   431,   434,   436,   440,   444,   448,
+   453,   458,   463,   468,   473,   475,   478,   480,   482,   484,
+   485,   488,   490,   493,   496,   501,   506,   510,   514,   516,
+   519,   524
+};
+
+static const short yyrhs[] = {    70,
+    35,     0,    35,     0,     1,    35,     0,    36,     0,     0,
+    46,    19,     0,    38,    19,     0,    39,    19,     0,    21,
+    38,    19,     0,    21,    39,    19,     0,    24,    19,     0,
+    21,    24,    19,     0,    25,    19,     0,    21,    25,    19,
+     0,    26,    21,     0,    21,    26,    21,     0,    27,    21,
+     0,    21,    27,    21,     0,    26,    19,     0,    21,    26,
+    19,     0,    27,    19,     0,    21,    27,    19,     0,    29,
+    19,     0,    21,    29,    19,     0,    27,    40,     0,    21,
+    27,    40,     0,    26,    40,     0,    21,    26,    40,     0,
+    30,    19,     0,    21,    31,    19,     0,    31,    19,     0,
+    32,    19,     0,    21,    32,    19,     0,    19,     0,    20,
+     0,    47,     0,    47,     0,    49,    47,     0,    48,     0,
+    50,    48,     0,    50,     0,    52,     0,    53,     0,    53,
+    49,     0,    10,    19,    69,    14,    65,    15,     0,    10,
+    19,    69,    41,    65,    42,     0,    10,    19,    34,    69,
+    14,    65,    15,     0,    10,    19,    34,    69,    41,    65,
+    42,     0,    10,    19,    69,    17,    46,    68,    69,    14,
+    65,    15,     0,    10,    19,    69,    17,    46,    68,    69,
+    41,    65,    42,     0,     8,    19,    69,    17,    69,     9,
+     0,     8,    19,    69,    17,    62,    69,     9,     0,     8,
+    19,    69,    17,    60,     9,     0,    12,    65,    14,    65,
+    15,     0,    13,    65,    14,    65,    15,     0,    54,     0,
+    57,     0,    56,     0,    58,     0,    55,     0,    11,    19,
+    69,    14,    65,    15,     0,    11,    19,    69,    41,    65,
+    42,     0,    11,    19,    34,    69,    14,    65,    15,     0,
+    11,    19,    34,    69,    41,    65,    42,     0,    11,    19,
+    69,    17,    46,    68,    69,    14,    65,    15,     0,    11,
+    19,    69,    17,    46,    68,    69,    41,    65,    42,     0,
+    19,    43,    44,    69,    58,     0,    19,    43,    44,    69,
+    58,    49,     0,    16,    19,    43,    44,    69,    58,     0,
+    16,    19,    43,    44,    69,    58,    49,     0,    16,    19,
+    69,    58,     0,    16,    19,    69,    58,    49,     0,    43,
+    65,    44,     0,     3,    65,     4,    65,     7,     0,     3,
+    65,     4,    65,     5,    65,     7,     0,     3,    65,     4,
+    65,    59,     7,     0,    41,    65,    42,     0,     6,    65,
+     4,    65,     0,     6,    65,     4,    65,     5,    65,     0,
+     6,    65,     4,    65,    59,     0,    61,     0,    62,    61,
+     0,    69,    64,    44,    65,     0,    69,    64,    44,    69,
+     0,    69,    43,    64,    44,    65,     0,    69,    43,    64,
+    44,    69,     0,    63,     0,    62,    63,     0,    69,    64,
+    44,    65,    28,     0,    69,    64,    44,    69,    28,     0,
+    69,    43,    64,    44,    65,    28,     0,    69,    43,    64,
+    44,    69,    28,     0,    19,     0,    64,    37,    19,     0,
+    69,    66,     0,    67,     0,    67,    35,    69,     0,    67,
+    33,    69,     0,    67,    34,    69,     0,    67,    22,    69,
+    67,     0,    67,    23,    69,    67,     0,    67,    33,    69,
+    67,     0,    67,    34,    69,    67,     0,    67,    35,    69,
+    67,     0,    72,     0,    18,    72,     0,    35,     0,    34,
+     0,    36,     0,     0,    69,    35,     0,    71,     0,    71,
+    33,     0,    71,    34,     0,    71,    22,    69,    71,     0,
+    71,    23,    69,    71,     0,    71,    33,    71,     0,    71,
+    34,    71,     0,    72,     0,    18,    72,     0,    72,    37,
+    69,    72,     0,    51,     0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+   163,   172,   179,   195,   205,   207,   211,   216,   221,   226,
+   231,   236,   241,   247,   253,   258,   263,   268,   273,   278,
+   283,   288,   293,   300,   307,   312,   317,   322,   327,   332,
+   337,   353,   358,   365,   367,   369,   373,   377,   388,   390,
+   394,   396,   400,   402,   417,   419,   421,   423,   425,   427,
+   430,   432,   434,   436,   438,   440,   442,   444,   446,   448,
+   452,   458,   464,   470,   476,   482,   490,   493,   496,   499,
+   502,   505,   509,   513,   515,   517,   522,   526,   528,   530,
+   534,   535,   539,   541,   543,   545,   549,   550,   554,   556,
+   558,   560,   564,   566,   575,   583,   584,   585,   592,   596,
+   598,   600,   607,   609,   611,   613,   620,   621,   622,   625,
+   626,   635,   641,   650,   658,   660,   662,   669,   671,   673,
+   680,   683
+};
+#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","IN","BANG","WORD","ASSIGNMENT_WORD","NUMBER","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","words","redirection","simple_command_element",
+"redirections","simple_command","command","shell_command","shell_command_1",
+"select_command","function_def","subshell","if_command","group_command","elif_clause",
+"case_clause_1","pattern_list_1","case_clause_sequence","pattern_list","pattern",
+"list","list0","list1","list_terminator","newlines","simple_list","simple_list1",
+"pipeline", NULL
+};
+#endif
+
+static const short yyr1[] = {     0,
+    45,    45,    45,    45,    46,    46,    47,    47,    47,    47,
+    47,    47,    47,    47,    47,    47,    47,    47,    47,    47,
+    47,    47,    47,    47,    47,    47,    47,    47,    47,    47,
+    47,    47,    47,    48,    48,    48,    49,    49,    50,    50,
+    51,    51,    52,    52,    53,    53,    53,    53,    53,    53,
+    53,    53,    53,    53,    53,    53,    53,    53,    53,    53,
+    54,    54,    54,    54,    54,    54,    55,    55,    55,    55,
+    55,    55,    56,    57,    57,    57,    58,    59,    59,    59,
+    60,    60,    61,    61,    61,    61,    62,    62,    63,    63,
+    63,    63,    64,    64,    65,    66,    66,    66,    66,    67,
+    67,    67,    67,    67,    67,    67,    68,    68,    68,    69,
+    69,    70,    70,    70,    71,    71,    71,    71,    71,    71,
+    72,    72
+};
+
+static const short yyr2[] = {     0,
+     2,     1,     2,     1,     0,     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,     1,     2,     6,     6,     7,     7,    10,    10,
+     6,     7,     6,     5,     5,     1,     1,     1,     1,     1,
+     6,     6,     7,     7,    10,    10,     5,     6,     6,     7,
+     4,     5,     3,     5,     7,     6,     3,     4,     6,     5,
+     1,     2,     4,     4,     5,     5,     1,     2,     5,     5,
+     6,     6,     1,     3,     2,     1,     3,     3,     3,     4,
+     4,     4,     4,     4,     1,     2,     1,     1,     1,     0,
+     2,     1,     2,     2,     4,     4,     3,     3,     1,     2,
+     4,     1
+};
+
+static const short yydefact[] = {     0,
+     0,   110,     0,     0,     0,   110,   110,     0,     0,    34,
+    35,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     2,     4,     0,     0,   110,   110,    36,    39,    41,   122,
+    42,    43,    56,    60,    58,    57,    59,     0,   112,   119,
+     3,     0,     0,   110,   110,   110,     0,     0,   110,   120,
+     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,    44,
+     1,   110,   110,   113,   114,   110,   110,     0,   111,    95,
+    96,   105,     0,   110,     0,   110,     0,   110,   110,     0,
+     0,   110,    12,    14,    20,    16,    28,    22,    18,    26,
+    24,    30,    33,     9,    10,    77,    73,    38,     0,     0,
+   117,   118,     0,     0,   106,   110,   110,   110,   110,   110,
+   110,     0,   110,     5,   110,     0,   110,     5,   110,     0,
+     0,   110,    71,     0,   115,   116,     0,     0,   121,   110,
+   110,    74,     0,     0,     0,    98,    99,    97,     0,    81,
+   110,    87,     0,   110,   110,     0,     0,     0,   110,   110,
+     0,     0,     0,    54,    55,     0,    72,    67,     0,     0,
+    76,   100,   101,   102,   103,   104,    53,    82,    88,     0,
+    51,    93,     0,     0,     0,     0,    45,     6,   108,   107,
+   109,   110,    46,     0,     0,    61,   110,    62,    69,    68,
+    75,   110,   110,   110,   110,    52,     0,     0,   110,    47,
+    48,     0,    63,    64,     0,    70,    78,     0,     0,     0,
+   110,    94,    83,    84,   110,   110,   110,   110,   110,    80,
+    85,    86,    89,    90,     0,     0,     0,     0,    79,    91,
+    92,    49,    50,    65,    66,     0,     0,     0
+};
+
+static const short yydefgoto[] = {   256,
+   167,    27,    28,    80,    29,    30,    31,    32,    33,    34,
+    35,    36,    37,   153,   159,   160,   161,   162,   194,    42,
+    90,    91,   202,    43,    38,   121,    92
+};
+
+static const short yypact[] = {   233,
+   -28,-32768,     2,    10,    15,-32768,-32768,    32,   437,    19,
+-32768,   494,    46,    52,    -5,    39,    59,    61,    93,    95,
+-32768,-32768,   102,   103,-32768,-32768,-32768,-32768,   462,-32768,
+-32768,   478,-32768,-32768,-32768,-32768,-32768,    71,   116,    91,
+-32768,   126,   301,-32768,   117,   118,   123,   139,    89,    91,
+   111,   137,   138,    75,    76,   141,   143,   146,   148,   149,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+-32768,-32768,-32768,-32768,   127,   131,-32768,-32768,-32768,   478,
+-32768,-32768,-32768,   369,   369,-32768,-32768,   437,-32768,-32768,
+   101,    91,    37,-32768,    -4,-32768,    22,-32768,-32768,   133,
+   -23,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,   335,   335,
+    60,    60,   403,    98,    91,-32768,-32768,-32768,-32768,-32768,
+-32768,     3,-32768,-32768,-32768,    33,-32768,-32768,-32768,   167,
+   172,-32768,   478,   -23,-32768,-32768,   369,   369,    91,-32768,
+-32768,-32768,   181,   301,   301,   301,   301,   301,   186,-32768,
+-32768,-32768,    21,-32768,-32768,   192,    83,   168,-32768,-32768,
+   194,    83,   175,-32768,-32768,   -23,   478,   478,   208,   214,
+-32768,-32768,-32768,    87,    87,    87,-32768,-32768,-32768,    24,
+-32768,-32768,   200,   -22,   205,   179,-32768,-32768,-32768,-32768,
+-32768,-32768,-32768,   207,   182,-32768,-32768,-32768,   478,   478,
+-32768,-32768,-32768,-32768,-32768,-32768,    29,   204,-32768,-32768,
+-32768,    34,-32768,-32768,    35,   478,   135,   301,   301,   301,
+-32768,-32768,   198,   173,-32768,-32768,-32768,-32768,-32768,-32768,
+   199,   267,-32768,-32768,   213,   193,   222,   196,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,   239,   240,-32768
+};
+
+static const short yypgoto[] = {-32768,
+   104,   -30,   218,  -132,-32768,-32768,-32768,-32768,-32768,-32768,
+-32768,-32768,   -92,    28,-32768,   100,-32768,   105,    55,    -6,
+-32768,  -130,    78,   -41,-32768,     6,    23
+};
+
+
+#define        YYLAST          533
+
+
+static const short yytable[] = {    47,
+    48,    79,    93,    95,    97,    39,    41,   101,   143,   133,
+   177,    89,   134,    63,   218,    64,   164,    25,    75,    76,
+    44,   219,    40,   182,   183,   184,   185,   186,    45,   191,
+    89,    50,   216,    46,    65,   137,   135,    89,   138,   192,
+   119,   120,   192,   165,   123,   210,   169,   235,   237,   118,
+    49,   178,   132,   131,   136,    89,    89,    66,    89,    67,
+   144,    51,   139,   193,    61,   218,   193,    89,    89,    89,
+    62,    89,   231,   170,   236,   238,   226,    69,    68,    70,
+   124,    82,    83,   209,   154,   155,   156,   157,   158,   163,
+   122,   140,   141,   105,   108,   106,   109,   184,   185,   186,
+   176,   198,   150,   151,   152,    81,    40,    40,   126,   127,
+   125,    71,    79,    72,   107,   110,   199,   200,   201,   190,
+    73,    74,   126,   127,   145,   146,   166,    86,   168,    87,
+   171,   100,   173,   128,   129,   130,    98,    82,    83,   239,
+   151,    40,    40,   179,   180,   149,   118,    79,    84,    85,
+    94,    96,    99,   122,   102,   103,   104,   195,   196,   111,
+   222,   112,   204,   205,   113,   225,   114,   115,   116,    40,
+    40,   228,   229,   230,   117,     2,   142,   234,    79,   118,
+     3,   174,     4,     5,     6,     7,   175,   181,     8,   242,
+    88,    10,    11,    12,   187,   118,    13,    14,    15,    16,
+   244,    17,    18,    19,    20,   227,   197,    89,   206,   203,
+    23,    24,   233,    25,   211,    26,   208,   212,   192,   220,
+   221,   223,   232,   224,   241,   243,   250,   252,   245,   246,
+   247,   248,   249,     1,   253,     2,   254,   255,   257,   258,
+     3,   172,     4,     5,     6,     7,    78,   217,     8,   207,
+     9,    10,    11,    12,   240,     0,    13,    14,    15,    16,
+   188,    17,    18,    19,    20,   189,     0,    21,    22,     2,
+    23,    24,     0,    25,     3,    26,     4,     5,     6,     7,
+     0,     0,     8,     0,    88,    10,    11,    12,     0,     0,
+    13,    14,    15,    16,   251,    17,    18,    19,    20,     0,
+     0,    89,     0,     2,    23,    24,     0,    25,     3,    26,
+     4,     5,     6,     7,     0,     0,     8,     0,    88,    10,
+    11,    12,     0,     0,    13,    14,    15,    16,     0,    17,
+    18,    19,    20,     0,     0,    89,     0,     2,    23,    24,
+     0,    25,     3,    26,     4,     5,     6,     7,     0,     0,
+     8,     0,     9,    10,    11,    12,     0,     0,    13,    14,
+    15,    16,     0,    17,    18,    19,    20,     0,     0,    89,
+     0,     2,    23,    24,     0,    25,     3,    26,     4,     5,
+     6,     7,     0,     0,     8,     0,     9,    10,    11,    12,
+     0,     0,    13,    14,    15,    16,     0,    17,    18,    19,
+    20,     0,     0,     0,     0,     2,    23,    24,     0,    25,
+     3,    26,     4,     5,     6,     7,     0,     0,     8,     0,
+     0,    10,    11,    12,     0,     0,    13,    14,    15,    16,
+     0,    17,    18,    19,    20,     0,     0,    89,     0,     2,
+    23,    24,     0,    25,     3,    26,     4,     5,     6,     7,
+     0,     0,     8,     0,     0,    10,    11,    12,     0,     0,
+    13,    14,    15,    16,     0,    17,    18,    19,    20,     0,
+     0,     0,     0,     0,    23,    24,     0,    25,     0,    26,
+    77,    11,    12,     0,     0,    13,    14,    15,    16,     0,
+    17,    18,    19,    20,     0,     0,     0,     0,    12,    23,
+    24,    13,    14,    15,    16,     0,    17,    18,    19,    20,
+     0,     0,     0,     0,     0,    23,    24,    52,    53,    54,
+    55,     0,    56,     0,    57,    58,     0,     0,     0,     0,
+     0,    59,    60
+};
+
+static const short yycheck[] = {     6,
+     7,    32,    44,    45,    46,     0,    35,    49,   101,    14,
+   143,    35,    17,    19,    37,    21,    14,    41,    25,    26,
+    19,    44,     0,   154,   155,   156,   157,   158,    19,     9,
+    35,     9,     9,    19,    40,    14,    41,    35,    17,    19,
+    82,    83,    19,    41,    86,   178,    14,    14,    14,    80,
+    19,   144,    94,    17,    96,    35,    35,    19,    35,    21,
+   102,    43,    41,    43,    19,    37,    43,    35,    35,    35,
+    19,    35,    44,    41,    41,    41,   209,    19,    40,    19,
+    87,    22,    23,   176,   126,   127,   128,   129,   130,   131,
+    85,    98,    99,    19,    19,    21,    21,   228,   229,   230,
+   142,    19,     5,     6,     7,    35,    84,    85,    22,    23,
+    88,    19,   143,    19,    40,    40,    34,    35,    36,   161,
+    19,    19,    22,    23,   119,   120,   133,    37,   135,     4,
+   137,    43,   139,    33,    34,    35,    14,    22,    23,     5,
+     6,   119,   120,   150,   151,   123,   177,   178,    33,    34,
+    34,    34,    14,   148,    44,    19,    19,   164,   165,    19,
+   202,    19,   169,   170,    19,   207,    19,    19,    42,   147,
+   148,   213,   214,   215,    44,     3,    44,   219,   209,   210,
+     8,    15,    10,    11,    12,    13,    15,     7,    16,   231,
+    18,    19,    20,    21,     9,   226,    24,    25,    26,    27,
+    28,    29,    30,    31,    32,   212,    15,    35,    15,    42,
+    38,    39,   219,    41,     7,    43,    42,     4,    19,    15,
+    42,    15,    19,    42,   231,    28,    28,    15,   235,   236,
+   237,   238,   239,     1,    42,     3,    15,    42,     0,     0,
+     8,   138,    10,    11,    12,    13,    29,   193,    16,   172,
+    18,    19,    20,    21,   227,    -1,    24,    25,    26,    27,
+   161,    29,    30,    31,    32,   161,    -1,    35,    36,     3,
+    38,    39,    -1,    41,     8,    43,    10,    11,    12,    13,
+    -1,    -1,    16,    -1,    18,    19,    20,    21,    -1,    -1,
+    24,    25,    26,    27,    28,    29,    30,    31,    32,    -1,
+    -1,    35,    -1,     3,    38,    39,    -1,    41,     8,    43,
+    10,    11,    12,    13,    -1,    -1,    16,    -1,    18,    19,
+    20,    21,    -1,    -1,    24,    25,    26,    27,    -1,    29,
+    30,    31,    32,    -1,    -1,    35,    -1,     3,    38,    39,
+    -1,    41,     8,    43,    10,    11,    12,    13,    -1,    -1,
+    16,    -1,    18,    19,    20,    21,    -1,    -1,    24,    25,
+    26,    27,    -1,    29,    30,    31,    32,    -1,    -1,    35,
+    -1,     3,    38,    39,    -1,    41,     8,    43,    10,    11,
+    12,    13,    -1,    -1,    16,    -1,    18,    19,    20,    21,
+    -1,    -1,    24,    25,    26,    27,    -1,    29,    30,    31,
+    32,    -1,    -1,    -1,    -1,     3,    38,    39,    -1,    41,
+     8,    43,    10,    11,    12,    13,    -1,    -1,    16,    -1,
+    -1,    19,    20,    21,    -1,    -1,    24,    25,    26,    27,
+    -1,    29,    30,    31,    32,    -1,    -1,    35,    -1,     3,
+    38,    39,    -1,    41,     8,    43,    10,    11,    12,    13,
+    -1,    -1,    16,    -1,    -1,    19,    20,    21,    -1,    -1,
+    24,    25,    26,    27,    -1,    29,    30,    31,    32,    -1,
+    -1,    -1,    -1,    -1,    38,    39,    -1,    41,    -1,    43,
+    19,    20,    21,    -1,    -1,    24,    25,    26,    27,    -1,
+    29,    30,    31,    32,    -1,    -1,    -1,    -1,    21,    38,
+    39,    24,    25,    26,    27,    -1,    29,    30,    31,    32,
+    -1,    -1,    -1,    -1,    -1,    38,    39,    24,    25,    26,
+    27,    -1,    29,    -1,    31,    32,    -1,    -1,    -1,    -1,
+    -1,    38,    39
+};
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "/usr/local/lib/bison.simple"
+
+/* Skeleton output parser for bison,
+   Copyright (C) 1984, 1989, 1990 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C.  */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#include <alloca.h>
+#else /* not sparc */
+#if defined (MSDOS) && !defined (__TURBOC__)
+#include <malloc.h>
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+#include <malloc.h>
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#ifdef __cplusplus
+extern "C" {
+void *alloca (unsigned int);
+};
+#else /* not __cplusplus */
+void *alloca ();
+#endif /* not __cplusplus */
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc.  */
+#endif /* not GNU C.  */
+#endif /* alloca not defined.  */
+
+/* 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.  */
+
+/* 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)
+#define YYEMPTY                -2
+#define YYEOF          0
+#define YYACCEPT       return(0)
+#define YYABORT        return(1)
+#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.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+#define YYFAIL         goto yyerrlab
+#define YYRECOVERING()  (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    { yychar = (token), yylval = (value);                      \
+      yychar1 = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK;                                              \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    { 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
+
+/* If nonreentrant, generate the variables here */
+
+#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                              */
+#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      */
+
+#ifndef        YYINITDEPTH
+#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).  */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+int yyparse (void);
+#endif
+\f
+#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
+
+/* 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;
+     int count;
+{
+  register char *f = from;
+  register char *t = to;
+  register int i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* 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, int count)
+{
+  register char *f = from;
+  register char *t = to;
+  register int i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#endif
+#endif
+\f
+#line 196 "/usr/local/lib/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 *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   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 */
+
+int
+yyparse(YYPARSE_PARAM_ARG)
+     YYPARSE_PARAM_DECL
+{
+  register int yystate;
+  register int yyn;
+  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 */
+
+#ifdef YYLSP_NEEDED
+  YYLTYPE yylsa[YYINITDEPTH];  /*  the location stack                  */
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+
+#define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK   (yyvsp--, yyssp--)
+#endif
+
+  int 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                            */
+
+  int yylen;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Starting parse\n");
+#endif
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;            /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss - 1;
+  yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+  yylsp = yyls;
+#endif
+
+/* 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:
+
+  *++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;
+
+#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
+#else /* no yyoverflow */
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+       {
+         yyerror("parser stack overflow");
+         return 2;
+       }
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+       yystacksize = YYMAXDEPTH;
+      yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
+      __yy_memcpy ((char *)yyss, (char *)yyss1, size * sizeof (*yyssp));
+      yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
+      __yy_memcpy ((char *)yyvs, (char *)yyvs1, size * sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+      yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
+      __yy_memcpy ((char *)yyls, (char *)yyls1, size * sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + size - 1;
+      yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+      yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+      if (yydebug)
+       fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+      if (yyssp >= yyss + yystacksize - 1)
+       YYABORT;
+    }
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+  goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+#if YYDEBUG != 0
+      if (yydebug)
+       fprintf(stderr, "Reading a token: ");
+#endif
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with */
+
+  if (yychar <= 0)             /* This means end of input. */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;          /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+      if (yydebug)
+       fprintf(stderr, "Now at end of input.\n");
+#endif
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+      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
+         YYPRINT (stderr, yychar, yylval);
+#endif
+         fprintf (stderr, ")\n");
+       }
+#endif
+    }
+
+  yyn += yychar1;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+
+  /* yyn is what to do for this token type in this state.
+     Negative => reduce, -yyn is rule number.
+     Positive => shift, yyn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+       goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  /* 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:
+
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+
+/* Do a reduction.  yyn is the number of a rule to reduce with.  */
+yyreduce:
+  yylen = yyr2[yyn];
+  if (yylen > 0)
+    yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      int i;
+
+      fprintf (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]]);
+    }
+#endif
+
+
+  switch (yyn) {
+
+case 1:
+#line 164 "./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);
+                         YYACCEPT;
+                       ;
+    break;}
+case 2:
+#line 173 "./parse.y"
+{
+                         /* Case of regular command, but not a very
+                            interesting one.  Return a NULL command. */
+                         global_command = (COMMAND *)NULL;
+                         YYACCEPT;
+                       ;
+    break;}
+case 3:
+#line 181 "./parse.y"
+{
+                         /* Error during parsing.  Return NULL command. */
+                         global_command = (COMMAND *)NULL;
+                         eof_encountered = 0;
+                         discard_parser_constructs (1);
+                         if (interactive)
+                           {
+                             YYACCEPT;
+                           }
+                         else
+                           {
+                             YYABORT;
+                           }
+                       ;
+    break;}
+case 4:
+#line 196 "./parse.y"
+{
+                         /* Case of EOF seen by itself.  Do ignoreeof or 
+                            not. */
+                         global_command = (COMMAND *)NULL;
+                         handle_eof_input_unit ();
+                         YYACCEPT;
+                       ;
+    break;}
+case 5:
+#line 206 "./parse.y"
+{ yyval.word_list = (WORD_LIST *)NULL; ;
+    break;}
+case 6:
+#line 208 "./parse.y"
+{ yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-1].word_list); ;
+    break;}
+case 7:
+#line 212 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (1, r_output_direction, redir);
+                       ;
+    break;}
+case 8:
+#line 217 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (0, r_input_direction, redir);
+                       ;
+    break;}
+case 9:
+#line 222 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (yyvsp[-2].number, r_output_direction, redir);
+                       ;
+    break;}
+case 10:
+#line 227 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (yyvsp[-2].number, r_input_direction, redir);
+                       ;
+    break;}
+case 11:
+#line 232 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (1, r_appending_to, redir);
+                       ;
+    break;}
+case 12:
+#line 237 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (yyvsp[-2].number, r_appending_to, redir);
+                       ;
+    break;}
+case 13:
+#line 242 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (0, r_reading_until, redir);
+                         redir_stack[need_here_doc++] = yyval.redirect;
+                       ;
+    break;}
+case 14:
+#line 248 "./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;}
+case 15:
+#line 254 "./parse.y"
+{
+                         redir.dest = yyvsp[0].number;
+                         yyval.redirect = make_redirection (0, r_duplicating_input, redir);
+                       ;
+    break;}
+case 16:
+#line 259 "./parse.y"
+{
+                         redir.dest = yyvsp[0].number;
+                         yyval.redirect = make_redirection (yyvsp[-2].number, r_duplicating_input, redir);
+                       ;
+    break;}
+case 17:
+#line 264 "./parse.y"
+{
+                         redir.dest = yyvsp[0].number;
+                         yyval.redirect = make_redirection (1, r_duplicating_output, redir);
+                       ;
+    break;}
+case 18:
+#line 269 "./parse.y"
+{
+                         redir.dest = yyvsp[0].number;
+                         yyval.redirect = make_redirection (yyvsp[-2].number, r_duplicating_output, redir);
+                       ;
+    break;}
+case 19:
+#line 274 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (0, r_duplicating_input_word, redir);
+                       ;
+    break;}
+case 20:
+#line 279 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (yyvsp[-2].number, r_duplicating_input_word, redir);
+                       ;
+    break;}
+case 21:
+#line 284 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (1, r_duplicating_output_word, redir);
+                       ;
+    break;}
+case 22:
+#line 289 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (yyvsp[-2].number, r_duplicating_output_word, redir);
+                       ;
+    break;}
+case 23:
+#line 294 "./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 301 "./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 308 "./parse.y"
+{
+                         redir.dest = 0L;
+                         yyval.redirect = make_redirection (1, r_close_this, redir);
+                       ;
+    break;}
+case 26:
+#line 313 "./parse.y"
+{
+                         redir.dest = 0L;
+                         yyval.redirect = make_redirection (yyvsp[-2].number, r_close_this, redir);
+                       ;
+    break;}
+case 27:
+#line 318 "./parse.y"
+{
+                         redir.dest = 0L;
+                         yyval.redirect = make_redirection (0, r_close_this, redir);
+                       ;
+    break;}
+case 28:
+#line 323 "./parse.y"
+{
+                         redir.dest = 0L;
+                         yyval.redirect = make_redirection (yyvsp[-2].number, r_close_this, redir);
+                       ;
+    break;}
+case 29:
+#line 328 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (1, r_err_and_out, redir);
+                       ;
+    break;}
+case 30:
+#line 333 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (yyvsp[-2].number, r_input_output, redir);
+                       ;
+    break;}
+case 31:
+#line 338 "./parse.y"
+{
+                         REDIRECT *t1, *t2;
+
+                         redir.filename = yyvsp[0].word;
+                         if (posixly_correct)
+                           yyval.redirect = make_redirection (0, r_input_output, redir);
+                         else
+                           {
+                             t1 = make_redirection (0, r_input_direction, redir);
+                             redir.filename = copy_word (yyvsp[0].word);
+                             t2 = make_redirection (1, r_output_direction, redir);
+                             t1->next = t2;
+                             yyval.redirect = t1;
+                           }
+                       ;
+    break;}
+case 32:
+#line 354 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (1, r_output_force, redir);
+                       ;
+    break;}
+case 33:
+#line 359 "./parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (yyvsp[-2].number, r_output_force, redir);
+                       ;
+    break;}
+case 34:
+#line 366 "./parse.y"
+{ yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; ;
+    break;}
+case 35:
+#line 368 "./parse.y"
+{ yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; ;
+    break;}
+case 36:
+#line 370 "./parse.y"
+{ yyval.element.redirect = yyvsp[0].redirect; yyval.element.word = 0; ;
+    break;}
+case 37:
+#line 374 "./parse.y"
+{
+                         yyval.redirect = yyvsp[0].redirect;
+                       ;
+    break;}
+case 38:
+#line 378 "./parse.y"
+{ 
+                         register REDIRECT *t = yyvsp[-1].redirect;
+
+                         while (t->next)
+                           t = t->next;
+                         t->next = yyvsp[0].redirect; 
+                         yyval.redirect = yyvsp[-1].redirect;
+                       ;
+    break;}
+case 39:
+#line 389 "./parse.y"
+{ yyval.command = make_simple_command (yyvsp[0].element, (COMMAND *)NULL); ;
+    break;}
+case 40:
+#line 391 "./parse.y"
+{ yyval.command = make_simple_command (yyvsp[0].element, yyvsp[-1].command); ;
+    break;}
+case 41:
+#line 395 "./parse.y"
+{ yyval.command = clean_simple_command (yyvsp[0].command); ;
+    break;}
+case 42:
+#line 397 "./parse.y"
+{ yyval.command = yyvsp[0].command; ;
+    break;}
+case 43:
+#line 401 "./parse.y"
+{ yyval.command = yyvsp[0].command; ;
+    break;}
+case 44:
+#line 403 "./parse.y"
+{
+                         if (yyvsp[-1].command->redirects)
+                           {
+                             register REDIRECT *t;
+                             for (t = yyvsp[-1].command->redirects; t->next; t = t->next)
+                               ;
+                             t->next = yyvsp[0].redirect;
+                           }
+                         else
+                           yyvsp[-1].command->redirects = yyvsp[0].redirect;
+                         yyval.command = yyvsp[-1].command;
+                       ;
+    break;}
+case 45:
+#line 418 "./parse.y"
+{ yyval.command = make_for_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ;
+    break;}
+case 46:
+#line 420 "./parse.y"
+{ yyval.command = make_for_command (yyvsp[-4].word, add_string_to_list ("$@", (WORD_LIST *)NULL), yyvsp[-1].command); ;
+    break;}
+case 47:
+#line 422 "./parse.y"
+{ yyval.command = make_for_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ;
+    break;}
+case 48:
+#line 424 "./parse.y"
+{ yyval.command = make_for_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ;
+    break;}
+case 49:
+#line 426 "./parse.y"
+{ yyval.command = make_for_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command); ;
+    break;}
+case 50:
+#line 428 "./parse.y"
+{ yyval.command = make_for_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command); ;
+    break;}
+case 51:
+#line 431 "./parse.y"
+{ yyval.command = make_case_command (yyvsp[-4].word, (PATTERN_LIST *)NULL); ;
+    break;}
+case 52:
+#line 433 "./parse.y"
+{ yyval.command = make_case_command (yyvsp[-5].word, yyvsp[-2].pattern); ;
+    break;}
+case 53:
+#line 435 "./parse.y"
+{ yyval.command = make_case_command (yyvsp[-4].word, yyvsp[-1].pattern); ;
+    break;}
+case 54:
+#line 437 "./parse.y"
+{ yyval.command = make_while_command (yyvsp[-3].command, yyvsp[-1].command); ;
+    break;}
+case 55:
+#line 439 "./parse.y"
+{ yyval.command = make_until_command (yyvsp[-3].command, yyvsp[-1].command); ;
+    break;}
+case 56:
+#line 441 "./parse.y"
+{ yyval.command = yyvsp[0].command; ;
+    break;}
+case 57:
+#line 443 "./parse.y"
+{ yyval.command = yyvsp[0].command; ;
+    break;}
+case 58:
+#line 445 "./parse.y"
+{ yyval.command = yyvsp[0].command; ;
+    break;}
+case 59:
+#line 447 "./parse.y"
+{ yyval.command = yyvsp[0].command; ;
+    break;}
+case 60:
+#line 449 "./parse.y"
+{ yyval.command = yyvsp[0].command; ;
+    break;}
+case 61:
+#line 453 "./parse.y"
+{
+#if defined (SELECT_COMMAND)
+                         yyval.command = make_select_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command);
+#endif
+                       ;
+    break;}
+case 62:
+#line 459 "./parse.y"
+{
+#if defined (SELECT_COMMAND)
+                         yyval.command = make_select_command (yyvsp[-4].word, add_string_to_list ("$@", (WORD_LIST *)NULL), yyvsp[-1].command);
+#endif
+                       ;
+    break;}
+case 63:
+#line 465 "./parse.y"
+{
+#if defined (SELECT_COMMAND)
+                         yyval.command = make_select_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command);
+#endif
+                       ;
+    break;}
+case 64:
+#line 471 "./parse.y"
+{
+#if defined (SELECT_COMMAND)
+                         yyval.command = make_select_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command);
+#endif
+                       ;
+    break;}
+case 65:
+#line 477 "./parse.y"
+{
+#if defined (SELECT_COMMAND)
+                         yyval.command = make_select_command (yyvsp[-8].word, (WORD_LIST *)reverse_list (yyvsp[-5].word_list), yyvsp[-1].command);
+#endif
+                       ;
+    break;}
+case 66:
+#line 483 "./parse.y"
+{
+#if defined (SELECT_COMMAND)
+                         yyval.command = make_select_command (yyvsp[-8].word, (WORD_LIST *)reverse_list (yyvsp[-5].word_list), yyvsp[-1].command);
+#endif
+                       ;
+    break;}
+case 67:
+#line 491 "./parse.y"
+{ yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command); ;
+    break;}
+case 68:
+#line 494 "./parse.y"
+{ yyvsp[-1].command->redirects = yyvsp[0].redirect; yyval.command = make_function_def (yyvsp[-5].word, yyvsp[-1].command); ;
+    break;}
+case 69:
+#line 497 "./parse.y"
+{ yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command); ;
+    break;}
+case 70:
+#line 500 "./parse.y"
+{ yyvsp[-1].command->redirects = yyvsp[0].redirect; yyval.command = make_function_def (yyvsp[-5].word, yyvsp[-1].command); ;
+    break;}
+case 71:
+#line 503 "./parse.y"
+{ yyval.command = make_function_def (yyvsp[-2].word, yyvsp[0].command); ;
+    break;}
+case 72:
+#line 506 "./parse.y"
+{ yyvsp[-1].command->redirects = yyvsp[0].redirect; yyval.command = make_function_def (yyvsp[-3].word, yyvsp[-1].command); ;
+    break;}
+case 73:
+#line 510 "./parse.y"
+{ yyvsp[-1].command->flags |= CMD_WANT_SUBSHELL; yyval.command = yyvsp[-1].command; ;
+    break;}
+case 74:
+#line 514 "./parse.y"
+{ yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, (COMMAND *)NULL); ;
+    break;}
+case 75:
+#line 516 "./parse.y"
+{ yyval.command = make_if_command (yyvsp[-5].command, yyvsp[-3].command, yyvsp[-1].command); ;
+    break;}
+case 76:
+#line 518 "./parse.y"
+{ yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[-1].command); ;
+    break;}
+case 77:
+#line 523 "./parse.y"
+{ yyval.command = make_group_command (yyvsp[-1].command); ;
+    break;}
+case 78:
+#line 527 "./parse.y"
+{ yyval.command = make_if_command (yyvsp[-2].command, yyvsp[0].command, (COMMAND *)NULL); ;
+    break;}
+case 79:
+#line 529 "./parse.y"
+{ yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[0].command); ;
+    break;}
+case 80:
+#line 531 "./parse.y"
+{ yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, yyvsp[0].command); ;
+    break;}
+case 82:
+#line 536 "./parse.y"
+{ yyvsp[0].pattern->next = yyvsp[-1].pattern; yyval.pattern = yyvsp[0].pattern; ;
+    break;}
+case 83:
+#line 540 "./parse.y"
+{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); ;
+    break;}
+case 84:
+#line 542 "./parse.y"
+{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); ;
+    break;}
+case 85:
+#line 544 "./parse.y"
+{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); ;
+    break;}
+case 86:
+#line 546 "./parse.y"
+{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); ;
+    break;}
+case 88:
+#line 551 "./parse.y"
+{ yyvsp[0].pattern->next = yyvsp[-1].pattern; yyval.pattern = yyvsp[0].pattern; ;
+    break;}
+case 89:
+#line 555 "./parse.y"
+{ yyval.pattern = make_pattern_list (yyvsp[-3].word_list, yyvsp[-1].command); ;
+    break;}
+case 90:
+#line 557 "./parse.y"
+{ yyval.pattern = make_pattern_list (yyvsp[-3].word_list, (COMMAND *)NULL); ;
+    break;}
+case 91:
+#line 559 "./parse.y"
+{ yyval.pattern = make_pattern_list (yyvsp[-3].word_list, yyvsp[-1].command); ;
+    break;}
+case 92:
+#line 561 "./parse.y"
+{ yyval.pattern = make_pattern_list (yyvsp[-3].word_list, (COMMAND *)NULL); ;
+    break;}
+case 93:
+#line 565 "./parse.y"
+{ yyval.word_list = make_word_list (yyvsp[0].word, (WORD_LIST *)NULL); ;
+    break;}
+case 94:
+#line 567 "./parse.y"
+{ yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-2].word_list); ;
+    break;}
+case 95:
+#line 576 "./parse.y"
+{
+                         yyval.command = yyvsp[0].command;
+                         if (need_here_doc)
+                           gather_here_documents ();
+                        ;
+    break;}
+case 98:
+#line 586 "./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 100:
+#line 597 "./parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); ;
+    break;}
+case 101:
+#line 599 "./parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); ;
+    break;}
+case 102:
+#line 601 "./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 103:
+#line 608 "./parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); ;
+    break;}
+case 104:
+#line 610 "./parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); ;
+    break;}
+case 105:
+#line 612 "./parse.y"
+{ yyval.command = yyvsp[0].command; ;
+    break;}
+case 106:
+#line 614 "./parse.y"
+{
+                         yyvsp[0].command->flags |= CMD_INVERT_RETURN;
+                         yyval.command = yyvsp[0].command;
+                       ;
+    break;}
+case 112:
+#line 636 "./parse.y"
+{
+                         yyval.command = yyvsp[0].command;
+                         if (need_here_doc)
+                           gather_here_documents ();
+                       ;
+    break;}
+case 113:
+#line 642 "./parse.y"
+{
+                         if (yyvsp[-1].command->type == cm_connection)
+                           yyval.command = connect_async_list (yyvsp[-1].command, (COMMAND *)NULL, '&');
+                         else
+                           yyval.command = command_connect (yyvsp[-1].command, (COMMAND *)NULL, '&');
+                         if (need_here_doc)
+                           gather_here_documents ();
+                       ;
+    break;}
+case 114:
+#line 651 "./parse.y"
+{
+                         yyval.command = yyvsp[-1].command;
+                         if (need_here_doc)
+                           gather_here_documents ();
+                       ;
+    break;}
+case 115:
+#line 659 "./parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); ;
+    break;}
+case 116:
+#line 661 "./parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); ;
+    break;}
+case 117:
+#line 663 "./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 118:
+#line 670 "./parse.y"
+{ yyval.command = command_connect (yyvsp[-2].command, yyvsp[0].command, ';'); ;
+    break;}
+case 119:
+#line 672 "./parse.y"
+{ yyval.command = yyvsp[0].command; ;
+    break;}
+case 120:
+#line 674 "./parse.y"
+{
+                         yyvsp[0].command->flags |= CMD_INVERT_RETURN;
+                         yyval.command = yyvsp[0].command;
+                       ;
+    break;}
+case 121:
+#line 682 "./parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, '|'); ;
+    break;}
+case 122:
+#line 684 "./parse.y"
+{ yyval.command = yyvsp[0].command; ;
+    break;}
+}
+   /* the action file gets copied in in place of this dollarsign */
+#line 498 "/usr/local/lib/bison.simple"
+\f
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "state stack now");
+      while (ssp1 != yyssp)
+       fprintf (stderr, " %d", *++ssp1);
+      fprintf (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;
+    }
+#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.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+yyerrlab:   /* here on detecting error */
+
+  if (! yyerrstatus)
+    /* If not already recovering from an error, report this error.  */
+    {
+      ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      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)
+           {
+             strcpy(msg, "parse error");
+
+             if (count < 5)
+               {
+                 count = 0;
+                 for (x = (yyn < 0 ? -yyn : 0);
+                      x < (sizeof(yytname) / sizeof(char *)); x++)
+                   if (yycheck[x + yyn] == x)
+                     {
+                       strcat(msg, count == 0 ? ", expecting `" : " or `");
+                       strcat(msg, yytname[x]);
+                       strcat(msg, "'");
+                       count++;
+                     }
+               }
+             yyerror(msg);
+             free(msg);
+           }
+         else
+           yyerror ("parse error; also virtual memory exceeded");
+       }
+      else
+#endif /* YYERROR_VERBOSE */
+       yyerror("parse error");
+    }
+
+  goto yyerrlab1;
+yyerrlab1:   /* here on error raised explicitly by an action */
+
+  if (yyerrstatus == 3)
+    {
+      /* 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
+
+      yychar = YYEMPTY;
+    }
+
+  /* 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. */
+
+#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;
+#endif
+
+yyerrpop:   /* pop the current state because it cannot handle the error token */
+
+  if (yyssp == yyss) YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "Error: state stack now");
+      while (ssp1 != yyssp)
+       fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+yyerrhandle:
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+       goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting error token, ");
+#endif
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+}
+#line 686 "./parse.y"
+
+
+/* Initial size to allocate for tokens, and the
+   amount to grow them by. */
+#define TOKEN_DEFAULT_GROW_SIZE 512
+
+/* The token currently being read. */
+static int current_token = 0;
+
+/* The last read token, or NULL.  read_token () uses this for context
+   checking. */
+static int last_read_token = 0;
+
+/* The token read prior to last_read_token. */
+static int token_before_that = 0;
+
+/* If non-zero, it is the token that we want read_token to return
+   regardless of what text is (or isn't) present to be read.  This
+   is reset by read_token. */
+static int token_to_read = 0;
+
+/* Global var is non-zero when end of file has been reached. */
+int EOF_Reached = 0;
+
+/* yy_getc () returns the next available character from input or EOF.
+   yy_ungetc (c) makes `c' the next character to read.
+   init_yy_io (get, unget, type, location) makes the function GET the
+   installed function for getting the next character, makes UNGET the
+   installed function for un-getting a character, sets the type of stream
+   (either string or file) from TYPE, and makes LOCATION point to where
+   the input is coming from. */
+
+/* Unconditionally returns end-of-file. */
+return_EOF ()
+{
+  return (EOF);
+}
+
+/* Variable containing the current get and unget functions.
+   See ./input.h for a clearer description. */
+BASH_INPUT bash_input;
+
+/* Set all of the fields in BASH_INPUT to NULL. */
+void
+initialize_bash_input ()
+{
+  bash_input.type = 0;
+  bash_input.name = (char *)NULL;
+  bash_input.location.file = (FILE *)NULL;
+  bash_input.location.string = (char *)NULL;
+  bash_input.getter = (Function *)NULL;
+  bash_input.ungetter = (Function *)NULL;
+}
+
+/* Set the contents of the current bash input stream from
+   GET, UNGET, TYPE, NAME, and LOCATION. */
+void
+init_yy_io (get, unget, type, name, location)
+     Function *get, *unget;
+     int type;
+     char *name;
+     INPUT_STREAM location;
+{
+  bash_input.type = type;
+  FREE (bash_input.name);
+
+  if (name)
+    bash_input.name = savestring (name);
+  else
+    bash_input.name = (char *)NULL;
+
+#if defined (CRAY)
+  memcpy((char *)&bash_input.location.string, (char *)&location.string, sizeof(location));
+#else
+  bash_input.location = location;
+#endif
+  bash_input.getter = get;
+  bash_input.ungetter = unget;
+}
+
+/* Call this to get the next character of input. */
+yy_getc ()
+{
+  return (*(bash_input.getter)) ();
+}
+
+/* Call this to unget C.  That is, to make C the next character
+   to be read. */
+yy_ungetc (c)
+     int c;
+{
+  return (*(bash_input.ungetter)) (c);
+}
+
+#if defined (BUFFERED_INPUT)
+int
+input_file_descriptor ()
+{
+  switch (bash_input.type)
+    {
+    case st_stream:
+      return (fileno (bash_input.location.file));
+    case st_bstream:
+      return (bash_input.location.buffered_fd);
+    default:
+      return (fileno (stdin));
+    }
+}
+#endif /* BUFFERED_INPUT */
+
+/* **************************************************************** */
+/*                                                                 */
+/*               Let input be read from readline ().               */
+/*                                                                 */
+/* **************************************************************** */
+
+#if defined (READLINE)
+char *current_readline_prompt = (char *)NULL;
+char *current_readline_line = (char *)NULL;
+int current_readline_line_index = 0;
+
+static int
+yy_readline_get ()
+{
+  if (!current_readline_line)
+    {
+      SigHandler *old_sigint;
+      int line_len;
+
+      if (!bash_readline_initialized)
+       initialize_readline ();
+
+#if defined (JOB_CONTROL)
+      if (job_control)
+       give_terminal_to (shell_pgrp);
+#endif /* JOB_CONTROL */
+
+      if (signal_is_ignored (SIGINT) == 0)
+       {
+         old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
+         interrupt_immediately++;
+       }
+
+      if (!current_readline_prompt)
+       current_readline_line = readline ("");
+      else
+       current_readline_line = readline (current_readline_prompt);
+
+      if (signal_is_ignored (SIGINT) == 0)
+       {
+         interrupt_immediately--;
+         set_signal_handler (SIGINT, old_sigint);
+       }
+
+      /* Reset the prompt to whatever is in the decoded value of
+        prompt_string_pointer. */
+      reset_readline_prompt ();
+
+      current_readline_line_index = 0;
+
+      if (!current_readline_line)
+       return (EOF);
+
+      line_len = strlen (current_readline_line);
+      current_readline_line = xrealloc (current_readline_line, 2 + line_len);
+      current_readline_line[line_len++] = '\n';
+      current_readline_line[line_len] = '\0';
+    }
+
+  if (!current_readline_line[current_readline_line_index])
+    {
+      free (current_readline_line);
+      current_readline_line = (char *)NULL;
+      return (yy_readline_get ());
+    }
+  else
+    {
+      int c = (unsigned char)current_readline_line[current_readline_line_index++];
+      return (c);
+    }
+}
+
+static int
+yy_readline_unget (c)
+{
+  if (current_readline_line_index && current_readline_line)
+    current_readline_line[--current_readline_line_index] = c;
+  return (c);
+}
+
+void  
+with_input_from_stdin ()
+{
+  INPUT_STREAM location;
+
+  if (bash_input.type != st_stdin && stream_on_stack (st_stdin) == 0)
+    {
+      location.string = current_readline_line;
+      init_yy_io (yy_readline_get, yy_readline_unget,
+                 st_stdin, "readline stdin", location);
+    }
+}
+
+#else  /* !READLINE */
+
+void
+with_input_from_stdin ()
+{
+  with_input_from_stream (stdin, "stdin");
+}
+#endif /* !READLINE */
+
+/* **************************************************************** */
+/*                                                                 */
+/*   Let input come from STRING.  STRING is zero terminated.       */
+/*                                                                 */
+/* **************************************************************** */
+
+static int
+yy_string_get ()
+{
+  register unsigned char *string;
+  register int c;
+
+  string = bash_input.location.string;
+  c = EOF;
+
+  /* If the string doesn't exist, or is empty, EOF found. */
+  if (string && *string)
+    {
+      c = *string++;
+      bash_input.location.string = string;
+    }
+  return (c);
+}
+
+static int
+yy_string_unget (c)
+     int c;
+{
+  *(--bash_input.location.string) = c;
+  return (c);
+}
+
+void
+with_input_from_string (string, name)
+     char *string;
+     char *name;
+{
+  INPUT_STREAM location;
+
+  location.string = string;
+
+  init_yy_io (yy_string_get, yy_string_unget, st_string, name, location);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                  Let input come from STREAM.                    */
+/*                                                                 */
+/* **************************************************************** */
+
+static int
+yy_stream_get ()
+{
+  int result = EOF;
+
+  if (bash_input.location.file)
+#if defined (NO_READ_RESTART_ON_SIGNAL)
+    result = (unsigned char)getc_with_restart (bash_input.location.file);
+#else
+    result = (unsigned char)getc (bash_input.location.file);
+#endif /* !NO_READ_RESTART_ON_SIGNAL */
+  return (result);
+}
+
+static int
+yy_stream_unget (c)
+     int c;
+{
+#if defined (NO_READ_RESTART_ON_SIGNAL)
+  return (ungetc_with_restart (c, bash_input.location.file));
+#else
+  return (ungetc (c, bash_input.location.file));
+#endif
+}
+
+void
+with_input_from_stream (stream, name)
+     FILE *stream;
+     char *name;
+{
+  INPUT_STREAM location;
+
+  location.file = stream;
+  init_yy_io (yy_stream_get, yy_stream_unget, st_stream, name, location);
+}
+
+typedef struct stream_saver {
+  struct stream_saver *next;
+  BASH_INPUT bash_input;
+  int line;
+#if defined (BUFFERED_INPUT)
+  BUFFERED_STREAM *bstream;
+#endif /* BUFFERED_INPUT */
+} STREAM_SAVER;
+
+/* The globally known line number. */
+int line_number = 0;
+
+STREAM_SAVER *stream_list = (STREAM_SAVER *)NULL;
+
+push_stream ()
+{
+  STREAM_SAVER *saver = (STREAM_SAVER *)xmalloc (sizeof (STREAM_SAVER));
+
+  xbcopy ((char *)&bash_input, (char *)&(saver->bash_input), sizeof (BASH_INPUT));
+
+#if defined (BUFFERED_INPUT)
+  saver->bstream = (BUFFERED_STREAM *)NULL;
+  /* If we have a buffered stream, clear out buffers[fd]. */
+  if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
+    {
+      saver->bstream = buffers[bash_input.location.buffered_fd];
+      buffers[bash_input.location.buffered_fd] = (BUFFERED_STREAM *)NULL;
+    }
+#endif /* BUFFERED_INPUT */
+
+  saver->line = line_number;
+  bash_input.name = (char *)NULL;
+  saver->next = stream_list;
+  stream_list = saver;
+  EOF_Reached = line_number = 0;
+}
+
+pop_stream ()
+{
+  int temp;
+
+  if (!stream_list)
+    EOF_Reached = 1;
+  else
+    {
+      STREAM_SAVER *saver = stream_list;
+
+      EOF_Reached = 0;
+      stream_list = stream_list->next;
+
+      init_yy_io (saver->bash_input.getter,
+                 saver->bash_input.ungetter,
+                 saver->bash_input.type,
+                 saver->bash_input.name,
+                 saver->bash_input.location);
+
+#if defined (BUFFERED_INPUT)
+      /* If we have a buffered stream, restore buffers[fd]. */
+      /* If the input file descriptor was changed while this was on the
+        save stack, update the buffered fd to the new file descriptor and
+        re-establish the buffer <-> bash_input fd correspondence. */
+      if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
+        {
+          if (bash_input_fd_changed)
+           {
+             bash_input_fd_changed = 0;
+             if (default_buffered_input >= 0)
+               {
+                 bash_input.location.buffered_fd = default_buffered_input;
+                 saver->bstream->b_fd = default_buffered_input;
+               }
+           }
+         buffers[bash_input.location.buffered_fd] = saver->bstream;
+        }
+#endif /* BUFFERED_INPUT */
+
+      line_number = saver->line;
+
+      FREE (saver->bash_input.name);
+      free (saver);
+    }
+}
+
+/* Return 1 if a stream of type TYPE is saved on the stack. */
+int
+stream_on_stack (type)
+     int type;
+{
+  register STREAM_SAVER *s;
+  for (s = stream_list; s; s = s->next)
+    if (s->bash_input.type == type)
+      return 1;
+  return 0;
+}
+
+\f
+/*
+ * This is used to inhibit alias expansion and reserved word recognition
+ * inside case statement pattern lists.  A `case statement pattern list'
+ * is:
+ *     everything between the `in' in a `case word in' and the next ')'
+ *     or `esac'
+ *     everything between a `;;' and the next `)' or `esac'
+ */
+static int in_case_pattern_list = 0;
+
+#if defined (ALIAS)
+/*
+ * Pseudo-global variables used in implementing token-wise alias expansion.
+ */
+
+static int expand_next_token = 0;
+
+/*
+ * Pushing and popping strings.  This works together with shell_getc to 
+ * implement alias expansion on a per-token basis.
+ */
+
+typedef struct string_saver {
+  struct string_saver *next;
+  int expand_alias;  /* Value to set expand_alias to when string is popped. */
+  char *saved_line;
+  int saved_line_size, saved_line_index, saved_line_terminator;
+} STRING_SAVER;
+
+STRING_SAVER *pushed_string_list = (STRING_SAVER *)NULL;
+
+static void save_expansion ();
+
+/*
+ * Push the current shell_input_line onto a stack of such lines and make S
+ * the current input.  Used when expanding aliases.  EXPAND is used to set
+ * the value of expand_next_token when the string is popped, so that the
+ * word after the alias in the original line is handled correctly when the
+ * alias expands to multiple words.  TOKEN is the token that was expanded
+ * into S; it is saved and used to prevent infinite recursive expansion.
+ */
+static void
+push_string (s, expand, token)
+     char *s;
+     int expand;
+     char *token;
+{
+  STRING_SAVER *temp = (STRING_SAVER *) xmalloc (sizeof (STRING_SAVER));
+
+  temp->expand_alias = expand;
+  temp->saved_line = shell_input_line;
+  temp->saved_line_size = shell_input_line_size;
+  temp->saved_line_index = shell_input_line_index;
+  temp->saved_line_terminator = shell_input_line_terminator;
+  temp->next = pushed_string_list;
+  pushed_string_list = temp;
+
+  save_expansion (token);
+
+  shell_input_line = s;
+  shell_input_line_size = strlen (s);
+  shell_input_line_index = 0;
+  shell_input_line_terminator = '\0';
+  expand_next_token = 0;
+}
+
+/*
+ * Make the top of the pushed_string stack be the current shell input.
+ * Only called when there is something on the stack.  Called from shell_getc
+ * when it thinks it has consumed the string generated by an alias expansion
+ * and needs to return to the original input line.
+ */
+static void
+pop_string ()
+{
+  STRING_SAVER *t;
+
+  FREE (shell_input_line);
+  shell_input_line = pushed_string_list->saved_line;
+  shell_input_line_index = pushed_string_list->saved_line_index;
+  shell_input_line_size = pushed_string_list->saved_line_size;
+  shell_input_line_terminator = pushed_string_list->saved_line_terminator;
+  expand_next_token = pushed_string_list->expand_alias;
+
+  t = pushed_string_list;
+  pushed_string_list = pushed_string_list->next;
+  free((char *)t);
+}
+
+static void
+free_string_list ()
+{
+  register STRING_SAVER *t = pushed_string_list, *t1;
+
+  while (t)
+    {
+      t1 = t->next;
+      FREE (t->saved_line);
+      free ((char *)t);
+      t = t1;
+    }
+  pushed_string_list = (STRING_SAVER *)NULL;
+}
+
+/* This is a stack to save the values of all tokens for which alias
+   expansion has been performed during the current call to read_token ().
+   It is used to prevent alias expansion loops:
+
+      alias foo=bar
+      alias bar=baz
+      alias baz=foo
+
+   Ideally this would be taken care of by push and pop string, but because
+   of when strings are popped the stack will not contain the correct
+   strings to test against.  (The popping is done in shell_getc, so that when
+   the current string is exhausted, shell_getc can simply pop that string off
+   the stack, restore the previous string, and continue with the character
+   following the token whose expansion was originally pushed on the stack.)
+
+   What we really want is a record of all tokens that have been expanded for
+   aliases during the `current' call to read_token().  This does that, at the
+   cost of being somewhat special-purpose (OK, OK vile and unclean). */
+
+typedef struct _exp_saver {
+      struct _exp_saver *next;
+      char *saved_token;
+} EXPANSION_SAVER;
+
+EXPANSION_SAVER *expanded_token_stack = (EXPANSION_SAVER *)NULL;
+
+static void
+save_expansion (s)
+     char *s;
+{
+  EXPANSION_SAVER *t;
+
+  t = (EXPANSION_SAVER *) xmalloc (sizeof (EXPANSION_SAVER));
+  t->saved_token = savestring (s);
+  t->next = expanded_token_stack;
+  expanded_token_stack = t;
+}
+
+/* Return 1 if TOKEN has already been expanded in the current `stack' of
+   expansions.  If it has been expanded already, it will appear as the value
+   of saved_token for some entry in the stack of expansions created for the
+   current token being expanded. */
+static int
+token_has_been_expanded (token)
+     char *token;
+{
+  register EXPANSION_SAVER *t = expanded_token_stack;
+
+  while (t)
+    {
+      if (STREQ (token, t->saved_token))
+       return (1);
+      t = t->next;
+    }
+  return (0);
+}
+
+static void
+free_expansion_stack ()
+{
+  register EXPANSION_SAVER *t = expanded_token_stack, *t1;
+
+  while (t)
+    {
+      t1 = t->next;
+      free (t->saved_token);
+      free (t);
+      t = t1;
+    }
+  expanded_token_stack = (EXPANSION_SAVER *)NULL;
+}
+
+#endif /* ALIAS */
+\f
+/* Return a line of text, taken from wherever yylex () reads input.
+   If there is no more input, then we return NULL.  If REMOVE_QUOTED_NEWLINE
+   is non-zero, we remove unquoted \<newline> pairs.  This is used by
+   read_secondary_line to read here documents. */
+static char *
+read_a_line (remove_quoted_newline)
+     int remove_quoted_newline;
+{
+  static char *line_buffer = (char *)NULL;
+  static int buffer_size = 0;
+  int indx = 0, c, peekc, pass_next;
+
+  pass_next = 0;
+  while (1)
+    {
+      c = yy_getc ();
+
+      /* Allow immediate exit if interrupted during input. */
+      QUIT;
+
+      if (c == 0)
+       continue;
+
+      /* If there is no more input, then we return NULL. */
+      if (c == EOF)
+       {
+         if (indx == 0)
+           return ((char *)NULL);
+         c = '\n';
+       }
+
+      /* `+2' in case the final character in the buffer is a newline. */
+      if (indx + 2 > buffer_size)
+       if (!buffer_size)
+         line_buffer = xmalloc (buffer_size = 128);
+       else
+         line_buffer = xrealloc (line_buffer, buffer_size += 128);
+
+      /* IF REMOVE_QUOTED_NEWLINES is non-zero, we are reading a
+        here document with an unquoted delimiter.  In this case,
+        the line will be expanded as if it were in double quotes.
+        We allow a backslash to escape the next character, but we
+        need to treat the backslash specially only if a backslash
+        quoting a backslash-newline pair appears in the line. */
+      if (pass_next)
+        {
+         line_buffer[indx++] = c;
+         pass_next = 0;
+        }
+      else if (c == '\\' && remove_quoted_newline)
+       {
+         peekc = yy_getc ();
+         if (peekc == '\n')
+           continue;   /* Make the unquoted \<newline> pair disappear. */
+         else
+           {
+             yy_ungetc (peekc);
+             pass_next = 1;
+             line_buffer[indx++] = c;          /* Preserve the backslash. */
+           }
+       }
+      else
+       line_buffer[indx++] = c;
+
+      if (c == '\n')
+       {
+         line_buffer[indx] = '\0';
+         return (line_buffer);
+       }
+    }
+}
+
+/* Return a line as in read_a_line (), but insure that the prompt is
+   the secondary prompt.  This is used to read the lines of a here
+   document.  REMOVE_QUOTED_NEWLINE is non-zero if we should remove
+   newlines quoted with backslashes while reading the line.  It is
+   non-zero unless the delimiter of the here document was quoted. */
+char *
+read_secondary_line (remove_quoted_newline)
+     int remove_quoted_newline;
+{
+  prompt_string_pointer = &ps2_prompt;
+  prompt_again ();
+  return (read_a_line (remove_quoted_newline));
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                             YYLEX ()                            */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Reserved words.  These are only recognized as the first word of a
+   command. */
+STRING_INT_ALIST word_token_alist[] = {
+  { "if", IF },
+  { "then", THEN },
+  { "else", ELSE },
+  { "elif", ELIF },
+  { "fi", FI },
+  { "case", CASE },
+  { "esac", ESAC },
+  { "for", FOR },
+#if defined (SELECT_COMMAND)
+  { "select", SELECT },
+#endif
+  { "while", WHILE },
+  { "until", UNTIL },
+  { "do", DO },
+  { "done", DONE },
+  { "in", IN },
+  { "function", FUNCTION },
+  { "{", '{' },
+  { "}", '}' },
+  { "!", BANG },
+  { (char *)NULL, 0}
+};
+
+/* Return the next shell input character.  This always reads characters
+   from shell_input_line; when that line is exhausted, it is time to
+   read the next line.  This is called by read_token when the shell is
+   processing normal command input. */
+static int
+shell_getc (remove_quoted_newline)
+     int remove_quoted_newline;
+{
+  int c;
+
+  QUIT;
+
+#if defined (ALIAS)
+  /* If shell_input_line[shell_input_line_index] == 0, but there is
+     something on the pushed list of strings, then we don't want to go
+     off and get another line.  We let the code down below handle it. */
+
+  if (!shell_input_line || ((!shell_input_line[shell_input_line_index]) &&
+                           (pushed_string_list == (STRING_SAVER *)NULL)))
+#else /* !ALIAS */
+  if (!shell_input_line || !shell_input_line[shell_input_line_index])
+#endif /* !ALIAS */
+    {
+      register int i, l;
+
+      restart_read_next_line:
+
+      line_number++;
+
+    restart_read:
+
+      /* Allow immediate exit if interrupted during input. */
+      QUIT;
+
+      i = 0;
+      shell_input_line_terminator = 0;
+
+#if defined (JOB_CONTROL)
+      /* This can cause a problem when reading a command as the result
+        of a trap, when the trap is called from flush_child.  This call
+        had better not cause jobs to disappear from the job table in
+        that case, or we will have big trouble. */
+      notify_and_cleanup ();
+#else /* !JOB_CONTROL */
+      cleanup_dead_jobs ();
+#endif /* !JOB_CONTROL */
+
+#if defined (READLINE)
+      if (interactive && bash_input.type != st_string && no_line_editing)
+#else
+      if (interactive && bash_input.type != st_string)
+#endif
+       print_prompt ();
+
+      if (bash_input.type == st_stream)
+       clearerr (stdin);
+
+      while (c = yy_getc ())
+       {
+         /* Allow immediate exit if interrupted during input. */
+         QUIT;
+
+         if (i + 2 > shell_input_line_size)
+           shell_input_line =
+             xrealloc (shell_input_line, shell_input_line_size += 256);
+
+         if (c == EOF)
+           {
+             if (bash_input.type == st_stream)
+               clearerr (stdin);
+
+             if (!i)
+               shell_input_line_terminator = EOF;
+
+             shell_input_line[i] = '\0';
+             break;
+           }
+
+         shell_input_line[i++] = c;
+
+         if (c == '\n')
+           {
+             shell_input_line[--i] = '\0';
+             current_command_line_count++;
+             break;
+           }
+       }
+      shell_input_line_index = 0;
+      shell_input_line_len = i;                /* == strlen (shell_input_line) */
+
+#if defined (HISTORY)
+      if (interactive && shell_input_line && shell_input_line[0])
+       {
+         char *expansions;
+
+         expansions = pre_process_line (shell_input_line, 1, 1);
+
+         free (shell_input_line);
+         shell_input_line = expansions;
+         shell_input_line_len = shell_input_line ?
+                                strlen (shell_input_line) :
+                                0;
+         if (!shell_input_line_len)
+           current_command_line_count--;
+
+         /* 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;
+       }
+#endif /* HISTORY */
+
+      if (shell_input_line)
+       {
+         /* Lines that signify the end of the shell's input should not be
+            echoed. */
+         if (echo_input_at_read && (shell_input_line[0] ||
+                                    shell_input_line_terminator != EOF))
+           fprintf (stderr, "%s\n", shell_input_line);
+       }
+      else
+       {
+         shell_input_line_size = 0;
+         prompt_string_pointer = &current_prompt_string;
+         prompt_again ();
+         goto restart_read;
+       }
+
+      /* Add the newline to the end of this string, iff the string does
+        not already end in an EOF character.  */
+      if (shell_input_line_terminator != EOF)
+       {
+         l = shell_input_line_len;     /* was a call to strlen */
+
+         if (l + 3 > shell_input_line_size)
+           shell_input_line = xrealloc (shell_input_line,
+                                       1 + (shell_input_line_size += 2));
+
+         shell_input_line[l] = '\n';
+         shell_input_line[l + 1] = '\0';
+       }
+    }
+  
+  c = shell_input_line[shell_input_line_index];
+
+  if (c)
+    shell_input_line_index++;
+
+  if (c == '\\' && remove_quoted_newline &&
+      shell_input_line[shell_input_line_index] == '\n')
+    {
+       prompt_again ();
+       goto restart_read_next_line;
+    }
+
+#if defined (ALIAS)
+  /* If C is NULL, we have reached the end of the current input string.  If
+     pushed_string_list is non-empty, it's time to pop to the previous string
+     because we have fully consumed the result of the last alias expansion.
+     Do it transparently; just return the next character of the string popped
+     to. */
+  if (!c && (pushed_string_list != (STRING_SAVER *)NULL))
+    {
+      pop_string ();
+      c = shell_input_line[shell_input_line_index];
+      if (c)
+       shell_input_line_index++;
+    }
+#endif /* ALIAS */
+
+  if (!c && shell_input_line_terminator == EOF)
+    {
+      if (shell_input_line_index != 0)
+       return ('\n');
+      else
+       return (EOF);
+    }
+
+  return ((unsigned char)c);
+}
+
+/* Put C back into the input for the shell. */
+static void
+shell_ungetc (c)
+     int c;
+{
+  if (shell_input_line && shell_input_line_index)
+    shell_input_line[--shell_input_line_index] = c;
+}
+
+/* Discard input until CHARACTER is seen. */
+static void
+discard_until (character)
+     int character;
+{
+  int c;
+
+  while ((c = shell_getc (0)) != EOF && c != character)
+    ;
+
+  if (c != EOF)
+    shell_ungetc (c);
+}
+\f
+/* Place to remember the token.  We try to keep the buffer
+   at a reasonable size, but it can grow. */
+static char *token = (char *)NULL;
+
+/* Current size of the token buffer. */
+static int token_buffer_size = 0;
+
+void
+execute_prompt_command (command)
+     char *command;
+{
+  Function *temp_last, *temp_this;
+  char *last_lastarg;
+  int temp_exit_value, temp_eof_encountered;
+
+  temp_last = last_shell_builtin;
+  temp_this = this_shell_builtin;
+  temp_exit_value = last_command_exit_value;
+  temp_eof_encountered = eof_encountered;
+  last_lastarg = get_string_value ("_");
+  if (last_lastarg)
+    last_lastarg = savestring (last_lastarg);
+
+  parse_and_execute (savestring (command), "PROMPT_COMMAND", 0);
+
+  last_shell_builtin = temp_last;
+  this_shell_builtin = temp_this;
+  last_command_exit_value = temp_exit_value;
+  eof_encountered = temp_eof_encountered;
+
+  bind_variable ("_", last_lastarg);
+  FREE (last_lastarg);
+
+  if (token_to_read == '\n')
+    token_to_read = 0;
+}
+
+/* Command to read_token () explaining what we want it to do. */
+#define READ 0
+#define RESET 1
+#define prompt_is_ps1 \
+      (!prompt_string_pointer || prompt_string_pointer == &ps1_prompt)
+
+/* Function for yyparse to call.  yylex keeps track of
+   the last two tokens read, and calls read_token.  */
+
+yylex ()
+{
+  if (interactive && (!current_token || current_token == '\n'))
+    {
+      /* Before we print a prompt, we might have to check mailboxes.
+        We do this only if it is time to do so. Notice that only here
+        is the mail alarm reset; nothing takes place in check_mail ()
+        except the checking of mail.  Please don't change this. */
+      if (prompt_is_ps1 && time_to_check_mail ())
+       {
+         check_mail ();
+         reset_mail_timer ();
+       }
+
+      /* Avoid printing a prompt if we're not going to read anything, e.g.
+        after resetting the parser with read_token (RESET). */
+      if (token_to_read == 0 && interactive)
+       prompt_again ();
+    }
+
+  token_before_that = last_read_token;
+  last_read_token = current_token;
+  current_token = read_token (READ);
+  return (current_token);
+}
+
+/* Called from shell.c when Control-C is typed at top level.  Or
+   by the error rule at top level. */
+reset_parser ()
+{
+  read_token (RESET);
+}
+  
+/* When non-zero, we have read the required tokens
+   which allow ESAC to be the next one read. */
+static int allow_esac_as_next = 0;
+
+/* When non-zero, accept single '{' as a token itself. */
+static int allow_open_brace = 0;
+
+/* DELIMITERS is a stack of the nested delimiters that we have
+   encountered so far. */
+static char *delimiters = (char *)NULL;
+
+/* Offset into the stack of delimiters. */
+int delimiter_depth = 0;
+
+/* How many slots are allocated to DELIMITERS. */
+static int delimiter_space = 0;
+
+void
+gather_here_documents ()
+{
+  int r = 0;
+  while (need_here_doc)
+    {
+      make_here_document (redir_stack[r++]);
+      need_here_doc--;
+    }
+}
+
+/* Macro for accessing the top delimiter on the stack.  Returns the
+   delimiter or zero if none. */
+#define current_delimiter() \
+  (delimiter_depth ? delimiters[delimiter_depth - 1] : 0)
+
+#define push_delimiter(character) \
+  do \
+    { \
+      if (delimiter_depth + 2 > delimiter_space) \
+       delimiters = xrealloc \
+         (delimiters, (delimiter_space += 10) * sizeof (char)); \
+      delimiters[delimiter_depth] = character; \
+      delimiter_depth++; \
+    } \
+  while (0)
+
+/* When non-zero, an open-brace used to create a group is awaiting a close
+   brace partner. */
+static int open_brace_awaiting_satisfaction = 0;
+
+#define command_token_position(token) \
+  (((token) == ASSIGNMENT_WORD) || \
+   ((token) != SEMI_SEMI && reserved_word_acceptable(token)))
+
+#define assignment_acceptable(token) command_token_position(token) && \
+                                       (in_case_pattern_list == 0)
+
+/* Check to see if TOKEN is a reserved word and return the token
+   value if it is. */
+#define CHECK_FOR_RESERVED_WORD(tok) \
+  do { \
+    if (!dollar_present && !quoted && \
+       reserved_word_acceptable (last_read_token)) \
+      { \
+       int i; \
+       for (i = 0; word_token_alist[i].word != (char *)NULL; i++) \
+         if (STREQ (tok, word_token_alist[i].word)) \
+           { \
+             if (in_case_pattern_list && (word_token_alist[i].token != ESAC)) \
+               break; \
+\
+             if (word_token_alist[i].token == ESAC) \
+               in_case_pattern_list = 0; \
+\
+             if (word_token_alist[i].token == '{') \
+               open_brace_awaiting_satisfaction++; \
+\
+             if (word_token_alist[i].token == '}' && open_brace_awaiting_satisfaction) \
+               open_brace_awaiting_satisfaction--; \
+\
+             return (word_token_alist[i].token); \
+           } \
+      } \
+  } while (0)
+
+/* Read the next token.  Command can be READ (normal operation) or 
+   RESET (to normalize state). */
+static int
+read_token (command)
+     int command;
+{
+  int character;               /* Current character. */
+  int peek_char;               /* Temporary look-ahead character. */
+  int result;                  /* The thing to return. */
+  WORD_DESC *the_word;         /* The value for YYLVAL when a WORD is read. */
+
+  if (token_buffer_size < TOKEN_DEFAULT_GROW_SIZE)
+    {
+      FREE (token);
+      token = xmalloc (token_buffer_size = TOKEN_DEFAULT_GROW_SIZE);
+    }
+
+  if (command == RESET)
+    {
+      delimiter_depth = 0;     /* No delimiters found so far. */
+      open_brace_awaiting_satisfaction = 0;
+      in_case_pattern_list = 0;
+
+#if defined (ALIAS)
+      if (pushed_string_list)
+       {
+         free_string_list ();
+         pushed_string_list = (STRING_SAVER *)NULL;
+       }
+
+      if (expanded_token_stack)
+       {
+         free_expansion_stack ();
+         expanded_token_stack = (EXPANSION_SAVER *)NULL;
+       }
+
+      expand_next_token = 0;
+#endif /* ALIAS */
+
+      if (shell_input_line)
+       {
+         free (shell_input_line);
+         shell_input_line = (char *)NULL;
+         shell_input_line_size = shell_input_line_index = 0;
+       }
+      last_read_token = '\n';
+      token_to_read = '\n';
+      return ('\n');
+    }
+
+  if (token_to_read)
+    {
+      int rt = token_to_read;
+      token_to_read = 0;
+      return (rt);
+    }
+
+#if defined (ALIAS)
+  /* If we hit read_token () and there are no saved strings on the
+     pushed_string_list, then we are no longer currently expanding a
+     token.  This can't be done in pop_stream, because pop_stream
+     may pop the stream before the current token has finished being
+     completely expanded (consider what happens when we alias foo to foo,
+     and then try to expand it). */
+  if (!pushed_string_list && expanded_token_stack)
+    {
+      free_expansion_stack ();
+      expanded_token_stack = (EXPANSION_SAVER *)NULL;
+    }
+
+  /* This is a place to jump back to once we have successfully expanded a
+     token with an alias and pushed the string with push_string () */
+ re_read_token:
+
+#endif /* ALIAS */
+
+  /* Read a single word from input.  Start by skipping blanks. */
+  while ((character = shell_getc (1)) != EOF && whitespace (character));
+
+  if (character == EOF)
+    {
+      EOF_Reached = 1;
+      return (yacc_EOF);
+    }
+
+  if (character == '#' && (!interactive || interactive_comments))
+    {
+      /* A comment.  Discard until EOL or EOF, and then return a newline. */
+      discard_until ('\n');
+      shell_getc (0);
+
+      /* If we're about to return an unquoted newline, we can go and collect
+        the text of any pending here documents. */
+      if (need_here_doc)
+        gather_here_documents ();
+
+#if defined (ALIAS)
+      expand_next_token = 0;
+#endif /* ALIAS */
+
+      return ('\n');
+    }
+
+  if (character == '\n')
+    {
+      /* If we're about to return an unquoted newline, we can go and collect
+        the text of any pending here document. */
+      if (need_here_doc)
+       gather_here_documents ();
+
+#if defined (ALIAS)
+      expand_next_token = 0;
+#endif /* ALIAS */
+
+      return (character);
+    }
+
+  if (member (character, "()<>;&|"))
+    {
+#if defined (ALIAS)
+      /* Turn off alias tokenization iff this character sequence would
+        not leave us ready to read a command. */
+      if (character == '<' || character == '>')
+       expand_next_token = 0;
+#endif /* ALIAS */
+
+      /* Please note that the shell does not allow whitespace to
+        appear in between tokens which are character pairs, such as
+        "<<" or ">>".  I believe this is the correct behaviour. */
+      if (character == (peek_char = shell_getc (1)))
+       {
+         switch (character)
+           {
+             /* If '<' then we could be at "<<" or at "<<-".  We have to
+                look ahead one more character. */
+           case '<':
+             peek_char = shell_getc (1);
+             if (peek_char == '-')
+               return (LESS_LESS_MINUS);
+             else
+               {
+                 shell_ungetc (peek_char);
+                 return (LESS_LESS);
+               }
+
+           case '>':
+             return (GREATER_GREATER);
+
+           case ';':
+             in_case_pattern_list = 1;
+#if defined (ALIAS)
+             expand_next_token = 0;
+#endif /* ALIAS */
+             return (SEMI_SEMI);
+
+           case '&':
+             return (AND_AND);
+
+           case '|':
+             return (OR_OR);
+           }
+       }
+      else
+       {
+         if (peek_char == '&')
+           {
+             switch (character)
+               {
+               case '<': return (LESS_AND);
+               case '>': return (GREATER_AND);
+               }
+           }
+         if (character == '<' && peek_char == '>')
+           return (LESS_GREATER);
+         if (character == '>' && peek_char == '|')
+           return (GREATER_BAR);
+         if (peek_char == '>' && character == '&')
+           return (AND_GREATER);
+       }
+      shell_ungetc (peek_char);
+
+      /* 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)
+       {
+         allow_open_brace = 1;
+#if defined (ALIAS)
+         expand_next_token = 0;
+#endif /* ALIAS */
+       }
+
+      if (in_case_pattern_list && (character == ')'))
+       in_case_pattern_list = 0;
+
+#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 == '(') == 0))
+#endif /* PROCESS_SUBSTITUTION */
+       return (character);
+    }
+
+  /* Hack <&- (close stdin) case. */
+  if (character == '-')
+    {
+      switch (last_read_token)
+       {
+       case LESS_AND:
+       case GREATER_AND:
+         return (character);
+       }
+    }
+  
+  /* Okay, if we got this far, we have to read a word.  Read one,
+     and then check it against the known ones. */
+  {
+    /* Index into the token that we are building. */
+    int token_index = 0;
+
+    /* ALL_DIGITS becomes zero when we see a non-digit. */
+    int all_digits = digit (character);
+
+    /* DOLLAR_PRESENT becomes non-zero if we see a `$'. */
+    int dollar_present = 0;
+
+    /* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */
+    int quoted = 0;
+
+    /* Non-zero means to ignore the value of the next character, and just
+       to add it no matter what. */
+    int pass_next_character = 0;
+
+    /* Non-zero means parsing a dollar-paren construct.  It is the count of
+       un-quoted closes we need to see. */
+    int dollar_paren_level = 0;
+
+    /* Non-zero means parsing a dollar-bracket construct ($[...]).  It is
+       the count of un-quoted `]' characters we need to see. */
+    int dollar_bracket_level = 0;
+
+    /* Non-zero means parsing a `${' construct.  It is the count of
+       un-quoted `}' we need to see. */
+    int dollar_brace_level = 0;
+
+    /* A level variable for parsing '${ ... }' constructs inside of double
+       quotes. */
+    int delimited_brace_level = 0;
+
+    /* A boolean variable denoting whether or not we are currently parsing
+       a double-quoted string embedded in a $( ) or ${ } construct. */
+    int embedded_quoted_string = 0;
+
+    /* Another level variable.  This one is for dollar_parens inside of
+       double-quotes. */
+    int delimited_paren_level = 0;
+
+    /* The current delimiting character. */
+    int cd;
+
+    for (;;)
+      {
+       if (character == EOF)
+         goto got_token;
+
+       if (pass_next_character)
+         {
+           pass_next_character = 0;
+           goto got_character;
+         }
+
+       cd = current_delimiter ();
+
+       if (cd && character == '\\' && cd != '\'')
+         {
+           peek_char = shell_getc (0);
+           if (peek_char != '\\')
+             shell_ungetc (peek_char);
+           else
+             {
+               token[token_index++] = character;
+               goto got_character;
+             }
+         }
+
+       /* Handle backslashes.  Quote lots of things when not inside of
+          double-quotes, quote some things inside of double-quotes. */
+          
+       if (character == '\\' && (!delimiter_depth || cd != '\''))
+         {
+           peek_char = shell_getc (0);
+
+           /* Backslash-newline is ignored in all cases excepting
+              when quoted with single quotes. */
+           if (peek_char == '\n')
+             {
+               character = '\n';
+               goto next_character;
+             }
+           else
+             {
+               shell_ungetc (peek_char);
+
+               /* If the next character is to be quoted, do it now. */
+               if (!cd || cd == '`' ||
+                   (cd == '"' && member (peek_char, slashify_in_quotes)))
+                 {
+                   pass_next_character++;
+                   quoted = 1;
+                   goto got_character;
+                 }
+             }
+         }
+
+       /* This is a hack, in its present form.  If a backquote substitution
+          appears within double quotes, everything within the backquotes
+          should be read as part of a single word.  Jesus.  Now I see why
+          Korn introduced the $() form. */
+       if (delimiter_depth && (cd == '"') && (character == '`'))
+         {
+           push_delimiter (character);
+           goto got_character;
+         }
+
+       cd = current_delimiter ();              /* XXX - may not need */
+       if (delimiter_depth)
+         {
+           if (character == cd)
+             {
+               /* If we see a double quote while parsing a double-quoted
+                 $( ) or ${ }, and we have not seen ) or }, respectively,
+                  note that we are in the middle of reading an embedded
+                  quoted string. */
+               if ((delimited_paren_level || delimited_brace_level) &&
+                   (character == '"'))
+                 {
+                   embedded_quoted_string = !embedded_quoted_string;
+                   goto got_character;
+                 }
+               
+               delimiter_depth--;
+               goto got_character;
+             }
+         }
+
+       if (cd != '\'')
+         {
+#if defined (PROCESS_SUBSTITUTION)
+           if (character == '$' || character == '<' || character == '>')
+#else
+           if (character == '$')
+#endif /* !PROCESS_SUBSTITUTION */
+             {
+               /* If we're in the middle of parsing a $( ) or ${ }
+                  construct with an embedded quoted string, don't
+                  bother looking at this character any further. */
+               if (embedded_quoted_string)
+                 goto got_character;
+
+               peek_char = shell_getc (1);
+               shell_ungetc (peek_char);
+               if (peek_char == '(')
+                 {
+                   if (!delimiter_depth)
+                     dollar_paren_level++;
+                   else
+                     delimited_paren_level++;
+
+                   pass_next_character++;
+                   goto got_character;
+                 }
+               else if (peek_char == '[' && character == '$')
+                 {
+                   if (!delimiter_depth)
+                     dollar_bracket_level++;
+
+                   pass_next_character++;
+                   goto got_character;
+                 }
+               /* This handles ${...} constructs. */
+               else if (peek_char == '{' && character == '$')
+                 {
+                   if (!delimiter_depth)
+                     dollar_brace_level++;
+                   else
+                     delimited_brace_level++;
+
+                   pass_next_character++;
+                   goto got_character;
+                 }
+             }
+
+           /* If we are parsing a $() or $[] construct, we need to balance
+              parens and brackets inside the construct.  This whole function
+              could use a rewrite. */
+           if (character == '(' && !embedded_quoted_string)
+             {
+               if (delimiter_depth && delimited_paren_level)
+                 delimited_paren_level++;
+
+               if (!delimiter_depth && dollar_paren_level)
+                 dollar_paren_level++;
+             }
+
+           if (character == '[')
+             {
+               if (!delimiter_depth && dollar_bracket_level)
+                 dollar_bracket_level++;
+             }
+
+           if (character == '{' && !embedded_quoted_string)
+             {
+               if (delimiter_depth && delimited_brace_level)
+                 delimited_brace_level++;
+
+               if (!delimiter_depth && dollar_brace_level)
+                 dollar_brace_level++;
+             }
+
+           /* This code needs to take into account whether we are inside a
+              case statement pattern list, and whether this paren is supposed
+              to terminate it (hey, it could happen).  It's not as simple
+              as just using in_case_pattern_list, because we're not parsing
+              anything while we're reading a $( ) construct.  Maybe we
+              should move that whole mess into the yacc parser. */
+           if (character == ')' && !embedded_quoted_string)
+             {
+               if (delimiter_depth && delimited_paren_level)
+                 delimited_paren_level--;
+
+               if (!delimiter_depth && dollar_paren_level)
+                 {
+                   dollar_paren_level--;
+                   goto got_character;
+                 }
+             }
+
+           if (character == ']')
+             {
+               if (!delimiter_depth && dollar_bracket_level)
+                 {
+                   dollar_bracket_level--;
+                   goto got_character;
+                 }
+             }
+
+           if (character == '}' && !embedded_quoted_string)
+             {
+               if (delimiter_depth && delimited_brace_level)
+                 delimited_brace_level--;
+
+               if (!delimiter_depth && dollar_brace_level)
+                 {
+                   dollar_brace_level--;
+                   goto got_character;
+                 }
+             }
+         }
+
+       if (!dollar_paren_level && !dollar_bracket_level &&
+           !dollar_brace_level && !delimiter_depth &&
+           member (character, " \t\n;&()|<>"))
+         {
+           shell_ungetc (character);
+           goto got_token;
+         }
+    
+       if (!delimiter_depth)
+         {
+           if (character == '"' || character == '`' || character == '\'')
+             {
+               push_delimiter (character);
+
+               quoted = 1;
+               goto got_character;
+             }
+         }
+
+       if (all_digits)
+         all_digits = digit (character);
+       if (character == '$')
+         dollar_present = 1;
+
+      got_character:
+
+       if (character == CTLESC || character == CTLNUL)
+         token[token_index++] = CTLESC;
+
+       token[token_index++] = character;
+
+       if (token_index == (token_buffer_size - 1))
+         {
+           token_buffer_size += TOKEN_DEFAULT_GROW_SIZE;
+           token = xrealloc (token, token_buffer_size);
+         }
+       next_character:
+       if (character == '\n' && interactive && bash_input.type != st_string)
+         prompt_again ();
+
+       /* We want to remove quoted newlines (that is, a \<newline> pair)
+          unless we are within single quotes or pass_next_character is
+          set (the shell equivalent of literal-next). */
+       character = shell_getc
+         ((current_delimiter () != '\'') && (!pass_next_character));
+      }
+
+  got_token:
+
+    token[token_index] = '\0';
+       
+    if ((delimiter_depth || dollar_paren_level || dollar_bracket_level) &&
+       character == EOF)
+      {
+       char reporter = '\0';
+
+       if (!delimiter_depth)
+         {
+           if (dollar_paren_level)
+             reporter = ')';
+           else if (dollar_bracket_level)
+             reporter = ']';
+         }
+
+       if (!reporter)
+         reporter = current_delimiter ();
+
+       report_error ("unexpected EOF while looking for `%c'", reporter);
+       return (-1);
+      }
+
+    if (all_digits)
+      {
+       /* Check to see what thing we should return.  If the last_read_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 (character == '<' || character == '>' ||
+           last_read_token == LESS_AND || last_read_token == GREATER_AND)
+         {
+           yylval.number = atoi (token);
+           return (NUMBER);
+         }
+      }
+
+    /* Handle special case.  IN is recognized if the last token
+       was WORD and the token before that was FOR or CASE. */
+    if ((last_read_token == WORD) &&
+#if defined (SELECT_COMMAND)
+       ((token_before_that == FOR) || (token_before_that == CASE) || (token_before_that == SELECT)) &&
+#else
+       ((token_before_that == FOR) || (token_before_that == CASE)) &&
+#endif
+       (token[0] == 'i' && token[1] == 'n' && !token[2]))
+      {
+       if (token_before_that == CASE)
+         {
+           in_case_pattern_list = 1;
+           allow_esac_as_next++;
+         }
+       return (IN);
+      }
+
+    /* Ditto for DO in the FOR case. */
+#if defined (SELECT_COMMAND)
+    if ((last_read_token == WORD) && ((token_before_that == FOR) || (token_before_that == SELECT)) &&
+#else
+    if ((last_read_token == WORD) && (token_before_that == FOR) &&
+#endif
+       (token[0] == 'd' && token[1] == 'o' && !token[2]))
+      return (DO);
+
+    /* Ditto for ESAC in the CASE case. 
+       Specifically, this handles "case word in esac", which is a legal
+       construct, certainly because someone will pass an empty arg to the
+       case construct, and we don't want it to barf.  Of course, we should
+       insist that the case construct has at least one pattern in it, but
+       the designers disagree. */
+    if (allow_esac_as_next)
+      {
+       allow_esac_as_next--;
+       if (STREQ (token, "esac"))
+         {
+           in_case_pattern_list = 0;
+           return (ESAC);
+         }
+      }
+
+    /* Ditto for `{' in the FUNCTION case. */
+    if (allow_open_brace)
+      {
+       allow_open_brace = 0;
+       if (token[0] == '{' && !token[1])
+         {
+           open_brace_awaiting_satisfaction++;
+           return ('{');
+         }
+      }
+
+    if (posixly_correct)
+      CHECK_FOR_RESERVED_WORD (token);
+
+#if defined (ALIAS)
+    /* 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
+       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
+       token is not the same as the current or any previously
+       processed alias.
+
+       Special cases that disqualify:
+        In a pattern list in a case statement (in_case_pattern_list). */
+    if (interactive_shell && !quoted && !in_case_pattern_list &&
+       (expand_next_token || command_token_position (last_read_token)))
+      {
+       char *alias_expand_word (), *expanded;
+
+       if (expanded_token_stack && token_has_been_expanded (token))
+         goto no_expansion;
+
+       expanded = alias_expand_word (token);
+       if (expanded)
+         {
+           int len = strlen (expanded), expand_next;
+
+           /* Erase the current token. */
+           token_index = 0;
+
+           expand_next = (expanded[len - 1] == ' ') ||
+                         (expanded[len - 1] == '\t');
+
+           push_string (expanded, expand_next, token);
+           goto re_read_token;
+         }
+       else
+         /* This is an eligible token that does not have an expansion. */
+no_expansion:
+         expand_next_token = 0;
+      }
+    else
+      {
+       expand_next_token = 0;
+      }
+#endif /* ALIAS */
+
+    if (!posixly_correct)
+      CHECK_FOR_RESERVED_WORD (token);
+
+    /* What if we are attempting to satisfy an open-brace grouper? */
+    if (open_brace_awaiting_satisfaction && token[0] == '}' && !token[1])
+      {
+       open_brace_awaiting_satisfaction--;
+       return ('}');
+      }
+
+    the_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
+    the_word->word = xmalloc (1 + token_index);
+    strcpy (the_word->word, token);
+    the_word->dollar_present = dollar_present;
+    the_word->quoted = quoted;
+    the_word->assignment = assignment (token);
+
+    yylval.word = the_word;
+    result = WORD;
+
+    /* A word is an assignment if it appears at the beginning of a
+       simple command, or after another assignment word.  This is
+       context-dependent, so it cannot be handled in the grammar. */
+    if (assignment_acceptable (last_read_token) && the_word->assignment)
+      result = ASSIGNMENT_WORD;
+
+    if (last_read_token == FUNCTION)
+      allow_open_brace = 1;
+  }
+  return (result);
+}
+
+/* Return 1 if TOKEN is a token that after being read would allow
+   a reserved word to be seen, else 0. */
+static int
+reserved_word_acceptable (token)
+     int token;
+{
+#if 0
+  if (member (token, "\n;()|&{") ||
+#else
+  if (token == '\n' || token == ';' || token == '(' || token == ')' ||
+      token == '|' || token == '&' || token == '{' ||
+#endif
+      token == '}' ||                  /* XXX */
+      token == AND_AND ||
+      token == BANG ||
+      token == DO ||
+      token == ELIF ||
+      token == ELSE ||
+      token == FI ||
+      token == IF ||
+      token == OR_OR ||
+      token == SEMI_SEMI ||
+      token == THEN ||
+      token == UNTIL ||
+      token == WHILE ||
+      token == DONE ||         /* XXX these two are experimental */
+      token == ESAC ||
+      token == 0)
+    return (1);
+  else
+    return (0);
+}
+
+/* Return the index of TOKEN in the alist of reserved words, or -1 if
+   TOKEN is not a shell reserved word. */
+int
+find_reserved_word (token)
+     char *token;
+{
+  int i;
+  for (i = 0; word_token_alist[i].word != (char *)NULL; i++)
+    if (STREQ (token, word_token_alist[i].word))
+      return i;
+  return -1;
+}
+
+#if defined (READLINE)
+/* Called after each time readline is called.  This insures that whatever
+   the new prompt string is gets propagated to readline's local prompt
+   variable. */
+static void
+reset_readline_prompt ()
+{
+  if (prompt_string_pointer)
+    {
+      char *temp_prompt;
+
+      temp_prompt = *prompt_string_pointer
+                       ? decode_prompt_string (*prompt_string_pointer)
+                       : (char *)NULL;
+
+      if (temp_prompt == 0)
+       {
+         temp_prompt = xmalloc (1);
+         temp_prompt[0] = '\0';
+       }
+
+      FREE (current_readline_prompt);
+
+      current_readline_prompt = temp_prompt;
+    }
+}
+#endif /* READLINE */
+
+#if defined (HISTORY)
+/* A list of tokens which can be followed by newlines, but not by
+   semi-colons.  When concatenating multiple lines of history, the
+   newline separator for such tokens is replaced with a space. */
+static int no_semi_successors[] = {
+  '\n', '{', '(', ')', ';', '&', '|',
+  CASE, DO, ELSE, IF, IN, SEMI_SEMI, THEN, UNTIL, WHILE, AND_AND, OR_OR,
+  0
+};
+
+/* If we are not within a delimited expression, try to be smart
+   about which separators can be semi-colons and which must be
+   newlines. */
+char *
+history_delimiting_chars ()
+{
+  if (!delimiter_depth)
+    {
+      register int i;
+
+      for (i = 0; no_semi_successors[i]; i++)
+       {
+         if (token_before_that == no_semi_successors[i])
+           return (" ");
+       }
+      return ("; ");
+    }
+  else
+    return ("\n");
+}
+#endif /* HISTORY */
+
+/* Issue a prompt, or prepare to issue a prompt when the next character
+   is read. */
+static void
+prompt_again ()
+{
+  char *temp_prompt;
+
+  if (!interactive)    /* XXX */
+    return;
+
+  ps1_prompt = get_string_value ("PS1");
+  ps2_prompt = get_string_value ("PS2");
+
+  if (!prompt_string_pointer)
+    prompt_string_pointer = &ps1_prompt;
+
+  temp_prompt = (*prompt_string_pointer)
+                       ? decode_prompt_string (*prompt_string_pointer)
+                       : (char *)NULL;
+
+  if (temp_prompt == 0)
+    {
+      temp_prompt = xmalloc (1);
+      temp_prompt[0] = '\0';
+    }
+
+  current_prompt_string = *prompt_string_pointer;
+  prompt_string_pointer = &ps2_prompt;
+
+#if defined (READLINE)
+  if (!no_line_editing)
+    {
+      FREE (current_readline_prompt);
+      current_readline_prompt = temp_prompt;
+    }
+  else
+#endif /* READLINE */
+    {
+      FREE (current_decoded_prompt);
+      current_decoded_prompt = temp_prompt;
+    }
+}
+
+static void
+print_prompt ()
+{
+  fprintf (stderr, "%s", current_decoded_prompt);
+  fflush (stderr);
+}
+
+/* Return a string which will be printed as a prompt.  The string
+   may contain special characters which are decoded as follows:
+   
+       \t      the time
+       \d      the date
+       \n      CRLF
+       \s      the name of the shell
+       \w      the current working directory
+       \W      the last element of PWD
+       \u      your username
+       \h      the hostname
+       \#      the command number of this command
+       \!      the history number of this command
+       \$      a $ or a # if you are root
+       \<octal> character code in octal
+       \\      a backslash
+*/
+#define PROMPT_GROWTH 50
+char *
+decode_prompt_string (string)
+     char *string;
+{
+  int result_size = PROMPT_GROWTH;
+  int result_index = 0;
+  char *result;
+  int c;
+  char *temp = (char *)NULL;
+  WORD_LIST *list;
+
+#if defined (PROMPT_STRING_DECODE)
+
+  result = xmalloc (PROMPT_GROWTH);
+  result[0] = 0;
+
+  while (c = *string++)
+    {
+      if (posixly_correct && c == '!')
+       {
+         if (*string == '!')
+           {
+             temp = savestring ("!");
+             goto add_string;
+           }
+         else
+           {
+#if !defined (HISTORY)
+               temp = savestring ("1");
+#else /* HISTORY */
+               temp = itos (history_number ());
+#endif /* HISTORY */
+               string--;       /* add_string increments string again. */
+               goto add_string;
+           }
+       } 
+      if (c == '\\')
+       {
+         c = *string;
+
+         switch (c)
+           {
+           case '0':
+           case '1':
+           case '2':
+           case '3':
+           case '4':
+           case '5':
+           case '6':
+           case '7':
+             {
+               char octal_string[4];
+               int n;
+
+               strncpy (octal_string, string, 3);
+               octal_string[3] = '\0';
+
+               n = read_octal (octal_string);
+               temp = xmalloc (3);
+
+               if (n == CTLESC || n == CTLNUL)
+                 {
+                   string += 3;
+                   temp[0] = CTLESC;
+                   temp[1] = n;
+                   temp[2] = '\0';
+                 }
+               else if (n == -1)
+                 {
+                   temp[0] = '\\';
+                   temp[1] = '\0';
+                 }
+               else
+                 {
+                   string += 3;
+                   temp[0] = n;
+                   temp[1] = '\0';
+                 }
+
+               c = 0;
+               goto add_string;
+             }
+         
+           case 't':
+           case 'd':
+             /* Make the current time/date into a string. */
+             {
+               time_t the_time = time (0);
+               char *ttemp = ctime (&the_time);
+               temp = savestring (ttemp);
+
+               if (c == 't')
+                 {
+                   strcpy (temp, temp + 11);
+                   temp[8] = '\0';
+                 }
+               else
+                 temp[10] = '\0';
+
+               goto add_string;
+             }
+
+           case 'n':
+             if (!no_line_editing)
+               temp = savestring ("\r\n");
+             else
+               temp = savestring ("\n");
+             goto add_string;
+
+           case 's':
+             {
+               temp = base_pathname (shell_name);
+               temp = savestring (temp);
+               goto add_string;
+             }
+       
+           case 'w':
+           case 'W':
+             {
+               /* Use the value of PWD because it is much more effecient. */
+#define EFFICIENT
+#ifdef EFFICIENT
+               char *polite_directory_format (), t_string[MAXPATHLEN];
+
+               temp = get_string_value ("PWD");
+
+               if (!temp)
+                 getwd (t_string);
+               else
+                 strcpy (t_string, temp);
+#else
+               getwd (t_string);
+#endif /* EFFICIENT */
+
+               if (c == 'W')
+                 {
+                   char *dir = (char *)strrchr (t_string, '/');
+                   if (dir && dir != t_string)
+                     strcpy (t_string, dir + 1);
+                   temp = savestring (t_string);
+                 }
+               else
+                 temp = savestring (polite_directory_format (t_string));
+               goto add_string;
+             }
+      
+           case 'u':
+             {
+               temp = savestring (current_user.user_name);
+               goto add_string;
+             }
+
+           case 'h':
+             {
+               char *t_string;
+
+               temp = savestring (current_host_name);
+               if (t_string = (char *)strchr (temp, '.'))
+                 *t_string = '\0';
+               goto add_string;
+             }
+
+           case '#':
+             {
+               temp = itos (current_command_number);
+               goto add_string;
+             }
+
+           case '!':
+             {
+#if !defined (HISTORY)
+               temp = savestring ("1");
+#else /* HISTORY */
+               temp = itos (history_number ());
+#endif /* HISTORY */
+               goto add_string;
+             }
+
+           case '$':
+             temp = savestring (geteuid () == 0 ? "#" : "$");
+             goto add_string;
+
+#if defined (READLINE)
+           case '[':
+           case ']':
+             temp = xmalloc(3);
+             temp[0] = '\001';
+             temp[1] = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
+             temp[2] = '\0';
+             goto add_string;
+#endif
+
+           case '\\':
+             temp = savestring ("\\");
+             goto add_string;
+
+           default:
+             temp = savestring ("\\ ");
+             temp[1] = c;
+
+           add_string:
+             if (c)
+               string++;
+             result =
+               sub_append_string (temp, result, &result_index, &result_size);
+             temp = (char *)NULL; /* Free ()'ed in sub_append_string (). */
+             result[result_index] = '\0';
+             break;
+           }
+       }
+      else
+       {
+         while (3 + result_index > result_size)
+           result = xrealloc (result, result_size += PROMPT_GROWTH);
+
+         result[result_index++] = c;
+         result[result_index] = '\0';
+       }
+    }
+#else /* !PROMPT_STRING_DECODE */
+  result = savestring (string);
+#endif /* !PROMPT_STRING_DECODE */
+
+  /* Perform variable and parameter expansion and command substitution on
+     the prompt string. */
+  list = expand_string_unsplit (result, 1);
+  free (result);
+  result = string_list (list);
+  dispose_words (list);
+
+  return (result);
+}
+
+/* Report a syntax error, and restart the parser.  Call here for fatal
+   errors. */
+yyerror ()
+{
+  report_syntax_error ((char *)NULL);
+  reset_parser ();
+}
+
+/* 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
+   out an appropriate message for you. */
+static void
+report_syntax_error (message)
+     char *message;
+{
+  if (message)
+    {
+      if (!interactive)
+       {
+         char *name = bash_input.name ? bash_input.name : "stdin";
+         report_error ("%s: line %d: `%s'", name, line_number, message);
+       }
+      else
+       {
+         if (EOF_Reached)
+           EOF_Reached = 0;
+         report_error ("%s", message);
+       }
+
+      last_command_exit_value = EX_USAGE;
+      return;
+    }
+
+  if (shell_input_line && *shell_input_line)
+    {
+      char *t = shell_input_line;
+      register int i = shell_input_line_index;
+      int token_end = 0;
+
+      if (!t[i] && i)
+       i--;
+
+      while (i && (t[i] == ' ' || t[i] == '\t' || t[i] == '\n'))
+       i--;
+
+      if (i)
+       token_end = i + 1;
+
+      while (i && !member (t[i], " \n\t;|&"))
+       i--;
+
+      while (i != token_end && member (t[i], " \t\n"))
+       i++;
+
+      if (token_end)
+       {
+         char *error_token;
+         error_token = xmalloc (1 + (token_end - i));
+         strncpy (error_token, t + i, token_end - i);
+         error_token[token_end - i] = '\0';
+
+         report_error ("syntax error near unexpected token `%s'", error_token);
+         free (error_token);
+       }
+      else if ((i == 0) && (token_end == 0))   /* a 1-character token */
+       {
+         char etoken[2];
+         etoken[0] = t[i];
+         etoken[1] = '\0';
+
+         report_error ("syntax error near unexpected token `%s'", etoken);
+       }
+
+      if (!interactive)
+       {
+         char *temp = savestring (shell_input_line);
+         char *name = bash_input.name ? bash_input.name : "stdin";
+         int l = strlen (temp);
+
+         while (l && temp[l - 1] == '\n')
+           temp[--l] = '\0';
+
+         report_error ("%s: line %d: `%s'", name, line_number, temp);
+         free (temp);
+       }
+    }
+  else
+    {
+      char *name, *msg;
+      if (!interactive)
+       name = bash_input.name ? bash_input.name : "stdin";
+      if (EOF_Reached)
+       msg = "syntax error: unexpected end of file";
+      else
+       msg = "syntax error";
+      if (!interactive)
+       report_error ("%s: line %d: %s", name, line_number, msg);
+      else
+       {
+         /* This file uses EOF_Reached only for error reporting
+            when the shell is interactive.  Other mechanisms are 
+            used to decide whether or not to exit. */
+         EOF_Reached = 0;
+         report_error (msg);
+       }
+    }
+  last_command_exit_value = EX_USAGE;
+}
+
+/* ??? Needed function. ??? We have to be able to discard the constructs
+   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. */
+discard_parser_constructs (error_p)
+     int error_p;
+{
+}
+   
+/* Do that silly `type "bye" to exit' stuff.  You know, "ignoreeof". */
+
+/* A flag denoting whether or not ignoreeof is set. */
+int ignoreeof = 0;
+
+/* The number of times that we have encountered an EOF character without
+   another character intervening.  When this gets above the limit, the
+   shell terminates. */
+int eof_encountered = 0;
+
+/* The limit for eof_encountered. */
+int eof_encountered_limit = 10;
+
+/* If we have EOF as the only input unit, this user wants to leave
+   the shell.  If the shell is not interactive, then just leave.
+   Otherwise, if ignoreeof is set, and we haven't done this the
+   required number of times in a row, print a message. */
+static void
+handle_eof_input_unit ()
+{
+  if (interactive)
+    {
+      /* shell.c may use this to decide whether or not to write out the
+        history, among other things.  We use it only for error reporting
+        in this file. */
+      if (EOF_Reached)
+       EOF_Reached = 0;
+
+      /* If the user wants to "ignore" eof, then let her do so, kind of. */
+      if (ignoreeof)
+       {
+         if (eof_encountered < eof_encountered_limit)
+           {
+             fprintf (stderr, "Use \"%s\" to leave the shell.\n",
+                      login_shell ? "logout" : "exit");
+             eof_encountered++;
+             /* Reset the prompt string to be $PS1. */
+             prompt_string_pointer = (char **)NULL;
+             prompt_again ();
+             last_read_token = current_token = '\n';
+             return;
+           } 
+       }
+
+      /* In this case EOF should exit the shell.  Do it now. */
+      reset_parser ();
+      exit_builtin ((WORD_LIST *)NULL);
+    }
+  else
+    {
+      /* We don't write history files, etc., for non-interactive shells. */
+      EOF_Reached = 1;
+    }
+}
diff --git a/y.tab.h b/y.tab.h
new file mode 100644 (file)
index 0000000..7ba3b28
--- /dev/null
+++ b/y.tab.h
@@ -0,0 +1,43 @@
+typedef union {
+  WORD_DESC *word;             /* the word that we read. */
+  int number;                  /* the number that we read. */
+  WORD_LIST *word_list;
+  COMMAND *command;
+  REDIRECT *redirect;
+  ELEMENT element;
+  PATTERN_LIST *pattern;
+} YYSTYPE;
+#define        IF      258
+#define        THEN    259
+#define        ELSE    260
+#define        ELIF    261
+#define        FI      262
+#define        CASE    263
+#define        ESAC    264
+#define        FOR     265
+#define        SELECT  266
+#define        WHILE   267
+#define        UNTIL   268
+#define        DO      269
+#define        DONE    270
+#define        FUNCTION        271
+#define        IN      272
+#define        BANG    273
+#define        WORD    274
+#define        ASSIGNMENT_WORD 275
+#define        NUMBER  276
+#define        AND_AND 277
+#define        OR_OR   278
+#define        GREATER_GREATER 279
+#define        LESS_LESS       280
+#define        LESS_AND        281
+#define        GREATER_AND     282
+#define        SEMI_SEMI       283
+#define        LESS_LESS_MINUS 284
+#define        AND_GREATER     285
+#define        LESS_GREATER    286
+#define        GREATER_BAR     287
+#define        yacc_EOF        288
+
+
+extern YYSTYPE yylval;