summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJari Aalto <jari.aalto@cante.net>1996-08-26 18:22:31 +0000
committerJari Aalto <jari.aalto@cante.net>2009-09-12 16:46:49 +0000
commit726f63884db0132f01745f1fb4465e6621088ccf (patch)
tree6c2f7765a890a97e0e513cb539df43283a8f7c4d
downloadbash-726f63884db0132f01745f1fb4465e6621088ccf.tar.gz
Imported from ../bash-1.14.7.tar.gz.
-rw-r--r--.distribution1
-rw-r--r--.patchlevel1
-rw-r--r--COPYING257
-rw-r--r--CWRU/PLATFORMS18
-rw-r--r--CWRU/POSIX.NOTES63
-rw-r--r--CWRU/README26
-rw-r--r--CWRU/changelog786
-rw-r--r--CWRU/misc/aux-mach-desc20
-rwxr-xr-xCWRU/misc/bison7
-rw-r--r--CWRU/misc/open-files.c16
-rw-r--r--CWRU/misc/pid.c7
-rw-r--r--CWRU/misc/sigs.c27
-rw-r--r--CWRU/misc/sigstat.c206
-rw-r--r--CWRU/sh-redir-hack15
-rw-r--r--INSTALL212
-rw-r--r--MANIFEST421
-rw-r--r--Makefile115
-rw-r--r--NEWS10
-rw-r--r--README52
-rw-r--r--RELEASE269
-rw-r--r--alias.c535
-rw-r--r--alias.h75
-rw-r--r--ansi_stdlib.h41
-rw-r--r--bashansi.h36
-rw-r--r--bashhist.c390
-rw-r--r--bashhist.h42
-rw-r--r--bashline.c1797
-rw-r--r--bashtypes.h34
-rw-r--r--bracecomp.c166
-rw-r--r--braces.c371
-rw-r--r--builtins.h45
-rw-r--r--builtins/ChangeLog0
-rw-r--r--builtins/Makefile267
-rw-r--r--builtins/alias.def180
-rw-r--r--builtins/bashgetopt.c136
-rw-r--r--builtins/bashgetopt.h37
-rw-r--r--builtins/bind.def219
-rw-r--r--builtins/break.def110
-rw-r--r--builtins/builtin.def67
-rw-r--r--builtins/cd.def689
-rw-r--r--builtins/colon.def37
-rw-r--r--builtins/command.def177
-rw-r--r--builtins/common.c829
-rw-r--r--builtins/common.h69
-rw-r--r--builtins/declare.def290
-rw-r--r--builtins/echo.def168
-rw-r--r--builtins/enable.def156
-rw-r--r--builtins/eval.def45
-rw-r--r--builtins/exec.def163
-rw-r--r--builtins/exit.def129
-rw-r--r--builtins/fc.def691
-rw-r--r--builtins/fg_bg.def145
-rw-r--r--builtins/getopt.c283
-rw-r--r--builtins/getopt.h57
-rw-r--r--builtins/getopts.def300
-rw-r--r--builtins/hash.def222
-rw-r--r--builtins/hashcom.h32
-rw-r--r--builtins/help.def134
-rw-r--r--builtins/history.def179
-rw-r--r--builtins/inlib.def74
-rw-r--r--builtins/jobs.def171
-rw-r--r--builtins/kill.def281
-rw-r--r--builtins/let.def77
-rw-r--r--builtins/mkbuiltins.c1311
-rw-r--r--builtins/psize.c63
-rwxr-xr-xbuiltins/psize.sh24
-rw-r--r--builtins/read.def276
-rw-r--r--builtins/reserved.def154
-rw-r--r--builtins/return.def57
-rw-r--r--builtins/set.def528
-rw-r--r--builtins/setattr.def253
-rw-r--r--builtins/shift.def95
-rw-r--r--builtins/source.def186
-rw-r--r--builtins/suspend.def86
-rw-r--r--builtins/test.def144
-rw-r--r--builtins/times.def89
-rw-r--r--builtins/trap.def204
-rw-r--r--builtins/type.def325
-rw-r--r--builtins/ulimit.def731
-rw-r--r--builtins/umask.def288
-rw-r--r--builtins/wait.def132
-rw-r--r--command.h215
-rw-r--r--config.h186
-rw-r--r--config.h.mini194
-rwxr-xr-xconfigure8
-rw-r--r--copy_cmd.c305
-rw-r--r--cpp-Makefile1553
-rw-r--r--dispose_cmd.c207
-rw-r--r--dispose_cmd.h32
-rw-r--r--documentation/FAQ795
-rw-r--r--documentation/Makefile103
-rw-r--r--documentation/README32
-rw-r--r--documentation/article.ms1114
-rw-r--r--documentation/article.ps1368
-rw-r--r--documentation/article.txt1111
-rw-r--r--documentation/bash.15371
-rw-r--r--documentation/bash.ps3959
-rw-r--r--documentation/bash.txt3960
-rw-r--r--documentation/builtins.115
-rw-r--r--documentation/builtins.ps1367
-rw-r--r--documentation/builtins.txt1188
-rw-r--r--documentation/features.dvibin0 -> 191364 bytes
-rw-r--r--documentation/features.info3011
-rw-r--r--documentation/features.ps3825
-rw-r--r--documentation/features.texi1907
-rw-r--r--documentation/readline.31216
-rw-r--r--documentation/readline.ps1052
-rw-r--r--documentation/readline.txt1122
-rw-r--r--documentation/texinfo.tex4003
-rw-r--r--endian.c148
-rw-r--r--error.c244
-rw-r--r--error.h34
-rwxr-xr-xexamples/alias-conv.sh22
-rw-r--r--examples/functions/autoload103
-rw-r--r--examples/functions/basename23
-rw-r--r--examples/functions/csh-compat36
-rw-r--r--examples/functions/dirfuncs142
-rw-r--r--examples/functions/dirname21
-rw-r--r--examples/functions/exitstat22
-rw-r--r--examples/functions/external50
-rw-r--r--examples/functions/fact13
-rw-r--r--examples/functions/fstty59
-rw-r--r--examples/functions/func27
-rw-r--r--examples/functions/jj.bash12
-rw-r--r--examples/functions/kshenv183
-rw-r--r--examples/functions/manpage129
-rw-r--r--examples/functions/notify.bash58
-rw-r--r--examples/functions/shcat7
-rw-r--r--examples/functions/substr79
-rw-r--r--examples/functions/substr281
-rw-r--r--examples/functions/term35
-rw-r--r--examples/functions/whatis52
-rw-r--r--examples/functions/whence59
-rwxr-xr-xexamples/scripts/adventure.sh545
-rw-r--r--examples/scripts/bcsh.sh1254
-rw-r--r--examples/scripts/precedence75
-rwxr-xr-xexamples/scripts/shprompt137
-rw-r--r--examples/startup-files/Bash_aliases63
-rw-r--r--examples/startup-files/Bash_profile20
-rw-r--r--examples/startup-files/Bashrc72
-rw-r--r--examples/startup-files/bash-profile54
-rw-r--r--examples/startup-files/bashrc139
-rw-r--r--examples/suncmd.termcap30
-rw-r--r--execute_cmd.c3698
-rw-r--r--execute_cmd.h47
-rw-r--r--expr.c902
-rw-r--r--externs.h67
-rw-r--r--filecntl.h36
-rw-r--r--flags.c270
-rw-r--r--flags.h65
-rw-r--r--general.c1273
-rw-r--r--general.h247
-rw-r--r--getcwd.c344
-rw-r--r--hash.c297
-rw-r--r--hash.h61
-rw-r--r--input.c464
-rw-r--r--input.h115
-rw-r--r--jobs.c2755
-rw-r--r--jobs.h345
-rw-r--r--lib/doc-support/Makefile23
-rw-r--r--lib/doc-support/getopt.h129
-rw-r--r--lib/doc-support/texindex.c1666
-rw-r--r--lib/glob/ChangeLog13
-rw-r--r--lib/glob/Makefile95
-rw-r--r--lib/glob/doc/Makefile5
-rw-r--r--lib/glob/doc/glob.texi1
-rw-r--r--lib/glob/fnmatch.c189
-rw-r--r--lib/glob/fnmatch.h36
-rw-r--r--lib/glob/glob.c574
-rw-r--r--lib/glob/ndir.h50
-rw-r--r--lib/malloc/Makefile28
-rw-r--r--lib/malloc/alloca.c480
-rw-r--r--lib/malloc/getpagesize.h49
-rw-r--r--lib/malloc/i386-alloca.s16
-rw-r--r--lib/malloc/malloc.c668
-rw-r--r--lib/malloc/x386-alloca.s63
-rw-r--r--lib/malloc/xmalloc.c78
-rw-r--r--lib/malloclib/Makefile53
-rw-r--r--lib/malloclib/alloca.c189
-rw-r--r--lib/malloclib/calloc.c39
-rw-r--r--lib/malloclib/cfree.c43
-rw-r--r--lib/malloclib/free.c212
-rw-r--r--lib/malloclib/getpagesize.h56
-rw-r--r--lib/malloclib/i386-alloca.s16
-rw-r--r--lib/malloclib/malloc.c324
-rw-r--r--lib/malloclib/malloc.h268
-rw-r--r--lib/malloclib/mcheck.c133
-rw-r--r--lib/malloclib/memalign.c61
-rw-r--r--lib/malloclib/morecore.c44
-rw-r--r--lib/malloclib/mstats.c39
-rw-r--r--lib/malloclib/mtrace.awk36
-rw-r--r--lib/malloclib/mtrace.c150
-rw-r--r--lib/malloclib/realloc.c146
-rw-r--r--lib/malloclib/valloc.c48
-rw-r--r--lib/malloclib/x386-alloca.s63
-rw-r--r--lib/malloclib/xmalloc.c69
-rw-r--r--lib/posixheaders/ansi_stdlib.h41
-rw-r--r--lib/posixheaders/filecntl.h36
-rw-r--r--lib/posixheaders/memalloc.h56
-rw-r--r--lib/posixheaders/posixstat.h149
-rw-r--r--lib/posixheaders/stdc.h78
-rw-r--r--lib/readline/COPYING257
-rw-r--r--lib/readline/ChangeLog403
-rw-r--r--lib/readline/Makefile134
-rw-r--r--lib/readline/README6
-rw-r--r--lib/readline/STANDALONE31
-rw-r--r--lib/readline/ansi_stdlib.h41
-rw-r--r--lib/readline/bind.c1487
-rw-r--r--lib/readline/chardefs.h122
-rw-r--r--lib/readline/complete.c1459
-rw-r--r--lib/readline/display.c1276
-rw-r--r--lib/readline/doc/Makefile55
-rw-r--r--lib/readline/doc/hist.texinfo113
-rw-r--r--lib/readline/doc/history.dvibin0 -> 47376 bytes
-rw-r--r--lib/readline/doc/history.info744
-rw-r--r--lib/readline/doc/history.ps2037
-rw-r--r--lib/readline/doc/hstech.texinfo489
-rw-r--r--lib/readline/doc/hsuser.texinfo198
-rw-r--r--lib/readline/doc/readline.dvibin0 -> 154240 bytes
-rw-r--r--lib/readline/doc/readline.info744
-rw-r--r--lib/readline/doc/readline.ps2037
-rw-r--r--lib/readline/doc/rlman.texinfo111
-rw-r--r--lib/readline/doc/rltech.texinfo1406
-rw-r--r--lib/readline/doc/rluser.texinfo875
-rw-r--r--lib/readline/doc/texindex.c1666
-rw-r--r--lib/readline/emacs_keymap.c885
-rw-r--r--lib/readline/examples/Inputrc65
-rw-r--r--lib/readline/examples/Makefile12
-rw-r--r--lib/readline/examples/fileman.c425
-rw-r--r--lib/readline/examples/histexamp.c82
-rw-r--r--lib/readline/examples/manexamp.c94
-rw-r--r--lib/readline/funmap.c299
-rw-r--r--lib/readline/history.c2218
-rw-r--r--lib/readline/history.h181
-rw-r--r--lib/readline/isearch.c378
-rw-r--r--lib/readline/keymaps.c200
-rw-r--r--lib/readline/keymaps.h95
-rw-r--r--lib/readline/memalloc.h56
-rw-r--r--lib/readline/parens.c130
-rw-r--r--lib/readline/posixstat.h149
-rw-r--r--lib/readline/readline.c3539
-rw-r--r--lib/readline/readline.h289
-rw-r--r--lib/readline/rlconf.h57
-rw-r--r--lib/readline/rldefs.h212
-rw-r--r--lib/readline/rltty.c705
-rw-r--r--lib/readline/search.c370
-rw-r--r--lib/readline/signals.c287
-rw-r--r--lib/readline/tilde.c380
-rw-r--r--lib/readline/tilde.h38
-rw-r--r--lib/readline/vi_keymap.c877
-rw-r--r--lib/readline/vi_mode.c1329
-rw-r--r--lib/readline/xmalloc.c78
-rw-r--r--lib/termcap/Makefile67
-rw-r--r--lib/termcap/grot/COPYING339
-rw-r--r--lib/termcap/grot/ChangeLog48
-rw-r--r--lib/termcap/grot/INSTALL117
-rw-r--r--lib/termcap/grot/Makefile.in118
-rw-r--r--lib/termcap/grot/NEWS12
-rw-r--r--lib/termcap/grot/README14
-rwxr-xr-xlib/termcap/grot/configure346
-rw-r--r--lib/termcap/grot/configure.in10
-rw-r--r--lib/termcap/grot/termcap.info80
-rw-r--r--lib/termcap/grot/termcap.info-11115
-rw-r--r--lib/termcap/grot/termcap.info-2969
-rw-r--r--lib/termcap/grot/termcap.info-31469
-rw-r--r--lib/termcap/grot/termcap.info-4218
-rw-r--r--lib/termcap/grot/termcap.texi3603
-rw-r--r--lib/termcap/grot/texinfo.tex3941
-rw-r--r--lib/termcap/termcap.c716
-rw-r--r--lib/termcap/termcap.h62
-rw-r--r--lib/termcap/tparam.c325
-rw-r--r--lib/termcap/version.c2
-rw-r--r--lib/tilde/ChangeLog6
-rw-r--r--lib/tilde/Makefile98
-rw-r--r--lib/tilde/doc/Makefile5
-rw-r--r--lib/tilde/doc/tilde.texi0
-rw-r--r--lib/tilde/memalloc.h56
-rw-r--r--lib/tilde/tilde.c380
-rw-r--r--lib/tilde/tilde.h38
-rw-r--r--machines.h2392
-rw-r--r--mailcheck.c427
-rw-r--r--make_cmd.c612
-rw-r--r--make_cmd.h55
-rw-r--r--maxpath.h43
-rw-r--r--memalloc.h60
-rw-r--r--newversion.c281
-rw-r--r--nojobs.c644
-rw-r--r--parse.y3005
-rw-r--r--parser-built0
-rw-r--r--parser.h8
-rw-r--r--portbash/README1
-rw-r--r--portbash/libc.sh172
-rw-r--r--portbash/mkdesc.sh11
-rw-r--r--portbash/pgrp.c48
-rw-r--r--portbash/signals.sh64
-rw-r--r--portbash/stdio.sh87
-rw-r--r--portbash/strings.sh87
-rw-r--r--portbash/syscalls.sh80
-rw-r--r--posixstat.h149
-rw-r--r--print_cmd.c827
-rw-r--r--quit.h33
l---------sh1
-rw-r--r--shell.c1792
-rw-r--r--shell.h107
-rw-r--r--siglist.c219
-rw-r--r--siglist.h40
-rw-r--r--signames.c297
-rw-r--r--stdc.h78
-rw-r--r--subst.c4867
-rw-r--r--subst.h181
-rw-r--r--support/PORTING22
-rw-r--r--support/SYMLINKS23
-rw-r--r--support/bash.xbm59
-rw-r--r--support/bashbug.sh84
-rw-r--r--support/cat-s16
-rwxr-xr-xsupport/clone-bash95
-rwxr-xr-xsupport/cppmagic51
-rwxr-xr-xsupport/fixlinks61
-rw-r--r--support/getcppsyms.c428
-rwxr-xr-xsupport/inpath19
-rwxr-xr-xsupport/install.sh235
-rwxr-xr-xsupport/mkdirs29
-rwxr-xr-xsupport/mklinks41
-rwxr-xr-xsupport/mkmachtype279
-rwxr-xr-xsupport/mksysdefs497
-rwxr-xr-xsupport/printenv11
-rw-r--r--support/recho.c32
-rwxr-xr-xsupport/srcdir13
-rwxr-xr-xsupport/texi2dvi263
-rw-r--r--test.c1132
-rw-r--r--tests/README1
-rwxr-xr-xtests/dollar-at.sh1
-rwxr-xr-xtests/dollar-star.sh1
-rw-r--r--tests/dollar.right3
-rw-r--r--tests/exp-tests326
-rw-r--r--tests/exp.right113
-rw-r--r--tests/glob-test179
-rw-r--r--tests/glob.right63
-rw-r--r--tests/ifs-test-1.sh5
-rw-r--r--tests/ifs-test-2.sh9
-rw-r--r--tests/ifs-test-3.sh9
-rw-r--r--tests/ifs.1.right1
-rw-r--r--tests/ifs.2.right1
-rw-r--r--tests/ifs.3.right1
-rw-r--r--tests/input-line.sh4
-rw-r--r--tests/input-line.sub2
-rw-r--r--tests/input.right3
-rw-r--r--tests/minus-e6
-rw-r--r--tests/minus-e.right1
-rwxr-xr-xtests/misc/chld-trap.sh14
-rw-r--r--tests/misc/dot-test-1.sh3
-rw-r--r--tests/misc/dot-test-1.sub1
-rw-r--r--tests/misc/gotest26
-rw-r--r--tests/misc/perf-script81
-rw-r--r--tests/misc/redir.t1.sh26
-rw-r--r--tests/misc/redir.t2.sh17
-rwxr-xr-xtests/misc/redir.t3.sh8
-rw-r--r--tests/misc/redir.t3.sub1
-rw-r--r--tests/misc/redir.t4.sh12
-rwxr-xr-xtests/misc/run.r1.sh1
-rwxr-xr-xtests/misc/run.r2.sh1
-rwxr-xr-xtests/misc/run.r3.sh3
-rwxr-xr-xtests/misc/sigint.t1.sh9
-rwxr-xr-xtests/misc/sigint.t2.sh7
-rwxr-xr-xtests/misc/sigint.t3.sh11
-rwxr-xr-xtests/misc/sigint.t4.sh13
-rw-r--r--tests/misc/test-minus-e.112
-rw-r--r--tests/misc/test-minus-e.214
-rw-r--r--tests/new-exp.right33
-rw-r--r--tests/new-exp.tests95
-rw-r--r--tests/prec.right28
-rwxr-xr-xtests/precedence75
-rwxr-xr-xtests/run-all17
-rwxr-xr-xtests/run-dollars3
-rwxr-xr-xtests/run-exp-tests2
-rwxr-xr-xtests/run-glob-test4
-rwxr-xr-xtests/run-ifs-tests13
-rwxr-xr-xtests/run-input-test2
-rwxr-xr-xtests/run-minus-e2
-rwxr-xr-xtests/run-new-exp2
-rwxr-xr-xtests/run-precedence2
-rwxr-xr-xtests/run-set-e-test2
-rwxr-xr-xtests/run-strip2
-rwxr-xr-xtests/run-varenv2
-rw-r--r--tests/set-e-test16
-rw-r--r--tests/set-e.right15
-rw-r--r--tests/strip.right12
-rw-r--r--tests/strip.tests22
-rw-r--r--tests/tilde-tests16
-rw-r--r--tests/tilde.right14
-rw-r--r--tests/varenv.right14
-rw-r--r--tests/varenv.sh94
-rw-r--r--trap.c672
-rw-r--r--trap.h65
-rw-r--r--unwind_prot.c272
-rw-r--r--unwind_prot.h47
-rw-r--r--variables.c1804
-rw-r--r--variables.h108
-rw-r--r--version.c26
-rw-r--r--vprint.c80
-rw-r--r--y.tab.c4205
-rw-r--r--y.tab.h43
402 files changed, 150297 insertions, 0 deletions
diff --git a/.distribution b/.distribution
new file mode 100644
index 00000000..63738cc2
--- /dev/null
+++ b/.distribution
@@ -0,0 +1 @@
+1.14
diff --git a/.patchlevel b/.patchlevel
new file mode 100644
index 00000000..7f8f011e
--- /dev/null
+++ b/.patchlevel
@@ -0,0 +1 @@
+7
diff --git a/COPYING b/COPYING
new file mode 100644
index 00000000..d642012b
--- /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.
+
+ 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.
+
+ 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.
+
+ 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
+
+ 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
index 00000000..a792966b
--- /dev/null
+++ b/CWRU/PLATFORMS
@@ -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
index 00000000..bc9a969f
--- /dev/null
+++ b/CWRU/POSIX.NOTES
@@ -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
index 00000000..8e3398d6
--- /dev/null
+++ b/CWRU/README
@@ -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
index 00000000..11d67757
--- /dev/null
+++ b/CWRU/changelog
@@ -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
index 00000000..71a8dabe
--- /dev/null
+++ b/CWRU/misc/aux-mach-desc
@@ -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
index 00000000..b819c901
--- /dev/null
+++ b/CWRU/misc/bison
@@ -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
index 00000000..8f4d18e5
--- /dev/null
+++ b/CWRU/misc/open-files.c
@@ -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
index 00000000..458fde43
--- /dev/null
+++ b/CWRU/misc/pid.c
@@ -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
index 00000000..ea9f955c
--- /dev/null
+++ b/CWRU/misc/sigs.c
@@ -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
index 00000000..f1ac5579
--- /dev/null
+++ b/CWRU/misc/sigstat.c
@@ -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
index 00000000..413b2979
--- /dev/null
+++ b/CWRU/sh-redir-hack
@@ -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
index 00000000..e3664068
--- /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
index 00000000..4307b2f4
--- /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
index 00000000..da50f7af
--- /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
index 00000000..783d193d
--- /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
index 00000000..6638c6e7
--- /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
index 00000000..6a5167e8
--- /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
index 00000000..f9be0b4d
--- /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
index 00000000..2a2d1846
--- /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
index 00000000..52339da5
--- /dev/null
+++ b/ansi_stdlib.h
@@ -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
index 00000000..44119701
--- /dev/null
+++ b/bashansi.h
@@ -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
index 00000000..cd7134b2
--- /dev/null
+++ b/bashhist.c
@@ -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
index 00000000..c1c24fc5
--- /dev/null
+++ b/bashhist.h
@@ -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
index 00000000..a924b054
--- /dev/null
+++ b/bashline.c
@@ -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
index 00000000..a725d619
--- /dev/null
+++ b/bashtypes.h
@@ -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
index 00000000..c07e15df
--- /dev/null
+++ b/bracecomp.c
@@ -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
index 00000000..2eb4de4b
--- /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);
+ }
+}
+
+/*
+ * 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
index 00000000..6d4d8e86
--- /dev/null
+++ b/builtins.h
@@ -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
index 00000000..e69de29b
--- /dev/null
+++ b/builtins/ChangeLog
diff --git a/builtins/Makefile b/builtins/Makefile
new file mode 100644
index 00000000..6472f7d2
--- /dev/null
+++ b/builtins/Makefile
@@ -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
index 00000000..a878c705
--- /dev/null
+++ b/builtins/alias.def
@@ -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
index 00000000..95dcaacb
--- /dev/null
+++ b/builtins/bashgetopt.c
@@ -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
index 00000000..0360dbb8
--- /dev/null
+++ b/builtins/bashgetopt.h
@@ -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
index 00000000..cdcd6a37
--- /dev/null
+++ b/builtins/bind.def
@@ -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
index 00000000..d72f9e32
--- /dev/null
+++ b/builtins/break.def
@@ -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
index 00000000..824b30d4
--- /dev/null
+++ b/builtins/builtin.def
@@ -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
index 00000000..338f6942
--- /dev/null
+++ b/builtins/cd.def
@@ -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
index 00000000..4ae5b65e
--- /dev/null
+++ b/builtins/colon.def
@@ -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
index 00000000..b84613e7
--- /dev/null
+++ b/builtins/command.def
@@ -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
index 00000000..ff940b56
--- /dev/null
+++ b/builtins/common.c
@@ -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
index 00000000..c7c99e7b
--- /dev/null
+++ b/builtins/common.h
@@ -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
index 00000000..17b7ea2d
--- /dev/null
+++ b/builtins/declare.def
@@ -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
index 00000000..7539103b
--- /dev/null
+++ b/builtins/echo.def
@@ -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
index 00000000..2aeae39d
--- /dev/null
+++ b/builtins/enable.def
@@ -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
index 00000000..5c3eda83
--- /dev/null
+++ b/builtins/eval.def
@@ -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
index 00000000..f950afc6
--- /dev/null
+++ b/builtins/exec.def
@@ -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
index 00000000..25a3b633
--- /dev/null
+++ b/builtins/exit.def
@@ -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
index 00000000..1f6db680
--- /dev/null
+++ b/builtins/fc.def
@@ -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
index 00000000..e48af386
--- /dev/null
+++ b/builtins/fg_bg.def
@@ -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
index 00000000..76034304
--- /dev/null
+++ b/builtins/getopt.c
@@ -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
index 00000000..fa9878c7
--- /dev/null
+++ b/builtins/getopt.h
@@ -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
index 00000000..0f2b82fc
--- /dev/null
+++ b/builtins/getopts.def
@@ -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
index 00000000..f4d319b9
--- /dev/null
+++ b/builtins/hash.def
@@ -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
index 00000000..defe2fc9
--- /dev/null
+++ b/builtins/hashcom.h
@@ -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
index 00000000..c9f1db87
--- /dev/null
+++ b/builtins/help.def
@@ -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
index 00000000..814e7054
--- /dev/null
+++ b/builtins/history.def
@@ -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
index 00000000..023945b8
--- /dev/null
+++ b/builtins/inlib.def
@@ -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
index 00000000..8a293da5
--- /dev/null
+++ b/builtins/jobs.def
@@ -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
index 00000000..53d5c8fa
--- /dev/null
+++ b/builtins/kill.def
@@ -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
index 00000000..fdb3a6f6
--- /dev/null
+++ b/builtins/let.def
@@ -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
index 00000000..572d01e8
--- /dev/null
+++ b/builtins/mkbuiltins.c
@@ -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 ();
+
+
+/* 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
index 00000000..03a4f6e4
--- /dev/null
+++ b/builtins/psize.c
@@ -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
index 00000000..961becd3
--- /dev/null
+++ b/builtins/psize.sh
@@ -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
index 00000000..7b6dfc90
--- /dev/null
+++ b/builtins/read.def
@@ -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
index 00000000..4074ae0c
--- /dev/null
+++ b/builtins/reserved.def
@@ -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
index 00000000..8340a44f
--- /dev/null
+++ b/builtins/return.def
@@ -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
index 00000000..a97168c4
--- /dev/null
+++ b/builtins/set.def
@@ -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
index 00000000..2340e1a8
--- /dev/null
+++ b/builtins/setattr.def
@@ -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
index 00000000..4d8fed0a
--- /dev/null
+++ b/builtins/shift.def
@@ -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
index 00000000..895e98bd
--- /dev/null
+++ b/builtins/source.def
@@ -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
index 00000000..48edc207
--- /dev/null
+++ b/builtins/suspend.def
@@ -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
index 00000000..2b1457ba
--- /dev/null
+++ b/builtins/test.def
@@ -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
index 00000000..9c42768d
--- /dev/null
+++ b/builtins/times.def
@@ -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
index 00000000..b81651df
--- /dev/null
+++ b/builtins/trap.def
@@ -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
index 00000000..aecc303c
--- /dev/null
+++ b/builtins/type.def
@@ -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
index 00000000..1947c367
--- /dev/null
+++ b/builtins/ulimit.def
@@ -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
index 00000000..1d84aa9a
--- /dev/null
+++ b/builtins/umask.def
@@ -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
index 00000000..f6131798
--- /dev/null
+++ b/builtins/wait.def
@@ -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
index 00000000..cffc15f8
--- /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
index 00000000..8fd2ba31
--- /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
index 00000000..3acc84e1
--- /dev/null
+++ b/config.h.mini
@@ -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
index 00000000..53e10b6e
--- /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
index 00000000..991bbc9d
--- /dev/null
+++ b/copy_cmd.c
@@ -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
index 00000000..9e1e2e8e
--- /dev/null
+++ b/cpp-Makefile
@@ -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
index 00000000..f420fe16
--- /dev/null
+++ b/dispose_cmd.c
@@ -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
index 00000000..11166dd7
--- /dev/null
+++ b/dispose_cmd.h
@@ -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
index 00000000..c44bc478
--- /dev/null
+++ b/documentation/FAQ
@@ -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
index 00000000..fb437eb4
--- /dev/null
+++ b/documentation/Makefile
@@ -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
index 00000000..c20007db
--- /dev/null
+++ b/documentation/README
@@ -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
index 00000000..027f8768
--- /dev/null
+++ b/documentation/article.ms
@@ -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
index 00000000..3cf5f39f
--- /dev/null
+++ b/documentation/article.ps
@@ -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
index 00000000..38cd71fe
--- /dev/null
+++ b/documentation/article.txt
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+ Bash - The GNU shell*
+
+
+ Chet Ramey
+ Case Western Reserve University
+ chet@po.cwru.edu
+
+
+
+
+
+
+_1. _I_n_t_r_o_d_u_c_t_i_o_n
+
+ _B_a_s_h 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|- shell /_b_i_n/_s_h, 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.
+
+_2. _W_h_a_t'_s _P_O_S_I_X, _a_n_y_w_a_y?
+
+ _P_O_S_I_X is a name originally coined by Richard Stallman
+_________________________
+*An earlier version of this article appeared in The
+Linux Journal.
+|- 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).|= 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+ Aspects of the shell's syntax and command language. A
+ number of special builtins such as _c_d and _e_x_e_c are
+ being specified as part of the shell, since their func-
+ tionality usually cannot be implemented by a separate
+ executable;
+
+o+ A set of utilities to be called by shell scripts and
+ applications. Examples are programs like _s_e_d, _t_r, and
+ _a_w_k. Utilities commonly implemented as shell builtins
+ are described in this section, such as _t_e_s_t and _k_i_l_l.
+ An expansion of this section's scope, termed the User
+ Portability Extension, or UPE, has standardized
+ interactive programs such as _v_i and _m_a_i_l_x;
+
+o+ 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 (_g_l_o_b_b_i_n_g),
+ obtain values of POSIX.2 system configuration vari-
+ ables, retrieve values of environment variables
+ (getenv()), _a_n_d _o_t_h_e_r _s_e_r_v_i_c_e_s;
+
+o+ A suite of "development" utilities such as _c_8_9 (the
+ POSIX.2 version of _c_c), and _y_a_c_c.
+
+ 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 _s_p_e_c_i_a_l builtins, which must be implemented as
+part of the shell to provide the desired functionality, are
+_________________________
+|=IEEE, _I_E_E_E _S_t_a_n_d_a_r_d _f_o_r _I_n_f_o_r_m_a_t_i_o_n _T_e_c_h_n_o_l_o_g_y --
+_P_o_r_t_a_b_l_e _O_p_e_r_a_t_i_n_g _S_y_s_t_e_m _I_n_t_e_r_f_a_c_e (_P_O_S_I_X) _P_a_r_t _2:
+_S_h_e_l_l _a_n_d _U_t_i_l_i_t_i_e_s, 1992.
+
+
+
+
+ July 18, 1994
+
+
+
+
+
+ - 3 -
+
+
+specified as being part of the shell; examples of these are
+_e_v_a_l and _e_x_p_o_r_t. 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
+_r_e_a_d and _t_e_s_t. 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 _v_i-style line editing commands have been standardized;
+_e_m_a_c_s 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 _l_o_g_i_n 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 ._p_r_o_f_i_l_e.
+
+_3. _B_a_s_i_c _B_a_s_h _f_e_a_t_u_r_e_s
+
+ 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 (_f_o_r, _i_f, _w_h_i_l_e,
+etc.). All of the Bourne shell builtins, including those
+not specified in the POSIX.2 standard, appear in Bash.
+Shell _f_u_n_c_t_i_o_n_s, 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 _P_S_1, _I_F_S, and _P_A_T_H. 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|-. 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 _R_A_N_D_O_M and _R_E_P_L_Y, the _t_y_p_e_s_e_t builtin, the ability
+to remove substrings from variables based on patterns, and
+shell arithmetic. _R_A_N_D_O_M expands to a random number each
+time it is referenced; assigning a value to _R_A_N_D_O_M seeds the
+_________________________
+|-Morris Bolsky and David Korn, _T_h_e _K_o_r_n_S_h_e_l_l _C_o_m_m_a_n_d
+_a_n_d _P_r_o_g_r_a_m_m_i_n_g _L_a_n_g_u_a_g_e, Prentice Hall, 1989.
+
+
+
+
+ July 18, 1994
+
+
+
+
+
+ - 4 -
+
+
+random number generator. _R_E_P_L_Y is the default variable used
+by the _r_e_a_d builtin when no variable names are supplied as
+arguments. The _t_y_p_e_s_e_t 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:
+9 $ echo $((3 + 5 * 32))
+ 163
+9
+For interactive use, Bash implements ksh-style aliases and
+builtins such as _f_c (discussed below) and _j_o_b_s. 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)|-, 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 _p_u_s_h_d, _p_o_p_d, and
+_d_i_r_s 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 _c_o_m_m_a_n_d 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 _t_e_s_t 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 _t_e_s_t, and leaves the behavior undefined
+when more arguments are supplied. Bash uses the POSIX.2
+_________________________
+|-Bill Joy, An Introduction to the C Shell, _U_N_I_X _U_s_e_r'_s
+_S_u_p_p_l_e_m_e_n_t_a_r_y _D_o_c_u_m_e_n_t_s, University of California at
+Berkeley, 1986.
+
+
+
+
+ July 18, 1994
+
+
+
+
+
+ - 5 -
+
+
+algorithm, which was conceived by David Korn.
+
+_3._1. _F_e_a_t_u_r_e_s _n_o_t _i_n _t_h_e _B_o_u_r_n_e _S_h_e_l_l
+
+ 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 _c_o_m_m_a_n_d builtin, the ability of the _r_e_a_d builtin
+to correctly return a line ending with a backslash, symbolic
+arguments to the _u_m_a_s_k builtin, variable substring removal,
+a way to get the length of a variable, and the new algorithm
+for the _t_e_s_t 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 $_I_F_S 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.
+
+_4. _B_a_s_h-_s_p_e_c_i_f_i_c _F_e_a_t_u_r_e_s
+
+ 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.
+
+_4._1. _S_t_a_r_t_u_p _F_i_l_e_s
+
+ 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
+~/._b_a_s_h__p_r_o_f_i_l_e (the file .bash_profile in the user's home
+directory), if it exists. An interactive non-login shell
+reads and executes ~/._b_a_s_h_r_c. 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 $_E_N_V, if
+set, as the name of a startup file. The ksh practice of
+reading $_E_N_V 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 $_E_N_V only for interac-
+tive shells.
+
+_4._2. _N_e_w _B_u_i_l_t_i_n _C_o_m_m_a_n_d_s
+
+ There are a few builtins which are new or have been
+extended in Bash. The _e_n_a_b_l_e builtin allows builtin com-
+mands to be turned on and off arbitrarily. To use the ver-
+sion of _e_c_h_o found in a user's search path rather than the
+Bash builtin, enable -n echo suffices. The _h_e_l_p builtin
+provides quick synopses of the shell facilities without
+requiring access to a manual page. _B_u_i_l_t_i_n is similar to
+_c_o_m_m_a_n_d in that it bypasses shell functions and directly
+executes builtin commands. Access to a csh-style stack of
+directories is provided via the _p_u_s_h_d, _p_o_p_d, and _d_i_r_s buil-
+tins. _P_u_s_h_d and _p_o_p_d insert and remove directories from the
+stack, respectively, and _d_i_r_s lists the stack contents. On
+systems that allow fine-grained control of resources, the
+_u_l_i_m_i_t builtin can be used to tune these settings. _U_l_i_m_i_t
+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 _s_u_s_p_e_n_d command
+will stop the shell process when job control is active; most
+other shells do not allow themselves to be stopped like
+that. _T_y_p_e, the Bash answer to _w_h_i_c_h and _w_h_e_n_c_e, shows what
+will happen when a word is typed as a command:
+9 $ 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
+ }
+9
+
+
+ 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 _c_o_m_m_a_n_d utility.
+
+_4._3. _E_d_i_t_i_n_g _a_n_d _C_o_m_p_l_e_t_i_o_n
+
+ One area in which Bash shines is command line editing.
+Bash uses the _r_e_a_d_l_i_n_e 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
+_i_n_p_u_t_r_c file, which defaults to the file ~/._i_n_p_u_t_r_c, 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 _m_e_t_a-_p_r_e_f_i_x 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
+$_P_A_T_H and double-quote the current or previous word:
+9 # Macros that are convenient for shell interaction
+
+
+9 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
+9
+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 _b_i_n_d builtin for more dyamic con-
+trol of readline than the startup file permits. _B_i_n_d is
+used in several ways. In _l_i_s_t 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 _b_a_t_c_h mode, it reads a series of key bindings
+directly from a file and passes them to readline. In its
+most common usage, _b_i_n_d 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_i_n_d.
+
+ The readline library also provides an interface for
+_w_o_r_d _c_o_m_p_l_e_t_i_o_n. When the _c_o_m_p_l_e_t_i_o_n 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.
+
+_4._4. _H_i_s_t_o_r_y
+
+ Access to the list of commands previously entered (the
+_c_o_m_m_a_n_d _h_i_s_t_o_r_y) is provided jointly by Bash and the
+
+
+9 July 18, 1994
+
+
+
+
+
+ - 9 -
+
+
+readline library. Bash provides variables ($HISTFILE,
+$HISTSIZE, and $HISTCONTROL) and the _h_i_s_t_o_r_y and _f_c builtins
+to manipulate the history list. The value of $_H_I_S_T_F_I_L_E
+specifes the file where Bash writes the command history on
+exit and reads it on startup. $_H_I_S_T_S_I_Z_E is used to limit
+the number of commands saved in the history. $_H_I_S_T_C_O_N_T_R_O_L
+provides a crude form of control over which commands are
+saved on the history list: a value of _i_g_n_o_r_e_s_p_a_c_e means to
+not save commands which begin with a space; a value of
+_i_g_n_o_r_e_d_u_p_s 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 _h_i_s_t_o_r_y command can read or
+write files containing the history list and display the
+current list contents. The _f_c 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 _h_i_s_t_o_r_y 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):
+9 $ 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
+9
+The command history is only saved when the shell is interac-
+tive, so it is not available for use by shell scripts.
+
+_4._5. _N_e_w _S_h_e_l_l _V_a_r_i_a_b_l_e_s
+
+ There are a number of convenience variables that Bash
+interprets to make life easier. These include _F_I_G_N_O_R_E,
+which is a set of filename suffixes identifying files to
+exclude when completing filenames; _H_O_S_T_T_Y_P_E, which is
+automatically set to a string describing the type of
+hardware on which Bash is currently executing;
+_c_o_m_m_a_n_d__o_r_i_e_n_t_e_d__h_i_s_t_o_r_y, which directs Bash to save all
+lines of a multiple-line command such as a _w_h_i_l_e or _f_o_r loop
+in a single history entry, allowing easy re-editing; and
+_I_G_N_O_R_E_E_O_F, 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 _a_u_t_o__r_e_s_u_m_e 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.
+
+_4._6. _B_r_a_c_e _E_x_p_a_n_s_i_o_n
+
+ 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 _b_r_a_c_e _e_x_p_a_n_s_i_o_n, 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 _p_r_e_a_m_b_l_e, followed
+by a pair of braces enclosing a series of comma-separated
+strings, and an optional _p_o_s_t_a_m_b_l_e. The preamble is
+prepended to each string within the braces, and the postam-
+ble is then appended to each resulting string:
+9 $ echo a{d,c,b}e
+ ade ace abe
+9
+As this example demonstrates, the results of brace expansion
+are not sorted, as they are by filename expansion.
+
+_4._7. _P_r_o_c_e_s_s _S_u_b_s_t_i_t_u_t_i_o_n
+
+ On systems that can support it, Bash provides a facil-
+ity known as _p_r_o_c_e_s_s _s_u_b_s_t_i_t_u_t_i_o_n. 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 /_d_e_v/_f_d 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:
+9 $ cmp <(old_prog) <(new_prog)
+9
+_4._8. _P_r_o_m_p_t _C_u_s_t_o_m_i_z_a_t_i_o_n
+
+ One of the more popular interactive features that Bash
+provides is the ability to customize the prompt. Both $_P_S_1
+and $_P_S_2, 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., $_S_H_L_V_L, 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 _s_u. Before printing each pri-
+mary prompt, Bash expands the variable $_P_R_O_M_P_T__C_O_M_M_A_N_D 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:
+9 $ PS1='\u@\h [\t] \W($SHLVL:\!)\$ '
+ chet@odin [21:03:44] documentation(2:636)$ cd ..
+ chet@odin [21:03:54] src(2:637)$
+9
+The string being assigned is surrounded by single quotes so
+that if it is exported, the value of $_S_H_L_V_L will be updated
+by a child shell:
+9 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)$
+9
+The \$ escape is displayed as "$" when running as a normal
+user, but as "#" when running as root.
+
+_4._9. _F_i_l_e _S_y_s_t_e_m _V_i_e_w_s
+
+ 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
+_c_d, and the resultant non-intuitive behavior of "cd ..".
+The UNIX kernel treats symbolic links _p_h_y_s_i_c_a_l_l_y. 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 _l_o_g_i_c_a_l view of the file system. In
+this default mode, command and filename completion and buil-
+tin commands such as _c_d and _p_u_s_h_d which change the current
+working directory transparently follow symbolic links as if
+they were directories. The $_P_W_D 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:
+9 $ 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
+9
+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 _p_h_y_s_i_c_a_l view of the file system is available:
+9 $ cd /usr/local/bin
+ $ pwd
+ /usr/local/bin
+ $ set -o physical
+ $ pwd
+ /net/share/sun4/local/bin
+9
+_4._1_0. _I_n_t_e_r_n_a_t_i_o_n_a_l_i_z_a_t_i_o_n
+
+ 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.
+
+_4._1_1. _P_O_S_I_X _M_o_d_e
+
+ 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 _P_O_S_I_X _m_o_d_e.
+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 -_p_o_s_i_x
+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 $_P_O_S_I_X_L_Y__C_O_R_R_E_C_T is set
+when Bash is started or assigned a value during execution.
+$_P_O_S_I_X__P_E_D_A_N_T_I_C 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
+$_E_N_V rather than the "normal" startup files, and does not
+allow reserved words to be aliased.
+
+_5. _N_e_w _F_e_a_t_u_r_e_s _a_n_d _F_u_t_u_r_e _P_l_a_n_s
+
+ 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.
+
+_5._1. _N_e_w _F_e_a_t_u_r_e_s _i_n _B_a_s_h-_1._1_4
+
+ 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 _s_e_t
+-_o _p_o_s_i_x and $_P_O_S_I_X__P_E_D_A_N_T_I_C, are new in version 1.14.
+There is a new shell variable, _O_S_T_Y_P_E, 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: $_H_I_S_T_C_O_N_-
+_T_R_O_L replaces $_h_i_s_t_o_r_y__c_o_n_t_r_o_l, and $_H_O_S_T_F_I_L_E replaces
+$_h_o_s_t_n_a_m_e__c_o_m_p_l_e_t_i_o_n__f_i_l_e. In both cases, the old names are
+accepted for backwards compatibility. The ksh _s_e_l_e_c_t con-
+struct, which allows the generation of simple menus, has
+been implemented. New capabilities have been added to
+existing variables: $_a_u_t_o__r_e_s_u_m_e can now take values of
+_e_x_a_c_t or _s_u_b_s_t_r_i_n_g, and $_H_I_S_T_C_O_N_T_R_O_L understands the value
+_i_g_n_o_r_e_b_o_t_h, which combines the two previously acceptable
+values. The _d_i_r_s builtin has acquired options to print out
+specific members of the directory stack. The $_n_o_l_i_n_k_s vari-
+able, which forces a physical view of the file system, has
+been superseded by the -_P option to the _s_e_t builtin
+(equivalent to set -o physical); the variable is retained
+for backwards compatibility. The version string contained
+in $_B_A_S_H__V_E_R_S_I_O_N now includes an indication of the patch
+level as well as the "build version". Some little-used
+features have been removed: the _b_y_e synonym for _e_x_i_t and
+the $_N_O__P_R_O_M_P_T__V_A_R_S 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 _i_n_f_o
+file has been updated to reflect the current version. As
+always, as many bugs as possible have been fixed, although
+some surely remain.
+
+_5._2. _O_t_h_e_r _F_e_a_t_u_r_e_s
+
+ 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 _v_a_r_n_a_m_e=( ... ) to assign a list of words
+directly to an array and a mechanism to allow the _r_e_a_d buil-
+tin to read a list of values directly into an array, would
+be desirable. Given those extensions, the ksh _s_e_t -_A syntax
+may not be worth supporting (the -_A option assigns a list of
+values to an array, but is a rather peculiar special case).
+
+ Some shells include a means of _p_r_o_g_r_a_m_m_a_b_l_e 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 _H_I_S_T_I_G_-
+_N_O_R_E, which would contain a colon-separated list of com-
+mands. Lines beginning with these commands, after the res-
+trictions of $_H_I_S_T_C_O_N_T_R_O_L 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 $_H_I_S_T_I_G_N_O_R_E.
+
+ One thing that newer shells such as _w_k_s_h (also known as
+_d_t_k_s_h) 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 (_x_x_x__b_u_i_l_t_i_n() 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 _h_e_l_p 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 _g_e_t_c_o_n_f command, which prints the values of sys-
+tem configuration variables defined by POSIX.2, and a _d_i_s_o_w_n
+builtin, which causes a shell running with job control
+active to "forget about" one or more background jobs in its
+internal jobs table. Using _g_e_t_c_o_n_f, for example, a user
+could retrieve a value for $_P_A_T_H 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.
+
+_6. _R_e_f_l_e_c_t_i_o_n_s _a_n_d _L_e_s_s_o_n_s _L_e_a_r_n_e_d
+
+ 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|- 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.|=
+
+The POSIX.2 standard includes a _y_a_c_c 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
+_y_a_c_c-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 $_a_l_l_o_w__n_u_l_l__g_l_o_b__e_x_p_a_n_s_i_o_n and
+$_g_l_o_b__d_o_t__f_i_l_e_n_a_m_e_s 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 _h_e_l_p builtin were external to the
+shell rather than compiled into it. The behavior enabled by
+$_c_o_m_m_a_n_d__o_r_i_e_n_t_e_d__h_i_s_t_o_r_y, 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.
+
+
+_________________________
+|-S. R. Bourne, "UNIX Time-Sharing System: The UNIX
+Shell", _B_e_l_l _S_y_s_t_e_m _T_e_c_h_n_i_c_a_l _J_o_u_r_n_a_l, 57(6), July-
+August, 1978, pp. 1971-1990.
+|=Tom Duff, "Rc - A Shell for Plan 9 and UNIX systems",
+_P_r_o_c. _o_f _t_h_e _S_u_m_m_e_r _1_9_9_0 _E_U_U_G _C_o_n_f_e_r_e_n_c_e, London, July,
+1990, pp. 21-33.
+
+
+
+
+ July 18, 1994
+
+
+
+
+
+ - 17 -
+
+
+_7. _A_v_a_i_l_a_b_i_l_i_t_y
+
+ As with all other GNU software, Bash is available for
+anonymous FTP from _p_r_e_p._a_i._m_i_t._e_d_u:/_p_u_b/_g_n_u and from other
+GNU software mirror sites. The current version is in _b_a_s_h-
+_1._1_4._1._t_a_r._g_z in that directory. Use _a_r_c_h_i_e to find the
+nearest archive site. The latest version is always avail-
+able for FTP from _b_a_s_h._C_W_R_U._E_d_u:/_p_u_b/_d_i_s_t. Bash documenta-
+tion is available for FTP from _b_a_s_h._C_W_R_U._E_d_u:/_p_u_b/_b_a_s_h.
+
+ 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 _p_u_s_h_d/_p_o_p_d/_d_i_r_s, process
+substitution, prompt string special character decoding, and
+the _s_e_l_e_c_t 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.
+
+_8. _C_o_n_c_l_u_s_i_o_n
+
+ 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
index 00000000..9a04b1a3
--- /dev/null
+++ b/documentation/bash.1
@@ -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\\*(]Xu-3p \{\\*(]X
+.br\}
+.el \\*(]X\h|\\n()Iu+\\n()Ru\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
index 00000000..c3a46430
--- /dev/null
+++ b/documentation/bash.ps
@@ -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
index 00000000..c23f2987
--- /dev/null
+++ b/documentation/bash.txt
@@ -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 _K_o_r_n
+ and _C 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 _s_t_r_i_n_g If the -c flag is present, then commands are read
+ from _s_t_r_i_n_g. If there are arguments after the
+ _s_t_r_i_n_g, they are assigned to the positional param-
+ eters, starting with $0.
+ -i If the -i flag is present, the shell is _i_n_t_e_r_a_c_-
+ _t_i_v_e.
+ -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 ~/._b_a_s_h_r_c 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
+ /_e_t_c/_p_r_o_f_i_l_e or any of the personal initialization
+
+
+
+GNU Last change: 1995 May 5 1
+
+
+
+
+
+
+BASH(1) USER COMMANDS BASH(1)
+
+
+
+ files ~/._b_a_s_h__p_r_o_f_i_l_e, ~/._b_a_s_h__l_o_g_i_n, or ~/._p_r_o_-
+ _f_i_l_e. By default, bash normally reads these files
+ when it is invoked as a login shell (see INVOCA-
+ TION below).
+ -rcfile _f_i_l_e
+ Execute commands from _f_i_l_e instead of the standard
+ personal initialization file ~/._b_a_s_h_r_c, 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 _r_e_a_d_l_i_n_e 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 _w_o_r_d 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 _t_o_k_e_n 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
+ _R_e_s_e_r_v_e_d _w_o_r_d_s 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 _s_i_m_p_l_e _c_o_m_m_a_n_d is a sequence of optional variable assign-
+ ments followed by _b_l_a_n_k-separated words and redirections,
+ and terminated by a _c_o_n_t_r_o_l _o_p_e_r_a_t_o_r. 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 _s_i_m_p_l_e _c_o_m_m_a_n_d is its exit status, or
+ 128+_n if the command is terminated by signal _n.
+
+ Pipelines
+ A _p_i_p_e_l_i_n_e is a sequence of one or more commands separated
+ by the character |. The format for a pipeline is:
+
+ [ ! ] _c_o_m_m_a_n_d [ | _c_o_m_m_a_n_d_2 ... ]
+
+ The standard output of _c_o_m_m_a_n_d is connected to the standard
+ input of _c_o_m_m_a_n_d_2. 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 _l_i_s_t 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 _b_a_c_k_g_r_o_u_n_d 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
+
+ _c_o_m_m_a_n_d && _c_o_m_m_a_n_d_2
+
+ _c_o_m_m_a_n_d_2 is executed if, and only if, _c_o_m_m_a_n_d returns an
+ exit status of zero.
+
+ An OR list has the form
+
+ _c_o_m_m_a_n_d || _c_o_m_m_a_n_d_2
+
+ _c_o_m_m_a_n_d_2 is executed if and only if _c_o_m_m_a_n_d 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 _c_o_m_p_o_u_n_d _c_o_m_m_a_n_d is one of the following:
+
+ (_l_i_s_t)
+ _l_i_s_t 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 _l_i_s_t.
+
+ { _l_i_s_t; }
+ _l_i_s_t is simply executed in the current shell environ-
+ ment. This is known as a _g_r_o_u_p _c_o_m_m_a_n_d. The return
+ status is the exit status of _l_i_s_t.
+
+ for _n_a_m_e [ in _w_o_r_d; ] do _l_i_s_t ; done
+ The list of words following in is expanded, generating
+ a list of items. The variable _n_a_m_e is set to each ele-
+ ment of this list in turn, and _l_i_s_t is executed each
+ time. If the in _w_o_r_d is omitted, the for command exe-
+ cutes _l_i_s_t once for each positional parameter that is
+ set (see PARAMETERS below).
+
+ select _n_a_m_e [ in _w_o_r_d; ] do _l_i_s_t ; 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 _w_o_r_d 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 _n_a_m_e 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 _n_a_m_e to be set to
+ null. The line read is saved in the variable REPLY.
+ The _l_i_s_t 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 _l_i_s_t, or zero if no commands were executed.
+
+ case _w_o_r_d in [ _p_a_t_t_e_r_n [ | _p_a_t_t_e_r_n ] ... ) _l_i_s_t ;; ] ... esac
+ A case command first expands _w_o_r_d, and tries to match
+ it against each _p_a_t_t_e_r_n in turn, using the same match-
+ ing rules as for pathname expansion (see Pathname
+ Expansion below). When a match is found, the
+ corresponding _l_i_s_t 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 _l_i_s_t.
+
+ if _l_i_s_t then _l_i_s_t [ elif _l_i_s_t then _l_i_s_t ] ... [ else _l_i_s_t ] fi
+ The if _l_i_s_t is executed. If its exit status is zero,
+ the then _l_i_s_t is executed. Otherwise, each elif _l_i_s_t
+ is executed in turn, and if its exit status is zero,
+ the corresponding then _l_i_s_t is executed and the command
+ completes. Otherwise, the else _l_i_s_t is executed, if
+ present. The exit status is the exit status of the
+ last command executed, or zero if no condition tested
+ true.
+
+ while _l_i_s_t do _l_i_s_t done
+ until _l_i_s_t do _l_i_s_t done
+ The while command continuously executes the do _l_i_s_t as
+ long as the last command in _l_i_s_t returns an exit status
+ of zero. The until command is identical to the while
+ command, except that the test is negated; the do _l_i_s_t
+ is executed as long as the last command in _l_i_s_t returns
+ a non-zero exit status. The exit status of the while
+ and until commands is the exit status of the last do
+ _l_i_s_t command executed, or zero if none was executed.
+
+ [ function ] _n_a_m_e () { _l_i_s_t; }
+ This defines a function named _n_a_m_e. The _b_o_d_y of the
+ function is the _l_i_s_t of commands between { and }. This
+ list is executed whenever _n_a_m_e 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
+ _Q_u_o_t_i_n_g 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 _m_e_t_a_c_h_a_r_a_c_t_e_r_s 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 _e_s_c_a_p_e _c_h_a_r_a_c_t_e_r, single quotes, and double
+ quotes.
+
+ A non-quoted backslash (\) is the _e_s_c_a_p_e _c_h_a_r_a_c_t_e_r. 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 _p_a_r_a_m_e_t_e_r is an entity that stores values, somewhat like a
+ variable in a conventional programming language. It can be
+ a _n_a_m_e, a number, or one of the special characters listed
+ below under Special Parameters. For the shell's purposes, a
+ _v_a_r_i_a_b_l_e is a parameter denoted by a _n_a_m_e.
+
+ 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 _v_a_r_i_a_b_l_e may be assigned to by a statement of the form
+
+ _n_a_m_e=[_v_a_l_u_e]
+
+ If _v_a_l_u_e is not given, the variable is assigned the null
+ string. All _v_a_l_u_e_s 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
+ _v_a_l_u_e 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 _p_o_s_i_t_i_o_n_a_l _p_a_r_a_m_e_t_e_r 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_c$2_c...'', where _c 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
+ _s_i_m_p_l_e _c_o_m_m_a_n_d_s 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 _I_n_t_e_r_n_a_l _F_i_e_l_d _S_e_p_a_r_a_t_o_r 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 ._b_a_s_h_r_c.
+ 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 _m_a_i_l_f_i_l_e 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 _s_e_l_e_c_t 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
+ ~/._b_a_s_h__h_i_s_t_o_r_y. 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 ~/._i_n_p_u_t_r_c (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 _i_g_n_o_r_e_s_p_a_c_e, lines which begin
+ with a space character are not entered on the history
+ list. If set to a value of _i_g_n_o_r_e_d_u_p_s, lines matching
+ the last history line are not entered. A value of
+ _i_g_n_o_r_e_b_o_t_h 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 _h_i_s_t_o_r_y _e_x_p_a_n_s_i_o_n
+ _c_h_a_r_a_c_t_e_r, that is, the character which signals the
+ start of a history expansion, normally `!'. The second
+ character is the _q_u_i_c_k _s_u_b_s_t_i_t_u_t_i_o_n 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
+ /_e_t_c/_h_o_s_t_s 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 _n_a_m_e of a
+ stopped job, in this context, is the command line used
+ to start it. If set to the value _e_x_a_c_t, the string
+ supplied must match the name of a stopped job exactly;
+ if set to _s_u_b_s_t_r_i_n_g, the string supplied needs to match
+ a substring of the name of a stopped job. The _s_u_b_-
+ _s_t_r_i_n_g 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: _b_r_a_c_e _e_x_p_a_n_s_i_o_n, _t_i_l_d_e _e_x_p_a_n_s_i_o_n, _p_a_r_a_m_e_t_e_r _a_n_d
+ _v_a_r_i_a_b_l_e _e_x_p_a_n_s_i_o_n, _c_o_m_m_a_n_d _s_u_b_s_t_i_t_u_t_i_o_n, _a_r_i_t_h_m_e_t_i_c _e_x_p_a_n_-
+ _s_i_o_n, _w_o_r_d _s_p_l_i_t_t_i_n_g, and _p_a_t_h_n_a_m_e _e_x_p_a_n_s_i_o_n.
+
+
+
+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: _p_r_o_c_e_s_s _s_u_b_s_t_i_t_u_t_i_o_n.
+
+ 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
+ _B_r_a_c_e _e_x_p_a_n_s_i_o_n is a mechanism by which arbitrary strings
+ may be generated. This mechanism is similar to _p_a_t_h_n_a_m_e
+ _e_x_p_a_n_s_i_o_n, but the filenames generated need not exist. Pat-
+ terns to be brace expanded take the form of an optional
+ _p_r_e_a_m_b_l_e, followed by a series of comma-separated strings
+ between a pair of braces, followed by an optional _p_o_s_t_a_m_b_l_e.
+ 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 _f_i_l_e{_1,_2}
+ appears identically in the output. The same word is output
+ as _f_i_l_e_1 _f_i_l_e_2 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 _l_o_g_i_n _n_a_m_e. If
+ this _l_o_g_i_n _n_a_m_e 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
+ _l_o_g_i_n _n_a_m_e, the tilde and _l_o_g_i_n _n_a_m_e 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.
+
+ ${_p_a_r_a_m_e_t_e_r}
+ The value of _p_a_r_a_m_e_t_e_r is substituted. The braces are
+ required when _p_a_r_a_m_e_t_e_r is a positional parameter with
+ more than one digit, or when _p_a_r_a_m_e_t_e_r is followed by a
+ character which is not to be interpreted as part of its
+ name.
+
+ In each of the cases below, _w_o_r_d 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)
+
+
+
+ ${_p_a_r_a_m_e_t_e_r:-_w_o_r_d}
+ Use Default Values. If _p_a_r_a_m_e_t_e_r is unset or null, the
+ expansion of _w_o_r_d is substituted. Otherwise, the value
+ of _p_a_r_a_m_e_t_e_r is substituted.
+ ${_p_a_r_a_m_e_t_e_r:=_w_o_r_d}
+ Assign Default Values. If _p_a_r_a_m_e_t_e_r is unset or null,
+ the expansion of _w_o_r_d is assigned to _p_a_r_a_m_e_t_e_r. The
+ value of _p_a_r_a_m_e_t_e_r is then substituted. Positional
+ parameters and special parameters may not be assigned
+ to in this way.
+ ${_p_a_r_a_m_e_t_e_r:?_w_o_r_d}
+ Display Error if Null or Unset. If _p_a_r_a_m_e_t_e_r is null
+ or unset, the expansion of _w_o_r_d (or a message to that
+ effect if _w_o_r_d is not present) is written to the stan-
+ dard error and the shell, if it is not interactive,
+ exits. Otherwise, the value of _p_a_r_a_m_e_t_e_r is substi-
+ tuted.
+ ${_p_a_r_a_m_e_t_e_r:+_w_o_r_d}
+ Use Alternate Value. If _p_a_r_a_m_e_t_e_r is null or unset,
+ nothing is substituted, otherwise the expansion of _w_o_r_d
+ is substituted.
+ ${#_p_a_r_a_m_e_t_e_r}
+ The length in characters of the value of _p_a_r_a_m_e_t_e_r is
+ substituted. If _p_a_r_a_m_e_t_e_r is * or @, the length sub-
+ stituted is the length of * expanded within double
+ quotes.
+ ${_p_a_r_a_m_e_t_e_r#_w_o_r_d}
+ ${_p_a_r_a_m_e_t_e_r##_w_o_r_d}
+ The _w_o_r_d is expanded to produce a pattern just as in
+ pathname expansion. If the pattern matches the begin-
+ ning of the value of _p_a_r_a_m_e_t_e_r, then the expansion is
+ the value of _p_a_r_a_m_e_t_e_r with the shortest matching pat-
+ tern deleted (the ``#'' case) or the longest matching
+ pattern deleted (the ``##'' case).
+
+ ${_p_a_r_a_m_e_t_e_r%_w_o_r_d}
+ ${_p_a_r_a_m_e_t_e_r%%_w_o_r_d}
+ The _w_o_r_d is expanded to produce a pattern just as in
+ pathname expansion. If the pattern matches a trailing
+ portion of the value of _p_a_r_a_m_e_t_e_r, then the expansion
+ is the value of _p_a_r_a_m_e_t_e_r with the shortest matching
+ pattern deleted (the ``%'' case) or the longest match-
+ ing pattern deleted (the ``%%'' case).
+
+ Command Substitution
+ _C_o_m_m_a_n_d _s_u_b_s_t_i_t_u_t_i_o_n allows the output of a command to
+ replace the command name. There are two forms:
+
+ $(_c_o_m_m_a_n_d)
+ or
+ `_c_o_m_m_a_n_d`
+
+
+
+
+GNU Last change: 1995 May 5 16
+
+
+
+
+
+
+BASH(1) USER COMMANDS BASH(1)
+
+
+
+ Bash performs the expansion by executing _c_o_m_m_a_n_d 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 $(_c_o_m_m_a_n_d) 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:
+
+ $[_e_x_p_r_e_s_s_i_o_n]
+
+ $((_e_x_p_r_e_s_s_i_o_n))
+
+ The _e_x_p_r_e_s_s_i_o_n 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 _e_x_p_r_e_s_s_i_o_n is
+ invalid, bash prints a message indicating failure and no
+ substitution occurs.
+
+ Process Substitution
+ _P_r_o_c_e_s_s _s_u_b_s_t_i_t_u_t_i_o_n is supported on systems that support
+ named pipes (_F_I_F_O_s) or the /dev/fd method of naming open
+ files. It takes the form of <(_l_i_s_t) or >(_l_i_s_t). The pro-
+ cess _l_i_s_t is run with its input or output connected to a
+ _F_I_F_O 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 >(_l_i_s_t) form is used, writing to
+ the file will provide input for _l_i_s_t. If the <(_l_i_s_t) form
+ is used, the file passed as an argument should be read to
+ obtain the output of _l_i_s_t.
+
+ On systems that support it, _p_r_o_c_e_s_s _s_u_b_s_t_i_t_u_t_i_o_n is per-
+ formed simultaneously with _p_a_r_a_m_e_t_e_r _a_n_d _v_a_r_i_a_b_l_e _e_x_p_a_n_s_i_o_n,
+ _c_o_m_m_a_n_d _s_u_b_s_t_i_t_u_t_i_o_n, and _a_r_i_t_h_m_e_t_i_c _e_x_p_a_n_s_i_o_n.
+
+
+
+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 _w_o_r_d _s_p_l_i_t_t_i_n_g.
+
+ 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 _p_a_r_a_m_e_t_e_r_s
+ 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 _w_o_r_d for the characters *, ?, and [. If one
+ of these characters appears, then the word is regarded as a
+ _p_a_t_t_e_r_n, 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 _r_a_n_g_e;
+ 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
+ _r_e_d_i_r_e_c_t_e_d 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 _s_i_m_p_l_e _c_o_m_m_a_n_d or may follow a _c_o_m_m_a_n_d. 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
+ _d_i_r_l_i_s_t, while the command
+
+ ls 2>&1 > dirlist
+
+ directs only the standard output to file _d_i_r_l_i_s_t, because
+ the standard error was duplicated as standard output before
+ the standard output was redirected to _d_i_r_l_i_s_t.
+
+ Redirecting Input
+ Redirection of input causes the file whose name results from
+ the expansion of _w_o_r_d to be opened for reading on file
+ descriptor _n, or the standard input (file descriptor 0) if _n
+ is not specified.
+
+ The general format for redirecting input is:
+
+
+
+
+
+GNU Last change: 1995 May 5 19
+
+
+
+
+
+
+BASH(1) USER COMMANDS BASH(1)
+
+
+
+ [_n]<_w_o_r_d
+
+ Redirecting Output
+ Redirection of output causes the file whose name results
+ from the expansion of _w_o_r_d to be opened for writing on file
+ descriptor _n, or the standard output (file descriptor 1) if
+ _n is not specified. If the file does not exist it is
+ created; if it does exist it is truncated to zero size.
+
+ The general format for redirecting output is:
+
+ [_n]>_w_o_r_d
+
+ 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 _w_o_r_d to be opened for
+ appending on file descriptor _n, or the standard output (file
+ descriptor 1) if _n is not specified. If the file does not
+ exist it is created.
+
+ The general format for appending output is:
+
+ [_n]>>_w_o_r_d
+
+ 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 _w_o_r_d
+ with this construct.
+
+ There are two formats for redirecting standard output and
+ standard error:
+
+ &>_w_o_r_d
+ and
+ >&_w_o_r_d
+
+ Of the two forms, the first is preferred. This is semanti-
+ cally equivalent to
+
+ >_w_o_r_d 2>&1
+
+ Here Documents
+ This type of redirection instructs the shell to read input
+ from the current source until a line containing only _w_o_r_d
+ (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:
+
+ <<[-]_w_o_r_d
+ _h_e_r_e-_d_o_c_u_m_e_n_t
+ _d_e_l_i_m_i_t_e_r
+
+ No parameter expansion, command substitution, pathname
+ expansion, or arithmetic expansion is performed on _w_o_r_d. If
+ any characters in _w_o_r_d are quoted, the _d_e_l_i_m_i_t_e_r is the
+ result of quote removal on _w_o_r_d, 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 _d_e_l_i_m_i_t_e_r. This allows here-documents within shell
+ scripts to be indented in a natural fashion.
+
+ Duplicating File Descriptors
+ The redirection operator
+
+ [_n]<&_w_o_r_d
+
+ is used to duplicate input file descriptors. If _w_o_r_d
+ expands to one or more digits, the file descriptor denoted
+ by _n is made to be a copy of that file descriptor. If _w_o_r_d
+ evaluates to -, file descriptor _n is closed. If _n is not
+ specified, the standard input (file descriptor 0) is used.
+
+ The operator
+
+ [_n]>&_w_o_r_d
+
+ is used similarly to duplicate output file descriptors. If
+ _n is not specified, the standard output (file descriptor 1)
+ is used. As a special case, if _n is omitted, and _w_o_r_d 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
+
+ [_n]<>_w_o_r_d
+
+ causes the file whose name is the expansion of _w_o_r_d to be
+ opened for both reading and writing on file descriptor _n, or
+ as the standard input and standard output if _n 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 _a_l_i_a_s_e_s 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 _m_e_t_a_c_h_a_r_a_c_t_e_r_s 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 _b_l_a_n_k, 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
+ _J_o_b _c_o_n_t_r_o_l refers to the ability to selectively stop
+ (_s_u_s_p_e_n_d) the execution of processes and continue (_r_e_s_u_m_e)
+ 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 _j_o_b 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 _b_a_c_k_g_r_o_u_n_d), 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 _j_o_b
+ 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 _c_u_r_r_e_n_t
+ _t_e_r_m_i_n_a_l _p_r_o_c_e_s_s _g_r_o_u_p _I_D. 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)
+
+
+
+ _f_o_r_e_g_r_o_u_n_d. _B_a_c_k_g_r_o_u_n_d 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 _s_u_s_p_e_n_d
+ character (typically ^Z, Control-Z) while a process is run-
+ ning causes that process to be stopped and returns you to
+ bash. Typing the _d_e_l_a_y_e_d _s_u_s_p_e_n_d 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. 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 _c_u_r_r_e_n_t _j_o_b, which is the last job
+ stopped while it was in the foreground. The _p_r_e_v_i_o_u_s _j_o_b
+ 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 _s_h_e_l_l _s_c_r_i_p_t, 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 _e_n_v_i_r_o_n_m_e_n_t. This is a list of _n_a_m_e-_v_a_l_u_e pairs,
+ of the form _n_a_m_e=_v_a_l_u_e.
+
+ 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 _e_x_p_o_r_t 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 _s_i_m_p_l_e _c_o_m_m_a_n_d 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 _a_l_l 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-_k_e_y, e.g., C-n
+ means Control-N. Similarly, _m_e_t_a keys are denoted by M-_k_e_y,
+
+
+
+GNU Last change: 1995 May 5 27
+
+
+
+
+
+
+BASH(1) USER COMMANDS BASH(1)
+
+
+
+ so M-x means Meta-X. (On keyboards without a _m_e_t_a key, M-_x
+ means ESC _x, i.e., press the Escape key then the _x key.
+ This makes ESC the _m_e_t_a _p_r_e_f_i_x. The combination M-C-_x means
+ ESC-Control-_x, or press the Escape key then hold the Control
+ key while pressing the _x key.)
+
+ The default key-bindings may be changed with an ~/._i_n_p_u_t_r_c
+ file. The value of the shell variable INPUTRC, if set, is
+ used instead of ~/._i_n_p_u_t_r_c. 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 ~/._i_n_p_u_t_r_c would make M-C-u execute the readline
+ command _u_n_i_v_e_r_s_a_l-_a_r_g_u_m_e_n_t.
+
+ The following symbolic character names are recognized:
+ _R_U_B_O_U_T, _D_E_L, _E_S_C, _L_F_D, _N_E_W_L_I_N_E, _R_E_T, _R_E_T_U_R_N, _S_P_C, _S_P_A_C_E, and
+ _T_A_B. In addition to command names, readline allows keys to
+ be bound to a string that is inserted when the key is
+ pressed (a _m_a_c_r_o).
+
+ 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 ~/._i_n_p_u_t_r_c. 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 ~/._i_n_p_u_t_r_c
+ 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 _M_e_t_a- or
+ _C_o_n_t_r_o_l- prefixes, or as a key sequence. When using the
+ form keyname:_f_u_n_c_t_i_o_n-_n_a_m_e or _m_a_c_r_o, _k_e_y_n_a_m_e 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, _M-_D_E_L is bound to the function
+ backward-kill-word, and _C-_o 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 >&_o_u_t_p_u_t into the line).
+
+ In the second form, "keyseq":_f_u_n_c_t_i_o_n-_n_a_m_e or _m_a_c_r_o, 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, _C-_u is again bound to the function
+ universal-argument. _C-_x _C-_r is bound to the function
+ re-read-init-file, and _E_S_C [ _1 _1 ~ 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 _i_n_p_u_t_r_c file
+ with a statement of the form
+
+ set _v_a_r_i_a_b_l_e-_n_a_m_e _v_a_l_u_e
+
+ 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 _e_m_a_c_s or _v_i. 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 _m_e_t_a _p_r_e_f_i_x).
+ 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 _e_m_a_c_s, _e_m_a_c_s-_s_t_a_n_d_a_r_d, _e_m_a_c_s-_m_e_t_a, _e_m_a_c_s-
+ _c_t_l_x, _v_i, _v_i-_m_o_v_e, _v_i-_c_o_m_m_a_n_d, and _v_i-_i_n_s_e_r_t. _v_i is
+ equivalent to _v_i-_c_o_m_m_a_n_d; _e_m_a_c_s is equivalent to
+ _e_m_a_c_s-_s_t_a_n_d_a_r_d. The default value is _e_m_a_c_s; 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
+ _e_m_a_c_s-_s_t_a_n_d_a_r_d and _e_m_a_c_s-_c_t_l_x 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 _s_u_n to match both _s_u_n and _s_u_n-_c_m_d, for
+ instance.
+
+ application
+ The application construct is used to include
+ application-specific settings. Each program using
+ the readline library sets the _a_p_p_l_i_c_a_t_i_o_n _n_a_m_e,
+ 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 _a_r_g_u_m_e_n_t_s, 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 _k_i_l_l_i_n_g text, the text
+ deleted is saved for possible future retrieval (_y_a_n_k_i_n_g).
+ The killed text is saved in a _k_i_l_l-_r_i_n_g. 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 _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 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 _i_n_p_u_t_r_c 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 _c_o_m_m_a_n_d
+ _h_i_s_t_o_r_y, 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 ~/._b_a_s_h__h_i_s_t_o_r_y). 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 _e_v_e_n_t, and the portions of that line that are
+ acted upon are _w_o_r_d_s. The line is broken into words in the
+ same fashion as when reading input, so that several
+ _m_e_t_a_c_h_a_r_a_c_t_e_r-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'.
+ !_n Refer to command line _n.
+ !-_n Refer to the current command line minus _n.
+ !_s_t_r_i_n_g
+ Refer to the most recent command starting with _s_t_r_i_n_g.
+ !?_s_t_r_i_n_g[?]
+ Refer to the most recent command containing _s_t_r_i_n_g.
+9 ^8_s_t_r_i_n_g_19^8_s_t_r_i_n_g_29^
+8 Quick substitution. Repeat the last command, replacing
+ _s_t_r_i_n_g_1 with _s_t_r_i_n_g_2. Equivalent to
+
+
+
+GNU Last change: 1995 May 5 38
+
+
+
+
+
+
+BASH(1) USER COMMANDS BASH(1)
+
+
+
+ ``!!:s/_s_t_r_i_n_g_1/_s_t_r_i_n_g_2/'' (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.
+ _n The _nth word.
+ ^ The first argument. That is, word 1.
+ $ The last argument.
+ % The word matched by the most recent `?_s_t_r_i_n_g?' search.
+ _x-_y A range of words; `-_y' abbreviates `0-_y'.
+ * All of the words but the zeroth. 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.
+
+ 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 ._x_x_x, 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/_o_l_d/_n_e_w/
+ Substitute _n_e_w for the first occurrence of _o_l_d 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 _o_l_d and _n_e_w with a single backslash. If & appears
+ in _n_e_w, it is replaced by _o_l_d. 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/_o_l_d/_n_e_w/') 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 _0_x or _0_X denotes hexadecimal. Otherwise, numbers
+ take the form [_b_a_s_e#]n, where _b_a_s_e is a decimal number
+ between 2 and 36 representing the arithmetic base, and _n is
+ a number in that base. If _b_a_s_e 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
+ : [_a_r_g_u_m_e_n_t_s]
+
+
+
+GNU Last change: 1995 May 5 40
+
+
+
+
+
+
+BASH(1) USER COMMANDS BASH(1)
+
+
+
+ No effect; the command does nothing beyond expanding
+ _a_r_g_u_m_e_n_t_s and performing any specified redirections. A
+ zero exit code is returned.
+
+ . _f_i_l_e_n_a_m_e [_a_r_g_u_m_e_n_t_s]
+ source _f_i_l_e_n_a_m_e [_a_r_g_u_m_e_n_t_s]
+ Read and execute commands from _f_i_l_e_n_a_m_e in the current
+ shell environment and return the exit status of the
+ last command executed from _f_i_l_e_n_a_m_e. If _f_i_l_e_n_a_m_e does
+ not contain a slash, pathnames in PATH are used to find
+ the directory containing _f_i_l_e_n_a_m_e. 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
+ _a_r_g_u_m_e_n_t_s are supplied, they become the positional
+ parameters when _f_i_l_e 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 _f_i_l_e_n_a_m_e
+ is not found.
+
+ alias [_n_a_m_e[=_v_a_l_u_e] ...]
+ Alias with no arguments prints the list of aliases in
+ the form _n_a_m_e=_v_a_l_u_e on standard output. When arguments
+ are supplied, an alias is defined for each _n_a_m_e whose
+ _v_a_l_u_e is given. A trailing space in _v_a_l_u_e causes the
+ next word to be checked for alias substitution when the
+ alias is expanded. For each _n_a_m_e in the argument list
+ for which no _v_a_l_u_e is supplied, the name and value of
+ the alias is printed. Alias returns true unless a _n_a_m_e
+ is given for which no alias has been defined.
+
+ bg [_j_o_b_s_p_e_c]
+ Place _j_o_b_s_p_e_c in the background, as if it had been
+ started with &. If _j_o_b_s_p_e_c is not present, the shell's
+ notion of the _c_u_r_r_e_n_t _j_o_b is used. bg _j_o_b_s_p_e_c returns
+ 0 unless run when job control is disabled or, when run
+ with job control enabled, if _j_o_b_s_p_e_c was not found or
+ started without job control.
+
+ bind [-m _k_e_y_m_a_p] [-lvd] [-q _n_a_m_e]
+ bind [-m _k_e_y_m_a_p] -f _f_i_l_e_n_a_m_e
+ bind [-m _k_e_y_m_a_p] _k_e_y_s_e_q:_f_u_n_c_t_i_o_n-_n_a_m_e
+ 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
+ ._i_n_p_u_t_r_c, 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 _k_e_y_m_a_p
+ Use _k_e_y_m_a_p as the keymap to be affected by the
+ subsequent bindings. Acceptable _k_e_y_m_a_p names are
+ _e_m_a_c_s, _e_m_a_c_s-_s_t_a_n_d_a_r_d, _e_m_a_c_s-_m_e_t_a, _e_m_a_c_s-_c_t_l_x, _v_i,
+
+
+
+GNU Last change: 1995 May 5 41
+
+
+
+
+
+
+BASH(1) USER COMMANDS BASH(1)
+
+
+
+ _v_i-_m_o_v_e, _v_i-_c_o_m_m_a_n_d, and _v_i-_i_n_s_e_r_t. _v_i is
+ equivalent to _v_i-_c_o_m_m_a_n_d; _e_m_a_c_s is equivalent to
+ _e_m_a_c_s-_s_t_a_n_d_a_r_d.
+ -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 _f_i_l_e_n_a_m_e
+ Read key bindings from _f_i_l_e_n_a_m_e
+ -q _f_u_n_c_t_i_o_n
+ Query about which keys invoke the named _f_u_n_c_t_i_o_n
+
+ The return value is 0 unless an unrecognized option is
+ given or an error occurred.
+
+ break [_n]
+ Exit from within a for, while, or until loop. If _n is
+ specified, break _n levels. _n must be >_ 1. If _n 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 _s_h_e_l_l-_b_u_i_l_t_i_n [_a_r_g_u_m_e_n_t_s]
+ Execute the specified shell builtin, passing it _a_r_g_u_-
+ _m_e_n_t_s, 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 _s_h_e_l_l-_b_u_i_l_t_i_n is not a shell builtin command.
+
+ cd [_d_i_r]
+ Change the current directory to _d_i_r. The variable HOME
+ is the default _d_i_r. The variable CDPATH defines the
+ search path for the directory containing _d_i_r. 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 _d_i_r 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] _c_o_m_m_a_n_d [_a_r_g ...]
+ Run _c_o_m_m_a_n_d with _a_r_g_s 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 _c_o_m_m_a_n_d 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 _c_o_m_m_a_n_d 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 _c_o_m_m_a_n_d 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 _c_o_m_m_a_n_d was found,
+ and 1 if not. If neither option is supplied and an
+ error occurred or _c_o_m_m_a_n_d cannot be found, the exit
+ status is 127. Otherwise, the exit status of the com-
+ mand builtin is the exit status of _c_o_m_m_a_n_d.
+
+ continue [_n]
+ Resume the next iteration of the enclosing for, while,
+ or until loop. If _n is specified, resume at the _nth
+ enclosing loop. _n must be >_ 1. If _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 con-
+ tinue is executed.
+
+ declare [-frxi] [_n_a_m_e[=_v_a_l_u_e]]
+ typeset [-frxi] [_n_a_m_e[=_v_a_l_u_e]]
+ Declare variables and/or give them attributes. If no
+ _n_a_m_es 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 _n_a_m_es readonly. These names cannot then be
+ assigned values by subsequent assignment state-
+ ments.
+ -x Mark _n_a_m_es 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 _n_a_m_es 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 _n_a_m_e_s 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 _nth 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 _nth 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 _n indexes beyond the end of the directory
+ stack.
+
+ echo [-neE] [_a_r_g ...]
+ Output the _a_r_gs, 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 _n_n_n (octal)
+
+ enable [-n] [-all] [_n_a_m_e ...]
+ 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 _n_a_m_e is disabled; otherwise, _n_a_m_e_s
+ 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 _n_a_m_e is not a
+ shell builtin.
+
+ eval [_a_r_g ...]
+ The _a_r_gs 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 _a_r_g_s, or only
+ null arguments, eval returns true.
+
+
+
+
+GNU Last change: 1995 May 5 44
+
+
+
+
+
+
+BASH(1) USER COMMANDS BASH(1)
+
+
+
+ exec [[-] _c_o_m_m_a_n_d [_a_r_g_u_m_e_n_t_s]]
+ If _c_o_m_m_a_n_d is specified, it replaces the shell. No new
+ process is created. The _a_r_g_u_m_e_n_t_s become the arguments
+ to _c_o_m_m_a_n_d. If the first argument is -, the shell
+ places a dash in the zeroth arg passed to _c_o_m_m_a_n_d.
+ 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 _c_o_m_m_a_n_d is not specified, any redirections
+ take effect in the current shell, and the return status
+ is 0.
+
+ exit [_n]
+ Cause the shell to exit with a status of _n. If _n is
+ omitted, the exit status is that of the last command
+ executed. A trap on EXIT is executed before the shell
+ terminates.
+
+ export [-nf] [_n_a_m_e[=_w_o_r_d]] ...
+ export -p
+ The supplied _n_a_m_e_s are marked for automatic export to
+ the environment of subsequently executed commands. If
+ the -f option is given, the _n_a_m_e_s refer to functions.
+ If no _n_a_m_e_s 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 _n_a_m_e_s is not a legal
+ shell variable name, or -f is supplied with a _n_a_m_e that
+ is not a function.
+
+ fc [-e _e_n_a_m_e] [-nlr] [_f_i_r_s_t] [_l_a_s_t]
+ fc -s [_p_a_t=_r_e_p] [_c_m_d]
+ Fix Command. In the first form, a range of commands
+ from _f_i_r_s_t to _l_a_s_t is selected from the history list.
+ _F_i_r_s_t and _l_a_s_t 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 _l_a_s_t is not specified it is set to
+ the current command for listing (so that fc -l -10
+ prints the last 10 commands) and to _f_i_r_s_t otherwise.
+ If _f_i_r_s_t 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 _e_n_a_m_e
+ is invoked on a file containing those commands. If
+ _e_n_a_m_e 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, _v_i is used. When editing is
+ complete, the edited commands are echoed and executed.
+
+ In the second form, _c_o_m_m_a_n_d is re-executed after each
+ instance of _p_a_t is replaced by _r_e_p. 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 _f_i_r_s_t or _l_a_s_t
+ 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 _c_m_d does not specify a valid history
+ line, in which case fc returns failure.
+
+ fg [_j_o_b_s_p_e_c]
+ Place _j_o_b_s_p_e_c in the foreground, and make it the
+ current job. If _j_o_b_s_p_e_c is not present, the shell's
+ notion of the _c_u_r_r_e_n_t _j_o_b 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 _j_o_b_s_p_e_c does not
+ specify a valid job or _j_o_b_s_p_e_c specifies a job that was
+ started without job control.
+
+ getopts _o_p_t_s_t_r_i_n_g _n_a_m_e [_a_r_g_s]
+ getopts is used by shell procedures to parse positional
+ parameters. _o_p_t_s_t_r_i_n_g 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 _n_a_m_e, initializing _n_a_m_e 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 _o_p_t_s_t_r_i_n_g is a colon, _s_i_l_e_n_t 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 _o_p_t_s_t_r_i_n_g is not a
+ colon.
+
+ If an illegal option is seen, getopts places ? into
+ _n_a_m_e 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 _n_a_m_e, OPTARG
+ is unset, and a diagnostic message is printed. If
+ getopts is silent, then a colon (:) is placed in _n_a_m_e
+ and OPTARG is set to the option character found.
+
+ getopts normally parses the positional parameters, but
+ if more arguments are given in _a_r_g_s, 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] [_n_a_m_e]
+ For each _n_a_m_e, 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 _n_a_m_e is not found or an illegal option is
+ supplied.
+
+ help [_p_a_t_t_e_r_n]
+ Display helpful information about builtin commands. If
+ _p_a_t_t_e_r_n is specified, help gives detailed help on all
+ commands matching _p_a_t_t_e_r_n; otherwise a list of the
+ builtins is printed. The return status is 0 unless no
+ command matches _p_a_t_t_e_r_n.
+
+ history [_n]
+ history -rwan [_f_i_l_e_n_a_m_e]
+ With no options, display the command history list with
+ line numbers. Lines listed with a * have been modi-
+ fied. An argument of _n lists only the last _n 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] [ _j_o_b_s_p_e_c ... ]
+ jobs -x _c_o_m_m_a_n_d [ _a_r_g_s ... ]
+ 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 _j_o_b_s_p_e_c 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 _j_o_b_s_p_e_c is
+ supplied.
+
+ If the -x option is supplied, jobs replaces any _j_o_b_s_p_e_c
+ found in _c_o_m_m_a_n_d or _a_r_g_s with the corresponding process
+ group ID, and executes _c_o_m_m_a_n_d passing it _a_r_g_s, return-
+ ing its exit status.
+
+ kill [-s sigspec | -sigspec] [_p_i_d | _j_o_b_s_p_e_c] ...
+ kill -l [_s_i_g_n_u_m]
+ Send the signal named by _s_i_g_s_p_e_c to the processes named
+ by _p_i_d or _j_o_b_s_p_e_c. _s_i_g_s_p_e_c is either a signal name
+ such as SIGKILL or a signal number. If _s_i_g_s_p_e_c is a
+ signal name, the name is case insensitive and may be
+ given with or without the SIG prefix. If _s_i_g_s_p_e_c 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 _a_r_g [_a_r_g ...]
+ Each _a_r_g is an arithmetic expression to be evaluated
+ (see ARITHMETIC EVALUATION). If the last _a_r_g evaluates
+
+
+
+GNU Last change: 1995 May 5 48
+
+
+
+
+
+
+BASH(1) USER COMMANDS BASH(1)
+
+
+
+ to 0, let returns 1; 0 is returned otherwise.
+
+ local [_n_a_m_e[=_v_a_l_u_e] ...]
+ For each argument, create a local variable named _n_a_m_e,
+ and assign it _v_a_l_u_e. When local is used within a func-
+ tion, it causes the variable _n_a_m_e 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 _n_a_m_e 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 _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.
+
+ 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 [_d_i_r]
+ 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 _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 _d_i_r 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 _d_i_r 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] [_n_a_m_e ...]
+ One line is read from the standard input, and the first
+ word is assigned to the first _n_a_m_e, the second word to
+ the second _n_a_m_e, and so on, with leftover words
+ assigned to the last _n_a_m_e. Only the characters in IFS
+ are recognized as word delimiters. If no _n_a_m_e_s 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] [_n_a_m_e ...]
+ readonly -p
+ The given _n_a_m_e_s are marked readonly and the values of
+ these _n_a_m_e_s may not be changed by subsequent assign-
+ ment. If the -f option is supplied, the functions
+ corresponding to the _n_a_m_e_s 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 _n_a_m_e_s is not a legal shell
+ variable name, or -f is supplied with a _n_a_m_e that is
+ not a function.
+
+ return [_n]
+ Causes a function to exit with the return value speci-
+ fied by _n. If _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 . (source) command, it causes the shell
+ to stop executing that script and return either _n 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 _o_p_t_i_o_n] [_a_r_g ...]
+ -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 _s_i_m_p_l_e-_c_o_m_m_a_n_d (see SHELL
+ GRAMMAR above) exits with a non-zero status.
+ The shell does not exit if the command that
+ fails is part of an _u_n_t_i_l or _w_h_i_l_e loop, part
+ of an _i_f 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 _o_p_t_i_o_n-_n_a_m_e
+ The _o_p_t_i_o_n-_n_a_m_e 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 _o_p_t_i_o_n-_n_a_m_e is supplied, the values of
+ the current options are printed.
+ -p Turn on _p_r_i_v_i_l_e_g_e_d 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 _s_i_m_p_l_e-_c_o_m_m_a_n_d, bash
+ displays the expanded value of PS4, followed by
+ the command and its expanded arguments.
+ -l Save and restore the binding of _n_a_m_e in a for
+ _n_a_m_e [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 _a_r_gs,
+ even if some of them begin with a -.
+ - Signal the end of options, cause all remaining
+ _a_r_gs to be assigned to the positional parame-
+ ters. The -x and -v options are turned off.
+ If there are no _a_r_gs, 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 _n _a_r_gs are treated as values for
+ the positional parameters and are assigned, in order,
+ to $1, $2, ... $_n. If no options or _a_r_gs are supplied,
+ all shell variables are printed. The return status is
+ always true unless an illegal option is encountered.
+
+ shift [_n]
+ The positional parameters from _n+1 ... are renamed to
+ $1 .... Parameters represented by the numbers $# down
+ to $#-_n+1 are unset. If _n is 0, no parameters are
+ changed. If _n is not given, it is assumed to be 1. _n
+ must be a non-negative number less than or equal to $#.
+ If _n is greater than $#, the positional parameters are
+ not changed. The return status is greater than 0 if _n
+ 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 _e_x_p_r
+ [ _e_x_p_r ]
+ Return a status of 0 (true) or 1 (false) depending on
+ the evaluation of the conditional expression _e_x_p_r.
+ 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 _f_i_l_e is of the form /dev/fd/_n, then file
+ descriptor _n is checked.
+ -b _f_i_l_e
+ True if _f_i_l_e exists and is block special.
+ -c _f_i_l_e
+ True if _f_i_l_e exists and is character special.
+ -d _f_i_l_e
+ True if _f_i_l_e exists and is a directory.
+ -e _f_i_l_e
+ True if _f_i_l_e exists.
+ -f _f_i_l_e
+ True if _f_i_l_e exists and is a regular file.
+ -g _f_i_l_e
+ True if _f_i_l_e exists and is set-group-id.
+ -k _f_i_l_e
+ True if _f_i_l_e has its ``sticky'' bit set.
+ -L _f_i_l_e
+ True if _f_i_l_e exists and is a symbolic link.
+ -p _f_i_l_e
+ True if _f_i_l_e exists and is a named pipe.
+ -r _f_i_l_e
+ True if _f_i_l_e exists and is readable.
+ -s _f_i_l_e
+ True if _f_i_l_e exists and has a size greater than
+ zero.
+ -S _f_i_l_e
+ True if _f_i_l_e exists and is a socket.
+ -t _f_d
+ True if _f_d is opened on a terminal.
+ -u _f_i_l_e
+ True if _f_i_l_e exists and its set-user-id bit is
+ set.
+ -w _f_i_l_e
+ True if _f_i_l_e exists and is writable.
+ -x _f_i_l_e
+ True if _f_i_l_e exists and is executable.
+ -O _f_i_l_e
+ True if _f_i_l_e exists and is owned by the effective
+ user id.
+ -G _f_i_l_e
+ True if _f_i_l_e exists and is owned by the effective
+ group id.
+ _f_i_l_e_1 -nt _f_i_l_e_2
+ True if _f_i_l_e_1 is newer (according to modification
+ date) than _f_i_l_e_2.
+ _f_i_l_e_1 -ot _f_i_l_e_2
+ True if _f_i_l_e_1 is older than file2.
+ _f_i_l_e_1 -ef _f_i_l_e
+ True if _f_i_l_e_1 and _f_i_l_e_2 have the same device and
+
+
+
+GNU Last change: 1995 May 5 54
+
+
+
+
+
+
+BASH(1) USER COMMANDS BASH(1)
+
+
+
+ inode numbers.
+ -z _s_t_r_i_n_g
+ True if the length of _s_t_r_i_n_g is zero.
+ -n _s_t_r_i_n_g
+ _s_t_r_i_n_g
+ True if the length of _s_t_r_i_n_g is non-zero.
+ _s_t_r_i_n_g_1 = _s_t_r_i_n_g_2
+ True if the strings are equal.
+ _s_t_r_i_n_g_1 != _s_t_r_i_n_g_2
+ True if the strings are not equal.
+ ! _e_x_p_r
+ True if _e_x_p_r is false.
+ _e_x_p_r_1 -a _e_x_p_r_2
+ True if both _e_x_p_r_1 AND _e_x_p_r_2 are true.
+ _e_x_p_r_1 -o _e_x_p_r_2
+ True if either _e_x_p_r_1 OR _e_x_p_r_2 is true.
+ _a_r_g_1 OP _a_r_g_2
+ OP is one of -eq, -ne, -lt, -le, -gt, or -ge.
+ These arithmetic binary operators return true if
+ _a_r_g_1 is equal, not-equal, less-than, less-than-
+ or-equal, greater-than, or greater-than-or-equal
+ than _a_r_g_2, respectively. _A_r_g_1 and _a_r_g_2 may be
+ positive integers, negative integers, or the spe-
+ cial expression -l _s_t_r_i_n_g, which evaluates to the
+ length of _s_t_r_i_n_g.
+
+ 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] [_a_r_g] [_s_i_g_s_p_e_c]
+ The command _a_r_g is to be read and executed when the
+ shell receives signal(s) _s_i_g_s_p_e_c. If _a_r_g is absent or
+ -, all specified signals are reset to their original
+ values (the values they had upon entrance to the
+ shell). If _a_r_g is the null string this signal is
+ ignored by the shell and by the commands it invokes.
+ _s_i_g_s_p_e_c is either a signal name defined in <_s_i_g_n_a_l._h>,
+ or a signal number. If _s_i_g_s_p_e_c is EXIT (0) the command
+ _a_r_g 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] _n_a_m_e [_n_a_m_e ...]
+ With no options, indicate how each _n_a_m_e would be inter-
+ preted if used as a command name. If the -type flag is
+ used, type prints a phrase which is one of _a_l_i_a_s, _k_e_y_-
+ _w_o_r_d, _f_u_n_c_t_i_o_n, _b_u_i_l_t_i_n, or _f_i_l_e if _n_a_m_e 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 _n_a_m_e were
+ specified as a command name, or nothing if -type would
+ not return _f_i_l_e. 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
+ _n_a_m_e. 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 [_l_i_m_i_t]]
+ 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 _l_i_m_i_t 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 _l_i_m_i_t 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 _l_i_m_i_t 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 _l_i_m_i_t, or an error occurs
+ while setting a new limit.
+
+ umask [-S] [_m_o_d_e]
+ The user file-creation mask is set to _m_o_d_e. If _m_o_d_e
+ 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 _c_h_m_o_d(1). If _m_o_d_e 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 _m_o_d_e argument was supplied, and false otherwise.
+
+ unalias [-a] [_n_a_m_e ...]
+ Remove _n_a_m_es from the list of defined aliases. If -a
+ is supplied, all alias definitions are removed. The
+ return value is true unless a supplied _n_a_m_e is not a
+ defined alias.
+
+ unset [-fv] [_n_a_m_e ...]
+ For each _n_a_m_e, 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 _n_a_m_e does not exist or is non-
+ unsettable.
+
+ wait [_n]
+ Wait for the specified process and return its termina-
+ tion status. _n 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 _n 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 _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.
+
+INVOCATION
+ A _l_o_g_i_n _s_h_e_l_l is one whose first character of argument zero
+ is a -, or one started with the -login flag.
+
+ An _i_n_t_e_r_a_c_t_i_v_e shell is one whose standard input and output
+ are both connected to terminals (as determined by
+ _i_s_a_t_t_y(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 /_e_t_c/_p_r_o_f_i_l_e exists, source it.
+
+ if ~/._b_a_s_h__p_r_o_f_i_l_e exists, source it,
+ else if ~/._b_a_s_h__l_o_g_i_n exists, source it,
+ else if ~/._p_r_o_f_i_l_e exists, source it.
+
+ On exit:
+ if ~/._b_a_s_h__l_o_g_o_u_t exists, source it.
+
+ Non-login interactive shells:
+ On startup (subject to the -norc and -rcfile options):
+ if ~/._b_a_s_h_r_c 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 /_e_t_c/_p_r_o_f_i_l_e and ~/._p_r_o_f_i_l_e, 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 _p_o_s_i_x 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
+ _B_a_s_h _F_e_a_t_u_r_e_s, Brian Fox and Chet Ramey
+ _T_h_e _G_n_u _R_e_a_d_l_i_n_e _L_i_b_r_a_r_y, Brian Fox and Chet Ramey
+ _T_h_e _G_n_u _H_i_s_t_o_r_y _L_i_b_r_a_r_y, Brian Fox and Chet Ramey
+Lennert
+ _A _S_y_s_t_e_m _V _C_o_m_p_a_t_i_b_l_e _I_m_p_l_e_m_e_n_t_a_t_i_o_n _o_f _4._2_B_S_D _J_o_b _C_o_n_t_r_o_l, David
+_U_t_i_l_i_t_i_e_s, IEEE
+ _P_o_r_t_a_b_l_e _O_p_e_r_a_t_i_n_g _S_y_s_t_e_m _I_n_t_e_r_f_a_c_e (_P_O_S_I_X) _P_a_r_t _2: _S_h_e_l_l _a_n_d
+ _s_h(1), _k_s_h(1), _c_s_h(1)
+ _e_m_a_c_s(1), _v_i(1)
+ _r_e_a_d_l_i_n_e(3)
+
+FILES
+ /_b_i_n/_b_a_s_h
+ The bash executable
+ /_e_t_c/_p_r_o_f_i_l_e
+ The systemwide initialization file, executed for login
+ shells
+ ~/._b_a_s_h__p_r_o_f_i_l_e
+ The personal initialization file, executed for login
+ shells
+ ~/._b_a_s_h_r_c
+ The individual per-interactive-shell startup file
+ ~/._i_n_p_u_t_r_c
+ Individual _r_e_a_d_l_i_n_e 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
+ _b_a_s_h_b_u_g 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 _b_u_g-
+ _b_a_s_h@_p_r_e_p._a_i._M_I_T._E_d_u 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)
+
+
+
+ _b_a_s_h_b_u_g 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 _c_h_e_t@_i_n_s._C_W_R_U._E_d_u.
+
+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
index 00000000..553c1078
--- /dev/null
+++ b/documentation/builtins.1
@@ -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
index 00000000..ebac7d15
--- /dev/null
+++ b/documentation/builtins.ps
@@ -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
index 00000000..3df6380d
--- /dev/null
+++ b/documentation/builtins.txt
@@ -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
+ : [_a_r_g_u_m_e_n_t_s]
+ No effect; the command does nothing beyond expanding
+ _a_r_g_u_m_e_n_t_s and performing any specified redirections. A
+ zero exit code is returned.
+
+ . _f_i_l_e_n_a_m_e [_a_r_g_u_m_e_n_t_s]
+ source _f_i_l_e_n_a_m_e [_a_r_g_u_m_e_n_t_s]
+ Read and execute commands from _f_i_l_e_n_a_m_e in the current
+ shell environment and return the exit status of the
+ last command executed from _f_i_l_e_n_a_m_e. If _f_i_l_e_n_a_m_e does
+ not contain a slash, pathnames in PATH are used to find
+ the directory containing _f_i_l_e_n_a_m_e. 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
+ _a_r_g_u_m_e_n_t_s are supplied, they become the positional
+ parameters when _f_i_l_e 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 _f_i_l_e_n_a_m_e
+ is not found.
+
+ alias [_n_a_m_e[=_v_a_l_u_e] ...]
+ Alias with no arguments prints the list of aliases in
+ the form _n_a_m_e=_v_a_l_u_e on standard output. When arguments
+ are supplied, an alias is defined for each _n_a_m_e whose
+ _v_a_l_u_e is given. A trailing space in _v_a_l_u_e causes the
+ next word to be checked for alias substitution when the
+ alias is expanded. For each _n_a_m_e in the argument list
+ for which no _v_a_l_u_e is supplied, the name and value of
+ the alias is printed. Alias returns true unless a _n_a_m_e
+ is given for which no alias has been defined.
+
+ bg [_j_o_b_s_p_e_c]
+ Place _j_o_b_s_p_e_c in the background, as if it had been
+ started with &. If _j_o_b_s_p_e_c is not present, the shell's
+ notion of the _c_u_r_r_e_n_t _j_o_b is used. bg _j_o_b_s_p_e_c returns
+ 0 unless run when job control is disabled or, when run
+ with job control enabled, if _j_o_b_s_p_e_c was not found or
+ started without job control.
+
+ bind [-m _k_e_y_m_a_p] [-lvd] [-q _n_a_m_e]
+ bind [-m _k_e_y_m_a_p] -f _f_i_l_e_n_a_m_e
+
+
+
+GNU Last change: 1993 September 16 1
+
+
+
+
+
+
+BASH_BUILTINS(1) USER COMMANDS BASH_BUILTINS(1)
+
+
+
+ bind [-m _k_e_y_m_a_p] _k_e_y_s_e_q:_f_u_n_c_t_i_o_n-_n_a_m_e
+ 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
+ ._i_n_p_u_t_r_c, 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 _k_e_y_m_a_p
+ Use _k_e_y_m_a_p as the keymap to be affected by the
+ subsequent bindings. Acceptable _k_e_y_m_a_p names are
+ _e_m_a_c_s, _e_m_a_c_s-_s_t_a_n_d_a_r_d, _e_m_a_c_s-_m_e_t_a, _e_m_a_c_s-_c_t_l_x, _v_i,
+ _v_i-_m_o_v_e, _v_i-_c_o_m_m_a_n_d, and _v_i-_i_n_s_e_r_t. _v_i is
+ equivalent to _v_i-_c_o_m_m_a_n_d; _e_m_a_c_s is equivalent to
+ _e_m_a_c_s-_s_t_a_n_d_a_r_d.
+ -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 _f_i_l_e_n_a_m_e
+ Read key bindings from _f_i_l_e_n_a_m_e
+ -q _f_u_n_c_t_i_o_n
+ Query about which keys invoke the named _f_u_n_c_t_i_o_n
+
+ The return value is 0 unless an unrecognized option is
+ given or an error occurred.
+
+ break [_n]
+ Exit from within a for, while, or until loop. If _n is
+ specified, break _n levels. _n must be >_ 1. If _n 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 _s_h_e_l_l-_b_u_i_l_t_i_n [_a_r_g_u_m_e_n_t_s]
+ Execute the specified shell builtin, passing it _a_r_g_u_-
+ _m_e_n_t_s, 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 _s_h_e_l_l-_b_u_i_l_t_i_n is not a shell builtin command.
+
+ cd [_d_i_r]
+ Change the current directory to _d_i_r. The variable HOME
+ is the default _d_i_r. The variable CDPATH defines the
+ search path for the directory containing _d_i_r. 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 _d_i_r 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] _c_o_m_m_a_n_d [_a_r_g ...]
+ Run _c_o_m_m_a_n_d with _a_r_g_s 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 _c_o_m_m_a_n_d 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 _c_o_m_m_a_n_d is
+ printed. The -v option causes a single word indicating
+ the command or pathname used to invoke _c_o_m_m_a_n_d 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 _c_o_m_m_a_n_d was found,
+ and 1 if not. If neither option is supplied and an
+ error occurred or _c_o_m_m_a_n_d cannot be found, the exit
+ status is 127. Otherwise, the exit status of the com-
+ mand builtin is the exit status of _c_o_m_m_a_n_d.
+
+ continue [_n]
+ Resume the next iteration of the enclosing for, while,
+ or until loop. If _n is specified, resume at the _nth
+ enclosing loop. _n must be >_ 1. If _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 con-
+ tinue is executed.
+
+ declare [-frxi] [_n_a_m_e[=_v_a_l_u_e]]
+ typeset [-frxi] [_n_a_m_e[=_v_a_l_u_e]]
+ Declare variables and/or give them attributes. If no
+ _n_a_m_es 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 _n_a_m_es readonly. These names cannot then be
+ assigned values by subsequent assignment state-
+ ments.
+ -x Mark _n_a_m_es 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 _n_a_m_es 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 _n_a_m_e_s 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 _nth entry counting from the left of
+ the list shown by dirs when invoked without
+ options, starting with zero.
+ -n displays the _nth 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 _n indexes beyond the end of the directory
+ stack.
+
+ echo [-neE] [_a_r_g ...]
+ Output the _a_r_gs, 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 _n_n_n (octal)
+
+ enable [-n] [-all] [_n_a_m_e ...]
+ 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 _n_a_m_e is disabled; otherwise, _n_a_m_e_s
+ 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 _n_a_m_e is not a
+ shell builtin.
+
+ eval [_a_r_g ...]
+ The _a_r_gs 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 _a_r_g_s, or only
+ null arguments, eval returns true.
+
+ exec [[-] _c_o_m_m_a_n_d [_a_r_g_u_m_e_n_t_s]]
+ If _c_o_m_m_a_n_d is specified, it replaces the shell. No new
+ process is created. The _a_r_g_u_m_e_n_t_s become the arguments
+ to _c_o_m_m_a_n_d. If the first argument is -, the shell
+ places a dash in the zeroth arg passed to _c_o_m_m_a_n_d.
+ 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 _c_o_m_m_a_n_d is not specified, any redirections
+ take effect in the current shell, and the return status
+ is 0.
+
+ exit [_n]
+ Cause the shell to exit with a status of _n. If _n is
+ omitted, the exit status is that of the last command
+ executed. A trap on EXIT is executed before the shell
+ terminates.
+
+ export [-nf] [_n_a_m_e[=_w_o_r_d]] ...
+ export -p
+ The supplied _n_a_m_e_s are marked for automatic export to
+ the environment of subsequently executed commands. If
+ the -f option is given, the _n_a_m_e_s refer to functions.
+ If no _n_a_m_e_s 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 _n_a_m_e_s is not a legal
+ shell variable name, or -f is supplied with a _n_a_m_e that
+ is not a function.
+
+ fc [-e _e_n_a_m_e] [-nlr] [_f_i_r_s_t] [_l_a_s_t]
+ fc -s [_p_a_t=_r_e_p] [_c_m_d]
+ Fix Command. In the first form, a range of commands
+ from _f_i_r_s_t to _l_a_s_t is selected from the history list.
+ _F_i_r_s_t and _l_a_s_t 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 _l_a_s_t is not specified it is set to
+ the current command for listing (so that fc -l -10
+ prints the last 10 commands) and to _f_i_r_s_t otherwise.
+ If _f_i_r_s_t 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 _e_n_a_m_e
+ is invoked on a file containing those commands. If
+ _e_n_a_m_e 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, _c_o_m_m_a_n_d is re-executed after each
+ instance of _p_a_t is replaced by _r_e_p. 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 _f_i_r_s_t or _l_a_s_t
+ 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 _c_m_d does not specify a valid history
+ line, in which case fc returns failure.
+
+ fg [_j_o_b_s_p_e_c]
+ Place _j_o_b_s_p_e_c in the foreground, and make it the
+ current job. If _j_o_b_s_p_e_c is not present, the shell's
+ notion of the _c_u_r_r_e_n_t _j_o_b 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 _j_o_b_s_p_e_c does not
+ specify a valid job or _j_o_b_s_p_e_c specifies a job that was
+ started without job control.
+
+ getopts _o_p_t_s_t_r_i_n_g _n_a_m_e [_a_r_g_s]
+ getopts is used by shell procedures to parse positional
+ parameters. _o_p_t_s_t_r_i_n_g 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 _n_a_m_e, initializing _n_a_m_e 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 _o_p_t_s_t_r_i_n_g is a colon, _s_i_l_e_n_t 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 _o_p_t_s_t_r_i_n_g is not a colon.
+
+ If an illegal option is seen, getopts places ? into
+ _n_a_m_e 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 _n_a_m_e, OPTARG
+ is unset, and a diagnostic message is printed. If
+ getopts is silent, then a colon (:) is placed in _n_a_m_e
+ and OPTARG is set to the option character found.
+
+ getopts normally parses the positional parameters, but
+ if more arguments are given in _a_r_g_s, 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] [_n_a_m_e]
+ For each _n_a_m_e, 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 _n_a_m_e is not found or an illegal option is
+ supplied.
+
+ help [_p_a_t_t_e_r_n]
+ Display helpful information about builtin commands. If
+ _p_a_t_t_e_r_n is specified, help gives detailed help on all
+ commands matching _p_a_t_t_e_r_n; otherwise a list of the
+ builtins is printed. The return status is 0 unless no
+ command matches _p_a_t_t_e_r_n.
+
+
+
+GNU Last change: 1993 September 16 7
+
+
+
+
+
+
+BASH_BUILTINS(1) USER COMMANDS BASH_BUILTINS(1)
+
+
+
+ history [_n]
+ history -rwan [_f_i_l_e_n_a_m_e]
+ With no options, display the command history list with
+ line numbers. Lines listed with a * have been modi-
+ fied. An argument of _n lists only the last _n 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] [ _j_o_b_s_p_e_c ... ]
+ jobs -x _c_o_m_m_a_n_d [ _a_r_g_s ... ]
+ 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 _j_o_b_s_p_e_c 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 _j_o_b_s_p_e_c is
+ supplied.
+
+ If the -x option is supplied, jobs replaces any _j_o_b_s_p_e_c
+ found in _c_o_m_m_a_n_d or _a_r_g_s with the corresponding process
+ group ID, and executes _c_o_m_m_a_n_d passing it _a_r_g_s, return-
+ ing its exit status.
+
+ kill [-s sigspec | -sigspec] [_p_i_d | _j_o_b_s_p_e_c] ...
+ kill -l [_s_i_g_n_u_m]
+ Send the signal named by _s_i_g_s_p_e_c to the processes named
+ by _p_i_d or _j_o_b_s_p_e_c. _s_i_g_s_p_e_c is either a signal name
+ such as SIGKILL or a signal number. If _s_i_g_s_p_e_c is a
+ signal name, the name is case insensitive and may be
+ given with or without the SIG prefix. If _s_i_g_s_p_e_c 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 _a_r_g [_a_r_g ...]
+ Each _a_r_g is an arithmetic expression to be evaluated
+ (see ARITHMETIC EVALUATION). If the last _a_r_g evaluates
+ to 0, let returns 1; 0 is returned otherwise.
+
+ local [_n_a_m_e[=_v_a_l_u_e] ...]
+ For each argument, create a local variable named _n_a_m_e,
+ and assign it _v_a_l_u_e. When local is used within a func-
+ tion, it causes the variable _n_a_m_e 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 _n_a_m_e 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 _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.
+
+ 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 [_d_i_r]
+ 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 _nth 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 _nth directory
+ (counting from the right) is at the top.
+ dir adds _d_i_r 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 _d_i_r 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] [_n_a_m_e ...]
+ One line is read from the standard input, and the first
+ word is assigned to the first _n_a_m_e, the second word to
+ the second _n_a_m_e, and so on, with leftover words
+ assigned to the last _n_a_m_e. Only the characters in IFS
+ are recognized as word delimiters. If no _n_a_m_e_s 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] [_n_a_m_e ...]
+ readonly -p
+ The given _n_a_m_e_s are marked readonly and the values of
+ these _n_a_m_e_s may not be changed by subsequent assign-
+ ment. If the -f option is supplied, the functions
+ corresponding to the _n_a_m_e_s 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 _n_a_m_e_s is not a legal shell
+ variable name, or -f is supplied with a _n_a_m_e that is
+ not a function.
+
+ return [_n]
+ Causes a function to exit with the return value speci-
+ fied by _n. If _n 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 _n 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 _o_p_t_i_o_n] [_a_r_g ...]
+ -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 _s_i_m_p_l_e-_c_o_m_m_a_n_d (see SHELL
+ GRAMMAR above) exits with a non-zero status.
+ The shell does not exit if the command that
+ fails is part of an _u_n_t_i_l or _w_h_i_l_e loop, part
+ of an _i_f 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 _o_p_t_i_o_n-_n_a_m_e
+ The _o_p_t_i_o_n-_n_a_m_e 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 _o_p_t_i_o_n-_n_a_m_e is supplied, the values of
+ the current options are printed.
+ -p Turn on _p_r_i_v_i_l_e_g_e_d 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 _s_i_m_p_l_e-_c_o_m_m_a_n_d, 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 _n_a_m_e in a for
+ _n_a_m_e [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 _a_r_gs,
+ even if some of them begin with a -.
+ - Signal the end of options, cause all remaining
+ _a_r_gs to be assigned to the positional parame-
+ ters. The -x and -v options are turned off.
+ If there are no _a_r_gs, 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 _n _a_r_gs are treated as values for
+ the positional parameters and are assigned, in order,
+ to $1, $2, ... $_n. If no options or _a_r_gs are supplied,
+ all shell variables are printed. The return status is
+ always true unless an illegal option is encountered.
+
+ shift [_n]
+ The positional parameters from _n+1 ... are renamed to
+ $1 .... Parameters represented by the numbers $# down
+ to $#-_n+1 are unset. If _n is 0, no parameters are
+ changed. If _n is not given, it is assumed to be 1. _n
+ must be a non-negative number less than or equal to $#.
+ If _n is greater than $#, the positional parameters are
+ not changed. The return status is greater than 0 if _n
+ 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 _e_x_p_r
+ [ _e_x_p_r ]
+ Return a status of 0 (true) or 1 (false) depending on
+ the evaluation of the conditional expression _e_x_p_r.
+ 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 _f_i_l_e is of the form /dev/fd/_n, then file
+ descriptor _n is checked.
+ -b _f_i_l_e
+ True if _f_i_l_e exists and is block special.
+ -c _f_i_l_e
+ True if _f_i_l_e exists and is character special.
+ -d _f_i_l_e
+ True if _f_i_l_e exists and is a directory.
+ -e _f_i_l_e
+ True if _f_i_l_e exists.
+ -f _f_i_l_e
+ True if _f_i_l_e exists and is a regular file.
+ -g _f_i_l_e
+ True if _f_i_l_e exists and is set-group-id.
+ -k _f_i_l_e
+ True if _f_i_l_e has its ``sticky'' bit set.
+ -L _f_i_l_e
+ True if _f_i_l_e exists and is a symbolic link.
+ -p _f_i_l_e
+ True if _f_i_l_e exists and is a named pipe.
+ -r _f_i_l_e
+ True if _f_i_l_e exists and is readable.
+ -s _f_i_l_e
+ True if _f_i_l_e exists and has a size greater than
+ zero.
+ -S _f_i_l_e
+ True if _f_i_l_e exists and is a socket.
+ -t _f_d
+ True if _f_d is opened on a terminal.
+ -u _f_i_l_e
+ True if _f_i_l_e exists and its set-user-id bit is
+ set.
+ -w _f_i_l_e
+ True if _f_i_l_e exists and is writable.
+ -x _f_i_l_e
+ True if _f_i_l_e exists and is executable.
+ -O _f_i_l_e
+ True if _f_i_l_e exists and is owned by the effective
+ user id.
+ -G _f_i_l_e
+
+
+
+GNU Last change: 1993 September 16 14
+
+
+
+
+
+
+BASH_BUILTINS(1) USER COMMANDS BASH_BUILTINS(1)
+
+
+
+ True if _f_i_l_e exists and is owned by the effective
+ group id.
+ _f_i_l_e_1 -nt _f_i_l_e_2
+ True if _f_i_l_e_1 is newer (according to modification
+ date) than _f_i_l_e_2.
+ _f_i_l_e_1 -ot _f_i_l_e_2
+ True if _f_i_l_e_1 is older than file2.
+ _f_i_l_e_1 -ef _f_i_l_e
+ True if _f_i_l_e_1 and _f_i_l_e_2 have the same device and
+ inode numbers.
+ -z _s_t_r_i_n_g
+ True if the length of _s_t_r_i_n_g is zero.
+ -n _s_t_r_i_n_g
+ _s_t_r_i_n_g
+ True if the length of _s_t_r_i_n_g is non-zero.
+ _s_t_r_i_n_g_1 = _s_t_r_i_n_g_2
+ True if the strings are equal.
+ _s_t_r_i_n_g_1 != _s_t_r_i_n_g_2
+ True if the strings are not equal.
+ ! _e_x_p_r
+ True if _e_x_p_r is false.
+ _e_x_p_r_1 -a _e_x_p_r_2
+ True if both _e_x_p_r_1 AND _e_x_p_r_2 are true.
+ _e_x_p_r_1 -o _e_x_p_r_2
+ True if either _e_x_p_r_1 OR _e_x_p_r_2 is true.
+ _a_r_g_1 OP _a_r_g_2
+ OP is one of -eq, -ne, -lt, -le, -gt, or -ge.
+ These arithmetic binary operators return true if
+ _a_r_g_1 is equal, not-equal, less-than, less-than-
+ or-equal, greater-than, or greater-than-or-equal
+ than _a_r_g_2, respectively. _A_r_g_1 and _a_r_g_2 may be
+ positive integers, negative integers, or the spe-
+ cial expression -l _s_t_r_i_n_g, which evaluates to the
+ length of _s_t_r_i_n_g.
+
+ 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] [_a_r_g] [_s_i_g_s_p_e_c]
+ The command _a_r_g is to be read and executed when the
+ shell receives signal(s) _s_i_g_s_p_e_c. If _a_r_g is absent or
+ -, all specified signals are reset to their original
+ values (the values they had upon entrance to the
+ shell). If _a_r_g is the null string this signal is
+ ignored by the shell and by the commands it invokes.
+ _s_i_g_s_p_e_c is either a signal name defined in <_s_i_g_n_a_l._h>,
+ or a signal number. If _s_i_g_s_p_e_c is EXIT (0) the command
+ _a_r_g 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] _n_a_m_e [_n_a_m_e ...]
+ With no options, indicate how each _n_a_m_e would be inter-
+ preted if used as a command name. If the -type flag is
+ used, type prints a phrase which is one of _a_l_i_a_s, _k_e_y_-
+ _w_o_r_d, _f_u_n_c_t_i_o_n, _b_u_i_l_t_i_n, or _f_i_l_e if _n_a_m_e 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 _n_a_m_e were
+ specified as a command name, or nothing if -type would
+ not return _f_i_l_e. 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
+ _n_a_m_e. 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 [_l_i_m_i_t]]
+ 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 _l_i_m_i_t 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 _l_i_m_i_t 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 _l_i_m_i_t 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 _l_i_m_i_t, or an error occurs
+ while setting a new limit.
+
+ umask [-S] [_m_o_d_e]
+ The user file-creation mask is set to _m_o_d_e. If _m_o_d_e
+ 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 _c_h_m_o_d(1). If _m_o_d_e 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 _m_o_d_e argument was supplied, and false otherwise.
+
+ unalias [-a] [_n_a_m_e ...]
+ Remove _n_a_m_es from the list of defined aliases. If -a
+ is supplied, all alias definitions are removed. The
+ return value is true unless a supplied _n_a_m_e is not a
+ defined alias.
+
+ unset [-fv] [_n_a_m_e ...]
+ For each _n_a_m_e, 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 _n_a_m_e does not exist or is non-
+ unsettable.
+
+ wait [_n]
+ Wait for the specified process and return its termina-
+ tion status. _n 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 _n is not given, all
+ currently active child processes are waited for, and
+ the return status is zero. If _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.
+
+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
index 00000000..21e53276
--- /dev/null
+++ b/documentation/features.dvi
Binary files differ
diff --git a/documentation/features.info b/documentation/features.info
new file mode 100644
index 00000000..63984456
--- /dev/null
+++ b/documentation/features.info
@@ -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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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."
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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}}
+
+
+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::.)
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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::.).
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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::.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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::.).
+
+
+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.
+
+
+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.
+
+
+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/'.
+
+
+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.
+
+
+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 `&'.
+
+
+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.
+
+
+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).
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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\\": "\\"
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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'.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+
+Tag Table:
+Node: Top1044
+Node: Bourne Shell Features2405
+Node: Looping Constructs3579
+Node: Conditional Constructs4634
+Node: Shell Functions6194
+Node: Bourne Shell Builtins7567
+Node: Bourne Shell Variables9766
+Node: Other Bourne Shell Features11025
+Node: Major Differences from the Bourne Shell11783
+Node: Csh Features14194
+Node: Tilde Expansion15087
+Node: Brace Expansion15691
+Node: C Shell Builtins17283
+Node: C Shell Variables20578
+Node: Korn Shell Features21088
+Node: Korn Shell Constructs21826
+Node: Korn Shell Builtins23037
+Node: Korn Shell Variables25190
+Node: Aliases26466
+Node: Alias Builtins28833
+Node: Bash Specific Features29356
+Node: Invoking Bash30085
+Node: Bash Startup Files32404
+Node: Is This Shell Interactive?34247
+Node: Bash Builtins35055
+Node: The Set Builtin41437
+Node: Bash Variables46377
+Node: Shell Arithmetic50945
+Node: Arithmetic Evaluation51307
+Node: Arithmetic Expansion53028
+Node: Arithmetic Builtins53862
+Node: Printing a Prompt54334
+Node: Job Control55599
+Node: Job Control Basics56074
+Node: Job Control Builtins60249
+Node: Job Control Variables61768
+Node: Using History Interactively63077
+Node: History Interaction63584
+Node: Event Designators64630
+Node: Word Designators65461
+Node: Modifiers66446
+Node: Command Line Editing67755
+Node: Introduction and Notation68415
+Node: Readline Interaction69435
+Node: Readline Bare Essentials70574
+Node: Readline Movement Commands72104
+Node: Readline Killing Commands72995
+Node: Readline Arguments74698
+Node: Readline Init File75649
+Node: Readline Init Syntax76647
+Node: Conditional Init Constructs83580
+Node: Bindable Readline Commands85826
+Node: Commands For Moving86496
+Node: Commands For History87344
+Node: Commands For Text89988
+Node: Commands For Killing91727
+Node: Numeric Arguments93176
+Node: Commands For Completion93803
+Node: Keyboard Macros94816
+Node: Miscellaneous Commands95375
+Node: Readline vi Mode97466
+Node: Variable Index98343
+Node: Concept Index101671
+
+End Tag Table
diff --git a/documentation/features.ps b/documentation/features.ps
new file mode 100644
index 00000000..b8b52cc4
--- /dev/null
+++ b/documentation/features.ps
@@ -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
index 00000000..bc1d2b3d
--- /dev/null
+++ b/documentation/features.texi
@@ -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
index 00000000..bbe9d913
--- /dev/null
+++ b/documentation/readline.3
@@ -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
index 00000000..5e004b1c
--- /dev/null
+++ b/documentation/readline.ps
@@ -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
index 00000000..653a9842
--- /dev/null
+++ b/documentation/readline.txt
@@ -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 _m_a_l_l_o_c(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
+ _e_m_a_c_s__k_e_y_m_a_p, _e_m_a_c_s__m_e_t_a__k_e_y_m_a_p, _e_m_a_c_s__c_t_l_x__k_e_y_m_a_p,
+ _v_i__i_n_s_e_r_t_i_o_n__k_e_y_m_a_p, _o_r _v_i__m_o_v_e_m_e_n_t__k_e_y_m_a_p.
+
+ 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-_k_e_y, e.g., C-n means Control-N.
+ Similarly, _m_e_t_a keys are denoted by M-_k_e_y, so M-x means
+
+
+
+GNU Last change: 1994 July 26 3
+
+
+
+
+
+
+READLINE(3) C LIBRARY FUNCTIONS READLINE(3)
+
+
+
+ Meta-X. (On keyboards without a _m_e_t_a key, M-_x means ESC _x,
+ i.e., press the Escape key then the _x key. This makes ESC
+ the _m_e_t_a _p_r_e_f_i_x. The combination M-C-_x means ESC-Control-_x,
+ or press the Escape key then hold the Control key while
+ pressing the _x key.)
+
+ Readline commands may be given numeric _a_r_g_u_m_e_n_t_s, 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 _k_i_l_l_i_n_g text, the text
+ deleted is saved for possible future retrieval (_y_a_n_k_i_n_g).
+ The killed text is saved in a _k_i_l_l-_r_i_n_g. 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 ~/._i_n_p_u_t_r_c. 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 ~/._i_n_p_u_t_r_c would make M-C-u execute the readline
+ command _u_n_i_v_e_r_s_a_l-_a_r_g_u_m_e_n_t.
+
+ The following symbolic character names are recognized while
+ processing key bindings: _R_U_B_O_U_T, _D_E_L, _E_S_C, _L_F_D, _N_E_W_L_I_N_E,
+ _R_E_T, _R_E_T_U_R_N, _S_P_C, _S_P_A_C_E, and _T_A_B. In addition to command
+ names, readline allows keys to be bound to a string that is
+ inserted when the key is pressed (a _m_a_c_r_o).
+
+ Key Bindings
+ The syntax for controlling key bindings in the ~/._i_n_p_u_t_r_c
+ 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 _M_e_t_a- or _C_o_n_-
+ _t_r_o_l- prefixes, or as a key sequence. When using the form
+ keyname:_f_u_n_c_t_i_o_n-_n_a_m_e or _m_a_c_r_o, _k_e_y_n_a_m_e 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, _M-_D_E_L is bound to the function
+ backward-kill-word, and _C-_o is bound to run the macro
+ expressed on the right hand side (that is, to insert the
+ text >&_o_u_t_p_u_t into the line).
+
+ In the second form, "keyseq":_f_u_n_c_t_i_o_n-_n_a_m_e or _m_a_c_r_o, 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, _C-_u is again bound to the function
+ universal-argument. _C-_x _C-_r is bound to the function
+ re-read-init-file, and _E_S_C [ _1 _1 ~ 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 _i_n_p_u_t_r_c
+ 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 _i_n_p_u_t_r_c file
+ with a statement of the form
+
+ set _v_a_r_i_a_b_l_e-_n_a_m_e _v_a_l_u_e
+
+ 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 _e_m_a_c_s or _v_i. 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 _m_e_t_a _p_r_e_f_i_x).
+ 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 _e_m_a_c_s, _e_m_a_c_s-_s_t_a_n_d_a_r_d, _e_m_a_c_s-_m_e_t_a, _e_m_a_c_s-
+ _c_t_l_x, _v_i, _v_i-_m_o_v_e, _v_i-_c_o_m_m_a_n_d, and _v_i-_i_n_s_e_r_t. _v_i is
+ equivalent to _v_i-_c_o_m_m_a_n_d; _e_m_a_c_s is equivalent to
+ _e_m_a_c_s-_s_t_a_n_d_a_r_d. The default value is _e_m_a_c_s; 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
+ _e_m_a_c_s-_s_t_a_n_d_a_r_d and _e_m_a_c_s-_c_t_l_x 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 _s_u_n to match both _s_u_n and _s_u_n-_c_m_d, 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 _a_p_p_l_i_c_a_t_i_o_n _n_a_m_e,
+ 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 _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-_)
+
+
+
+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 _i_n_p_u_t_r_c 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 _m_e_t_a_f_i_e_d 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 _s_e_l_f-_i_n_s_e_r_t func-
+ tion, which just inserts the given character into the input
+ line. In vi insertion mode, all characters not specifically
+ mentioned are bound to _s_e_l_f-_i_n_s_e_r_t. Characters assigned to
+ signal generation by _s_t_t_y(1) or the terminal driver, such as
+ C-Z or C-C, retain that function. Upper and lower case
+ _m_e_t_a_f_i_e_d 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
+ _T_h_e _G_n_u _R_e_a_d_l_i_n_e _L_i_b_r_a_r_y, Brian Fox and Chet Ramey
+ _T_h_e _G_n_u _H_i_s_t_o_r_y _L_i_b_r_a_r_y, Brian Fox and Chet Ramey
+ _b_a_s_h(1)
+
+FILES
+ ~/._i_n_p_u_t_r_c
+ 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 _b_a_s_h-_m_a_i_n_t_a_i_n_e_r_s@_p_r_e_p._a_i._M_I_T._E_d_u. If you have
+ a fix, you are welcome to mail that as well! Suggestions
+ and `philosophical' bug reports may be mailed to _b_u_g-
+ _b_a_s_h@_p_r_e_p._a_i._M_I_T._E_d_u or posted to the Usenet newsgroup
+ gnu.bash.bug.
+
+ Comments and bug reports concerning this manual page should
+ be directed to _c_h_e_t@_i_n_s._C_W_R_U._E_d_u.
+
+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
index 00000000..ce8124ec
--- /dev/null
+++ b/documentation/texinfo.tex
@@ -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 `\=\other
+\catcode `\=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\ =\other
+\catcode `\^^L=\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 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
index 00000000..7de87061
--- /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
index 00000000..5ffd4abc
--- /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
index 00000000..15a50910
--- /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
index 00000000..edbed865
--- /dev/null
+++ b/examples/alias-conv.sh
@@ -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
index 00000000..a6ae4215
--- /dev/null
+++ b/examples/functions/autoload
@@ -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
index 00000000..a5413495
--- /dev/null
+++ b/examples/functions/basename
@@ -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
index 00000000..8eaf7545
--- /dev/null
+++ b/examples/functions/csh-compat
@@ -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
index 00000000..3958bbec
--- /dev/null
+++ b/examples/functions/dirfuncs
@@ -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
index 00000000..ccb8c841
--- /dev/null
+++ b/examples/functions/dirname
@@ -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
index 00000000..bae3f271
--- /dev/null
+++ b/examples/functions/exitstat
@@ -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
index 00000000..c2e52cdd
--- /dev/null
+++ b/examples/functions/external
@@ -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
index 00000000..cd7bf467
--- /dev/null
+++ b/examples/functions/fact
@@ -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
index 00000000..a770d841
--- /dev/null
+++ b/examples/functions/fstty
@@ -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
index 00000000..710f6433
--- /dev/null
+++ b/examples/functions/func
@@ -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
index 00000000..212c9cec
--- /dev/null
+++ b/examples/functions/jj.bash
@@ -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
index 00000000..fbec76f4
--- /dev/null
+++ b/examples/functions/kshenv
@@ -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
index 00000000..3fdc7acf
--- /dev/null
+++ b/examples/functions/manpage
@@ -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
index 00000000..dafbac5a
--- /dev/null
+++ b/examples/functions/notify.bash
@@ -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
index 00000000..55a30965
--- /dev/null
+++ b/examples/functions/shcat
@@ -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
index 00000000..c5576779
--- /dev/null
+++ b/examples/functions/substr
@@ -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
index 00000000..f5e75473
--- /dev/null
+++ b/examples/functions/substr2
@@ -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
index 00000000..fbe99f13
--- /dev/null
+++ b/examples/functions/term
@@ -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
index 00000000..56c5a580
--- /dev/null
+++ b/examples/functions/whatis
@@ -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
index 00000000..70b2322a
--- /dev/null
+++ b/examples/functions/whence
@@ -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
index 00000000..a6d2eaa3
--- /dev/null
+++ b/examples/scripts/adventure.sh
@@ -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
index 00000000..9d93b305
--- /dev/null
+++ b/examples/scripts/bcsh.sh
@@ -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
index 00000000..9bbdb971
--- /dev/null
+++ b/examples/scripts/precedence
@@ -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
index 00000000..ec8b997a
--- /dev/null
+++ b/examples/scripts/shprompt
@@ -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
index 00000000..012ad5ca
--- /dev/null
+++ b/examples/startup-files/Bash_aliases
@@ -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
index 00000000..b1b24c0a
--- /dev/null
+++ b/examples/startup-files/Bash_profile
@@ -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
index 00000000..935bff82
--- /dev/null
+++ b/examples/startup-files/Bashrc
@@ -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
index 00000000..01c322aa
--- /dev/null
+++ b/examples/startup-files/bash-profile
@@ -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
index 00000000..5363e583
--- /dev/null
+++ b/examples/startup-files/bashrc
@@ -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
index 00000000..c3422fb4
--- /dev/null
+++ b/examples/suncmd.termcap
@@ -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
index 00000000..55274ead
--- /dev/null
+++ b/execute_cmd.c
@@ -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);
+}
+
+/* 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
index 00000000..e0961034
--- /dev/null
+++ b/execute_cmd.h
@@ -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
index 00000000..5f9eb6da
--- /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
index 00000000..8330838c
--- /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
index 00000000..c0b20811
--- /dev/null
+++ b/filecntl.h
@@ -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
index 00000000..b812ec98
--- /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
index 00000000..bcff4efe
--- /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
index 00000000..9ccfce62
--- /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
index 00000000..5c8f4d1d
--- /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
index 00000000..6f6eed39
--- /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
index 00000000..b955b3f9
--- /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 */
+
+/*
+ * 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
index 00000000..54587879
--- /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
index 00000000..852d3695
--- /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
index 00000000..1824b404
--- /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
index 00000000..40e7f7db
--- /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
index 00000000..18d3d736
--- /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
index 00000000..553b61f8
--- /dev/null
+++ b/lib/doc-support/Makefile
@@ -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
index 00000000..45541f5a
--- /dev/null
+++ b/lib/doc-support/getopt.h
@@ -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
index 00000000..9233bab1
--- /dev/null
+++ b/lib/doc-support/texindex.c
@@ -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. */
+
+
+#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 ();
+
+#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);
+}
+
+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 ();
+}
+
+/* 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;
+}
+
+/* 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;
+ }
+}
+
+/* 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;
+}
+
+/* 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);
+}
+
+/* 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);
+}
+
+/* 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;
+}
+
+/* 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);
+}
+
+/* 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);
+}
+
+/* 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;
+}
+
+/* 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;
+}
+
+/* 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
index 00000000..377f0c17
--- /dev/null
+++ b/lib/glob/ChangeLog
@@ -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
index 00000000..5811ba2e
--- /dev/null
+++ b/lib/glob/Makefile
@@ -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
index 00000000..1b6084c2
--- /dev/null
+++ b/lib/glob/doc/Makefile
@@ -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
index 00000000..0262ef11
--- /dev/null
+++ b/lib/glob/doc/glob.texi
@@ -0,0 +1 @@
+Nothing happens here.
diff --git a/lib/glob/fnmatch.c b/lib/glob/fnmatch.c
new file mode 100644
index 00000000..6a8b5749
--- /dev/null
+++ b/lib/glob/fnmatch.c
@@ -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
index 00000000..62c8c8fa
--- /dev/null
+++ b/lib/glob/fnmatch.h
@@ -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
index 00000000..6ff2cb49
--- /dev/null
+++ b/lib/glob/glob.c
@@ -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. */
+
+/* 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;
+
+
+/* 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';
+}
+
+
+/* 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);
+}
+
+/* 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);
+}
+
+/* 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);
+}
+
+#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
index 00000000..31261eb0
--- /dev/null
+++ b/lib/glob/ndir.h
@@ -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
index 00000000..4c0ab72b
--- /dev/null
+++ b/lib/malloc/Makefile
@@ -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
index 00000000..567ea1bb
--- /dev/null
+++ b/lib/malloc/alloca.c
@@ -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
index 00000000..0cb44161
--- /dev/null
+++ b/lib/malloc/getpagesize.h
@@ -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
index 00000000..01b2cfed
--- /dev/null
+++ b/lib/malloc/i386-alloca.s
@@ -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
index 00000000..78fb640d
--- /dev/null
+++ b/lib/malloc/malloc.c
@@ -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;
+}
+
+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;
+ }
+}
+
+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 */
+
+#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 */
+
+/*
+ * 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
index 00000000..112d33cc
--- /dev/null
+++ b/lib/malloc/x386-alloca.s
@@ -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
index 00000000..4f6dc762
--- /dev/null
+++ b/lib/malloc/xmalloc.c
@@ -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
index 00000000..7a449c37
--- /dev/null
+++ b/lib/malloclib/Makefile
@@ -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
index 00000000..918d0235
--- /dev/null
+++ b/lib/malloclib/alloca.c
@@ -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
index 00000000..f870e944
--- /dev/null
+++ b/lib/malloclib/calloc.c
@@ -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
index 00000000..adc1ff69
--- /dev/null
+++ b/lib/malloclib/cfree.c
@@ -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
index 00000000..db97fcbc
--- /dev/null
+++ b/lib/malloclib/free.c
@@ -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
index 00000000..b3aa4ba2
--- /dev/null
+++ b/lib/malloclib/getpagesize.h
@@ -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
index 00000000..01b2cfed
--- /dev/null
+++ b/lib/malloclib/i386-alloca.s
@@ -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
index 00000000..1d9bc036
--- /dev/null
+++ b/lib/malloclib/malloc.c
@@ -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
index 00000000..705a8c09
--- /dev/null
+++ b/lib/malloclib/malloc.h
@@ -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
index 00000000..f7d9d4f8
--- /dev/null
+++ b/lib/malloclib/mcheck.c
@@ -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
index 00000000..f5ad17cb
--- /dev/null
+++ b/lib/malloclib/memalign.c
@@ -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
index 00000000..c9a9ca5a
--- /dev/null
+++ b/lib/malloclib/morecore.c
@@ -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
index 00000000..511cdad9
--- /dev/null
+++ b/lib/malloclib/mstats.c
@@ -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
index 00000000..d7689cec
--- /dev/null
+++ b/lib/malloclib/mtrace.awk
@@ -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
index 00000000..ea1d3a49
--- /dev/null
+++ b/lib/malloclib/mtrace.c
@@ -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
index 00000000..2d31766a
--- /dev/null
+++ b/lib/malloclib/realloc.c
@@ -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
index 00000000..eb5d3728
--- /dev/null
+++ b/lib/malloclib/valloc.c
@@ -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
index 00000000..112d33cc
--- /dev/null
+++ b/lib/malloclib/x386-alloca.s
@@ -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
index 00000000..a25cb119
--- /dev/null
+++ b/lib/malloclib/xmalloc.c
@@ -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
index 00000000..52339da5
--- /dev/null
+++ b/lib/posixheaders/ansi_stdlib.h
@@ -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
index 00000000..c0b20811
--- /dev/null
+++ b/lib/posixheaders/filecntl.h
@@ -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
index 00000000..750d53df
--- /dev/null
+++ b/lib/posixheaders/memalloc.h
@@ -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
index 00000000..7d1cece3
--- /dev/null
+++ b/lib/posixheaders/posixstat.h
@@ -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
index 00000000..5dcc32bf
--- /dev/null
+++ b/lib/posixheaders/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/lib/readline/COPYING b/lib/readline/COPYING
new file mode 100644
index 00000000..1bb82d1b
--- /dev/null
+++ b/lib/readline/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.
+
+ 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.
+
+ 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.
+
+ 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
+
+ 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
index 00000000..1cf0c004
--- /dev/null
+++ b/lib/readline/ChangeLog
@@ -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
index 00000000..b36cab7f
--- /dev/null
+++ b/lib/readline/Makefile
@@ -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
index 00000000..131471ca
--- /dev/null
+++ b/lib/readline/README
@@ -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
index 00000000..c1387f34
--- /dev/null
+++ b/lib/readline/STANDALONE
@@ -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
index 00000000..52339da5
--- /dev/null
+++ b/lib/readline/ansi_stdlib.h
@@ -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
index 00000000..88215990
--- /dev/null
+++ b/lib/readline/bind.c
@@ -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 */
+}
+
+/* **************************************************************** */
+/* */
+/* 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
index 00000000..8c92811d
--- /dev/null
+++ b/lib/readline/chardefs.h
@@ -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
index 00000000..f219877a
--- /dev/null
+++ b/lib/readline/complete.c
@@ -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 */
+
+/* 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__ */
+}
+
+/* **************************************************************** */
+/* */
+/* 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)
+
+/* **************************************************************** */
+/* */
+/* 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
index 00000000..daf736ca
--- /dev/null
+++ b/lib/readline/display.c
@@ -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
index 00000000..72b8ce77
--- /dev/null
+++ b/lib/readline/doc/Makefile
@@ -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
index 00000000..cc80efab
--- /dev/null
+++ b/lib/readline/doc/hist.texinfo
@@ -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
index 00000000..60d73763
--- /dev/null
+++ b/lib/readline/doc/history.dvi
Binary files differ
diff --git a/lib/readline/doc/history.info b/lib/readline/doc/history.info
new file mode 100644
index 00000000..6df0bd94
--- /dev/null
+++ b/lib/readline/doc/history.info
@@ -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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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/'.
+
+
+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.
+
+
+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 `&'.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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 `='.
+
+
+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");
+ }
+ }
+ }
+ }
+
+
+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.
+
+
+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.
+
+
+
+Tag Table:
+Node: Top975
+Node: Using History Interactively1569
+Node: History Interaction2077
+Node: Event Designators3122
+Node: Word Designators3952
+Node: Modifiers4936
+Node: Programming with GNU History6065
+Node: Introduction to History6791
+Node: History Storage8112
+Node: History Functions9205
+Node: Initializing History and State Management10176
+Node: History List Management10968
+Node: Information About the History List12396
+Node: Moving Around the History List13702
+Node: Searching the History List14587
+Node: Managing the History File16419
+Node: History Expansion17925
+Node: History Variables19769
+Node: History Programming Example21138
+Node: Concept Index23742
+Node: Function and Variable Index24223
+
+End Tag Table
diff --git a/lib/readline/doc/history.ps b/lib/readline/doc/history.ps
new file mode 100644
index 00000000..839598f3
--- /dev/null
+++ b/lib/readline/doc/history.ps
@@ -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
index 00000000..5f0f6004
--- /dev/null
+++ b/lib/readline/doc/hstech.texinfo
@@ -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
index 00000000..51327a3f
--- /dev/null
+++ b/lib/readline/doc/hsuser.texinfo
@@ -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
index 00000000..aea321a2
--- /dev/null
+++ b/lib/readline/doc/readline.dvi
Binary files differ
diff --git a/lib/readline/doc/readline.info b/lib/readline/doc/readline.info
new file mode 100644
index 00000000..6df0bd94
--- /dev/null
+++ b/lib/readline/doc/readline.info
@@ -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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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/'.
+
+
+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.
+
+
+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 `&'.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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 `='.
+
+
+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");
+ }
+ }
+ }
+ }
+
+
+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.
+
+
+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.
+
+
+
+Tag Table:
+Node: Top975
+Node: Using History Interactively1569
+Node: History Interaction2077
+Node: Event Designators3122
+Node: Word Designators3952
+Node: Modifiers4936
+Node: Programming with GNU History6065
+Node: Introduction to History6791
+Node: History Storage8112
+Node: History Functions9205
+Node: Initializing History and State Management10176
+Node: History List Management10968
+Node: Information About the History List12396
+Node: Moving Around the History List13702
+Node: Searching the History List14587
+Node: Managing the History File16419
+Node: History Expansion17925
+Node: History Variables19769
+Node: History Programming Example21138
+Node: Concept Index23742
+Node: Function and Variable Index24223
+
+End Tag Table
diff --git a/lib/readline/doc/readline.ps b/lib/readline/doc/readline.ps
new file mode 100644
index 00000000..839598f3
--- /dev/null
+++ b/lib/readline/doc/readline.ps
@@ -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
index 00000000..ec140667
--- /dev/null
+++ b/lib/readline/doc/rlman.texinfo
@@ -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
index 00000000..636c9239
--- /dev/null
+++ b/lib/readline/doc/rltech.texinfo
@@ -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
index 00000000..35675492
--- /dev/null
+++ b/lib/readline/doc/rluser.texinfo
@@ -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
index 00000000..9233bab1
--- /dev/null
+++ b/lib/readline/doc/texindex.c
@@ -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. */
+
+
+#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 ();
+
+#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);
+}
+
+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 ();
+}
+
+/* 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;
+}
+
+/* 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;
+ }
+}
+
+/* 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;
+}
+
+/* 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);
+}
+
+/* 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);
+}
+
+/* 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;
+}
+
+/* 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);
+}
+
+/* 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);
+}
+
+/* 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;
+}
+
+/* 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;
+}
+
+/* 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
index 00000000..849d85fe
--- /dev/null
+++ b/lib/readline/emacs_keymap.c
@@ -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
index 00000000..5b71bd70
--- /dev/null
+++ b/lib/readline/examples/Inputrc
@@ -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
index 00000000..3d1fc527
--- /dev/null
+++ b/lib/readline/examples/Makefile
@@ -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
index 00000000..3ecb9f18
--- /dev/null
+++ b/lib/readline/examples/fileman.c
@@ -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
index 00000000..eceb66df
--- /dev/null
+++ b/lib/readline/examples/histexamp.c
@@ -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
index 00000000..3496efa0
--- /dev/null
+++ b/lib/readline/examples/manexamp.c
@@ -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
index 00000000..9255974c
--- /dev/null
+++ b/lib/readline/funmap.c
@@ -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)
+
+/* **************************************************************** */
+/* */
+/* 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
index 00000000..9172755d
--- /dev/null
+++ b/lib/readline/history.c
@@ -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);
+}
+
+
+/* **************************************************************** */
+/* */
+/* 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)
+
+/* **************************************************************** */
+/* */
+/* 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 */
+
+/* **************************************************************** */
+/* */
+/* 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 */
+
+/*
+* 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
index 00000000..6935efd2
--- /dev/null
+++ b/lib/readline/history.h
@@ -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
index 00000000..1a0193f4
--- /dev/null
+++ b/lib/readline/isearch.c
@@ -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
index 00000000..e1be552c
--- /dev/null
+++ b/lib/readline/keymaps.c
@@ -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)
+
+/* **************************************************************** */
+/* */
+/* 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
index 00000000..f0eda3d7
--- /dev/null
+++ b/lib/readline/keymaps.h
@@ -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
index 00000000..750d53df
--- /dev/null
+++ b/lib/readline/memalloc.h
@@ -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
index 00000000..57a97778
--- /dev/null
+++ b/lib/readline/parens.c
@@ -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
index 00000000..7d1cece3
--- /dev/null
+++ b/lib/readline/posixstat.h
@@ -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
index 00000000..6040cbb4
--- /dev/null
+++ b/lib/readline/readline.c
@@ -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 */
+
+
+/* **************************************************************** */
+/* */
+/* 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;
+
+
+/* **************************************************************** */
+/* */
+/* `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;
+
+/* **************************************************************** */
+/* */
+/* 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));
+}
+
+/* **************************************************************** */
+/* */
+/* 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);
+}
+
+
+/* **************************************************************** */
+/* */
+/* 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;
+}
+
+/* **************************************************************** */
+/* */
+/* 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;
+}
+
+
+/* **************************************************************** */
+/* */
+/* 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 ());
+}
+
+/* **************************************************************** */
+/* */
+/* 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;
+}
+
+
+/* **************************************************************** */
+/* */
+/* 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;
+}
+
+
+/* **************************************************************** */
+/* */
+/* 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);
+}
+
+
+/* **************************************************************** */
+/* */
+/* Readline character functions */
+/* */
+/* **************************************************************** */
+
+/* This is not a gap editor, just a stupid line input routine. No hair
+ is involved in writing any of the functions, and none should be. */
+
+/* Note that:
+
+ rl_end is the place in the string that we would place '\0';
+ i.e., it is always safe to place '\0' there.
+
+ rl_point is the place in the string where the cursor is. Sometimes
+ this is the same as rl_end.
+
+ Any command that is called interactively receives two arguments.
+ The first is a count: the numeric arg pased to this command.
+ The second is the key which invoked this command.
+*/
+
+
+/* **************************************************************** */
+/* */
+/* Movement Commands */
+/* */
+/* **************************************************************** */
+
+/* Note that if you `optimize' the display for these functions, you cannot
+ use said functions in other functions which do not do optimizing display.
+ I.e., you will have to update the data base for rl_redisplay, and you
+ might as well let rl_redisplay do that job. */
+
+/* Move forward COUNT 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;
+}
+
+
+/* **************************************************************** */
+/* */
+/* 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;
+}
+
+
+/* **************************************************************** */
+/* */
+/* 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;
+}
+
+
+/* **************************************************************** */
+/* */
+/* 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;
+}
+
+/* **************************************************************** */
+/* */
+/* 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;
+}
+
+/* **************************************************************** */
+/* */
+/* 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;
+}
+
+/* **************************************************************** */
+/* */
+/* 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;
+}
+
+
+/* **************************************************************** */
+/* */
+/* 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;
+}
+
+
+/* **************************************************************** */
+/* */
+/* 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)
+
+/* **************************************************************** */
+/* */
+/* 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 */
+
+
+/* **************************************************************** */
+/* */
+/* 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 */
+
+
+/*
+ * 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
index 00000000..b3971775
--- /dev/null
+++ b/lib/readline/readline.h
@@ -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
index 00000000..0035b935
--- /dev/null
+++ b/lib/readline/rlconf.h
@@ -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
index 00000000..683f8b51
--- /dev/null
+++ b/lib/readline/rldefs.h
@@ -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
index 00000000..02c036d0
--- /dev/null
+++ b/lib/readline/rltty.c
@@ -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__ */
+}
+
+/* **************************************************************** */
+/* */
+/* 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;
+}
+
+/* **************************************************************** */
+/* */
+/* 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
index 00000000..d56e5543
--- /dev/null
+++ b/lib/readline/search.c
@@ -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
index 00000000..e3d93a04
--- /dev/null
+++ b/lib/readline/signals.c
@@ -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 */
+
+
+/* **************************************************************** */
+/* */
+/* 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
index 00000000..da75d957
--- /dev/null
+++ b/lib/readline/tilde.c
@@ -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);
+}
+
+
+#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
index 00000000..726d081b
--- /dev/null
+++ b/lib/readline/tilde.h
@@ -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
index 00000000..b8b3123a
--- /dev/null
+++ b/lib/readline/vi_keymap.c
@@ -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
index 00000000..d0b93107
--- /dev/null
+++ b/lib/readline/vi_mode.c
@@ -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)
+
+/* **************************************************************** */
+/* */
+/* 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
index 00000000..4f6dc762
--- /dev/null
+++ b/lib/readline/xmalloc.c
@@ -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
index 00000000..b87de8d8
--- /dev/null
+++ b/lib/termcap/Makefile
@@ -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
index 00000000..a43ea212
--- /dev/null
+++ b/lib/termcap/grot/COPYING
@@ -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.
+
+ 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.)
+
+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.
+
+ 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.
+
+ 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
+
+ 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
index 00000000..3a8b8448
--- /dev/null
+++ b/lib/termcap/grot/ChangeLog
@@ -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.
+
+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
index 00000000..014e0f72
--- /dev/null
+++ b/lib/termcap/grot/INSTALL
@@ -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
index 00000000..309603d6
--- /dev/null
+++ b/lib/termcap/grot/Makefile.in
@@ -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
index 00000000..c696fdf5
--- /dev/null
+++ b/lib/termcap/grot/NEWS
@@ -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.
+
+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
index 00000000..9db9095b
--- /dev/null
+++ b/lib/termcap/grot/README
@@ -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
index 00000000..bc34d0ab
--- /dev/null
+++ b/lib/termcap/grot/configure
@@ -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
index 00000000..1c2aaf2a
--- /dev/null
+++ b/lib/termcap/grot/configure.in
@@ -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
index 00000000..f8515f19
--- /dev/null
+++ b/lib/termcap/grot/termcap.info
@@ -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.
+
+
+Indirect:
+termcap.info-1: 912
+termcap.info-2: 47539
+termcap.info-3: 90314
+termcap.info-4: 138449
+
+Tag Table:
+(Indirect)
+Node: Top912
+Node: Introduction4143
+Node: Library5870
+Node: Preparation6889
+Node: Find8072
+Node: Interrogate11620
+Node: Initialize16928
+Node: Padding18568
+Node: Why Pad19274
+Node: Not Enough20896
+Node: Describe Padding23464
+Node: Output Padding24954
+Node: Parameters28569
+Node: Encode Parameters30229
+Node: Using Parameters36313
+Node: tparam36908
+Node: tgoto38934
+Node: Data Base41489
+Node: Format42385
+Node: Capability Format44474
+Node: Naming47539
+Node: Inheriting52108
+Node: Changing54352
+Node: Capabilities55516
+Node: Basic58255
+Node: Screen Size62308
+Node: Cursor Motion64048
+Node: Wrapping74190
+Node: Scrolling77015
+Node: Windows82904
+Node: Clearing83638
+Node: Insdel Line85402
+Node: Insdel Char90314
+Node: Standout100299
+Node: Underlining109357
+Node: Cursor Visibility111776
+Node: Bell112524
+Node: Keypad113073
+Node: Meta Key117794
+Node: Initialization118748
+Node: Pad Specs121112
+Node: Status Line123165
+Node: Half-Line125049
+Node: Printer125851
+Node: Summary127530
+Node: Var Index137736
+Node: Cap Index138449
+Node: Index145507
+
+End Tag Table
diff --git a/lib/termcap/grot/termcap.info-1 b/lib/termcap/grot/termcap.info-1
new file mode 100644
index 00000000..8390359c
--- /dev/null
+++ b/lib/termcap/grot/termcap.info-1
@@ -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.
+
+
+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.
+
+
+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
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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'.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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::.
+
+
+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.
+
+
+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.
+
+
+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);
+
+
+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.
+
+
+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.
+
+
+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".
+
+
+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.
+
+
+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".
+
+
+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
index 00000000..7142dc87
--- /dev/null
+++ b/lib/termcap/grot/termcap.info-2
@@ -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.
+
+
+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'.
+
+
+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:
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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::.
+
+
+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.
+
+
+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'.
+
+
+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
index 00000000..c1e6af99
--- /dev/null
+++ b/lib/termcap/grot/termcap.info-3
@@ -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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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'.
+
+
+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.
+
+
+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".
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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
index 00000000..21dd81c6
--- /dev/null
+++ b/lib/termcap/grot/termcap.info-4
@@ -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.
+
+
+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.
+
+
+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
index 00000000..d9918389
--- /dev/null
+++ b/lib/termcap/grot/termcap.texi
@@ -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
index 00000000..d10917e2
--- /dev/null
+++ b/lib/termcap/grot/texinfo.tex
@@ -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 `\=\other
+\catcode `\=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\ =\other
+\catcode `\^^L=\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 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
index 00000000..3d6125a1
--- /dev/null
+++ b/lib/termcap/termcap.c
@@ -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 */
+
+/* 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;
+}
+
+/* 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);
+}
+
+/* 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;
+}
+
+#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
index 00000000..e9d9361c
--- /dev/null
+++ b/lib/termcap/termcap.h
@@ -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
index 00000000..4badb65a
--- /dev/null
+++ b/lib/termcap/tparam.c
@@ -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
+
+#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 */
+
+/* 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;
+}
+
+#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
index 00000000..51336dbd
--- /dev/null
+++ b/lib/termcap/version.c
@@ -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
index 00000000..986db67a
--- /dev/null
+++ b/lib/tilde/ChangeLog
@@ -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
index 00000000..50b4285d
--- /dev/null
+++ b/lib/tilde/Makefile
@@ -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
index 00000000..4e158bfe
--- /dev/null
+++ b/lib/tilde/doc/Makefile
@@ -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
index 00000000..e69de29b
--- /dev/null
+++ b/lib/tilde/doc/tilde.texi
diff --git a/lib/tilde/memalloc.h b/lib/tilde/memalloc.h
new file mode 100644
index 00000000..750d53df
--- /dev/null
+++ b/lib/tilde/memalloc.h
@@ -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
index 00000000..da75d957
--- /dev/null
+++ b/lib/tilde/tilde.c
@@ -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);
+}
+
+
+#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
index 00000000..726d081b
--- /dev/null
+++ b/lib/tilde/tilde.h
@@ -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
index 00000000..7fe1ff9e
--- /dev/null
+++ b/machines.h
@@ -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
index 00000000..78f657db
--- /dev/null
+++ b/mailcheck.c
@@ -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
index 00000000..85eb3d59
--- /dev/null
+++ b/make_cmd.c
@@ -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
index 00000000..21187702
--- /dev/null
+++ b/make_cmd.h
@@ -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
index 00000000..6677309f
--- /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
index 00000000..92c06481
--- /dev/null
+++ b/memalloc.h
@@ -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
index 00000000..bdba4807
--- /dev/null
+++ b/newversion.c
@@ -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
index 00000000..e5e8d2c0
--- /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
index 00000000..9c4c75ac
--- /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;
+}
+
+
+/*
+ * 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 */
+
+/* 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));
+}
+
+
+/* **************************************************************** */
+/* */
+/* 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);
+}
+
+/* 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
index 00000000..e69de29b
--- /dev/null
+++ b/parser-built
diff --git a/parser.h b/parser.h
new file mode 100644
index 00000000..247d78ec
--- /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
index 00000000..93a9348d
--- /dev/null
+++ b/portbash/README
@@ -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
index 00000000..28429b3d
--- /dev/null
+++ b/portbash/libc.sh
@@ -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
index 00000000..77e82321
--- /dev/null
+++ b/portbash/mkdesc.sh
@@ -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
index 00000000..5198dd60
--- /dev/null
+++ b/portbash/pgrp.c
@@ -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
index 00000000..bcdb5ff8
--- /dev/null
+++ b/portbash/signals.sh
@@ -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
index 00000000..6a1be936
--- /dev/null
+++ b/portbash/stdio.sh
@@ -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
index 00000000..99a686a4
--- /dev/null
+++ b/portbash/strings.sh
@@ -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
index 00000000..e89a7422
--- /dev/null
+++ b/portbash/syscalls.sh
@@ -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
index 00000000..7d1cece3
--- /dev/null
+++ b/posixstat.h
@@ -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
index 00000000..b70e8d4c
--- /dev/null
+++ b/print_cmd.c
@@ -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
index 00000000..57de7a00
--- /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
index 00000000..5d4150d0
--- /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
index 00000000..26b20c0c
--- /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
index 00000000..b7d31322
--- /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
index 00000000..7571cf08
--- /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
index 00000000..b52d7adf
--- /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
index 00000000..f5216d5a
--- /dev/null
+++ b/signames.c
@@ -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
index 00000000..5dcc32bf
--- /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
index 00000000..9dd00a84
--- /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
index 00000000..6584ef97
--- /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
index 00000000..18694726
--- /dev/null
+++ b/support/PORTING
@@ -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
index 00000000..bd36b7e0
--- /dev/null
+++ b/support/SYMLINKS
@@ -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
index 00000000..5c32613e
--- /dev/null
+++ b/support/bash.xbm
@@ -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
index 00000000..fb5600b9
--- /dev/null
+++ b/support/bashbug.sh
@@ -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
index 00000000..87ba1634
--- /dev/null
+++ b/support/cat-s
@@ -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
index 00000000..89e07526
--- /dev/null
+++ b/support/clone-bash
@@ -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
index 00000000..b0a951c2
--- /dev/null
+++ b/support/cppmagic
@@ -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
index 00000000..b82ca4dd
--- /dev/null
+++ b/support/fixlinks
@@ -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
index 00000000..eb4c72d8
--- /dev/null
+++ b/support/getcppsyms.c
@@ -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
index 00000000..95f28bc1
--- /dev/null
+++ b/support/inpath
@@ -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
index 00000000..ea88212b
--- /dev/null
+++ b/support/install.sh
@@ -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
index 00000000..52228d1e
--- /dev/null
+++ b/support/mkdirs
@@ -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
index 00000000..612aa99a
--- /dev/null
+++ b/support/mklinks
@@ -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
index 00000000..00b7403a
--- /dev/null
+++ b/support/mkmachtype
@@ -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
index 00000000..37b188eb
--- /dev/null
+++ b/support/mksysdefs
@@ -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
index 00000000..8aebd437
--- /dev/null
+++ b/support/printenv
@@ -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
index 00000000..b9dc00b3
--- /dev/null
+++ b/support/recho.c
@@ -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
index 00000000..9d8ccd71
--- /dev/null
+++ b/support/srcdir
@@ -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
index 00000000..12281e5e
--- /dev/null
+++ b/support/texi2dvi
@@ -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
index 00000000..d8356f1b
--- /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
index 00000000..a1a081be
--- /dev/null
+++ b/tests/README
@@ -0,0 +1 @@
+Type `sh run-all'.
diff --git a/tests/dollar-at.sh b/tests/dollar-at.sh
new file mode 100755
index 00000000..c3004d50
--- /dev/null
+++ b/tests/dollar-at.sh
@@ -0,0 +1 @@
+recho "$@"
diff --git a/tests/dollar-star.sh b/tests/dollar-star.sh
new file mode 100755
index 00000000..982f04c3
--- /dev/null
+++ b/tests/dollar-star.sh
@@ -0,0 +1 @@
+recho "$*"
diff --git a/tests/dollar.right b/tests/dollar.right
new file mode 100644
index 00000000..4d9b7467
--- /dev/null
+++ b/tests/dollar.right
@@ -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
index 00000000..d45b7024
--- /dev/null
+++ b/tests/exp-tests
@@ -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 ''`
+expect "<^A>"
+recho `echo ""`
+expect "<^B>"
+recho `echo ''`
+expect "<^B>"
+recho `echo ""`
+expect "<^A>"
+recho `echo `
+expect "<^B>"
+recho `echo `
+
+# 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 
+expect "<^B>"
+recho 
+expect "<^A>"
+recho ""
+expect "<^B>"
+recho ""
+expect "<^A>"
+recho ''
+expect "<^B>"
+recho ''
+
+# 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 "\"
+
+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 ' ' | 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 ''
+expect '<^A^A>'
+recho ''
+expect '<^A^B>'
+recho ''
+expect '<^A^A^B>'
+recho ''
+
+# 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
index 00000000..f34e88a7
--- /dev/null
+++ b/tests/exp.right
@@ -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
index 00000000..e8c1c706
--- /dev/null
+++ b/tests/glob-test
@@ -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
index 00000000..4f2acbb9
--- /dev/null
+++ b/tests/glob.right
@@ -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
index 00000000..a153ce94
--- /dev/null
+++ b/tests/ifs-test-1.sh
@@ -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
index 00000000..3249f1bf
--- /dev/null
+++ b/tests/ifs-test-2.sh
@@ -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
index 00000000..4693792a
--- /dev/null
+++ b/tests/ifs-test-3.sh
@@ -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
index 00000000..af0abb2c
--- /dev/null
+++ b/tests/ifs.1.right
@@ -0,0 +1 @@
+a:b:c
diff --git a/tests/ifs.2.right b/tests/ifs.2.right
new file mode 100644
index 00000000..af0abb2c
--- /dev/null
+++ b/tests/ifs.2.right
@@ -0,0 +1 @@
+a:b:c
diff --git a/tests/ifs.3.right b/tests/ifs.3.right
new file mode 100644
index 00000000..af0abb2c
--- /dev/null
+++ b/tests/ifs.3.right
@@ -0,0 +1 @@
+a:b:c
diff --git a/tests/input-line.sh b/tests/input-line.sh
new file mode 100644
index 00000000..086d7e31
--- /dev/null
+++ b/tests/input-line.sh
@@ -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
index 00000000..7bc8df29
--- /dev/null
+++ b/tests/input-line.sub
@@ -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
index 00000000..8733febe
--- /dev/null
+++ b/tests/input.right
@@ -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
index 00000000..be67ec58
--- /dev/null
+++ b/tests/minus-e
@@ -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
index 00000000..45b983be
--- /dev/null
+++ b/tests/minus-e.right
@@ -0,0 +1 @@
+hi
diff --git a/tests/misc/chld-trap.sh b/tests/misc/chld-trap.sh
new file mode 100755
index 00000000..89b342dc
--- /dev/null
+++ b/tests/misc/chld-trap.sh
@@ -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
index 00000000..eab465ef
--- /dev/null
+++ b/tests/misc/dot-test-1.sh
@@ -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
index 00000000..58df5f4f
--- /dev/null
+++ b/tests/misc/dot-test-1.sub
@@ -0,0 +1 @@
+echo this is dot-test-1.sub
diff --git a/tests/misc/gotest b/tests/misc/gotest
new file mode 100644
index 00000000..df0a342e
--- /dev/null
+++ b/tests/misc/gotest
@@ -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
index 00000000..e1172a9d
--- /dev/null
+++ b/tests/misc/perf-script
@@ -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
index 00000000..0ea00f92
--- /dev/null
+++ b/tests/misc/redir.t1.sh
@@ -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
index 00000000..44b2624e
--- /dev/null
+++ b/tests/misc/redir.t2.sh
@@ -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
index 00000000..9fd42c79
--- /dev/null
+++ b/tests/misc/redir.t3.sh
@@ -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
index 00000000..b32fbaa8
--- /dev/null
+++ b/tests/misc/redir.t3.sub
@@ -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
index 00000000..861acdd8
--- /dev/null
+++ b/tests/misc/redir.t4.sh
@@ -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
index 00000000..bf22fe32
--- /dev/null
+++ b/tests/misc/run.r1.sh
@@ -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
index 00000000..3b247018
--- /dev/null
+++ b/tests/misc/run.r2.sh
@@ -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
index 00000000..b4136742
--- /dev/null
+++ b/tests/misc/run.r3.sh
@@ -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
index 00000000..7b74c307
--- /dev/null
+++ b/tests/misc/sigint.t1.sh
@@ -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
index 00000000..69eaf56a
--- /dev/null
+++ b/tests/misc/sigint.t2.sh
@@ -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
index 00000000..2627fe6c
--- /dev/null
+++ b/tests/misc/sigint.t3.sh
@@ -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
index 00000000..587dd265
--- /dev/null
+++ b/tests/misc/sigint.t4.sh
@@ -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
index 00000000..03d7ecfc
--- /dev/null
+++ b/tests/misc/test-minus-e.1
@@ -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
index 00000000..ad6a0c81
--- /dev/null
+++ b/tests/misc/test-minus-e.2
@@ -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
index 00000000..07e2e9c6
--- /dev/null
+++ b/tests/new-exp.right
@@ -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
index 00000000..f19ecf6c
--- /dev/null
+++ b/tests/new-exp.tests
@@ -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
index 00000000..e6af552c
--- /dev/null
+++ b/tests/prec.right
@@ -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
index 00000000..9bbdb971
--- /dev/null
+++ b/tests/precedence
@@ -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
index 00000000..7add6881
--- /dev/null
+++ b/tests/run-all
@@ -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
index 00000000..00ad7f10
--- /dev/null
+++ b/tests/run-dollars
@@ -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
index 00000000..b95f6033
--- /dev/null
+++ b/tests/run-exp-tests
@@ -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
index 00000000..1e598dc7
--- /dev/null
+++ b/tests/run-glob-test
@@ -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
index 00000000..1f9c8c06
--- /dev/null
+++ b/tests/run-ifs-tests
@@ -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
index 00000000..25d63a0f
--- /dev/null
+++ b/tests/run-input-test
@@ -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
index 00000000..51d3229c
--- /dev/null
+++ b/tests/run-minus-e
@@ -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
index 00000000..ef57d320
--- /dev/null
+++ b/tests/run-new-exp
@@ -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
index 00000000..9303e873
--- /dev/null
+++ b/tests/run-precedence
@@ -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
index 00000000..1afef169
--- /dev/null
+++ b/tests/run-set-e-test
@@ -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
index 00000000..8c97f6ff
--- /dev/null
+++ b/tests/run-strip
@@ -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
index 00000000..04aece91
--- /dev/null
+++ b/tests/run-varenv
@@ -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
index 00000000..ce3feb06
--- /dev/null
+++ b/tests/set-e-test
@@ -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
index 00000000..92cb7af0
--- /dev/null
+++ b/tests/set-e.right
@@ -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
index 00000000..dfab897f
--- /dev/null
+++ b/tests/strip.right
@@ -0,0 +1,12 @@
+''
+' ab '
+' '
+''
+''
+''
+'ababababababab'
+'ababababababab '
+'ababababababab '
+'abababa
+bababab '
+''
diff --git a/tests/strip.tests b/tests/strip.tests
new file mode 100644
index 00000000..b669b52e
--- /dev/null
+++ b/tests/strip.tests
@@ -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
index 00000000..a5107514
--- /dev/null
+++ b/tests/tilde-tests
@@ -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
index 00000000..2920187e
--- /dev/null
+++ b/tests/tilde.right
@@ -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
index 00000000..74ce5d30
--- /dev/null
+++ b/tests/varenv.right
@@ -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
index 00000000..d6bd4e52
--- /dev/null
+++ b/tests/varenv.sh
@@ -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
index 00000000..c2b951b3
--- /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
index 00000000..16702316
--- /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
index 00000000..d9399d7d
--- /dev/null
+++ b/unwind_prot.c
@@ -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
index 00000000..e0136315
--- /dev/null
+++ b/unwind_prot.h
@@ -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
index 00000000..2c911c2c
--- /dev/null
+++ b/variables.c
@@ -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
index 00000000..8f4ef3ed
--- /dev/null
+++ b/variables.h
@@ -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
index 00000000..8ba1db76
--- /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
index 00000000..9907936b
--- /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
index 00000000..0b1fd090
--- /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
+
+#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
+
+#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"
+
+ 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;
+}
+
+
+/*
+ * 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 */
+
+/* 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));
+}
+
+
+/* **************************************************************** */
+/* */
+/* 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);
+}
+
+/* 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
index 00000000..7ba3b282
--- /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;