Port readline lib into gnu system tree.
authorAndrey Chernov <ache@FreeBSD.org>
Mon, 9 May 1994 15:59:10 +0000 (15:59 +0000)
committerAndrey Chernov <ache@FreeBSD.org>
Mon, 9 May 1994 15:59:10 +0000 (15:59 +0000)
Really we don't need copy of this library into each program
(gdb f.e.)

P.S. it is much cleaner port than /usr/ports version and based
on /usr/ports version. /usr/ports version will be removed.

30 files changed:
gnu/lib/libreadline/COPYING [new file with mode: 0644]
gnu/lib/libreadline/ChangeLog [new file with mode: 0644]
gnu/lib/libreadline/Makefile [new file with mode: 0644]
gnu/lib/libreadline/README.FreeBSD [new file with mode: 0644]
gnu/lib/libreadline/VERSION [new file with mode: 0644]
gnu/lib/libreadline/doc/Makefile [new file with mode: 0644]
gnu/lib/libreadline/doc/hist.texinfo [new file with mode: 0644]
gnu/lib/libreadline/doc/history.dvi [new file with mode: 0644]
gnu/lib/libreadline/doc/hstech.texinfo [new file with mode: 0644]
gnu/lib/libreadline/doc/hsuser.texinfo [new file with mode: 0644]
gnu/lib/libreadline/doc/readline.dvi [new file with mode: 0644]
gnu/lib/libreadline/doc/rlman.texinfo [new file with mode: 0644]
gnu/lib/libreadline/doc/rltech.texinfo [new file with mode: 0644]
gnu/lib/libreadline/doc/rluser.texinfo [new file with mode: 0644]
gnu/lib/libreadline/doc/texinfo.tex [new file with mode: 0644]
gnu/lib/libreadline/emacs_keymap.c [new file with mode: 0644]
gnu/lib/libreadline/examples/Makefile [new file with mode: 0644]
gnu/lib/libreadline/examples/fileman.c [new file with mode: 0644]
gnu/lib/libreadline/examples/manexamp.c [new file with mode: 0644]
gnu/lib/libreadline/funmap.c [new file with mode: 0644]
gnu/lib/libreadline/history.c [new file with mode: 0644]
gnu/lib/libreadline/history.h [new file with mode: 0644]
gnu/lib/libreadline/keymaps.c [new file with mode: 0644]
gnu/lib/libreadline/readline.c [new file with mode: 0644]
gnu/lib/libreadline/readline/chardefs.h [new file with mode: 0644]
gnu/lib/libreadline/readline/keymaps.h [new file with mode: 0644]
gnu/lib/libreadline/readline/readline.h [new file with mode: 0644]
gnu/lib/libreadline/tcsh_hack.readme [new file with mode: 0644]
gnu/lib/libreadline/vi_keymap.c [new file with mode: 0644]
gnu/lib/libreadline/vi_mode.c [new file with mode: 0644]

diff --git a/gnu/lib/libreadline/COPYING b/gnu/lib/libreadline/COPYING
new file mode 100644 (file)
index 0000000..1bb82d1
--- /dev/null
@@ -0,0 +1,257 @@
+
+                   GNU GENERAL PUBLIC LICENSE
+                    Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+                   675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+The Free Software Foundation has exempted Bash from the requirement of
+Paragraph 2c of the General Public License.  This is to say, there is
+no requirement for Bash to print a notice when it is started
+interactively in the usual way.         We made this exception because users
+and standards expect shells not to print such messages.         This
+exception applies to any program that serves as a shell and that is
+based primarily on Bash as opposed to other GNU software.
+
+                           Preamble
+
+  The license agreements of most software companies try to keep users
+at the mercy of those companies.  By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must tell them their rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License.  The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications.  Each
+licensee is addressed as "you".
+
+  1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program.         You may charge a fee for the physical act of
+transferring a copy.
+
+  2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+    a) cause the modified files to carry prominent notices stating that
+    you changed the files and the date of any change; and
+
+    b) cause the whole of any work that you distribute or publish, that
+    in whole or in part contains the Program or any part thereof, either
+    with or without modifications, to be licensed at no charge to all
+    third parties under the terms of this General Public License (except
+    that you may choose to grant warranty protection to some or all
+    third parties, at your option).
+
+    c) If the modified program normally reads commands interactively when
+    run, you must cause it, when started running for such interactive use
+    in the simplest and most usual way, to print or display an
+    announcement including an appropriate copyright notice and a notice
+    that there is no warranty (or else, saying that you provide a
+    warranty) and that users may redistribute the program under these
+    conditions, and telling the user how to view a copy of this General
+    Public License.
+
+    d) You may charge a fee for the physical act of transferring a
+    copy, and you may at your option offer warranty protection in
+    exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+\f
+  3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+    a) accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    b) accompany it with a written offer, valid for at least three
+    years, to give any third party free (except for a nominal charge
+    for the cost of distribution) a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    c) accompany it with the information you received as to where the
+    corresponding source code may be obtained. (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it.  For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+  4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License.         However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+  5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions.  You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+\f
+  7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+  8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+  To do so, attach the following notices to the program.  It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 1, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19xx name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License.  Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  program `Gnomovision' (a program to direct compilers to make passes
+  at assemblers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/gnu/lib/libreadline/ChangeLog b/gnu/lib/libreadline/ChangeLog
new file mode 100644 (file)
index 0000000..67c5df8
--- /dev/null
@@ -0,0 +1,120 @@
+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/gnu/lib/libreadline/Makefile b/gnu/lib/libreadline/Makefile
new file mode 100644 (file)
index 0000000..5be1dc5
--- /dev/null
@@ -0,0 +1,22 @@
+#       $Id: Makefile,v 1.1 1993/12/28 07:54:51 ache Exp $
+
+SHLIB_MAJOR=1
+SHLIB_MINOR=0
+
+CFLAGS+= -I${.CURDIR} -I${.CURDIR}/readline -DVOID_SIGHANDLER -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp
+
+LIB=    readline
+SRCS+=  readline.c history.c funmap.c keymaps.c
+NOMAN= noman
+
+beforeinstall:
+       @-if [ ! -d ${DESTDIR}/usr/include/readline ]; then \
+         mkdir ${DESTDIR}/usr/include/readline; \
+         chown ${BINOWN}.${BINGRP} ${DESTDIR}/usr/include/readline; \
+         chmod 755 ${DESTDIR}/usr/include/readline; \
+       fi
+       cd ${.CURDIR}/readline; \
+       install -c -o ${BINOWN} -g ${BINGRP} -m 444 \
+       readline.h keymaps.h chardefs.h ${DESTDIR}/usr/include/readline
+
+.include <bsd.lib.mk>
diff --git a/gnu/lib/libreadline/README.FreeBSD b/gnu/lib/libreadline/README.FreeBSD
new file mode 100644 (file)
index 0000000..7c917b0
--- /dev/null
@@ -0,0 +1,14 @@
+The GNU Readline library is a programming tool that provides a
+consistent user interface for recalling lines of previously typed
+input and performing editing tasks on input lines.
+
+paul@freefall.cdrom.com
+
+There was a bug with tcsh: when readline attempt to get tty
+modes from background, it got no-echo editing tcsh mode.
+
+Workaround for this implemented via TIOCGWINSZ/TIOCSWINSZ
+with same winsize structure: it does nothing expect polling
+process from background. Look tcsh_hack.readme for details.
+
+ache@astral.msk.su
diff --git a/gnu/lib/libreadline/VERSION b/gnu/lib/libreadline/VERSION
new file mode 100644 (file)
index 0000000..b3803cc
--- /dev/null
@@ -0,0 +1 @@
+readline-1.1
diff --git a/gnu/lib/libreadline/doc/Makefile b/gnu/lib/libreadline/doc/Makefile
new file mode 100644 (file)
index 0000000..786e099
--- /dev/null
@@ -0,0 +1,30 @@
+# This makefile for Readline library documentation is in -*- text -*- mode.
+# Emacs likes it that way.
+
+DVIOBJ = readline.dvi history.dvi
+INFOBJ = readline.info history.info
+
+all: $(DVIOBJ) $(INFOBJ)
+
+readline.dvi: rlman.texinfo rluser.texinfo rltech.texinfo
+       tex rlman.texinfo
+       tex rlman.texinfo
+       mv rlman.dvi readline.dvi
+
+history.dvi: hist.texinfo hsuser.texinfo hstech.texinfo
+       tex hist.texinfo
+       tex hist.texinfo
+       mv hist.dvi history.dvi
+
+readline.info: rlman.texinfo rluser.texinfo rltech.texinfo
+       makeinfo rlman.texinfo
+
+history.info: hist.texinfo hsuser.texinfo hstech.texinfo
+       makeinfo hist.texinfo
+
+clean:
+       rm -f *.log *.cp *.ky *.tp *.vr *.fn *.aux *.pg *.toc core
+
+squeaky-clean:
+       rm -f *.log *.cp *.ky *.tp *.vr *.fn *.aux *.pg *.toc core *.dvi *.~* *.info
+
diff --git a/gnu/lib/libreadline/doc/hist.texinfo b/gnu/lib/libreadline/doc/hist.texinfo
new file mode 100644 (file)
index 0000000..d110374
--- /dev/null
@@ -0,0 +1,106 @@
+\input texinfo    @c -*-texinfo-*-
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename history.info
+@settitle GNU Readline Library
+@comment %**end of header (This is for running Texinfo on a region.)
+@synindex fn vr
+@setchapternewpage odd
+
+@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
+@center @titlefont{GNU History Library}
+@center Brian Fox
+@center Free Software Foundation
+@center Version 1.1
+@center April 1991
+
+@c Include the Distribution inside the titlepage environment so
+@c that headings are turned off. 
+
+@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
+
+@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/gnu/lib/libreadline/doc/history.dvi b/gnu/lib/libreadline/doc/history.dvi
new file mode 100644 (file)
index 0000000..637e9ed
Binary files /dev/null and b/gnu/lib/libreadline/doc/history.dvi differ
diff --git a/gnu/lib/libreadline/doc/hstech.texinfo b/gnu/lib/libreadline/doc/hstech.texinfo
new file mode 100644 (file)
index 0000000..c3fe3f6
--- /dev/null
@@ -0,0 +1,311 @@
+@ignore
+This file documents the user interface to the GNU History library.
+
+Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+Authored by Brian Fox.
+
+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 the GNU History Library with
+programs that you write.  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 making up new
+ones.
+
+The programmer using the History library has available to him functions
+for remembering lines on a history stack, associating arbitrary data
+with a line, removing lines from the stack, searching through the stack
+for a line containing an arbitrary text string, and referencing any line
+on the stack directly.  In addition, a history @dfn{expansion} function
+is available which provides for a consistent user interface across many
+different programs.
+
+The end-user using programs written with the History library has the
+benifit 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 used 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 Emacs style command line editing.
+
+@node History Storage
+@section History Storage
+
+@example
+typedef struct _hist_entry @{
+  char *line;
+  char *data;
+@} HIST_ENTRY;
+@end example
+
+@node History Functions
+@section History Functions
+
+This section describes the calling sequence for the various functions
+present in GNU History.
+
+@defun {void using_history} ()
+Begin a session in which the history functions might be used.  This
+just initializes the interactive variables.
+@end defun
+
+@defun {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 defun
+
+@defun {int where_history} ()
+Returns the number which says what history element we are now looking
+at.
+@end defun
+  
+@defun {int history_set_pos} (int pos)
+Set the position in the history list to @var{pos}.
+@end defun
+
+@defun {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.  @var{direction}, if negative, says to search
+backwards from @var{pos}, else forwards.  Returns the absolute index of
+the history element where @var{string} was found, or -1 otherwise.
+@end defun
+
+@defun {HIST_ENTRY *remove_history} ();
+Remove history element @var{which} from the history.  The removed
+element is returned to you so you can free the line, data,
+and containing structure.
+@end defun
+
+@defun {void stifle_history} (int max)
+Stifle the history list, remembering only @var{max} number of entries.
+@end defun
+
+@defun {int unstifle_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.
+@end defun
+
+@defun {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 defun
+
+@defun {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 the @var{from}'th line and end at the @var{to}'th.  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 defun
+
+@defun {int write_history} (char *filename)
+Append the current history to @var{filename}.  If @var{filename} is
+@code{NULL}, then append the history list to @file{~/.history}.  Values
+returned are as in @code{read_history ()}.
+@end defun
+
+@defun {int append_history} (int nelements, char *filename)
+Append @var{nelement} entries to @var{filename}.  The entries appended
+are from the end of the list minus @var{nelements} up to the end of the
+list.
+@end defun
+
+@defun {HIST_ENTRY *replace_history_entry} ()
+Make the history entry at @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 defun
+
+@defun {HIST_ENTRY *current_history} ()
+Return the history entry at the current position, as determined by
+@code{history_offset}.  If there is no entry there, return a @code{NULL}
+pointer.
+@end defun
+
+@defun {HIST_ENTRY *previous_history} ()
+Back up @var{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 defun
+
+@defun {HIST_ENTRY *next_history} ()
+Move @code{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 defun
+
+@defun {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 defun
+
+@defun {int history_search} (char *string, int direction)
+Search the history for @var{string}, starting at @code{history_offset}.
+If @var{direction} < 0, then the search is through previous entries,
+else through subsequent.  If @var{string} is found, then
+@code{current_history ()} is the history entry, and the value of this
+function is the offset in the line of that history entry that the
+@var{string} was found in.  Otherwise, nothing is changed, and a -1 is
+returned.
+@end defun
+
+@defun {int history_expand} (char *string, char **output)
+Expand @var{string}, placing the result into @var{output}, a pointer
+to a string.  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, or
+@item -1
+if there was an error in expansion.
+@end table
+
+If an error ocurred in expansion, then @var{output} contains a descriptive
+error message.
+@end defun
+
+@defun {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
+the GNU Bash shell.
+@end defun
+
+@defun {int history_total_bytes} ();
+Return the number of bytes that the primary history entries are using.
+This just adds up the lengths of @code{the_history->lines}.
+@end defun
+
+@node History Variables
+@section History Variables
+
+This section describes the variables in GNU History that are externally
+visible.
+
+@defvar {int history_base}
+For convenience only.  You set this when interpreting history commands.
+It is the logical offset of the first history element.
+@end defvar
+
+@node History Programming Example
+@section History Programming Example
+
+The following snippet of code demonstrates simple use of the GNU History
+Library.
+
+@smallexample
+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");
+            @}
+        @}
+    @}
+@}
+@end smallexample
+
+
+
diff --git a/gnu/lib/libreadline/doc/hsuser.texinfo b/gnu/lib/libreadline/doc/hsuser.texinfo
new file mode 100644 (file)
index 0000000..cda0a68
--- /dev/null
@@ -0,0 +1,153 @@
+@ignore
+This file documents the user interface to the GNU History library.
+
+Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+Authored by Brian Fox.
+
+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
+
+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}.
+
+@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 in Csh.  The following text describes the sytax
+that you use 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 the Bash shell 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 susbstitution.
+@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.
+
+@table @asis
+
+@item @code{!}
+Start a history subsititution, except when followed by a space, tab, or
+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 line @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}.
+
+@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 zero'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, excepting the zero'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.
+
+@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 #
+The entire command line typed so far.  This means the current command,
+not the previous command, so it really isn't a word designator, and doesn't
+belong in this section.
+
+@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 suffix.
+
+@item t
+Remove all leading  pathname  components, leaving the tail.
+
+@item p
+Print the new command but do not execute it.
+@end table
diff --git a/gnu/lib/libreadline/doc/readline.dvi b/gnu/lib/libreadline/doc/readline.dvi
new file mode 100644 (file)
index 0000000..347fbd0
Binary files /dev/null and b/gnu/lib/libreadline/doc/readline.dvi differ
diff --git a/gnu/lib/libreadline/doc/rlman.texinfo b/gnu/lib/libreadline/doc/rlman.texinfo
new file mode 100644 (file)
index 0000000..9ac246d
--- /dev/null
@@ -0,0 +1,103 @@
+\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 fn vr
+@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, 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
+@center @titlefont{GNU Readline Library}
+@center Brian Fox
+@center Free Software Foundation
+@center Version 1.1
+@center April 1991
+
+@page
+This document describes the GNU Readline Library, a utility for aiding
+in the consistency of user interface across discrete programs that need
+to provide a command line interface.
+
+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 for aiding
+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
+@appendix Concept Index
+@printindex cp
+
+@node Function and Variable Index
+@appendix Function and Variable Index
+@printindex vr
+@contents
+
+@bye
+
diff --git a/gnu/lib/libreadline/doc/rltech.texinfo b/gnu/lib/libreadline/doc/rltech.texinfo
new file mode 100644 (file)
index 0000000..f52288e
--- /dev/null
@@ -0,0 +1,1010 @@
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename rltech.info
+@synindex fn vr
+@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 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 manual describes the interface between the GNU Readline Library and
+user programs.  If you are a programmer, and you wish to include the
+features found in GNU Readline in your own programs, such as completion,
+line editing, and interactive history manipulation, this documentation
+is for you.
+
+@menu
+* Default Behaviour::  Using the default behaviour of Readline.
+* Custom Functions::   Adding your own functions to Readline.
+* Custom Completers::  Supplanting or supplementing Readline's
+                       completion functions.
+@end menu
+
+@node Default Behaviour
+@section Default Behaviour
+
+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 ()}.
+
+@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 which @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
+
+So, one might say
+@example
+@code{char *line = readline ("Enter a line: ");}
+@end example
+in order to read a line of text from the user.
+
+The line which is returned has the final newline removed, so only the
+text of the line remains.
+
+If 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 was 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
+
+For full details on the GNU History Library, see the associated manual.
+
+It is polite to avoid saving empty lines on the history list, since it
+is rare than someone has a burning need to reuse a blank line.  Here is
+a function which usefully replaces the standard @code{gets ()} library
+function:
+
+@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 *
+do_gets ()
+@{
+  /* If the buffer has already been allocated, return the memory
+     to the free pool. */
+  if (line_read != (char *)NULL)
+    @{
+      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
+
+The above code 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 ()}.
+
+@findex rl_bind_key ()
+@example
+@code{int rl_bind_key (int @var{key}, (int (*)())@var{function});}
+@end example
+
+@code{rl_bind_key ()} takes 2 arguments; @var{key} is the character that
+you want to bind, and @var{function} is the address of the function to
+run when @var{key} is pressed.  Binding @key{TAB} to @code{rl_insert ()}
+makes @key{TAB} just insert itself.
+
+@code{rl_bind_key ()} returns non-zero if @var{key} is not a valid
+ASCII character code (between 0 and 255).
+
+@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, etc.
+
+@node Custom Functions
+@section Custom Functions
+
+Readline provides a great 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 in 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 Naming::    How to give a function you write a name.
+* Keymaps::            Making keymaps.
+* Binding Keys::       Changing Keymaps.
+* Function Writing::   Variables and calling conventions.
+* Allowing Undoing::   How to make your functions undoable.
+@end menu
+
+@node The Function Type
+@subsection The Function Type
+
+For the sake of readabilty, we declare a new type of object, called
+@dfn{Function}.  A @code{Function} is a C language 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;}
+
+we have
+
+@code{Function *func;}
+
+@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:
+
+@defun 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 defun
+
+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 already.  If you need to do more or different
+things 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.
+
+@defun {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 defun
+
+@defun {Keymap rl_copy_keymap} (Keymap map)
+Return a new keymap which is a copy of @var{map}.
+@end defun
+
+@defun {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 defun
+
+@node Binding Keys
+@subsection Binding Keys
+
+You associate keys with functions through the keymap.  Here are
+functions for doing that.
+
+@defun {int rl_bind_key} (int key, Function *function)
+Binds @var{key} to @var{function} in the currently selected keymap.
+Returns non-zero in the case of an invalid @var{key}.
+@end defun
+
+@defun {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 defun
+
+@defun {int rl_unbind_key} (int key)
+Make @var{key} do nothing in the currently selected keymap.
+Returns non-zero in case of error.
+@end defun
+
+@defun {int rl_unbind_key_in_map} (int key, Keymap map)
+Make @var{key} be bound to the null function in @var{map}.
+Returns non-zero in case of error.
+@end defun
+
+@defun 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}; right now this can be a function (@code{ISFUNC}), a macro
+(@code{ISMACR}), or a keymap (@code{ISKMAP}).  This makes new keymaps as
+necessary.  The initial place to do bindings is in @var{map}.
+@end defun
+
+@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 gathered so far.
+
+@defvar {char *rl_line_buffer}
+This is the line gathered so far.  You are welcome to modify the
+contents of this, but see Undoing, below.
+@end defvar
+
+@defvar {int rl_point}
+The offset of the current cursor position in @var{rl_line_buffer}.
+@end defvar
+
+@defvar {int rl_end}
+The number of characters present in @code{rl_line_buffer}.  When
+@code{rl_point} is at the end of the line, then @code{rl_point} and
+@code{rl_end} are equal.
+@end defvar
+
+The calling sequence for a command @code{foo} looks like
+
+@example
+@code{foo (int count, int key)}
+@end example
+
+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, other
+functions as a flag, and 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 a negative argument as well as a positive
+argument.  At the very least, it should be aware that it can be passed a
+negative argument.
+
+@node Allowing Undoing
+@subsection Allowing Undoing
+
+Supporting the undo command is a painless thing to do, and makes your
+functions much more useful to the end user.  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 it
+calls @code{rl_insert_text ()} or @code{rl_delete_text ()} to do it, then
+undoing is already done for you automatically, and you can safely skip
+this section.
+
+If you do multiple insertions or multiple deletions, or any combination
+of these operations, you should group them together into one operation.
+This can be done with @code{rl_begin_undo_group ()} and
+@code{rl_end_undo_group ()}.
+
+@defun 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 they could be direct calls to
+@code{rl_add_undo ()}.
+@end defun
+
+@defun rl_end_undo_group ()
+Closes the current undo group started with @code{rl_begin_undo_group
+()}.  There should be exactly one call to @code{rl_end_undo_group ()}
+for every call to @code{rl_begin_undo_group ()}.
+@end defun
+
+Finally, if you neither insert nor delete text, but directly modify the
+existing text (e.g. change its case), you 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.
+
+@defun 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 subsequent to this call you will
+modify that range of text in some way.
+@end defun
+
+@subsection An Example
+
+Here is a function which changes lowercase characters to the uppercase
+equivalents, and uppercase characters to the lowercase equivalents.  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{10 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. */
+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;
+@}
+@end example
+
+@node Custom Completers
+@section Custom Completers
+
+Typically, a program that reads commands from the user has a way of
+disambiguating between commands and data.  If your program is one of
+these, then it can provide completion for either commands, or data, or
+both commands and data.  The following sections describe how your
+program and Readline cooperate to provide this service to end users.
+
+@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 to say, it is not possible to accurately
+expand a partial word without knowing what all of the possible words
+that make sense in that context are.  The GNU Readline library provides
+the user interface to completion, and additionally, 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 those functions must do, and provides an example
+function.
+
+There are three major functions used to perform completion:
+
+@enumerate
+@item
+The user-interface function @code{rl_complete ()}.  This function is
+called interactively with the same calling conventions as other
+functions in readline intended for interactive use; i.e. @var{count},
+and @code{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 or actually performs the
+completion, depending on which behaviour 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, 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.
+
+@end enumerate
+
+@defun 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 defun
+
+Note that @code{rl_complete ()} has the identical calling conventions as
+any other key-invokable function; this is because by default it is bound
+to the @samp{TAB} key.
+
+@defvar {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 is
+used, namely @code{filename_entry_function ()}.
+@end defvar
+
+@node Completion Functions
+@subsection Completion Functions
+
+Here is the complete list of callable completion functions present in
+Readline.
+
+@defun 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.
+@end defun
+
+@defun 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.  This just calls @code{rl_complete_internal ()} with an
+argument of @samp{TAB}.
+@end defun
+
+@defun rl_possible_completions ()
+List the possible completions.  See description of @code{rl_complete
+()}.  This just calls @code{rl_complete_internal ()} with an argument of
+@samp{?}.
+@end defun
+
+@defun {char **completion_matches} (char *text, char *(*entry_function) ())
+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_function} 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.  It returns a @code{NULL}  pointer to the caller when there are
+no more matches.
+@end defun
+
+@defun {char *filename_completion_function} (char *text, int state)
+A generator function for filename completion in the general case.  Note
+that completion in the Bash shell is a little different because of all
+the pathnames that must be followed when looking up the completion for a
+command.
+@end defun
+
+@defun {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{~}).
+@end defun
+
+@node Completion Variables
+@subsection Completion Variables
+
+@defvar {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 defvar
+
+@defvar {Function *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} 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 defvar
+
+@defvar {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 defvar
+
+@defvar {char *rl_basic_word_break_characters}
+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 Bash shell, i.e. " \t\n\"\\'`@@$><=".
+@end defvar
+
+@defvar {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 contents of
+@code{rl_basic_word_break_characters}.
+@end defvar
+
+@defvar {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.
+@end defvar
+
+@defvar {int rl_ignore_completion_duplicates}
+If non-zero, then disallow duplicates in the matches.  Default is 1.
+@end defvar
+
+@defvar {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.
+@end defvar
+
+@defvar {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 pointers to @code{(char *)}
+known as @var{matches} in the code.  The 1st element (@code{matches[0]})
+is the maximal substring that is common to all matches. This function
+can re-arrange the list of matches as required, but each deleted
+element of the array must be @code{free()}'d.
+@end defvar
+
+@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{readline/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 <readline/readline.h>
+#include <readline/history.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+
+/* 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 @}
+@};
+
+/* 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 = 0;
+@page
+main (argc, argv)
+     int argc;
+     char **argv;
+@{
+  progname = argv[0];
+
+  initialize_readline ();       /* Bind our completer. */
+
+  /* Loop reading and executing lines until the user quits. */
+  while (!done)
+    @{
+      char *line;
+
+      line = readline ("FileMan: ");
+
+      if (!line)
+        @{
+          done = 1;             /* Encountered EOF at top level. */
+        @}
+      else
+        @{
+          /* Remove leading and trailing whitespace from the line.
+             Then, if there is anything left, add it to the history list
+             and execute it. */
+          stripwhite (line);
+
+          if (*line)
+            @{
+              add_history (line);
+              execute_line (line);
+            @}
+        @}
+
+      if (line)
+        free (line);
+    @}
+  exit (0);
+@}
+
+/* Execute a command line. */
+execute_line (line)
+     char *line;
+@{
+  register int i;
+  COMMAND *find_command (), *command;
+  char *word;
+
+  /* Isolate the command word. */
+  i = 0;
+  while (line[i] && !whitespace (line[i]))
+    i++;
+
+  word = line;
+
+  if (line[i])
+    line[i++] = '\0';
+
+  command = find_command (word);
+
+  if (!command)
+    @{
+      fprintf (stderr, "%s: No such command for FileMan.\n", word);
+      return;
+    @}
+
+  /* Get argument to command, if any. */
+  while (whitespace (line[i]))
+    i++;
+
+  word = line + i;
+
+  /* Call the function. */
+  (*(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. */
+stripwhite (string)
+     char *string;
+@{
+  register int i = 0;
+
+  while (whitespace (string[i]))
+    i++;
+
+  if (i)
+    strcpy (string, string + i);
+
+  i = strlen (string) - 1;
+
+  while (i > 0 && whitespace (string[i]))
+    i--;
+
+  string[++i] = '\0';
+@}
+@page
+/* **************************************************************** */
+/*                                                                  */
+/*                  Interface to Readline 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 ()
+@{
+  char **fileman_completion ();
+
+  /* Allow conditional parsing of the ~/.inputrc file. */
+  rl_readline_name = "FileMan";
+
+  /* Tell the completer that we want a crack first. */
+  rl_attempted_completion_function = (Function *)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;
+  char *command_generator ();
+
+  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 (name);
+    @}
+
+  /* If no names matched, then return NULL. */
+  return ((char *)NULL);
+@}
+@page
+/* **************************************************************** */
+/*                                                                  */
+/*                       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;
+@{
+  sprintf (syscom, "ls -FClg %s", arg);
+  system (syscom);
+@}
+
+com_view (arg)
+     char *arg;
+@{
+  if (!valid_argument ("view", arg))
+    return;
+
+  sprintf (syscom, "cat %s | more", arg);
+  system (syscom);
+@}
+
+com_rename (arg)
+     char *arg;
+@{
+  too_dangerous ("rename");
+@}
+
+com_stat (arg)
+     char *arg;
+@{
+  struct stat finfo;
+
+  if (!valid_argument ("stat", arg))
+    return;
+
+  if (stat (arg, &finfo) == -1)
+    @{
+      perror (arg);
+      return;
+    @}
+
+  printf ("Statistics for `%s':\n", arg);
+
+  printf ("%s has %d link%s, and is %d bytes in length.\n", arg,
+          finfo.st_nlink, (finfo.st_nlink == 1) ? "" : "s",  finfo.st_size);
+  printf ("      Created on: %s", ctime (&finfo.st_ctime));
+  printf ("  Last access at: %s", ctime (&finfo.st_atime));
+  printf ("Last modified at: %s", ctime (&finfo.st_mtime));
+@}
+
+com_delete (arg)
+     char *arg;
+@{
+  too_dangerous ("delete");
+@}
+
+/* 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");
+    @}
+@}
+
+/* Change to the directory ARG. */
+com_cd (arg)
+     char *arg;
+@{
+  if (chdir (arg) == -1)
+    perror (arg);
+
+  com_pwd ("");
+@}
+
+/* Print out the current working directory. */
+com_pwd (ignore)
+     char *ignore;
+@{
+  char dir[1024];
+
+  (void) getwd (dir);
+
+  printf ("Current directory is %s\n", dir);
+@}
+
+/* The user wishes to quit using this program.  Just set DONE non-zero. */
+com_quit (arg)
+     char *arg;
+@{
+  done = 1;
+@}
+
+/* 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/gnu/lib/libreadline/doc/rluser.texinfo b/gnu/lib/libreadline/doc/rluser.texinfo
new file mode 100644 (file)
index 0000000..ea20205
--- /dev/null
@@ -0,0 +1,489 @@
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename rluser.info
+@synindex fn vr
+@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 feautres.  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.
+
+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
+
+@node Command Line Editing
+@chapter Command Line Editing
+
+This text describes GNU's 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.
+@end menu
+
+@node Introduction and Notation
+@section Introduction to Line Editing
+
+In this tex a the following notation is used to describe 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 @key{DEL} 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.  Aftwerwards, 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 get `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 get `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 itself 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
+
+The act of @dfn{cutting} text means to delete the text from the line, and
+to save away the deleted text for later use, just as if you had cut the
+text out of the line with a pair of scissors.  There is a
+
+@dfn{Killing} text means to delete the text from the line, but to save
+it away for later use, usually by @dfn{yanking} 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.
+
+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 fromthe cursor the start ofthe 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
+is
+
+@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
+
+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 in one clean sweep.  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.
+
+@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, 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
+file is @file{~/.inputrc}.
+
+When a program which uses the Readline library starts up, the
+@file{~/.inputrc} file is read, and the keybindings are set.
+
+@menu
+* Readline Init Syntax::       Syntax for the commands in @file{~/.inputrc}.
+* Readline Vi Mode::           Switching to @code{vi} mode in Readline.
+@end menu
+
+@node Readline Init Syntax
+@subsection Readline Init Syntax
+
+You can start up with a vi-like editing mode by placing
+
+@example
+@code{set editing-mode vi}
+@end example
+
+in your @file{~/.inputrc} file.
+
+You can have Readline use a single line for display, scrolling the input
+between the two edges of the screen by placing
+
+@example
+@code{set horizontal-scroll-mode On}
+@end example
+
+in your @file{~/.inputrc} file.
+
+The syntax for controlling keybindings in the @file{~/.inputrc} file is
+simple.  First you have to know the @i{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 @file{~/.inputrc} file.  Here is an example:
+
+@example
+# This is a comment line.
+Meta-Rubout:   backward-kill-word
+Control-u:     universal-argument
+@end example
+
+@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.
+* Miscellaneous Commands::     Other miscillaneous commands.
+@end menu
+
+@node Commands For Moving
+@subsubsection Commands For Moving
+@table @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.
+
+@item backward-word (M-b)
+Move back to the start of this, or the previous, word.
+
+@item clear-screen (C-l)
+Clear the screen leaving the current line at the top of the screen.
+
+@end table
+
+@node Commands For History
+@subsubsection Commands For Manipulating The History
+
+@table @code
+@item accept-line (Newline, Return)
+Accept the line regardless of where the cursor is.  If this line is
+non-empty, add it too the history list.  If this line was a history
+line, then restore the history line to its original state.
+
+@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 neccessary.
+
+@end table
+
+@node Commands For Text
+@subsubsection Commands For Changing Text
+
+@table @code
+@item delete-char (C-d)
+Delete the character under the cursor.  If the cursor is at the
+beginning of the line, and 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 things like 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 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 args 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 point.
+
+@item downcase-word (M-l)
+Lowercase the current (or following) word.  With a negative argument,
+do the previous word, but do not move point.
+
+@item capitalize-word (M-c)
+Uppercase the current (or following) word.  With a negative argument,
+do the previous word, but do not move point.
+
+@end table
+
+@node Commands For Killing
+@subsubsection Killing And Yanking
+
+@table @code
+
+@item kill-line (C-k)
+Kill the text from the current cursor position to the end of the line.
+
+@item backward-kill-line ()
+Kill backward to the beginning of the line.  This is normally 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.
+
+@item backward-kill-word (M-DEL)
+Kill the word behind the cursor.
+
+@item unix-line-discard (C-u)
+Do what C-u used to do in Unix line input.  We save the killed text on
+the kill-ring, though.
+
+@item unix-word-rubout (C-w)
+Do what C-w used to do in Unix line input.  The killed text is saved
+on the kill-ring.  This is different than backward-kill-word because
+the word boundaries differ.
+
+@item yank (C-y)
+Yank the top of the kill ring into the buffer at point.
+
+@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 table
+
+@node Numeric Arguments
+@subsubsection Specifying Numeric Arguments
+@table @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 ()
+Do what C-u does in emacs.  By default, this is not bound.
+@end table
+
+
+@node Commands For Completion
+@subsubsection Letting Readline Type For You
+
+@table @code
+@item complete (TAB)
+Attempt to do completion on the text before point.  This is
+implementation defined.  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...
+
+@item possible-completions (M-?)
+List the possible completions of the text before point.
+@end table
+
+@node Miscellaneous Commands
+@subsubsection Some Miscellaneous Commands
+@table @code
+
+@item abort (C-g)
+Ding!  Stops things.
+
+@item do-uppercase-version (M-a, M-b, ...)
+Run the command that is bound to your uppercase brother.
+
+@item prefix-meta (ESC)
+Make the next character that you type be metafied.  This is for
+people without a meta key.  @key{ESC-f} is equivalent to @key{M-f}.
+
+@item undo (C-_)
+Incremental undo, separately remembered for each line.
+
+@item 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.
+@end table
+
+@node Readline Vi Mode
+@subsection 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.
+
+In order to switch interactively between Emacs and Vi editing modes, use
+the command M-C-j (toggle-editing-mode).
+
+When you enter a line in Vi mode, you are already placed in `insertion'
+mode, as if you had typed an `i'.  Pressing @key{ESC} switches you into
+`edit' 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.
diff --git a/gnu/lib/libreadline/doc/texinfo.tex b/gnu/lib/libreadline/doc/texinfo.tex
new file mode 100644 (file)
index 0000000..638e7c5
--- /dev/null
@@ -0,0 +1,2735 @@
+%% TeX macros to handle texinfo files
+
+%   Copyright (C) 1985, 1986, 1988, 1990, 1991 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 1, 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.41}
+\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
+
+\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
+
+%---------------------Begin change-----------------------
+%
+% 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
+\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}
+
+
+% 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
+                \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 can be delimited with [...] or with "..." or braces
+% or it can be a whole line.
+% #1 should be a macro which expects
+% an ordinary undelimited TeX argument.
+
+\def\parsearg #1{\let\next=#1\begingroup\obeylines\futurelet\temp\parseargx}
+
+\def\parseargx{%
+\ifx \obeyedspace\temp \aftergroup\parseargdiscardspace \else%
+\aftergroup \parseargline %
+\fi \endgroup}
+
+{\obeyspaces %
+\gdef\parseargdiscardspace {\begingroup\obeylines\futurelet\temp\parseargx}}
+
+\gdef\obeyedspace{\ }
+
+\def\parseargline{\begingroup \obeylines \parsearglinex}
+{\obeylines %
+\gdef\parsearglinex #1^^M{\endgroup \next {#1}}}
+
+\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.
+%% foo can be delimited by doublequotes or brackets.
+
+\def\end{\parsearg\endxxx}
+
+\def\endxxx #1{%
+\expandafter\ifx\csname E#1\endcsname\relax
+\expandafter\ifx\csname #1\endcsname\relax
+\errmessage{Undefined command @end #1}\else
+\errorE{#1}\fi\fi
+\csname E#1\endcsname}
+\def\errorE#1{
+{\errhelp=\EMsimple \errmessage{@end #1 not within #1 environment}}}
+
+% 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}}
+
+% 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
+\def\w #1{\hbox{#1}}
+
+% @group ... @end group  forces ... to be all on one page.
+
+\def\group{\begingroup% \inENV ???
+\def \Egroup{\egroup\endgroup}
+\vbox\bgroup}
+
+% @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}
+
+\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
+}}
+
+% @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
+
+\def\exdent{\errmessage{@exdent in filled text}}
+  % @lisp, etc, define \exdent locally from \internalexdent
+
+{\obeyspaces
+\gdef\internalexdent{\parsearg\exdentzzz}}
+
+\def\exdentzzz #1{{\advance \leftskip by -\lispnarrowing
+\advance \hsize by -\leftskip
+\advance \hsize by -\rightskip
+\leftline{{\rm#1}}}}
+
+% @include file    insert text of that file as input.
+
+\def\include{\parsearg\includezzz}
+\def\includezzz #1{{\def\thisfile{#1}\input #1
+}}
+
+\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
+}
+
+\def\ignore{\begingroup\ignoresections\ignorexxx}
+\long\def\ignorexxx #1\end ignore{\endgroup\ignorespaces}
+
+\def\direntry{\begingroup\direntryxxx}
+\long\def\direntryxxx #1\end direntry{\endgroup\ignorespaces}
+
+% Conditionals to test whether a flag is set.
+
+\outer\def\ifset{\begingroup\ignoresections\parsearg\ifsetxxx}
+
+\def\ifsetxxx #1{\endgroup
+\expandafter\ifx\csname IF#1\endcsname\relax \let\temp=\ifsetfail
+\else \let\temp=\relax \fi
+\temp}
+\def\Eifset{}
+\def\ifsetfail{\begingroup\ignoresections\ifsetfailxxx}
+\long\def\ifsetfailxxx #1\end ifset{\endgroup\ignorespaces}
+
+\outer\def\ifclear{\begingroup\ignoresections\parsearg\ifclearxxx}
+
+\def\ifclearxxx #1{\endgroup
+\expandafter\ifx\csname IF#1\endcsname\relax \let\temp=\relax
+\else \let\temp=\ifclearfail \fi
+\temp}
+\def\Eifclear{}
+\def\ifclearfail{\begingroup\ignoresections\ifclearfailxxx}
+\long\def\ifclearfailxxx #1\end ifclear{\endgroup\ignorespaces}
+
+% Some texinfo constructs that are trivial in tex
+
+\def\iftex{}
+\def\Eiftex{}
+\def\ifinfo{\begingroup\ignoresections\ifinfoxxx}
+\long\def\ifinfoxxx #1\end ifinfo{\endgroup\ignorespaces}
+
+\long\def\menu #1\end menu{}
+\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}
+
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\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{\losespace#3{}}, node \samp{\losespace#1{}}}
+\def\losespace #1{#1}
+
+\message{fonts,}
+
+% Font-change commands.
+
+%% Try out Computer Modern fonts at \magstephalf
+\font\tenrm=cmr10 scaled \magstephalf
+\font\tentt=cmtt10 scaled \magstephalf
+% 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\tenbf=cmb10 scaled \magstephalf 
+\font\tenit=cmti10 scaled \magstephalf
+\font\tensl=cmsl10 scaled \magstephalf
+\font\tensf=cmss10 scaled \magstephalf
+\def\li{\sf}
+\font\tensc=cmcsc10 scaled \magstephalf
+
+% Fonts for @defun, etc.
+\font\defbf=cmbx10 scaled \magstep1 %was 1314
+\font\deftt=cmtt10 scaled \magstep1
+\def\df{\let\tt=\deftt \defbf}
+
+% 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.
+\font\ninett=cmtt9
+\font\indit=cmsl9 \font\indrm=cmr9
+\let\indtt=\ninett
+\def\indbf{\indrm} \def\indsl{\indit}
+\def\indexfonts{\let\it=\indit \let\sl=\indsl \let\bf=\indbf \let\rm=\indrm
+\let\tt=\indtt}
+
+% 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\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\ssecrm=cmbx10 scaled \magstep1    % This size an fontlooked 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 for title
+% There seems to have been a confusion: two definitions of this font.
+% It is not clear why, or which one is better.
+\font\titlerm = cmbx12 scaled \magstep3
+\let\authorrm = \secrm
+
+\def\textfonts{\let\rm=\tenrm\let\it=\tenit\let\sl=\tensl\let\bf=\tenbf%
+\let\smallcaps=\tensc\let\sf=\tensf}
+\def\chapfonts{\let\rm=\chaprm\let\it=\chapit\let\sl=\chapsl\let\bf=\chapbf\let\tt=\chaptt\let\sf=\chapsf}
+\def\secfonts{\let\rm=\secrm\let\it=\secit\let\sl=\secsl\let\bf=\secbf\let\tt=\sectt\let\sf=\secsf}
+\def\subsecfonts{\let\rm=\ssecrm\let\it=\ssecit\let\sl=\ssecsl\let\bf=\ssecbf\let\tt=\ssectt\let\sf=\ssecsf}
+% 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
+
+\def\t#1{{\tt \exhyphenpenalty=10000\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 \exhyphenpenalty=10000\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.
+\newdimen\tclosesave
+\newdimen\tcloserm
+\def\tclose#1{{\rm \tcloserm=\fontdimen2\font \tt \tclosesave=\fontdimen2\font
+\fontdimen2\font=\tcloserm
+% prevent breaking lines at hyphens.
+\exhyphenpenalty=10000
+\def\ {{\fontdimen2\font=\tclosesave{} }}%
+ \rawbackslash \frenchspacing #1\fontdimen2\font=\tclosesave}\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}
+
+\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}}
+
+\newtoks\realeverypar
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+\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, @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 and @ftable 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 -\leftskip %
+\setbox0=\hbox{\itemfont{#1}}%
+\itemindex{#1}%
+\parskip=0in %
+\noindent %
+\ifdim \wd0>\itemmax %
+\vadjust{\penalty 10000}%
+\hbox to \hsize{\hskip -\tableindent\box0\hss}\ %
+\else %
+\hbox to 0pt{\hskip -\tableindent\box0\hss}%
+\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\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\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 %
+\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{\itemizey {#1}{\Eitemize}}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\begingroup %
+\itemno = 0 %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\endgroup\afterenvbreak}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+\def\bullet{$\ptexbullet$}
+\def\minus{$-$}
+
+% 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 }
+
+\def\enumerate{\itemizey{\the\itemno.}\Eenumerate\flushcr}
+
+% 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 300}}%
+\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 normalunderscore}}%
+\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}}%
+}
+
+% \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{%
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\count10=\lastpenalty %
+\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{%
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\count10=\lastpenalty %
+\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
+\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 empty)
+\else \closein 1 \input \jobname.#1s
+\fi
+\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
+
+\outer\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}}
+
+\outer\def\entry #1#2{
+{\parfillskip=0in \parskip=0in \parindent=0in
+\hangindent=1in \hangafter=1%
+\noindent\hbox{#1}\indexdotfill #2\par
+}}
+
+% 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  \doublecolumnhsize = 3.11in
+\newdimen\doublecolumnvsize  \doublecolumnvsize = 19.1in
+\newdimen\availdimen@
+
+\def\begindoublecolumns{\begingroup
+  \output={\global\setbox\partialpage=\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}\eject
+  \output={\doublecolumnout} \hsize=\doublecolumnhsize \vsize=\doublecolumnvsize}
+\def\enddoublecolumns{\output={\balancecolumns}\eject
+  \endgroup \pagegoal=\vsize}
+
+\def\doublecolumnout{\splittopskip=\topskip \splitmaxdepth=\maxdepth
+  \dimen@=\pageheight \advance\dimen@ by-\ht\partialpage
+  \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+  \onepageout\pagesofar \unvbox255 \penalty\outputpenalty}
+\def\pagesofar{\unvbox\partialpage %
+  \hsize=\doublecolumnhsize % have to restore this since output routine
+%            changes it to set cropmarks (P. A. MacKay, 12 Nov. 1986)
+  \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}}
+\def\balancecolumns{%
+% Unset the glue.
+  \setbox255=\vbox{\unvbox255}
+  \dimen@=\ht255
+  \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+  \divide\dimen@ by2
+  \availdimen@=\pageheight \advance\availdimen@ by-\ht\partialpage
+% If the remaining data is too big for one page,
+% output one page normally, then work with what remains.
+  \ifdim \dimen@>\availdimen@
+   {
+     \splittopskip=\topskip \splitmaxdepth=\maxdepth
+     \dimen@=\pageheight \advance\dimen@ by-\ht\partialpage
+     \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+     \onepageout\pagesofar
+   }
+% Recompute size of what remains, in case we just output some of it.
+  \dimen@=\ht255
+  \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
+  \divide\dimen@ by2
+  \fi
+  \setbox0=\vbox{\unvbox255}
+  \splittopskip=\topskip
+  {\vbadness=10000 \loop \global\setbox3=\copy0
+    \global\setbox1=\vsplit3 to\dimen@
+    \ifdim\ht3>\dimen@ \global\advance\dimen@ by1pt \repeat}
+  \setbox0=\vbox to\dimen@{\unvbox1}  \setbox2=\vbox to\dimen@{\unvbox3}
+  \pagesofar}
+
+\catcode `\@=\other
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno
+\newcount \subsecno
+\newcount \subsubsecno
+
+% 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\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}}
+}
+
+\outer\def\chapter{\parsearg\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 %
+}}
+
+\outer\def\appendix{\parsearg\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 %
+}}
+
+\outer\def\top{\parsearg\unnumberedzzz}
+\outer\def\unnumbered{\parsearg\unnumberedzzz}
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0 \message{(#1)}
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp  %
+\unnumbnoderef %
+}}
+
+\outer\def\section{\parsearg\sectionzzz}
+\def\sectionzzz #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\appendixsection{\parsearg\appendixsectionzzz}
+\outer\def\appendixsec{\parsearg\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\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\subsection{\parsearg\subsectionzzz}
+\def\subsectionzzz #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\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\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\subsubsection{\parsearg\subsubsectionzzz}
+\def\subsubsectionzzz #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\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\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.
+\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}
+
+% Define @majorheading, @heading and @subheading
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \line{\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
+    \leftline{\rm #2\enspace #1}%
+  }%
+  \bigskip
+  \penalty5000
+}
+
+\def\unnchfplain #1{%
+\pchapsepmacro %
+{\chapfonts \line{\rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \line{\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}}
+
+
+% 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 \line{\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 \line{\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 \line{\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.
+
+\def\startcontents#1{%
+   \ifnum \pageno>0
+      \pagealignmacro
+      \immediate\closeout \contentsfile
+      \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 -1in    % 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}}
+\def\shortchapentry#1#2#3{%
+   \line{{#2\labelspace #1}\dotfill\doshortpageno{#3}}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{%
+   \line{#1\dotfill\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
+   \line{\chapentryfonts #1\dotfill \dopageno{#2}}%
+   \nobreak\vskip .25\baselineskip
+}
+
+\def\dosecentry#1#2{%
+   \line{\secentryfonts \hskip\tocindent #1\dotfill \dopageno{#2}}%
+}
+
+\def\dosubsecentry#1#2{%
+   \line{\subsecentryfonts \hskip2\tocindent #1\dotfill \dopageno{#2}}%
+}
+
+\def\dosubsubsecentry#1#2{%
+   \line{\subsubsecentryfonts \hskip3\tocindent #1\dotfill \dopageno{#2}}%
+}
+
+% 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\copy\dblarrowbox}
+\def\expansion{\leavevmode\raise.1ex\copy\longdblarrowbox}
+\def\print{\leavevmode\lower.1ex\copy\pushcharbox}
+
+\def\equiv{\leavevmode\lower.1ex\copy\equivbox}
+
+% Does anyone really want this?
+% \def\bull{\leavevmode\copy\bullbox}
+
+% 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}}
+
+% Cause \obeyspaces to make each Space cause a word-separation
+% rather than the default which is that it acts punctuation.
+% This is because space in tt font looks funny.
+{\obeyspaces %
+\gdef\sepspaces{\def {\ }}}
+
+\newskip\aboveenvskipamount \aboveenvskipamount= 0pt
+\def\aboveenvbreak{{\advance\aboveenvskipamount by \parskip
+\endgraf \ifdim\lastskip<\aboveenvskipamount
+\removelastskip \penalty-50 \vskip\aboveenvskipamount \fi}}
+
+\def\afterenvbreak{\endgraf \ifdim\lastskip<\aboveenvskipamount
+\removelastskip \penalty-50 \vskip\aboveenvskipamount \fi}
+
+\def\lisp{\aboveenvbreak\begingroup\inENV %This group ends at the end of the @lisp body
+\hfuzz=12truept % Don't be fussy
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Elisp{\endgroup\afterenvbreak}%
+\parskip=0pt
+\advance \leftskip by \lispnarrowing
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines \tt \rawbackslash
+\def\next##1{}\next}
+
+
+\let\example=\lisp
+\def\Eexample{\Elisp}
+
+\let\smallexample=\lisp
+\def\Esmallexample{\Elisp}
+
+% Macro for 9 pt. examples, necessary to print with 5" lines.
+% From Pavel@xerox.  This is not really used unless the
+% @smallbook command is given.
+
+\def\smalllispx{\aboveenvbreak\begingroup\inENV
+%                      This group ends at the end of the @lisp body
+\hfuzz=12truept % Don't be fussy
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Esmalllisp{\endgroup\afterenvbreak}%
+\parskip=0pt
+\advance \leftskip by \lispnarrowing
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines \ninett \indexfonts \rawbackslash
+\def\next##1{}\next}
+
+% This is @display; same as @lisp except use roman font.
+
+\def\display{\begingroup\inENV %This group ends at the end of the @display body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% Single space lines
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Edisplay{\endgroup\afterenvbreak}%
+\parskip=0pt
+\advance \leftskip by \lispnarrowing
+\parindent=0pt
+\let\exdent=\internalexdent
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% This is @format; same as @lisp except use roman font and don't narrow margins
+
+\def\format{\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+\singlespace %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+\let\par=\lisppar
+\def\Eformat{\endgroup\afterenvbreak}
+\parskip=0pt \parindent=0pt
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% @flushleft and @flushright
+
+\def\flushleft{\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+% This also causes @ to work when the directive name
+% is terminated by end of line.
+\let\par=\lisppar
+\def\Eflushleft{\endgroup\afterenvbreak}%
+\parskip=0pt \parindent=0pt
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+\def\flushright{\begingroup\inENV %This group ends at the end of the @format body
+\aboveenvbreak
+% Make spaces be word-separators rather than space tokens.
+\sepspaces %
+% The following causes blank lines not to be ignored
+% by adding a space to the end of each line.
+% This also causes @ to work when the directive name
+% is terminated by end of line.
+\let\par=\lisppar
+\def\Eflushright{\endgroup\afterenvbreak}%
+\parskip=0pt \parindent=0pt
+\advance \leftskip by 0pt plus 1fill
+\obeyspaces \obeylines
+\def\next##1{}\next}
+
+% @quotation - narrow 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}%
+\advance \rightskip by \lispnarrowing 
+\advance \leftskip by \lispnarrowing}
+
+\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}
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+\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}}}%
+\tolerance=10000 \hbadness=10000    % Make all lines underfull and no complaints
+{\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
+\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
+\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
+\begingroup\obeylines\activeparens\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\sl=0
+#1%
+\hyphenchar\sl=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}%
+\defopparsebody\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{\defmethparsebody\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{\defmethparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defparsebody\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{\defparsebody\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{\defparsebody\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{\defmethparsebody\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{\defmethparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+\newif\ifhavexrefs  % True if xref values are known.
+\newif\ifwarnedxrefs  % True if we warned once that they aren't known.
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+\def\appendixsetref#1{%
+%\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Yappendixletterandtype}}
+
+% \xref, \pxref, and \ref generate cross-references to specified points.
+% For \xrefX, #1 is the node name, #2 the name of the Info
+% cross-reference, #3 the printed node name, #4 the name of the Info
+% file, #5 the name of the printed manual.  All but the node name can be
+% omitted.
+% 
+\def\pxref#1{see \xrefX[#1,,,,,,,]}
+\def\xref#1{See \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup%
+\def\printedmanual{\ignorespaces #5}%
+\def\printednodename{\ignorespaces #3}%
+%
+\setbox1=\hbox{\printedmanual}%
+\setbox0=\hbox{\printednodename}%
+\ifdim \wd0=0pt%
+\def\printednodename{\ignorespaces #1}%
+%%% Uncommment the following line to make the actual chapter or section title
+%%% appear inside the square brackets.
+%\def\printednodename{#1-title}%
+\fi%
+%
+%
+% If we use \unhbox0 and \unhbox1 to print the node names, TeX does
+% not insert empty discretionaries after hyphens, which means that it
+% will not find a line break at a hyphen in a node names.  Since some
+% manuals are best written with fairly long node names, containing
+% hyphens, this is a loss.  Therefore, we simply give the text of
+% the node name again, so it is as if TeX is seeing it for the first
+% time.
+\ifdim \wd1>0pt
+section ``\printednodename'' in \cite{\printedmanual}%
+\else%
+\turnoffactive%
+\refx{#1-snt}{} [\printednodename], page\tie\refx{#1-pg}{}%
+\fi
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \turnoffactive so that punctuation chars such as underscore
+% work in node names.
+\def\dosetq #1#2{{\let\folio=0 \turnoffactive%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thischapter}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 Chapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 Section\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+% 
+\ifx\inputlineno\thisisundefined
+  \let\linenumber = \empty % Non-3.0.
+\else
+  \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+
+\def\refx#1#2{%
+  \expandafter\ifx\csname X#1\endcsname\relax
+    % If not defined, say something at least.
+    $\langle$un\-de\-fined$\rangle$%
+    \ifhavexrefs
+      \message{\linenumber Undefined cross reference `#1'.}%
+    \else
+      \ifwarnedxrefs\else
+        \global\warnedxrefstrue
+        \message{Cross reference values unknown; you must run TeX again.}%
+      \fi
+    \fi
+  \else
+    % It's defined, so just use it.
+    \csname X#1\endcsname
+  \fi
+  #2% Output the suffix in any case.
+}
+
+% Read the last existing aux file, if any.  No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+\def\readauxfile{%
+\begingroup
+\catcode `\^^@=\other
+\catcode `\\ 1=\other
+\catcode `\\ 2=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\\v=\other
+\catcode `\^^L=\other
+\catcode `\\ e=\other
+\catcode `\\ f=\other
+\catcode `\\10=\other
+\catcode `\\11=\other
+\catcode `\\12=\other
+\catcode `\\13=\other
+\catcode `\\14=\other
+\catcode `\\15=\other
+\catcode `\\16=\other
+\catcode `\\17=\other
+\catcode `\\18=\other
+\catcode `\\19=\other
+\catcode `\\1a=\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
+% 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
+\fi
+% Open the new aux file.  Tex will close it automatically at exit.
+\openout \auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+\long\gdef\footnote #1{\global\advance \footnoteno by \@ne
+\removelastskip
+\edef\thisfootno{$^{\the\footnoteno}$}%
+\let\@sf\empty
+\ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+\thisfootno\@sf \footnotezzz{#1}}
+% \parsearg\footnotezzz}
+
+\long\gdef\footnotezzz #1{\insert\footins{
+\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
+\footstrut\parindent=\defaultparindent\hang\textindent{\thisfootno}#1\strut}}
+
+}%end \catcode `\@=11
+
+% 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
+\baselineskip 15pt
+\advance\topskip by 1.2cm
+
+% Prevent underfull vbox error messages.
+\vbadness=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 \else
+  \emergencystretch = \hsize
+  \divide\emergencystretch by 45
+\fi
+
+% Use @smallbook to reset parameters for 7x9.5 format
+\def\smallbook{
+\global\lispnarrowing = 0.3in
+\global\baselineskip 12pt
+\global\parskip 3pt plus 1pt
+\global\hsize = 5in
+\global\doublecolumnhsize=2.4in \global\doublecolumnvsize=15.0in
+\global\vsize=7.5in
+\global\tolerance=700
+\global\hfuzz=1pt
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+
+\global\let\smalllisp=\smalllispx
+\global\let\smallexample=\smalllispx
+\global\def\Esmallexample{\Esmalllisp}
+}
+
+%% 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}
+
+% 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\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+\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
diff --git a/gnu/lib/libreadline/emacs_keymap.c b/gnu/lib/libreadline/emacs_keymap.c
new file mode 100644 (file)
index 0000000..0b07fb3
--- /dev/null
@@ -0,0 +1,472 @@
+/* emacs_keymap.c -- the keymap for emacs_mode in readline (). */
+
+/* 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. */
+
+#ifndef 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 },       /* ( */
+  { 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 */
+};
+
+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, (Function *)0x0 }, /* 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, (Function *)0x0 }, /* 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, (Function *)0x0 }, /* 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, (Function *)0x0 }, /* 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, rl_arrow_keys },   /* Meta-[ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-\ */
+  { ISFUNC, (Function *)0x0 }, /* Meta-] */
+  { ISFUNC, (Function *)0x0 }, /* Meta-^ */
+  { ISFUNC, (Function *)0x0 }, /* 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, (Function *)0x0 }, /* Meta-n */
+  { ISFUNC, rl_arrow_keys },   /* Meta-o */
+  { ISFUNC, (Function *)0x0 }, /* 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, (Function *)0x0 }, /* Meta-~ */
+  { ISFUNC, rl_backward_kill_word } /* Meta-rubout */
+};
+
+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 */
+};
diff --git a/gnu/lib/libreadline/examples/Makefile b/gnu/lib/libreadline/examples/Makefile
new file mode 100644 (file)
index 0000000..3d1fc52
--- /dev/null
@@ -0,0 +1,12 @@
+# This is the Makefile for the examples subdirectory of readline. -*- text -*-
+#
+
+EXECUTABLES = fileman
+CFLAGS  = -g -I../..
+LDFLAGS = -g -L..
+
+fileman: fileman.o
+       $(CC) $(LDFLAGS) -o fileman fileman.o -lreadline -ltermcap
+
+fileman.o: fileman.c
+  
diff --git a/gnu/lib/libreadline/examples/fileman.c b/gnu/lib/libreadline/examples/fileman.c
new file mode 100644 (file)
index 0000000..92f3942
--- /dev/null
@@ -0,0 +1,392 @@
+/* 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 <readline/readline.h>
+#include <readline/history.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+
+/* 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 }
+};
+
+/* 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 = 0;
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  progname = argv[0];
+
+  initialize_readline ();      /* Bind our completer. */
+
+  /* Loop reading and executing lines until the user quits. */
+  while (!done)
+    {
+      char *line;
+
+      line = readline ("FileMan: ");
+
+      if (!line)
+       {
+         done = 1;             /* Encountered EOF at top level. */
+       }
+      else
+       {
+         /* Remove leading and trailing whitespace from the line.
+            Then, if there is anything left, add it to the history list
+            and execute it. */
+         stripwhite (line);
+
+         if (*line)
+           {
+             add_history (line);
+             execute_line (line);
+           }
+       }
+
+      if (line)
+       free (line);
+    }
+  exit (0);
+}
+
+/* Execute a command line. */
+execute_line (line)
+     char *line;
+{
+  register int i;
+  COMMAND *find_command (), *command;
+  char *word;
+
+  /* Isolate the command word. */
+  i = 0;
+  while (line[i] && !whitespace (line[i]))
+    i++;
+
+  word = line;
+
+  if (line[i])
+    line[i++] = '\0';
+
+  command = find_command (word);
+
+  if (!command)
+    {
+      fprintf (stderr, "%s: No such command for FileMan.\n", word);
+      return;
+    }
+
+  /* Get argument to command, if any. */
+  while (whitespace (line[i]))
+    i++;
+
+  word = line + i;
+
+  /* Call the function. */
+  (*(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. */
+stripwhite (string)
+     char *string;
+{
+  register int i = 0;
+
+  while (whitespace (string[i]))
+    i++;
+
+  if (i)
+    strcpy (string, string + i);
+
+  i = strlen (string) - 1;
+
+  while (i > 0 && whitespace (string[i]))
+    i--;
+
+  string[++i] = '\0';
+}
+
+/* **************************************************************** */
+/*                                                                  */
+/*                  Interface to Readline 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 ()
+{
+  char **fileman_completion ();
+
+  /* Allow conditional parsing of the ~/.inputrc file. */
+  rl_readline_name = "FileMan";
+
+  /* Tell the completer that we want a crack first. */
+  rl_attempted_completion_function = (Function *)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;
+  char *command_generator ();
+
+  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 (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;
+{
+  sprintf (syscom, "ls -FClg %s", arg);
+  system (syscom);
+}
+
+com_view (arg)
+     char *arg;
+{
+  if (!valid_argument ("view", arg))
+    return;
+
+  sprintf (syscom, "cat %s | more", arg);
+  system (syscom);
+}
+
+com_rename (arg)
+     char *arg;
+{
+  too_dangerous ("rename");
+}
+
+com_stat (arg)
+     char *arg;
+{
+  struct stat finfo;
+
+  if (!valid_argument ("stat", arg))
+    return;
+
+  if (stat (arg, &finfo) == -1)
+    {
+      perror (arg);
+      return;
+    }
+
+  printf ("Statistics for `%s':\n", arg);
+
+  printf ("%s has %d link%s, and is %d bytes in length.\n", arg,
+         finfo.st_nlink, (finfo.st_nlink == 1) ? "" : "s",  finfo.st_size);
+  printf ("      Created on: %s", ctime (&finfo.st_ctime));
+  printf ("  Last access at: %s", ctime (&finfo.st_atime));
+  printf ("Last modified at: %s", ctime (&finfo.st_mtime));
+}
+
+com_delete (arg)
+     char *arg;
+{
+  too_dangerous ("delete");
+}
+
+/* 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");
+    }
+}
+
+/* Change to the directory ARG. */
+com_cd (arg)
+     char *arg;
+{
+  if (chdir (arg) == -1)
+    perror (arg);
+
+  com_pwd ("");
+}
+
+/* Print out the current working directory. */
+com_pwd (ignore)
+     char *ignore;
+{
+  char dir[1024];
+
+  (void) getwd (dir);
+
+  printf ("Current directory is %s\n", dir);
+}
+
+/* The user wishes to quit using this program.  Just set DONE non-zero. */
+com_quit (arg)
+     char *arg;
+{
+  done = 1;
+}
+
+/* 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);
+}
+
+\f
+/*
+ * Local variables:
+ * compile-command: "cc -g -I../.. -L.. -o fileman fileman.c -lreadline -ltermcap"
+ * end:
+ */
diff --git a/gnu/lib/libreadline/examples/manexamp.c b/gnu/lib/libreadline/examples/manexamp.c
new file mode 100644 (file)
index 0000000..b7ec96a
--- /dev/null
@@ -0,0 +1,96 @@
+/* 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 *
+do_gets ()
+{
+  /* If the buffer has already been allocated, return the memory
+     to the free pool. */
+  if (line_read != (char *)NULL)
+    {
+      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/gnu/lib/libreadline/funmap.c b/gnu/lib/libreadline/funmap.c
new file mode 100644 (file)
index 0000000..77fad75
--- /dev/null
@@ -0,0 +1,214 @@
+/* funmap.c -- attach names to functions. */
+
+/* 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 STATIC_MALLOC
+#ifndef STATIC_MALLOC
+extern char *xmalloc (), *xrealloc ();
+#else
+static char *xmalloc (), *xrealloc ();
+#endif
+
+#ifndef BUFSIZ
+#include <stdio.h>
+#endif /* BUFSIZ */
+
+#include "readline.h"
+
+FUNMAP **funmap = (FUNMAP **)NULL;
+static int funmap_size = 0;
+static int funmap_entry = 0;
+
+static FUNMAP default_funmap[] = {
+  { "arrow-key-prefix", rl_arrow_keys },
+  { "redraw-current-line", rl_refresh_line},
+  { "beginning-of-line", rl_beg_of_line },
+  { "backward-char", rl_backward },
+  { "delete-char", rl_delete },
+  { "end-of-line", rl_end_of_line },
+  { "forward-char", rl_forward },
+  { "accept-line", rl_newline },
+  { "kill-line", rl_kill_line },
+  { "clear-screen", rl_clear_screen },
+  { "next-history", rl_get_next_history },
+  { "previous-history", rl_get_previous_history },
+  { "quoted-insert", rl_quoted_insert },
+  { "reverse-search-history", rl_reverse_search_history },
+  { "forward-search-history", rl_forward_search_history },
+  { "transpose-chars", rl_transpose_chars },
+  { "unix-line-discard", rl_unix_line_discard },
+  { "unix-word-rubout", rl_unix_word_rubout },
+  { "yank", rl_yank },
+  { "yank-pop", rl_yank_pop },
+  { "yank-nth-arg", rl_yank_nth_arg },
+  { "backward-delete-char", rl_rubout },
+  { "backward-word", rl_backward_word },
+  { "kill-word", rl_kill_word },
+  { "forward-word", rl_forward_word },
+  { "tab-insert", rl_tab_insert },
+  { "backward-kill-word", rl_backward_kill_word },
+  { "backward-kill-line", rl_backward_kill_line },
+  { "transpose-words", rl_transpose_words },
+  { "digit-argument", rl_digit_argument },
+  { "complete", rl_complete },
+  { "possible-completions", rl_possible_completions },
+  { "do-lowercase-version", rl_do_lowercase_version },
+  { "digit-argument", rl_digit_argument },
+  { "universal-argument", rl_universal_argument },
+  { "abort", rl_abort },
+  { "undo", rl_undo_command },
+  { "upcase-word", rl_upcase_word },
+  { "downcase-word", rl_downcase_word },
+  { "capitalize-word", rl_capitalize_word },
+  { "revert-line", rl_revert_line },
+  { "beginning-of-history", rl_beginning_of_history },
+  { "end-of-history", rl_end_of_history },
+  { "self-insert", rl_insert },
+  { "start-kbd-macro", rl_start_kbd_macro },
+  { "end-kbd-macro", rl_end_kbd_macro },
+  { "re-read-init-file", rl_re_read_init_file },
+#ifdef VI_MODE
+  { "vi-movement-mode", rl_vi_movement_mode },
+  { "vi-insertion-mode", rl_vi_insertion_mode },
+  { "vi-arg-digit", rl_vi_arg_digit },
+  { "vi-prev-word", rl_vi_prev_word },
+  { "vi-next-word", rl_vi_next_word },
+  { "vi-char-search", rl_vi_char_search },
+  { "vi-editing-mode", rl_vi_editing_mode },
+  { "vi-eof-maybe", rl_vi_eof_maybe },
+  { "vi-append-mode", rl_vi_append_mode },
+  { "vi-put", rl_vi_put },
+  { "vi-append-eol", rl_vi_append_eol },
+  { "vi-insert-beg", rl_vi_insert_beg },
+  { "vi-delete", rl_vi_delete },
+  { "vi-comment", rl_vi_comment },
+  { "vi-first-print", rl_vi_first_print },
+  { "vi-fword", rl_vi_fword },
+  { "vi-fWord", rl_vi_fWord },
+  { "vi-bword", rl_vi_bword },
+  { "vi-bWord", rl_vi_bWord },
+  { "vi-eword", rl_vi_eword },
+  { "vi-eWord", rl_vi_eWord },
+  { "vi-end-word", rl_vi_end_word },
+  { "vi-change-case", rl_vi_change_case },
+  { "vi-match", rl_vi_match },
+  { "vi-bracktype", rl_vi_bracktype },
+  { "vi-change-char", rl_vi_change_char },
+  { "vi-yank-arg", rl_vi_yank_arg },
+  { "vi-search", rl_vi_search },
+  { "vi-search-again", rl_vi_search_again },
+  { "vi-dosearch", rl_vi_dosearch },
+  { "vi-subst", rl_vi_subst },
+  { "vi-overstrike", rl_vi_overstrike },
+  { "vi-overstrike-delete", rl_vi_overstrike_delete },
+  { "vi-replace, ", rl_vi_replace },
+  { "vi-column", rl_vi_column },
+  { "vi-delete-to", rl_vi_delete_to },
+  { "vi-change-to", rl_vi_change_to },
+  { "vi-yank-to", rl_vi_yank_to },
+  { "vi-complete", rl_vi_complete },
+#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;
+}
+
+static int funmap_initialized = 0;
+
+/* Make the funmap contain all of the default entries. */
+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;
+}
+
+/* Things that mean `Control'. */
+char *possible_control_prefixes[] = {
+  "Control-", "C-", "CTRL-", (char *)NULL
+};
+
+char *possible_meta_prefixes[] = {
+  "Meta", "M-", (char *)NULL
+};
+
+#ifdef STATIC_MALLOC
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp = (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/gnu/lib/libreadline/history.c b/gnu/lib/libreadline/history.c
new file mode 100644 (file)
index 0000000..97df610
--- /dev/null
@@ -0,0 +1,1646 @@
+/* History.c -- standalone history library */
+
+/* Copyright (C) 1989 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. */
+
+/* Remove these declarations when we have a complete libgnu.a. */
+#define STATIC_MALLOC
+#ifndef STATIC_MALLOC
+extern char *xmalloc (), *xrealloc ();
+#else
+static char *xmalloc (), *xrealloc ();
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#if defined (sparc) && defined (sun)
+#include <alloca.h>
+#else
+extern char *alloca ();
+#endif
+#endif
+
+#include "history.h"
+
+#ifndef savestring
+#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 member
+#define member(c, s) ((c) ? index ((s), (c)) : 0)
+#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. */
+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;
+
+/* 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;
+
+  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)
+       return;
+
+      /* If there is something in the slot, then remove it. */
+      if (the_history[0])
+       {
+         free (the_history[0]->line);
+         free (the_history[0]);
+       }
+
+      for (i = 0; i < history_length; i++)
+       the_history[i] = the_history[i + 1];
+
+      history_base++;
+
+    }
+  else
+    {
+      if (!history_size)
+       {
+         the_history = (HIST_ENTRY **)
+           xmalloc ((history_size = DEFAULT_HISTORY_GROW_SIZE)
+                    * sizeof (HIST_ENTRY *));
+         history_length = 1;
+
+       }
+      else
+       {
+         if (history_length == (history_size - 1))
+           {
+             the_history = (HIST_ENTRY **)
+               xrealloc (the_history,
+                         ((history_size += DEFAULT_HISTORY_GROW_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 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. */
+int
+history_search (string, direction)
+     char *string;
+     int direction;
+{
+  register int i = history_offset;
+  register int reverse = (direction < 0);
+  register char *line;
+  register int index;
+  int string_len = strlen (string);
+
+  /* Take care of trivial cases first. */
+
+  if (!history_length || ((i == history_length) && !reverse))
+    return (-1);
+
+  if (reverse && (i == history_length))
+    i--;
+
+  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;
+      index = strlen (line);
+
+      /* If STRING is longer than line, no match. */
+      if (string_len > index)
+       goto next_line;
+
+      /* Do the actual search. */
+      if (reverse)
+       {
+         index -= string_len;
+
+         while (index >= 0)
+           {
+             if (strncmp (string, line + index, string_len) == 0)
+               {
+                 history_offset = i;
+                 return (index);
+               }
+             index--;
+           }
+       }
+      else
+       {
+         register int limit = (string_len - index) + 1;
+         index = 0;
+
+         while (index < limit)
+           {
+             if (strncmp (string, line + index, string_len) == 0)
+               {
+                 history_offset = i;
+                 return (index);
+               }
+             index++;
+           }
+       }
+    next_line:
+      if (reverse)
+       i--;
+      else
+       i++;
+    }
+}
+
+/* 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 (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);
+}
+
+/* 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 = (char *)getenv ("HOME");
+      if (!home) home = ".";
+      return_val = (char *)xmalloc (2 + strlen (home) + strlen (".history"));
+      sprintf (return_val, "%s/.history", home);
+    }
+  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, done;
+  struct stat finfo;
+  extern int errno;
+
+  input = history_filename (filename);
+  file = open (input, O_RDONLY, 0666);
+
+  if ((file < 0) ||
+      (stat (input, &finfo) == -1))
+    goto error_and_exit;
+
+  buffer = (char *)xmalloc (finfo.st_size + 1);
+
+  if (read (file, buffer, finfo.st_size) != finfo.st_size)
+  error_and_exit:
+    {
+      if (file >= 0)
+       close (file);
+
+      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;
+      }
+  return (0);
+}
+
+/* Truncate the history file FNAME, leaving only LINES trailing lines.
+   If FNAME is NULL, then use ~/.history. */
+history_truncate_file (fname, lines)
+     char *fname;
+     register int lines;
+{
+  register int i;
+  int file;
+  char *buffer = (char *)NULL, *filename;
+  struct stat finfo;
+
+  filename = history_filename (fname);
+  if (stat (filename, &finfo) == -1)
+    goto truncate_exit;
+
+  file = open (filename, O_RDONLY, 066);
+
+  if (file == -1)
+    goto truncate_exit;
+
+  buffer = (char *)xmalloc (finfo.st_size + 1);
+  read (file, buffer, finfo.st_size);
+  close (file);
+
+  /* Count backwards from the end of buffer until we have passed
+     LINES lines. */
+  for (i = finfo.st_size; lines && i; i--)
+    {
+      if (buffer[i] == '\n')
+       lines--;
+    }
+
+  /* If there are fewer lines in the file than we want to truncate to,
+     then we are all done. */
+  if (!i)
+    goto truncate_exit;
+
+  /* Otherwise, write from the start of this line until the end of the
+     buffer. */
+  for (--i; i; i--)
+    if (buffer[i] == '\n')
+      {
+       i++;
+       break;
+      }
+
+  file = open (filename, O_WRONLY | O_TRUNC | O_CREAT, 0666);
+  if (file == -1)
+    goto truncate_exit;
+
+  write (file, buffer + i, finfo.st_size - i);
+  close (file);
+
+ truncate_exit:
+  if (buffer)
+    free (buffer);
+
+  free (filename);
+}
+
+#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;
+{
+  extern int errno;
+  register int i;
+  char *output = history_filename (filename);
+  int file, mode;
+  char cr = '\n';
+
+  if (overwrite)
+    mode = O_WRONLY | O_CREAT | O_TRUNC;
+  else
+    mode = O_WRONLY | O_APPEND;
+
+  if ((file = open (output, mode, 0666)) == -1)
+    return (errno);
+
+  if (nelements > history_length)
+    nelements = history_length;
+
+  for (i = history_length - nelements; i < history_length; i++)
+    {
+      if (write (file, the_history[i]->line, strlen (the_history[i]->line)) < 0)
+       break;
+      if (write (file, &cr, 1) < 0)
+       break;
+    }
+
+  close (file);
+  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 index = offset - history_base;
+
+  if (index >= history_length ||
+      index < 0 ||
+      !the_history)
+    return ((HIST_ENTRY *)NULL);
+  return (the_history[index]);
+}
+
+/* Search for STRING in the history list.  DIR is < 0 for searching
+   backwards.  POS is an absolute index into the history list at
+   which point to begin searching. */
+int
+history_search_pos (string, dir, pos)
+     char *string;
+     int dir, pos;
+{
+  int ret, old = where_history ();
+  history_set_pos (pos);
+  if (history_search (string, dir) == -1)
+    {
+      history_set_pos (old);
+      return (-1);
+    }
+  ret = where_history ();
+  history_set_pos (old);
+  return ret;
+}
+
+/* Make the current history item be the one at POS, an absolute index.
+   Returns zero if POS is out of range, else non-zero. */
+int
+history_set_pos (pos)
+     int pos;
+{
+  if (pos > history_length || pos < 0 || !the_history)
+    return (0);
+  history_offset = pos;
+  return (1);
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Expansion                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Hairy history expansion on text, not tokens.  This is of general
+   use, and thus belongs in this library. */
+
+/* The last string searched for in a !?string? search. */
+static char *search_string = (char *)NULL;
+
+/* 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;
+  int which, sign = 1;
+  HIST_ENTRY *entry;
+
+  /* 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++;
+
+  /* Handle !! case. */
+  if (string[i] == history_expansion_char)
+    {
+      i++;
+      which = history_base + (history_length - 1);
+      *caller_index = i;
+      goto get_which;
+    }
+
+  /* Hack case of numeric line specification. */
+ read_which:
+  if (string[i] == '-')
+    {
+      sign = -1;
+      i++;
+    }
+
+  if (digit (string[i]))
+    {
+      int start = i;
+
+      /* Get the extent of the digits. */
+      for (; digit (string[i]); i++);
+
+      /* Get the digit value. */
+      sscanf (string + start, "%d", &which);
+
+      *caller_index = i;
+
+      if (sign < 0)
+       which = (history_length + history_base) - which;
+
+    get_which:
+      if (entry = history_get (which))
+       return (entry->line);
+
+      return ((char *)NULL);
+    }
+
+  /* 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. */
+  {
+    int index;
+    char *temp;
+    int substring_okay = 0;
+
+    if (string[i] == '?')
+      {
+       substring_okay++;
+       i++;
+      }
+
+    for (index = i; string[i]; i++)
+      if (whitespace (string[i]) ||
+         string[i] == '\n' ||
+         string[i] == ':' ||
+         (substring_okay && string[i] == '?') ||
+         string[i] == delimiting_quote)
+       break;
+
+    temp = (char *)alloca (1 + (i - index));
+    strncpy (temp, &string[index], (i - index));
+    temp[i - index] = '\0';
+
+    if (string[i] == '?')
+      i++;
+
+    *caller_index = i;
+
+  search_again:
+
+    index = history_search (temp, -1);
+
+    if (index < 0)
+    search_lost:
+      {
+       history_offset = history_length;
+       return ((char *)NULL);
+      }
+
+    if (index == 0 || substring_okay || 
+       (strncmp (temp, the_history[history_offset]->line,
+                 strlen (temp)) == 0))
+      {
+      search_won:
+       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 = savestring (temp);
+         }
+
+       return (entry->line);
+      }
+
+    if (history_offset)
+      history_offset--;
+    else
+      goto search_lost;
+    
+    goto search_again;
+  }
+}
+
+/* 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.
+
+  If an error ocurred in expansion, then OUTPUT contains a descriptive
+  error message. */
+int
+history_expand (string, output)
+     char *string;
+     char **output;
+{
+  register int j, l = strlen (string);
+  int i, word_spec_error = 0;
+  int cc, modified = 0;
+  char *word_spec, *event;
+  int starting_index, only_printing = 0, substitute_globally = 0;
+
+  char *get_history_word_specifier (), *rindex ();
+
+  /* The output string, and its length. */
+  int len = 0;
+  char *result = (char *)NULL;
+
+  /* Used in add_string; */
+  char *temp, tt[2], tbl[3];
+
+  /* Prepare the buffer for printing error messages. */
+  result = (char *)xmalloc (len = 255);
+
+  result[0] = tt[1] = tbl[2] = '\0';
+  tbl[0] = '\\';
+  tbl[1] = history_expansion_char;
+
+  /* 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 (string[0] == history_subst_char)
+    {
+      char *format_string = (char *)alloca (10 + strlen (string));
+
+      sprintf (format_string, "%c%c:s%s",
+              history_expansion_char, history_expansion_char,
+              string);
+      string = format_string;
+      l += 4;
+      goto grovel;
+    }
+
+  /* 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++)
+    if (string[i] == history_expansion_char)
+      if (!string[i + 1] || member (string[i + 1], history_no_expand_chars))
+       continue;
+      else
+       goto grovel;
+
+  free (result);
+  *output = savestring (string);
+  return (0);
+
+ grovel:
+
+  for (i = j = 0; i < l; i++)
+    {
+      int tchar = string[i];
+      if (tchar == history_expansion_char)
+       tchar = -3;
+
+      switch (tchar)
+       {
+       case '\\':
+         if (string[i + 1] == history_expansion_char)
+           {
+             i++;
+             temp = tbl;
+             goto do_add;
+           }
+         else
+           goto add_char;
+
+         /* case history_expansion_char: */
+       case -3:
+         starting_index = i + 1;
+         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))
+           goto add_char;
+
+         /* 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 (cc == '#')
+           goto hack_pound_sign;
+
+         /* If it is followed by something that starts a word specifier,
+            then !! is implied as the event specifier. */
+
+         if (member (cc, ":$*%^"))
+           {
+             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
+           {
+             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)
+         event_not_found:
+           {
+           int l = 1 + (i - starting_index);
+
+           temp = (char *)alloca (1 + l);
+           strncpy (temp, string + starting_index, l);
+           temp[l - 1] = 0;
+           sprintf (result, "%s: %s.", temp,
+                    word_spec_error ? "Bad word specifier" : "Event not found");
+         error_exit:
+           *output = 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 *)-1)
+         bad_word_spec:
+         {
+           word_spec_error++;
+           goto event_not_found;
+         }
+
+         /* If no word specifier, than the thing of interest was the event. */
+         if (!word_spec)
+           temp = event;
+         else
+           {
+             temp = (char *)alloca (1 + strlen (word_spec));
+             strcpy (temp, word_spec);
+             free (word_spec);
+           }
+
+         /* Perhaps there are other modifiers involved.  Do what they say. */
+
+       hack_specials:
+
+         if (string[i] == ':')
+           {
+             char *tstr;
+
+             switch (string[i + 1])
+               {
+                 /* :p means make this the last executed line.  So we
+                    return an error state after adding this line to the
+                    history. */
+               case 'p':
+                 only_printing++;
+                 goto next_special;
+
+                 /* :t discards all but the last part of the pathname. */
+               case 't':
+                 tstr = rindex (temp, '/');
+                 if (tstr)
+                   temp = ++tstr;
+                 goto next_special;
+
+                 /* :h discards the last part of a pathname. */
+               case 'h':
+                 tstr = rindex (temp, '/');
+                 if (tstr)
+                   *tstr = '\0';
+                 goto next_special;
+
+                 /* :r discards the suffix. */
+               case 'r':
+                 tstr = rindex (temp, '.');
+                 if (tstr)
+                   *tstr = '\0';
+                 goto next_special;
+
+                 /* :e discards everything but the suffix. */
+               case 'e':
+                 tstr = rindex (temp, '.');
+                 if (tstr)
+                   temp = tstr;
+                 goto next_special;
+
+                 /* :s/this/that substitutes `this' for `that'. */
+                 /* :gs/this/that substitutes `this' for `that' globally. */
+               case 'g':
+                 if (string[i + 2] == 's')
+                   {
+                     i++;
+                     substitute_globally = 1;
+                     goto substitute;
+                   }
+                 else
+                   
+               case 's':
+                 substitute:
+                 {
+                   char *this, *that, *new_event;
+                   int delimiter = 0;
+                   int si, l_this, l_that, l_temp = strlen (temp);
+
+                   if (i + 2 < strlen (string))
+                     delimiter = string[i + 2];
+
+                   if (!delimiter)
+                     break;
+
+                   i += 3;
+
+                   /* Get THIS. */
+                   for (si = i; string[si] && string[si] != delimiter; si++);
+                   l_this = (si - i);
+                   this = (char *)alloca (1 + l_this);
+                   strncpy (this, string + i, l_this);
+                   this[l_this] = '\0';
+
+                   i = si;
+                   if (string[si])
+                     i++;
+
+                   /* Get THAT. */
+                   for (si = i; string[si] && string[si] != delimiter; si++);
+                   l_that = (si - i);
+                   that = (char *)alloca (1 + l_that);
+                   strncpy (that, string + i, l_that);
+                   that[l_that] = '\0';
+
+                   i = si;
+                   if (string[si]) i++;
+
+                   /* Ignore impossible cases. */
+                   if (l_this > l_temp)
+                     goto cant_substitute;
+
+                   /* Find the first occurrence of THIS in TEMP. */
+                   si = 0;
+                   for (; (si + l_this) <= l_temp; si++)
+                     if (strncmp (temp + si, this, l_this) == 0)
+                       {
+                         new_event =
+                           (char *)alloca (1 + (l_that - l_this) + l_temp);
+                         strncpy (new_event, temp, si);
+                         strncpy (new_event + si, that, l_that);
+                         strncpy (new_event + si + l_that,
+                                  temp + si + l_this,
+                                  l_temp - (si + l_this));
+                         new_event[(l_that - l_this) + l_temp] = '\0';
+                         temp = new_event;
+
+                         if (substitute_globally)
+                           {
+                             si += l_that;
+                             l_temp = strlen (temp);
+                             substitute_globally++;
+                             continue;
+                           }
+
+                         goto hack_specials;
+                       }
+
+                 cant_substitute:
+
+                   if (substitute_globally > 1)
+                     {
+                       substitute_globally = 0;
+                       goto hack_specials;
+                     }
+
+                   goto event_not_found;
+                 }
+
+                 /* :# is the line so far.  Note that we have to
+                    alloca () it since RESULT could be realloc ()'ed
+                    below in add_string. */
+               case '#':
+               hack_pound_sign:
+                 if (result)
+                   {
+                     temp = (char *)alloca (1 + strlen (result));
+                     strcpy (temp, result);
+                   }
+                 else
+                   temp = "";
+
+               next_special:
+                 i += 2;
+                 goto hack_specials;
+               }
+
+           }
+         /* Believe it or not, we have to back the pointer up by one. */
+         --i;
+         goto add_string;
+
+         /* A regular character.  Just add it to the output string. */
+       default:
+       add_char:
+         tt[0] = string[i];
+         temp = tt;
+         goto do_add;
+
+       add_string:
+         modified++;
+
+       do_add:
+         j += strlen (temp);
+         while (j > len)
+           result = (char *)xrealloc (result, (len += 255));
+
+         strcpy (result + (j - strlen (temp)), temp);
+       }
+    }
+
+  *output = result;
+
+  if (only_printing)
+    {
+      add_history (result);
+      return (-1);
+    }
+
+  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.  -1 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. */
+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 *history_arg_extract ();
+
+  /* The range of words to return doesn't exist yet. */
+  first = last = 0;
+
+  /* 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;
+      if (search_string)
+       return (savestring (search_string));
+      else
+       return (savestring (""));
+    }
+
+  /* `*' matches all of the arguments, but not the command. */
+  if (spec[i] == '*')
+    {
+      char *star_result;
+
+      *caller_index = i + 1;
+      star_result = history_arg_extract (1, '$', from);
+
+      if (!star_result)
+       star_result = savestring ("");
+
+      return (star_result);
+    }
+
+  /* `$' 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] == '-' || spec[i] == '^')
+    {
+      first = 1;
+      goto get_last;
+    }
+
+ get_first:
+  if (digit (spec[i]) && expecting_word_spec)
+    {
+      sscanf (spec + i, "%d", &first);
+      for (; digit (spec[i]); i++);
+    }
+  else
+    return ((char *)NULL);
+
+ get_last:
+  if (spec[i] == '^')
+    {
+      i++;
+      last = 1;
+      goto get_args;
+    }
+
+  if (spec[i] != '-')
+    {
+      last = first;
+      goto get_args;
+    }
+
+  i++;
+
+  if (digit (spec[i]))
+    {
+      sscanf (spec + i, "%d", &last);
+      for (; digit (spec[i]); i++);
+    }
+  else
+    if (spec[i] == '$')
+      {
+       i++;
+       last = '$';
+      }
+
+ get_args:
+  {
+    char *result = (char *)NULL;
+
+    *caller_index = i;
+
+    if (last >= first)
+      result = history_arg_extract (first, last, from);
+
+    if (result)
+      return (result);
+    else
+      return ((char *)-1);
+  }
+}
+
+/* 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). */
+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 **history_tokenize (), **list;
+
+  if (!(list = history_tokenize (string)))
+    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)
+    result = ((char *)NULL);
+  else
+    {
+      for (i = first; i < last; i++)
+       {
+         int l = strlen (list[i]);
+
+         if (!result)
+           result = (char *)xmalloc ((size = (2 + l)));
+         else
+           result = (char *)xrealloc (result, (size += (2 + l)));
+         strcpy (result + offset, list[i]);
+         offset += l;
+         if (i + 1 < last)
+           {
+             strcpy (result + offset, " ");
+             offset++;
+           }
+       }
+    }
+
+  for (i = 0; i < len; i++)
+    free (list[i]);
+
+  free (list);
+
+  return (result);
+}
+
+#define slashify_in_quotes "\\`\"$"
+
+/* Return an array of tokens, much as the shell might.  The tokens are
+   parsed out of STRING. */
+char **
+history_tokenize (string)
+     char *string;
+{
+  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. */
+ get_token:
+
+  /* Skip leading whitespace. */
+  for (; string[i] && whitespace(string[i]); i++);
+
+  start = i;
+
+  if (!string[i] || string[i] == history_comment_char)
+    return (result);
+
+  if (member (string[i], "()\n")) {
+    i++;
+    goto got_token;
+  }
+
+  if (member (string[i], "<>;&|")) {
+    int peek = string[i + 1];
+
+    if (peek == string[i]) {
+      if (peek ==  '<') {
+       if (string[1 + 2] == '-')
+         i++;
+       i += 2;
+       goto got_token;
+      }
+
+      if (member (peek, ">:&|")) {
+       i += 2;
+       goto got_token;
+      }
+    } else {
+      if ((peek == '&' &&
+         (string[i] == '>' || string[i] == '<')) ||
+         ((peek == '>') &&
+         (string[i] == '&'))) {
+       i += 2;
+       goto got_token;
+      }
+    }
+    i++;
+    goto got_token;
+  }
+
+  /* Get word from string + i; */
+  {
+    int delimiter = 0;
+
+    if (member (string[i], "\"'`"))
+      delimiter = string[i++];
+
+    for (;string[i]; i++) {
+
+      if (string[i] == '\\') {
+
+       if (string[i + 1] == '\n') {
+         i++;
+         continue;
+       } else {
+         if (delimiter != '\'')
+           if ((delimiter != '"') ||
+               (member (string[i], slashify_in_quotes))) {
+             i++;
+             continue;
+           }
+       }
+      }
+
+      if (delimiter && string[i] == delimiter) {
+       delimiter = 0;
+       continue;
+      }
+
+      if (!delimiter && (member (string[i], " \t\n;&()|<>")))
+       goto got_token;
+
+      if (!delimiter && member (string[i], "\"'`")) {
+       delimiter = string[i];
+       continue;
+      }
+    }
+    got_token:
+
+    len = i - start;
+    if (result_index + 2 >= size) {
+      if (!size)
+       result = (char **)xmalloc ((size = 10) * (sizeof (char *)));
+      else
+       result =
+         (char **)xrealloc (result, ((size += 10) * (sizeof (char *))));
+    }
+    result[result_index] = (char *)xmalloc (1 + len);
+    strncpy (result[result_index], string + start, len);
+    result[result_index][len] = '\0';
+    result_index++;
+    result[result_index] = (char *)NULL;
+  }
+  if (string[i])
+    goto get_token;
+
+  return (result);
+}
+
+#if defined (STATIC_MALLOC)
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)xmalloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "history: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                             Test Code                           */
+/*                                                                 */
+/* **************************************************************** */
+#ifdef TEST
+main ()
+{
+  char line[1024], *t;
+  int done = 0;
+
+  line[0] = 0;
+
+  while (!done)
+    {
+      fprintf (stdout, "history%% ");
+      t = gets (line);
+
+      if (!t)
+       strcpy (line, "quit");
+
+      if (line[0])
+       {
+         char *expansion;
+         int result;
+
+         using_history ();
+
+         result = history_expand (line, &expansion);
+         strcpy (line, expansion);
+         free (expansion);
+         if (result)
+           fprintf (stderr, "%s\n", line);
+
+         if (result < 0)
+           continue;
+
+         add_history (line);
+       }
+
+      if (strcmp (line, "quit") == 0) done = 1;
+      if (strcmp (line, "save") == 0) write_history (0);
+      if (strcmp (line, "read") == 0) read_history (0);
+      if (strcmp (line, "list") == 0)
+       {
+         register HIST_ENTRY **the_list = history_list ();
+         register int i;
+
+         if (the_list)
+           for (i = 0; the_list[i]; i++)
+             fprintf (stdout, "%d: %s\n", i + history_base, the_list[i]->line);
+       }
+      if (strncmp (line, "delete", strlen ("delete")) == 0)
+       {
+         int which;
+         if ((sscanf (line + strlen ("delete"), "%d", &which)) == 1)
+           {
+             HIST_ENTRY *entry = remove_history (which);
+             if (!entry)
+               fprintf (stderr, "No such entry %d\n", which);
+             else
+               {
+                 free (entry->line);
+                 free (entry);
+               }
+           }
+         else
+           {
+             fprintf (stderr, "non-numeric arg given to `delete'\n");
+           }
+       }
+    }
+}
+
+#endif                         /* TEST */
+\f
+/*
+* Local variables:
+* compile-command: "gcc -g -DTEST -o history history.c"
+* end:
+*/
diff --git a/gnu/lib/libreadline/history.h b/gnu/lib/libreadline/history.h
new file mode 100644 (file)
index 0000000..cd5574d
--- /dev/null
@@ -0,0 +1,120 @@
+/* History.h -- the names of functions that you can call in history. */
+
+typedef struct _hist_entry {
+  char *line;
+  char *data;
+} HIST_ENTRY;
+
+/* For convenience only.  You set this when interpreting history commands.
+   It is the logical offset of the first history element. */
+extern int history_base;
+
+/* Begin a session in which the history functions might be used.  This
+   just initializes the interactive variables. */
+extern void using_history ();
+
+/* Place STRING at the end of the history list.
+   The associated data field (if any) is set to NULL. */
+extern void add_history ();
+
+/* Returns the number which says what history element we are now
+   looking at.  */
+extern int where_history ();
+  
+/* Set the position in the history list to POS. */
+int history_set_pos ();
+
+/* 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 ();
+
+/* 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 ();
+
+/* 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 ();
+
+/* 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 ();
+
+/* Append the current history to FILENAME.  If FILENAME is NULL,
+   then append 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 ();
+
+/* 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 ();
+
+/* 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 ();
+
+/* 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 ();
+
+/* 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 ();
+
+/* 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 ();
+
+/* 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.
+
+  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 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 ();
diff --git a/gnu/lib/libreadline/keymaps.c b/gnu/lib/libreadline/keymaps.c
new file mode 100644 (file)
index 0000000..5e8ee24
--- /dev/null
@@ -0,0 +1,173 @@
+/* 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. */
+
+#include "keymaps.h"
+#include "emacs_keymap.c"
+
+#ifdef VI_MODE
+#include "vi_keymap.c"
+#endif
+
+/* Remove these declarations when we have a complete libgnu.a. */
+#define STATIC_MALLOC
+#ifndef STATIC_MALLOC
+extern char *xmalloc (), *xrealloc ();
+#else
+static char *xmalloc (), *xrealloc ();
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*                   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 (128 * sizeof (KEYMAP_ENTRY));
+
+  for (i = 0; i < 128; 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 < 128; 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 ()
+{
+  extern rl_insert (), rl_rubout (), rl_do_lowercase_version ();
+  extern rl_digit_argument ();
+  register int i;
+  Keymap newmap;
+
+  newmap = rl_make_bare_keymap ();
+
+  /* All printing characters are self-inserting. */
+  for (i = ' '; i < 126; i++)
+    newmap[i].function = rl_insert;
+
+  newmap[TAB].function = rl_insert;
+  newmap[RUBOUT].function = rl_rubout;
+  newmap[CTRL('H')].function = rl_rubout;
+
+  return (newmap);
+}
+
+/* Free the storage associated with MAP. */
+rl_discard_keymap (map)
+     Keymap (map);
+{
+  int i;
+
+  if (!map)
+    return;
+
+  for (i = 0; i < 128; 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;
+       }
+    }
+}
+
+#ifdef STATIC_MALLOC
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp = (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/gnu/lib/libreadline/readline.c b/gnu/lib/libreadline/readline.c
new file mode 100644 (file)
index 0000000..7222e37
--- /dev/null
@@ -0,0 +1,5927 @@
+/* readline.c -- a general facility for reading lines of input
+   with emacs style editing and completion. */
+
+/* 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. */
+
+/* Remove these declarations when we have a complete libgnu.a. */
+#define STATIC_MALLOC
+#ifndef STATIC_MALLOC
+extern char *xmalloc (), *xrealloc ();
+#else
+static char *xmalloc (), *xrealloc ();
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/file.h>
+#include <signal.h>
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#if defined (sparc) && defined (sun)
+#include <alloca.h>
+#endif
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+
+#define NEW_TTY_DRIVER
+#define HAVE_BSD_SIGNALS
+
+/* 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)
+#undef NEW_TTY_DRIVER
+#include <termio.h>
+
+#if !defined (TCOON)
+#define TCOON 1
+#endif
+
+#endif /* USG | hpux | Xenix sgi | DUGX */
+#endif /* !_POSIX_VERSION */
+
+/* Posix systems use termios. */
+#if defined (_POSIX_VERSION)
+#undef NEW_TTY_DRIVER
+#include <termios.h>
+#if !defined (O_NDELAY)
+#define O_NDELAY O_NONBLOCK    /* Posix-style non-blocking i/o */
+#endif /* O_NDELAY */
+#endif
+
+/* Other (BSD) machines use sgtty. */
+#if defined (NEW_TTY_DRIVER)
+#include <sgtty.h>
+#endif
+
+#include <errno.h>
+extern int errno;
+
+#include <setjmp.h>
+#include <sys/stat.h>
+
+/* These next are for filename completion.  Perhaps this belongs
+   in a different place. */
+#include <pwd.h>
+#if defined (USG)
+struct passwd *getpwuid (), *getpwent ();
+#endif
+
+/* #define HACK_TERMCAP_MOTION */
+
+#if !defined (USG)
+#include <sys/dir.h>
+#else  /* USG */
+#if defined (Xenix)
+#include <sys/ndir.h>
+#else
+#ifdef hpux
+#include <ndir.h>
+#else
+#include <dirent.h>
+#define direct dirent
+#define d_namlen d_reclen
+#endif  /* hpux */
+#endif  /* xenix */
+#endif  /* USG */
+
+#if defined (USG) && defined (TIOCGWINSZ)
+#include <sys/stream.h>
+#  if defined (USGr4) || defined (USGr3)
+#    include <sys/ptem.h>
+#  endif /* USGr4 */
+#endif /* USG && TIOCGWINSZ */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#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
+
+#ifndef member
+char *index ();
+#define member(c, s) ((c) ? index ((s), (c)) : 0)
+#endif
+
+#ifndef isident
+#define isident(c) ((isletter(c) || digit(c) || c == '_'))
+#endif
+
+#ifndef exchange
+#define exchange(x, y) {int temp = x; x = y; y = temp;}
+#endif
+
+static update_line ();
+static delete_chars ();
+static insert_some_chars ();
+
+#ifdef VOID_SIGHANDLER
+#define sighandler void
+#else
+#define sighandler int
+#endif
+
+/* This typedef is equivalant to the one for Function; it allows us
+   to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
+typedef sighandler SigHandler ();
+
+/* If on, then readline handles signals in a way that doesn't screw. */
+#define HANDLE_SIGNALS
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Line editing input utility                  */
+/*                                                                 */
+/* **************************************************************** */
+
+/* A pointer to the keymap that is currently in use.
+   By default, it is the standard emacs keymap. */
+Keymap keymap = emacs_standard_keymap;
+
+#define vi_mode 0
+#define emacs_mode 1
+
+/* 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. */
+static int 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 char *running_in_emacs = (char *)NULL;
+
+/* 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 = stdin, *rl_outstream = stdout;
+
+/* Non-zero means echo characters as they are read. */
+int readline_echoing_p = 1;
+
+/* Current prompt. */
+char *rl_prompt;
+
+/* 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;
+
+/* 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_symbolic_link_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. */
+static int 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;
+
+/* Line buffer and maintenence. */
+char *rl_line_buffer = (char *)NULL;
+static int rl_line_buffer_len = 0;
+#define DEFAULT_BUFFER_SIZE 256
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     `Forward' declarations                      */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero means do not parse any lines other than comments and
+   parser directives. */
+static unsigned char parsing_conditionalized_out = 0;
+
+/* Non-zero means to save keys that we dispatch on in a kbd macro. */
+static int defining_kbd_macro = 0;
+
+/* XXX this prevents to got editing mode from tcsh */
+static void wait_foreground(void)
+{
+       struct winsize w;
+       int tty = fileno (rl_instream);
+
+       if (ioctl (tty, TIOCGWINSZ, &w) == 0)
+               (void) ioctl (tty, TIOCSWINSZ, &w);
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Top Level Functions                         */
+/*                                                                 */
+/* **************************************************************** */
+
+/* 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;
+{
+  static rl_prep_terminal (), rl_deprep_terminal ();
+  char *readline_internal ();
+  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_initialize ();
+  rl_prep_terminal ();
+
+#ifdef HANDLE_SIGNALS
+  rl_set_signals ();
+#endif
+
+  value = readline_internal ();
+  rl_deprep_terminal ();
+
+#ifdef 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. */
+char *
+readline_internal ()
+{
+  int lastc, c, eof_found;
+
+  in_stream = rl_instream; out_stream = rl_outstream;
+  lastc = 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 ();
+#ifdef 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 = 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 eof_char typed to blank line, and not as the
+        previous character is interpreted as EOF. */
+      if (((c == eof_char && lastc != c) || c == EOF) && !rl_end)
+       {
+         eof_found = 1;
+         break;
+       }
+
+      lastc = c;
+      rl_dispatch (c, 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;
+       }
+
+#ifdef 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 && keymap == vi_movement_keymap)
+       rl_vi_check ();
+#endif
+
+      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);
+       free_history_entry (entry);
+
+       strcpy (the_line, temp);
+       free (temp);
+      }
+  }
+
+  /* At any rate, it is highly likely that this line has an undo list.  Get
+     rid of it now. */
+  if (rl_undo_list)
+    free_undo_list ();
+
+  if (eof_found)
+    return (char *)NULL;
+  else
+    return (savestring (the_line));
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                        Signal Handling                          */
+/*                                                                 */
+/* **************************************************************** */
+
+#ifdef SIGWINCH
+static SigHandler *old_sigwinch = (SigHandler *)NULL;
+
+static sighandler
+rl_handle_sigwinch (sig, code, scp)
+     int sig, code;
+     struct sigcontext *scp;
+{
+  char *term = rl_terminal_name;
+
+  if (readline_echoing_p)
+    {
+      if (!term)
+       term = getenv ("TERM");
+      if (!term)
+       term = "dumb";
+      rl_reset_terminal (term);
+#ifdef NEVER
+      crlf ();
+      rl_forced_update_display ();
+#endif
+    }
+
+  if (old_sigwinch &&
+      old_sigwinch != (SigHandler *)SIG_IGN &&
+      old_sigwinch != (SigHandler *)SIG_DFL)
+    (*old_sigwinch)(sig, code, scp);
+}
+#endif  /* SIGWINCH */
+
+#ifdef HANDLE_SIGNALS
+/* Interrupt handling. */
+static SigHandler *old_int  = (SigHandler *)NULL,
+                 *old_tstp = (SigHandler *)NULL,
+                 *old_ttou = (SigHandler *)NULL,
+                 *old_ttin = (SigHandler *)NULL,
+                 *old_cont = (SigHandler *)NULL;
+
+/* Handle an interrupt character. */
+static sighandler
+rl_signal_handler (sig, code, scp)
+     int sig, code;
+     struct sigcontext *scp;
+{
+  static rl_prep_terminal (), rl_deprep_terminal ();
+
+#if !defined (HAVE_BSD_SIGNALS) || defined (hpux)
+  /* 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 || hpux */
+
+  switch (sig)
+    {
+    case SIGINT:
+      free_undo_list ();
+      rl_clear_message ();
+      rl_init_argument ();
+
+#ifdef SIGTSTP
+    case SIGTSTP:
+    case SIGTTOU:
+    case SIGTTIN:
+#endif
+
+      rl_clean_up_for_exit ();
+      rl_deprep_terminal ();
+      rl_clear_signals ();
+      rl_pending_input = 0;
+
+      kill (getpid (), sig);
+
+#if defined (_POSIX_VERSION)
+      {
+       sigset_t set;
+
+       sigemptyset (&set);
+       sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
+      }
+#else
+#if defined (HAVE_BSD_SIGNALS)
+      sigsetmask (0);
+#endif /* HAVE_BSD_SIGNALS */
+#endif /* _POSIX_VERSION */
+
+      rl_prep_terminal ();
+      rl_set_signals ();
+    }
+}
+
+rl_set_signals ()
+{
+  old_int = (SigHandler *)signal (SIGINT, rl_signal_handler);
+  if (old_int == (SigHandler *)SIG_IGN)
+    signal (SIGINT, SIG_IGN);
+
+#ifdef SIGTSTP
+  old_tstp = (SigHandler *)signal (SIGTSTP, rl_signal_handler);
+  if (old_tstp == (SigHandler *)SIG_IGN)
+    signal (SIGTSTP, SIG_IGN);
+#endif
+#ifdef SIGTTOU
+  old_ttou = (SigHandler *)signal (SIGTTOU, rl_signal_handler);
+  old_ttin = (SigHandler *)signal (SIGTTIN, rl_signal_handler);
+
+  if (old_tstp == (SigHandler *)SIG_IGN)
+    {
+      signal (SIGTTOU, SIG_IGN);
+      signal (SIGTTIN, SIG_IGN);
+    }
+#endif
+
+#ifdef SIGWINCH
+  old_sigwinch = (SigHandler *)signal (SIGWINCH, rl_handle_sigwinch);
+#endif
+}
+
+rl_clear_signals ()
+{
+  signal (SIGINT, old_int);
+
+#ifdef SIGTSTP
+  signal (SIGTSTP, old_tstp);
+#endif
+
+#ifdef SIGTTOU
+  signal (SIGTTOU, old_ttou);
+  signal (SIGTTIN, old_ttin);
+#endif
+
+#ifdef SIGWINCH
+      signal (SIGWINCH, old_sigwinch);
+#endif
+}
+#endif  /* HANDLE_SIGNALS */
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Character Input Buffering                   */
+/*                                                                 */
+/* **************************************************************** */
+
+/* If the terminal was in xoff state when we got to it, then xon_char
+   contains the character that is supposed to start it again. */
+static int xon_char, xoff_state;
+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 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. */
+rl_gather_tyi ()
+{
+  int tty = fileno (in_stream);
+  register int tem, result = -1;
+  long chars_avail;
+  char input;
+
+#ifdef FIONREAD
+  result = ioctl (tty, FIONREAD, &chars_avail);
+#endif
+
+  if (result == -1)
+    {
+      fcntl (tty, F_SETFL, O_NDELAY);
+      chars_avail = read (tty, &input, 1);
+      fcntl (tty, F_SETFL, 0);
+      if (chars_avail == -1 && errno == EAGAIN)
+       return;
+    }
+
+  /* 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);
+    }
+}
+
+/* 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
+    {
+      static int next_macro_key ();
+
+      /* 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);
+       }
+    }
+
+#ifdef NEVER  /* This breaks supdup to 4.0.3c machines. */
+#ifdef TIOCSTART
+  /* Ugh.  But I can't think of a better way. */
+  if (xoff_state && c == xon_char)
+    {
+      ioctl (fileno (in_stream), TIOCSTART, 0);
+      xoff_state = 0;
+      return (rl_read_key ());
+    }
+#endif /* TIOCSTART */
+#endif
+
+  return (c);
+}
+
+/* I'm beginning to hate the declaration rules for various compilers. */
+static void add_macro_char ();
+
+/* 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. */
+rl_dispatch (key, map)
+     register int key;
+     Keymap map;
+{
+
+  if (defining_kbd_macro)
+    add_macro_char (key);
+
+  if (key > 127 && key < 256)
+    {
+      if (map[ESC].type == ISKMAP)
+       {
+         map = (Keymap)map[ESC].function;
+         key -= 128;
+         rl_dispatch (key, map);
+       }
+      else
+       ding ();
+      return;
+    }
+
+  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)
+             {
+               rl_dispatch (to_lower (key), map);
+               return;
+             }
+
+           (*map[key].function)(rl_numeric_arg * 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;
+         }
+      }
+      break;
+
+    case ISKMAP:
+      if (map[key].function != (Function *)NULL)
+       {
+         int newkey;
+
+         rl_key_sequence_length++;
+         newkey = rl_read_key ();
+         rl_dispatch (newkey, (Keymap)map[key].function);
+       }
+      else
+       {
+         rl_abort ();
+         return;
+       }
+      break;
+
+    case ISMACR:
+      if (map[key].function != (Function *)NULL)
+       {
+         static with_macro_input ();
+         char *macro = savestring ((char *)map[key].function);
+
+         with_macro_input (macro);
+         return;
+       }
+      break;
+    }
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Hacking Keyboard Macros                     */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The currently executing macro string.  If this is non-zero,
+   then it is a malloc ()'ed string where input is coming from. */
+static char *executing_macro = (char *)NULL;
+
+/* The offset in the above string to the next character to be read. */
+static int executing_macro_index = 0;
+
+/* The current macro string being built.  Characters get stuffed
+   in here by add_macro_char (). */
+static char *current_macro = (char *)NULL;
+
+/* The size of the buffer allocated to current_macro. */
+static int current_macro_size = 0;
+
+/* The index at which characters are being added to current_macro. */
+static int current_macro_index = 0;
+
+/* A structure used to save nested macro strings.
+   It is a linked list of string/index for each saved macro. */
+struct saved_macro {
+  struct saved_macro *next;
+  char *string;
+  int index;
+};
+
+/* 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
+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->index = 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->index;
+      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 = (char *)xmalloc (current_macro_size = 25);
+      else
+       current_macro =
+         (char *)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 ();
+
+  if (rl_explicit_arg)
+    {
+      if (current_macro)
+       with_macro_input (savestring (current_macro));
+    }
+  else
+    current_macro_index = 0;
+
+  defining_kbd_macro = 1;
+}
+
+/* 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 ();
+
+  current_macro_index -= (rl_key_sequence_length - 1);
+  current_macro[current_macro_index] = '\0';
+
+  defining_kbd_macro = 0;
+
+  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 ();
+
+  while (count--)
+    with_macro_input (savestring (current_macro));
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Initializations                             */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Initliaze readline (and terminal if not already). */
+rl_initialize ()
+{
+  extern char *rl_display_prompt;
+
+  /* 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. */
+  {
+    extern char *rl_display_prompt;
+    extern int forced_display;
+
+    rl_on_new_line ();
+
+    rl_display_prompt = rl_prompt ? rl_prompt : "";
+    forced_display = 1;
+  }
+
+  /* No such function typed yet. */
+  rl_last_func = (Function *)NULL;
+
+  /* Parsing of key-bindings begins in an enabled state. */
+  parsing_conditionalized_out = 0;
+}
+
+/* Initialize the entire state of the world. */
+readline_initialize_everything ()
+{
+  /* Find out if we are running in Emacs. */
+  running_in_emacs = getenv ("EMACS");
+
+  /* Allocate data structures. */
+  if (!rl_line_buffer)
+    rl_line_buffer =
+      (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
+
+  /* Initialize the terminal interface. */
+  init_terminal_io ((char *)NULL);
+
+  /* Bind tty characters to readline functions. */
+  readline_default_bindings ();
+
+  /* Initialize the function names. */
+  rl_initialize_funmap ();
+
+  /* Read in the init file. */
+  rl_read_init_file ((char *)NULL);
+
+  /* If the completion parser's default word break characters haven't
+     been set yet, then do so now. */
+  {
+    extern char *rl_completer_word_break_characters;
+    extern char *rl_basic_word_break_characters;
+
+    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. */
+readline_default_bindings ()
+{
+
+#ifdef NEW_TTY_DRIVER
+  struct sgttyb ttybuff;
+  int tty = fileno (rl_instream);
+
+  if (ioctl (tty, TIOCGETP, &ttybuff) != -1)
+    {
+      int erase = ttybuff.sg_erase, kill = ttybuff.sg_kill;
+
+      if (erase != -1 && keymap[erase].type == ISFUNC)
+       keymap[erase].function = rl_rubout;
+
+      if (kill != -1 && keymap[kill].type == ISFUNC)
+       keymap[kill].function = rl_unix_line_discard;
+    }
+
+#ifdef TIOCGLTC
+  {
+    struct ltchars lt;
+
+    if (ioctl (tty, TIOCGLTC, &lt) != -1)
+      {
+       int erase = lt.t_werasc, nextc = lt.t_lnextc;
+
+       if (erase != -1 && keymap[erase].type == ISFUNC)
+         keymap[erase].function = rl_unix_word_rubout;
+
+       if (nextc != -1 && keymap[nextc].type == ISFUNC)
+         keymap[nextc].function = rl_quoted_insert;
+      }
+  }
+#endif /* TIOCGLTC */
+#else /* not NEW_TTY_DRIVER */
+
+#if defined (_POSIX_VERSION)
+  struct termios ttybuff;
+#else
+  struct termio ttybuff;
+#endif /* POSIX */
+  int tty = fileno (rl_instream);
+
+  wait_foreground ();   /* XXX this prevents to got editing mode from tcsh */
+#if defined (_POSIX_VERSION)
+  if (tcgetattr (tty, &ttybuff) != -1)
+#else
+  if (ioctl (tty, TCGETA, &ttybuff) != -1)
+#endif /* POSIX */
+    {
+      int erase = ttybuff.c_cc[VERASE];
+      int kill = ttybuff.c_cc[VKILL];
+
+      if (erase != -1 && keymap[(unsigned char)erase].type == ISFUNC)
+       keymap[(unsigned char)erase].function = rl_rubout;
+
+      if (kill != -1 && keymap[(unsigned char)kill].type == ISFUNC)
+       keymap[(unsigned char)kill].function = rl_unix_line_discard;
+    }
+#endif /* NEW_TTY_DRIVER */
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Numeric Arguments                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Handle C-u style numeric args, as well as M--, and M-digits. */
+
+/* Add the current digit to the argument in progress. */
+rl_digit_argument (ignore, key)
+     int ignore, key;
+{
+  rl_pending_input = key;
+  rl_digit_loop ();
+}
+
+/* What to do when you abort reading an argument. */
+rl_discard_argument ()
+{
+  ding ();
+  rl_clear_message ();
+  rl_init_argument ();
+}
+
+/* Create a default argument. */
+rl_init_argument ()
+{
+  rl_numeric_arg = arg_sign = 1;
+  rl_explicit_arg = 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;
+  rl_digit_loop ();
+}
+
+rl_digit_loop ()
+{
+  int key, c;
+  while (1)
+    {
+      rl_message ("(arg: %d) ", arg_sign * rl_numeric_arg);
+      key = c = rl_read_key ();
+
+      if (keymap[c].type == ISFUNC &&
+         keymap[c].function == rl_universal_argument)
+       {
+         rl_numeric_arg *= 4;
+         continue;
+       }
+      c = UNMETA (c);
+      if (numeric (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;
+             arg_sign = -1;
+           }
+         else
+           {
+             rl_clear_message ();
+             rl_dispatch (key, keymap);
+             return;
+           }
+       }
+    }
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     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.  Carefull attention needs
+   to be paid to the vertical position variables.
+
+   handling of terminals with autowrap on (incl. DEC braindamage)
+   could be improved a bit.  Right now I just cheat and decrement
+   screenwidth by one. */
+
+/* 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. */
+
+/* Termcap variables: */
+extern char *term_up, *term_dc, *term_cr;
+extern int screenheight, screenwidth, terminal_can_insert;
+
+/* What YOU turn on when you have handled all redisplay yourself. */
+int rl_display_fixed = 0;
+
+/* The visible cursor position.  If you print some text, adjust this. */
+int last_c_pos = 0;
+int last_v_pos = 0;
+
+/* 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;
+
+/* Number of lines currently on screen minus 1. */
+int vis_botlin = 0;
+
+/* A buffer for `modeline' messages. */
+char msg_buf[128];
+
+/* Non-zero forces the redisplay even if we thought it was unnecessary. */
+int forced_display = 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;
+
+/* Default and initial buffer size.  Can grow. */
+static int line_size = 1024;
+
+/* Non-zero means to always use horizontal scrolling in line display. */
+static int horizontal_scroll_mode = 0;
+
+/* Non-zero means to display an asterisk at the starts of history lines
+   which have been modified. */
+static int mark_modified_lines = 0;
+
+/* Non-zero means to use a visible bell if one is available rather than
+   simply ringing the terminal bell. */
+static int prefer_visible_bell = 0;
+
+/* I really disagree with this, but my boss (among others) insists that we
+   support compilers that don't work.  I don't think we are gaining by doing
+   so; what is the advantage in producing better code if we can't use it? */
+/* The following two declarations belong inside the
+   function block, not here. */
+static void move_cursor_relative ();
+static void output_some_chars ();
+void output_character_function ();
+static int compare_strings ();
+
+/* Basic redisplay algorithm. */
+rl_redisplay ()
+{
+  register int in, out, c, linenum;
+  register char *line = invisible_line;
+  char *prompt_this_line;
+  int c_pos = 0;
+  int inv_botlin = 0;          /* Number of lines in newly drawn buffer. */
+
+  extern int readline_echoing_p;
+
+  if (!readline_echoing_p)
+    return;
+
+  if (!rl_display_prompt)
+    rl_display_prompt = "";
+
+  if (!invisible_line)
+    {
+      visible_line = (char *)xmalloc (line_size);
+      invisible_line = (char *)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 (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 callers misconception. */
+  if (visible_line[0] != invisible_line[0])
+    rl_display_fixed = 0;
+
+  prompt_this_line = rindex (rl_display_prompt, '\n');
+  if (!prompt_this_line)
+    prompt_this_line = rl_display_prompt;
+  else
+    {
+      prompt_this_line++;
+      if (forced_display)
+       output_some_chars (rl_display_prompt,
+                          prompt_this_line - rl_display_prompt);
+    }
+
+  strncpy (line + out,  prompt_this_line, strlen (prompt_this_line));
+  out += strlen (prompt_this_line);
+  line[out] = '\0';
+
+  for (in = 0; in < rl_end; in++)
+    {
+      c = the_line[in];
+
+      if (out + 1 >= line_size)
+       {
+         line_size *= 2;
+         visible_line = (char *)xrealloc (visible_line, line_size);
+         invisible_line = (char *)xrealloc (invisible_line, line_size);
+         line = invisible_line;
+       }
+
+      if (in == rl_point)
+       c_pos = out;
+
+      if (c > 127)
+       {
+         line[out++] = 'M';
+         line[out++] = '-';
+         line[out++] = c - 128;
+       }
+#define DISPLAY_TABS
+#ifdef DISPLAY_TABS
+      else if (c == '\t')
+       {
+         register int newout = (out | (int)7) + 1;
+         while (out < newout)
+           line[out++] = ' ';
+       }
+#endif
+      else if (c < 32)
+       {
+         line[out++] = 'C';
+         line[out++] = '-';
+         line[out++] = c + 64;
+       }
+      else
+       line[out++] = c;
+    }
+  line[out] = '\0';
+  if (c_pos < 0)
+    c_pos = out;
+
+  /* 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 (!horizontal_scroll_mode && term_up && *term_up)
+    {
+      int total_screen_chars = (screenwidth * screenheight);
+
+      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. */
+         inv_botlin = out / screenwidth;
+
+         /* For each line in the buffer, do the updating display. */
+         for (linenum = 0; linenum <= inv_botlin; linenum++)
+           update_line (linenum > vis_botlin ? ""
+                        : &visible_line[linenum * screenwidth],
+                        &invisible_line[linenum * screenwidth],
+                        linenum);
+
+         /* We may have deleted some lines.  If so, clear the left over
+            blank ones at the bottom out. */
+         if (vis_botlin > inv_botlin)
+           {
+             char *tt;
+             for (; linenum <= vis_botlin; linenum++)
+               {
+                 tt = &visible_line[linenum * screenwidth];
+                 move_vert (linenum);
+                 move_cursor_relative (0, tt);
+                 clear_to_eol ((linenum == vis_botlin)?
+                               strlen (tt) : screenwidth);
+               }
+           }
+         vis_botlin = inv_botlin;
+
+         /* Move the cursor where it should be. */
+         move_vert (c_pos / screenwidth);
+         move_cursor_relative (c_pos % screenwidth,
+                               &invisible_line[(c_pos / screenwidth) * screenwidth]);
+       }
+    }
+  else                         /* Do horizontal scrolling. */
+    {
+      int lmargin;
+
+      /* Always at top line. */
+      last_v_pos = 0;
+
+      /* If the display position of the cursor would be off the edge
+        of the screen, start the display of this line at an offset that
+        leaves the cursor on the screen. */
+      if (c_pos - last_lmargin > screenwidth - 2)
+       lmargin = (c_pos / (screenwidth / 3) - 2) * (screenwidth / 3);
+      else if (c_pos - last_lmargin < 1)
+       lmargin = ((c_pos - 1) / (screenwidth / 3)) * (screenwidth / 3);
+      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 (lmargin + screenwidth < out)
+       line[lmargin + screenwidth - 1] = '>';
+
+      if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
+       {
+         forced_display = 0;
+         update_line (&visible_line[last_lmargin],
+                      &invisible_line[lmargin], 0);
+
+         move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
+         last_lmargin = lmargin;
+       }
+    }
+  fflush (out_stream);
+
+  /* Swap visible and non-visible lines. */
+  {
+    char *temp = visible_line;
+    visible_line = invisible_line;
+    invisible_line = temp;
+    rl_display_fixed = 0;
+  }
+}
+
+/* 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
+update_line (old, new, current_line)
+     register char *old, *new;
+     int current_line;
+{
+  register char *ofd, *ols, *oe, *nfd, *nls, *ne;
+  int lendiff, wsatend;
+
+  /* Find first difference. */
+  for (ofd = old, nfd = new;
+       (ofd - old < screenwidth) && *ofd && (*ofd == *nfd);
+       ofd++, nfd++)
+    ;
+
+  /* Move to the end of the screen line. */
+  for (oe = ofd; ((oe - old) < screenwidth) && *oe; oe++);
+  for (ne = nfd; ((ne - new) < screenwidth) && *ne; ne++);
+
+  /* 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 == *nls) && (ols > ofd) && (nls > nfd))
+    {
+      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++;
+    }
+
+  move_vert (current_line);
+  move_cursor_relative (ofd - old, old);
+
+  /* if (len (new) > len (old)) */
+  lendiff = (nls - nfd) - (ols - ofd);
+
+  /* Insert (diff(len(old),len(new)) ch */
+  if (lendiff > 0)
+    {
+      if (terminal_can_insert)
+       {
+         extern char *term_IC;
+
+         /* Sometimes it is cheaper to print the characters rather than
+            use the terminal's capabilities. */
+         if ((2 * (ne - nfd)) < lendiff && !term_IC)
+           {
+             output_some_chars (nfd, (ne - nfd));
+             last_c_pos += (ne - nfd);
+           }
+         else
+           {
+             if (*ols)
+               {
+                 insert_some_chars (nfd, lendiff);
+                 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. */
+                 output_some_chars (nfd, lendiff);
+                 last_c_pos += lendiff;
+               }
+             /* Copy (new) chars to screen from first diff to last match. */
+             if (((nls - nfd) - lendiff) > 0)
+               {
+                 output_some_chars (&nfd[lendiff], ((nls - nfd) - lendiff));
+                 last_c_pos += ((nls - nfd) - lendiff);
+               }
+           }
+       }
+      else
+       {               /* cannot insert chars, write to EOL */
+         output_some_chars (nfd, (ne - nfd));
+         last_c_pos += (ne - nfd);
+       }
+    }
+  else                         /* Delete characters from line. */
+    {
+      /* If possible and inexpensive to use terminal deletion, then do so. */
+      if (term_dc && (2 * (ne - nfd)) >= (-lendiff))
+       {
+         if (lendiff)
+           delete_chars (-lendiff); /* delete (diff) characters */
+
+         /* Copy (new) chars to screen from first diff to last match */
+         if ((nls - nfd) > 0)
+           {
+             output_some_chars (nfd, (nls - nfd));
+             last_c_pos += (nls - nfd);
+           }
+       }
+      /* Otherwise, print over the existing material. */
+      else
+       {
+         output_some_chars (nfd, (ne - nfd));
+         last_c_pos += (ne - nfd);
+         clear_to_eol ((oe - old) - (ne - new));
+       }
+    }
+}
+
+/* (PWP) tell the update routines that we have moved onto a
+   new (empty) line. */
+rl_on_new_line ()
+{
+  if (visible_line)
+    visible_line[0] = '\0';
+
+  last_c_pos = last_v_pos = 0;
+  vis_botlin = last_lmargin = 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 ();
+}
+
+/* Move the cursor from 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. */
+static void
+move_cursor_relative (new, data)
+     int new;
+     char *data;
+{
+  register int i;
+
+  /* It may be faster to output a CR, and then move forwards instead
+     of moving backwards. */
+  if (new + 1 < last_c_pos - new)
+    {
+      tputs (term_cr, 1, output_character_function);
+      last_c_pos = 0;
+    }
+
+  if (last_c_pos == new) return;
+
+  if (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. */
+#ifdef HACK_TERMCAP_MOTION
+      extern char *term_forward_char;
+
+      if (term_forward_char)
+       for (i = last_c_pos; i < new; i++)
+         tputs (term_forward_char, 1, output_character_function);
+      else
+       for (i = last_c_pos; i < new; i++)
+         putc (data[i], out_stream);
+#else
+      for (i = last_c_pos; i < new; i++)
+       putc (data[i], out_stream);
+#endif                         /* HACK_TERMCAP_MOTION */
+    }
+  else
+    backspace (last_c_pos - new);
+  last_c_pos = new;
+}
+
+/* PWP: move the cursor up or down. */
+move_vert (to)
+     int to;
+{
+  register int delta, i;
+
+  if (last_v_pos == to) return;
+
+  if (to > screenheight)
+    return;
+
+  if ((delta = to - last_v_pos) > 0)
+    {
+      for (i = 0; i < delta; i++)
+       putc ('\n', out_stream);
+      tputs (term_cr, 1, output_character_function);
+      last_c_pos = 0;          /* because crlf() will do \r\n */
+    }
+  else
+    {                  /* delta < 0 */
+      if (term_up && *term_up)
+       for (i = 0; i < -delta; i++)
+         tputs (term_up, 1, output_character_function);
+    }
+  last_v_pos = to;             /* now to is here */
+}
+
+/* Physically print C on out_stream.  This is for functions which know
+   how to optimize the display. */
+rl_show_char (c)
+     int c;
+{
+  if (c > 127)
+    {
+      fprintf (out_stream, "M-");
+      c -= 128;
+    }
+
+#ifdef DISPLAY_TABS
+  if (c < 32 && c != '\t')
+#else
+  if (c < 32)
+#endif
+    {
+
+      c += 64;
+    }
+
+  putc (c, out_stream);
+  fflush (out_stream);
+}
+
+#ifdef DISPLAY_TABS
+int
+rl_character_len (c, pos)
+     register int c, pos;
+{
+  if (c < ' ' || c > 126)
+    {
+      if (c == '\t')
+       return (((pos | (int)7) + 1) - pos);
+      else
+       return (3);
+    }
+  else
+    return (1);
+}
+#else
+int
+rl_character_len (c)
+     int c;
+{
+  if (c < ' ' || c > 126)
+    return (3);
+  else
+    return (1);
+}
+#endif  /* DISPLAY_TAB */
+
+/* How to print things in the "echo-area".  The prompt is treated as a
+   mini-modeline. */
+rl_message (string, arg1, arg2)
+     char *string;
+{
+  sprintf (msg_buf, string, arg1, arg2);
+  rl_display_prompt = msg_buf;
+  rl_redisplay ();
+}
+
+/* How to clear things from the "echo-area". */
+rl_clear_message ()
+{
+  rl_display_prompt = rl_prompt;
+  rl_redisplay ();
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Terminal and Termcap                        */
+/*                                                                 */
+/* **************************************************************** */
+
+static char *term_buffer = (char *)NULL;
+static char *term_string_buffer = (char *)NULL;
+
+/* Non-zero means this terminal can't really do anything. */
+int dumb_term = 0;
+
+char PC;
+char *BC, *UP;
+
+/* Some strings to control terminal actions.  These are output by tputs (). */
+char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace;
+
+int screenwidth, screenheight;
+
+/* 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;
+
+#ifdef 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;
+
+/* 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);
+}
+
+init_terminal_io (terminal_name)
+     char *terminal_name;
+{
+  char *term = (terminal_name? terminal_name : getenv ("TERM"));
+  char *tgetstr (), *buffer;
+#ifdef TIOCGWINSZ
+  struct winsize window_size;
+#endif
+  int tty;
+
+  if (!term_string_buffer)
+    term_string_buffer = (char *)xmalloc (2048);
+
+  if (!term_buffer)
+    term_buffer = (char *)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;
+      return;
+    }
+
+  BC = tgetstr ("pc", &buffer);
+  PC = buffer ? *buffer : 0;
+
+  term_backspace = tgetstr ("le", &buffer);
+
+  term_cr = tgetstr ("cr", &buffer);
+  term_clreol = tgetstr ("ce", &buffer);
+  term_clrpag = tgetstr ("cl", &buffer);
+
+  if (!term_cr)
+    term_cr =  "\r";
+
+#ifdef HACK_TERMCAP_MOTION
+  term_forward_char = tgetstr ("nd", &buffer);
+#endif  /* HACK_TERMCAP_MOTION */
+
+  if (rl_instream)
+    tty = fileno (rl_instream);
+  else
+    tty = 0;
+    
+  screenwidth = screenheight = 0;
+#ifdef TIOCGWINSZ
+  if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
+    {
+      screenwidth = (int) window_size.ws_col;
+      screenheight = (int) window_size.ws_row;
+    }
+#endif
+
+  if (screenwidth <= 0 || screenheight <= 0)
+    {
+      screenwidth = tgetnum ("co");
+      screenheight = tgetnum ("li");
+    }
+
+  screenwidth--;
+
+  if (screenwidth <= 0)
+    screenwidth = 79;
+
+  if (screenheight <= 0)
+    screenheight = 24;
+
+  term_im = tgetstr ("im", &buffer);
+  term_ei = tgetstr ("ei", &buffer);
+  term_IC = tgetstr ("IC", &buffer);
+  term_ic = tgetstr ("ic", &buffer);
+
+  /* "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);
+
+  term_up = tgetstr ("up", &buffer);
+  term_dc = tgetstr ("dc", &buffer);
+  term_DC = tgetstr ("DC", &buffer);
+
+  visible_bell = tgetstr ("vb", &buffer);
+}
+
+/* A function for the use of tputs () */
+void
+output_character_function (c)
+     int c;
+{
+  putc (c, out_stream);
+}
+
+/* Write COUNT characters from STRING to the output stream. */
+static void
+output_some_chars (string, count)
+     char *string;
+     int count;
+{
+  fwrite (string, 1, count, out_stream);
+}
+
+/* Delete COUNT characters from the display line. */
+static
+delete_chars (count)
+     int count;
+{
+  if (count > screenwidth)
+    return;
+
+  if (term_DC && *term_DC)
+    {
+      char *tgoto (), *buffer;
+      buffer = tgoto (term_DC, 0, count);
+      tputs (buffer, 1, output_character_function);
+    }
+  else
+    {
+      if (term_dc && *term_dc)
+       while (count--)
+         tputs (term_dc, 1, output_character_function);
+    }
+}
+
+/* Insert COUNT characters from STRING to the output stream. */
+static
+insert_some_chars (string, count)
+     char *string;
+     int count;
+{
+  /* 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, output_character_function);
+      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, 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, output_character_function);
+       }
+
+      /* Print the text. */
+      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, output_character_function);
+    }
+}
+
+/* Move the cursor back. */
+backspace (count)
+     int count;
+{
+  register int i;
+
+  if (term_backspace)
+    for (i = 0; i < count; i++)
+      tputs (term_backspace, 1, output_character_function);
+  else
+    for (i = 0; i < count; i++)
+      putc ('\b', out_stream);
+}
+
+/* Move to the start of the next line. */
+crlf ()
+{
+  tputs (term_cr, 1, output_character_function);
+  putc ('\n', out_stream);
+}
+
+/* Clear to the end of the line.  COUNT is the minimum
+   number of character spaces to clear, */
+clear_to_eol (count)
+     int count;
+{
+  if (term_clreol)
+    {
+      tputs (term_clreol, 1, output_character_function);
+    }
+  else
+    {
+      register int i;
+
+      /* Do one more character space. */
+      count++;
+
+      for (i = 0; i < count; i++)
+       putc (' ', out_stream);
+
+      backspace (count);
+    }
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                   Saving and Restoring the TTY                  */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero means that the terminal is in a prepped state. */
+static int terminal_prepped = 0;
+
+#ifdef NEW_TTY_DRIVER
+
+/* Standard flags, including ECHO. */
+static int original_tty_flags = 0;
+
+/* Local mode flags, like LPASS8. */
+static int local_mode_flags = 0;
+
+/* Terminal characters.  This has C-s and C-q in it. */
+static struct tchars original_tchars;
+
+/* Local special characters.  This has the interrupt characters in it. */
+static struct ltchars original_ltchars;
+
+/* We use this to get and set the tty_flags. */
+static struct sgttyb the_ttybuff;
+
+/* Put the terminal in CBREAK mode so that we can detect key presses. */
+static
+rl_prep_terminal ()
+{
+  int tty = fileno (rl_instream);
+  int oldmask = sigblock (sigmask (SIGINT));
+
+  if (!terminal_prepped)
+    {
+      /* We always get the latest tty values.  Maybe stty changed them. */
+      ioctl (tty, TIOCGETP, &the_ttybuff);
+      original_tty_flags = the_ttybuff.sg_flags;
+
+      readline_echoing_p = (original_tty_flags & ECHO);
+
+#if defined (TIOCLGET)
+      ioctl (tty, TIOCLGET, &local_mode_flags);
+#endif
+
+#if !defined (ANYP)
+#define ANYP (EVENP | ODDP)
+#endif
+      /* If this terminal doesn't care how the 8th bit is used,
+        then we can use it for the meta-key.
+        We check by seeing if BOTH odd and even parity are allowed. */
+      if (the_ttybuff.sg_flags & ANYP)
+       {
+#if defined (PASS8)
+         the_ttybuff.sg_flags |= PASS8;
+#endif
+
+         /* Hack on local mode flags if we can. */
+#if defined (TIOCLGET) && defined (LPASS8)
+         {
+           int flags;
+           flags = local_mode_flags | LPASS8;
+           ioctl (tty, TIOCLSET, &flags);
+         }
+#endif /* TIOCLGET && LPASS8 */
+       }
+#ifdef TIOCGETC
+      {
+       struct tchars temp;
+
+       ioctl (tty, TIOCGETC, &original_tchars);
+       temp = original_tchars;
+
+       /* Get rid of C-s and C-q.
+          We remember the value of startc (C-q) so that if the terminal is in
+          xoff state, the user can xon it by pressing that character. */
+       xon_char = temp.t_startc;
+       temp.t_stopc = -1;
+       temp.t_startc = -1;
+
+       /* If there is an XON character, bind it to restart the output. */
+       if (xon_char != -1)
+         rl_bind_key (xon_char, rl_restart_output);
+
+       /* If there is an EOF char, bind eof_char to it. */
+       if (temp.t_eofc != -1)
+         eof_char = temp.t_eofc;
+
+#if defined (NOTDEF)
+       /* Get rid of C-\ and C-c. */
+       temp.t_intrc = temp.t_quitc = -1;
+#endif /* NOTDEF */
+
+       ioctl (tty, TIOCSETC, &temp);
+      }
+#endif /* TIOCGETC */
+
+#ifdef TIOCGLTC
+      {
+       struct ltchars temp;
+
+       ioctl (tty, TIOCGLTC, &original_ltchars);
+       temp = original_ltchars;
+
+       /* Make the interrupt keys go away.  Just enough to make people
+          happy. */
+       temp.t_dsuspc = -1;     /* C-y */
+       temp.t_lnextc = -1;     /* C-v */
+
+       ioctl (tty, TIOCSLTC, &temp);
+      }
+#endif /* TIOCGLTC */
+
+      the_ttybuff.sg_flags &= (~ECHO|CRMOD);
+      the_ttybuff.sg_flags |= CBREAK;
+      ioctl (tty, TIOCSETN, &the_ttybuff);
+
+      terminal_prepped = 1;
+    }
+  sigsetmask (oldmask);
+}
+
+/* Restore the terminal to its original state. */
+static
+rl_deprep_terminal ()
+{
+  int tty = fileno (rl_instream);
+  int oldmask = sigblock (sigmask (SIGINT));
+
+  if (terminal_prepped)
+    {
+      the_ttybuff.sg_flags = original_tty_flags;
+      ioctl (tty, TIOCSETN, &the_ttybuff);
+      readline_echoing_p = 1;
+
+#if defined (TIOCLGET)
+      ioctl (tty, TIOCLSET, &local_mode_flags);
+#endif
+
+#ifdef TIOCSLTC
+      ioctl (tty, TIOCSLTC, &original_ltchars);
+#endif
+
+#ifdef TIOCSETC
+      ioctl (tty, TIOCSETC, &original_tchars);
+#endif
+      terminal_prepped = 0;
+    }
+  sigsetmask (oldmask);
+}
+
+#else  /* !defined (NEW_TTY_DRIVER) */
+
+#if !defined (VMIN)
+#define VMIN VEOF
+#endif
+
+#if !defined (VTIME)
+#define VTIME VEOL
+#endif
+
+#if defined (_POSIX_VERSION)
+static struct termios otio;
+#else
+static struct termio otio;
+#endif
+
+static
+rl_prep_terminal ()
+{
+  int tty = fileno (rl_instream);
+#if defined (_POSIX_VERSION)
+  struct termios tio;
+#else
+  struct termio tio;
+#endif
+
+  /* If we are on a Posix system, block the delivery of SIGINT for a while. */
+#if defined (_POSIX_VERSION)
+  sigset_t set, oset;
+
+  sigemptyset (&set);
+  sigaddset (&set, SIGINT);
+  sigprocmask (SIG_BLOCK, &set, &oset);
+#else 
+#  if defined (HAVE_BSD_SIGNALS)
+  int oldmask = sigblock (sigmask (SIGINT));
+#  endif /* HAVE_BSD_SIGNALS */
+#endif /* POSIX */
+
+  wait_foreground ();   /* XXX this prevents to got editing mode from tcsh */
+#if defined (_POSIX_VERSION)
+  tcgetattr (tty, &tio);
+#else
+  ioctl (tty, TCGETA, &tio);
+#endif /* POSIX */
+
+  otio = tio;
+
+  readline_echoing_p = (tio.c_lflag & ECHO);
+
+  tio.c_lflag &= ~(ICANON|ECHO);
+
+#if defined (IXANY)
+  tio.c_iflag &= ~(IXON|IXOFF|IXANY);
+#else
+  /* `strict' Posix systems do not define IXANY. */
+  tio.c_iflag &= ~(IXON|IXOFF);
+#endif /* IXANY */
+
+  /* Only turn this off if we are using all 8 bits. */
+  /* |ISTRIP|INPCK */
+
+#if !defined (HANDLE_SIGNALS)
+  tio.c_lflag &= ~ISIG;
+#else
+  tio.c_lflag |= ISIG; /* shouldn't be needed, but... */
+#endif
+
+  tio.c_cc[VMIN] = 1;
+  tio.c_cc[VTIME] = 0;
+
+  /* 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 (_POSIX_VERSION) && defined (_POSIX_JOB_CONTROL)
+
+#if !defined (_POSIX_VDISABLE)
+#define _POSIX_VDISABLE        0
+#endif /* POSIX_VDISABLE */
+
+#if defined (VLNEXT)
+  tio.c_cc[VLNEXT] = _POSIX_VDISABLE;
+#endif
+
+#if defined (VDSUSP)
+  tio.c_cc[VDSUSP] = _POSIX_VDISABLE;
+#endif
+
+#endif /* POSIX && JOB_CONTROL */
+
+#if defined (_POSIX_VERSION)
+  tcsetattr (tty, TCSADRAIN, &tio);
+  tcflow (tty, TCOON);         /* Simulate a ^Q. */
+#else
+  ioctl (tty, TCSETAW, &tio);
+  ioctl (tty, TCXONC, 1);      /* Simulate a ^Q. */
+#endif /* POSIX */
+
+#if defined (_POSIX_VERSION)
+  sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+#else
+#  if defined (HAVE_BSD_SIGNALS)
+  sigsetmask (oldmask);
+#  endif /* HAVE_BSD_SIGNALS */
+#endif /* POSIX */
+}
+
+static
+rl_deprep_terminal ()
+{
+  int tty = fileno (rl_instream);
+
+  /* If we are on a Posix system, block the delivery of SIGINT for a while. */
+#if defined (_POSIX_VERSION)
+  sigset_t set, oset;
+
+  sigemptyset (&set);
+  sigaddset (&set, SIGINT);
+  sigprocmask (SIG_BLOCK, &set, &oset);
+#else
+#  if defined (HAVE_BSD_SIGNALS)
+  int oldmask = sigblock (sigmask (SIGINT));
+#  endif /* HAVE_BSD_SIGNALS */
+#endif /* POSIX */
+
+#if defined (_POSIX_VERSION)
+  tcsetattr (tty, TCSADRAIN, &otio);
+  tcflow (tty, TCOON);         /* Simulate a ^Q. */
+#else
+  ioctl (tty, TCSETAW, &otio);
+  ioctl (tty, TCXONC, 1);      /* Simulate a ^Q. */
+#endif /* POSIX */
+
+#if defined (_POSIX_VERSION)
+  sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+#else
+#  if defined (HAVE_BSD_SIGNALS)
+  sigsetmask (oldmask);
+#  endif /* HAVE_BSD_SIGNALS */
+#endif /* POSIX */
+}
+#endif  /* NEW_TTY_DRIVER */
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Utility Functions                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Return 0 if C is not a member of the class of characters that belong
+   in words, or 1 if it is. */
+
+int allow_pathname_alphabetic_chars = 0;
+char *pathname_alphabetic_chars = "/-_=~.#$";
+
+int
+alphabetic (c)
+     int c;
+{
+  if (pure_alphabetic (c) || (numeric (c)))
+    return (1);
+
+  if (allow_pathname_alphabetic_chars)
+    return ((int)rindex (pathname_alphabetic_chars, c));
+  else
+    return (0);
+}
+
+/* Return non-zero if C is a numeric character. */
+int
+numeric (c)
+     int c;
+{
+  return (c >= '0' && c <= '9');
+}
+
+/* Ring the terminal bell. */
+int
+ding ()
+{
+  if (readline_echoing_p)
+    {
+      if (prefer_visible_bell && visible_bell)
+       tputs (visible_bell, 1, output_character_function);
+      else
+       {
+         fprintf (stderr, "\007");
+         fflush (stderr);
+       }
+    }
+  return (-1);
+}
+
+/* How to abort things. */
+rl_abort ()
+{
+  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. */
+#if defined (sun) /* Yes, that's right, some crufty function in sunview is
+                    called rl_copy (). */
+static
+#endif
+char *
+rl_copy (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 = (char *)xmalloc (1 + length);
+  strncpy (copy, the_line + from, length);
+  copy[length] = '\0';
+  return (copy);
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Insert and Delete                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Insert a string of text into the line at point.  This is the only
+   way that you should do insertion.  rl_insert () calls this
+   function. */
+rl_insert_text (string)
+     char *string;
+{
+  extern int doing_an_undo;
+  register int i, l = strlen (string);
+  while (rl_end + l >= rl_line_buffer_len)
+    {
+      rl_line_buffer =
+       (char *)xrealloc (rl_line_buffer,
+                         rl_line_buffer_len += DEFAULT_BUFFER_SIZE);
+      the_line = rl_line_buffer;
+    }
+
+  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 ((strlen (string) == 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';
+}
+
+/* Delete the string between FROM and TO.  FROM is
+   inclusive, TO is not. */
+rl_delete_text (from, to)
+     int from, to;
+{
+  extern int doing_an_undo;
+  register char *text;
+
+  /* Fix it if the caller is confused. */
+  if (from > to)
+    {
+      int t = from;
+      from = to;
+      to = t;
+    }
+  text = rl_copy (from, to);
+  strncpy (the_line + from, the_line + to, rl_end - to);
+
+  /* Remember how to undo this delete. */
+  if (!doing_an_undo)
+    rl_add_undo (UNDO_DELETE, from, to, text);
+  else
+    free (text);
+
+  rl_end -= (to - from);
+  the_line[rl_end] = '\0';
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Readline character functions                */
+/*                                                                 */
+/* **************************************************************** */
+
+/* This is not a gap editor, just a stupid line input routine.  No hair
+   is involved in writing any of the functions, and none should be. */
+
+/* Note that:
+
+   rl_end is the place in the string that we would place '\0';
+   i.e., it is always safe to place '\0' there.
+
+   rl_point is the place in the string where the cursor is.  Sometimes
+   this is the same as rl_end.
+
+   Any command that is called interactively receives two arguments.
+   The first is a count: the numeric arg pased to this command.
+   The second is the key which invoked this command.
+*/
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Movement Commands                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Note that if you `optimize' the display for these functions, you cannot
+   use said functions in other functions which do not do optimizing display.
+   I.e., you will have to update the data base for rl_redisplay, and you
+   might as well let rl_redisplay do that job. */
+
+/* Move forward COUNT characters. */
+rl_forward (count)
+     int count;
+{
+  if (count < 0)
+    rl_backward (-count);
+  else
+    while (count)
+      {
+#ifdef VI_MODE
+       if (rl_point == (rl_end - (rl_editing_mode == vi_mode)))
+#else
+       if (rl_point == rl_end)
+#endif
+         {
+           ding ();
+           return;
+         }
+       else
+         rl_point++;
+       --count;
+      }
+}
+
+/* Move backward COUNT characters. */
+rl_backward (count)
+     int count;
+{
+  if (count < 0)
+    rl_forward (-count);
+  else
+    while (count)
+      {
+       if (!rl_point)
+         {
+           ding ();
+           return;
+         }
+       else
+         --rl_point;
+       --count;
+      }
+}
+
+/* Move to the beginning of the line. */
+rl_beg_of_line ()
+{
+  rl_point = 0;
+}
+
+/* Move to the end of the line. */
+rl_end_of_line ()
+{
+  rl_point = rl_end;
+}
+
+/* Move forward a word.  We do what Emacs does. */
+rl_forward_word (count)
+     int count;
+{
+  int c;
+
+  if (count < 0)
+    {
+      rl_backward_word (-count);
+      return;
+    }
+
+  while (count)
+    {
+      if (rl_point == rl_end)
+       return;
+
+      /* 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;
+      while (++rl_point < rl_end)
+       {
+         c = the_line[rl_point];
+         if (!alphabetic (c)) break;
+       }
+      --count;
+    }
+}
+
+/* Move backward a word.  We do what Emacs does. */
+rl_backward_word (count)
+     int count;
+{
+  int c;
+
+  if (count < 0)
+    {
+      rl_forward_word (-count);
+      return;
+    }
+
+  while (count)
+    {
+      if (!rl_point)
+       return;
+
+      /* 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;
+    }
+}
+
+/* Clear the current line.  Numeric argument to C-l does this. */
+rl_refresh_line ()
+{
+  int curr_line = last_c_pos / screenwidth;
+  extern char *term_clreol;
+
+  move_vert(curr_line);
+  move_cursor_relative (0, the_line);   /* XXX is this right */
+
+  if (term_clreol)
+    tputs (term_clreol, 1, output_character_function);
+
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+}
+
+/* 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 ()
+{
+  extern char *term_clrpag;
+
+  if (rl_explicit_arg)
+    {
+      rl_refresh_line ();
+      return;
+    }
+
+  if (term_clrpag)
+    tputs (term_clrpag, 1, output_character_function);
+  else
+    crlf ();
+
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+}
+
+rl_arrow_keys(count,c)
+     int count,c;
+{
+  int ch = rl_read_key();
+
+  switch(ch) {
+    case 'a':
+    case 'A':
+      rl_get_previous_history(count);
+      return;
+    case 'b':
+    case 'B':
+      rl_get_next_history(count);
+      return;
+    case 'c':
+    case 'C':
+      rl_forward(count);
+      return;
+    case 'd':
+    case 'D':
+      rl_backward(count);
+      return;
+    default:
+      ding();
+      return;
+  }
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Text commands                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Insert the character C at the current location, moving point forward. */
+rl_insert (count, c)
+     int count, c;
+{
+  register int i;
+  char *string;
+
+  if (count <= 0)
+    return;
+
+  /* If we can optimize, then do it.  But don't let people crash
+     readline because of extra large arguments. */
+  if (count > 1 && count < 1024)
+    {
+      string = (char *)alloca (1 + count);
+
+      for (i = 0; i < count; i++)
+       string[i] = c;
+
+      string[i] = '\0';
+      rl_insert_text (string);
+      return;
+    }
+
+  if (count > 1024)
+    {
+      int decreaser;
+
+      string = (char *)alloca (1024 + 1);
+
+      for (i = 0; i < 1024; i++)
+       string[i] = c;
+
+      while (count)
+       {
+         decreaser = (count > 1024 ? 1024 : count);
+         string[decreaser] = '\0';
+         rl_insert_text (string);
+         count -= decreaser;
+       }
+      return;
+    }
+
+  /* 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 = (char *)alloca (ibuffer_len + 1);
+      string[i++] = c;
+
+      while ((t = rl_get_char (&key)) &&
+            (keymap[key].type == ISFUNC &&
+             keymap[key].function == rl_insert))
+       string[i++] = key;
+
+      if (t)
+       rl_unget_char (key);
+
+      string[i] = '\0';
+      rl_insert_text (string);
+      return;
+    }
+  else
+    {
+      /* Inserting a single character. */
+      string = (char *)alloca (2);
+
+      string[1] = '\0';
+      string[0] = c;
+      rl_insert_text (string);
+    }
+}
+
+/* Insert the next typed character verbatim. */
+rl_quoted_insert (count)
+     int count;
+{
+  int c = rl_read_key ();
+  rl_insert (count, c);
+}
+
+/* Insert a tab character. */
+rl_tab_insert (count)
+     int count;
+{
+  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;
+
+#ifdef VI_MODE
+  {
+    extern int vi_doing_insert;
+    if (vi_doing_insert)
+      {
+       rl_end_undo_group ();
+       vi_doing_insert = 0;
+      }
+  }
+#endif /* VI_MODE */
+
+  if (readline_echoing_p)
+    {
+      move_vert (vis_botlin);
+      vis_botlin = 0;
+      crlf ();
+      fflush (out_stream);
+      rl_display_fixed++;
+    }
+}
+
+rl_clean_up_for_exit ()
+{
+  if (readline_echoing_p)
+    {
+      move_vert (vis_botlin);
+      vis_botlin = 0;
+      fflush (out_stream);
+      rl_restart_output ();
+    }
+}
+
+/* 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;
+{
+}
+
+/* Rubout the character behind point. */
+rl_rubout (count)
+     int count;
+{
+  if (count < 0)
+    {
+      rl_delete (-count);
+      return;
+    }
+
+  if (!rl_point)
+    {
+      ding ();
+      return;
+    }
+
+  if (count > 1)
+    {
+      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 && alphabetic (c) && last_c_pos)
+       {
+         backspace (1);
+         putc (' ', out_stream);
+         backspace (1);
+         last_c_pos--;
+         visible_line[last_c_pos] = '\0';
+         rl_display_fixed++;
+       }
+    }
+}
+
+/* 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)
+    {
+      rl_rubout (-count);
+      return;
+    }
+
+  if (rl_point == rl_end)
+    {
+      ding ();
+      return;
+    }
+
+  if (count > 1)
+    {
+      int orig_point = rl_point;
+      rl_forward (count);
+      rl_kill_text (orig_point, rl_point);
+      rl_point = orig_point;
+    }
+  else
+    rl_delete_text (rl_point, rl_point + 1);
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Kill commands                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The next two functions mimic unix line editing behaviour, except they
+   save the deleted text on the kill ring.  This is safer than not saving
+   it, and since we have a ring, nobody should get screwed. */
+
+/* This does what C-w does in Unix.  We can't prevent people from
+   using behaviour that they expect. */
+rl_unix_word_rubout ()
+{
+  if (!rl_point) ding ();
+  else {
+    int orig_point = rl_point;
+    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 (rl_point, orig_point);
+  }
+}
+
+/* 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 ()
+{
+  if (!rl_point) ding ();
+  else {
+    rl_kill_text (rl_point, 0);
+    rl_point = 0;
+  }
+}
+
+\f
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Commands For Typos                          */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Random and interesting things in here.  */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Changing Case                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The three kinds of things that we know how to do. */
+#define UpCase 1
+#define DownCase 2
+#define CapCase 3
+
+/* Uppercase the word at point. */
+rl_upcase_word (count)
+     int count;
+{
+  rl_change_case (count, UpCase);
+}
+
+/* Lowercase the word at point. */
+rl_downcase_word (count)
+     int count;
+{
+  rl_change_case (count, DownCase);
+}
+
+/* Upcase the first letter, downcase the rest. */
+rl_capitalize_word (count)
+     int count;
+{
+  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. */
+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:
+         abort ();
+       }
+    }
+  rl_point = end;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Transposition                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Transpose the words at point. */
+rl_transpose_words (count)
+     int count;
+{
+  char *word1, *word2;
+  int w1_beg, w1_end, w2_beg, w2_end;
+  int orig_point = rl_point;
+
+  if (!count) return;
+
+  /* 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;
+    }
+
+  /* Get the text of the words. */
+  word1 = rl_copy (w1_beg, w1_end);
+  word2 = rl_copy (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);
+}
+
+/* Transpose the characters at point.  If point is at the end of the line,
+   then transpose the characters before point. */
+rl_transpose_chars (count)
+     int count;
+{
+  if (!count)
+    return;
+
+  if (!rl_point || rl_end < 2) {
+    ding ();
+    return;
+  }
+
+  while (count) {
+    if (rl_point == rl_end) {
+      int t = the_line[rl_point - 1];
+      the_line[rl_point - 1] = the_line[rl_point - 2];
+      the_line[rl_point - 2] = t;
+    } else {
+      int t = the_line[rl_point];
+      the_line[rl_point] = the_line[rl_point - 1];
+      the_line[rl_point - 1] = t;
+      if (count < 0 && rl_point)
+       rl_point--;
+      else
+       rl_point++;
+    }
+    if (count < 0)
+      count++;
+    else
+      count--;
+  }
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Bogus Flow Control                          */
+/*                                                                 */
+/* **************************************************************** */
+
+rl_restart_output (count, key)
+     int count, key;
+{
+  int fildes = fileno (stdin);
+#if defined (TIOCSTART)
+#if defined (apollo)
+  ioctl (&fildes, TIOCSTART, 0);
+#else
+  ioctl (fildes, TIOCSTART, 0);
+#endif /* apollo */
+
+#else
+#  if defined (TCXONC)
+  ioctl (fildes, TCXONC, TCOON);
+#  endif /* TCXONC */
+#endif /* TIOCSTART */
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*     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. */
+Function *rl_attempted_completion_function = (Function *)NULL;
+
+/* 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)
+    rl_complete_internal ('?');
+  else
+    rl_complete_internal (TAB);
+}
+
+/* List the possible completions.  See description of rl_complete (). */
+rl_possible_completions ()
+{
+  rl_complete_internal ('?');
+}
+
+/* The user must press "y" or "n". Non-zero return means "y" pressed. */
+get_y_or_n ()
+{
+  int c;
+ loop:
+  c = rl_read_key ();
+  if (c == 'y' || c == 'Y') return (1);
+  if (c == 'n' || c == 'N') return (0);
+  if (c == ABORT_CHAR) rl_abort ();
+  ding (); goto loop;
+}
+
+/* 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 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;
+
+/* 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;
+
+/* 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. */
+rl_complete_internal (what_to_do)
+     int what_to_do;
+{
+  char *filename_completion_function ();
+  char **completion_matches (), **matches;
+  Function *our_func;
+  int start, end, delimiter = 0;
+  char *text;
+
+  if (rl_completion_entry_function)
+    our_func = rl_completion_entry_function;
+  else
+    our_func = (int (*)())filename_completion_function;
+
+  /* Only the completion entry function can change this. */
+  rl_filename_completion_desired = 0;
+
+  /* We now look backwards for the start of a filename/variable word. */
+  end = rl_point;
+
+  if (rl_point)
+    {
+      while (--rl_point &&
+            !rindex (rl_completer_word_break_characters, the_line[rl_point]));
+
+      /* If we are at a word break, then advance past it. */
+      if (rindex (rl_completer_word_break_characters,  (the_line[rl_point])))
+       {
+         /* If the character that caused the word break was a quoting
+            character, then remember it as the delimiter. */
+         if (rindex ("\"'", the_line[rl_point]) && (end - rl_point) > 1)
+           delimiter = the_line[rl_point];
+
+         /* 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 ||
+             !rindex (rl_special_prefixes, the_line[rl_point]))
+           rl_point++;
+       }
+    }
+
+  start = rl_point;
+  rl_point = end;
+  text = rl_copy (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 =
+       (char **)(*rl_attempted_completion_function) (text, start, end);
+
+      if (matches)
+       {
+         our_func = (Function *)NULL;
+         goto after_usual_completion;
+       } 
+    }
+
+  matches = completion_matches (text, our_func);
+
+ after_usual_completion:
+  free (text);
+
+  if (!matches)
+    ding ();
+  else
+    {
+      register int i;
+
+    some_matches:
+
+      /* 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;
+
+         /* 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++);
+         qsort (matches, i, 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 *)-1;
+               }
+             else
+               newlen++;
+           }
+
+         /* We have marked all the dead slots with (char *)-1.
+            Copy all the non-dead entries into a new array. */
+         {
+           char **temp_array =
+             (char **)malloc ((3 + newlen) * sizeof (char *));
+
+           for (i = 1, j = 1; matches[i]; i++)
+             {
+               if (matches[i] != (char *)-1)
+                 temp_array[j++] = matches[i];
+             }
+
+           temp_array[j] = (char *)NULL;
+
+           if (matches[0] != (char *)-1)
+             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:
+         /* 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 == (int (*)())filename_completion_function)
+           (void)(*rl_ignore_some_completions_function)(matches);
+         
+         if (matches[0])
+           {
+             rl_delete_text (start, rl_point);
+             rl_point = start;
+             rl_insert_text (matches[0]);
+           }
+         
+         /* 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])
+           {
+             ding ();          /* There are other matches remaining. */
+           }
+         else
+           {
+             char temp_string[2];
+
+             temp_string[0] = delimiter ? delimiter : ' ';
+             temp_string[1] = '\0';
+
+             if (rl_filename_completion_desired)
+               {
+                 struct stat finfo;
+                 char *tilde_expand ();
+                 char *filename = tilde_expand (matches[0]);
+
+                 if ((stat (filename, &finfo) == 0) &&
+                     ((finfo.st_mode & S_IFMT) == S_IFDIR))
+                   {
+                     if (the_line[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_delete_text (start, rl_point);
+           rl_point = start;
+           rl_begin_undo_group ();
+           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 = 0;
+           int j, k, l;
+
+           /* Handle simple case first.  What if there is only one answer? */
+           if (!matches[1])
+             {
+               char *temp;
+
+               if (rl_filename_completion_desired)
+                 temp = rindex (matches[0], '/');
+               else
+                 temp = (char *)NULL;
+
+               if (!temp)
+                 temp = matches[0];
+               else
+                 temp++;
+
+               crlf ();
+               fprintf (out_stream, "%s", temp);
+               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. */
+           for (i = 1; matches[i]; i++)
+             {
+               char *temp = (char *)NULL;
+
+               /* If we are hacking filenames, then only count the characters
+                  after the last slash in the pathname. */
+               if (rl_filename_completion_desired)
+                 temp = rindex (matches[i], '/');
+               else
+                 temp = (char *)NULL;
+
+               if (!temp)
+                 temp = matches[i];
+               else
+                 temp++;
+
+               if (strlen (temp) > max)
+                 max = strlen (temp);
+             }
+
+           len = i;
+
+           /* 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 (out_stream,
+                        "There are %d possibilities.  Do you really", len);
+               crlf ();
+               fprintf (out_stream, "wish to see them all? (y or n)");
+               fflush (out_stream);
+               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. */
+           if (len < limit) count = 1;
+
+           /* Sort the items if they are not already sorted. */
+           if (!rl_ignore_completion_duplicates)
+             qsort (matches, len, sizeof (char *), compare_strings);
+
+           /* Print the sorted items, up-and-down alphabetically, like
+              ls might. */
+           crlf ();
+
+           for (i = 1; i < count + 1; i++)
+             {
+               for (j = 0, l = i; j < limit; j++)
+                 {
+                   if (l > len || !matches[l])
+                     {
+                       break;
+                     }
+                   else
+                     {
+                       char *temp = (char *)NULL;
+
+                       if (rl_filename_completion_desired)
+                         temp = rindex (matches[l], '/');
+                       else
+                         temp = (char *)NULL;
+
+                       if (!temp)
+                         temp = matches[l];
+                       else
+                         temp++;
+
+                       fprintf (out_stream, "%s", temp);
+                       for (k = 0; k < max - strlen (temp); k++)
+                         putc (' ', out_stream);
+                     }
+                   l += count;
+                 }
+               crlf ();
+             }
+         restart:
+
+           rl_on_new_line ();
+         }
+         break;
+
+       default:
+         abort ();
+       }
+
+      for (i = 0; matches[i]; i++)
+       free (matches[i]);
+      free (matches);
+    }
+}
+
+/* Stupid comparison routine for qsort () ing strings. */
+static int
+compare_strings (s1, s2)
+  char **s1, **s2;
+{
+  return (strcmp (*s1, *s2));
+}
+
+/* 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;
+{
+  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 ())
+    {
+      if (strncmp (username, entry->pw_name, namelen) == 0)
+       break;
+    }
+
+  if (!entry)
+    {
+      endpwent ();
+      return ((char *)NULL);
+    }
+  else
+    {
+      char *value = (char *)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);
+    }
+}
+
+/* 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. */
+Function *rl_tilde_expander = (Function *)NULL;
+
+/* Expand FILENAME if it begins with a tilde.  This always returns
+   a new string. */
+char *
+tilde_expand (filename)
+     char *filename;
+{
+  char *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 = getenv ("HOME");
+
+         temp_name = (char *)alloca (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 = savestring (temp_name);
+       }
+      else
+       {
+         struct passwd *getpwnam (), *user_entry;
+         char *username = (char *)alloca (257);
+         int i, c;
+
+         for (i = 1; c = dirname[i]; i++)
+           {
+             if (c == '/') break;
+             else username[i - 1] = c;
+           }
+         username[i - 1] = '\0';
+
+         if (!(user_entry = getpwnam (username)))
+           {
+             /* If the calling program has a special syntax for
+                expanding tildes, and we couldn't find a standard
+                expansion, then let them try. */
+             if (rl_tilde_expander)
+               {
+                 char *expansion;
+
+                 expansion = (char *)(*rl_tilde_expander) (username);
+
+                 if (expansion)
+                   {
+                     temp_name = (char *)alloca (1 + strlen (expansion)
+                                                 + strlen (&dirname[i]));
+                     strcpy (temp_name, expansion);
+                     strcat (temp_name, &dirname[i]);
+                     free (expansion);
+                     goto return_name;
+                   }
+               }
+             /*
+              * We shouldn't report errors.
+              */
+           }
+         else
+           {
+             temp_name = (char *)alloca (1 + strlen (user_entry->pw_dir)
+                                         + strlen (&dirname[i]));
+             strcpy (temp_name, user_entry->pw_dir);
+             strcat (temp_name, &dirname[i]);
+           return_name:
+             free (dirname);
+             dirname = savestring (temp_name);
+           }
+           endpwent ();
+       }
+    }
+  return (dirname);
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Undo, and Undoing                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero tells rl_delete_text and rl_insert_text to not add to
+   the undo list. */
+int doing_an_undo = 0;
+
+/* 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. */
+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. */
+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);
+  }
+}
+
+/* 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
+      abort ();
+    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. */
+rl_begin_undo_group ()
+{
+  rl_add_undo (UNDO_BEGIN, 0, 0, 0);
+}
+
+/* End an undo group started with rl_begin_undo_group (). */
+rl_end_undo_group ()
+{
+  rl_add_undo (UNDO_END, 0, 0, 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 (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 ();
+    }
+}
+
+/* Revert the current line to its previous state. */
+rl_revert_line ()
+{
+  if (!rl_undo_list) ding ();
+  else {
+    while (rl_undo_list)
+      rl_do_undo ();
+  }
+}
+
+/* Do some undoing of things that were done. */
+rl_undo_command (count)
+{
+  if (count < 0) return;       /* Nothing to do. */
+
+  while (count)
+    {
+      if (rl_do_undo ())
+       {
+         count--;
+       }
+      else
+       {
+         ding ();
+         break;
+       }
+    }
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Utilities                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* We already have a history library, and that is what we use to control
+   the history features of readline.  However, this is our local interface
+   to the history mechanism. */
+
+/* While we are editing the history, this is the saved
+   version of the original line. */
+HIST_ENTRY *saved_line_for_history = (HIST_ENTRY *)NULL;
+
+/* Set the history pointer back to the last entry in the history. */
+start_using_history ()
+{
+  using_history ();
+  if (saved_line_for_history)
+    free_history_entry (saved_line_for_history);
+
+  saved_line_for_history = (HIST_ENTRY *)NULL;
+}
+
+/* Free the contents (and containing structure) of a HIST_ENTRY. */
+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);
+  }
+}
+
+/* Put back the saved_line_for_history if there is one. */
+maybe_unsave_line ()
+{
+  if (saved_line_for_history) {
+    strcpy (the_line, saved_line_for_history->line);
+    rl_undo_list = (UNDO_LIST *)saved_line_for_history->data;
+    free_history_entry (saved_line_for_history);
+    saved_line_for_history = (HIST_ENTRY *)NULL;
+    rl_end = rl_point = strlen (the_line);
+  } else {
+    ding ();
+  }
+}
+
+/* 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;
+  }
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Commands                            */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Meta-< goes to the start of the history. */
+rl_beginning_of_history ()
+{
+  rl_get_previous_history (1 + where_history ());
+}
+
+/* Meta-> goes to the end of the history.  (The current line). */
+rl_end_of_history ()
+{
+  maybe_replace_line ();
+  using_history ();
+  maybe_unsave_line ();
+}
+
+/* Move down to the next history line. */
+rl_get_next_history (count)
+     int count;
+{
+  HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
+
+  if (count < 0)
+    {
+      rl_get_previous_history (-count);
+      return;
+    }
+
+  if (!count)
+    return;
+
+  maybe_replace_line ();
+
+  while (count)
+    {
+      temp = next_history ();
+      if (!temp)
+       break;
+      --count;
+    }
+
+  if (!temp)
+    maybe_unsave_line ();
+  else
+    {
+      strcpy (the_line, temp->line);
+      rl_undo_list = (UNDO_LIST *)temp->data;
+      rl_end = rl_point = strlen (the_line);
+    }
+}
+
+/* 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)
+     int count;
+{
+  HIST_ENTRY *old_temp = (HIST_ENTRY *)NULL;
+  HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
+
+  if (count < 0)
+    {
+      rl_get_next_history (-count);
+      return;
+    }
+
+  if (!count)
+    return;
+
+  /* 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
+    {
+      strcpy (the_line, temp->line);
+      rl_undo_list = (UNDO_LIST *)temp->data;
+      rl_end = rl_point = strlen (the_line);
+#ifdef VI_MODE
+      if (rl_editing_mode == vi_mode)
+       rl_point = 0;
+#endif /* VI_MODE */
+    }
+}
+
+/* There is a command in the K*rn shell which yanks into this line, the last
+   word of the previous line.  Here it is.  We left it on M-. */
+rl_yank_previous_last_arg (ignore)
+     int ignore;
+{
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     I-Search and Searching                      */
+/*                                                                 */
+/* **************************************************************** */
+
+/* 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;
+{
+  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;
+{
+  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. */
+rl_display_search (search_string, reverse_p, where)
+     char *search_string;
+     int reverse_p, where;
+{
+  char *message = (char *)NULL;
+
+  message =
+    (char *)alloca (1 + (search_string ? strlen (search_string) : 0) + 30);
+
+  *message = '\0';
+
+#ifdef NEVER
+  if (where != -1)
+    sprintf (message, "[%d]", where + history_base);
+#endif
+
+  strcat (message, "(");
+
+  if (reverse_p)
+    strcat (message, "reverse-");
+
+  strcat (message, "i-search)`");
+
+  if (search_string)
+    strcat (message, search_string);
+
+  strcat (message, "': ");
+  rl_message (message, 0, 0);
+  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. */
+rl_search_history (direction, invoking_key)
+     int direction;
+     int invoking_key;
+{
+  /* The string that the user types in to search for. */
+  char *search_string = (char *)alloca (128);
+
+  /* The current length of SEARCH_STRING. */
+  int search_string_index;
+
+  /* The list of lines to search through. */
+  char **lines;
+
+  /* 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;
+
+  /* The line currently being searched. */
+  char *sline;
+
+  /* Offset in that line. */
+  int 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 **)alloca ((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
+    {
+      /* So I have to type it in this way instead. */
+      lines[i] = (char *)alloca (1 + strlen (the_line));
+      strcpy (lines[i], &the_line[0]);
+    }
+
+  hlen++;
+
+  /* The line where we start the search. */
+  i = orig_line;
+
+  /* Initialize search parameters. */
+  *search_string = '\0';
+  search_string_index = 0;
+
+  rl_display_search (search_string, reverse, -1);
+
+  sline = the_line;
+  index = rl_point;
+
+  while (!done)
+    {
+      c = rl_read_key ();
+
+      /* Hack C to Do What I Mean. */
+      {
+       Function *f = (Function *)NULL;
+
+       if (keymap[c].type == ISFUNC)
+         f = 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 invoking_key: */
+       case -1:
+         goto search_again;
+
+         /* switch directions */
+       case -2:
+         direction = -direction;
+         reverse = (direction < 0);
+
+         goto do_search;
+
+       case CTRL ('G'):
+         strcpy (the_line, lines[orig_line]);
+         rl_point = orig_point;
+         rl_end = strlen (the_line);
+         rl_clear_message ();
+         return;
+
+       default:
+         if (c < 32 || c > 126)
+           {
+             rl_execute_next (c);
+             done = 1;
+             continue;
+           }
+         else
+           {
+             search_string[search_string_index++] = c;
+             search_string[search_string_index] = '\0';
+             goto do_search;
+
+           search_again:
+
+             if (!search_string_index)
+               continue;
+             else
+               {
+                 if (reverse)
+                   --index;
+                 else
+                   if (index != strlen (sline))
+                     ++index;
+                   else
+                     ding ();
+               }
+           do_search:
+
+             while (1)
+               {
+                 if (reverse)
+                   {
+                     while (index >= 0)
+                       if (strncmp
+                           (search_string,
+                            sline + index,
+                            search_string_index) == 0)
+                         goto string_found;
+                       else
+                         index--;
+                   }
+                 else
+                   {
+                     register int limit =
+                       (strlen (sline) - search_string_index) + 1;
+
+                     while (index < limit)
+                       {
+                         if (strncmp (search_string,
+                                      sline + index,
+                                      search_string_index) == 0)
+                           goto string_found;
+                         index++;
+                       }
+                   }
+
+               next_line:
+                 i += direction;
+
+                 /* At limit for direction? */
+                 if ((reverse && i < 0) ||
+                     (!reverse && i == hlen))
+                   goto search_failed;
+
+                 sline = lines[i];
+                 if (reverse)
+                   index = strlen (sline);
+                 else
+                   index = 0;
+
+                 /* If the search string is longer than the current
+                    line, no match. */
+                 if (search_string_index > strlen (sline))
+                   goto next_line;
+
+                 /* Start actually searching. */
+                 if (reverse)
+                   index -= search_string_index;
+               }
+
+           search_failed:
+             /* We cannot find the search string.  Ding the bell. */
+             ding ();
+             i = last_found_line;
+             break;
+
+           string_found:
+             /* 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. */
+             strcpy (the_line, lines[i]);
+             rl_point = index;
+             rl_end = strlen (the_line);
+             last_found_line = i;
+             rl_display_search (search_string, reverse,
+                                (i == orig_line) ? -1 : i);
+           }
+       }
+      continue;
+    }
+
+  /* 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
+     INDEX is -1, then that shows that the string searched for was not
+     found.  We use this to determine where to place rl_point. */
+  {
+    int now = last_found_line;
+
+    /* First put back the original state. */
+    strcpy (the_line, lines[orig_line]);
+
+    if (now < orig_line)
+      rl_get_previous_history (orig_line - now);
+    else
+      rl_get_next_history (now - orig_line);
+
+    /* If the index of the "matched" string is less than zero, then the
+       final search string was never matched, so put point somewhere
+       reasonable. */
+    if (index < 0)
+      index = strlen (the_line);
+
+    rl_point = index;
+    rl_clear_message ();
+  }
+}
+
+/* Make C be the next command to be executed. */
+rl_execute_next (c)
+     int c;
+{
+  rl_pending_input = c;
+}
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Killing Mechanism                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* What we assume for a max number of kills. */
+#define DEFAULT_MAX_KILLS 10
+
+/* The real variable to look at to find out when to flush kills. */
+int rl_max_kills = DEFAULT_MAX_KILLS;
+
+/* Where to store killed text. */
+char **rl_kill_ring = (char **)NULL;
+
+/* Where we are in the kill ring. */
+int rl_kill_index = 0;
+
+/* How many slots we have in the kill ring. */
+int rl_kill_ring_length = 0;
+
+/* How to say that you only want to save a certain amount
+   of kill material. */
+rl_set_retained_kills (num)
+     int num;
+{}
+
+/* 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 = rl_copy (from, to);
+
+  /* Is there anything to kill? */
+  if (from == to)
+    {
+      free (text);
+      last_command_was_kill++;
+      return;
+    }
+
+  /* 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 *));
+         slot = 1;
+       }
+      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
+           {
+             rl_kill_ring =
+               (char **)
+                 xrealloc (rl_kill_ring,
+                           ((slot = (rl_kill_ring_length += 1)) + 1)
+                           * sizeof (char *));
+           }
+       }
+      slot--;
+    }
+  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 = (char *)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++;
+}
+
+/* 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)
+     int count;
+{
+  int orig_point = rl_point;
+
+  if (count < 0)
+    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;
+    }
+}
+
+/* Rubout the word before point, placing it on the kill ring. */
+rl_backward_kill_word (count)
+     int count;
+{
+  int orig_point = rl_point;
+
+  if (count < 0)
+    rl_kill_word (-count);
+  else
+    {
+      rl_backward_word (count);
+
+      if (rl_point != orig_point)
+       rl_kill_text (orig_point, rl_point);
+    }
+}
+
+/* Kill from here to the end of the line.  If DIRECTION is negative, kill
+   back to the line start instead. */
+rl_kill_line (direction)
+     int direction;
+{
+  int orig_point = rl_point;
+
+  if (direction < 0)
+    rl_backward_kill_line (1);
+  else
+    {
+      rl_end_of_line ();
+      if (orig_point != rl_point)
+       rl_kill_text (orig_point, rl_point);
+      rl_point = orig_point;
+    }
+}
+
+/* Kill backwards to the start of the line.  If DIRECTION is negative, kill
+   forwards to the line end instead. */
+rl_backward_kill_line (direction)
+     int direction;
+{
+  int orig_point = rl_point;
+
+  if (direction < 0)
+    rl_kill_line (1);
+  else
+    {
+      if (!rl_point)
+       ding ();
+      else
+       {
+         rl_beg_of_line ();
+         rl_kill_text (orig_point, rl_point);
+       }
+    }
+}
+
+/* Yank back the last killed text.  This ignores arguments. */
+rl_yank ()
+{
+  if (!rl_kill_ring) rl_abort ();
+  rl_insert_text (rl_kill_ring[rl_kill_index]);
+}
+
+/* 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 ()
+{
+  int l;
+
+  if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) ||
+      !rl_kill_ring)
+    {
+      rl_abort ();
+    }
+
+  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 ();
+    }
+  else
+    rl_abort ();
+
+}
+
+/* Yank the COUNTth argument from the previous history line. */
+rl_yank_nth_arg (count, ignore)
+     int count;
+{
+  register HIST_ENTRY *entry = previous_history ();
+  char *arg;
+
+  if (entry)
+    next_history ();
+  else
+    {
+      ding ();
+      return;
+    }
+
+  arg = history_arg_extract (count, count, entry->line);
+  if (!arg || !*arg)
+    {
+      ding ();
+      return;
+    }
+
+  rl_begin_undo_group ();
+  if (rl_point && the_line[rl_point - 1] != ' ')
+    rl_insert_text (" ");
+  rl_insert_text (arg);
+  free (arg);
+  rl_end_undo_group ();
+}
+
+/* Vi Mode. */
+#ifdef VI_MODE
+#include "vi_mode.c"
+#endif /* VI_MODE */
+
+/* How to toggle back and forth between editing modes. */
+rl_vi_editing_mode ()
+{
+#ifdef VI_MODE
+  rl_editing_mode = vi_mode;
+  rl_vi_insertion_mode ();
+#endif /* VI_MODE */
+}
+
+rl_emacs_editing_mode ()
+{
+  rl_editing_mode = emacs_mode;
+  keymap = emacs_standard_keymap;
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                          Completion                             */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Non-zero means that case is not significant in completion. */
+int completion_case_fold = 0;
+
+/* Return an array of (char *) which is a list of completions for TEXT.
+   If there are no completions, return a NULL pointer.
+   The first entry in the returned array is the substitution for TEXT.
+    The remaining entries are the possible completions.
+   The array is terminated with a NULL pointer.
+
+   ENTRY_FUNCTION is a function of two args, and returns a (char *).
+     The first argument is TEXT.
+     The second is a state argument; it should be zero on the first call, and
+     non-zero on subsequent calls.  It returns a NULL pointer to the caller
+     when there are no more matches.
+ */
+char **
+completion_matches (text, entry_function)
+     char *text;
+     char *(*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] = (char *)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 direct *entry = (struct direct *)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 = rindex (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 *tilde_expand (), *temp_dirname = tilde_expand (dirname);
+       free (dirname);
+       dirname = temp_dirname;
+
+       if (rl_symbolic_link_hook)
+         (*rl_symbolic_link_hook) (&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*\/te<TAB>.  If the directory name contains
+     globbing characters, then build an array of directories to glob on, and
+     glob on the first one. */
+
+  /* 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 upto the length of filename, then
+            it is a match. */
+           if ((entry->d_namlen >= filename_len) &&
+               (strncmp (filename, entry->d_name, filename_len) == 0))
+             {
+               break;
+             }
+       }
+    }
+
+  if (!entry)
+    {
+      if (directory)
+       {
+         closedir (directory);
+         directory = (DIR *)NULL;
+       }
+      return (char *)NULL;
+    }
+  else
+    {
+      char *temp;
+
+      if (dirname && (strcmp (dirname, ".") != 0))
+       {
+         temp = (char *)xmalloc (1 + strlen (users_dirname)
+                                 + entry->d_namlen);
+         strcpy (temp, users_dirname);
+         strcat (temp, entry->d_name);
+       }
+      else
+       {
+         temp = (savestring (entry->d_name));
+       }
+      return (temp);
+    }
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     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);
+}
+
+/* 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 (key > 127 && key < 256)
+    {
+      if (keymap[ESC].type == ISKMAP)
+       {
+         Keymap escmap = (Keymap)keymap[ESC].function;
+
+         key -= 128;
+         escmap[key].type = ISFUNC;
+         escmap[key].function = function;
+         return (0);
+       }
+      return (key);
+    }
+
+  keymap[key].type = ISFUNC;
+  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 = keymap;
+
+  keymap = map;
+  result = rl_bind_key (key, function);
+  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;
+{
+  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 = (char *)xmalloc (2 * (strlen (macro)));
+  int macro_keys_len;
+
+  if (rl_translate_keyseq (macro, macro_keys, &macro_keys_len))
+    {
+      free (macro_keys);
+      return;
+    }
+  rl_generic_bind (ISMACR, keyseq, macro_keys, map);
+}
+
+/* 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;
+    }
+
+  keys = (char *)alloca (1 + (2 * strlen (keyseq)));
+
+  /* Translate the ASCII representation of KEYSEQ into an array
+     of characters.  Stuff the characters into ARRAY, and the
+     length of ARRAY into LENGTH. */
+  if (rl_translate_keyseq (keyseq, keys, &keys_len))
+    return;
+
+  /* Bind keys, making new keymaps as necessary. */
+  for (i = 0; i < keys_len; i++)
+    {
+      if (i + 1 < keys_len)
+       {
+         if (map[keys[i]].type != ISKMAP)
+           {
+             if (map[i].type == ISMACR)
+               free ((char *)map[i].function);
+
+             map[keys[i]].type = ISKMAP;
+             map[keys[i]].function = (Function *)rl_make_bare_keymap ();
+           }
+         map = (Keymap)map[keys[i]].function;
+       }
+      else
+       {
+         if (map[keys[i]].type == ISMACR)
+           free ((char *)map[keys[i]].function);
+
+         map[keys[i]].function = (Function *)data;
+         map[keys[i]].type = type;
+       }
+    }
+}
+
+/* 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;
+                 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;
+
+  for (i = 0; funmap[i]; i++)
+    if (stricmp (funmap[i]->name, string) == 0)
+      return (funmap[i]->function);
+  return ((Function *)NULL);
+}
+
+/* The last key bindings file read. */
+static char *last_readline_init_file = "~/.inputrc";
+
+/* Re-read the current keybindings file. */
+rl_re_read_init_file (count, ignore)
+     int count, ignore;
+{
+  rl_read_init_file ((char *)NULL);
+}
+
+/* Do key bindings from a file.  If FILENAME is NULL it defaults
+   to `~/.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;
+
+  openname = tilde_expand (filename);
+
+  if ((stat (openname, &finfo) < 0) ||
+      (file = open (openname, O_RDONLY, 0666)) < 0)
+    {
+      free (openname);
+      return (errno);
+    }
+  else
+    free (openname);
+
+  last_readline_init_file = filename;
+
+  /* Read the file into BUFFER. */
+  buffer = (char *)xmalloc (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';
+
+      /* If the line is not a comment, then parse it. */
+      if (*line != '#')
+       rl_parse_and_bind (line);
+
+      /* Move to the next line. */
+      line += i + 1;
+    }
+  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 parsing_conditionalized_out, and set parser state based on ARGS. */
+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++] = parsing_conditionalized_out;
+
+  /* We only check to see if the first word in ARGS is the same as the
+     value stored in rl_readline_name. */
+
+  /* Isolate first argument. */
+  for (i = 0; args[i] && !whitespace (args[i]); i++);
+
+  if (args[i])
+    args[i++] = '\0';
+
+  /* Handle "if term=foo" construct.  If this isn't term=foo, 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 = rindex (tname, '-');
+      if (tem)
+       *tem = '\0';
+
+      if (stricmp (args + 5, tname) == 0)
+       parsing_conditionalized_out = 1;
+      else
+       parsing_conditionalized_out = 0;
+    }
+  else if (stricmp (args, rl_readline_name) == 0)
+    parsing_conditionalized_out = 0;
+  else
+    parsing_conditionalized_out = 1;
+}
+
+/* Invert the current parser state if there is anything on the stack. */
+parser_else (args)
+     char *args;
+{
+  if (if_stack_depth)
+    parsing_conditionalized_out = !parsing_conditionalized_out;
+  else
+    {
+      /* *** What, no error message? *** */
+    }
+}
+
+/* Terminate a conditional, popping the value of
+   parsing_conditionalized_out from the stack. */
+parser_endif (args)
+     char *args;
+{
+  if (if_stack_depth)
+    parsing_conditionalized_out = if_stack[--if_stack_depth];
+  else
+    {
+      /* *** What, no error message? *** */
+    }
+}
+
+/* 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);
+}
+
+/* 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;
+{
+  extern char *possible_control_prefixes[], *possible_meta_prefixes[];
+  char *funname, *kname;
+  static int substring_member_of_array ();
+  register int c;
+  int key, i;
+
+  if (!string || !*string || *string == '#')
+    return;
+
+  /* If this is a parser directive, act on it. */
+  if (*string == '$')
+    {
+      handle_parser_directive (&string[1]);
+      return;
+    }
+
+  /* If we are supposed to be skipping parsing right now, then do it. */
+  if (parsing_conditionalized_out)
+    return;
+
+  i = 0;
+  /* If this keyname is a complex key expression surrounded by quotes,
+     advance to after the matching close quote. */
+  if (*string == '"')
+    {
+      for (i = 1; c = string[i]; i++)
+       {
+         if (c == '"' && string[i - 1] != '\\')
+           break;
+       }
+    }
+
+  /* Advance to the colon (:) or whitespace which separates the two objects. */
+  for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
+
+  /* Mark the end of the command (or keyname). */
+  if (string[i])
+    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;
+    }
+
+  /* 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. */
+  if (*funname == '\'' || *funname == '"')
+    {
+      int delimiter = string[i++];
+
+      for (; c = string[i]; i++)
+       {
+         if (c == delimiter && string[i - 1] != '\\')
+           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';
+
+  /* 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 = (char *)alloca (1 + strlen (string));
+      register int j, k = 0;
+
+      for (j = 1; string[j]; j++)
+       {
+         if (string[j] == '"' && string[j - 1] != '\\')
+           break;
+
+         seq[k++] = string[j];
+       }
+      seq[k] = '\0';
+
+      /* Binding macro? */
+      if (*funname == '\'' || *funname == '"')
+       {
+         j = strlen (funname);
+
+         if (j && funname[j - 1] == *funname)
+           funname[j - 1] = '\0';
+
+         rl_macro_bind (seq, &funname[1], keymap);
+       }
+      else
+       rl_set_key (seq, rl_named_function (funname), keymap);
+
+      return;
+    }
+
+  /* Get the actual character we want to deal with. */
+  kname = rindex (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], keymap);
+    }
+  else
+    rl_bind_key (key, rl_named_function (funname));
+}
+
+rl_variable_bind (name, value)
+     char *name, *value;
+{
+  if (stricmp (name, "editing-mode") == 0)
+    {
+      if (strnicmp (value, "vi", 2) == 0)
+       {
+#ifdef VI_MODE
+         keymap = vi_insertion_keymap;
+         rl_editing_mode = vi_mode;
+#endif /* VI_MODE */
+       }
+      else if (strnicmp (value, "emacs", 5) == 0)
+       {
+         keymap = emacs_standard_keymap;
+         rl_editing_mode = emacs_mode;
+       }
+    }
+  else if (stricmp (name, "horizontal-scroll-mode") == 0)
+    {
+      if (!*value || stricmp (value, "On") == 0)
+       horizontal_scroll_mode = 1;
+      else
+       horizontal_scroll_mode = 0;
+    }
+  else if (stricmp (name, "mark-modified-lines") == 0)
+    {
+      if (!*value || stricmp (value, "On") == 0)
+       mark_modified_lines = 1;
+      else
+       mark_modified_lines = 0;
+    }
+  else if (stricmp (name, "prefer-visible-bell") == 0)
+    {
+      if (!*value || stricmp (value, "On") == 0)
+        prefer_visible_bell = 1;
+      else
+        prefer_visible_bell = 0;
+    }
+}
+
+/* Return the character which matches NAME.
+   For example, `Space' returns ' '. */
+
+typedef struct {
+  char *name;
+  int value;
+} assoc_list;
+
+assoc_list name_key_alist[] = {
+  { "Space", ' ' },
+  { "SPC", ' ' },
+  { "Rubout", 0x7f },
+  { "DEL", 0x7f },
+  { "Tab", 0x09 },
+  { "Newline", '\n' },
+  { "Return", '\r' },
+  { "RET", '\r' },
+  { "LFD", '\n' },
+  { "Escape", '\033' },
+  { "ESC", '\033' },
+
+  { (char *)0x0, 0 }
+};
+
+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 (*name);
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     String Utility Functions                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Return non-zero if any members of ARRAY are a substring in STRING. */
+static int
+substring_member_of_array (string, array)
+     char *string, **array;
+{
+  static char *strindex ();
+
+  while (*array)
+    {
+      if (strindex (string, *array))
+       return (1);
+      array++;
+    }
+  return (0);
+}
+
+/* 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);
+}
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     USG (System V) Support                      */
+/*                                                                 */
+/* **************************************************************** */
+
+/* When compiling and running in the `Posix' environment, Ultrix does
+   not restart system calls, so this needs to do it. */
+int
+rl_getc (stream)
+     FILE *stream;
+{
+  int result;
+  unsigned char c;
+
+  while (1)
+    {
+      result = read (fileno (stream), &c, sizeof (char));
+
+      if (result == sizeof (char))
+       return (c);
+
+      if (errno != EINTR)
+       return (EOF);
+    }
+}
+
+#ifdef STATIC_MALLOC
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     xmalloc and xrealloc ()                     */
+/*                                                                 */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     Testing Readline                            */
+/*                                                                 */
+/* **************************************************************** */
+
+#if defined (TEST)
+
+main ()
+{
+  HIST_ENTRY **history_list ();
+  char *temp = (char *)NULL;
+  char *prompt = "readline% ";
+  int done = 0;
+
+  while (!done)
+    {
+      temp = readline (prompt);
+
+      /* Test for EOF. */
+      if (!temp)
+       exit (1);
+
+      /* If there is anything on the line, print it and remember it. */
+      if (*temp)
+       {
+         fprintf (stderr, "%s\r\n", temp);
+         add_history (temp);
+       }
+
+      /* Check for `command' that we handle. */
+      if (strcmp (temp, "quit") == 0)
+       done = 1;
+
+      if (strcmp (temp, "list") == 0) {
+       HIST_ENTRY **list = history_list ();
+       register int i;
+       if (list) {
+         for (i = 0; list[i]; i++) {
+           fprintf (stderr, "%d: %s\r\n", i, list[i]->line);
+           free (list[i]->line);
+         }
+         free (list);
+       }
+      }
+      free (temp);
+    }
+}
+
+#endif /* TEST */
+
+\f
+/*
+ * Local variables:
+ * compile-command: "gcc -g -traditional -I. -I.. -DTEST -o readline readline.c keymaps.o funmap.o history.o -ltermcap"
+ * end:
+ */
diff --git a/gnu/lib/libreadline/readline/chardefs.h b/gnu/lib/libreadline/readline/chardefs.h
new file mode 100644 (file)
index 0000000..9749ae4
--- /dev/null
@@ -0,0 +1,50 @@
+/* chardefs.h -- Character definitions for readline. */
+#ifndef _CHARDEFS_
+
+#ifndef savestring
+#define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x))
+#endif
+
+#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 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 CTRL(c) ((c) & (~control_character_bit))
+#define META(c) ((c) | meta_character_bit)
+
+#define UNMETA(c) ((c) & (~meta_character_bit))
+#define UNCTRL(c) to_upper(((c)|control_character_bit))
+
+#define lowercase_p(c) (((c) > ('a' - 1) && (c) < ('z' + 1)))
+#define uppercase_p(c) (((c) > ('A' - 1) && (c) < ('Z' + 1)))
+
+#define pure_alphabetic(c) (lowercase_p(c) || uppercase_p(c))
+
+#ifndef to_upper
+#define to_upper(c) (lowercase_p(c) ? ((c) - 32) : (c))
+#define to_lower(c) (uppercase_p(c) ? ((c) + 32) : (c))
+#endif
+
+#define CTRL_P(c) ((c) < control_character_threshold)
+#define META_P(c) ((c) > meta_character_threshold)
+
+#define NEWLINE '\n'
+#define RETURN CTRL('M')
+#define RUBOUT 0x07f
+#define TAB '\t'
+#define ABORT_CHAR CTRL('G')
+#define PAGE CTRL('L')
+#define SPACE 0x020
+#define ESC CTRL('[')
+
+#endif  /* _CHARDEFS_ */
diff --git a/gnu/lib/libreadline/readline/keymaps.h b/gnu/lib/libreadline/readline/keymaps.h
new file mode 100644 (file)
index 0000000..a0b5aeb
--- /dev/null
@@ -0,0 +1,51 @@
+/* keymaps.h -- Manipulation of readline keymaps. */
+
+#ifndef _KEYMAPS_H_
+#define _KEYMAPS_H_
+
+#include <readline/chardefs.h>
+
+#ifndef __FUNCTION_DEF
+typedef int Function ();
+#define __FUNCTION_DEF
+#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;
+
+/* 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[128];
+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. */
+Keymap rl_make_bare_keymap ();
+
+/* Return a new keymap which is a copy of MAP. */
+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. */
+Keymap rl_make_keymap ();
+
+#endif /* _KEYMAPS_H_ */
diff --git a/gnu/lib/libreadline/readline/readline.h b/gnu/lib/libreadline/readline/readline.h
new file mode 100644 (file)
index 0000000..ad1e27a
--- /dev/null
@@ -0,0 +1,179 @@
+/* Readline.h -- the names of functions callable from within readline. */
+
+#ifndef _READLINE_H_
+#define _READLINE_H_
+
+#include <readline/keymaps.h>
+
+#ifndef __FUNCTION_DEF
+typedef int Function ();
+#define __FUNCTION_DEF
+#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_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_do_lowercase_version
+(), 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 ();
+
+/* These are *both* defined even when VI_MODE is not. */
+extern int rl_vi_editing_mode (), rl_emacs_editing_mode ();
+
+#ifdef VI_MODE
+/* Things for vi mode. */
+extern int 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_dosearch (), 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 ();
+#endif /* VI_MODE */
+
+/* Keyboard macro commands. */
+extern int
+rl_start_kbd_macro (), rl_end_kbd_macro (), 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 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 Function *rl_attempted_completion_function;
+
+/* 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 Function *rl_tilde_expander;
+
+/* 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_symbolic_link_hook;
+
+/* Non-zero means that modified history lines are preceded
+   with an asterisk. */
+extern int rl_show_star;
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Well Published Functions                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Read a line of input.  Prompt with PROMPT.  A NULL PROMPT means none. */
+extern char *readline ();
+
+/* Return an array of strings which are the result of repeatadly calling
+   FUNC with TEXT. */
+extern char **completion_matches ();
+
+/* 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 ();
+
+#endif /* _READLINE_H_ */
diff --git a/gnu/lib/libreadline/tcsh_hack.readme b/gnu/lib/libreadline/tcsh_hack.readme
new file mode 100644 (file)
index 0000000..2777512
--- /dev/null
@@ -0,0 +1,50 @@
+*** readline.c.orig    Thu May  5 04:02:17 1994
+--- readline.c Mon May  9 00:33:44 1994
+***************
+*** 32,37 ****
+--- 32,38 ----
+  
+  #include <stdio.h>
+  #include <sys/types.h>
++ #include <sys/ioctl.h>
+  #include <fcntl.h>
+  #include <sys/file.h>
+  #include <signal.h>
+***************
+*** 280,285 ****
+--- 281,295 ----
+  /* Non-zero means to save keys that we dispatch on in a kbd macro. */
+  static int defining_kbd_macro = 0;
+  
++ /* XXX this prevents to got editing mode from tcsh */
++ static void wait_foreground(void)
++ {
++      struct winsize w;
++      int tty = fileno (rl_instream);
++ 
++      if (ioctl (tty, TIOCGWINSZ, &w) == 0)
++              (void) ioctl (tty, TIOCSWINSZ, &w);
++ }
+  \f
+  /* **************************************************************** */
+  /*                                                               */
+***************
+*** 1153,1158 ****
+--- 1163,1169 ----
+  #endif /* POSIX */
+    int tty = fileno (rl_instream);
+  
++   wait_foreground ();   /* XXX this prevents to got editing mode from tcsh */
+  #if defined (_POSIX_VERSION)
+    if (tcgetattr (tty, &ttybuff) != -1)
+  #else
+***************
+*** 2307,2312 ****
+--- 2318,2324 ----
+  #  endif /* HAVE_BSD_SIGNALS */
+  #endif /* POSIX */
+  
++   wait_foreground ();   /* XXX this prevents to got editing mode from tcsh */
+  #if defined (_POSIX_VERSION)
+    tcgetattr (tty, &tio);
+  #else
diff --git a/gnu/lib/libreadline/vi_keymap.c b/gnu/lib/libreadline/vi_keymap.c
new file mode 100644 (file)
index 0000000..712889c
--- /dev/null
@@ -0,0 +1,474 @@
+/* vi_keymap.c -- the keymap for vi_mode in readline (). */
+
+/* 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. */
+
+#ifndef BUFSIZ
+#include <stdio.h>
+#endif /* BUFSIZ */
+
+#include "readline.h"
+
+extern KEYMAP_ENTRY_ARRAY vi_escape_keymap;
+
+/* 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_rubout },               /* 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 */
+
+  { ISKMAP, (Function *)vi_escape_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_forward },              /* SPACE */
+  { ISFUNC, (Function *)0x0 },         /* ! */
+  { ISFUNC, (Function *)0x0 },         /* " */
+  { ISFUNC, rl_vi_comment },           /* # */
+  { ISFUNC, rl_end_of_line },          /* $ */
+  { ISFUNC, rl_vi_match },             /* % */
+  { ISFUNC, (Function *)0x0 },         /* & */
+  { 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, (Function *)0x0 },         /* . */
+  { ISFUNC, rl_vi_search },            /* / */
+
+  /* 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, rl_vi_char_search },       /* ; */
+  { ISFUNC, (Function *)0x0 },         /* < */
+  { ISFUNC, (Function *)0x0 },         /* = */
+  { 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, (Function *)0x0 },         /* 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, (Function *)0x0 },         /* \ */
+  { 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, rl_backward }              /* RUBOUT */
+};
+
+
+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 */
+};
+
+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, (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, (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, (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_word }    /* RUBOUT */
+};
diff --git a/gnu/lib/libreadline/vi_mode.c b/gnu/lib/libreadline/vi_mode.c
new file mode 100644 (file)
index 0000000..f0d9e04
--- /dev/null
@@ -0,0 +1,987 @@
+/* vi_mode.c -- A vi emulation mode for Bash.
+
+   Derived from code written by Jeff Sparkes (jeff1@????).
+ */
+
+\f
+/* **************************************************************** */
+/*                                                                 */
+/*                     VI Emulation Mode                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Last string searched for from `/' or `?'. */
+static char *vi_last_search = (char *)NULL;
+static int vi_histpos;
+
+/* Non-zero means enter insertion mode. */
+int vi_doing_insert = 0;
+
+/* *** 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 vi_replace_count = 0;
+
+/* Yank the nth arg from the previous line into this line at point. */
+rl_vi_yank_arg (count)
+     int count;
+{
+  rl_yank_nth_arg (count, 0);
+}
+
+/* Search again for the last thing searched for. */
+rl_vi_search_again (ignore, key)
+     int ignore, key;
+{
+  switch (key)
+    {
+    case 'n':
+      rl_vi_dosearch (vi_last_search, -1);
+      break;
+
+    case 'N':
+      rl_vi_dosearch (vi_last_search, 1);
+      break;
+    }
+}
+
+/* Do a vi style search. */
+rl_vi_search (count, key)
+     int count, key;
+{
+  int dir, c, save_pos;
+  char *p;
+
+  switch (key)
+    {
+    case '?':
+      dir = 1;
+      break;
+
+    case '/':
+      dir = -1;
+      break;
+
+    default:
+      ding ();
+      return;
+    }
+
+  vi_histpos = where_history ();
+  maybe_save_line ();
+  save_pos = rl_point;
+
+  /* Reuse the line input buffer to read the search string. */
+  the_line[0] = 0;
+  rl_end = rl_point = 0;
+  p = (char *)alloca (2 + (rl_prompt ? strlen (rl_prompt) : 0));
+
+  sprintf (p, "%s%c", rl_prompt ? rl_prompt : "", key);
+
+  rl_message (p, 0, 0);
+
+  while (c = rl_read_key ())
+    {
+      switch (c)
+       {
+       case CTRL('H'):
+       case RUBOUT:
+         if (rl_point == 0)
+           {
+             maybe_unsave_line ();
+             rl_clear_message ();
+             rl_point = save_pos;
+             return;
+           }
+
+       case CTRL('W'):
+       case CTRL('U'):
+         rl_dispatch (c, keymap);
+         break;
+
+       case ESC:
+       case RETURN:
+       case NEWLINE:
+         goto dosearch;
+         break;
+
+       case CTRL('C'):
+         maybe_unsave_line ();
+         rl_clear_message ();
+         rl_point = 0;
+         ding ();
+         return;
+
+       default:
+         rl_insert (1, c);
+         break;
+       }
+      rl_redisplay ();
+    }
+ dosearch:
+  if (vi_last_search)
+    free (vi_last_search);
+
+  vi_last_search = savestring (the_line);
+  rl_vi_dosearch (the_line, dir);
+}
+
+rl_vi_dosearch (string, dir)
+     char *string;
+     int dir;
+{
+  int old, save = vi_histpos;
+  HIST_ENTRY *h;
+
+  if (string == 0 || *string == 0 || vi_histpos < 0)
+    {
+      ding ();
+      return;
+    }
+
+  if ((save = history_search_pos (string, dir, vi_histpos + dir)) == -1)
+    {
+      maybe_unsave_line ();
+      rl_clear_message ();
+      rl_point = 0;
+      ding ();
+      return;
+    }
+
+  vi_histpos = save;
+
+  old = where_history ();
+  history_set_pos (vi_histpos);
+  h = current_history ();
+  history_set_pos (old);
+
+  strcpy (the_line, h->line);
+  rl_undo_list = (UNDO_LIST *)h->data;
+  rl_end = strlen (the_line);
+  rl_point = 0;
+  rl_clear_message ();
+}
+
+/* Completion, from vi's point of view. */
+rl_vi_complete (ignore, key)
+     int ignore, key;
+{
+  if ((rl_point < rl_end) && (!whitespace (the_line[rl_point])))
+    {
+      if (!whitespace (the_line[rl_point + 1]))
+       rl_vi_end_word (1, 'E');
+      rl_point++;
+    }
+
+  if (key == '*')
+    rl_complete_internal ('*');
+  else
+    rl_complete (0, key);
+
+  rl_vi_insertion_mode ();
+}
+
+/* Previous word in vi mode. */
+rl_vi_prev_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    {
+      rl_vi_next_word (-count, key);
+      return;
+    }
+
+  if (uppercase_p (key))
+    rl_vi_bWord (count);
+  else
+    rl_vi_bword (count);
+}
+
+/* Next word in vi mode. */
+rl_vi_next_word (count, key)
+     int count;
+{
+  if (count < 0)
+    {
+      rl_vi_prev_word (-count, key);
+      return;
+    }
+
+  if (uppercase_p (key))
+    rl_vi_fWord (count);
+  else
+    rl_vi_fword (count);
+}
+
+/* Move to the end of the ?next? word. */
+rl_vi_end_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    {
+      ding ();
+      return;
+    }
+
+  if (uppercase_p (key))
+    rl_vi_eWord (count);
+  else
+    rl_vi_eword (count);
+}
+
+/* Move forward a word the way that 'W' does. */
+/* 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 (the_line[rl_point]) && rl_point < rl_end)
+        rl_point++;
+
+      /* Now skip whitespace. */
+      while (whitespace (the_line[rl_point]) && rl_point < rl_end)
+        rl_point++;
+    }
+}
+
+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 (the_line[rl_point]) &&
+          whitespace (the_line[rl_point - 1]))
+        rl_point--;
+
+      while (rl_point > 0 && whitespace (the_line[rl_point]))
+        rl_point--;
+
+      if (rl_point > 0)
+        {
+          while (--rl_point >= 0 && !whitespace (the_line[rl_point]));
+          rl_point++;
+        }
+    }
+}
+
+rl_vi_eWord (count)
+     int count;
+{
+  while (count-- && rl_point < (rl_end - 1))
+    {
+      /* Move to white space. */
+      while (++rl_point < rl_end && whitespace (the_line[rl_point]))
+        ;
+
+      if (rl_point && rl_point < rl_end)
+        {
+          /* Skip whitespace. */
+          while (rl_point < rl_end && whitespace (the_line[rl_point]))
+            rl_point++;
+
+          /* Skip until whitespace. */
+          while (rl_point < rl_end && !whitespace (the_line[rl_point]))
+            rl_point++;
+
+          /* Move back to the last character of the word. */
+          rl_point--;
+        }
+    }
+}
+
+rl_vi_fword (count)
+     int count;
+{
+  while (count-- && rl_point < (rl_end - 1))
+    {
+      /* Move to white space (really non-identifer). */
+      if (isident (the_line[rl_point]))
+        {
+          while (isident (the_line[rl_point]) && rl_point < rl_end)
+            rl_point++;
+        }
+      else /* if (!whitespace (the_line[rl_point])) */
+        {
+          while (!isident (the_line[rl_point]) &&
+                 !whitespace (the_line[rl_point]) && rl_point < rl_end)
+            rl_point++;
+        }
+
+      /* Move past whitespace. */
+      while (whitespace (the_line[rl_point]) && rl_point < rl_end)
+        rl_point++;
+    }
+}
+
+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 a non-identifier
+         so we will go back to the start of the previous word. */
+      if (isident (the_line[rl_point]) && !isident (the_line[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 (the_line[rl_point - 1]);
+      if ((isident (the_line[rl_point]) && !last_is_ident) ||
+          (!isident (the_line[rl_point]) && last_is_ident))
+        rl_point--;
+
+      while (rl_point > 0 && whitespace (the_line[rl_point]))
+        rl_point--;
+
+      if (rl_point > 0)
+        {
+          if (isident (the_line[rl_point]))
+            while (--rl_point >= 0 && isident (the_line[rl_point]));
+          else
+            while (--rl_point >= 0 && !isident (the_line[rl_point]) &&
+                   !whitespace (the_line[rl_point]));
+          rl_point++;
+        }
+    }
+}
+
+rl_vi_eword (count)
+     int count;
+{
+  while (count-- && rl_point < rl_end - 1)
+    {
+      while (++rl_point < rl_end && whitespace (the_line[rl_point]))
+        ;
+
+      if (rl_point < rl_end)
+        {
+          if (isident (the_line[rl_point]))
+            while (++rl_point < rl_end && isident (the_line[rl_point]));
+          else
+            while (++rl_point < rl_end && !isident (the_line[rl_point])
+                   && !whitespace (the_line[rl_point]));
+          rl_point--;
+        }
+    }
+}
+
+rl_vi_insert_beg ()
+{
+  rl_beg_of_line ();
+  rl_vi_insertion_mode ();
+  return 0;
+}
+
+rl_vi_append_mode ()
+{
+  if (rl_point < rl_end)
+    rl_point += 1;
+  rl_vi_insertion_mode ();
+  return 0;
+}
+
+rl_vi_append_eol ()
+{
+  rl_end_of_line ();
+  rl_vi_append_mode ();
+  return 0;
+}
+
+/* What to do in the case of C-d. */
+rl_vi_eof_maybe (count, c)
+     int count, c;
+{
+  rl_newline (1, '\n');
+}
+
+/* Insertion mode stuff. */
+
+/* Switching from one mode to the other really just involves
+   switching keymaps. */
+rl_vi_insertion_mode ()
+{
+  keymap = vi_insertion_keymap;
+}
+
+rl_vi_movement_mode ()
+{
+  if (rl_point > 0)
+    rl_backward (1);
+
+  keymap = vi_movement_keymap;
+  vi_done_inserting ();
+}
+
+vi_done_inserting ()
+{
+  if (vi_doing_insert)
+    {
+      rl_end_undo_group ();
+      vi_doing_insert = 0;
+    }
+}
+
+rl_vi_arg_digit (count, c)
+     int count, c;
+{
+  if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
+    rl_beg_of_line ();
+  else
+    rl_digit_argument (count, c);
+}
+
+/* Doesn't take an arg count in vi */
+rl_vi_change_case (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  char c = 0;
+
+  /* Don't try this on an empty line. */
+  if (rl_point >= rl_end - 1)
+    return;
+
+  if (uppercase_p (the_line[rl_point]))
+    c = to_lower (the_line[rl_point]);
+  else if (lowercase_p (the_line[rl_point]))
+    c = to_upper (the_line[rl_point]);
+
+  /* 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);
+}
+
+rl_vi_put (count, key)
+     int count, key;
+{
+  if (!uppercase_p (key) && (rl_point + 1 <= rl_end))
+    rl_forward (1);
+
+  rl_yank ();
+  rl_backward (1);
+}
+
+rl_vi_check ()
+{
+  if (rl_point && rl_point == rl_end)
+    rl_point--;
+}
+
+rl_vi_column (count)
+{
+  if (count > rl_end)
+    rl_end_of_line ();
+  else
+    rl_point = count - 1;
+}
+
+int
+rl_vi_domove (key, nextkey)
+     int key, *nextkey;
+{
+  int c, save;
+
+  rl_mark = rl_point;
+  c = rl_read_key ();
+  *nextkey = c;
+
+  if (!member (c, vi_motion))
+    {
+      if (digit (c))
+       {
+         save = rl_numeric_arg;
+         rl_digit_loop1 ();
+         rl_numeric_arg *= save;
+       }
+      else if ((key == 'd' && c == 'd') ||
+              (key == 'c' && c == 'c'))
+       {
+         rl_mark = rl_end;
+         rl_beg_of_line ();
+         return (0);
+       }
+      else
+       return (-1);
+    }
+
+  rl_dispatch (c, keymap);
+
+  /* No change in position means the command failed. */
+  if (rl_mark == rl_point)
+    return (-1);
+
+  if ((c == 'w' || c == 'W') && rl_point < rl_end)
+    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? */
+rl_digit_loop1 ()
+{
+  int key, c;
+
+  while (1)
+    {
+      rl_message ("(arg: %d) ", arg_sign * rl_numeric_arg, 0);
+      key = c = rl_read_key ();
+
+      if (keymap[c].type == ISFUNC &&
+         keymap[c].function == rl_universal_argument)
+       {
+         rl_numeric_arg *= 4;
+         continue;
+       }
+
+      c = UNMETA (c);
+      if (numeric (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
+       {
+         rl_clear_message ();
+         rl_stuff_char (key);
+         break;
+       }
+    }
+}
+
+rl_vi_delete_to (count, key)
+     int count, key;
+{
+  int c;
+
+  if (uppercase_p (key))
+    rl_stuff_char ('$');
+
+  if (rl_vi_domove (key, &c))
+    {
+      ding ();
+      return;
+    }
+
+  if ((c != '|') && (c != 'h') && rl_mark < rl_end)
+    rl_mark++;
+
+  rl_kill_text (rl_point, rl_mark);
+}
+
+rl_vi_change_to (count, key)
+     int count, key;
+{
+  int c;
+
+  if (uppercase_p (key))
+    rl_stuff_char ('$');
+
+  if (rl_vi_domove (key, &c))
+    {
+      ding ();
+      return;
+    }
+
+  if ((c != '|') && (c != 'h') && rl_mark < rl_end)
+    rl_mark++;
+
+  rl_begin_undo_group ();
+  vi_doing_insert = 1;
+  rl_kill_text (rl_point, rl_mark);
+  rl_vi_insertion_mode ();
+}
+
+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;
+    }
+
+  rl_begin_undo_group ();
+  rl_kill_text (rl_point, rl_mark);
+  rl_end_undo_group ();
+  rl_do_undo ();
+  rl_point = save;
+}
+
+rl_vi_delete (count)
+{
+  int end;
+
+  if (rl_end == 0)
+    {
+      ding ();
+      return;
+    }
+
+  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);
+}
+
+/* Turn the current line into a comment in shell history.
+   A K*rn shell style function. */
+rl_vi_comment ()
+{
+  rl_beg_of_line ();
+  rl_insert_text (": ");       /* `#' doesn't work in interactive mode */
+  rl_redisplay ();
+  rl_newline (1, '\010');
+}
+
+rl_vi_first_print ()
+{
+  rl_back_to_indent ();
+}
+
+rl_back_to_indent (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  rl_beg_of_line ();
+  while (rl_point < rl_end && whitespace (the_line[rl_point]))
+    rl_point++;
+}
+
+/* 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
+    {
+      target = rl_getc (in_stream);
+
+      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;
+
+  if (dir < 0)
+    {
+      pos--;
+      do
+       {
+         if (the_line[pos] == target)
+           {
+             if (dir == BTO)
+               rl_point = pos + 1;
+             else
+               rl_point = pos;
+             return;
+           }
+       }
+      while (pos--);
+
+      if (pos < 0)
+       {
+         ding ();
+         return;
+       }
+    }
+  else
+    {                  /* dir > 0 */
+      pos++;
+      do
+       {
+         if (the_line[pos] == target)
+           {
+             if (dir == FTO)
+               rl_point = pos - 1;
+             else
+               rl_point = pos;
+             return;
+           }
+       }
+      while (++pos < rl_end);
+
+      if (pos >= (rl_end - 1))
+       ding ();
+    }
+}
+
+/* Match brackets */
+rl_vi_match ()
+{
+  int count = 1, brack, pos;
+
+  pos = rl_point;
+  if ((brack = rl_vi_bracktype (the_line[rl_point])) == 0)
+    {
+      while ((brack = rl_vi_bracktype (the_line[rl_point])) == 0 &&
+            rl_point < rl_end - 1)
+       rl_forward (1);
+
+      if (brack <= 0)
+       {
+         rl_point = pos;
+         ding ();
+         return;
+       }
+    }
+
+  pos = rl_point;
+
+  if (brack < 0)
+    {
+      while (count)
+       {
+         if (--pos >= 0)
+           {
+             int b = rl_vi_bracktype (the_line[pos]);
+             if (b == -brack)
+               count--;
+             else if (b == brack)
+               count++;
+           }
+         else
+           {
+             ding ();
+             return;
+           }
+       }
+    }
+  else
+    {                  /* brack > 0 */
+      while (count)
+       {
+         if (++pos < rl_end)
+           {
+             int b = rl_vi_bracktype (the_line[pos]);
+             if (b == -brack)
+               count--;
+             else if (b == brack)
+               count++;
+           }
+         else
+           {
+             ding ();
+             return;
+           }
+       }
+    }
+  rl_point = pos;
+}
+
+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 ()
+{
+  int c;
+
+  c = rl_getc (in_stream);
+
+  switch (c)
+    {
+    case '\033':
+    case CTRL('C'):
+      return;
+
+    default:
+      rl_begin_undo_group ();
+      rl_delete (1, c);
+      rl_insert (1, c);
+      rl_end_undo_group ();
+      break;
+    }
+}
+
+rl_vi_subst (count, key)
+     int count, key;
+{
+  rl_begin_undo_group ();
+  vi_doing_insert = 1;
+
+  if (uppercase_p (key))
+    {
+      rl_beg_of_line ();
+      rl_kill_line (1);
+    }
+  else
+    rl_delete (count, key);
+
+  rl_vi_insertion_mode ();
+}
+
+rl_vi_overstrike (count, key)
+     int count, key;
+{
+  int i;
+
+  if (vi_doing_insert == 0)
+    {
+      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 ();
+    }
+}
+
+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 && vi_doing_insert)
+    {
+      rl_end_undo_group ();
+      rl_do_undo ();
+      vi_doing_insert = 0;
+    }
+}
+
+rl_vi_replace ()
+{
+  int i;
+
+  vi_replace_count = 0;
+
+  vi_replace_map = rl_make_bare_keymap ();
+
+  for (i = ' '; i < 127; 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;
+  keymap = vi_replace_map;
+}
+
+/*
+ * 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 (!index (" ;", the_line[rl_point]))
+    {
+      while (!index(" ;", the_line[++rl_point]))
+       ;
+    }
+  else if (the_line[rl_point-1] == ';')
+    {
+      ding ();
+      return (0);
+    }
+
+  rl_possible_completions ();
+  rl_point = save_pos;
+
+  return (0);
+}