changeset 1432:4c3d46b02f99

[project @ 1995-09-19 07:20:14 by jwe] Initial revision
author jwe
date Tue, 19 Sep 1995 07:21:00 +0000
parents d90d88618a9e
children b8a8821962af
files readline/COPYING readline/ChangeLog readline/README readline/STANDALONE readline/ansi_stdlib.h readline/bind.c readline/chardefs.h readline/complete.c readline/display.c readline/doc/hist.texinfo readline/doc/hstech.texinfo readline/doc/hsuser.texinfo readline/doc/rlman.texinfo readline/doc/rltech.texinfo readline/doc/rluser.texinfo readline/doc/texindex.c readline/emacs_keymap.c readline/examples/Inputrc readline/examples/fileman.c readline/examples/histexamp.c readline/examples/manexamp.c readline/funmap.c readline/history.c readline/history.h readline/isearch.c readline/keymaps.c readline/keymaps.h readline/memalloc.h readline/parens.c readline/posixstat.h readline/readline.c readline/readline.h readline/rlconf.h readline/rldefs.h readline/rltty.c readline/search.c readline/signals.c readline/tilde.c readline/tilde.h readline/vi_keymap.c readline/vi_mode.c readline/xmalloc.c
diffstat 42 files changed, 23347 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/COPYING	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,257 @@
+
+		    GNU GENERAL PUBLIC LICENSE
+		     Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+		    675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+The Free Software Foundation has exempted Bash from the requirement of
+Paragraph 2c of the General Public License.  This is to say, there is
+no requirement for Bash to print a notice when it is started
+interactively in the usual way.	 We made this exception because users
+and standards expect shells not to print such messages.	 This
+exception applies to any program that serves as a shell and that is
+based primarily on Bash as opposed to other GNU software.
+
+			    Preamble
+
+  The license agreements of most software companies try to keep users
+at the mercy of those companies.  By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.	The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.	Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must tell them their rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License.  The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications.  Each
+licensee is addressed as "you".
+
+  1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program.	 You may charge a fee for the physical act of
+transferring a copy.
+
+  2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+    a) cause the modified files to carry prominent notices stating that
+    you changed the files and the date of any change; and
+
+    b) cause the whole of any work that you distribute or publish, that
+    in whole or in part contains the Program or any part thereof, either
+    with or without modifications, to be licensed at no charge to all
+    third parties under the terms of this General Public License (except
+    that you may choose to grant warranty protection to some or all
+    third parties, at your option).
+
+    c) If the modified program normally reads commands interactively when
+    run, you must cause it, when started running for such interactive use
+    in the simplest and most usual way, to print or display an
+    announcement including an appropriate copyright notice and a notice
+    that there is no warranty (or else, saying that you provide a
+    warranty) and that users may redistribute the program under these
+    conditions, and telling the user how to view a copy of this General
+    Public License.
+
+    d) You may charge a fee for the physical act of transferring a
+    copy, and you may at your option offer warranty protection in
+    exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+  3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+    a) accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    b) accompany it with a written offer, valid for at least three
+    years, to give any third party free (except for a nominal charge
+    for the cost of distribution) a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    c) accompany it with the information you received as to where the
+    corresponding source code may be obtained.	(This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it.  For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+  4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License.	 However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+  5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions.  You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+  7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.	If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+  8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.	For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+  To do so, attach the following notices to the program.  It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy	<name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 1, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19xx name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License.  Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  program `Gnomovision' (a program to direct compilers to make passes
+  at assemblers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+That's all there is to it!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/ChangeLog	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,403 @@
+Tue Mar 23 14:36:51 1993  Brian Fox  (bfox@eos.crseo.ucsb.edu)
+
+	* readline.c (rl_copy): Changed name to rl_copy_text.
+
+Mon Mar 22 19:16:05 1993  Brian Fox  (bfox@eos.crseo.ucsb.edu)
+
+	* dispose_cmd.c, several other files. Declare dispose_xxx () as
+	"void".
+
+	* builtins/hashcom.h: Make declarations of hashed_filenames be
+	"extern" to keep the SGI compiler happy.
+
+	* readline.c (rl_initialize_everything): Assign values to
+	out_stream and in_stream immediately, since
+	output_character_function () can be called before
+	readline_internal () is called.
+
+Tue Dec  8 09:30:56 1992  Brian Fox  (bfox@cubit)
+
+	* readline.c (rl_init_terminal) Set PC from BC, not from *buffer.
+
+Mon Nov 30 09:35:47 1992  Brian Fox  (bfox@cubit)
+
+	* readline.c (invoking_keyseqs_in_map, rl_parse_and_bind) Allow
+	backslash to quote characters, such as backslash, double quote,
+	and space. Backslash quotes all character indiscriminately.
+
+	* funmap.c (vi_keymap) Fix type in "vi-replace" declaration.
+
+Fri Nov 20 10:55:05 1992  Brian Fox  (bfox@cubit)
+
+	* readline.c (init_terminal_io, rl_prep_terminal): FINALLY!
+	Declare and use termcap variable `ospeed' when setting up terminal
+	parameters.
+
+Thu Oct  8 08:53:07 1992  Brian J. Fox  (bfox@helios)
+
+	* Makefile, this directory: Include (as links to the canonical
+	sources), tilde.c, tilde.h, posixstat.h and xmalloc.c.
+
+Tue Sep 29 13:07:21 1992  Brian J. Fox  (bfox@helios)
+
+	* readline.c (init_terminal_io) Don't set arrow keys if the key
+	sequences that represent them are already set.
+
+	* readline.c (rl_function_of_keyseq) New function returns the first
+	function (or macro) found while searching a key sequence.
+
+Mon Sep 28 00:34:04 1992  Brian J. Fox  (bfox@helios)
+
+	* readline.c (LibraryVersion) New static char * contains current
+	version number.  Version is at 2.0.
+
+	* readline.c (rl_complete_internal): Incorporated clean changes
+	from gilmore (gnu@cygnus.com) to support quoted substrings within
+	completion functions.
+
+	* readline.c (many locations) Added support for the _GO32_,
+	whatever that is.  Patches supplied by Cygnus, typed in by hand,
+	with cleanups.
+
+Sun Aug 16 12:46:24 1992  Brian Fox  (bfox@cubit)
+
+	* readline.c (init_terminal_io): Find out the values of the keypad
+	arrows and bind them to appropriate RL functions if present.
+
+Mon Aug 10 18:13:24 1992  Brian Fox  (bfox@cubit)
+
+	* history.c (stifle_history): A negative argument to stifle
+	becomes zero.
+
+Tue Jul 28 09:28:41 1992  Brian Fox  (bfox@cubit)
+
+	* readline.c (rl_variable_bind): New local structure describes
+	booleans by name and address; code in rl_variable_bind () looks at
+	structure to set simple variables.
+
+	* parens.c (rl_insert_close): New variable rl_blink_matching_paren
+	is non-zero if we want to blink the matching open when a close is
+	inserted.  If FD_SET is defined, rl_blink_matching_paren defaults
+	to 1, else 0.  If FD_SET is not defined, and
+	rl_blink_matching_paren is non-zero, the close character(s) are/is
+	simply inserted.
+
+Wed Jul 22 20:03:59 1992  Brian Fox  (bfox@cubit)
+
+	* history.c, readline.c, vi_mode.c: Cause the functions strchr ()
+	and strrchr () to be used instead of index () and rindex ()
+	throughout the source.
+
+Mon Jul 13 11:34:07 1992  Brian Fox  (bfox@cubit)
+
+	* readline.c: (rl_variable_bind) New variable "meta-flag" if "on"
+	means force the use of the 8th bit as Meta bit.  Internal variable
+	is called meta_flag.
+
+Thu Jul  9 10:37:56 1992  Brian Fox  (bfox@cubit)
+
+	* history.c (get_history_event) Change INDEX to LOCAL_INDEX.  If
+	compiling for the shell, allow shell metacharacters to separate
+	history tokens as they would for shell tokens.
+
+Sat Jul  4 19:29:12 1992  Brian Fox  (bfox@cubit)
+
+	* vi_keymap.c: According to Posix, TAB self-inserts instead of
+	doing completion.
+
+	* vi_mode.c: (rl_vi_yank_arg) Enter VI insert mode after yanking
+	an arg from the previous line.
+
+	* search.c: New file takes over vi style searching and implements
+	non-incremental searching the history.
+
+	Makefile: Add search.c and search.o.
+
+	funmap.c: Add names for non-incremental-forward-search-history and
+	non-incremental-reverse-search-history.
+
+	readline.h: Add extern definitions for non-incremental searching.
+
+	vi_mode.c: Remove old search code; add calls to code in search.c.
+
+Fri Jul  3 10:36:33 1992  Brian Fox  (bfox@cubit)
+
+	* readline.c (rl_delete_horizontal_space); New function deletes
+	all whitespace surrounding point.
+
+	funmap.c: Add "delete-horizontal-space".
+	emacs_keymap.c: Put rl_delete_horizontal_space () on M-\.
+
+	* readline.c (rl_set_signals, rl_clear_signals); New function
+	rl_set_sighandler () is either defined in a Posix way (if
+	HAVE_POSIX_SIGNALS is defined) or in a BSD way.  Function is
+	called from rl_set_signals () and rl_clear_signals ().
+
+Fri May  8 12:50:15 1992  Brian Fox  (bfox@cubit)
+
+	* readline.c: (readline_default_bindings) Do comparisons with
+	_POSIX_VDISABLE casted to `unsigned char'.  Change tty characters
+	to be unsigned char.
+
+Thu Apr 30 12:36:35 1992  Brian Fox  (bfox@cubit)
+
+	* readline.c: (rl_getc) Handle "read would block" error on
+	non-blocking IO streams.
+
+	* readline.c: (rl_signal_handler): Unblock only the signal that we
+	have caught, not all signals.
+
+Sun Feb 23 03:33:09 1992  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c: Many functions.  Use only the macros META_CHAR and
+	UNMETA to deal with meta characters.  Prior to this, we used
+	numeric values and tests.
+
+	* readline.c (rl_complete_internal) Report exactly the number of
+	possible completions, not the number + 1.
+
+	* vi_mode.c (rl_do_move) Do not change the cursor position when
+	using `cw' or `cW'.
+
+	* vi_mode.c (rl_vi_complete) Enter insert mode after completing
+	with `*' or `\'.
+
+Fri Feb 21 05:58:18 1992  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c (rl_dispatch) Increment rl_key_sequence_length for
+	meta characters that map onto ESC map.
+
+Mon Feb 10 01:41:35 1992  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* history.c (history_do_write) Build a buffer of all of the lines
+	to write and write them in one fell swoop (lower overhead than
+	calling write () for each line).  Suggested by Peter Ho.
+
+	* readline.c: Include hbullx20 as well as hpux for determining
+	USGr3ness.
+
+	* readline.c (rl_unix_word_rubout) As per the "Now REMEMBER"
+	comment, pass arguments to rl_kill_text () in the correct order to
+	preserve prepending and appending of killed text.
+
+	* readline.c (rl_search_history) malloc (), realloc (), and free
+	() SEARCH_STRING so that there are no static limits on searching.
+
+	* vi_mode.c (rl_vi_subst) Don't forget to end the undo group.
+
+Fri Jan 31 14:51:02 1992  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c (rl_signal_handler): Zero the current history entry's
+	pointer after freeing the undo_list when SIGINT received.
+	Reformat a couple of functions.
+
+Sat Jan 25 13:47:35 1992  Brian Fox  (bfox at bears)
+
+        * readline.c (parser_if): free () TNAME after use.
+
+Tue Jan 21 01:01:35 1992  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c (rl_redisplay) and (rl_character_len): Display
+	Control characters as "^c" and Meta characters as "\234", instead
+	of "C-C" and "M-C".
+
+Sun Dec 29 10:59:00 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c (init_terminal_io) Default to environment variables
+	LINES and COLUMNS before termcap entry values.  If all else fails,
+	then assume 80x24 terminal.
+
+Sat Dec 28 16:33:11 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c: If this machine is USG and it is hpux, then define
+	USGr3.
+
+	* history.c: Cosmetic fixes.
+
+Thu Nov 21 00:10:12 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* vi_mode.c: (rl_do_move) Place cursor at end of line, never at
+	next to last character.
+
+Thu Nov 14 05:08:01 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* history.c (get_history_event) Non-anchored searches can have a
+	return index of greater than zero from get_history_event ().
+
+Fri Nov  1 07:02:13 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c (rl_translate_keyseq) Make C-? translate to RUBOUT
+	unconditionally.
+
+Mon Oct 28 11:34:52 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c; Use Posix directory routines and macros.
+
+	* funmap.c; Add entry for call-last-kbd-macro.
+
+	* readline.c (rl_prep_term); Use system EOF character on POSIX
+	systems also.
+
+Thu Oct  3 16:19:53 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c; Make a distinction between having a TERMIOS tty
+	driver, and having POSIX signal handling.  You might one without
+	the other.  New defines used HAVE_POSIX_SIGNALS, and
+	TERMIOS_TTY_DRIVER.
+
+Tue Jul 30 22:37:26 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c: rl_getc () If a call to read () returns without an
+	error, but with zero characters, the file is empty, so return EOF.
+
+Thu Jul 11 20:58:38 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c: (rl_get_next_history, rl_get_previous_history)
+	Reallocate the buffer space if the line being moved to is longer
+	the the current space allocated.  Amazing that no one has found
+	this bug until now.
+
+Sun Jul  7 02:37:05 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c:(rl_parse_and_bind) Allow leading whitespace.
+	  Make sure TERMIO and TERMIOS systems treat CR and NL
+	  disctinctly.
+	
+Tue Jun 25 04:09:27 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c: Rework parsing conditionals to pay attention to the
+	prior states of the conditional stack.  This makes $if statements
+	work correctly.
+
+Mon Jun 24 20:45:59 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c: support for displaying key binding information
+	includes the functions rl_list_funmap_names (),
+	invoking_keyseqs_in_map (), rl_invoking_keyseqs (),
+	rl_dump_functions (), and rl_function_dumper ().
+
+	funmap.c: support for same includes rl_funmap_names ().
+
+	readline.c, funmap.c: no longer define STATIC_MALLOC.  However,
+	update both version of xrealloc () to handle a null pointer.
+
+Thu Apr 25 12:03:49 1991  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* vi_mode.c (rl_vi_fword, fWord, etc.  All functions use
+	the macro `isident()'.  Fixed movement bug which prevents
+	continious movement through the text.
+
+Fri Jul 27 16:47:01 1990  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c (parser_if) Allow "$if term=foo" construct.
+
+Wed May 23 16:10:33 1990  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c (rl_dispatch) Correctly remember the last command
+	executed.  Fixed typo in username_completion_function ().
+
+Mon Apr  9 19:55:48 1990  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c: username_completion_function (); For text passed in
+	with a leading `~', remember that this could be a filename (after
+	it is completed).
+
+Thu Apr  5 13:44:24 1990  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c: rl_search_history (): Correctly handle case of an
+	unfound search string, but a graceful exit (as with ESC).
+
+	* readline.c: rl_restart_output ();  The Apollo passes the address
+	of the file descriptor to TIOCSTART, not the descriptor itself.
+
+Tue Mar 20 05:38:55 1990  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* readline.c: rl_complete (); second call in a row causes possible
+	completions to be listed.
+
+	* readline.c: rl_redisplay (), added prompt_this_line variable
+	which is the first character character following \n in prompt.
+
+Sun Mar 11 04:32:03 1990  Brian Fox  (bfox at gnuwest.fsf.org)
+
+	* Signals are now supposedly handled inside of SYSV compilation.
+
+Wed Jan 17 19:24:09 1990  Brian Fox  (bfox at sbphy.ucsb.edu)
+
+	* history.c: history_expand (); fixed overwriting memory error,
+	added needed argument to call to get_history_event ().
+
+Thu Jan 11 10:54:04 1990  Brian Fox  (bfox at sbphy.ucsb.edu)
+
+	* readline.c: added mark_modified_lines to control the
+	display of an asterisk on modified history lines.  Also
+	added a user variable called mark-modified-lines to the
+	`set' command.
+
+Thu Jan  4 10:38:05 1990  Brian Fox  (bfox at sbphy.ucsb.edu)
+
+	* readline.c: start_insert ().  Only use IC if we don't have an im
+	capability.
+
+Fri Sep  8 09:00:45 1989  Brian Fox  (bfox at aurel)
+
+	* readline.c: rl_prep_terminal ().  Only turn on 8th bit
+	  as meta-bit iff the terminal is not using parity.
+
+Sun Sep  3 08:57:40 1989  Brian Fox  (bfox at aurel)
+
+	* readline.c: start_insert ().  Uses multiple
+	  insertion call in cases where that makes sense.
+
+	  rl_insert ().  Read type-ahead buffer for additional
+	  keys that are bound to rl_insert, and insert them
+	  all at once.  Make insertion of single keys given
+	  with an argument much more efficient.
+
+Tue Aug  8 18:13:57 1989  Brian Fox  (bfox at aurel)
+
+	* readline.c: Changed handling of EOF.  readline () returns
+	 (char *)EOF or consed string.  The EOF character is read from the
+	 tty, or if the tty doesn't have one, defaults to C-d.
+
+	* readline.c: Added support for event driven programs.
+	  rl_event_hook is the address of a function you want called
+	  while Readline is waiting for input.
+
+	* readline.c: Cleanup time.  Functions without type declarations
+	  do not use return with a value.
+
+	* history.c: history_expand () has new variable which is the
+	  characters to ignore immediately following history_expansion_char.
+
+Sun Jul 16 08:14:00 1989  Brian Fox  (bfox at aurel)
+
+	* rl_prep_terminal ()
+	  BSD version turns off C-s, C-q, C-y, C-v.
+
+	* readline.c -- rl_prep_terminal ()
+	  SYSV version hacks readline_echoing_p.
+	  BSD version turns on passing of the 8th bit for the duration
+	  of reading the line.
+
+Tue Jul 11 06:25:01 1989  Brian Fox  (bfox at aurel)
+
+	* readline.c: new variable rl_tilde_expander.
+	  If non-null, this contains the address of a function to call if
+	  the standard meaning for expanding a tilde fails.  The function is
+	  called with the text sans tilde (as in "foo"), and returns a
+	  malloc()'ed string which is the expansion, or a NULL pointer if
+	  there is no expansion. 
+
+	* readline.h - new file chardefs.h
+	  Separates things that only readline.c needs from the standard
+	  header file publishing interesting things about readline.
+
+	* readline.c:
+	  readline_default_bindings () now looks at terminal chararacters
+	  and binds those as well.
+
+Wed Jun 28 20:20:51 1989  Brian Fox  (bfox at aurel)
+
+	* Made readline and history into independent libraries.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/README	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,6 @@
+This is the distribution of the Gnu Readline library.  See the file
+STANDALONE for a description of the #defines that can be passed via
+the makefile to build readline on different systems.
+
+The file rlconf.h contains defines that enable and disable certain
+readline features.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/STANDALONE	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,31 @@
+This is a description of C preprocessor defines that readline accepts.
+Most are passed in from the parent `make'; e.g. from the bash source
+directory.
+
+NO_SYS_FILE		<sys/file.h> is not present
+HAVE_UNISTD_H		<unistd.h> exists
+HAVE_STDLIB_H		<stdlib.h> exists
+HAVE_VARARGS_H		<varargs.h> exists and is usable
+HAVE_STRING_H		<string.h> exists
+HAVE_ALLOCA_H		<alloca.h> exists and is needed for alloca()
+HAVE_ALLOCA		alloca(3) or a define for it exists
+PRAGMA_ALLOCA		use of alloca() requires a #pragma, as in AIX 3.x
+VOID_SIGHANDLER		signal handlers are void functions
+HAVE_DIRENT_H		<dirent.h> exists and is usable
+HAVE_SYS_PTEM_H		<sys/ptem.h> exists 
+HAVE_SYS_PTE_H		<sys/pte.h> exists 
+HAVE_SYS_STREAM_H	<sys/stream.h> exists
+
+System-specific options:
+
+GWINSZ_IN_SYS_IOCTL	need to include <sys/ioctl.h> for TIOCGWINSZ
+HAVE_GETPW_DECLS	the getpw* functions are declared in <pwd.h> and cannot
+			be redeclared without compiler errors
+HAVE_STRCASECMP		the strcasecmp and strncasecmp functions are available
+
+USG			Running a variant of System V
+USGr3			Running System V.3
+XENIX_22		Xenix 2.2
+Linux			Linux
+CRAY			running a recent version of Cray UNICOS
+SunOS4			Running SunOS 4.x
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/ansi_stdlib.h	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,41 @@
+/* ansi_stdlib.h -- An ANSI Standard stdlib.h. */
+/* A minimal stdlib.h containing extern declarations for those functions
+   that bash uses. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_STDLIB_H_)
+#define	_STDLIB_H_ 1
+
+/* String conversion functions. */
+extern int atoi ();
+extern long int atol ();
+
+/* Memory allocation functions. */
+extern char *malloc ();
+extern char *realloc ();
+extern void free ();
+
+/* Other miscellaneous functions. */
+extern void abort ();
+extern void exit ();
+extern char *getenv ();
+extern void qsort ();
+
+#endif /* _STDLIB_H  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/bind.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,1487 @@
+/* bind.c -- key binding and startup file support for the readline library. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#if !defined (NO_SYS_FILE)
+#  include <sys/file.h>
+#endif /* !NO_SYS_FILE */
+#include <signal.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <errno.h>
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+extern int _rl_horizontal_scroll_mode;
+extern int _rl_mark_modified_lines;
+extern int _rl_bell_preference;
+extern int _rl_meta_flag;
+extern int _rl_convert_meta_chars_to_ascii;
+extern int _rl_output_meta_chars;
+extern int _rl_complete_show_all;
+#if defined (PAREN_MATCHING)
+extern int rl_blink_matching_paren;
+#endif /* PAREN_MATCHING */
+#if defined (VISIBLE_STATS)
+extern int rl_visible_stats;
+#endif /* VISIBLE_STATS */
+extern int rl_complete_with_tilde_expansion;
+extern int rl_completion_query_items;
+#if defined (VI_MODE)
+extern char *rl_vi_comment_begin;
+#endif
+
+extern int rl_explicit_arg;
+extern int rl_editing_mode;
+extern unsigned short _rl_parsing_conditionalized_out;
+extern Keymap _rl_keymap;
+
+extern char *possible_control_prefixes[], *possible_meta_prefixes[];
+
+extern char **rl_funmap_names ();
+
+/* Forward declarations */
+void rl_set_keymap_from_edit_mode ();
+
+static int glean_key_from_name ();
+
+#if defined (HAVE_STRCASECMP)
+#define stricmp strcasecmp
+#define strnicmp strncasecmp
+#else
+static int stricmp (), strnicmp ();
+#endif
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+/* **************************************************************** */
+/*								    */
+/*			Binding keys				    */
+/*								    */
+/* **************************************************************** */
+
+/* rl_add_defun (char *name, Function *function, int key)
+   Add NAME to the list of named functions.  Make FUNCTION be the function
+   that gets called.  If KEY is not -1, then bind it. */
+rl_add_defun (name, function, key)
+     char *name;
+     Function *function;
+     int key;
+{
+  if (key != -1)
+    rl_bind_key (key, function);
+  rl_add_funmap_entry (name, function);
+  return 0;
+}
+
+/* Bind KEY to FUNCTION.  Returns non-zero if KEY is out of range. */
+int
+rl_bind_key (key, function)
+     int key;
+     Function *function;
+{
+  if (key < 0)
+    return (key);
+
+  if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
+    {
+      if (_rl_keymap[ESC].type == ISKMAP)
+	{
+	  Keymap escmap;
+
+	  escmap = FUNCTION_TO_KEYMAP (_rl_keymap, ESC);
+	  key = UNMETA (key);
+	  escmap[key].type = ISFUNC;
+	  escmap[key].function = function;
+	  return (0);
+	}
+      return (key);
+    }
+
+  _rl_keymap[key].type = ISFUNC;
+  _rl_keymap[key].function = function;
+  return (0);
+}
+
+/* Bind KEY to FUNCTION in MAP.  Returns non-zero in case of invalid
+   KEY. */
+int
+rl_bind_key_in_map (key, function, map)
+     int key;
+     Function *function;
+     Keymap map;
+{
+  int result;
+  Keymap oldmap = _rl_keymap;
+
+  _rl_keymap = map;
+  result = rl_bind_key (key, function);
+  _rl_keymap = oldmap;
+  return (result);
+}
+
+/* Make KEY do nothing in the currently selected keymap.
+   Returns non-zero in case of error. */
+int
+rl_unbind_key (key)
+     int key;
+{
+  return (rl_bind_key (key, (Function *)NULL));
+}
+
+/* Make KEY do nothing in MAP.
+   Returns non-zero in case of error. */
+int
+rl_unbind_key_in_map (key, map)
+     int key;
+     Keymap map;
+{
+  return (rl_bind_key_in_map (key, (Function *)NULL, map));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+   FUNCTION.  This makes new keymaps as necessary.  The initial
+   place to do bindings is in MAP. */
+rl_set_key (keyseq, function, map)
+     char *keyseq;
+     Function *function;
+     Keymap map;
+{
+  return (rl_generic_bind (ISFUNC, keyseq, function, map));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+   the string of characters MACRO.  This makes new keymaps as
+   necessary.  The initial place to do bindings is in MAP. */
+rl_macro_bind (keyseq, macro, map)
+     char *keyseq, *macro;
+     Keymap map;
+{
+  char *macro_keys;
+  int macro_keys_len;
+
+  macro_keys = (char *)xmalloc ((2 * strlen (macro)) + 1);
+
+  if (rl_translate_keyseq (macro, macro_keys, &macro_keys_len))
+    {
+      free (macro_keys);
+      return -1;
+    }
+  rl_generic_bind (ISMACR, keyseq, macro_keys, map);
+  return 0;
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+   the arbitrary pointer DATA.  TYPE says what kind of data is
+   pointed to by DATA, right now this can be a function (ISFUNC),
+   a macro (ISMACR), or a keymap (ISKMAP).  This makes new keymaps
+   as necessary.  The initial place to do bindings is in MAP. */
+rl_generic_bind (type, keyseq, data, map)
+     int type;
+     char *keyseq, *data;
+     Keymap map;
+{
+  char *keys;
+  int keys_len;
+  register int i;
+
+  /* If no keys to bind to, exit right away. */
+  if (!keyseq || !*keyseq)
+    {
+      if (type == ISMACR)
+	free (data);
+      return -1;
+    }
+
+  keys = xmalloc (1 + (2 * strlen (keyseq)));
+
+  /* Translate the ASCII representation of KEYSEQ into an array of
+     characters.  Stuff the characters into KEYS, and the length of
+     KEYS into KEYS_LEN. */
+  if (rl_translate_keyseq (keyseq, keys, &keys_len))
+    {
+      free (keys);
+      return -1;
+    }
+
+  /* Bind keys, making new keymaps as necessary. */
+  for (i = 0; i < keys_len; i++)
+    {
+      int ic = (int) ((unsigned char)keys[i]);
+
+      if (_rl_convert_meta_chars_to_ascii && META_CHAR (ic))
+	{
+	  ic = UNMETA (ic);
+	  if (map[ESC].type == ISKMAP)
+	    map = FUNCTION_TO_KEYMAP (map, ESC);
+	}
+
+      if ((i + 1) < keys_len)
+	{
+	  if (map[ic].type != ISKMAP)
+	    {
+	      if (map[ic].type == ISMACR)
+		free ((char *)map[ic].function);
+
+	      map[ic].type = ISKMAP;
+	      map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap());
+	    }
+	  map = FUNCTION_TO_KEYMAP (map, ic);
+	}
+      else
+	{
+	  if (map[ic].type == ISMACR)
+	    free ((char *)map[ic].function);
+
+	  map[ic].function = KEYMAP_TO_FUNCTION (data);
+	  map[ic].type = type;
+	}
+    }
+  free (keys);
+  return 0;
+}
+
+/* Translate the ASCII representation of SEQ, stuffing the values into ARRAY,
+   an array of characters.  LEN gets the final length of ARRAY.  Return
+   non-zero if there was an error parsing SEQ. */
+rl_translate_keyseq (seq, array, len)
+     char *seq, *array;
+     int *len;
+{
+  register int i, c, l = 0;
+
+  for (i = 0; c = seq[i]; i++)
+    {
+      if (c == '\\')
+	{
+	  c = seq[++i];
+
+	  if (!c)
+	    break;
+
+	  if (((c == 'C' || c == 'M') &&  seq[i + 1] == '-') ||
+	      (c == 'e'))
+	    {
+	      /* Handle special case of backwards define. */
+	      if (strncmp (&seq[i], "C-\\M-", 5) == 0)
+		{
+		  array[l++] = ESC;
+		  i += 5;
+		  array[l++] = CTRL (to_upper (seq[i]));
+		  if (!seq[i])
+		    i--;
+		  continue;
+		}
+
+	      switch (c)
+		{
+		case 'M':
+		  i++;
+		  array[l++] = ESC;
+		  break;
+
+		case 'C':
+		  i += 2;
+		  /* Special hack for C-?... */
+		  if (seq[i] == '?')
+		    array[l++] = RUBOUT;
+		  else
+		    array[l++] = CTRL (to_upper (seq[i]));
+		  break;
+
+		case 'e':
+		  array[l++] = ESC;
+		}
+
+	      continue;
+	    }
+	}
+      array[l++] = c;
+    }
+
+  *len = l;
+  array[l] = '\0';
+  return (0);
+}
+
+/* Return a pointer to the function that STRING represents.
+   If STRING doesn't have a matching function, then a NULL pointer
+   is returned. */
+Function *
+rl_named_function (string)
+     char *string;
+{
+  register int i;
+
+  rl_initialize_funmap ();
+
+  for (i = 0; funmap[i]; i++)
+    if (stricmp (funmap[i]->name, string) == 0)
+      return (funmap[i]->function);
+  return ((Function *)NULL);
+}
+
+/* Return the function (or macro) definition which would be invoked via
+   KEYSEQ if executed in MAP.  If MAP is NULL, then the current keymap is
+   used.  TYPE, if non-NULL, is a pointer to an int which will receive the
+   type of the object pointed to.  One of ISFUNC (function), ISKMAP (keymap),
+   or ISMACR (macro). */
+Function *
+rl_function_of_keyseq (keyseq, map, type)
+     char *keyseq;
+     Keymap map;
+     int *type;
+{
+  register int i;
+
+  if (!map)
+    map = _rl_keymap;
+
+  for (i = 0; keyseq && keyseq[i]; i++)
+    {
+      int ic = keyseq[i];
+
+      if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
+	{
+	  if (map[ESC].type != ISKMAP)
+	    {
+	      if (type)
+		*type = map[ESC].type;
+
+	      return (map[ESC].function);
+	    }
+	  else
+	    {
+	      map = FUNCTION_TO_KEYMAP (map, ESC);
+	      ic = UNMETA (ic);
+	    }
+	}
+
+      if (map[ic].type == ISKMAP)
+	{
+	  /* If this is the last key in the key sequence, return the
+	     map. */
+	  if (!keyseq[i + 1])
+	    {
+	      if (type)
+		*type = ISKMAP;
+
+	      return (map[ic].function);
+	    }
+	  else
+	    map = FUNCTION_TO_KEYMAP (map, ic);
+	}
+      else
+	{
+	  if (type)
+	    *type = map[ic].type;
+
+	  return (map[ic].function);
+	}
+    }
+  return ((Function *) NULL);
+}
+
+/* The last key bindings file read. */
+static char *last_readline_init_file = (char *)NULL;
+
+/* Re-read the current keybindings file. */
+rl_re_read_init_file (count, ignore)
+     int count, ignore;
+{
+  int r;
+  r = rl_read_init_file ((char *)NULL);
+  rl_set_keymap_from_edit_mode ();
+  return r;
+}
+
+/* Do key bindings from a file.  If FILENAME is NULL it defaults
+   to the first non-null filename from this list:
+     1. the filename used for the previous call
+     2. the value of the shell variable `INPUTRC'
+     3. ~/.inputrc
+   If the file existed and could be opened and read, 0 is returned,
+   otherwise errno is returned. */
+int
+rl_read_init_file (filename)
+     char *filename;
+{
+  register int i;
+  char *buffer, *openname, *line, *end;
+  struct stat finfo;
+  int file;
+
+  /* Default the filename. */
+  if (!filename)
+    {
+      filename = last_readline_init_file;
+      if (!filename)
+        filename = getenv ("INPUTRC");
+      if (!filename)
+	filename = DEFAULT_INPUTRC;
+    }
+
+  if (!*filename)
+    filename = DEFAULT_INPUTRC;
+
+  openname = tilde_expand (filename);
+
+  if ((stat (openname, &finfo) < 0) ||
+      (file = open (openname, O_RDONLY, 0666)) < 0)
+    {
+      free (openname);
+      return (errno);
+    }
+  else
+    free (openname);
+
+  if (filename != last_readline_init_file)
+    {
+      if (last_readline_init_file)
+	free (last_readline_init_file);
+
+      last_readline_init_file = savestring (filename);
+    }
+
+  /* Read the file into BUFFER. */
+  buffer = (char *)xmalloc ((int)finfo.st_size + 1);
+  i = read (file, buffer, finfo.st_size);
+  close (file);
+
+  if (i != finfo.st_size)
+    return (errno);
+
+  /* Loop over the lines in the file.  Lines that start with `#' are
+     comments; all other lines are commands for readline initialization. */
+  line = buffer;
+  end = buffer + finfo.st_size;
+  while (line < end)
+    {
+      /* Find the end of this line. */
+      for (i = 0; line + i != end && line[i] != '\n'; i++);
+
+      /* Mark end of line. */
+      line[i] = '\0';
+
+      /* Skip leading whitespace. */
+      while (*line && whitespace (*line))
+        {
+	  line++;
+	  i--;
+        }
+
+      /* If the line is not a comment, then parse it. */
+      if (*line && *line != '#')
+	rl_parse_and_bind (line);
+
+      /* Move to the next line. */
+      line += i + 1;
+    }
+  free (buffer);
+  return (0);
+}
+
+/* **************************************************************** */
+/*								    */
+/*			Parser Directives       		    */
+/*								    */
+/* **************************************************************** */
+
+/* Conditionals. */
+
+/* Calling programs set this to have their argv[0]. */
+char *rl_readline_name = "other";
+
+/* Stack of previous values of parsing_conditionalized_out. */
+static unsigned char *if_stack = (unsigned char *)NULL;
+static int if_stack_depth = 0;
+static int if_stack_size = 0;
+
+/* Push _rl_parsing_conditionalized_out, and set parser state based
+   on ARGS. */
+static int
+parser_if (args)
+     char *args;
+{
+  register int i;
+
+  /* Push parser state. */
+  if (if_stack_depth + 1 >= if_stack_size)
+    {
+      if (!if_stack)
+	if_stack = (unsigned char *)xmalloc (if_stack_size = 20);
+      else
+	if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20);
+    }
+  if_stack[if_stack_depth++] = _rl_parsing_conditionalized_out;
+
+  /* If parsing is turned off, then nothing can turn it back on except
+     for finding the matching endif.  In that case, return right now. */
+  if (_rl_parsing_conditionalized_out)
+    return 0;
+
+  /* Isolate first argument. */
+  for (i = 0; args[i] && !whitespace (args[i]); i++);
+
+  if (args[i])
+    args[i++] = '\0';
+
+  /* Handle "if term=foo" and "if mode=emacs" constructs.  If this
+     isn't term=foo, or mode=emacs, then check to see if the first
+     word in ARGS is the same as the value stored in rl_readline_name. */
+  if (rl_terminal_name && strnicmp (args, "term=", 5) == 0)
+    {
+      char *tem, *tname;
+
+      /* Terminals like "aaa-60" are equivalent to "aaa". */
+      tname = savestring (rl_terminal_name);
+      tem = strchr (tname, '-');
+      if (tem)
+	*tem = '\0';
+
+      /* Test the `long' and `short' forms of the terminal name so that
+	 if someone has a `sun-cmd' and does not want to have bindings
+	 that will be executed if the terminal is a `sun', they can put
+	 `$if term=sun-cmd' into their .inputrc. */
+      if ((stricmp (args + 5, tname) == 0) ||
+	  (stricmp (args + 5, rl_terminal_name) == 0))
+	_rl_parsing_conditionalized_out = 0;
+      else
+	_rl_parsing_conditionalized_out = 1;
+
+      free (tname);
+    }
+#if defined (VI_MODE)
+  else if (strnicmp (args, "mode=", 5) == 0)
+    {
+      int mode;
+
+      if (stricmp (args + 5, "emacs") == 0)
+	mode = emacs_mode;
+      else if (stricmp (args + 5, "vi") == 0)
+	mode = vi_mode;
+      else
+	mode = no_mode;
+
+      if (mode == rl_editing_mode)
+	_rl_parsing_conditionalized_out = 0;
+      else
+	_rl_parsing_conditionalized_out = 1;
+    }
+#endif /* VI_MODE */
+  /* Check to see if the first word in ARGS is the same as the
+     value stored in rl_readline_name. */
+  else if (stricmp (args, rl_readline_name) == 0)
+    _rl_parsing_conditionalized_out = 0;
+  else
+    _rl_parsing_conditionalized_out = 1;
+  return 0;
+}
+
+/* Invert the current parser state if there is anything on the stack. */
+static int
+parser_else (args)
+     char *args;
+{
+  register int i;
+
+  if (!if_stack_depth)
+    {
+      /* Error message? */
+      return 0;
+    }
+
+  /* Check the previous (n - 1) levels of the stack to make sure that
+     we haven't previously turned off parsing. */
+  for (i = 0; i < if_stack_depth - 1; i++)
+    if (if_stack[i] == 1)
+      return 0;
+
+  /* Invert the state of parsing if at top level. */
+  _rl_parsing_conditionalized_out = !_rl_parsing_conditionalized_out;
+  return 0;
+}
+
+/* Terminate a conditional, popping the value of
+   _rl_parsing_conditionalized_out from the stack. */
+static int
+parser_endif (args)
+     char *args;
+{
+  if (if_stack_depth)
+    _rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
+  else
+    {
+      /* *** What, no error message? *** */
+    }
+  return 0;
+}
+
+/* Associate textual names with actual functions. */
+static struct {
+  char *name;
+  Function *function;
+} parser_directives [] = {
+  { "if", parser_if },
+  { "endif", parser_endif },
+  { "else", parser_else },
+  { (char *)0x0, (Function *)0x0 }
+};
+
+/* Handle a parser directive.  STATEMENT is the line of the directive
+   without any leading `$'. */
+static int
+handle_parser_directive (statement)
+     char *statement;
+{
+  register int i;
+  char *directive, *args;
+
+  /* Isolate the actual directive. */
+
+  /* Skip whitespace. */
+  for (i = 0; whitespace (statement[i]); i++);
+
+  directive = &statement[i];
+
+  for (; statement[i] && !whitespace (statement[i]); i++);
+
+  if (statement[i])
+    statement[i++] = '\0';
+
+  for (; statement[i] && whitespace (statement[i]); i++);
+
+  args = &statement[i];
+
+  /* Lookup the command, and act on it. */
+  for (i = 0; parser_directives[i].name; i++)
+    if (stricmp (directive, parser_directives[i].name) == 0)
+      {
+	(*parser_directives[i].function) (args);
+	return (0);
+      }
+
+  /* *** Should an error message be output? */
+  return (1);
+}
+
+static int substring_member_of_array ();
+
+/* Read the binding command from STRING and perform it.
+   A key binding command looks like: Keyname: function-name\0,
+   a variable binding command looks like: set variable value.
+   A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */
+rl_parse_and_bind (string)
+     char *string;
+{
+  char *funname, *kname;
+  register int c, i;
+  int key, equivalency;
+
+  while (string && whitespace (*string))
+    string++;
+
+  if (!string || !*string || *string == '#')
+    return 0;
+
+  /* If this is a parser directive, act on it. */
+  if (*string == '$')
+    {
+      handle_parser_directive (&string[1]);
+      return 0;
+    }
+
+  /* If we aren't supposed to be parsing right now, then we're done. */
+  if (_rl_parsing_conditionalized_out)
+    return 0;
+
+  i = 0;
+  /* If this keyname is a complex key expression surrounded by quotes,
+     advance to after the matching close quote.  This code allows the
+     backslash to quote characters in the key expression. */
+  if (*string == '"')
+    {
+      int passc = 0;
+
+      for (i = 1; c = string[i]; i++)
+	{
+	  if (passc)
+	    {
+	      passc = 0;
+	      continue;
+	    }
+
+	  if (c == '\\')
+	    {
+	      passc++;
+	      continue;
+	    }
+
+	  if (c == '"')
+	    break;
+	}
+    }
+
+  /* Advance to the colon (:) or whitespace which separates the two objects. */
+  for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
+
+  equivalency = (c == ':' && string[i + 1] == '=');
+
+  /* Mark the end of the command (or keyname). */
+  if (string[i])
+    string[i++] = '\0';
+
+  /* If doing assignment, skip the '=' sign as well. */
+  if (equivalency)
+    string[i++] = '\0';
+
+  /* If this is a command to set a variable, then do that. */
+  if (stricmp (string, "set") == 0)
+    {
+      char *var = string + i;
+      char *value;
+
+      /* Make VAR point to start of variable name. */
+      while (*var && whitespace (*var)) var++;
+
+      /* Make value point to start of value string. */
+      value = var;
+      while (*value && !whitespace (*value)) value++;
+      if (*value)
+	*value++ = '\0';
+      while (*value && whitespace (*value)) value++;
+
+      rl_variable_bind (var, value);
+      return 0;
+    }
+
+  /* Skip any whitespace between keyname and funname. */
+  for (; string[i] && whitespace (string[i]); i++);
+  funname = &string[i];
+
+  /* Now isolate funname.
+     For straight function names just look for whitespace, since
+     that will signify the end of the string.  But this could be a
+     macro definition.  In that case, the string is quoted, so skip
+     to the matching delimiter.  We allow the backslash to quote the
+     delimiter characters in the macro body. */
+  /* This code exists to allow whitespace in macro expansions, which
+     would otherwise be gobbled up by the next `for' loop.*/
+  /* XXX - it may be desirable to allow backslash quoting only if " is
+     the quoted string delimiter, like the shell. */
+  if (*funname == '\'' || *funname == '"')
+    {
+      int delimiter = string[i++];
+      int passc = 0;
+
+      for (; c = string[i]; i++)
+	{
+	  if (passc)
+	    {
+	      passc = 0;
+	      continue;
+	    }
+
+	  if (c == '\\')
+	    {
+	      passc = 1;
+	      continue;
+	    }
+
+	  if (c == delimiter)
+	    break;
+	}
+      if (c)
+	i++;
+    }
+
+  /* Advance to the end of the string.  */
+  for (; string[i] && !whitespace (string[i]); i++);
+
+  /* No extra whitespace at the end of the string. */
+  string[i] = '\0';
+
+  /* Handle equivalency bindings here.  Make the left-hand side be exactly
+     whatever the right-hand evaluates to, including keymaps. */
+  if (equivalency)
+    {
+      return 0;
+    }
+
+  /* If this is a new-style key-binding, then do the binding with
+     rl_set_key ().  Otherwise, let the older code deal with it. */
+  if (*string == '"')
+    {
+      char *seq = xmalloc (1 + strlen (string));
+      register int j, k = 0;
+      int passc = 0;
+
+      for (j = 1; string[j]; j++)
+	{
+	  /* Allow backslash to quote characters, but leave them in place.
+	     This allows a string to end with a backslash quoting another
+	     backslash, or with a backslash quoting a double quote.  The
+	     backslashes are left in place for rl_translate_keyseq (). */
+	  if (passc || (string[j] == '\\'))
+	    {
+	      seq[k++] = string[j];
+	      passc = !passc;
+	      continue;
+	    }
+
+	  if (string[j] == '"')
+	    break;
+
+	  seq[k++] = string[j];
+	}
+      seq[k] = '\0';
+
+      /* Binding macro? */
+      if (*funname == '\'' || *funname == '"')
+	{
+	  j = strlen (funname);
+
+	  /* Remove the delimiting quotes from each end of FUNNAME. */
+	  if (j && funname[j - 1] == *funname)
+	    funname[j - 1] = '\0';
+
+	  rl_macro_bind (seq, &funname[1], _rl_keymap);
+	}
+      else
+	rl_set_key (seq, rl_named_function (funname), _rl_keymap);
+
+      free (seq);
+      return 0;
+    }
+
+  /* Get the actual character we want to deal with. */
+  kname = strrchr (string, '-');
+  if (!kname)
+    kname = string;
+  else
+    kname++;
+
+  key = glean_key_from_name (kname);
+
+  /* Add in control and meta bits. */
+  if (substring_member_of_array (string, possible_control_prefixes))
+    key = CTRL (to_upper (key));
+
+  if (substring_member_of_array (string, possible_meta_prefixes))
+    key = META (key);
+
+  /* Temporary.  Handle old-style keyname with macro-binding. */
+  if (*funname == '\'' || *funname == '"')
+    {
+      char seq[2];
+      int fl = strlen (funname);
+
+      seq[0] = key; seq[1] = '\0';
+      if (fl && funname[fl - 1] == *funname)
+	funname[fl - 1] = '\0';
+
+      rl_macro_bind (seq, &funname[1], _rl_keymap);
+    }
+#if defined (PREFIX_META_HACK)
+  /* Ugly, but working hack to keep prefix-meta around. */
+  else if (stricmp (funname, "prefix-meta") == 0)
+    {
+      char seq[2];
+
+      seq[0] = key;
+      seq[1] = '\0';
+      rl_generic_bind (ISKMAP, seq, (char *)emacs_meta_keymap, _rl_keymap);
+    }
+#endif /* PREFIX_META_HACK */
+  else
+    rl_bind_key (key, rl_named_function (funname));
+  return 0;
+}
+
+/* Simple structure for boolean readline variables (i.e., those that can
+   have one of two values; either "On" or 1 for truth, or "Off" or 0 for
+   false. */
+
+static struct {
+  char *name;
+  int *value;
+} boolean_varlist [] = {
+  { "horizontal-scroll-mode",	&_rl_horizontal_scroll_mode },
+  { "mark-modified-lines",	&_rl_mark_modified_lines },
+  { "meta-flag",		&_rl_meta_flag },
+#if defined (PAREN_MATCHING)
+  { "blink-matching-paren",	&rl_blink_matching_paren },
+#endif
+  { "convert-meta",		&_rl_convert_meta_chars_to_ascii },
+  { "show-all-if-ambiguous",	&_rl_complete_show_all },
+  { "output-meta",		&_rl_output_meta_chars },
+#if defined (VISIBLE_STATS)
+  { "visible-stats",		&rl_visible_stats },
+#endif /* VISIBLE_STATS */
+  { "expand-tilde",		&rl_complete_with_tilde_expansion },
+  { (char *)NULL, (int *)NULL }
+};
+
+rl_variable_bind (name, value)
+     char *name, *value;
+{
+  register int i;
+
+  /* Check for simple variables first. */
+  for (i = 0; boolean_varlist[i].name; i++)
+    {
+      if (stricmp (name, boolean_varlist[i].name) == 0)
+	{
+	  /* A variable is TRUE if the "value" is "on", "1" or "". */
+	  if ((!*value) ||
+	      (stricmp (value, "On") == 0) ||
+	      (value[0] == '1' && value[1] == '\0'))
+	    *boolean_varlist[i].value = 1;
+	  else
+	    *boolean_varlist[i].value = 0;
+	  return 0;
+	}
+    }
+
+  /* Not a boolean variable, so check for specials. */
+
+  /* Editing mode change? */
+  if (stricmp (name, "editing-mode") == 0)
+    {
+      if (strnicmp (value, "vi", 2) == 0)
+	{
+#if defined (VI_MODE)
+	  _rl_keymap = vi_insertion_keymap;
+	  rl_editing_mode = vi_mode;
+#endif /* VI_MODE */
+	}
+      else if (strnicmp (value, "emacs", 5) == 0)
+	{
+	  _rl_keymap = emacs_standard_keymap;
+	  rl_editing_mode = emacs_mode;
+	}
+    }
+
+  /* Comment string change? */
+  else if (stricmp (name, "comment-begin") == 0)
+    {
+#if defined (VI_MODE)
+      if (*value)
+	{
+	  if (rl_vi_comment_begin)
+	    free (rl_vi_comment_begin);
+
+	  rl_vi_comment_begin = savestring (value);
+	}
+#endif /* VI_MODE */
+    }
+  else if (stricmp (name, "completion-query-items") == 0)
+    {
+      int nval = 100;
+      if (*value)
+	{
+	  nval = atoi (value);
+	  if (nval < 0)
+	    nval = 0;
+	}
+      rl_completion_query_items = nval;
+    }
+  else if (stricmp (name, "keymap") == 0)
+    {
+      Keymap kmap;
+      kmap = rl_get_keymap_by_name (value);
+      if (kmap)
+        rl_set_keymap (kmap);
+    }
+  else if (stricmp (name, "bell-style") == 0)
+    {
+      if (!*value)
+        _rl_bell_preference = AUDIBLE_BELL;
+      else
+        {
+          if (stricmp (value, "none") == 0 || stricmp (value, "off") == 0)
+            _rl_bell_preference = NO_BELL;
+          else if (stricmp (value, "audible") == 0 || stricmp (value, "on") == 0)
+            _rl_bell_preference = AUDIBLE_BELL;
+          else if (stricmp (value, "visible") == 0)
+            _rl_bell_preference = VISIBLE_BELL;
+        }
+    }
+  else if (stricmp (name, "prefer-visible-bell") == 0)
+    {
+      /* Backwards compatibility. */
+      if (*value && (stricmp (value, "on") == 0 ||
+		     (*value == '1' && !value[1])))
+        _rl_bell_preference = VISIBLE_BELL;
+      else
+        _rl_bell_preference = AUDIBLE_BELL;
+    }
+
+  return 0;
+}
+
+/* Return the character which matches NAME.
+   For example, `Space' returns ' '. */
+
+typedef struct {
+  char *name;
+  int value;
+} assoc_list;
+
+static assoc_list name_key_alist[] = {
+  { "DEL", 0x7f },
+  { "ESC", '\033' },
+  { "Escape", '\033' },
+  { "LFD", '\n' },
+  { "Newline", '\n' },
+  { "RET", '\r' },
+  { "Return", '\r' },
+  { "Rubout", 0x7f },
+  { "SPC", ' ' },
+  { "Space", ' ' },
+  { "Tab", 0x09 },
+  { (char *)0x0, 0 }
+};
+
+static int
+glean_key_from_name (name)
+     char *name;
+{
+  register int i;
+
+  for (i = 0; name_key_alist[i].name; i++)
+    if (stricmp (name, name_key_alist[i].name) == 0)
+      return (name_key_alist[i].value);
+
+  return (*(unsigned char *)name);	/* XXX was return (*name) */
+}
+
+/* Auxiliary functions to manage keymaps. */
+static struct {
+  char *name;
+  Keymap map;
+} keymap_names[] = {
+  { "emacs", emacs_standard_keymap },
+  { "emacs-standard", emacs_standard_keymap },
+  { "emacs-meta", emacs_meta_keymap },
+  { "emacs-ctlx", emacs_ctlx_keymap },
+#if defined (VI_MODE)
+  { "vi", vi_movement_keymap },
+  { "vi-move", vi_movement_keymap },
+  { "vi-command", vi_movement_keymap },
+  { "vi-insert", vi_insertion_keymap },
+#endif /* VI_MODE */
+  { (char *)0x0, (Keymap)0x0 }
+};
+
+Keymap
+rl_get_keymap_by_name (name)
+     char *name;
+{
+  register int i;
+
+  for (i = 0; keymap_names[i].name; i++)
+    if (strcmp (name, keymap_names[i].name) == 0)
+      return (keymap_names[i].map);
+  return ((Keymap) NULL);
+}
+
+void
+rl_set_keymap (map)
+     Keymap map;
+{
+  if (map)
+    _rl_keymap = map;
+}
+
+Keymap
+rl_get_keymap ()
+{
+  return (_rl_keymap);
+}
+
+void
+rl_set_keymap_from_edit_mode ()
+{
+  if (rl_editing_mode == emacs_mode)
+    _rl_keymap = emacs_standard_keymap;
+#if defined (VI_MODE)
+  else if (rl_editing_mode == vi_mode)
+    _rl_keymap = vi_insertion_keymap;
+#endif /* VI_MODE */
+}
+
+/* **************************************************************** */
+/*								    */
+/*		  Key Binding and Function Information		    */
+/*								    */
+/* **************************************************************** */
+
+/* Each of the following functions produces information about the
+   state of keybindings and functions known to Readline.  The info
+   is always printed to rl_outstream, and in such a way that it can
+   be read back in (i.e., passed to rl_parse_and_bind (). */
+
+/* Print the names of functions known to Readline. */
+void
+rl_list_funmap_names (count, ignore)
+     int count, ignore;
+{
+  register int i;
+  char **funmap_names;
+
+  funmap_names = rl_funmap_names ();
+
+  if (!funmap_names)
+    return;
+
+  for (i = 0; funmap_names[i]; i++)
+    fprintf (rl_outstream, "%s\n", funmap_names[i]);
+
+  free (funmap_names);
+}
+
+/* Return a NULL terminated array of strings which represent the key
+   sequences that are used to invoke FUNCTION in MAP. */
+char **
+rl_invoking_keyseqs_in_map (function, map)
+     Function *function;
+     Keymap map;
+{
+  register int key;
+  char **result;
+  int result_index, result_size;
+
+  result = (char **)NULL;
+  result_index = result_size = 0;
+
+  for (key = 0; key < 128; key++)
+    {
+      switch (map[key].type)
+	{
+	case ISMACR:
+	  /* Macros match, if, and only if, the pointers are identical.
+	     Thus, they are treated exactly like functions in here. */
+	case ISFUNC:
+	  /* If the function in the keymap is the one we are looking for,
+	     then add the current KEY to the list of invoking keys. */
+	  if (map[key].function == function)
+	    {
+	      char *keyname = (char *)xmalloc (5);
+
+	      if (CTRL_CHAR (key))
+		sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key)));
+	      else if (key == RUBOUT)
+		sprintf (keyname, "\\C-?");
+	      else if (key == '\\' || key == '"')
+		{
+		  keyname[0] = '\\';
+		  keyname[1] = (char) key;
+		  keyname[2] = '\0';
+		}
+	      else
+		{
+		  keyname[0] = (char) key;
+		  keyname[1] = '\0';
+		}
+
+	      if (result_index + 2 > result_size)
+		result = (char **) xrealloc
+		  (result, (result_size += 10) * sizeof (char *));
+
+	      result[result_index++] = keyname;
+	      result[result_index] = (char *)NULL;
+	    }
+	  break;
+
+	case ISKMAP:
+	  {
+	    char **seqs = (char **)NULL;
+
+	    /* Find the list of keyseqs in this map which have FUNCTION as
+	       their target.  Add the key sequences found to RESULT. */
+	    if (map[key].function)
+	      seqs =
+	        rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
+
+	    if (seqs)
+	      {
+		register int i;
+
+		for (i = 0; seqs[i]; i++)
+		  {
+		    char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
+
+		    if (key == ESC)
+		      sprintf (keyname, "\\e");
+		    else if (CTRL_CHAR (key))
+		      sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key)));
+		    else if (key == RUBOUT)
+		      sprintf (keyname, "\\C-?");
+		    else if (key == '\\' || key == '"')
+		      {
+			keyname[0] = '\\';
+			keyname[1] = (char) key;
+			keyname[2] = '\0';
+		      }
+		    else
+		      {
+			keyname[0] = (char) key;
+			keyname[1] = '\0';
+		      }
+
+		    strcat (keyname, seqs[i]);
+		    free (seqs[i]);
+
+		    if (result_index + 2 > result_size)
+		      result = (char **) xrealloc
+			(result, (result_size += 10) * sizeof (char *));
+
+		    result[result_index++] = keyname;
+		    result[result_index] = (char *)NULL;
+		  }
+
+		free (seqs);
+	      }
+	  }
+	  break;
+	}
+    }
+  return (result);
+}
+
+/* Return a NULL terminated array of strings which represent the key
+   sequences that can be used to invoke FUNCTION using the current keymap. */
+char **
+rl_invoking_keyseqs (function)
+     Function *function;
+{
+  return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
+}
+
+/* Print all of the current functions and their bindings to
+   rl_outstream.  If an explicit argument is given, then print
+   the output in such a way that it can be read back in. */
+int
+rl_dump_functions (count, key)
+     int count, key;
+{
+  rl_function_dumper (rl_explicit_arg);
+  rl_on_new_line ();
+  return (0);
+}
+
+/* Print all of the functions and their bindings to rl_outstream.  If
+   PRINT_READABLY is non-zero, then print the output in such a way
+   that it can be read back in. */
+void
+rl_function_dumper (print_readably)
+     int print_readably;
+{
+  register int i;
+  char **names;
+  char *name;
+
+  names = rl_funmap_names ();
+
+  fprintf (rl_outstream, "\n");
+
+  for (i = 0; name = names[i]; i++)
+    {
+      Function *function;
+      char **invokers;
+
+      function = rl_named_function (name);
+      invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap);
+
+      if (print_readably)
+	{
+	  if (!invokers)
+	    fprintf (rl_outstream, "# %s (not bound)\n", name);
+	  else
+	    {
+	      register int j;
+
+	      for (j = 0; invokers[j]; j++)
+		{
+		  fprintf (rl_outstream, "\"%s\": %s\n",
+			   invokers[j], name);
+		  free (invokers[j]);
+		}
+
+	      free (invokers);
+	    }
+	}
+      else
+	{
+	  if (!invokers)
+	    fprintf (rl_outstream, "%s is not bound to any keys\n",
+		     name);
+	  else
+	    {
+	      register int j;
+
+	      fprintf (rl_outstream, "%s can be found on ", name);
+
+	      for (j = 0; invokers[j] && j < 5; j++)
+		{
+		  fprintf (rl_outstream, "\"%s\"%s", invokers[j],
+			   invokers[j + 1] ? ", " : ".\n");
+		}
+
+	      if (j == 5 && invokers[j])
+		fprintf (rl_outstream, "...\n");
+
+	      for (j = 0; invokers[j]; j++)
+		free (invokers[j]);
+
+	      free (invokers);
+	    }
+	}
+    }
+}
+
+/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. */
+void
+_rl_bind_if_unbound (keyseq, default_func)
+     char *keyseq;
+     Function *default_func;
+{
+  Function *func;
+
+  if (keyseq)
+    {
+      func = rl_function_of_keyseq (keyseq, _rl_keymap, (int *)NULL);
+      if (!func || func == rl_do_lowercase_version)
+	rl_set_key (keyseq, default_func, _rl_keymap);
+    }
+}
+
+/* **************************************************************** */
+/*								    */
+/*			String Utility Functions		    */
+/*								    */
+/* **************************************************************** */
+
+static char *strindex ();
+
+/* Return non-zero if any members of ARRAY are a substring in STRING. */
+static int
+substring_member_of_array (string, array)
+     char *string, **array;
+{
+  while (*array)
+    {
+      if (strindex (string, *array))
+	return (1);
+      array++;
+    }
+  return (0);
+}
+
+#if !defined (HAVE_STRCASECMP)
+/* Whoops, Unix doesn't have strnicmp. */
+
+/* Compare at most COUNT characters from string1 to string2.  Case
+   doesn't matter. */
+static int
+strnicmp (string1, string2, count)
+     char *string1, *string2;
+     int count;
+{
+  register char ch1, ch2;
+
+  while (count)
+    {
+      ch1 = *string1++;
+      ch2 = *string2++;
+      if (to_upper(ch1) == to_upper(ch2))
+	count--;
+      else
+        break;
+    }
+  return (count);
+}
+
+/* strcmp (), but caseless. */
+static int
+stricmp (string1, string2)
+     char *string1, *string2;
+{
+  register char ch1, ch2;
+
+  while (*string1 && *string2)
+    {
+      ch1 = *string1++;
+      ch2 = *string2++;
+      if (to_upper(ch1) != to_upper(ch2))
+	return (1);
+    }
+  return (*string1 - *string2);
+}
+#endif /* !HAVE_STRCASECMP */
+
+/* Determine if s2 occurs in s1.  If so, return a pointer to the
+   match in s1.  The compare is case insensitive. */
+static char *
+strindex (s1, s2)
+     register char *s1, *s2;
+{
+  register int i, l = strlen (s2);
+  register int len = strlen (s1);
+
+  for (i = 0; (len - i) >= l; i++)
+    if (strnicmp (s1 + i, s2, l) == 0)
+      return (s1 + i);
+  return ((char *)NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/chardefs.h	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,122 @@
+/* chardefs.h -- Character definitions for readline. */
+
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _CHARDEFS_H
+#define _CHARDEFS_H
+
+#include <ctype.h>
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else
+#  include <strings.h>
+#endif /* HAVE_STRING_H */
+
+#ifndef whitespace
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#endif
+
+#ifdef CTRL
+#undef CTRL
+#endif
+
+/* Some character stuff. */
+#define control_character_threshold 0x020   /* Smaller than this is control. */
+#define control_character_mask 0x1f	    /* 0x20 - 1 */
+#define meta_character_threshold 0x07f	    /* Larger than this is Meta. */
+#define control_character_bit 0x40	    /* 0x000000, must be off. */
+#define meta_character_bit 0x080	    /* x0000000, must be on. */
+#define largest_char 255		    /* Largest character value. */
+
+#define CTRL_CHAR(c) ((c) < control_character_threshold)
+#define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char)
+
+#define CTRL(c) ((c) & control_character_mask)
+#define META(c) ((c) | meta_character_bit)
+
+#define UNMETA(c) ((c) & (~meta_character_bit))
+#define UNCTRL(c) to_upper(((c)|control_character_bit))
+
+/* Old versions
+#define lowercase_p(c) (((c) > ('a' - 1) && (c) < ('z' + 1)))
+#define uppercase_p(c) (((c) > ('A' - 1) && (c) < ('Z' + 1)))
+#define digit_p(c)  ((c) >= '0' && (c) <= '9')
+*/
+
+#define lowercase_p(c) (islower(c))
+#define uppercase_p(c) (isupper(c))
+#define digit_p(x)  (isdigit (x))
+
+#define pure_alphabetic(c) (lowercase_p(c) || uppercase_p(c))
+
+/* Old versions
+#  define to_upper(c) (lowercase_p(c) ? ((c) - 32) : (c))
+#  define to_lower(c) (uppercase_p(c) ? ((c) + 32) : (c))
+*/
+
+#ifndef to_upper
+#  define to_upper(c) (islower(c) ? toupper(c) : (c))
+#  define to_lower(c) (isupper(c) ? tolower(c) : (c))
+#endif
+
+#ifndef digit_value
+#define digit_value(x) ((x) - '0')
+#endif
+
+#ifndef NEWLINE
+#define NEWLINE '\n'
+#endif
+
+#ifndef RETURN
+#define RETURN CTRL('M')
+#endif
+
+#ifndef RUBOUT
+#define RUBOUT 0x7f
+#endif
+
+#ifndef TAB
+#define TAB '\t'
+#endif
+
+#ifdef ABORT_CHAR
+#undef ABORT_CHAR
+#endif
+#define ABORT_CHAR CTRL('G')
+
+#ifdef PAGE
+#undef PAGE
+#endif
+#define PAGE CTRL('L')
+
+#ifdef SPACE
+#undef SPACE
+#endif
+#define SPACE ' '	/* XXX - was 0x20 */
+
+#ifdef ESC
+#undef ESC
+#endif
+
+#define ESC CTRL('[')
+
+#endif  /* _CHARDEFS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/complete.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,1450 @@
+/* complete.c -- filename completion for readline. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#if !defined (NO_SYS_FILE)
+#  include <sys/file.h>
+#endif /* !NO_SYS_FILE */
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <errno.h>
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include <pwd.h>
+#if defined (USG) && !defined (HAVE_GETPW_DECLS)
+extern struct passwd *getpwent ();
+#endif /* USG && !HAVE_GETPW_DECLS */
+
+/* ISC systems don't define getpwent() if _POSIX_SOURCE is defined. */
+#if defined (isc386) && defined (_POSIX_SOURCE)
+#  if defined (__STDC__)
+extern struct passwd *getpwent (void);
+#  else
+extern struct passwd *getpwent ();
+#  endif /* !__STDC__ */
+#endif /* isc386 && _POSIX_SOURCE */
+
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+
+/* Possible values for do_replace in rl_complete_internal. */
+#define NO_MATCH	0
+#define SINGLE_MATCH	1
+#define MULT_MATCH	2
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+extern char *tilde_expand ();
+extern char *rl_copy_text ();
+
+extern Function *rl_last_func;
+extern int rl_editing_mode;
+extern int screenwidth;
+
+/* Forward declarations for functions defined and used in this file. */
+char *filename_completion_function ();
+char **completion_matches ();
+
+static int compare_strings ();
+static char *rl_strpbrk ();
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+/* If non-zero, then this is the address of a function to call when
+   completing on a directory name.  The function is called with
+   the address of a string (the current directory name) as an arg. */
+Function *rl_directory_completion_hook = (Function *)NULL;
+
+/* Non-zero means readline completion functions perform tilde expansion. */
+int rl_complete_with_tilde_expansion = 0;
+
+/* If non-zero, non-unique completions always show the list of matches. */
+int _rl_complete_show_all = 0;
+
+#if defined (VISIBLE_STATS)
+#  if !defined (X_OK)
+#    define X_OK 1
+#  endif
+
+static int stat_char ();
+
+/* Non-zero means add an additional character to each filename displayed
+   during listing completion iff rl_filename_completion_desired which helps
+   to indicate the type of file being listed. */
+int rl_visible_stats = 0;
+#endif /* VISIBLE_STATS */
+
+/* **************************************************************** */
+/*								    */
+/*	Completion matching, from readline's point of view.	    */
+/*								    */
+/* **************************************************************** */
+
+/* Pointer to the generator function for completion_matches ().
+   NULL means to use filename_entry_function (), the default filename
+   completer. */
+Function *rl_completion_entry_function = (Function *)NULL;
+
+/* Pointer to alternative function to create matches.
+   Function is called with TEXT, START, and END.
+   START and END are indices in RL_LINE_BUFFER saying what the boundaries
+   of TEXT are.
+   If this function exists and returns NULL then call the value of
+   rl_completion_entry_function to try to match, otherwise use the
+   array of strings returned. */
+CPPFunction *rl_attempted_completion_function = (CPPFunction *)NULL;
+
+/* Non-zero means to suppress normal filename completion after the
+   user-specified completion function has been called. */
+int rl_attempted_completion_over = 0;
+
+/* Local variable states what happened during the last completion attempt. */
+static int completion_changed_buffer = 0;
+
+/* Complete the word at or before point.  You have supplied the function
+   that does the initial simple matching selection algorithm (see
+   completion_matches ()).  The default is to do filename completion. */
+
+rl_complete (ignore, invoking_key)
+     int ignore, invoking_key;
+{
+  if (rl_last_func == rl_complete && !completion_changed_buffer)
+    return (rl_complete_internal ('?'));
+  else if (_rl_complete_show_all)
+    return (rl_complete_internal ('!'));
+  else
+    return (rl_complete_internal (TAB));
+}
+
+/* List the possible completions.  See description of rl_complete (). */
+rl_possible_completions (ignore, invoking_key)
+     int ignore, invoking_key;
+{
+  return (rl_complete_internal ('?'));
+}
+
+rl_insert_completions (ignore, invoking_key)
+     int ignore, invoking_key;
+{
+  return (rl_complete_internal ('*'));
+}
+
+/* The user must press "y" or "n". Non-zero return means "y" pressed. */
+get_y_or_n ()
+{
+  int c;
+
+  for (;;)
+    {
+      c = rl_read_key ();
+      if (c == 'y' || c == 'Y' || c == ' ')
+	return (1);
+      if (c == 'n' || c == 'N' || c == RUBOUT)
+	return (0);
+      if (c == ABORT_CHAR)
+	rl_abort ();
+      ding ();
+    }
+}
+
+/* Up to this many items will be displayed in response to a
+   possible-completions call.  After that, we ask the user if
+   she is sure she wants to see them all. */
+int rl_completion_query_items = 100;
+
+/* The basic list of characters that signal a break between words for the
+   completer routine.  The contents of this variable is what breaks words
+   in the shell, i.e. " \t\n\"\\'`@$><=" */
+char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(";
+
+/* The list of characters that signal a break between words for
+   rl_complete_internal.  The default list is the contents of
+   rl_basic_word_break_characters.  */
+char *rl_completer_word_break_characters = (char *)NULL;
+
+/* List of characters which can be used to quote a substring of the line.
+   Completion occurs on the entire substring, and within the substring
+   rl_completer_word_break_characters are treated as any other character,
+   unless they also appear within this list. */
+char *rl_completer_quote_characters = (char *)NULL;
+
+/* List of characters that are word break characters, but should be left
+   in TEXT when it is passed to the completion function.  The shell uses
+   this to help determine what kind of completing to do. */
+char *rl_special_prefixes = (char *)NULL;
+
+/* If non-zero, then disallow duplicates in the matches. */
+int rl_ignore_completion_duplicates = 1;
+
+/* Non-zero means that the results of the matches are to be treated
+   as filenames.  This is ALWAYS zero on entry, and can only be changed
+   within a completion entry finder function. */
+int rl_filename_completion_desired = 0;
+
+/* Non-zero means that the results of the matches are to be quoted using
+   double quotes (or an application-specific quoting mechanism) if the
+   filename contains any characters in rl_word_break_chars.  This is
+   ALWAYS non-zero on entry, and can only be changed within a completion
+   entry finder function. */
+int rl_filename_quoting_desired = 1;
+
+/* This function, if defined, is called by the completer when real
+   filename completion is done, after all the matching names have been
+   generated. It is passed a (char**) known as matches in the code below.
+   It consists of a NULL-terminated array of pointers to potential
+   matching strings.  The 1st element (matches[0]) is the maximal
+   substring that is common to all matches. This function can re-arrange
+   the list of matches as required, but all elements of the array must be
+   free()'d if they are deleted. The main intent of this function is
+   to implement FIGNORE a la SunOS csh. */
+Function *rl_ignore_some_completions_function = (Function *)NULL;
+
+#if defined (SHELL)
+/* A function to strip quotes that are not protected by backquotes.  It
+   allows single quotes to appear within double quotes, and vice versa.
+   It should be smarter.  It's fairly shell-specific, hence the SHELL
+   definition wrapper. */
+static char *
+_delete_quotes (text)
+     char *text;
+{
+  char *ret, *p, *r;
+  int l, quoted;
+
+  l = strlen (text);
+  ret = xmalloc (l + 1);
+  for (quoted = 0, p = text, r = ret; p && *p; p++)
+    {
+      /* Allow backslash-quoted characters to pass through unscathed. */
+      if (*p == '\\')
+        continue;
+      /* Close quote. */
+      if (quoted && *p == quoted)
+	{
+	  quoted = 0;
+	  continue;
+	}
+      /* Open quote. */
+      if (quoted == 0 && (*p == '\'' || *p == '"'))
+	{
+	  quoted = *p;
+	  continue;
+	}
+      *r++ = *p;
+    }
+  *r = '\0';
+  return ret;
+}
+#endif /* SHELL */
+
+/* Return the portion of PATHNAME that should be output when listing
+   possible completions.  If we are hacking filename completion, we
+   are only interested in the basename, the portion following the
+   final slash.  Otherwise, we return what we were passed. */
+static char *
+printable_part (pathname)
+      char *pathname;
+{
+  char *temp = (char *)NULL;
+
+  if (rl_filename_completion_desired)
+    temp = strrchr (pathname, '/');
+
+  if (!temp)
+    return (pathname);
+  else
+    return (++temp);
+}
+
+/* Output TO_PRINT to rl_outstream.  If VISIBLE_STATS is defined and we
+   are using it, check for and output a single character for `special'
+   filenames.  Return 1 if we printed an extension character, 0 if not. */
+#define PUTX(c) \
+      if (CTRL_CHAR (c)) \
+        { \
+          putc ('^', rl_outstream); \
+          putc (UNCTRL (c), rl_outstream); \
+        } \
+      else if (c == RUBOUT) \
+        { \
+          putc ('^', rl_outstream); \
+          putc ('?', rl_outstream); \
+        } \
+      else \
+        putc (c, rl_outstream)
+
+static int
+print_filename (to_print, full_pathname)
+     char *to_print, *full_pathname;
+{
+#if !defined (VISIBLE_STATS)
+  char *s;
+
+  for (s = to_print; *s; s++)
+    {
+      PUTX (*s);
+    }
+  return 0;
+#else  
+  char *s, c, *new_full_pathname;
+  int extension_char = 0, slen, tlen;
+
+  for (s = to_print; *s; s++)
+    {
+      PUTX (*s);
+    }  
+
+  if (rl_filename_completion_desired && rl_visible_stats)
+    {
+      /* If to_print != full_pathname, to_print is the basename of the
+	 path passed.  In this case, we try to expand the directory
+	 name before checking for the stat character. */
+      if (to_print != full_pathname)
+	{
+	  /* Terminate the directory name. */
+	  c = to_print[-1];
+	  to_print[-1] = '\0';
+
+	  s = tilde_expand (full_pathname);
+	  if (rl_directory_completion_hook)
+	    (*rl_directory_completion_hook) (&s);
+
+	  slen = strlen (s);
+	  tlen = strlen (to_print);
+	  new_full_pathname = xmalloc (slen + tlen + 2);
+	  strcpy (new_full_pathname, s);
+	  new_full_pathname[slen] = '/';
+	  strcpy (new_full_pathname + slen + 1, to_print);
+
+	  extension_char = stat_char (new_full_pathname);
+
+	  free (new_full_pathname);
+	  to_print[-1] = c;
+	}
+      else
+	{
+	  s = tilde_expand (full_pathname);
+	  extension_char = stat_char (s);
+	}
+
+      free (s);
+      if (extension_char)
+	putc (extension_char, rl_outstream);
+      return (extension_char != 0);
+    }
+  else
+    return 0;
+#endif /* VISIBLE_STATS */
+}
+
+/* Complete the word at or before point.
+   WHAT_TO_DO says what to do with the completion.
+   `?' means list the possible completions.
+   TAB means do standard completion.
+   `*' means insert all of the possible completions.
+   `!' means to do standard completion, and list all possible completions if
+   there is more than one. */
+rl_complete_internal (what_to_do)
+     int what_to_do;
+{
+  char **matches;
+  Function *our_func;
+  int start, scan, end, delimiter = 0, pass_next;
+  char *text, *saved_line_buffer;
+  char *replacement;
+  char quote_char = '\0';
+  int found_quote = 0;
+
+  if (rl_line_buffer)
+    saved_line_buffer = savestring (rl_line_buffer);
+  else
+    saved_line_buffer = (char *)NULL;
+
+  if (rl_completion_entry_function)
+    our_func = rl_completion_entry_function;
+  else
+    our_func = (Function *)filename_completion_function;
+
+  /* Only the completion entry function can change these. */
+  rl_filename_completion_desired = 0;
+  rl_filename_quoting_desired = 1;
+
+  /* We now look backwards for the start of a filename/variable word. */
+  end = rl_point;
+
+  if (rl_point)
+    {
+      if (rl_completer_quote_characters)
+	{
+	  /* We have a list of characters which can be used in pairs to
+	     quote substrings for the completer.  Try to find the start
+	     of an unclosed quoted substring. */
+	  /* FOUND_QUOTE is set so we know what kind of quotes we found. */
+	  for (scan = pass_next = 0; scan < end; scan++)
+	    {
+	      if (pass_next)
+		{
+		  pass_next = 0;
+		  continue;
+		}
+
+	      if (rl_line_buffer[scan] == '\\')
+		{
+		  pass_next = 1;
+		  found_quote |= 4;
+		  continue;
+		}
+
+	      if (quote_char != '\0')
+		{
+		  /* Ignore everything until the matching close quote char. */
+		  if (rl_line_buffer[scan] == quote_char)
+		    {
+		      /* Found matching close.  Abandon this substring. */
+		      quote_char = '\0';
+		      rl_point = end;
+		    }
+		}
+	      else if (strchr (rl_completer_quote_characters, rl_line_buffer[scan]))
+		{
+		  /* Found start of a quoted substring. */
+		  quote_char = rl_line_buffer[scan];
+		  rl_point = scan + 1;
+		  /* Shell-like quoting conventions. */
+		  if (quote_char == '\'')
+		    found_quote |= 1;
+		  else if (quote_char == '"')
+		    found_quote |= 2;
+		}
+	    }
+	}
+
+      if (rl_point == end && found_quote == 0)
+	{
+	  int quoted = 0;
+	  /* We didn't find an unclosed quoted substring upon which to do
+	     completion, so use the word break characters to find the
+	     substring on which to complete. */
+	  while (--rl_point)
+	    {
+	      scan = rl_line_buffer[rl_point];
+
+	      if (strchr (rl_completer_word_break_characters, scan) == 0)
+		continue;
+
+#if defined (SHELL)
+	      /* Don't let word break characters in quoted substrings break
+		 words for the completer. */
+	      if (found_quote && char_is_quoted (rl_line_buffer, rl_point))
+		continue;
+#endif /* SHELL */
+
+	      /* Convoluted code, but it avoids an n^2 algorithm with calls
+	      	 to char_is_quoted. */
+	      break;
+	    }
+	}
+
+      /* If we are at an unquoted word break, then advance past it. */
+      scan = rl_line_buffer[rl_point];
+#if defined (SHELL)
+      if ((found_quote == 0 || char_is_quoted (rl_line_buffer, rl_point) == 0) &&
+          strchr (rl_completer_word_break_characters, scan))
+#else
+      if (strchr (rl_completer_word_break_characters, scan))
+#endif
+	{
+	  /* If the character that caused the word break was a quoting
+	     character, then remember it as the delimiter. */
+	  if (strchr ("\"'", scan) && (end - rl_point) > 1)
+	    delimiter = scan;
+
+	  /* If the character isn't needed to determine something special
+	     about what kind of completion to perform, then advance past it. */
+	  if (!rl_special_prefixes || strchr (rl_special_prefixes, scan) == 0)
+	    rl_point++;
+	}
+    }
+
+  /* At this point, we know we have an open quote if quote_char != '\0'. */
+  start = rl_point;
+  rl_point = end;
+  text = rl_copy_text (start, end);
+
+  /* If the user wants to TRY to complete, but then wants to give
+     up and use the default completion function, they set the
+     variable rl_attempted_completion_function. */
+  if (rl_attempted_completion_function)
+    {
+      matches = (*rl_attempted_completion_function) (text, start, end);
+
+      if (matches || rl_attempted_completion_over)
+	{
+	  rl_attempted_completion_over = 0;
+	  our_func = (Function *)NULL;
+	  goto after_usual_completion;
+	}
+    }
+
+#if defined (SHELL)
+  /* Beware -- we're stripping the quotes here.  Do this only if we know
+     we are doing filename completion. */
+  if (found_quote && our_func == (Function *)filename_completion_function)
+    {
+      /* delete single and double quotes */
+      replacement = _delete_quotes (text);
+      free (text);
+      text = replacement;
+      replacement = (char *)0;
+    }
+#endif /* SHELL */
+
+  matches = completion_matches (text, our_func);
+
+ after_usual_completion:
+  free (text);
+
+  if (!matches)
+    ding ();
+  else
+    {
+      register int i;
+      int should_quote;
+
+      /* It seems to me that in all the cases we handle we would like
+	 to ignore duplicate possiblilities.  Scan for the text to
+	 insert being identical to the other completions. */
+      if (rl_ignore_completion_duplicates)
+	{
+	  char *lowest_common;
+	  int j, newlen = 0;
+	  char dead_slot;
+	  char **temp_array;
+
+	  /* Sort the items. */
+	  /* It is safe to sort this array, because the lowest common
+	     denominator found in matches[0] will remain in place. */
+	  for (i = 0; matches[i]; i++)
+	    ;
+	  /* Try sorting the array without matches[0], since we need it to
+	     stay in place no matter what. */
+	  if (i)
+	    qsort (matches+1, i-1, sizeof (char *), compare_strings);
+
+	  /* Remember the lowest common denominator for it may be unique. */
+	  lowest_common = savestring (matches[0]);
+
+	  for (i = 0; matches[i + 1]; i++)
+	    {
+	      if (strcmp (matches[i], matches[i + 1]) == 0)
+		{
+		  free (matches[i]);
+		  matches[i] = (char *)&dead_slot;
+		}
+	      else
+		newlen++;
+	    }
+
+	  /* We have marked all the dead slots with (char *)&dead_slot.
+	     Copy all the non-dead entries into a new array. */
+	  temp_array = (char **)xmalloc ((3 + newlen) * sizeof (char *));
+	  for (i = j = 1; matches[i]; i++)
+	    {
+	      if (matches[i] != (char *)&dead_slot)
+		temp_array[j++] = matches[i];
+	    }
+	  temp_array[j] = (char *)NULL;
+
+	  if (matches[0] != (char *)&dead_slot)
+	    free (matches[0]);
+	  free (matches);
+
+	  matches = temp_array;
+
+	  /* Place the lowest common denominator back in [0]. */
+	  matches[0] = lowest_common;
+
+	  /* If there is one string left, and it is identical to the
+	     lowest common denominator, then the LCD is the string to
+	     insert. */
+	  if (j == 2 && strcmp (matches[0], matches[1]) == 0)
+	    {
+	      free (matches[1]);
+	      matches[1] = (char *)NULL;
+	    }
+	}
+
+      switch (what_to_do)
+	{
+	case TAB:
+	case '!':
+	  /* If we are matching filenames, then here is our chance to
+	     do clever processing by re-examining the list.  Call the
+	     ignore function with the array as a parameter.  It can
+	     munge the array, deleting matches as it desires. */
+	  if (rl_ignore_some_completions_function &&
+	      our_func == (Function *)filename_completion_function)
+	    (void)(*rl_ignore_some_completions_function)(matches);
+
+	  /* If we are doing completion on quoted substrings, and any matches
+	     contain any of the completer_word_break_characters, then auto-
+	     matically prepend the substring with a quote character (just pick
+	     the first one from the list of such) if it does not already begin
+	     with a quote string.  FIXME: Need to remove any such automatically
+	     inserted quote character when it no longer is necessary, such as
+	     if we change the string we are completing on and the new set of
+	     matches don't require a quoted substring. */
+	  replacement = matches[0];
+
+	  should_quote = matches[0] && rl_completer_quote_characters &&
+			 rl_filename_completion_desired &&
+			 rl_filename_quoting_desired;
+
+	  if (should_quote)
+#if defined (SHELL)
+	    should_quote = should_quote && (!quote_char || quote_char == '"');
+#else
+	    should_quote = should_quote && !quote_char;
+#endif
+
+	  if (should_quote)
+	    {
+	      int do_replace;
+
+	      do_replace = NO_MATCH;
+
+	      /* If there is a single match, see if we need to quote it.
+		 This also checks whether the common prefix of several
+		 matches needs to be quoted.  If the common prefix should
+		 not be checked, add !matches[1] to the if clause. */
+	      should_quote = rl_strpbrk (matches[0], rl_completer_word_break_characters) != 0;
+#if defined (SHELL)
+	      should_quote = should_quote || rl_strpbrk (matches[0], "#$`?*[!") != 0;
+#endif
+
+	      if (should_quote)
+		do_replace = matches[1] ? MULT_MATCH : SINGLE_MATCH;
+
+	      if (do_replace != NO_MATCH)
+		{
+#if defined (SHELL)
+		  /* Quote the replacement, since we found an
+		     embedded word break character in a potential
+		     match. */
+		  char *rtext, *mtext;
+		  int rlen;
+		  extern char *double_quote ();	/* in builtins/common.c */
+
+		  /* If DO_REPLACE == MULT_MATCH, it means that there is
+		     more than one match.  In this case, we do not add
+		     the closing quote or attempt to perform tilde
+		     expansion.  If DO_REPLACE == SINGLE_MATCH, we try
+		     to perform tilde expansion, because double quotes
+		     inhibit tilde expansion by the shell. */
+
+		  mtext = matches[0];
+		  if (mtext[0] == '~' && do_replace == SINGLE_MATCH)
+		    mtext = tilde_expand (matches[0]);
+		  rtext = double_quote (mtext);
+		  if (mtext != matches[0])
+		    free (mtext);
+
+		  rlen = strlen (rtext);
+		  replacement = xmalloc (rlen + 1);
+		  /* If we're completing on a quoted string where the user
+		     has already supplied the opening quote, we don't want
+		     the quote in the replacement text, and we reset
+		     QUOTE_CHAR to 0 to avoid an extra closing quote. */
+		  if (quote_char == '"')
+		    {
+		      strcpy (replacement, rtext + 1);
+		      rlen--;
+		      quote_char = 0;
+		    }
+		  else
+		    strcpy (replacement, rtext);
+		  if (do_replace == MULT_MATCH)
+		    replacement[rlen - 1] = '\0';
+		  free (rtext);
+#else /* !SHELL */
+		  /* Found an embedded word break character in a potential
+		     match, so we need to prepend a quote character if we
+		     are replacing the completion string. */
+		  replacement = xmalloc (strlen (matches[0]) + 2);
+		  quote_char = *rl_completer_quote_characters;
+		  *replacement = quote_char;
+		  strcpy (replacement + 1, matches[0]);
+#endif /* SHELL */
+		}
+	    }
+
+	  if (replacement)
+	    {
+	      rl_begin_undo_group ();
+	      rl_delete_text (start, rl_point);
+	      rl_point = start;
+	      rl_insert_text (replacement);
+	      rl_end_undo_group ();
+	      if (replacement != matches[0])
+		free (replacement);
+	    }
+
+	  /* If there are more matches, ring the bell to indicate.
+	     If this was the only match, and we are hacking files,
+	     check the file to see if it was a directory.  If so,
+	     add a '/' to the name.  If not, and we are at the end
+	     of the line, then add a space. */
+	  if (matches[1])
+	    {
+	      if (what_to_do == '!')
+		goto display_matches;		/* XXX */
+	      else if (rl_editing_mode != vi_mode)
+		ding ();	/* There are other matches remaining. */
+	    }
+	  else
+	    {
+	      char temp_string[4];
+	      int temp_string_index = 0;
+
+	      if (quote_char)
+		temp_string[temp_string_index++] = quote_char;
+
+	      temp_string[temp_string_index++] = delimiter ? delimiter : ' ';
+	      temp_string[temp_string_index++] = '\0';
+
+	      if (rl_filename_completion_desired)
+		{
+		  struct stat finfo;
+		  char *filename = tilde_expand (matches[0]);
+
+		  if ((stat (filename, &finfo) == 0) && S_ISDIR (finfo.st_mode))
+		    {
+		      if (rl_line_buffer[rl_point] != '/')
+			rl_insert_text ("/");
+		    }
+		  else
+		    {
+		      if (rl_point == rl_end)
+			rl_insert_text (temp_string);
+		    }
+		  free (filename);
+		}
+	      else
+		{
+		  if (rl_point == rl_end)
+		    rl_insert_text (temp_string);
+		}
+	    }
+	  break;
+
+	case '*':
+	  {
+	    int i = 1;
+
+	    rl_begin_undo_group ();
+	    rl_delete_text (start, rl_point);
+	    rl_point = start;
+	    if (matches[1])
+	      {
+		while (matches[i])
+		  {
+		    rl_insert_text (matches[i++]);
+		    rl_insert_text (" ");
+		  }
+	      }
+	    else
+	      {
+		rl_insert_text (matches[0]);
+		rl_insert_text (" ");
+	      }
+	    rl_end_undo_group ();
+	  }
+	  break;
+
+	case '?':
+	  {
+	    int len, count, limit, max;
+	    int j, k, l;
+
+	    /* Handle simple case first.  What if there is only one answer? */
+	    if (!matches[1])
+	      {
+		char *temp;
+
+		temp = printable_part (matches[0]);
+		crlf ();
+		print_filename (temp, matches[0]);
+		crlf ();
+		goto restart;
+	      }
+
+	    /* There is more than one answer.  Find out how many there are,
+	       and find out what the maximum printed length of a single entry
+	       is. */
+	  display_matches:
+	    for (max = 0, i = 1; matches[i]; i++)
+	      {
+		char *temp;
+		int name_length;
+
+		temp = printable_part (matches[i]);
+		name_length = strlen (temp);
+
+		if (name_length > max)
+		  max = name_length;
+	      }
+
+	    len = i - 1;
+
+	    /* If there are many items, then ask the user if she
+	       really wants to see them all. */
+	    if (len >= rl_completion_query_items)
+	      {
+		crlf ();
+		fprintf (rl_outstream,
+			 "There are %d possibilities.  Do you really", len);
+		crlf ();
+		fprintf (rl_outstream, "wish to see them all? (y or n)");
+		fflush (rl_outstream);
+		if (!get_y_or_n ())
+		  {
+		    crlf ();
+		    goto restart;
+		  }
+	      }
+
+	    /* How many items of MAX length can we fit in the screen window? */
+	    max += 2;
+	    limit = screenwidth / max;
+	    if (limit != 1 && (limit * max == screenwidth))
+	      limit--;
+
+	    /* Avoid a possible floating exception.  If max > screenwidth,
+	       limit will be 0 and a divide-by-zero fault will result. */
+	    if (limit == 0)
+	      limit = 1;
+
+	    /* How many iterations of the printing loop? */
+	    count = (len + (limit - 1)) / limit;
+
+	    /* Watch out for special case.  If LEN is less than LIMIT, then
+	       just do the inner printing loop.
+	       0 < len <= limit  implies  count = 1. */
+
+	    /* Sort the items if they are not already sorted. */
+	    if (!rl_ignore_completion_duplicates)
+	      qsort (matches + 1, len - 1, sizeof (char *), compare_strings);
+
+	    /* Print the sorted items, up-and-down alphabetically, like
+	       ls might. */
+	    crlf ();
+
+	    for (i = 1; i <= count; i++)
+	      {
+		for (j = 0, l = i; j < limit; j++)
+		  {
+		    if (l > len || !matches[l])
+		      break;
+		    else
+		      {
+			char *temp;
+			int printed_length;
+
+			temp = printable_part (matches[l]);
+			printed_length = strlen (temp);
+			printed_length += print_filename (temp, matches[l]);
+
+			if (j + 1 < limit)
+			  {
+			    for (k = 0; k < max - printed_length; k++)
+			      putc (' ', rl_outstream);
+			  }
+		      }
+		    l += count;
+		  }
+		crlf ();
+	      }
+	  restart:
+
+	    rl_on_new_line ();
+	  }
+	  break;
+
+	default:
+	  fprintf (stderr, "\r\nreadline: bad value for what_to_do in rl_complete\n");
+	  abort ();
+	}
+
+      for (i = 0; matches[i]; i++)
+	free (matches[i]);
+      free (matches);
+    }
+
+  /* Check to see if the line has changed through all of this manipulation. */
+  if (saved_line_buffer)
+    {
+      if (strcmp (rl_line_buffer, saved_line_buffer) != 0)
+	completion_changed_buffer = 1;
+      else
+	completion_changed_buffer = 0;
+
+      free (saved_line_buffer);
+    }
+  return 0;
+}
+
+#if defined (VISIBLE_STATS)
+/* Return the character which best describes FILENAME.
+     `@' for symbolic links
+     `/' for directories
+     `*' for executables
+     `=' for sockets */
+static int
+stat_char (filename)
+     char *filename;
+{
+  struct stat finfo;
+  int character, r;
+
+#if defined (S_ISLNK)
+  r = lstat (filename, &finfo);
+#else
+  r = stat (filename, &finfo);
+#endif
+
+  if (r == -1)
+    return (0);
+
+  character = 0;
+  if (S_ISDIR (finfo.st_mode))
+    character = '/';
+#if defined (S_ISLNK)
+  else if (S_ISLNK (finfo.st_mode))
+    character = '@';
+#endif /* S_ISLNK */
+#if defined (S_ISSOCK)
+  else if (S_ISSOCK (finfo.st_mode))
+    character = '=';
+#endif /* S_ISSOCK */
+  else if (S_ISREG (finfo.st_mode))
+    {
+      if (access (filename, X_OK) == 0)
+	character = '*';
+    }
+  return (character);
+}
+#endif /* VISIBLE_STATS */
+
+/* Stupid comparison routine for qsort () ing strings. */
+static int
+compare_strings (s1, s2)
+  char **s1, **s2;
+{
+  int result;
+
+  result = **s1 - **s2;
+  if (result == 0)
+    result = strcmp (*s1, *s2);
+
+  return result;
+}
+
+/* A completion function for usernames.
+   TEXT contains a partial username preceded by a random
+   character (usually `~').  */
+char *
+username_completion_function (text, state)
+     int state;
+     char *text;
+{
+#if defined (__GO32__)
+  return (char *)NULL;
+#else /* !__GO32__ */
+  static char *username = (char *)NULL;
+  static struct passwd *entry;
+  static int namelen, first_char, first_char_loc;
+
+  if (!state)
+    {
+      if (username)
+	free (username);
+
+      first_char = *text;
+
+      if (first_char == '~')
+	first_char_loc = 1;
+      else
+	first_char_loc = 0;
+
+      username = savestring (&text[first_char_loc]);
+      namelen = strlen (username);
+      setpwent ();
+    }
+
+  while (entry = getpwent ())
+    {
+      /* Null usernames should result in all users as possible completions. */
+      if (namelen == 0)
+        break;
+      else if ((username[0] == entry->pw_name[0]) &&
+	       (strncmp (username, entry->pw_name, namelen) == 0))
+	break;
+    }
+
+  if (!entry)
+    {
+      endpwent ();
+      return ((char *)NULL);
+    }
+  else
+    {
+      char *value = xmalloc (2 + strlen (entry->pw_name));
+
+      *value = *text;
+
+      strcpy (value + first_char_loc, entry->pw_name);
+
+      if (first_char == '~')
+	rl_filename_completion_desired = 1;
+
+      return (value);
+    }
+#endif /* !__GO32__ */
+}
+
+/* **************************************************************** */
+/*								    */
+/*			     Completion				    */
+/*								    */
+/* **************************************************************** */
+
+/* Non-zero means that case is not significant in completion. */
+int completion_case_fold = 0;
+
+/* Return an array of (char *) which is a list of completions for TEXT.
+   If there are no completions, return a NULL pointer.
+   The first entry in the returned array is the substitution for TEXT.
+   The remaining entries are the possible completions.
+   The array is terminated with a NULL pointer.
+
+   ENTRY_FUNCTION is a function of two args, and returns a (char *).
+     The first argument is TEXT.
+     The second is a state argument; it should be zero on the first call, and
+     non-zero on subsequent calls.  It returns a NULL pointer to the caller
+     when there are no more matches.
+ */
+char **
+completion_matches (text, entry_function)
+     char *text;
+     CPFunction *entry_function;
+{
+  /* Number of slots in match_list. */
+  int match_list_size;
+
+  /* The list of matches. */
+  char **match_list =
+    (char **)xmalloc (((match_list_size = 10) + 1) * sizeof (char *));
+
+  /* Number of matches actually found. */
+  int matches = 0;
+
+  /* Temporary string binder. */
+  char *string;
+
+  match_list[1] = (char *)NULL;
+
+  while (string = (*entry_function) (text, matches))
+    {
+      if (matches + 1 == match_list_size)
+	match_list = (char **)xrealloc
+	  (match_list, ((match_list_size += 10) + 1) * sizeof (char *));
+
+      match_list[++matches] = string;
+      match_list[matches + 1] = (char *)NULL;
+    }
+
+  /* If there were any matches, then look through them finding out the
+     lowest common denominator.  That then becomes match_list[0]. */
+  if (matches)
+    {
+      register int i = 1;
+      int low = 100000;		/* Count of max-matched characters. */
+
+      /* If only one match, just use that. */
+      if (matches == 1)
+	{
+	  match_list[0] = match_list[1];
+	  match_list[1] = (char *)NULL;
+	}
+      else
+	{
+	  /* Otherwise, compare each member of the list with
+	     the next, finding out where they stop matching. */
+
+	  while (i < matches)
+	    {
+	      register int c1, c2, si;
+
+	      if (completion_case_fold)
+		{
+		  for (si = 0;
+		       (c1 = to_lower(match_list[i][si])) &&
+		       (c2 = to_lower(match_list[i + 1][si]));
+		       si++)
+		    if (c1 != c2) break;
+		}
+	      else
+		{
+		  for (si = 0;
+		       (c1 = match_list[i][si]) &&
+		       (c2 = match_list[i + 1][si]);
+		       si++)
+		    if (c1 != c2) break;
+		}
+
+	      if (low > si) low = si;
+	      i++;
+	    }
+	  match_list[0] = xmalloc (low + 1);
+	  strncpy (match_list[0], match_list[1], low);
+	  match_list[0][low] = '\0';
+	}
+    }
+  else				/* There were no matches. */
+    {
+      free (match_list);
+      match_list = (char **)NULL;
+    }
+  return (match_list);
+}
+
+/* Okay, now we write the entry_function for filename completion.  In the
+   general case.  Note that completion in the shell is a little different
+   because of all the pathnames that must be followed when looking up the
+   completion for a command. */
+char *
+filename_completion_function (text, state)
+     int state;
+     char *text;
+{
+  static DIR *directory;
+  static char *filename = (char *)NULL;
+  static char *dirname = (char *)NULL;
+  static char *users_dirname = (char *)NULL;
+  static int filename_len;
+
+  struct dirent *entry = (struct dirent *)NULL;
+
+  /* If we don't have any state, then do some initialization. */
+  if (!state)
+    {
+      char *temp;
+
+      if (dirname) free (dirname);
+      if (filename) free (filename);
+      if (users_dirname) free (users_dirname);
+
+      filename = savestring (text);
+      if (!*text) text = ".";
+      dirname = savestring (text);
+
+      temp = strrchr (dirname, '/');
+
+      if (temp)
+	{
+	  strcpy (filename, ++temp);
+	  *temp = '\0';
+	}
+      else
+	strcpy (dirname, ".");
+
+      /* We aren't done yet.  We also support the "~user" syntax. */
+
+      /* Save the version of the directory that the user typed. */
+      users_dirname = savestring (dirname);
+      {
+	char *temp_dirname;
+	int replace_dirname;
+
+	temp_dirname = tilde_expand (dirname);
+	free (dirname);
+	dirname = temp_dirname;
+
+	replace_dirname = 0;
+	if (rl_directory_completion_hook)
+	  replace_dirname = (*rl_directory_completion_hook) (&dirname);
+	if (replace_dirname)
+	  {
+	    free (users_dirname);
+	    users_dirname = savestring (dirname);
+	  }
+      }
+      directory = opendir (dirname);
+      filename_len = strlen (filename);
+
+      rl_filename_completion_desired = 1;
+    }
+
+  /* At this point we should entertain the possibility of hacking wildcarded
+     filenames, like /usr/man/man<WILD>/te<TAB>.  If the directory name
+     contains globbing characters, then build an array of directories, and
+     then map over that list while completing. */
+  /* *** UNIMPLEMENTED *** */
+
+  /* Now that we have some state, we can read the directory. */
+
+  while (directory && (entry = readdir (directory)))
+    {
+      /* Special case for no filename.
+	 All entries except "." and ".." match. */
+      if (!filename_len)
+	{
+	  if ((strcmp (entry->d_name, ".") != 0) &&
+	      (strcmp (entry->d_name, "..") != 0))
+	    break;
+	}
+      else
+	{
+	  /* Otherwise, if these match up to the length of filename, then
+	     it is a match. */
+	    if ((entry->d_name[0] == filename[0]) &&
+		(((int)D_NAMLEN (entry)) >= filename_len) &&
+		(strncmp (filename, entry->d_name, filename_len) == 0))
+	      break;
+	}
+    }
+
+  if (!entry)
+    {
+      if (directory)
+	{
+	  closedir (directory);
+	  directory = (DIR *)NULL;
+	}
+      if (dirname)
+	{
+	  free (dirname);
+	  dirname = (char *)NULL;
+	}
+      if (filename)
+	{
+	  free (filename);
+	  filename = (char *)NULL;
+	}
+      if (users_dirname)
+	{
+	  free (users_dirname);
+	  users_dirname = (char *)NULL;
+	}
+
+      return (char *)NULL;
+    }
+  else
+    {
+      char *temp;
+
+      /* dirname && (strcmp (dirname, ".") != 0) */
+      if (dirname && (dirname[0] != '.' || dirname[1]))
+	{
+	  if (rl_complete_with_tilde_expansion && *users_dirname == '~')
+	    {
+	      int dirlen = strlen (dirname);
+	      temp = xmalloc (2 + dirlen + D_NAMLEN (entry));
+	      strcpy (temp, dirname);
+	      /* Canonicalization cuts off any final slash present.  We need
+		 to add it back. */
+	      if (dirname[dirlen - 1] != '/')
+	        {
+	          temp[dirlen] = '/';
+	          temp[dirlen + 1] = '\0';
+	        }
+	    }
+	  else
+	    {
+	      temp = xmalloc (1 + strlen (users_dirname) + D_NAMLEN (entry));
+	      strcpy (temp, users_dirname);
+	    }
+
+	  strcat (temp, entry->d_name);
+	}
+      else
+	temp = (savestring (entry->d_name));
+
+      return (temp);
+    }
+}
+
+/* A function for simple tilde expansion. */
+int
+rl_tilde_expand (ignore, key)
+     int ignore, key;
+{
+  register int start, end;
+  char *homedir;
+
+  end = rl_point;
+  start = end - 1;
+
+  if (rl_point == rl_end && rl_line_buffer[rl_point] == '~')
+    {
+      homedir = tilde_expand ("~");
+      goto insert;
+    }
+  else if (rl_line_buffer[start] != '~')
+    {
+      for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--);
+      start++;
+    }
+
+  end = start;
+  do
+    {
+      end++;
+    }
+  while (!whitespace (rl_line_buffer[end]) && end < rl_end);
+
+  if (whitespace (rl_line_buffer[end]) || end >= rl_end)
+    end--;
+
+  /* If the first character of the current word is a tilde, perform
+     tilde expansion and insert the result.  If not a tilde, do
+     nothing. */
+  if (rl_line_buffer[start] == '~')
+    {
+      char *temp;
+      int len;
+
+      len = end - start + 1;
+      temp = xmalloc (len + 1);
+      strncpy (temp, rl_line_buffer + start, len);
+      temp[len] = '\0';
+      homedir = tilde_expand (temp);
+      free (temp);
+
+    insert:
+      rl_begin_undo_group ();
+      rl_delete_text (start, end + 1);
+      rl_point = start;
+      rl_insert_text (homedir);
+      rl_end_undo_group ();
+    }
+
+  return (0);
+}
+
+/* Find the first occurrence in STRING1 of any character from STRING2.
+   Return a pointer to the character in STRING1. */
+static char *
+rl_strpbrk (string1, string2)
+     char *string1, *string2;
+{
+  register char *scan;
+
+  for (; *string1; string1++)
+    {
+      for (scan = string2; *scan; scan++)
+	{
+	  if (*string1 == *scan)
+	    {
+	      return (string1);
+	    }
+	}
+    }
+  return ((char *)NULL);
+}
+
+#if defined (STATIC_MALLOC)
+
+/* **************************************************************** */
+/*								    */
+/*			xmalloc and xrealloc ()		     	    */
+/*								    */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/display.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,1276 @@
+/* display.c -- readline redisplay facility. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+/* Global and pseudo-global variables and functions
+   imported from readline.c. */
+extern char *rl_prompt;
+extern int readline_echoing_p;
+extern char *term_clreol, *term_im, *term_ic,  *term_ei, *term_DC;
+/* Termcap variables. */
+extern char *term_up, *term_dc, *term_cr, *term_IC;
+extern int screenheight, screenwidth, screenchars;
+extern int terminal_can_insert, term_xn;
+
+extern void _rl_output_some_chars ();
+extern int _rl_output_character_function ();
+
+extern int _rl_output_meta_chars;
+extern int _rl_horizontal_scroll_mode;
+extern int _rl_mark_modified_lines;
+extern int _rl_prefer_visible_bell;
+
+/* Pseudo-global functions (local to the readline library) exported
+   by this file. */
+void _rl_move_cursor_relative (), _rl_output_some_chars ();
+void _rl_move_vert ();
+
+static void update_line (), clear_to_eol (), space_to_eol ();
+static void delete_chars (), insert_some_chars ();
+
+extern char *xmalloc (), *xrealloc ();
+
+/* Heuristic used to decide whether it is faster to move from CUR to NEW
+   by backing up or outputting a carriage return and moving forward. */
+#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
+
+/* **************************************************************** */
+/*								    */
+/*			Display stuff				    */
+/*								    */
+/* **************************************************************** */
+
+/* This is the stuff that is hard for me.  I never seem to write good
+   display routines in C.  Let's see how I do this time. */
+
+/* (PWP) Well... Good for a simple line updater, but totally ignores
+   the problems of input lines longer than the screen width.
+
+   update_line and the code that calls it makes a multiple line,
+   automatically wrapping line update.  Careful attention needs
+   to be paid to the vertical position variables. */
+
+/* Keep two buffers; one which reflects the current contents of the
+   screen, and the other to draw what we think the new contents should
+   be.  Then compare the buffers, and make whatever changes to the
+   screen itself that we should.  Finally, make the buffer that we
+   just drew into be the one which reflects the current contents of the
+   screen, and place the cursor where it belongs.
+
+   Commands that want to can fix the display themselves, and then let
+   this function know that the display has been fixed by setting the
+   RL_DISPLAY_FIXED variable.  This is good for efficiency. */
+
+/* Global variables declared here. */
+/* What YOU turn on when you have handled all redisplay yourself. */
+int rl_display_fixed = 0;
+
+/* The stuff that gets printed out before the actual text of the line.
+   This is usually pointing to rl_prompt. */
+char *rl_display_prompt = (char *)NULL;
+
+/* Pseudo-global variables declared here. */
+/* The visible cursor position.  If you print some text, adjust this. */
+int _rl_last_c_pos = 0;
+int _rl_last_v_pos = 0;
+
+/* Number of lines currently on screen minus 1. */
+int _rl_vis_botlin = 0;
+
+/* Variables used only in this file. */
+/* The last left edge of text that was displayed.  This is used when
+   doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
+static int last_lmargin = 0;
+
+/* The line display buffers.  One is the line currently displayed on
+   the screen.  The other is the line about to be displayed. */
+static char *visible_line = (char *)NULL;
+static char *invisible_line = (char *)NULL;
+
+/* A buffer for `modeline' messages. */
+static char msg_buf[128];
+
+/* Non-zero forces the redisplay even if we thought it was unnecessary. */
+static int forced_display = 0;
+
+/* Default and initial buffer size.  Can grow. */
+static int line_size = 1024;
+
+static char *last_prompt_string = (char *)NULL;
+static char *local_prompt, *local_prompt_prefix;
+static int visible_length, prefix_length;
+
+/* The number of invisible characters in the line currently being
+   displayed on the screen. */
+static int visible_wrap_offset = 0;
+
+/* The length (buffer offset) of the first line of the last (possibly
+   multi-line) buffer displayed on the screen. */
+static int visible_first_line_len = 0;
+
+/* Expand the prompt string S and return the number of visible
+   characters in *LP, if LP is not null.  This is currently more-or-less
+   a placeholder for expansion. */
+
+/* Current implementation:
+	\001 (^A) start non-visible characters
+	\002 (^B) end non-visible characters
+   all characters except \001 and \002 (following a \001) are copied to
+   the returned string; all characters except those between \001 and
+   \002 are assumed to be `visible'. */	
+
+static char *
+expand_prompt (pmt, lp)
+     char *pmt;
+     int *lp;
+{
+  char *r, *ret, *p;
+  int l, rl, ignoring;
+
+  /* Short-circuit if we can. */
+  if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
+    {
+      r = savestring (pmt);
+      if (lp)
+	*lp = strlen (r);
+      return r;
+    }
+
+  l = pmt ? strlen (pmt) : 0;
+  r = ret = xmalloc (l + 1);
+  
+  for (rl = ignoring = 0, p = pmt; p && *p; p++)
+    {
+      /* This code strips the invisible character string markers
+	 RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
+      if (*p == RL_PROMPT_START_IGNORE)
+	{
+	  ignoring++;
+	  continue;
+	}
+      else if (ignoring && *p == RL_PROMPT_END_IGNORE)
+	{
+	  ignoring = 0;
+	  continue;
+	}
+      else
+	{
+	  *r++ = *p;
+	  if (!ignoring)
+	    rl++;
+	}
+    }
+
+  *r = '\0';
+  if (lp)
+    *lp = rl;
+  return ret;
+}
+
+/*
+ * Expand the prompt string into the various display components, if
+ * necessary.
+ *
+ * local_prompt = expanded last line of string in rl_display_prompt
+ *		  (portion after the final newline)
+ * local_prompt_prefix = portion before last newline of rl_display_prompt,
+ *			 expanded via expand_prompt
+ * visible_length = number of visible characters in local_prompt
+ * prefix_length = number of visible characters in local_prompt_prefix
+ *
+ * This function is called once per call to readline().  It may also be
+ * called arbitrarily to expand the primary prompt.
+ *
+ * The return value is the number of visible characters on the last line
+ * of the (possibly multi-line) prompt.
+ */
+int
+rl_expand_prompt (prompt)
+     char *prompt;
+{
+  char *p, *t;
+  int c;
+
+  /* Clear out any saved values. */
+  if (local_prompt)
+    free (local_prompt);
+  if (local_prompt_prefix)
+    free (local_prompt_prefix);
+  local_prompt = local_prompt_prefix = (char *)0;
+
+  if (prompt == 0 || *prompt == '\0')
+    return (0);
+
+  p = strrchr (prompt, '\n');
+  if (!p)
+    {
+      /* The prompt is only one line. */
+      local_prompt = expand_prompt (prompt, &visible_length);
+      local_prompt_prefix = (char *)0;
+      return (visible_length);
+    }
+  else
+    {
+      /* The prompt spans multiple lines. */
+      t = ++p;
+      local_prompt = expand_prompt (p, &visible_length);
+      c = *t; *t = '\0';
+      /* The portion of the prompt string up to and including the
+	 final newline is now null-terminated. */
+      local_prompt_prefix = expand_prompt (prompt, &prefix_length);
+      *t = c;
+      return (prefix_length);
+    }
+}
+
+/* Basic redisplay algorithm. */
+void
+rl_redisplay ()
+{
+  register int in, out, c, linenum;
+  register char *line = invisible_line;
+  int c_pos = 0, inv_botlin = 0, wrap_offset, wrap_column;
+  char *prompt_this_line;
+
+  if (!readline_echoing_p)
+    return;
+
+  if (!rl_display_prompt)
+    rl_display_prompt = "";
+
+  if (!invisible_line)
+    {
+      visible_line = xmalloc (line_size);
+      invisible_line = xmalloc (line_size);
+      line = invisible_line;
+      for (in = 0; in < line_size; in++)
+	{
+	  visible_line[in] = 0;
+	  invisible_line[in] = 1;
+	}
+      rl_on_new_line ();
+    }
+
+  /* Draw the line into the buffer. */
+  c_pos = -1;
+
+  /* Mark the line as modified or not.  We only do this for history
+     lines. */
+  out = 0;
+  if (_rl_mark_modified_lines && current_history () && rl_undo_list)
+    {
+      line[out++] = '*';
+      line[out] = '\0';
+    }
+
+  /* If someone thought that the redisplay was handled, but the currently
+     visible line has a different modification state than the one about
+     to become visible, then correct the caller's misconception. */
+  if (visible_line[0] != invisible_line[0])
+    rl_display_fixed = 0;
+
+  /* If the prompt to be displayed is the `primary' readline prompt (the
+     one passed to readline()), use the values we have already expanded.
+     If not, use what's already in rl_display_prompt.  WRAP_OFFSET is the
+     number of non-visible characters in the prompt string. */
+  if (rl_display_prompt == rl_prompt)
+    {
+      int local_len = local_prompt ? strlen (local_prompt) : 0;
+      if (local_prompt_prefix && forced_display)
+	_rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
+
+      if (local_len > 0)
+	strncpy (line + out, local_prompt, local_len);
+      out += local_len;
+      line[out] = '\0';
+      wrap_offset = local_len - visible_length;
+    }
+  else
+    {
+      int pmtlen;
+      prompt_this_line = strrchr (rl_display_prompt, '\n');
+      if (!prompt_this_line)
+	prompt_this_line = rl_display_prompt;
+      else
+	{
+	  prompt_this_line++;
+	  if (forced_display)
+	    _rl_output_some_chars (rl_display_prompt, prompt_this_line - rl_display_prompt);
+	}
+
+      pmtlen = strlen (prompt_this_line);
+      strncpy (line + out,  prompt_this_line, pmtlen);
+      out += pmtlen;
+      line[out] = '\0';
+      wrap_offset = 0;
+    }
+
+  for (in = 0; in < rl_end; in++)
+    {
+      c = (unsigned char)rl_line_buffer[in];
+
+      if (out + 8 >= line_size)		/* XXX - 8 for \t */
+	{
+	  line_size *= 2;
+	  visible_line = xrealloc (visible_line, line_size);
+	  invisible_line = xrealloc (invisible_line, line_size);
+	  line = invisible_line;
+	}
+
+      if (in == rl_point)
+	c_pos = out;
+
+      if (META_CHAR (c))
+	{
+	  if (_rl_output_meta_chars == 0)
+	    {
+	      sprintf (line + out, "\\%o", c);
+	      out += 4;
+	    }
+	  else
+	    line[out++] = c;	  
+	}
+#if defined (DISPLAY_TABS)
+      else if (c == '\t')
+	{
+	  register int newout = (out | (int)7) + 1;
+	  while (out < newout)
+	    line[out++] = ' ';
+	}
+#endif
+      else if (c < ' ')
+	{
+	  line[out++] = '^';
+	  line[out++] = UNCTRL (c);	/* XXX was c ^ 0x40 */
+	}
+      else if (c == 127)
+	{
+	  line[out++] = '^';
+	  line[out++] = '?';
+	}
+      else
+	line[out++] = c;
+    }
+  line[out] = '\0';
+  if (c_pos < 0)
+    c_pos = out;
+
+  /* C_POS == position in buffer where cursor should be placed. */
+
+  /* PWP: now is when things get a bit hairy.  The visible and invisible
+     line buffers are really multiple lines, which would wrap every
+     (screenwidth - 1) characters.  Go through each in turn, finding
+     the changed region and updating it.  The line order is top to bottom. */
+
+  /* If we can move the cursor up and down, then use multiple lines,
+     otherwise, let long lines display in a single terminal line, and
+     horizontally scroll it. */
+
+  if (!_rl_horizontal_scroll_mode && term_up && *term_up)
+    {
+      int total_screen_chars = screenchars;
+      int nleft, cursor_linenum, pos, changed_screen_line;
+
+      if (!rl_display_fixed || forced_display)
+	{
+	  forced_display = 0;
+
+	  /* If we have more than a screenful of material to display, then
+	     only display a screenful.  We should display the last screen,
+	     not the first.  I'll fix this in a minute. */
+	  if (out >= total_screen_chars)
+	    out = total_screen_chars - 1;
+
+	  /* Number of screen lines to display.  The first line wraps at
+	     (screenwidth + wrap_offset) chars, the rest of the lines have
+	     screenwidth chars. */
+	  nleft = out - wrap_offset + term_xn - 1;
+	  inv_botlin = (nleft > 0) ? nleft / screenwidth : 0;
+
+	  /* The first line is at character position 0 in the buffer.  The
+	     second and subsequent lines start at N * screenwidth, offset by
+	     OFFSET.  OFFSET is wrap_offset for the invisible line and
+	     visible_wrap_offset for the line currently displayed. */
+
+#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
+#define L_OFFSET(n, offset) ((n) > 0 ? ((n) * screenwidth) + (offset) : 0)
+#define VIS_CHARS(line) &visible_line[L_OFFSET((line), visible_wrap_offset)]
+#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
+#define INV_LINE(line) &invisible_line[L_OFFSET((line), wrap_offset)]
+
+	  /* For each line in the buffer, do the updating display. */
+	  for (linenum = 0; linenum <= inv_botlin; linenum++)
+	    {
+	      update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
+			   screenwidth + W_OFFSET(linenum, visible_wrap_offset),
+			   screenwidth + W_OFFSET(linenum, wrap_offset),
+			   inv_botlin);
+
+	      /* If this is the line with the prompt, we might need to
+		 compensate for invisible characters in the new line. Do
+		 this only if there is not more than one new line (which
+		 implies that we completely overwrite the old visible line)
+		 and the new line is shorter than the old. */
+	      if (linenum == 0 &&
+		  inv_botlin == 0 &&
+		  (wrap_offset > visible_wrap_offset) &&
+		  (_rl_last_c_pos < visible_first_line_len))
+		{
+		  nleft = screenwidth + wrap_offset - _rl_last_c_pos;
+		  if (nleft)
+		    clear_to_eol (nleft);
+		}
+
+	      /* Since the new first line is now visible, save its length. */
+	      if (linenum == 0)
+		visible_first_line_len = (inv_botlin > 0) ? screenwidth : out - wrap_offset;
+	    }
+
+	  /* We may have deleted some lines.  If so, clear the left over
+	     blank ones at the bottom out. */
+	  if (_rl_vis_botlin > inv_botlin)
+	    {
+	      char *tt;
+	      for (; linenum <= _rl_vis_botlin; linenum++)
+		{
+		  tt = VIS_CHARS (linenum);
+		  _rl_move_vert (linenum);
+		  _rl_move_cursor_relative (0, tt);
+		  clear_to_eol
+		    ((linenum == _rl_vis_botlin) ? strlen (tt) : screenwidth);
+		}
+	    }
+	  _rl_vis_botlin = inv_botlin;
+
+	  /* Move the cursor where it should be. */
+	  /* Which line? */
+	  nleft = c_pos - wrap_offset + term_xn - 1;
+	  cursor_linenum = (nleft > 0) ? nleft / screenwidth : 0;
+
+	  /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
+	     different screen line during this redisplay. */
+	  changed_screen_line = _rl_last_v_pos != cursor_linenum;
+	  if (changed_screen_line)
+	    {
+	      _rl_move_vert (cursor_linenum);
+	      /* If we moved up to the line with the prompt using term_up,
+	         the physical cursor position on the screen stays the same,
+	         but the buffer position needs to be adjusted to account
+	         for invisible characters. */
+	      if (cursor_linenum == 0 && wrap_offset)
+	        _rl_last_c_pos += wrap_offset;
+	    }
+
+	  /* We have to reprint the prompt if it contains invisible
+	     characters, since it's not generally OK to just reprint
+	     the characters from the current cursor position. */
+	  nleft = visible_length + wrap_offset;
+	  if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
+	      _rl_last_c_pos <= nleft && local_prompt)
+	    {
+	      if (term_cr)
+		tputs (term_cr, 1, _rl_output_character_function);
+	      _rl_output_some_chars (local_prompt, nleft);
+	      _rl_last_c_pos = nleft;
+	    }
+
+	  /* Where on that line?  And where does that line start
+	     in the buffer? */
+	  pos = L_OFFSET(cursor_linenum, wrap_offset);
+	  /* nleft == number of characters in the line buffer between the
+	     start of the line and the cursor position. */
+	  nleft = c_pos - pos;
+
+	  /* Since backspace() doesn't know about invisible characters in the
+	     prompt, and there's no good way to tell it, we compensate for
+	     those characters here and call backspace() directly. */
+	  if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
+	    {
+	      backspace (_rl_last_c_pos - nleft);
+	      _rl_last_c_pos = nleft;
+	    }
+
+	  if (nleft != _rl_last_c_pos)
+	    _rl_move_cursor_relative (nleft, &invisible_line[pos]);
+	}
+    }
+  else				/* Do horizontal scrolling. */
+    {
+#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
+      int lmargin, ndisp, nleft, phys_c_pos, t;
+
+      /* Always at top line. */
+      _rl_last_v_pos = 0;
+
+      /* Compute where in the buffer the displayed line should start.  This
+	 will be LMARGIN. */
+
+      /* The number of characters that will be displayed before the cursor. */
+      ndisp = c_pos - wrap_offset;
+      nleft  = visible_length + wrap_offset;
+      /* Where the new cursor position will be on the screen.  This can be
+         longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
+      phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
+      t = screenwidth / 3;
+
+      /* If the number of characters had already exceeded the screenwidth,
+         last_lmargin will be > 0. */
+
+      /* If the number of characters to be displayed is more than the screen
+         width, compute the starting offset so that the cursor is about
+         two-thirds of the way across the screen. */
+      if (phys_c_pos > screenwidth - 2)
+	{
+	  lmargin = c_pos - (2 * t);
+	  if (lmargin < 0)
+	    lmargin = 0;
+	  /* If the left margin would be in the middle of a prompt with
+	     invisible characters, don't display the prompt at all. */
+	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
+	    lmargin = nleft;
+	}
+      else if (ndisp < screenwidth - 2)		/* XXX - was -1 */
+        lmargin = 0;
+      else if (phys_c_pos < 1)
+	{
+	  /* If we are moving back towards the beginning of the line and
+	     the last margin is no longer correct, compute a new one. */
+	  lmargin = ((c_pos - 1) / t) * t;	/* XXX */
+	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
+	    lmargin = nleft;
+	}
+      else
+        lmargin = last_lmargin;
+
+      /* If the first character on the screen isn't the first character
+	 in the display line, indicate this with a special character. */
+      if (lmargin > 0)
+	line[lmargin] = '<';
+
+      /* If SCREENWIDTH characters starting at LMARGIN do not encompass
+         the whole line, indicate that with a special characters at the
+         right edge of the screen.  If LMARGIN is 0, we need to take the
+         wrap offset into account. */
+      t = lmargin + M_OFFSET (lmargin, wrap_offset) + screenwidth;
+      if (t < out)
+        line[t - 1] = '>';
+
+      if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
+	{
+	  forced_display = 0;
+	  update_line (&visible_line[last_lmargin],
+		       &invisible_line[lmargin],
+		       0,
+		       screenwidth + visible_wrap_offset,
+		       screenwidth + (lmargin ? 0 : wrap_offset),
+		       0);
+
+	  /* If the visible new line is shorter than the old, but the number
+	     of invisible characters is greater, and we are at the end of
+	     the new line, we need to clear to eol. */
+	  t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
+	  if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
+	      (_rl_last_c_pos == out) &&
+	      t < visible_first_line_len)
+	    {
+	      nleft = screenwidth - t;
+	      clear_to_eol (nleft);
+	    }
+	  visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
+	  if (visible_first_line_len > screenwidth)
+	    visible_first_line_len = screenwidth;
+
+	  _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
+	  last_lmargin = lmargin;
+	}
+    }
+  fflush (rl_outstream);
+
+  /* Swap visible and non-visible lines. */
+  {
+    char *temp = visible_line;
+    visible_line = invisible_line;
+    invisible_line = temp;
+    rl_display_fixed = 0;
+    /* If we are displaying on a single line, and last_lmargin is > 0, we
+       are not displaying any invisible characters, so set visible_wrap_offset
+       to 0. */
+    if (_rl_horizontal_scroll_mode && last_lmargin)
+      visible_wrap_offset = 0;
+    else
+      visible_wrap_offset = wrap_offset;
+  }
+}
+
+/* PWP: update_line() is based on finding the middle difference of each
+   line on the screen; vis:
+
+			     /old first difference
+	/beginning of line   |	      /old last same       /old EOL
+	v		     v	      v		    v
+old:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
+new:	eddie> Oh, my little buggy says to me, as lurgid as
+	^		     ^	^			   ^
+	\beginning of line   |	\new last same	   \new end of line
+			     \new first difference
+
+   All are character pointers for the sake of speed.  Special cases for
+   no differences, as well as for end of line additions must be handeled.
+
+   Could be made even smarter, but this works well enough */
+static void
+update_line (old, new, current_line, omax, nmax, inv_botlin)
+     register char *old, *new;
+     int current_line, omax, nmax;
+{
+  register char *ofd, *ols, *oe, *nfd, *nls, *ne;
+  int temp, lendiff, wsatend, od, nd;
+
+  /* If we're at the right edge of a terminal that supports xn, we're
+     ready to wrap around, so do so.  This fixes problems with knowing
+     the exact cursor position and cut-and-paste with certain terminal
+     emulators.  In this calculation, TEMP is the physical screen
+     position of the cursor. */
+  temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
+  if (temp == screenwidth && term_xn && !_rl_horizontal_scroll_mode
+      && _rl_last_v_pos == current_line - 1)
+    {
+      if (new[0])
+	putc (new[0], rl_outstream);
+      else
+	putc (' ', rl_outstream);
+      _rl_last_c_pos = 1;		/* XXX */
+      _rl_last_v_pos++;
+      if (old[0] && new[0])
+        old[0] = new[0];
+    }
+      
+  /* Find first difference. */
+  for (ofd = old, nfd = new;
+       (ofd - old < omax) && *ofd && (*ofd == *nfd);
+       ofd++, nfd++)
+    ;
+
+  /* Move to the end of the screen line.  ND and OD are used to keep track
+     of the distance between ne and new and oe and old, respectively, to
+     move a subtraction out of each loop. */
+  for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
+  for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
+
+  /* If no difference, continue to next line. */
+  if (ofd == oe && nfd == ne)
+    return;
+
+  wsatend = 1;			/* flag for trailing whitespace */
+  ols = oe - 1;			/* find last same */
+  nls = ne - 1;
+  while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
+    {
+      if (*ols != ' ')
+	wsatend = 0;
+      ols--;
+      nls--;
+    }
+
+  if (wsatend)
+    {
+      ols = oe;
+      nls = ne;
+    }
+  else if (*ols != *nls)
+    {
+      if (*ols)			/* don't step past the NUL */
+	ols++;
+      if (*nls)
+	nls++;
+    }
+
+  _rl_move_vert (current_line);
+
+  /* If this is the first line and there are invisible characters in the
+     prompt string, and the prompt string has not changed, then redraw
+     the entire prompt string.  We can only do this reliably if the
+     terminal supports a `cr' capability.
+
+     This is more than just an efficiency hack -- there is a problem with
+     redrawing portions of the prompt string if they contain terminal
+     escape sequences (like drawing the `unbold' sequence without a
+     corresponding `bold') that manifests itself on certain terminals. */
+
+  lendiff = local_prompt ? strlen (local_prompt) : 0;
+  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
+      lendiff > visible_length &&
+      _rl_last_c_pos > 0 && (ofd - old) >= lendiff && term_cr)
+    {
+      tputs (term_cr, 1, _rl_output_character_function);
+      _rl_output_some_chars (local_prompt, lendiff);
+      _rl_last_c_pos = lendiff;
+    }
+
+  _rl_move_cursor_relative (ofd - old, old);
+
+  /* if (len (new) > len (old)) */
+  lendiff = (nls - nfd) - (ols - ofd);
+
+  /* Insert (diff (len (old), len (new)) ch. */
+  temp = ne - nfd;
+  if (lendiff > 0)
+    {
+      /* Non-zero if we're increasing the number of lines. */
+      int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
+      /* Sometimes it is cheaper to print the characters rather than
+	 use the terminal's capabilities.  If we're growing the number
+	 of lines, make sure we actually cause the new line to wrap
+	 around on auto-wrapping terminals. */
+      if (terminal_can_insert && ((2 * temp) >= lendiff || term_IC) && (!term_xn || !gl))
+	{
+	  /* If lendiff > visible_length and _rl_last_c_pos == 0 and
+	     _rl_horizontal_scroll_mode == 1, inserting the characters with
+	     term_IC or term_ic will screw up the screen because of the
+	     invisible characters.  We need to just draw them. */
+	  if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
+			lendiff <= visible_length))
+	    {
+	      insert_some_chars (nfd, lendiff);
+	      _rl_last_c_pos += lendiff;
+	    }
+	  else
+	    {
+	      /* At the end of a line the characters do not have to
+		 be "inserted".  They can just be placed on the screen. */
+	      _rl_output_some_chars (nfd, lendiff);
+	      _rl_last_c_pos += lendiff;
+	    }
+	  /* Copy (new) chars to screen from first diff to last match. */
+	  temp = nls - nfd;
+	  if ((temp - lendiff) > 0)
+	    {
+	      _rl_output_some_chars (nfd + lendiff, temp - lendiff);
+	      _rl_last_c_pos += temp - lendiff;
+	    }
+	}
+      else
+	{
+	  /* cannot insert chars, write to EOL */
+	  _rl_output_some_chars (nfd, temp);
+	  _rl_last_c_pos += temp;
+	}
+    }
+  else				/* Delete characters from line. */
+    {
+      /* If possible and inexpensive to use terminal deletion, then do so. */
+      if (term_dc && (2 * temp) >= -lendiff)
+	{
+	  /* If all we're doing is erasing the invisible characters in the
+	     prompt string, don't bother.  It screws up the assumptions
+	     about what's on the screen. */
+	  if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
+	      -lendiff == visible_wrap_offset)
+	    lendiff = 0;
+
+	  if (lendiff)
+	    delete_chars (-lendiff); /* delete (diff) characters */
+
+	  /* Copy (new) chars to screen from first diff to last match */
+	  temp = nls - nfd;
+	  if (temp > 0)
+	    {
+	      _rl_output_some_chars (nfd, temp);
+	      _rl_last_c_pos += temp;
+	    }
+	}
+      /* Otherwise, print over the existing material. */
+      else
+	{
+	  if (temp > 0)
+	    {
+	      _rl_output_some_chars (nfd, temp);
+	      _rl_last_c_pos += temp;
+	    }
+	  lendiff = (oe - old) - (ne - new);
+	  if (term_xn && current_line < inv_botlin)
+	    space_to_eol (lendiff);
+	  else
+	    clear_to_eol (lendiff);
+	}
+    }
+}
+
+/* Tell the update routines that we have moved onto a new (empty) line. */
+rl_on_new_line ()
+{
+  if (visible_line)
+    visible_line[0] = '\0';
+
+  _rl_last_c_pos = _rl_last_v_pos = 0;
+  _rl_vis_botlin = last_lmargin = 0;
+  return 0;
+}
+
+/* Actually update the display, period. */
+rl_forced_update_display ()
+{
+  if (visible_line)
+    {
+      register char *temp = visible_line;
+
+      while (*temp) *temp++ = '\0';
+    }
+  rl_on_new_line ();
+  forced_display++;
+  rl_redisplay ();
+  return 0;
+}
+
+/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
+   DATA is the contents of the screen line of interest; i.e., where
+   the movement is being done. */
+void
+_rl_move_cursor_relative (new, data)
+     int new;
+     char *data;
+{
+  register int i;
+
+  /* If we don't have to do anything, then return. */
+  if (_rl_last_c_pos == new) return;
+
+  /* It may be faster to output a CR, and then move forwards instead
+     of moving backwards. */
+  /* i == current physical cursor position. */
+  i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
+  if (CR_FASTER (new, _rl_last_c_pos) || (term_xn && i == screenwidth))
+    {
+#if defined (__MSDOS__)
+      putc ('\r', rl_outstream);
+#else
+      tputs (term_cr, 1, _rl_output_character_function);
+#endif /* !__MSDOS__ */
+      _rl_last_c_pos = 0;
+    }
+
+  if (_rl_last_c_pos < new)
+    {
+      /* Move the cursor forward.  We do it by printing the command
+	 to move the cursor forward if there is one, else print that
+	 portion of the output buffer again.  Which is cheaper? */
+
+      /* The above comment is left here for posterity.  It is faster
+	 to print one character (non-control) than to print a control
+	 sequence telling the terminal to move forward one character.
+	 That kind of control is for people who don't know what the
+	 data is underneath the cursor. */
+#if defined (HACK_TERMCAP_MOTION)
+      extern char *term_forward_char;
+
+      if (term_forward_char)
+	for (i = _rl_last_c_pos; i < new; i++)
+	  tputs (term_forward_char, 1, _rl_output_character_function);
+      else
+	for (i = _rl_last_c_pos; i < new; i++)
+	  putc (data[i], rl_outstream);
+#else
+      for (i = _rl_last_c_pos; i < new; i++)
+	putc (data[i], rl_outstream);
+#endif /* HACK_TERMCAP_MOTION */
+    }
+  else if (_rl_last_c_pos != new)
+    backspace (_rl_last_c_pos - new);
+  _rl_last_c_pos = new;
+}
+
+/* PWP: move the cursor up or down. */
+void
+_rl_move_vert (to)
+     int to;
+{
+  register int delta, i;
+
+  if (_rl_last_v_pos == to || to > screenheight)
+    return;
+
+#if defined (__GO32__)
+  {
+    int row, col;
+
+    ScreenGetCursor (&row, &col);
+    ScreenSetCursor ((row + to - _rl_last_v_pos), col);
+  }
+#else /* !__GO32__ */
+
+  if ((delta = to - _rl_last_v_pos) > 0)
+    {
+      for (i = 0; i < delta; i++)
+	putc ('\n', rl_outstream);
+      tputs (term_cr, 1, _rl_output_character_function);
+      _rl_last_c_pos = 0;
+    }
+  else
+    {			/* delta < 0 */
+      if (term_up && *term_up)
+	for (i = 0; i < -delta; i++)
+	  tputs (term_up, 1, _rl_output_character_function);
+    }
+#endif /* !__GO32__ */
+  _rl_last_v_pos = to;		/* Now TO is here */
+}
+
+/* Physically print C on rl_outstream.  This is for functions which know
+   how to optimize the display.  Return the number of characters output. */
+rl_show_char (c)
+     int c;
+{
+  int n = 1;
+  if (META_CHAR (c) && (_rl_output_meta_chars == 0))
+    {
+      fprintf (rl_outstream, "M-");
+      n += 2;
+      c = UNMETA (c);
+    }
+
+#if defined (DISPLAY_TABS)
+  if (c < 32 && c != '\t')
+#else
+  if (c < 32)
+#endif /* !DISPLAY_TABS */
+    {
+      fprintf (rl_outstream, "C-");
+      n += 2;
+      c += 64;
+    }
+
+  putc (c, rl_outstream);
+  fflush (rl_outstream);
+  return n;
+}
+
+int
+rl_character_len (c, pos)
+     register int c, pos;
+{
+  unsigned char uc;
+
+  uc = (unsigned char)c;
+
+  if (META_CHAR (uc))
+    return ((_rl_output_meta_chars == 0) ? 4 : 1);
+
+  if (uc == '\t')
+    {
+#if defined (DISPLAY_TABS)
+      return (((pos | 7) + 1) - pos);
+#else
+      return (2);
+#endif /* !DISPLAY_TABS */
+    }
+
+  return ((isprint (uc)) ? 1 : 2);
+}
+
+/* How to print things in the "echo-area".  The prompt is treated as a
+   mini-modeline. */
+
+#if defined (HAVE_VARARGS_H)
+rl_message (va_alist)
+     va_dcl
+{
+  char *format;
+  va_list args;
+
+  va_start (args);
+  format = va_arg (args, char *);
+  vsprintf (msg_buf, format, args);
+  va_end (args);
+
+  rl_display_prompt = msg_buf;
+  rl_redisplay ();
+  return 0;
+}
+#else /* !HAVE_VARARGS_H */
+rl_message (format, arg1, arg2)
+     char *format;
+{
+  sprintf (msg_buf, format, arg1, arg2);
+  rl_display_prompt = msg_buf;
+  rl_redisplay ();
+  return 0;
+}
+#endif /* !HAVE_VARARGS_H */
+
+/* How to clear things from the "echo-area". */
+rl_clear_message ()
+{
+  rl_display_prompt = rl_prompt;
+  rl_redisplay ();
+  return 0;
+}
+
+rl_reset_line_state ()
+{
+  rl_on_new_line ();
+
+  rl_display_prompt = rl_prompt ? rl_prompt : "";
+  forced_display = 1;
+  return 0;
+}
+
+/* Quick redisplay hack when erasing characters at the end of the line. */
+void
+_rl_erase_at_end_of_line (l)
+     int l;
+{
+  register int i;
+
+  backspace (l);
+  for (i = 0; i < l; i++)
+    putc (' ', rl_outstream);
+  backspace (l);
+  for (i = 0; i < l; i++)
+    visible_line[--_rl_last_c_pos] = '\0';
+  rl_display_fixed++;
+}
+
+/* Clear to the end of the line.  COUNT is the minimum
+   number of character spaces to clear, */
+static void
+clear_to_eol (count)
+     int count;
+{
+#if !defined (__GO32__)
+  if (term_clreol)
+    {
+      tputs (term_clreol, 1, _rl_output_character_function);
+    }
+  else
+#endif /* !__GO32__ */
+    space_to_eol (count);
+}
+
+/* Clear to the end of the line using spaces.  COUNT is the minimum
+   number of character spaces to clear, */
+static void
+space_to_eol (count)
+     int count;
+{
+  register int i;
+
+  for (i = 0; i < count; i++)
+   putc (' ', rl_outstream);
+
+  _rl_last_c_pos += count;
+}
+
+/* Insert COUNT characters from STRING to the output stream. */
+static void
+insert_some_chars (string, count)
+     char *string;
+     int count;
+{
+#if defined (__GO32__)
+  int row, col, width;
+  char *row_start;
+
+  ScreenGetCursor (&row, &col);
+  width = ScreenCols ();
+  row_start = ScreenPrimary + (row * width);
+
+  memcpy (row_start + col + count, row_start + col, width - col - count);
+
+  /* Place the text on the screen. */
+  _rl_output_some_chars (string, count);
+#else /* !_GO32 */
+
+  /* If IC is defined, then we do not have to "enter" insert mode. */
+  if (term_IC)
+    {
+      char *tgoto (), *buffer;
+      buffer = tgoto (term_IC, 0, count);
+      tputs (buffer, 1, _rl_output_character_function);
+      _rl_output_some_chars (string, count);
+    }
+  else
+    {
+      register int i;
+
+      /* If we have to turn on insert-mode, then do so. */
+      if (term_im && *term_im)
+	tputs (term_im, 1, _rl_output_character_function);
+
+      /* If there is a special command for inserting characters, then
+	 use that first to open up the space. */
+      if (term_ic && *term_ic)
+	{
+	  for (i = count; i--; )
+	    tputs (term_ic, 1, _rl_output_character_function);
+	}
+
+      /* Print the text. */
+      _rl_output_some_chars (string, count);
+
+      /* If there is a string to turn off insert mode, we had best use
+	 it now. */
+      if (term_ei && *term_ei)
+	tputs (term_ei, 1, _rl_output_character_function);
+    }
+#endif /* !__GO32__ */
+}
+
+/* Delete COUNT characters from the display line. */
+static void
+delete_chars (count)
+     int count;
+{
+#if defined (__GO32__)
+  int row, col, width;
+  char *row_start;
+
+  ScreenGetCursor (&row, &col);
+  width = ScreenCols ();
+  row_start = ScreenPrimary + (row * width);
+
+  memcpy (row_start + col, row_start + col + count, width - col - count);
+  memset (row_start + width - count, 0, count * 2);
+#else /* !_GO32 */
+
+  if (count > screenwidth)	/* XXX */
+    return;
+
+  if (term_DC && *term_DC)
+    {
+      char *tgoto (), *buffer;
+      buffer = tgoto (term_DC, count, count);
+      tputs (buffer, count, _rl_output_character_function);
+    }
+  else
+    {
+      if (term_dc && *term_dc)
+	while (count--)
+	  tputs (term_dc, 1, _rl_output_character_function);
+    }
+#endif /* !__GO32__ */
+}
+
+void
+_rl_update_final ()
+{
+  int full_lines;
+
+  full_lines = 0;
+  if (_rl_vis_botlin && visible_line[screenwidth * _rl_vis_botlin] == 0)
+    {
+      _rl_vis_botlin--;
+      full_lines = 1;
+    }
+  _rl_move_vert (_rl_vis_botlin);
+  if (full_lines && term_xn)
+    {
+      /* Remove final line-wrap flag in xterm. */
+      char *last_line;
+      last_line = &visible_line[screenwidth * _rl_vis_botlin];
+      _rl_move_cursor_relative (screenwidth - 1, last_line);
+      clear_to_eol (0);
+      putc (last_line[screenwidth - 1], rl_outstream);
+    }
+  _rl_vis_botlin = 0;
+  crlf ();
+  fflush (rl_outstream);
+  rl_display_fixed++;
+}
+
+/* Move to the start of the current line. */
+static void
+cr ()
+{
+  if (term_cr)
+    {
+      tputs (term_cr, 1, _rl_output_character_function);
+      _rl_last_c_pos = 0;
+    }
+}
+
+/* Redisplay the current line after a SIGWINCH is received. */
+void
+_rl_redisplay_after_sigwinch ()
+{
+  char *t, *oldp;
+
+  /* Clear the current line and put the cursor at column 0.  Make sure
+     the right thing happens if we have wrapped to a new screen line. */
+  if (term_cr)
+    {
+      tputs (term_cr, 1, _rl_output_character_function);
+      _rl_last_c_pos = 0;
+      if (term_clreol)
+	tputs (term_clreol, 1, _rl_output_character_function);
+      else
+	{
+	  space_to_eol (screenwidth);
+	  tputs (term_cr, 1, _rl_output_character_function);
+	}
+      if (_rl_last_v_pos > 0)
+	_rl_move_vert (0);
+    }
+  else
+    crlf ();
+
+  /* Redraw only the last line of a multi-line prompt. */
+  t = strrchr (rl_display_prompt, '\n');
+  if (t)
+    {
+      oldp = rl_display_prompt;
+      rl_display_prompt = ++t;
+      rl_forced_update_display ();
+      rl_display_prompt = oldp;
+    }
+  else
+    rl_forced_update_display ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/doc/hist.texinfo	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,113 @@
+\input texinfo    @c -*-texinfo-*-
+@c %**start of header (This is for running Texinfo on a region.)
+@setfilename history.info
+@settitle GNU History Library
+@c %**end of header (This is for running Texinfo on a region.)
+
+@setchapternewpage odd
+
+@ignore
+last change: Wed Jul 20 09:57:17 EDT 1994
+@end ignore
+
+@set EDITION 2.0
+@set VERSION 2.0
+@set UPDATED 20 July 1994
+@set UPDATE-MONTH July 1994
+
+@ifinfo
+This document describes the GNU History library, a programming tool that
+provides a consistent user interface for recalling lines of previously
+typed input.
+
+Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+pare preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@titlepage
+@sp 10
+@title GNU History Library
+@subtitle Edition @value{EDITION}, for @code{History Library} Version @value{VERSION}.
+@subtitle @value{UPDATE-MONTH}
+@author Brian Fox, Free Software Foundation
+@author Chet Ramey, Case Western Reserve University
+
+@page
+This document describes the GNU History library, a programming tool that
+provides a consistent user interface for recalling lines of previously
+typed input.
+
+Published by the Free Software Foundation @*
+675 Massachusetts Avenue, @*
+Cambridge, MA 02139 USA
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
+@end titlepage
+
+@ifinfo
+@node Top
+@top GNU History Library
+
+This document describes the GNU History library, a programming tool that
+provides a consistent user interface for recalling lines of previously
+typed input.
+
+@menu
+* Using History Interactively::	  GNU History User's Manual.
+* Programming with GNU History::  GNU History Programmer's Manual.
+* Concept Index::		  Index of concepts described in this manual.
+* Function and Variable Index::	  Index of externally visible functions
+				  and variables.
+@end menu
+@end ifinfo
+
+@syncodeindex fn vr
+
+@include hsuser.texinfo
+@include hstech.texinfo
+
+@node Concept Index
+@appendix Concept Index
+@printindex cp
+
+@node Function and Variable Index
+@appendix Function and Variable Index
+@printindex vr
+
+@contents
+@bye
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/doc/hstech.texinfo	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,489 @@
+@ignore
+This file documents the user interface to the GNU History library.
+
+Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+Authored by Brian Fox and Chet Ramey.
+
+Permission is granted to make and distribute verbatim copies of this manual
+provided the copyright notice and this permission notice are preserved on
+all copies.
+
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+GNU Copyright statement is available to the distributee, and provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ignore
+
+@node Programming with GNU History
+@chapter Programming with GNU History
+
+This chapter describes how to interface programs that you write
+with the GNU History Library.
+It should be considered a technical guide.
+For information on the interactive use of GNU History, @pxref{Using
+History Interactively}.
+
+@menu
+* Introduction to History::	What is the GNU History library for?
+* History Storage::		How information is stored.
+* History Functions::		Functions that you can use.
+* History Variables::		Variables that control behaviour.
+* History Programming Example::	Example of using the GNU History Library.
+@end menu
+
+@node Introduction to History
+@section Introduction to History
+
+Many programs read input from the user a line at a time.  The GNU History
+library is able to keep track of those lines, associate arbitrary data with
+each line, and utilize information from previous lines in composing new
+ones.
+
+The programmer using the History library has available functions
+for remembering lines on a history list, associating arbitrary data
+with a line, removing lines from the list, searching through the list
+for a line containing an arbitrary text string, and referencing any line
+in the list directly.  In addition, a history @dfn{expansion} function
+is available which provides for a consistent user interface across
+different programs.
+
+The user using programs written with the History library has the
+benefit of a consistent user interface with a set of well-known
+commands for manipulating the text of previous lines and using that text
+in new commands.  The basic history manipulation commands are similar to
+the history substitution provided by @code{csh}.
+
+If the programmer desires, he can use the Readline library, which
+includes some history manipulation by default, and has the added
+advantage of command line editing.
+
+@node History Storage
+@section History Storage
+
+The history list is an array of history entries.  A history entry is
+declared as follows:
+
+@example
+typedef struct _hist_entry @{
+  char *line;
+  char *data;
+@} HIST_ENTRY;
+@end example
+
+The history list itself might therefore be declared as
+
+@example
+HIST_ENTRY **the_history_list;
+@end example
+
+The state of the History library is encapsulated into a single structure:
+
+@example
+/* A structure used to pass the current state of the history stuff around. */
+typedef struct _hist_state @{
+  HIST_ENTRY **entries;         /* Pointer to the entries themselves. */
+  int offset;                   /* The location pointer within this array. */
+  int length;                   /* Number of elements within this array. */
+  int size;                     /* Number of slots allocated to this array. */
+  int flags;
+@} HISTORY_STATE;
+@end example
+
+If the flags member includes @code{HS_STIFLED}, the history has been
+stifled.
+
+@node History Functions
+@section History Functions
+
+This section describes the calling sequence for the various functions
+present in GNU History.
+
+@menu
+* Initializing History and State Management::	Functions to call when you
+						want to use history in a
+						program.
+* History List Management::		Functions used to manage the list
+					of history entries.
+* Information About the History List::	Functions returning information about
+					the history list.
+* Moving Around the History List::	Functions used to change the position
+					in the history list.
+* Searching the History List::		Functions to search the history list
+					for entries containing a string.
+* Managing the History File::		Functions that read and write a file
+					containing the history list.
+* History Expansion::			Functions to perform csh-like history
+					expansion.
+@end menu
+
+@node Initializing History and State Management
+@subsection Initializing History and State Management
+
+This section describes functions used to initialize and manage
+the state of the History library when you want to use the history
+functions in your program.
+
+@deftypefun void using_history ()
+Begin a session in which the history functions might be used.  This
+initializes the interactive variables.
+@end deftypefun
+
+@deftypefun {HISTORY_STATE *} history_get_history_state ()
+Return a structure describing the current state of the input history.
+@end deftypefun
+
+@deftypefun void history_set_history_state (HISTORY_STATE *state)
+Set the state of the history list according to @var{state}.
+@end deftypefun
+
+@node History List Management
+@subsection History List Management
+
+These functions manage individual entries on the history list, or set
+parameters managing the list itself.
+
+@deftypefun void add_history (char *string)
+Place @var{string} at the end of the history list.  The associated data
+field (if any) is set to @code{NULL}.
+@end deftypefun
+
+@deftypefun {HIST_ENTRY *} remove_history (int which)
+Remove history entry at offset @var{which} from the history.  The
+removed element is returned so you can free the line, data,
+and containing structure.
+@end deftypefun
+
+@deftypefun {HIST_ENTRY *} replace_history_entry (int which, char *line, char *data)
+Make the history entry at offset @var{which} have @var{line} and @var{data}.
+This returns the old entry so you can dispose of the data.  In the case
+of an invalid @var{which}, a @code{NULL} pointer is returned.
+@end deftypefun
+
+@deftypefun void stifle_history (int max)
+Stifle the history list, remembering only the last @var{max} entries.
+@end deftypefun
+
+@deftypefun int unstifle_history ()
+Stop stifling the history.  This returns the previous amount the
+history was stifled.  The value is positive if the history was
+stifled, negative if it wasn't.
+@end deftypefun
+
+@deftypefun int history_is_stifled ()
+Returns non-zero if the history is stifled, zero if it is not.
+@end deftypefun
+
+@node Information About the History List
+@subsection Information About the History List
+
+These functions return information about the entire history list or
+individual list entries.
+
+@deftypefun {HIST_ENTRY **} history_list ()
+Return a @code{NULL} terminated array of @code{HIST_ENTRY} which is the
+current input history.  Element 0 of this list is the beginning of time.
+If there is no history, return @code{NULL}.
+@end deftypefun
+
+@deftypefun int where_history ()
+Returns the offset of the current history element.
+@end deftypefun
+
+@deftypefun {HIST_ENTRY *} current_history ()
+Return the history entry at the current position, as determined by
+@code{where_history ()}.  If there is no entry there, return a @code{NULL}
+pointer.
+@end deftypefun
+
+@deftypefun {HIST_ENTRY *} history_get (int offset)
+Return the history entry at position @var{offset}, starting from
+@code{history_base}.  If there is no entry there, or if @var{offset}
+is greater than the history length, return a @code{NULL} pointer.
+@end deftypefun
+
+@deftypefun int history_total_bytes ()
+Return the number of bytes that the primary history entries are using.
+This function returns the sum of the lengths of all the lines in the
+history.
+@end deftypefun
+
+@node Moving Around the History List
+@subsection Moving Around the History List
+
+These functions allow the current index into the history list to be
+set or changed.
+
+@deftypefun int history_set_pos (int pos)
+Set the position in the history list to @var{pos}, an absolute index
+into the list.
+@end deftypefun
+
+@deftypefun {HIST_ENTRY *} previous_history ()
+Back up the current history offset to the previous history entry, and
+return a pointer to that entry.  If there is no previous entry, return
+a @code{NULL} pointer.
+@end deftypefun
+
+@deftypefun {HIST_ENTRY *} next_history ()
+Move the current history offset forward to the next history entry, and
+return the a pointer to that entry.  If there is no next entry, return
+a @code{NULL} pointer.
+@end deftypefun
+
+@node Searching the History List
+@subsection Searching the History List
+@cindex History Searching
+
+These functions allow searching of the history list for entries containing
+a specific string.  Searching may be performed both forward and backward
+from the current history position.  The search may be @dfn{anchored},
+meaning that the string must match at the beginning of the history entry.
+@cindex anchored search
+
+@deftypefun int history_search (char *string, int direction)
+Search the history for @var{string}, starting at the current history
+offset.  If @var{direction} < 0, then the search is through previous entries,
+else through subsequent.  If @var{string} is found, then
+the current history index is set to that history entry, and the value
+returned is the offset in the line of the entry where
+@var{string} was found.  Otherwise, nothing is changed, and a -1 is
+returned.
+@end deftypefun
+
+@deftypefun int history_search_prefix (char *string, int direction)
+Search the history for @var{string}, starting at the current history
+offset.  The search is anchored: matching lines must begin with
+@var{string}.  If @var{direction} < 0, then the search is through previous
+entries, else through subsequent.  If @var{string} is found, then the
+current history index is set to that entry, and the return value is 0. 
+Otherwise, nothing is changed, and a -1 is returned. 
+@end deftypefun
+
+@deftypefun int history_search_pos (char *string, int direction, int pos)
+Search for @var{string} in the history list, starting at @var{pos}, an
+absolute index into the list.  If @var{direction} is negative, the search
+proceeds backward from @var{pos}, otherwise forward.  Returns the absolute
+index of the history element where @var{string} was found, or -1 otherwise.
+@end deftypefun
+
+@node Managing the History File
+@subsection Managing the History File
+
+The History library can read the history from and write it to a file.
+This section documents the functions for managing a history file.
+
+@deftypefun int read_history (char *filename)
+Add the contents of @var{filename} to the history list, a line at a
+time.  If @var{filename} is @code{NULL}, then read from
+@file{~/.history}.  Returns 0 if successful, or errno if not.
+@end deftypefun
+
+@deftypefun int read_history_range (char *filename, int from, int to)
+Read a range of lines from @var{filename}, adding them to the history list.
+Start reading at line @var{from} and end at @var{to}.  If
+@var{from} is zero, start at the beginning.  If @var{to} is less than
+@var{from}, then read until the end of the file.  If @var{filename} is
+@code{NULL}, then read from @file{~/.history}.  Returns 0 if successful,
+or @code{errno} if not.
+@end deftypefun
+
+@deftypefun int write_history (char *filename)
+Write the current history to @var{filename}, overwriting @var{filename}
+if necessary.  If @var{filename} is
+@code{NULL}, then write the history list to @file{~/.history}.  Values
+returned are as in @code{read_history ()}.
+@end deftypefun
+
+@deftypefun int append_history (int nelements, char *filename)
+Append the last @var{nelements} of the history list to @var{filename}.
+@end deftypefun
+
+@deftypefun int history_truncate_file (char *filename, int nlines)
+Truncate the history file @var{filename}, leaving only the last
+@var{nlines} lines.
+@end deftypefun
+
+@node History Expansion
+@subsection History Expansion
+
+These functions implement @code{csh}-like history expansion.
+
+@deftypefun int history_expand (char *string, char **output)
+Expand @var{string}, placing the result into @var{output}, a pointer
+to a string (@pxref{History Interaction}).  Returns:
+@table @code
+@item 0
+If no expansions took place (or, if the only change in
+the text was the de-slashifying of the history expansion
+character);
+@item 1
+if expansions did take place;
+@item -1
+if there was an error in expansion;
+@item 2
+if the returned line should only be displayed, but not executed,
+as with the @code{:p} modifier (@pxref{Modifiers}).
+@end table
+
+If an error ocurred in expansion, then @var{output} contains a descriptive
+error message.
+@end deftypefun
+
+@deftypefun {char *} history_arg_extract (int first, int last, char *string)
+Extract a string segment consisting of the @var{first} through @var{last}
+arguments present in @var{string}.  Arguments are broken up as in Bash.
+@end deftypefun
+
+@deftypefun {char *} get_history_event (char *string, int *cindex, int qchar)
+Returns the text of the history event beginning at @var{string} +
+@var{*cindex}.  @var{*cindex} is modified to point to after the event
+specifier.  At function entry, @var{cindex} points to the index into
+@var{string} where the history event specification begins.  @var{qchar}
+is a character that is allowed to end the event specification in addition
+to the ``normal'' terminating characters.
+@end deftypefun
+
+@deftypefun {char **} history_tokenize (char *string)
+Return an array of tokens parsed out of @var{string}, much as the
+shell might.  The tokens are split on white space and on the
+characters @code{()<>;&|$}, and shell quoting conventions are
+obeyed.
+@end deftypefun
+
+@node History Variables
+@section History Variables
+
+This section describes the externally visible variables exported by
+the GNU History Library.
+
+@deftypevar int history_base
+The logical offset of the first entry in the history list.
+@end deftypevar
+
+@deftypevar int history_length
+The number of entries currently stored in the history list.
+@end deftypevar
+
+@deftypevar int max_input_history
+The maximum number of history entries.  This must be changed using
+@code{stifle_history ()}.
+@end deftypevar
+
+@deftypevar char history_expansion_char
+The character that starts a history event.  The default is @samp{!}.
+@end deftypevar
+
+@deftypevar char history_subst_char
+The character that invokes word substitution if found at the start of
+a line.  The default is @samp{^}.
+@end deftypevar
+
+@deftypevar char history_comment_char
+During tokenization, if this character is seen as the first character
+of a word, then it and all subsequent characters up to a newline are
+ignored, suppressing history expansion for the remainder of the line.
+This is disabled by default.
+@end deftypevar
+
+@deftypevar {char *} history_no_expand_chars
+The list of characters which inhibit history expansion if found immediately
+following @var{history_expansion_char}.  The default is whitespace and
+@samp{=}.
+@end deftypevar
+
+@node History Programming Example
+@section History Programming Example
+
+The following program demonstrates simple use of the GNU History Library.
+
+@smallexample
+main ()
+@{
+  char line[1024], *t;
+  int len, done = 0;
+
+  line[0] = 0;
+
+  using_history ();
+  while (!done)
+    @{
+      printf ("history$ ");
+      fflush (stdout);
+      t = fgets (line, sizeof (line) - 1, stdin);
+      if (t && *t)
+        @{
+          len = strlen (t);
+          if (t[len - 1] == '\n')
+            t[len - 1] = '\0';
+        @}
+
+      if (!t)
+        strcpy (line, "quit");
+
+      if (line[0])
+        @{
+          char *expansion;
+          int result;
+
+          result = history_expand (line, &expansion);
+          if (result)
+            fprintf (stderr, "%s\n", expansion);
+
+          if (result < 0 || result == 2)
+            @{
+              free (expansion);
+              continue;
+            @}
+
+          add_history (expansion);
+          strncpy (line, expansion, sizeof (line) - 1);
+          free (expansion);
+        @}
+
+      if (strcmp (line, "quit") == 0)
+        done = 1;
+      else if (strcmp (line, "save") == 0)
+        write_history ("history_file");
+      else if (strcmp (line, "read") == 0)
+        read_history ("history_file");
+      else if (strcmp (line, "list") == 0)
+        @{
+          register HIST_ENTRY **the_list;
+          register int i;
+
+          the_list = history_list ();
+          if (the_list)
+            for (i = 0; the_list[i]; i++)
+              printf ("%d: %s\n", i + history_base, the_list[i]->line);
+        @}
+      else if (strncmp (line, "delete", 6) == 0)
+        @{
+          int which;
+          if ((sscanf (line + 6, "%d", &which)) == 1)
+            @{
+              HIST_ENTRY *entry = remove_history (which);
+              if (!entry)
+                fprintf (stderr, "No such entry %d\n", which);
+              else
+                @{
+                  free (entry->line);
+                  free (entry);
+                @}
+            @}
+          else
+            @{
+              fprintf (stderr, "non-numeric arg given to `delete'\n");
+            @}
+        @}
+    @}
+@}
+@end smallexample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/doc/hsuser.texinfo	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,198 @@
+@ignore
+This file documents the user interface to the GNU History library.
+
+Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+Authored by Brian Fox and Chet Ramey.
+
+Permission is granted to make and distribute verbatim copies of this manual
+provided the copyright notice and this permission notice are preserved on
+all copies.
+
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+GNU Copyright statement is available to the distributee, and provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ignore
+
+@node Using History Interactively
+@chapter Using History Interactively
+
+@ifset BashFeatures
+This chapter describes how to use the GNU History Library interactively,
+from a user's standpoint.  It should be considered a user's guide.  For
+information on using the GNU History Library in your own programs,
+see the GNU Readline Library Manual.
+@end ifset
+@ifclear BashFeatures
+This chapter describes how to use the GNU History Library interactively,
+from a user's standpoint.  It should be considered a user's guide.  For
+information on using the GNU History Library in your own programs,
+@pxref{Programming with GNU History}.
+@end ifclear
+
+@menu
+* History Interaction::		What it feels like using History as a user.
+@end menu
+
+@node History Interaction
+@section History Interaction
+@cindex expansion
+
+The History library provides a history expansion feature that is similar
+to the history expansion provided by @code{csh}.  The following text
+describes the syntax used to manipulate the history information.
+
+History expansion takes place in two parts.  The first is to determine
+which line from the previous history should be used during substitution.
+The second is to select portions of that line for inclusion into the
+current one.  The line selected from the previous history is called the
+@dfn{event}, and the portions of that line that are acted upon are
+called @dfn{words}.  The line is broken into words in the same fashion
+that Bash does, so that several English (or Unix) words
+surrounded by quotes are considered as one word.
+
+@menu
+* Event Designators::	How to specify which history line to use.
+* Word Designators::	Specifying which words are of interest.
+* Modifiers::		Modifying the results of substitution.
+@end menu
+
+@node Event Designators
+@subsection Event Designators
+@cindex event designators
+
+An event designator is a reference to a command line entry in the
+history list.
+@cindex history events
+
+@table @asis
+
+@item @code{!}
+Start a history substitution, except when followed by a space, tab,
+the end of the line, @key{=} or @key{(}.
+
+@item @code{!!}
+Refer to the previous command.  This is a synonym for @code{!-1}.
+
+@item @code{!n}
+Refer to command line @var{n}.
+
+@item @code{!-n}
+Refer to the command @var{n} lines back.
+
+@item @code{!string}
+Refer to the most recent command starting with @var{string}.
+
+@item @code{!?string}[@code{?}]
+Refer to the most recent command containing @var{string}.
+
+@item @code{!#}
+The entire command line typed so far.
+
+@item @code{^string1^string2^}
+Quick Substitution.  Repeat the last command, replacing @var{string1}
+with @var{string2}.  Equivalent to
+@code{!!:s/string1/string2/}.
+
+@end table
+
+@node Word Designators
+@subsection Word Designators
+
+A @key{:} separates the event specification from the word designator.  It
+can be omitted if the word designator begins with a @key{^}, @key{$},
+@key{*} or @key{%}.  Words are numbered from the beginning of the line,
+with the first word being denoted by a 0 (zero).
+
+@table @code
+
+@item 0 (zero)
+The @code{0}th word.  For many applications, this is the command word.
+
+@item n
+The @var{n}th word.
+
+@item ^
+The first argument;  that is, word 1.
+
+@item $
+The last argument.
+
+@item %
+The word matched by the most recent @code{?string?} search.
+
+@item x-y
+A range of words; @code{-@var{y}} abbreviates @code{0-@var{y}}.
+
+@item *
+All of the words, except the @code{0}th.  This is a synonym for @code{1-$}.
+It is not an error to use @key{*} if there is just one word in the event;
+the empty string is returned in that case.
+
+@item x*
+Abbreviates @code{x-$}
+
+@item x-
+Abbreviates @code{x-$} like @code{x*}, but omits the last word.
+
+@end table
+
+@node Modifiers
+@subsection Modifiers
+
+After the optional word designator, you can add a sequence of one or more
+of the following modifiers, each preceded by a @key{:}.
+
+@table @code
+
+@item h
+Remove a trailing pathname component, leaving only the head.
+
+@item r
+Remove a trailing suffix of the form @samp{.}@var{suffix}, leaving the basename.
+
+@item e
+Remove all but the trailing suffix.
+
+@item t
+Remove all leading  pathname  components, leaving the tail.
+
+@item p
+Print the new command but do not execute it.
+
+@ifset BashFeatures
+@item q
+Quote the substituted words, escaping further substitutions.
+
+@item x
+Quote the substituted words as with @code{q},         
+but break into words at spaces, tabs, and newlines.
+@end ifset
+
+@item s/old/new/
+Substitute @var{new} for the first occurrence of @var{old} in the
+event line.  Any delimiter may be used in place of @key{/}.
+The delimiter may be quoted in @var{old} and @var{new}
+with a single backslash.  If @key{&} appears in @var{new},
+it is replaced by @var{old}.  A single backslash will quote
+the @key{&}.  The final delimiter is optional if it is the last
+character on the input line.
+
+@item &
+Repeat the previous substitution.
+
+@item g
+Cause changes to be applied over the entire event line.  Used in
+conjunction with @code{s}, as in @code{gs/old/new/}, or with
+@code{&}.
+
+@end table
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/doc/rlman.texinfo	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,111 @@
+\input texinfo    @c -*-texinfo-*-
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename readline.info
+@settitle GNU Readline Library
+@comment %**end of header (This is for running Texinfo on a region.)
+@synindex vr fn
+@setchapternewpage odd
+
+@ignore
+last change: Thu Jul 21 16:02:40 EDT 1994
+@end ignore
+
+@set EDITION 2.0
+@set VERSION 2.0
+@set UPDATED 21 July 1994
+@set UPDATE-MONTH July 1994
+
+@ifinfo
+This document describes the GNU Readline Library, a utility which aids
+in the consistency of user interface across discrete programs that need
+to provide a command line interface.
+
+Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+pare preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@titlepage  
+@sp 10
+@title GNU Readline Library
+@subtitle Edition @value{EDITION}, for @code{Readline Library} Version @value{VERSION}.
+@subtitle @value{UPDATE-MONTH}
+@author Brian Fox, Free Software Foundation
+@author Chet Ramey, Case Western Reserve University
+
+@page
+This document describes the GNU Readline Library, a utility which aids
+in the consistency of user interface across discrete programs that need
+to provide a command line interface.
+
+Published by the Free Software Foundation @*
+675 Massachusetts Avenue, @*
+Cambridge, MA 02139 USA
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
+@end titlepage
+
+@ifinfo
+@node Top
+@top GNU Readline Library
+
+This document describes the GNU Readline Library, a utility which aids
+in the consistency of user interface across discrete programs that need
+to provide a command line interface.
+
+@menu
+* Command Line Editing::	   GNU Readline User's Manual.
+* Programming with GNU Readline::  GNU Readline Programmer's Manual.
+* Concept Index::		   Index of concepts described in this manual.
+* Function and Variable Index::	   Index of externally visible functions
+				   and variables.
+@end menu
+@end ifinfo
+
+@include rluser.texinfo
+@include rltech.texinfo
+
+@node Concept Index
+@unnumbered Concept Index
+@printindex cp
+
+@node Function and Variable Index
+@unnumbered Function and Variable Index
+@printindex fn
+
+@contents
+@bye
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/doc/rltech.texinfo	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,1406 @@
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename rltech.info
+@comment %**end of header (This is for running Texinfo on a region.)
+@setchapternewpage odd
+
+@ifinfo
+This document describes the GNU Readline Library, a utility for aiding
+in the consitency of user interface across discrete programs that need
+to provide a command line interface.
+
+Copyright (C) 1988, 1994 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+pare preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@node Programming with GNU Readline
+@chapter Programming with GNU Readline
+
+This chapter describes the interface between the GNU Readline Library and
+other programs.  If you are a programmer, and you wish to include the
+features found in GNU Readline
+such as completion, line editing, and interactive history manipulation
+in your own programs, this section is for you.
+
+@menu
+* Basic Behavior::	Using the default behavior of Readline.
+* Custom Functions::	Adding your own functions to Readline.
+* Readline Variables::			Variables accessible to custom
+					functions.
+* Readline Convenience Functions::	Functions which Readline supplies to
+					aid in writing your own
+* Custom Completers::	Supplanting or supplementing Readline's
+			completion functions.
+@end menu
+
+@node Basic Behavior
+@section Basic Behavior
+
+Many programs provide a command line interface, such as @code{mail},
+@code{ftp}, and @code{sh}.  For such programs, the default behaviour of
+Readline is sufficient.  This section describes how to use Readline in
+the simplest way possible, perhaps to replace calls in your code to
+@code{gets()} or @code{fgets ()}.
+
+@findex readline
+@cindex readline, function
+The function @code{readline ()} prints a prompt and then reads and returns
+a single line of text from the user.  The line @code{readline}
+returns is allocated with @code{malloc ()}; you should @code{free ()}
+the line when you are done with it.  The declaration for @code{readline}
+in ANSI C is
+
+@example
+@code{char *readline (char *@var{prompt});}
+@end example
+
+@noindent
+So, one might say
+@example
+@code{char *line = readline ("Enter a line: ");}
+@end example
+@noindent
+in order to read a line of text from the user.
+The line returned has the final newline removed, so only the
+text remains.
+
+If @code{readline} encounters an @code{EOF} while reading the line, and the
+line is empty at that point, then @code{(char *)NULL} is returned.
+Otherwise, the line is ended just as if a newline had been typed.
+
+If you want the user to be able to get at the line later, (with
+@key{C-p} for example), you must call @code{add_history ()} to save the
+line away in a @dfn{history} list of such lines.
+
+@example
+@code{add_history (line)};
+@end example
+
+@noindent
+For full details on the GNU History Library, see the associated manual.
+
+It is preferable to avoid saving empty lines on the history list, since
+users rarely have a burning need to reuse a blank line.  Here is
+a function which usefully replaces the standard @code{gets ()} library
+function, and has the advantage of no static buffer to overflow:
+
+@example
+/* A static variable for holding the line. */
+static char *line_read = (char *)NULL;
+
+/* Read a string, and return a pointer to it.  Returns NULL on EOF. */
+char *
+rl_gets ()
+@{
+  /* If the buffer has already been allocated, return the memory
+     to the free pool. */
+  if (line_read)
+    @{
+      free (line_read);
+      line_read = (char *)NULL;
+    @}
+
+  /* Get a line from the user. */
+  line_read = readline ("");
+
+  /* If the line has any text in it, save it on the history. */
+  if (line_read && *line_read)
+    add_history (line_read);
+
+  return (line_read);
+@}
+@end example
+
+This function gives the user the default behaviour of @key{TAB}
+completion: completion on file names.  If you do not want Readline to
+complete on filenames, you can change the binding of the @key{TAB} key
+with @code{rl_bind_key ()}.
+
+@example
+@code{int rl_bind_key (int @var{key}, int (*@var{function})());}
+@end example
+
+@code{rl_bind_key ()} takes two arguments: @var{key} is the character that
+you want to bind, and @var{function} is the address of the function to
+call when @var{key} is pressed.  Binding @key{TAB} to @code{rl_insert ()}
+makes @key{TAB} insert itself.
+@code{rl_bind_key ()} returns non-zero if @var{key} is not a valid
+ASCII character code (between 0 and 255).
+
+Thus, to disable the default @key{TAB} behavior, the following suffices:
+@example
+@code{rl_bind_key ('\t', rl_insert);}
+@end example
+
+This code should be executed once at the start of your program; you
+might write a function called @code{initialize_readline ()} which
+performs this and other desired initializations, such as installing
+custom completers (@pxref{Custom Completers}).
+
+@node Custom Functions
+@section Custom Functions
+
+Readline provides many functions for manipulating the text of
+the line, but it isn't possible to anticipate the needs of all
+programs.  This section describes the various functions and variables
+defined within the Readline library which allow a user program to add
+customized functionality to Readline.
+
+@menu
+* The Function Type::	C declarations to make code readable.
+* Function Writing::	Variables and calling conventions.
+@end menu
+
+@node The Function Type
+@subsection The Function Type
+
+For readabilty, we declare a new type of object, called
+@dfn{Function}.  A @code{Function} is a C function which
+returns an @code{int}.  The type declaration for @code{Function} is:
+
+@noindent
+@code{typedef int Function ();}
+
+The reason for declaring this new type is to make it easier to write
+code describing pointers to C functions.  Let us say we had a variable
+called @var{func} which was a pointer to a function.  Instead of the
+classic C declaration
+
+@code{int (*)()func;}
+
+@noindent
+we may write
+
+@code{Function *func;}
+
+@noindent
+Similarly, there are
+
+@example
+typedef void VFunction ();
+typedef char *CPFunction (); @r{and}
+typedef char **CPPFunction ();
+@end example
+
+@noindent
+for functions returning no value, @code{pointer to char}, and
+@code{pointer to pointer to char}, respectively.
+
+@node Function Writing
+@subsection Writing a New Function
+
+In order to write new functions for Readline, you need to know the
+calling conventions for keyboard-invoked functions, and the names of the
+variables that describe the current state of the line read so far.
+
+The calling sequence for a command @code{foo} looks like
+
+@example
+@code{foo (int count, int key)}
+@end example
+
+@noindent
+where @var{count} is the numeric argument (or 1 if defaulted) and
+@var{key} is the key that invoked this function.
+
+It is completely up to the function as to what should be done with the
+numeric argument.  Some functions use it as a repeat count, some
+as a flag, and others to choose alternate behavior (refreshing the current
+line as opposed to refreshing the screen, for example).  Some choose to
+ignore it.  In general, if a
+function uses the numeric argument as a repeat count, it should be able
+to do something useful with both negative and positive arguments.
+At the very least, it should be aware that it can be passed a
+negative argument.
+
+@node Readline Variables
+@section Readline Variables
+
+These variables are available to function writers.
+
+@deftypevar {char *} rl_line_buffer
+This is the line gathered so far.  You are welcome to modify the
+contents of the line, but see @ref{Allowing Undoing}.
+@end deftypevar
+
+@deftypevar int rl_point
+The offset of the current cursor position in @code{rl_line_buffer}
+(the @emph{point}).
+@end deftypevar
+
+@deftypevar int rl_end
+The number of characters present in @code{rl_line_buffer}.  When
+@code{rl_point} is at the end of the line, @code{rl_point} and
+@code{rl_end} are equal.
+@end deftypevar
+
+@deftypevar int rl_mark
+The mark (saved position) in the current line.  If set, the mark
+and point define a @emph{region}.
+@end deftypevar
+
+@deftypevar int rl_done
+Setting this to a non-zero value causes Readline to return the current
+line immediately.
+@end deftypevar
+
+@deftypevar int rl_pending_input
+Setting this to a value makes it the next keystroke read.  This is a
+way to stuff a single character into the input stream.
+@end deftypevar
+
+@deftypevar {char *} rl_prompt
+The prompt Readline uses.  This is set from the argument to
+@code{readline ()}, and should not be assigned to directly.
+@end deftypevar
+
+@deftypevar {char *} rl_terminal_name
+The terminal type, used for initialization.
+@end deftypevar
+
+@deftypevar {char *} rl_readline_name
+This variable is set to a unique name by each application using Readline.
+The value allows conditional parsing of the inputrc file
+(@pxref{Conditional Init Constructs}).
+@end deftypevar
+
+@deftypevar {FILE *} rl_instream
+The stdio stream from which Readline reads input.
+@end deftypevar
+
+@deftypevar {FILE *} rl_outstream
+The stdio stream to which Readline performs output.
+@end deftypevar
+
+@deftypevar {Function *} rl_startup_hook
+If non-zero, this is the address of a function to call just
+before @code{readline} prints the first prompt.
+@end deftypevar
+
+@deftypevar {Function *} rl_event_hook
+If non-zero, this is the address of a function to call periodically
+when readline is waiting for terminal input.
+@end deftypevar
+
+@node Readline Convenience Functions
+@section Readline Convenience Functions
+
+@menu
+* Function Naming::	How to give a function you write a name.
+* Keymaps::		Making keymaps.
+* Binding Keys::	Changing Keymaps.
+* Associating Function Names and Bindings::	Translate function names to
+						key sequences.
+* Allowing Undoing::	How to make your functions undoable.
+* Redisplay::		Functions to control line display.
+* Modifying Text::	Functions to modify @code{rl_line_buffer}.
+* Utility Functions::	Generally useful functions and hooks.
+@end menu
+
+@node Function Naming
+@subsection Naming a Function
+
+The user can dynamically change the bindings of keys while using
+Readline.  This is done by representing the function with a descriptive
+name.  The user is able to type the descriptive name when referring to
+the function.  Thus, in an init file, one might find
+
+@example
+Meta-Rubout:	backward-kill-word
+@end example
+
+This binds the keystroke @key{Meta-Rubout} to the function
+@emph{descriptively} named @code{backward-kill-word}.  You, as the
+programmer, should bind the functions you write to descriptive names as
+well.  Readline provides a function for doing that:
+
+@deftypefun int rl_add_defun (char *name, Function *function, int key)
+Add @var{name} to the list of named functions.  Make @var{function} be
+the function that gets called.  If @var{key} is not -1, then bind it to
+@var{function} using @code{rl_bind_key ()}.
+@end deftypefun
+
+Using this function alone is sufficient for most applications.  It is
+the recommended way to add a few functions to the default functions that
+Readline has built in.  If you need to do something other
+than adding a function to Readline, you may need to use the
+underlying functions described below.
+
+@node Keymaps
+@subsection Selecting a Keymap
+
+Key bindings take place on a @dfn{keymap}.  The keymap is the
+association between the keys that the user types and the functions that
+get run.  You can make your own keymaps, copy existing keymaps, and tell
+Readline which keymap to use.
+
+@deftypefun Keymap rl_make_bare_keymap ()
+Returns a new, empty keymap.  The space for the keymap is allocated with
+@code{malloc ()}; you should @code{free ()} it when you are done.
+@end deftypefun
+
+@deftypefun Keymap rl_copy_keymap (Keymap map)
+Return a new keymap which is a copy of @var{map}.
+@end deftypefun
+
+@deftypefun Keymap rl_make_keymap ()
+Return a new keymap with the printing characters bound to rl_insert,
+the lowercase Meta characters bound to run their equivalents, and
+the Meta digits bound to produce numeric arguments.
+@end deftypefun
+
+@deftypefun void rl_discard_keymap (Keymap keymap)
+Free the storage associated with @var{keymap}.
+@end deftypefun
+
+Readline has several internal keymaps.  These functions allow you to
+change which keymap is active.
+
+@deftypefun Keymap rl_get_keymap ()
+Returns the currently active keymap.
+@end deftypefun
+
+@deftypefun void rl_set_keymap (Keymap keymap)
+Makes @var{keymap} the currently active keymap.
+@end deftypefun
+
+@deftypefun Keymap rl_get_keymap_by_name (char *name)
+Return the keymap matching @var{name}.  @var{name} is one which would
+be supplied in a @code{set keymap} inputrc line (@pxref{Readline Init File}).
+@end deftypefun
+
+@node Binding Keys
+@subsection Binding Keys
+
+You associate keys with functions through the keymap.  Readline has
+several internal keymaps: @code{emacs_standard_keymap},
+@code{emacs_meta_keymap}, @code{emacs_ctlx_keymap},
+@code{vi_movement_keymap}, and @code{vi_insertion_keymap}.
+@code{emacs_standard_keymap} is the default, and the examples in
+this manual assume that.
+
+These functions manage key bindings.
+
+@deftypefun int rl_bind_key (int key, Function *function)
+Binds @var{key} to @var{function} in the currently active keymap.
+Returns non-zero in the case of an invalid @var{key}.
+@end deftypefun
+
+@deftypefun int rl_bind_key_in_map (int key, Function *function, Keymap map)
+Bind @var{key} to @var{function} in @var{map}.  Returns non-zero in the case
+of an invalid @var{key}.
+@end deftypefun
+
+@deftypefun int rl_unbind_key (int key)
+Bind @var{key} to the null function in the currently active keymap.
+Returns non-zero in case of error.
+@end deftypefun
+
+@deftypefun int rl_unbind_key_in_map (int key, Keymap map)
+Bind @var{key} to the null function in @var{map}.
+Returns non-zero in case of error.
+@end deftypefun
+
+@deftypefun int rl_generic_bind (int type, char *keyseq, char *data, Keymap map)
+Bind the key sequence represented by the string @var{keyseq} to the arbitrary
+pointer @var{data}.  @var{type} says what kind of data is pointed to by
+@var{data}; this can be a function (@code{ISFUNC}), a macro
+(@code{ISMACR}), or a keymap (@code{ISKMAP}).  This makes new keymaps as
+necessary.  The initial keymap in which to do bindings is @var{map}.
+@end deftypefun
+
+@deftypefun int rl_parse_and_bind (char *line)
+Parse @var{line} as if it had been read from the @code{inputrc} file and
+perform any key bindings and variable assignments found
+(@pxref{Readline Init File}).
+@end deftypefun
+
+@deftypefun int rl_read_init_file (char *filename)
+Read keybindings and variable assignments from @var{filename}
+(@pxref{Readline Init File}).
+@end deftypefun
+
+@node Associating Function Names and Bindings
+@subsection Associating Function Names and Bindings
+
+These functions allow you to find out what keys invoke named functions
+and the functions invoked by a particular key sequence.
+
+@deftypefun {Function *} rl_named_function (char *name)
+Return the function with name @var{name}.
+@end deftypefun
+
+@deftypefun {Function *} rl_function_of_keyseq (char *keyseq, Keymap map, int *type)
+Return the function invoked by @var{keyseq} in keymap @var{map}.
+If @var{map} is NULL, the current keymap is used.  If @var{type} is
+not NULL, the type of the object is returned in it (one of @code{ISFUNC},
+@code{ISKMAP}, or @code{ISMACR}).
+@end deftypefun
+
+@deftypefun {char **} rl_invoking_keyseqs (Function *function)
+Return an array of strings representing the key sequences used to
+invoke @var{function} in the current keymap.
+@end deftypefun
+
+@deftypefun {char **} rl_invoking_keyseqs_in_map (Function *function, Keymap map)
+Return an array of strings representing the key sequences used to
+invoke @var{function} in the keymap @var{map}.
+@end deftypefun
+
+@deftypefun void rl_function_dumper (int readable)
+Print the readline function names and the key sequences currently
+bound to them to @code{rl_outstream}.  If @var{readable} is non-zero,
+the list is formatted in such a way that it can be made part of an
+@code{inputrc} file and re-read.
+@end deftypefun
+
+@deftypefun void rl_list_funmap_names ()
+Print the names of all bindable Readline functions to @code{rl_outstream}.
+@end deftypefun
+
+@node Allowing Undoing
+@subsection Allowing Undoing
+
+Supporting the undo command is a painless thing, and makes your
+functions much more useful.  It is certainly easy to try
+something if you know you can undo it.  I could use an undo function for
+the stock market.
+
+If your function simply inserts text once, or deletes text once, and
+uses @code{rl_insert_text ()} or @code{rl_delete_text ()} to do it, then
+undoing is already done for you automatically.
+
+If you do multiple insertions or multiple deletions, or any combination
+of these operations, you should group them together into one operation.
+This is done with @code{rl_begin_undo_group ()} and
+@code{rl_end_undo_group ()}.
+
+The types of events that can be undone are:
+
+@example
+enum undo_code @{ UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END @}; 
+@end example
+
+Notice that @code{UNDO_DELETE} means to insert some text, and
+@code{UNDO_INSERT} means to delete some text.  That is, the undo code
+tells undo what to undo, not how to undo it.  @code{UNDO_BEGIN} and
+@code{UNDO_END} are tags added by @code{rl_begin_undo_group ()} and
+@code{rl_end_undo_group ()}.
+
+@deftypefun int rl_begin_undo_group ()
+Begins saving undo information in a group construct.  The undo
+information usually comes from calls to @code{rl_insert_text ()} and
+@code{rl_delete_text ()}, but could be the result of calls to
+@code{rl_add_undo ()}.
+@end deftypefun
+
+@deftypefun int rl_end_undo_group ()
+Closes the current undo group started with @code{rl_begin_undo_group
+()}.  There should be one call to @code{rl_end_undo_group ()}
+for each call to @code{rl_begin_undo_group ()}.
+@end deftypefun
+
+@deftypefun void rl_add_undo (enum undo_code what, int start, int end, char *text)
+Remember how to undo an event (according to @var{what}).  The affected
+text runs from @var{start} to @var{end}, and encompasses @var{text}.
+@end deftypefun
+
+@deftypefun void free_undo_list ()
+Free the existing undo list.
+@end deftypefun
+
+@deftypefun int rl_do_undo ()
+Undo the first thing on the undo list.  Returns @code{0} if there was
+nothing to undo, non-zero if something was undone.
+@end deftypefun
+
+Finally, if you neither insert nor delete text, but directly modify the
+existing text (e.g., change its case), call @code{rl_modifying ()}
+once, just before you modify the text.  You must supply the indices of
+the text range that you are going to modify.
+
+@deftypefun int rl_modifying (int start, int end)
+Tell Readline to save the text between @var{start} and @var{end} as a
+single undo unit.  It is assumed that you will subsequently modify
+that text.
+@end deftypefun
+
+@node Redisplay
+@subsection Redisplay
+
+@deftypefun int rl_redisplay ()
+Change what's displayed on the screen to reflect the current contents
+of @code{rl_line_buffer}.
+@end deftypefun
+
+@deftypefun int rl_forced_update_display ()
+Force the line to be updated and redisplayed, whether or not
+Readline thinks the screen display is correct.
+@end deftypefun
+
+@deftypefun int rl_on_new_line ()
+Tell the update routines that we have moved onto a new (empty) line,
+usually after ouputting a newline.
+@end deftypefun
+
+@deftypefun int rl_reset_line_state ()
+Reset the display state to a clean state and redisplay the current line
+starting on a new line.
+@end deftypefun
+
+@deftypefun int rl_message (va_alist)
+The arguments are a string as would be supplied to @code{printf}.  The
+resulting string is displayed in the @dfn{echo area}.  The echo area
+is also used to display numeric arguments and search strings.
+@end deftypefun
+
+@deftypefun int rl_clear_message ()
+Clear the message in the echo area.
+@end deftypefun
+
+@node Modifying Text
+@subsection Modifying Text
+
+@deftypefun int rl_insert_text (char *text)
+Insert @var{text} into the line at the current cursor position.
+@end deftypefun
+
+@deftypefun int rl_delete_text (int start, int end)
+Delete the text between @var{start} and @var{end} in the current line.
+@end deftypefun
+
+@deftypefun {char *} rl_copy_text (int start, int end)
+Return a copy of the text between @var{start} and @var{end} in
+the current line.
+@end deftypefun
+
+@deftypefun int rl_kill_text (int start, int end)
+Copy the text between @var{start} and @var{end} in the current line
+to the kill ring, appending or prepending to the last kill if the
+last command was a kill command.  The text is deleted.
+If @var{start} is less than @var{end},
+the text is appended, otherwise prepended.  If the last command was
+not a kill, a new kill ring slot is used.
+@end deftypefun
+
+@node Utility Functions
+@subsection Utility Functions
+
+@deftypefun int rl_read_key ()
+Return the next character available.  This handles input inserted into
+the input stream via @var{pending input} (@pxref{Readline Variables})
+and @code{rl_stuff_char ()}, macros, and characters read from the keyboard.
+@end deftypefun
+
+@deftypefun int rl_stuff_char (int c)
+Insert @var{c} into the Readline input stream.  It will be "read"
+before Readline attempts to read characters from the terminal with
+@code{rl_read_key ()}.
+@end deftypefun
+
+@deftypefun int rl_initialize ()
+Initialize or re-initialize Readline's internal state.
+@end deftypefun
+
+@deftypefun int rl_reset_terminal (char *terminal_name)
+Reinitialize Readline's idea of the terminal settings using
+@var{terminal_name} as the terminal type (e.g., @code{vt100}).
+@end deftypefun
+
+@deftypefun int alphabetic (int c)
+Return 1 if @var{c} is an alphabetic character.
+@end deftypefun
+
+@deftypefun int numeric (int c)
+Return 1 if @var{c} is a numeric character.
+@end deftypefun
+
+@deftypefun int ding ()
+Ring the terminal bell, obeying the setting of @code{bell-style}.
+@end deftypefun
+
+The following are implemented as macros, defined in @code{chartypes.h}.
+
+@deftypefun int uppercase_p (int c)
+Return 1 if @var{c} is an uppercase alphabetic character.
+@end deftypefun
+
+@deftypefun int lowercase_p (int c)
+Return 1 if @var{c} is a lowercase alphabetic character.
+@end deftypefun
+
+@deftypefun int digit_p (int c)
+Return 1 if @var{c} is a numeric character.
+@end deftypefun
+
+@deftypefun int to_upper (int c)
+If @var{c} is a lowercase alphabetic character, return the corresponding
+uppercase character.
+@end deftypefun
+
+@deftypefun int to_lower (int c)
+If @var{c} is an uppercase alphabetic character, return the corresponding
+lowercase character.
+@end deftypefun
+
+@deftypefun int digit_value (int c)
+If @var{c} is a number, return the value it represents.
+@end deftypefun
+
+@subsection An Example
+
+Here is a function which changes lowercase characters to their uppercase
+equivalents, and uppercase characters to lowercase.  If
+this function was bound to @samp{M-c}, then typing @samp{M-c} would
+change the case of the character under point.  Typing @samp{M-1 0 M-c}
+would change the case of the following 10 characters, leaving the cursor on
+the last character changed.
+
+@example
+/* Invert the case of the COUNT following characters. */
+int
+invert_case_line (count, key)
+     int count, key;
+@{
+  register int start, end, i;
+
+  start = rl_point;
+
+  if (rl_point >= rl_end)
+    return (0);
+
+  if (count < 0)
+    @{
+      direction = -1;
+      count = -count;
+    @}
+  else
+    direction = 1;
+      
+  /* Find the end of the range to modify. */
+  end = start + (count * direction);
+
+  /* Force it to be within range. */
+  if (end > rl_end)
+    end = rl_end;
+  else if (end < 0)
+    end = 0;
+
+  if (start == end)
+    return (0);
+
+  if (start > end)
+    @{
+      int temp = start;
+      start = end;
+      end = temp;
+    @}
+
+  /* Tell readline that we are modifying the line, so it will save
+     the undo information. */
+  rl_modifying (start, end);
+
+  for (i = start; i != end; i++)
+    @{
+      if (uppercase_p (rl_line_buffer[i]))
+        rl_line_buffer[i] = to_lower (rl_line_buffer[i]);
+      else if (lowercase_p (rl_line_buffer[i]))
+        rl_line_buffer[i] = to_upper (rl_line_buffer[i]);
+    @}
+  /* Move point to on top of the last character changed. */
+  rl_point = (direction == 1) ? end - 1 : start;
+  return (0);
+@}
+@end example
+
+@node Custom Completers
+@section Custom Completers
+
+Typically, a program that reads commands from the user has a way of
+disambiguating commands and data.  If your program is one of these, then
+it can provide completion for commands, data, or both.
+The following sections describe how your program and Readline
+cooperate to provide this service.
+
+@menu
+* How Completing Works::	The logic used to do completion.
+* Completion Functions::	Functions provided by Readline.
+* Completion Variables::	Variables which control completion.
+* A Short Completion Example::	An example of writing completer subroutines.
+@end menu
+
+@node How Completing Works
+@subsection How Completing Works
+
+In order to complete some text, the full list of possible completions
+must be available.  That is, it is not possible to accurately
+expand a partial word without knowing all of the possible words
+which make sense in that context.  The Readline library provides
+the user interface to completion, and two of the most common
+completion functions:  filename and username.  For completing other types
+of text, you must write your own completion function.  This section
+describes exactly what such functions must do, and provides an example.
+
+There are three major functions used to perform completion:
+
+@enumerate
+@item
+The user-interface function @code{rl_complete ()}.  This function is
+called with the same arguments as other Readline
+functions intended for interactive use:  @var{count} and
+@var{invoking_key}.  It isolates the word to be completed and calls
+@code{completion_matches ()} to generate a list of possible completions.
+It then either lists the possible completions, inserts the possible
+completions, or actually performs the
+completion, depending on which behavior is desired.
+
+@item
+The internal function @code{completion_matches ()} uses your
+@dfn{generator} function to generate the list of possible matches, and
+then returns the array of these matches.  You should place the address
+of your generator function in @code{rl_completion_entry_function}.
+
+@item
+The generator function is called repeatedly from
+@code{completion_matches ()}, returning a string each time.  The
+arguments to the generator function are @var{text} and @var{state}.
+@var{text} is the partial word to be completed.  @var{state} is zero the
+first time the function is called, allowing the generator to perform
+any necessary initialization, and a positive non-zero integer for
+each subsequent call.  When the generator function returns
+@code{(char *)NULL} this signals @code{completion_matches ()} that there are
+no more possibilities left.  Usually the generator function computes the
+list of possible completions when @var{state} is zero, and returns them
+one at a time on subsequent calls.  Each string the generator function
+returns as a match must be allocated with @code{malloc()}; Readline
+frees the strings when it has finished with them.
+
+@end enumerate
+
+@deftypefun int rl_complete (int ignore, int invoking_key)
+Complete the word at or before point.  You have supplied the function
+that does the initial simple matching selection algorithm (see
+@code{completion_matches ()}).  The default is to do filename completion.
+@end deftypefun
+
+@deftypevar {Function *} rl_completion_entry_function
+This is a pointer to the generator function for @code{completion_matches
+()}.  If the value of @code{rl_completion_entry_function} is
+@code{(Function *)NULL} then the default filename generator function,
+@code{filename_entry_function ()}, is used.
+@end deftypevar
+
+@node Completion Functions
+@subsection Completion Functions
+
+Here is the complete list of callable completion functions present in
+Readline.
+
+@deftypefun int rl_complete_internal (int what_to_do)
+Complete the word at or before point.  @var{what_to_do} says what to do
+with the completion.  A value of @samp{?} means list the possible
+completions.  @samp{TAB} means do standard completion.  @samp{*} means
+insert all of the possible completions.  @samp{!} means to display
+all of the possible completions, if there is more than one, as well as
+performing partial completion.
+@end deftypefun
+
+@deftypefun int rl_complete (int ignore, int invoking_key)
+Complete the word at or before point.  You have supplied the function
+that does the initial simple matching selection algorithm (see
+@code{completion_matches ()} and @code{rl_completion_entry_function}).
+The default is to do filename
+completion.  This calls @code{rl_complete_internal ()} with an
+argument depending on @var{invoking_key}.
+@end deftypefun
+
+@deftypefun int rl_possible_completions (int count, int invoking_key))
+List the possible completions.  See description of @code{rl_complete
+()}.  This calls @code{rl_complete_internal ()} with an argument of
+@samp{?}.
+@end deftypefun
+
+@deftypefun int rl_insert_completions (int count, int invoking_key))
+Insert the list of possible completions into the line, deleting the
+partially-completed word.  See description of @code{rl_complete ()}.
+This calls @code{rl_complete_internal ()} with an argument of @samp{*}.
+@end deftypefun
+
+@deftypefun {char **} completion_matches (char *text, CPFunction *entry_func)
+Returns an array of @code{(char *)} which is a list of completions for
+@var{text}.  If there are no completions, returns @code{(char **)NULL}.
+The first entry in the returned array is the substitution for @var{text}.
+The remaining entries are the possible completions.  The array is
+terminated with a @code{NULL} pointer.
+
+@var{entry_func} is a function of two args, and returns a
+@code{(char *)}.  The first argument is @var{text}.  The second is a
+state argument; it is zero on the first call, and non-zero on subsequent
+calls.  @var{entry_func} returns a @code{NULL}  pointer to the caller
+when there are no more matches.
+@end deftypefun
+
+@deftypefun {char *} filename_completion_function (char *text, int state)
+A generator function for filename completion in the general case.  Note
+that completion in Bash is a little different because of all
+the pathnames that must be followed when looking up completions for a
+command.  The Bash source is a useful reference for writing custom
+completion functions.
+@end deftypefun
+
+@deftypefun {char *} username_completion_function (char *text, int state)
+A completion generator for usernames.  @var{text} contains a partial
+username preceded by a random character (usually @samp{~}).  As with all
+completion generators, @var{state} is zero on the first call and non-zero
+for subsequent calls.
+@end deftypefun
+
+@node Completion Variables
+@subsection Completion Variables
+
+@deftypevar {Function *} rl_completion_entry_function
+A pointer to the generator function for @code{completion_matches ()}.
+@code{NULL} means to use @code{filename_entry_function ()}, the default
+filename completer.
+@end deftypevar
+
+@deftypevar {CPPFunction *} rl_attempted_completion_function
+A pointer to an alternative function to create matches.
+The function is called with @var{text}, @var{start}, and @var{end}.
+@var{start} and @var{end} are indices in @code{rl_line_buffer} saying
+what the boundaries of @var{text} are.  If this function exists and
+returns @code{NULL}, or if this variable is set to @code{NULL}, then
+@code{rl_complete ()} will call the value of
+@code{rl_completion_entry_function} to generate matches, otherwise the
+array of strings returned will be used.
+@end deftypevar
+
+@deftypevar int rl_completion_query_items
+Up to this many items will be displayed in response to a
+possible-completions call.  After that, we ask the user if she is sure
+she wants to see them all.  The default value is 100.
+@end deftypevar
+
+@deftypevar {char *} rl_basic_word_break_characters
+The basic list of characters that signal a break between words for the
+completer routine.  The default value of this variable is the characters
+which break words for completion in Bash, i.e.,
+@code{" \t\n\"\\'`@@$><=;|&@{("}.
+@end deftypevar
+
+@deftypevar {char *} rl_completer_word_break_characters
+The list of characters that signal a break between words for
+@code{rl_complete_internal ()}.  The default list is the value of
+@code{rl_basic_word_break_characters}.
+@end deftypevar
+
+@deftypevar {char *} rl_completer_quote_characters
+List of characters which can be used to quote a substring of the line.
+Completion occurs on the entire substring, and within the substring
+@code{rl_completer_word_break_characters} are treated as any other character,
+unless they also appear within this list.
+@end deftypevar
+
+@deftypevar {char *} rl_special_prefixes
+The list of characters that are word break characters, but should be
+left in @var{text} when it is passed to the completion function.
+Programs can use this to help determine what kind of completing to do.
+For instance, Bash sets this variable to "$@@" so that it can complete
+shell variables and hostnames.
+@end deftypevar
+
+@deftypevar int rl_ignore_completion_duplicates
+If non-zero, then disallow duplicates in the matches.  Default is 1.
+@end deftypevar
+
+@deftypevar int rl_filename_completion_desired
+Non-zero means that the results of the matches are to be treated as
+filenames.  This is @emph{always} zero on entry, and can only be changed
+within a completion entry generator function.  If it is set to a non-zero
+value, directory names have a slash appended and Readline attempts to
+quote completed filenames if they contain any embedded word break
+characters.
+@end deftypevar
+
+@deftypevar int rl_filename_quoting_desired
+Non-zero means that the results of the matches are to be quoted using
+double quotes (or an application-specific quoting mechanism) if the
+completed filename contains any characters in
+@code{rl_completer_word_break_chars}.  This is @emph{always} non-zero
+on entry, and can only be changed within a completion entry generator
+function.
+@end deftypevar
+
+@deftypevar {Function *} rl_ignore_some_completions_function
+This function, if defined, is called by the completer when real filename
+completion is done, after all the matching names have been generated.
+It is passed a @code{NULL} terminated array of matches.
+The first element (@code{matches[0]}) is the
+maximal substring common to all matches. This function can
+re-arrange the list of matches as required, but each element deleted
+from the array must be freed.
+@end deftypevar
+
+@deftypevar {Function *} rl_directory_completion_hook
+This function, if defined, is allowed to modify the directory portion
+of filenames Readline completes.  It is called with the address of a
+string (the current directory name) as an argument.  It could be used
+to expand symbolic links or shell variables in pathnames.
+@end deftypevar
+
+@node A Short Completion Example
+@subsection A Short Completion Example
+
+Here is a small application demonstrating the use of the GNU Readline
+library.  It is called @code{fileman}, and the source code resides in
+@file{examples/fileman.c}.  This sample application provides
+completion of command names, line editing features, and access to the
+history list.
+
+@page
+@smallexample
+/* fileman.c -- A tiny application which demonstrates how to use the
+   GNU Readline library.  This application interactively allows users
+   to manipulate files and their modes. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+extern char *getwd ();
+extern char *xmalloc ();
+
+/* The names of functions that actually do the manipulation. */
+int com_list (), com_view (), com_rename (), com_stat (), com_pwd ();
+int com_delete (), com_help (), com_cd (), com_quit ();
+
+/* A structure which contains information on the commands this program
+   can understand. */
+
+typedef struct @{
+  char *name;			/* User printable name of the function. */
+  Function *func;		/* Function to call to do the job. */
+  char *doc;			/* Documentation for this function.  */
+@} COMMAND;
+
+COMMAND commands[] = @{
+  @{ "cd", com_cd, "Change to directory DIR" @},
+  @{ "delete", com_delete, "Delete FILE" @},
+  @{ "help", com_help, "Display this text" @},
+  @{ "?", com_help, "Synonym for `help'" @},
+  @{ "list", com_list, "List files in DIR" @},
+  @{ "ls", com_list, "Synonym for `list'" @},
+  @{ "pwd", com_pwd, "Print the current working directory" @},
+  @{ "quit", com_quit, "Quit using Fileman" @},
+  @{ "rename", com_rename, "Rename FILE to NEWNAME" @},
+  @{ "stat", com_stat, "Print out statistics on FILE" @},
+  @{ "view", com_view, "View the contents of FILE" @},
+  @{ (char *)NULL, (Function *)NULL, (char *)NULL @}
+@};
+
+/* Forward declarations. */
+char *stripwhite ();
+COMMAND *find_command ();
+
+/* The name of this program, as taken from argv[0]. */
+char *progname;
+
+/* When non-zero, this global means the user is done using this program. */
+int done;
+
+char *
+dupstr (s)
+     int s;
+@{
+  char *r;
+
+  r = xmalloc (strlen (s) + 1);
+  strcpy (r, s);
+  return (r);
+@}
+
+main (argc, argv)
+     int argc;
+     char **argv;
+@{
+  char *line, *s;
+
+  progname = argv[0];
+
+  initialize_readline ();	/* Bind our completer. */
+
+  /* Loop reading and executing lines until the user quits. */
+  for ( ; done == 0; )
+    @{
+      line = readline ("FileMan: ");
+
+      if (!line)
+        break;
+
+      /* Remove leading and trailing whitespace from the line.
+         Then, if there is anything left, add it to the history list
+         and execute it. */
+      s = stripwhite (line);
+
+      if (*s)
+        @{
+          add_history (s);
+          execute_line (s);
+        @}
+
+      free (line);
+    @}
+  exit (0);
+@}
+
+/* Execute a command line. */
+int
+execute_line (line)
+     char *line;
+@{
+  register int i;
+  COMMAND *command;
+  char *word;
+
+  /* Isolate the command word. */
+  i = 0;
+  while (line[i] && whitespace (line[i]))
+    i++;
+  word = line + i;
+
+  while (line[i] && !whitespace (line[i]))
+    i++;
+
+  if (line[i])
+    line[i++] = '\0';
+
+  command = find_command (word);
+
+  if (!command)
+    @{
+      fprintf (stderr, "%s: No such command for FileMan.\n", word);
+      return (-1);
+    @}
+
+  /* Get argument to command, if any. */
+  while (whitespace (line[i]))
+    i++;
+
+  word = line + i;
+
+  /* Call the function. */
+  return ((*(command->func)) (word));
+@}
+
+/* Look up NAME as the name of a command, and return a pointer to that
+   command.  Return a NULL pointer if NAME isn't a command name. */
+COMMAND *
+find_command (name)
+     char *name;
+@{
+  register int i;
+
+  for (i = 0; commands[i].name; i++)
+    if (strcmp (name, commands[i].name) == 0)
+      return (&commands[i]);
+
+  return ((COMMAND *)NULL);
+@}
+
+/* Strip whitespace from the start and end of STRING.  Return a pointer
+   into STRING. */
+char *
+stripwhite (string)
+     char *string;
+@{
+  register char *s, *t;
+
+  for (s = string; whitespace (*s); s++)
+    ;
+    
+  if (*s == 0)
+    return (s);
+
+  t = s + strlen (s) - 1;
+  while (t > s && whitespace (*t))
+    t--;
+  *++t = '\0';
+
+  return s;
+@}
+
+/* **************************************************************** */
+/*                                                                  */
+/*                  Interface to Readline Completion                */
+/*                                                                  */
+/* **************************************************************** */
+
+char *command_generator ();
+char **fileman_completion ();
+
+/* Tell the GNU Readline library how to complete.  We want to try to complete
+   on command names if this is the first word in the line, or on filenames
+   if not. */
+initialize_readline ()
+@{
+  /* Allow conditional parsing of the ~/.inputrc file. */
+  rl_readline_name = "FileMan";
+
+  /* Tell the completer that we want a crack first. */
+  rl_attempted_completion_function = (CPPFunction *)fileman_completion;
+@}
+
+/* Attempt to complete on the contents of TEXT.  START and END show the
+   region of TEXT that contains the word to complete.  We can use the
+   entire line in case we want to do some simple parsing.  Return the
+   array of matches, or NULL if there aren't any. */
+char **
+fileman_completion (text, start, end)
+     char *text;
+     int start, end;
+@{
+  char **matches;
+
+  matches = (char **)NULL;
+
+  /* If this word is at the start of the line, then it is a command
+     to complete.  Otherwise it is the name of a file in the current
+     directory. */
+  if (start == 0)
+    matches = completion_matches (text, command_generator);
+
+  return (matches);
+@}
+
+/* Generator function for command completion.  STATE lets us know whether
+   to start from scratch; without any state (i.e. STATE == 0), then we
+   start at the top of the list. */
+char *
+command_generator (text, state)
+     char *text;
+     int state;
+@{
+  static int list_index, len;
+  char *name;
+
+  /* If this is a new word to complete, initialize now.  This includes
+     saving the length of TEXT for efficiency, and initializing the index
+     variable to 0. */
+  if (!state)
+    @{
+      list_index = 0;
+      len = strlen (text);
+    @}
+
+  /* Return the next name which partially matches from the command list. */
+  while (name = commands[list_index].name)
+    @{
+      list_index++;
+
+      if (strncmp (name, text, len) == 0)
+        return (dupstr(name));
+    @}
+
+  /* If no names matched, then return NULL. */
+  return ((char *)NULL);
+@}
+
+/* **************************************************************** */
+/*                                                                  */
+/*                       FileMan Commands                           */
+/*                                                                  */
+/* **************************************************************** */
+
+/* String to pass to system ().  This is for the LIST, VIEW and RENAME
+   commands. */
+static char syscom[1024];
+
+/* List the file(s) named in arg. */
+com_list (arg)
+     char *arg;
+@{
+  if (!arg)
+    arg = "";
+
+  sprintf (syscom, "ls -FClg %s", arg);
+  return (system (syscom));
+@}
+
+com_view (arg)
+     char *arg;
+@{
+  if (!valid_argument ("view", arg))
+    return 1;
+
+  sprintf (syscom, "more %s", arg);
+  return (system (syscom));
+@}
+
+com_rename (arg)
+     char *arg;
+@{
+  too_dangerous ("rename");
+  return (1);
+@}
+
+com_stat (arg)
+     char *arg;
+@{
+  struct stat finfo;
+
+  if (!valid_argument ("stat", arg))
+    return (1);
+
+  if (stat (arg, &finfo) == -1)
+    @{
+      perror (arg);
+      return (1);
+    @}
+
+  printf ("Statistics for `%s':\n", arg);
+
+  printf ("%s has %d link%s, and is %d byte%s in length.\n", arg,
+          finfo.st_nlink,
+          (finfo.st_nlink == 1) ? "" : "s",
+          finfo.st_size,
+          (finfo.st_size == 1) ? "" : "s");
+  printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime));
+  printf ("      Last access at: %s", ctime (&finfo.st_atime));
+  printf ("    Last modified at: %s", ctime (&finfo.st_mtime));
+  return (0);
+@}
+
+com_delete (arg)
+     char *arg;
+@{
+  too_dangerous ("delete");
+  return (1);
+@}
+
+/* Print out help for ARG, or for all of the commands if ARG is
+   not present. */
+com_help (arg)
+     char *arg;
+@{
+  register int i;
+  int printed = 0;
+
+  for (i = 0; commands[i].name; i++)
+    @{
+      if (!*arg || (strcmp (arg, commands[i].name) == 0))
+        @{
+          printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
+          printed++;
+        @}
+    @}
+
+  if (!printed)
+    @{
+      printf ("No commands match `%s'.  Possibilties are:\n", arg);
+
+      for (i = 0; commands[i].name; i++)
+        @{
+          /* Print in six columns. */
+          if (printed == 6)
+            @{
+              printed = 0;
+              printf ("\n");
+            @}
+
+          printf ("%s\t", commands[i].name);
+          printed++;
+        @}
+
+      if (printed)
+        printf ("\n");
+    @}
+  return (0);
+@}
+
+/* Change to the directory ARG. */
+com_cd (arg)
+     char *arg;
+@{
+  if (chdir (arg) == -1)
+    @{
+      perror (arg);
+      return 1;
+    @}
+
+  com_pwd ("");
+  return (0);
+@}
+
+/* Print out the current working directory. */
+com_pwd (ignore)
+     char *ignore;
+@{
+  char dir[1024], *s;
+
+  s = getwd (dir);
+  if (s == 0)
+    @{
+      printf ("Error getting pwd: %s\n", dir);
+      return 1;
+    @}
+
+  printf ("Current directory is %s\n", dir);
+  return 0;
+@}
+
+/* The user wishes to quit using this program.  Just set DONE non-zero. */
+com_quit (arg)
+     char *arg;
+@{
+  done = 1;
+  return (0);
+@}
+
+/* Function which tells you that you can't do this. */
+too_dangerous (caller)
+     char *caller;
+@{
+  fprintf (stderr,
+           "%s: Too dangerous for me to distribute.  Write it yourself.\n",
+           caller);
+@}
+
+/* Return non-zero if ARG is a valid argument for CALLER, else print
+   an error message and return zero. */
+int
+valid_argument (caller, arg)
+     char *caller, *arg;
+@{
+  if (!arg || !*arg)
+    @{
+      fprintf (stderr, "%s: Argument required.\n", caller);
+      return (0);
+    @}
+
+  return (1);
+@}
+@end smallexample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/doc/rluser.texinfo	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,875 @@
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename rluser.info
+@comment %**end of header (This is for running Texinfo on a region.)
+@setchapternewpage odd
+
+@ignore
+This file documents the end user interface to the GNU command line
+editing features.  It is to be an appendix to manuals for programs which
+use these features.  There is a document entitled "readline.texinfo"
+which contains both end-user and programmer documentation for the GNU
+Readline Library.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Authored by Brian Fox and Chet Ramey.
+
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+Permission is granted to make and distribute verbatim copies of this manual
+provided the copyright notice and this permission notice are preserved on
+all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+GNU Copyright statement is available to the distributee, and provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ignore
+
+@comment If you are including this manual as an appendix, then set the
+@comment variable readline-appendix.
+
+@node Command Line Editing
+@chapter Command Line Editing
+
+This chapter describes the basic features of the GNU
+command line editing interface.
+
+@menu
+* Introduction and Notation::	Notation used in this text.
+* Readline Interaction::	The minimum set of commands for editing a line.
+* Readline Init File::		Customizing Readline from a user's view.
+* Bindable Readline Commands::	A description of most of the Readline commands
+				available for binding
+* Readline vi Mode::		A short description of how to make Readline
+				behave like the vi editor.
+@end menu
+
+@node Introduction and Notation
+@section Introduction to Line Editing
+
+The following paragraphs describe the notation used to represent
+keystrokes.
+
+The text @key{C-k} is read as `Control-K' and describes the character
+produced when the Control key is depressed and the @key{k} key is struck.
+
+The text @key{M-k} is read as `Meta-K' and describes the character
+produced when the meta key (if you have one) is depressed, and the @key{k}
+key is struck.  If you do not have a meta key, the identical keystroke
+can be generated by typing @key{ESC} @i{first}, and then typing @key{k}.
+Either process is known as @dfn{metafying} the @key{k} key.
+
+The text @key{M-C-k} is read as `Meta-Control-k' and describes the
+character produced by @dfn{metafying} @key{C-k}.
+
+In addition, several keys have their own names.  Specifically,
+@key{DEL}, @key{ESC}, @key{LFD}, @key{SPC}, @key{RET}, and @key{TAB} all
+stand for themselves when seen in this text, or in an init file
+(@pxref{Readline Init File}, for more info).
+
+@node Readline Interaction
+@section Readline Interaction
+@cindex interaction, readline
+
+Often during an interactive session you type in a long line of text,
+only to notice that the first word on the line is misspelled.  The
+Readline library gives you a set of commands for manipulating the text
+as you type it in, allowing you to just fix your typo, and not forcing
+you to retype the majority of the line.  Using these editing commands,
+you move the cursor to the place that needs correction, and delete or
+insert the text of the corrections.  Then, when you are satisfied with
+the line, you simply press @key{RETURN}.  You do not have to be at the
+end of the line to press @key{RETURN}; the entire line is accepted
+regardless of the location of the cursor within the line.
+
+@menu
+* Readline Bare Essentials::	The least you need to know about Readline.
+* Readline Movement Commands::	Moving about the input line.
+* Readline Killing Commands::	How to delete text, and how to get it back!
+* Readline Arguments::		Giving numeric arguments to commands.
+@end menu
+
+@node Readline Bare Essentials
+@subsection Readline Bare Essentials
+
+In order to enter characters into the line, simply type them.  The typed
+character appears where the cursor was, and then the cursor moves one
+space to the right.  If you mistype a character, you can use your
+erase character to back up and delete the mistyped character.
+
+Sometimes you may miss typing a character that you wanted to type, and
+not notice your error until you have typed several other characters.  In
+that case, you can type @key{C-b} to move the cursor to the left, and then
+correct your mistake.  Afterwards, you can move the cursor to the right
+with @key{C-f}.
+
+When you add text in the middle of a line, you will notice that characters
+to the right of the cursor are `pushed over' to make room for the text
+that you have inserted.  Likewise, when you delete text behind the cursor,
+characters to the right of the cursor are `pulled back' to fill in the
+blank space created by the removal of the text.  A list of the basic bare
+essentials for editing the text of an input line follows.
+
+@table @asis
+@item @key{C-b}
+Move back one character.
+@item @key{C-f}
+Move forward one character.
+@item @key{DEL}
+Delete the character to the left of the cursor.
+@item @key{C-d}
+Delete the character underneath the cursor.
+@item @w{Printing characters}
+Insert the character into the line at the cursor.
+@item @key{C-_}
+Undo the last thing that you did.  You can undo all the way back to an
+empty line.
+@end table
+
+@node Readline Movement Commands
+@subsection Readline Movement Commands
+
+
+The above table describes the most basic possible keystrokes that you need
+in order to do editing of the input line.  For your convenience, many
+other commands have been added in addition to @key{C-b}, @key{C-f},
+@key{C-d}, and @key{DEL}.  Here are some commands for moving more rapidly
+about the line.
+
+@table @key
+@item C-a
+Move to the start of the line.
+@item C-e
+Move to the end of the line.
+@item M-f
+Move forward a word.
+@item M-b
+Move backward a word.
+@item C-l
+Clear the screen, reprinting the current line at the top.
+@end table
+
+Notice how @key{C-f} moves forward a character, while @key{M-f} moves
+forward a word.  It is a loose convention that control keystrokes
+operate on characters while meta keystrokes operate on words.
+
+@node Readline Killing Commands
+@subsection Readline Killing Commands
+
+@cindex Killing text
+@cindex Yanking text
+
+@dfn{Killing} text means to delete the text from the line, but to save
+it away for later use, usually by @dfn{yanking} (re-inserting)
+it back into the line.
+If the description for a command says that it `kills' text, then you can
+be sure that you can get the text back in a different (or the same)
+place later.
+
+When you use a kill command, the text is saved in a @dfn{kill-ring}.
+Any number of consecutive kills save all of the killed text together, so
+that when you yank it back, you get it all.  The kill
+ring is not line specific; the text that you killed on a previously
+typed line is available to be yanked back later, when you are typing
+another line.
+@cindex Kill ring
+
+Here is the list of commands for killing text.
+
+@table @key
+@item C-k
+Kill the text from the current cursor position to the end of the line.
+
+@item M-d
+Kill from the cursor to the end of the current word, or if between
+words, to the end of the next word.
+
+@item M-DEL
+Kill from the cursor the start of the previous word, or if between
+words, to the start of the previous word.
+
+@item C-w
+Kill from the cursor to the previous whitespace.  This is different than
+@key{M-DEL} because the word boundaries differ.
+
+@end table
+
+And, here is how to @dfn{yank} the text back into the line.  Yanking
+means to copy the most-recently-killed text from the kill buffer.
+
+@table @key
+@item C-y
+Yank the most recently killed text back into the buffer at the cursor.
+
+@item M-y
+Rotate the kill-ring, and yank the new top.  You can only do this if
+the prior command is @key{C-y} or @key{M-y}.
+@end table
+
+@node Readline Arguments
+@subsection Readline Arguments
+
+You can pass numeric arguments to Readline commands.  Sometimes the
+argument acts as a repeat count, other times it is the @i{sign} of the
+argument that is significant.  If you pass a negative argument to a
+command which normally acts in a forward direction, that command will
+act in a backward direction.  For example, to kill text back to the
+start of the line, you might type @key{M--} @key{C-k}.
+
+The general way to pass numeric arguments to a command is to type meta
+digits before the command.  If the first `digit' you type is a minus
+sign (@key{-}), then the sign of the argument will be negative.  Once
+you have typed one meta digit to get the argument started, you can type
+the remainder of the digits, and then the command.  For example, to give
+the @key{C-d} command an argument of 10, you could type @key{M-1 0 C-d}.
+
+
+@node Readline Init File
+@section Readline Init File
+
+Although the Readline library comes with a set of Emacs-like
+keybindings installed by default,
+it is possible that you would like to use a different set
+of keybindings.  You can customize programs that use Readline by putting
+commands in an @dfn{init} file in your home directory.  The name of this
+@ifset BashFeatures
+file is taken from the value of the shell variable @code{INPUTRC}.  If
+@end ifset
+@ifclear BashFeatures
+file is taken from the value of the environment variable @code{INPUTRC}.  If
+@end ifclear
+that variable is unset, the default is @file{~/.inputrc}.
+
+When a program which uses the Readline library starts up, the
+init file is read, and the key bindings are set.
+
+In addition, the @code{C-x C-r} command re-reads this init file, thus
+incorporating any changes that you might have made to it.
+
+@menu
+* Readline Init Syntax::	Syntax for the commands in the inputrc file.
+* Conditional Init Constructs::	Conditional key bindings in the inputrc file.
+@end menu
+
+@node Readline Init Syntax
+@subsection Readline Init Syntax
+
+There are only a few basic constructs allowed in the
+Readline init file.  Blank lines are ignored.
+Lines beginning with a @key{#} are comments.
+Lines beginning with a @key{$} indicate conditional
+constructs (@pxref{Conditional Init Constructs}).  Other lines
+denote variable settings and key bindings.
+
+@table @asis
+@item Variable Settings
+You can change the state of a few variables in Readline by
+using the @code{set} command within the init file.  Here is how you
+would specify that you wish to use @code{vi} line editing commands:
+
+@example
+set editing-mode vi
+@end example
+
+Right now, there are only a few variables which can be set;
+so few, in fact, that we just list them here:
+
+@table @code
+
+@item editing-mode
+@vindex editing-mode
+The @code{editing-mode} variable controls which editing mode you are
+using.  By default, Readline starts up in Emacs editing mode, where
+the keystrokes are most similar to Emacs.  This variable can be
+set to either @code{emacs} or @code{vi}.
+
+@item horizontal-scroll-mode
+@vindex horizontal-scroll-mode
+This variable can be set to either @code{On} or @code{Off}.  Setting it
+to @code{On} means that the text of the lines that you edit will scroll
+horizontally on a single screen line when they are longer than the width
+of the screen, instead of wrapping onto a new screen line.  By default,
+this variable is set to @code{Off}.
+
+@item mark-modified-lines
+@vindex mark-modified-lines
+This variable, when set to @code{On}, says to display an asterisk
+(@samp{*}) at the start of history lines which have been modified.
+This variable is @code{off} by default.
+
+@item bell-style
+@vindex bell-style
+Controls what happens when Readline wants to ring the terminal bell.
+If set to @code{none}, Readline never rings the bell.  If set to
+@code{visible}, Readline uses a visible bell if one is available.
+If set to @code{audible} (the default), Readline attempts to ring
+the terminal's bell.
+
+@item comment-begin
+@vindex comment-begin
+The string to insert at the beginning of the line when the
+@code{vi-comment} command is executed.  The default value
+is @code{"#"}.
+
+@item meta-flag
+@vindex meta-flag
+If set to @code{on}, Readline will enable eight-bit input (it
+will not strip the eighth bit from the characters it reads),
+regardless of what the terminal claims it can support.  The
+default value is @code{off}.
+
+@item convert-meta
+@vindex convert-meta
+If set to @code{on}, Readline will convert characters with the
+eigth bit set to an ASCII key sequence by stripping the eigth
+bit and prepending an @key{ESC} character, converting them to a
+meta-prefixed key sequence.  The default value is @code{on}.
+
+@item output-meta
+@vindex output-meta
+If set to @code{on}, Readline will display characters with the
+eighth bit set directly rather than as a meta-prefixed escape
+sequence.  The default is @code{off}.
+
+@item completion-query-items
+@vindex completion-query-items
+The number of possible completions that determines when the user is
+asked whether he wants to see the list of possibilities.  If the
+number of possible completions is greater than this value,
+Readline will ask the user whether or not he wishes to view
+them; otherwise, they are simply listed.  The default limit is
+@code{100}.
+
+@item keymap
+@vindex keymap
+Sets Readline's idea of the current keymap for key binding commands.
+Acceptable @code{keymap} names are
+@code{emacs},
+@code{emacs-standard},
+@code{emacs-meta},
+@code{emacs-ctlx},
+@code{vi},
+@code{vi-move},
+@code{vi-command}, and
+@code{vi-insert}.
+@code{vi} is equivalent to @code{vi-command}; @code{emacs} is
+equivalent to @code{emacs-standard}.  The default value is @code{emacs}.
+The value of the @code{editing-mode} variable also affects the
+default keymap.
+
+@item show-all-if-ambiguous
+@vindex show-all-if-ambiguous
+This alters the default behavior of the completion functions.  If
+set to @code{on}, 
+words which have more than one possible completion cause the
+matches to be listed immediately instead of ringing the bell.
+The default value is @code{off}.
+
+@item expand-tilde
+@vindex expand-tilde
+If set to @code{on}, tilde expansion is performed when Readline
+attempts word completion.  The default is @code{off}.
+
+@end table
+
+@item Key Bindings
+The syntax for controlling key bindings in the init file is
+simple.  First you have to know the name of the command that you
+want to change.  The following pages contain tables of the command name,
+the default keybinding, and a short description of what the command
+does.
+
+Once you know the name of the command, simply place the name of the key
+you wish to bind the command to, a colon, and then the name of the
+command on a line in the init file.  The name of the key
+can be expressed in different ways, depending on which is most
+comfortable for you.
+
+@table @asis
+@item @w{@var{keyname}: @var{function-name} or @var{macro}}
+@var{keyname} is the name of a key spelled out in English.  For example:
+@example
+Control-u: universal-argument
+Meta-Rubout: backward-kill-word
+Control-o: ">&output"
+@end example
+
+In the above example, @samp{C-u} is bound to the function
+@code{universal-argument}, and @samp{C-o} is bound to run the macro
+expressed on the right hand side (that is, to insert the text
+@samp{>&output} into the line).
+
+@item @w{"@var{keyseq}": @var{function-name} or @var{macro}}
+@var{keyseq} differs from @var{keyname} above in that strings
+denoting an entire key sequence can be specified, by placing
+the key sequence in double quotes.  Some GNU Emacs style key
+escapes can be used, as in the following example, but the
+special character names are not recognized.
+
+@example
+"\C-u": universal-argument
+"\C-x\C-r": re-read-init-file
+"\e[11~": "Function Key 1"
+@end example
+
+In the above example, @samp{C-u} is bound to the function
+@code{universal-argument} (just as it was in the first example),
+@samp{C-x C-r} is bound to the function @code{re-read-init-file}, and
+@samp{ESC [ 1 1 ~} is bound to insert the text @samp{Function Key 1}.
+The following escape sequences are available when specifying key
+sequences:
+
+@table @code
+@item @kbd{\C-}
+control prefix
+@item @kbd{\M-}
+meta prefix
+@item @kbd{\e}
+an escape character
+@item @kbd{\\}
+backslash
+@item @kbd{\"}
+@key{"}
+@item @kbd{\'}
+@key{'}
+@end table
+
+When entering the text of a macro, single or double quotes should
+be used to indicate a macro definition.  Unquoted text
+is assumed to be a function name.  Backslash
+will quote any character in the macro text, including @key{"}
+and @key{'}.
+For example, the following binding will make @kbd{C-x \}
+insert a single @key{\} into the line:
+@example
+"\C-x\\": "\\"
+@end example
+
+@end table
+@end table
+
+@node Conditional Init Constructs
+@subsection Conditional Init Constructs
+
+Readline implements a facility similar in spirit to the conditional
+compilation features of the C preprocessor which allows key
+bindings and variable settings to be performed as the result
+of tests.  There are three parser directives used.
+
+@ftable @code
+@item $if
+The @code{$if} construct allows bindings to be made based on the
+editing mode, the terminal being used, or the application using
+Readline.  The text of the test extends to the end of the line;
+no characters are required to isolate it.
+
+@table @code
+@item mode
+The @code{mode=} form of the @code{$if} directive is used to test
+whether Readline is in @code{emacs} or @code{vi} mode.
+This may be used in conjunction
+with the @samp{set keymap} command, for instance, to set bindings in
+the @code{emacs-standard} and @code{emacs-ctlx} keymaps only if
+Readline is starting out in @code{emacs} mode.
+
+@item term
+The @code{term=} form may be used to include terminal-specific
+key bindings, perhaps to bind the key sequences output by the
+terminal's function keys.  The word on the right side of the
+@samp{=} is tested against the full name of the terminal and the
+portion of the terminal name before the first @samp{-}.  This
+allows @var{sun} to match both @var{sun} and @var{sun-cmd},
+for instance.
+
+@item application
+The @var{application} construct is used to include
+application-specific settings.  Each program using the Readline
+library sets the @var{application name}, and you can test for it. 
+This could be used to bind key sequences to functions useful for
+a specific program.  For instance, the following command adds a
+key sequence that quotes the current or previous word in Bash:
+@example
+$if bash
+# Quote the current or previous word
+"\C-xq": "\eb\"\ef\""
+$endif
+@end example
+@end table
+
+@item $endif
+This command, as you saw in the previous example, terminates an
+@code{$if} command.
+
+@item $else
+Commands in this branch of the @code{$if} directive are executed if
+the test fails.
+@end ftable
+
+@node Bindable Readline Commands
+@section Bindable Readline Commands
+
+@menu
+* Commands For Moving::		Moving about the line.
+* Commands For History::	Getting at previous lines.
+* Commands For Text::		Commands for changing text.
+* Commands For Killing::	Commands for killing and yanking.
+* Numeric Arguments::		Specifying numeric arguments, repeat counts.
+* Commands For Completion::	Getting Readline to do the typing for you.
+* Keyboard Macros::		Saving and re-executing typed characters
+* Miscellaneous Commands::	Other miscellaneous commands.
+@end menu
+
+@node Commands For Moving
+@subsection Commands For Moving
+@ftable @code
+@item beginning-of-line (C-a)
+Move to the start of the current line.
+
+@item end-of-line (C-e)
+Move to the end of the line.
+
+@item forward-char (C-f)
+Move forward a character.
+
+@item backward-char (C-b)
+Move back a character.
+
+@item forward-word (M-f)
+Move forward to the end of the next word.  Words are composed of
+letters and digits.
+
+@item backward-word (M-b)
+Move back to the start of this, or the previous, word.  Words are
+composed of letters and digits.
+
+@item clear-screen (C-l)
+Clear the screen and redraw the current line,
+leaving the current line at the top of the screen.
+
+@item redraw-current-line ()
+Refresh the current line.  By default, this is unbound.
+
+@end ftable
+
+@node Commands For History
+@subsection Commands For Manipulating The History
+
+@ftable @code
+@item accept-line (Newline, Return)
+@ifset BashFeatures
+Accept the line regardless of where the cursor is.  If this line is
+non-empty, add it to the history list according to the setting of
+the @code{HISTCONTROL} variable.  If this line was a history
+line, then restore the history line to its original state.
+@end ifset
+@ifclear BashFeatures
+Accept the line regardless of where the cursor is.  If this line is
+non-empty, add it to the history list.  If this line was a history
+line, then restore the history line to its original state.
+@end ifclear
+
+@item previous-history (C-p)
+Move `up' through the history list.
+
+@item next-history (C-n)
+Move `down' through the history list.
+
+@item beginning-of-history (M-<)
+Move to the first line in the history.
+
+@item end-of-history (M->)
+Move to the end of the input history, i.e., the line you are entering.
+
+@item reverse-search-history (C-r)
+Search backward starting at the current line and moving `up' through
+the history as necessary.  This is an incremental search.
+
+@item forward-search-history (C-s)
+Search forward starting at the current line and moving `down' through
+the the history as necessary.  This is an incremental search.
+
+@item non-incremental-reverse-search-history (M-p)
+Search backward starting at the current line and moving `up'
+through the history as necessary using a non-incremental search
+for a string supplied by the user.
+
+@item non-incremental-forward-search-history (M-n)
+Search forward starting at the current line and moving `down'
+through the the history as necessary using a non-incremental search
+for a string supplied by the user.
+
+@item history-search-forward ()
+Search forward through the history for the string of characters
+between the start of the current line and the current point.  This
+is a non-incremental search.  By default, this command is unbound.
+
+@item history-search-backward ()
+Search backward through the history for the string of characters
+between the start of the current line and the current point.  This
+is a non-incremental search.  By default, this command is unbound.
+
+@item yank-nth-arg (M-C-y)
+Insert the first argument to the previous command (usually
+the second word on the previous line).  With an argument @var{n},
+insert the @var{n}th word from the previous command (the words
+in the previous command begin with word 0).  A negative argument
+inserts the @var{n}th word from the end of the previous command.
+
+@item yank-last-arg (M-., M-_)
+Insert last argument to the previous command (the last word on the
+previous line).  With an
+argument, behave exactly like @code{yank-nth-arg}.
+
+@end ftable
+
+@node Commands For Text
+@subsection Commands For Changing Text
+
+@ftable @code
+@item delete-char (C-d)
+Delete the character under the cursor.  If the cursor is at the
+beginning of the line, there are no characters in the line, and
+the last character typed was not C-d, then return EOF.
+
+@item backward-delete-char (Rubout)
+Delete the character behind the cursor.  A numeric arg says to kill
+the characters instead of deleting them.
+
+@item quoted-insert (C-q, C-v)
+Add the next character that you type to the line verbatim.  This is
+how to insert key sequences like @key{C-q}, for example.
+
+@item tab-insert (M-TAB)
+Insert a tab character.
+
+@item self-insert (a, b, A, 1, !, ...)
+Insert yourself.
+
+@item transpose-chars (C-t)
+Drag the character before the cursor forward over
+the character at the cursor, moving the
+cursor forward as well.  If the insertion point
+is at the end of the line, then this
+transposes the last two characters of the line.
+Negative argumentss don't work.
+
+@item transpose-words (M-t)
+Drag the word behind the cursor past the word in front of the cursor
+moving the cursor over that word as well.
+
+@item upcase-word (M-u)
+Uppercase the current (or following) word.  With a negative argument,
+do the previous word, but do not move the cursor.
+
+@item downcase-word (M-l)
+Lowercase the current (or following) word.  With a negative argument,
+do the previous word, but do not move the cursor.
+
+@item capitalize-word (M-c)
+Capitalize the current (or following) word.  With a negative argument,
+do the previous word, but do not move the cursor.
+
+@end ftable
+
+@node Commands For Killing
+@subsection Killing And Yanking
+
+@ftable @code
+
+@item kill-line (C-k)
+Kill the text from the current cursor position to the end of the line.
+
+@item backward-kill-line (C-x Rubout)
+Kill backward to the beginning of the line.
+
+@item unix-line-discard (C-u)
+Kill backward from the cursor to the beginning of the current line.
+Save the killed text on the kill-ring.
+
+@item kill-whole-line ()
+Kill all characters on the current line, no matter where the
+cursor is.  By default, this is unbound.
+
+@item kill-word (M-d)
+Kill from the cursor to the end of the current word, or if between
+words, to the end of the next word.  Word boundaries are the same
+as @code{forward-word}.
+
+@item backward-kill-word (M-DEL)
+Kill the word behind the cursor.  Word boundaries are the same
+as @code{backward-word}.
+
+@item unix-word-rubout (C-w)
+Kill the word behind the cursor, using white space as a word
+boundary.  The killed text is saved on the kill-ring.
+
+@item delete-horizontal-space ()
+Delete all spaces and tabs around point.  By default, this is unbound.
+
+@item yank (C-y)
+Yank the top of the kill ring into the buffer at the current
+cursor position.
+
+@item yank-pop (M-y)
+Rotate the kill-ring, and yank the new top.  You can only do this if
+the prior command is yank or yank-pop.
+@end ftable
+
+@node Numeric Arguments
+@subsection Specifying Numeric Arguments
+@ftable @code
+
+@item digit-argument (M-0, M-1, ... M--)
+Add this digit to the argument already accumulating, or start a new
+argument.  M-- starts a negative argument.
+
+@item universal-argument ()
+Each time this is executed, the argument count is multiplied by four.
+The argument count is initially one, so executing this function the
+first time makes the argument count four.  By default, this is not
+bound to a key.
+@end ftable
+
+@node Commands For Completion
+@subsection Letting Readline Type For You
+
+@ftable @code
+@item complete (TAB)
+Attempt to do completion on the text before the cursor.  This is
+application-specific.  Generally, if you are typing a filename
+argument, you can do filename completion; if you are typing a command,
+you can do command completion, if you are typing in a symbol to GDB, you
+can do symbol name completion, if you are typing in a variable to Bash,
+you can do variable name completion, and so on.
+@ifset BashFeatures
+See the Bash manual page for a complete list of available completion
+functions.
+@end ifset
+
+@item possible-completions (M-?)
+List the possible completions of the text before the cursor.
+
+@item insert-completions ()
+Insert all completions of the text before point that would have
+been generated by @code{possible-completions}.  By default, this
+is not bound to a key.
+
+@end ftable
+
+@node Keyboard Macros
+@subsection Keyboard Macros
+@ftable @code
+
+@item start-kbd-macro (C-x ()
+Begin saving the characters typed into the current keyboard macro.
+
+@item end-kbd-macro (C-x ))
+Stop saving the characters typed into the current keyboard macro
+and save the definition.
+
+@item call-last-kbd-macro (C-x e)
+Re-execute the last keyboard macro defined, by making the characters
+in the macro appear as if typed at the keyboard.
+
+@end ftable
+
+@node Miscellaneous Commands
+@subsection Some Miscellaneous Commands
+@ftable @code
+
+@item re-read-init-file (C-x C-r)
+Read in the contents of your init file, and incorporate
+any bindings or variable assignments found there.
+
+@item abort (C-g)
+Abort the current editing command and
+ring the terminal's bell (subject to the setting of
+@code{bell-style}).
+
+@item do-uppercase-version (M-a, M-b, ...)
+Run the command that is bound to the corresoponding uppercase
+character.
+
+@item prefix-meta (ESC)
+Make the next character that you type be metafied.  This is for people
+without a meta key.  Typing @samp{ESC f} is equivalent to typing
+@samp{M-f}.
+
+@item undo (C-_, C-x C-u)
+Incremental undo, separately remembered for each line.
+
+@item revert-line (M-r)
+Undo all changes made to this line.  This is like typing the @code{undo}
+command enough times to get back to the beginning.
+
+@item tilde-expand (M-~)
+Perform tilde expansion on the current word.
+
+@item dump-functions ()
+Print all of the functions and their key bindings to the
+readline output stream.  If a numeric argument is supplied,
+the output is formatted in such a way that it can be made part
+of an @var{inputrc} file.
+
+@ifset BashFeatures
+@item display-shell-version (C-x C-v)
+Display version information about the current instance of Bash.
+
+@item shell-expand-line (M-C-e)
+Expand the line the way the shell does when it reads it.  This
+performs alias and history expansion as well as all of the shell
+word expansions.
+
+@item history-expand-line (M-^)
+Perform history expansion on the current line.
+
+@item insert-last-argument (M-., M-_)
+A synonym for @code{yank-last-arg}.
+
+@item operate-and-get-next (C-o)
+Accept the current line for execution and fetch the next line
+relative to the current line from the history for editing.  Any
+argument is ignored.
+
+@item emacs-editing-mode (C-e)
+When in @code{vi} editing mode, this causes a switch back to
+emacs editing mode, as if the command @code{set -o emacs} had
+been executed.
+
+@end ifset
+
+@end ftable
+
+@node Readline vi Mode
+@section Readline vi Mode
+
+While the Readline library does not have a full set of @code{vi}
+editing functions, it does contain enough to allow simple editing
+of the line.  The Readline @code{vi} mode behaves as specified in
+the Posix 1003.2 standard.
+
+@ifset BashFeatures
+In order to switch interactively between @code{Emacs} and @code{Vi}
+editing modes, use the @code{set -o emacs} and @code{set -o vi}
+commands (@pxref{The Set Builtin}).
+@end ifset
+@ifclear BashFeatures
+In order to switch interactively between @code{Emacs} and @code{Vi}
+editing modes, use the command M-C-j (toggle-editing-mode).
+@end ifclear
+The Readline default is @code{emacs} mode.
+
+When you enter a line in @code{vi} mode, you are already placed in
+`insertion' mode, as if you had typed an @samp{i}.  Pressing @key{ESC}
+switches you into `command' mode, where you can edit the text of the
+line with the standard @code{vi} movement keys, move to previous
+history lines with @samp{k}, and following lines with @samp{j}, and
+so forth.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/doc/texindex.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,1666 @@
+/* Prepare TeX index dribble output into an actual index.
+
+   Version 1.45
+
+   Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include "getopt.h"
+#include "bashansi.h"
+
+#if !defined (errno)
+extern int errno;
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#else /* !HAVE_UNISTD_H */
+extern long lseek ();
+#endif /* !HAVE_UNISTD_H */
+
+extern char *mktemp ();
+
+#if !defined (HAVE_STRERROR)
+extern int sys_nerr;
+extern char *sys_errlist[];
+#endif
+
+#include <sys/types.h>
+
+#if defined (_AIX) || !defined (_POSIX_VERSION)
+#  include <sys/file.h>
+#endif
+
+#include <fcntl.h>
+
+#define TI_NO_ERROR 0
+#define TI_FATAL_ERROR 1
+
+#if !defined (SEEK_SET)
+#  define SEEK_SET 0
+#  define SEEK_CUR 1
+#  define SEEK_END 2
+#endif /* !SEEK_SET */
+
+/* When sorting in core, this structure describes one line
+   and the position and length of its first keyfield.  */
+struct lineinfo
+{
+  char *text;		/* The actual text of the line. */
+  union {
+    char *text;		/* The start of the key (for textual comparison). */
+    long number;	/* The numeric value (for numeric comparison). */
+  } key;
+  long keylen;		/* Length of KEY field. */
+};
+
+/* This structure describes a field to use as a sort key. */
+struct keyfield
+{
+  int startwords;	/* Number of words to skip. */
+  int startchars;	/* Number of additional chars to skip. */
+  int endwords;		/* Number of words to ignore at end. */
+  int endchars;		/* Ditto for characters of last word. */
+  char ignore_blanks;	/* Non-zero means ignore spaces and tabs. */
+  char fold_case;	/* Non-zero means case doesn't matter. */
+  char reverse;		/* Non-zero means compare in reverse order. */
+  char numeric;		/* Non-zeros means field is ASCII numeric. */
+  char positional;	/* Sort according to file position. */
+  char braced;		/* Count balanced-braced groupings as fields. */
+};
+
+/* Vector of keyfields to use. */
+struct keyfield keyfields[3];
+
+/* Number of keyfields stored in that vector.  */
+int num_keyfields = 3;
+
+/* Vector of input file names, terminated with a null pointer. */
+char **infiles;
+
+/* Vector of corresponding output file names, or NULL, meaning default it
+   (add an `s' to the end). */
+char **outfiles;
+
+/* Length of `infiles'. */
+int num_infiles;
+
+/* Pointer to the array of pointers to lines being sorted. */
+char **linearray;
+
+/* The allocated length of `linearray'. */
+long nlines;
+
+/* Directory to use for temporary files.  On Unix, it ends with a slash.  */
+char *tempdir;
+
+/* Start of filename to use for temporary files.  */
+char *tempbase;
+
+/* Number of last temporary file.  */
+int tempcount;
+
+/* Number of last temporary file already deleted.
+   Temporary files are deleted by `flush_tempfiles' in order of creation.  */
+int last_deleted_tempcount;
+
+/* During in-core sort, this points to the base of the data block
+   which contains all the lines of data.  */
+char *text_base;
+
+/* Additional command switches .*/
+
+/* Nonzero means do not delete tempfiles -- for debugging. */
+int keep_tempfiles;
+
+/* The name this program was run with. */
+char *program_name;
+
+/* Forward declarations of functions in this file. */
+
+void decode_command ();
+void sort_in_core ();
+void sort_offline ();
+char **parsefile ();
+char *find_field ();
+char *find_pos ();
+long find_value ();
+char *find_braced_pos ();
+char *find_braced_end ();
+void writelines ();
+int compare_field ();
+int compare_full ();
+long readline ();
+int merge_files ();
+int merge_direct ();
+void pfatal_with_name ();
+void fatal ();
+void error ();
+void *xmalloc (), *xrealloc ();
+char *concat ();
+char *maketempname ();
+void flush_tempfiles ();
+char *tempcopy ();
+
+#define MAX_IN_CORE_SORT 500000
+
+void
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int i;
+
+  tempcount = 0;
+  last_deleted_tempcount = 0;
+  program_name = argv[0];
+
+  /* Describe the kind of sorting to do. */
+  /* The first keyfield uses the first braced field and folds case. */
+  keyfields[0].braced = 1;
+  keyfields[0].fold_case = 1;
+  keyfields[0].endwords = -1;
+  keyfields[0].endchars = -1;
+
+  /* The second keyfield uses the second braced field, numerically. */
+  keyfields[1].braced = 1;
+  keyfields[1].numeric = 1;
+  keyfields[1].startwords = 1;
+  keyfields[1].endwords = -1;
+  keyfields[1].endchars = -1;
+
+  /* The third keyfield (which is ignored while discarding duplicates)
+     compares the whole line. */
+  keyfields[2].endwords = -1;
+  keyfields[2].endchars = -1;
+
+  decode_command (argc, argv);
+
+  tempbase = mktemp (concat ("txiXXXXXX", "", ""));
+
+  /* Process input files completely, one by one.  */
+
+  for (i = 0; i < num_infiles; i++)
+    {
+      int desc;
+      long ptr;
+      char *outfile;
+
+      desc = open (infiles[i], O_RDONLY, 0);
+      if (desc < 0)
+	pfatal_with_name (infiles[i]);
+      lseek (desc, 0L, SEEK_END);
+      ptr = lseek (desc, 0L, SEEK_CUR);
+
+      close (desc);
+
+      outfile = outfiles[i];
+      if (!outfile)
+	{
+	  outfile = concat (infiles[i], "s", "");
+	}
+
+      if (ptr < MAX_IN_CORE_SORT)
+	/* Sort a small amount of data. */
+	sort_in_core (infiles[i], ptr, outfile);
+      else
+	sort_offline (infiles[i], ptr, outfile);
+    }
+
+  flush_tempfiles (tempcount);
+  exit (TI_NO_ERROR);
+}
+
+void
+usage ()
+{
+  fprintf (stderr, "\
+Usage: %s [-k] infile [-o outfile] ...\n", program_name);
+  exit (1);
+}
+
+/* Decode the command line arguments to set the parameter variables
+   and set up the vector of keyfields and the vector of input files. */
+
+void
+decode_command (argc, argv)
+     int argc;
+     char **argv;
+{
+  int optc;
+  char **ip;
+  char **op;
+
+  /* Store default values into parameter variables. */
+
+  tempdir = getenv ("TMPDIR");
+  if (tempdir == NULL)
+    tempdir = "/tmp/";
+  else
+    tempdir = concat (tempdir, "/", "");
+
+  keep_tempfiles = 0;
+
+  /* Allocate ARGC input files, which must be enough.  */
+
+  infiles = (char **) xmalloc (argc * sizeof (char *));
+  outfiles = (char **) xmalloc (argc * sizeof (char *));
+  ip = infiles;
+  op = outfiles;
+
+  while ((optc = getopt (argc, argv, "-ko:")) != EOF)
+    {
+      switch (optc)
+	{
+	case 1:		/* Non-option filename. */
+	  *ip++ = optarg;
+	  *op++ = NULL;
+	  break;
+
+	case 'k':
+	  keep_tempfiles = 1;
+	  break;
+
+	case 'o':
+	  if (op > outfiles)
+	    *(op - 1) = optarg;
+	  break;
+
+	default:
+	  usage ();
+	}
+    }
+
+  /* Record number of keyfields and terminate list of filenames. */
+  num_infiles = ip - infiles;
+  *ip = 0;
+  if (num_infiles == 0)
+    usage ();
+}
+
+/* Return a name for a temporary file. */
+
+char *
+maketempname (count)
+     int count;
+{
+  char tempsuffix[10];
+  sprintf (tempsuffix, "%d", count);
+  return concat (tempdir, tempbase, tempsuffix);
+}
+
+/* Delete all temporary files up to TO_COUNT. */
+
+void
+flush_tempfiles (to_count)
+     int to_count;
+{
+  if (keep_tempfiles)
+    return;
+  while (last_deleted_tempcount < to_count)
+    unlink (maketempname (++last_deleted_tempcount));
+}
+
+/* Copy the input file open on IDESC into a temporary file
+   and return the temporary file name. */
+
+#define BUFSIZE 1024
+
+char *
+tempcopy (idesc)
+     int idesc;
+{
+  char *outfile = maketempname (++tempcount);
+  int odesc;
+  char buffer[BUFSIZE];
+
+  odesc = open (outfile, O_WRONLY | O_CREAT, 0666);
+
+  if (odesc < 0)
+    pfatal_with_name (outfile);
+
+  while (1)
+    {
+      int nread = read (idesc, buffer, BUFSIZE);
+      write (odesc, buffer, nread);
+      if (!nread)
+	break;
+    }
+
+  close (odesc);
+
+  return outfile;
+}
+
+/* Compare LINE1 and LINE2 according to the specified set of keyfields. */
+
+int
+compare_full (line1, line2)
+     char **line1, **line2;
+{
+  int i;
+
+  /* Compare using the first keyfield;
+     if that does not distinguish the lines, try the second keyfield;
+     and so on. */
+
+  for (i = 0; i < num_keyfields; i++)
+    {
+      long length1, length2;
+      char *start1 = find_field (&keyfields[i], *line1, &length1);
+      char *start2 = find_field (&keyfields[i], *line2, &length2);
+      int tem = compare_field (&keyfields[i], start1, length1, *line1 - text_base,
+			       start2, length2, *line2 - text_base);
+      if (tem)
+	{
+	  if (keyfields[i].reverse)
+	    return -tem;
+	  return tem;
+	}
+    }
+
+  return 0;			/* Lines match exactly. */
+}
+
+/* Compare LINE1 and LINE2, described by structures
+   in which the first keyfield is identified in advance.
+   For positional sorting, assumes that the order of the lines in core
+   reflects their nominal order.  */
+
+int
+compare_prepared (line1, line2)
+     struct lineinfo *line1, *line2;
+{
+  int i;
+  int tem;
+  char *text1, *text2;
+
+  /* Compare using the first keyfield, which has been found for us already. */
+  if (keyfields->positional)
+    {
+      if (line1->text - text_base > line2->text - text_base)
+	tem = 1;
+      else
+	tem = -1;
+    }
+  else if (keyfields->numeric)
+    tem = line1->key.number - line2->key.number;
+  else
+    tem = compare_field (keyfields, line1->key.text, line1->keylen, 0,
+			 line2->key.text, line2->keylen, 0);
+  if (tem)
+    {
+      if (keyfields->reverse)
+	return -tem;
+      return tem;
+    }
+
+  text1 = line1->text;
+  text2 = line2->text;
+
+  /* Compare using the second keyfield;
+     if that does not distinguish the lines, try the third keyfield;
+     and so on. */
+
+  for (i = 1; i < num_keyfields; i++)
+    {
+      long length1, length2;
+      char *start1 = find_field (&keyfields[i], text1, &length1);
+      char *start2 = find_field (&keyfields[i], text2, &length2);
+      int tem = compare_field (&keyfields[i], start1, length1, text1 - text_base,
+			       start2, length2, text2 - text_base);
+      if (tem)
+	{
+	  if (keyfields[i].reverse)
+	    return -tem;
+	  return tem;
+	}
+    }
+
+  return 0;			/* Lines match exactly. */
+}
+
+/* Like compare_full but more general.
+   You can pass any strings, and you can say how many keyfields to use.
+   POS1 and POS2 should indicate the nominal positional ordering of
+   the two lines in the input.  */
+
+int
+compare_general (str1, str2, pos1, pos2, use_keyfields)
+     char *str1, *str2;
+     long pos1, pos2;
+     int use_keyfields;
+{
+  int i;
+
+  /* Compare using the first keyfield;
+     if that does not distinguish the lines, try the second keyfield;
+     and so on. */
+
+  for (i = 0; i < use_keyfields; i++)
+    {
+      long length1, length2;
+      char *start1 = find_field (&keyfields[i], str1, &length1);
+      char *start2 = find_field (&keyfields[i], str2, &length2);
+      int tem = compare_field (&keyfields[i], start1, length1, pos1,
+			       start2, length2, pos2);
+      if (tem)
+	{
+	  if (keyfields[i].reverse)
+	    return -tem;
+	  return tem;
+	}
+    }
+
+  return 0;			/* Lines match exactly. */
+}
+
+/* Find the start and length of a field in STR according to KEYFIELD.
+   A pointer to the starting character is returned, and the length
+   is stored into the int that LENGTHPTR points to.  */
+
+char *
+find_field (keyfield, str, lengthptr)
+     struct keyfield *keyfield;
+     char *str;
+     long *lengthptr;
+{
+  char *start;
+  char *end;
+  char *(*fun) ();
+
+  if (keyfield->braced)
+    fun = find_braced_pos;
+  else
+    fun = find_pos;
+
+  start = (*fun) (str, keyfield->startwords, keyfield->startchars,
+		  keyfield->ignore_blanks);
+  if (keyfield->endwords < 0)
+    {
+      if (keyfield->braced)
+	end = find_braced_end (start);
+      else
+	{
+	  end = start;
+	  while (*end && *end != '\n')
+	    end++;
+	}
+    }
+  else
+    {
+      end = (*fun) (str, keyfield->endwords, keyfield->endchars, 0);
+      if (end - str < start - str)
+	end = start;
+    }
+  *lengthptr = end - start;
+  return start;
+}
+
+/* Return a pointer to a specified place within STR,
+   skipping (from the beginning) WORDS words and then CHARS chars.
+   If IGNORE_BLANKS is nonzero, we skip all blanks
+   after finding the specified word.  */
+
+char *
+find_pos (str, words, chars, ignore_blanks)
+     char *str;
+     int words, chars;
+     int ignore_blanks;
+{
+  int i;
+  char *p = str;
+
+  for (i = 0; i < words; i++)
+    {
+      char c;
+      /* Find next bunch of nonblanks and skip them. */
+      while ((c = *p) == ' ' || c == '\t')
+	p++;
+      while ((c = *p) && c != '\n' && !(c == ' ' || c == '\t'))
+	p++;
+      if (!*p || *p == '\n')
+	return p;
+    }
+
+  while (*p == ' ' || *p == '\t')
+    p++;
+
+  for (i = 0; i < chars; i++)
+    {
+      if (!*p || *p == '\n')
+	break;
+      p++;
+    }
+  return p;
+}
+
+/* Like find_pos but assumes that each field is surrounded by braces
+   and that braces within fields are balanced. */
+
+char *
+find_braced_pos (str, words, chars, ignore_blanks)
+     char *str;
+     int words, chars;
+     int ignore_blanks;
+{
+  int i;
+  int bracelevel;
+  char *p = str;
+  char c;
+
+  for (i = 0; i < words; i++)
+    {
+      bracelevel = 1;
+      while ((c = *p++) != '{' && c != '\n' && c)
+	/* Do nothing. */ ;
+      if (c != '{')
+	return p - 1;
+      while (bracelevel)
+	{
+	  c = *p++;
+	  if (c == '{')
+	    bracelevel++;
+	  if (c == '}')
+	    bracelevel--;
+	  if (c == 0 || c == '\n')
+	    return p - 1;
+	}
+    }
+
+  while ((c = *p++) != '{' && c != '\n' && c)
+    /* Do nothing. */ ;
+
+  if (c != '{')
+    return p - 1;
+
+  if (ignore_blanks)
+    while ((c = *p) == ' ' || c == '\t')
+      p++;
+
+  for (i = 0; i < chars; i++)
+    {
+      if (!*p || *p == '\n')
+	break;
+      p++;
+    }
+  return p;
+}
+
+/* Find the end of the balanced-brace field which starts at STR.
+   The position returned is just before the closing brace. */
+
+char *
+find_braced_end (str)
+     char *str;
+{
+  int bracelevel;
+  char *p = str;
+  char c;
+
+  bracelevel = 1;
+  while (bracelevel)
+    {
+      c = *p++;
+      if (c == '{')
+	bracelevel++;
+      if (c == '}')
+	bracelevel--;
+      if (c == 0 || c == '\n')
+	return p - 1;
+    }
+  return p - 1;
+}
+
+long
+find_value (start, length)
+     char *start;
+     long length;
+{
+  while (length != 0L)
+    {
+      if (isdigit (*start))
+	return atol (start);
+      length--;
+      start++;
+    }
+  return 0l;
+}
+
+/* Vector used to translate characters for comparison.
+   This is how we make all alphanumerics follow all else,
+   and ignore case in the first sorting.  */
+int char_order[256];
+
+void
+init_char_order ()
+{
+  int i;
+  for (i = 1; i < 256; i++)
+    char_order[i] = i;
+
+  for (i = '0'; i <= '9'; i++)
+    char_order[i] += 512;
+
+  for (i = 'a'; i <= 'z'; i++)
+    {
+      char_order[i] = 512 + i;
+      char_order[i + 'A' - 'a'] = 512 + i;
+    }
+}
+
+/* Compare two fields (each specified as a start pointer and a character count)
+   according to KEYFIELD.
+   The sign of the value reports the relation between the fields. */
+
+int
+compare_field (keyfield, start1, length1, pos1, start2, length2, pos2)
+     struct keyfield *keyfield;
+     char *start1;
+     long length1;
+     long pos1;
+     char *start2;
+     long length2;
+     long pos2;
+{
+  if (keyfields->positional)
+    {
+      if (pos1 > pos2)
+	return 1;
+      else
+	return -1;
+    }
+  if (keyfield->numeric)
+    {
+      long value = find_value (start1, length1) - find_value (start2, length2);
+      if (value > 0)
+	return 1;
+      if (value < 0)
+	return -1;
+      return 0;
+    }
+  else
+    {
+      char *p1 = start1;
+      char *p2 = start2;
+      char *e1 = start1 + length1;
+      char *e2 = start2 + length2;
+
+      while (1)
+	{
+	  int c1, c2;
+
+	  if (p1 == e1)
+	    c1 = 0;
+	  else
+	    c1 = *p1++;
+	  if (p2 == e2)
+	    c2 = 0;
+	  else
+	    c2 = *p2++;
+
+	  if (char_order[c1] != char_order[c2])
+	    return char_order[c1] - char_order[c2];
+	  if (!c1)
+	    break;
+	}
+
+      /* Strings are equal except possibly for case.  */
+      p1 = start1;
+      p2 = start2;
+      while (1)
+	{
+	  int c1, c2;
+
+	  if (p1 == e1)
+	    c1 = 0;
+	  else
+	    c1 = *p1++;
+	  if (p2 == e2)
+	    c2 = 0;
+	  else
+	    c2 = *p2++;
+
+	  if (c1 != c2)
+	    /* Reverse sign here so upper case comes out last.  */
+	    return c2 - c1;
+	  if (!c1)
+	    break;
+	}
+
+      return 0;
+    }
+}
+
+/* A `struct linebuffer' is a structure which holds a line of text.
+   `readline' reads a line from a stream into a linebuffer
+   and works regardless of the length of the line.  */
+
+struct linebuffer
+{
+  long size;
+  char *buffer;
+};
+
+/* Initialize LINEBUFFER for use. */
+
+void
+initbuffer (linebuffer)
+     struct linebuffer *linebuffer;
+{
+  linebuffer->size = 200;
+  linebuffer->buffer = (char *) xmalloc (200);
+}
+
+/* Read a line of text from STREAM into LINEBUFFER.
+   Return the length of the line.  */
+
+long
+readline (linebuffer, stream)
+     struct linebuffer *linebuffer;
+     FILE *stream;
+{
+  char *buffer = linebuffer->buffer;
+  char *p = linebuffer->buffer;
+  char *end = p + linebuffer->size;
+
+  while (1)
+    {
+      int c = getc (stream);
+      if (p == end)
+	{
+	  buffer = (char *) xrealloc (buffer, linebuffer->size *= 2);
+	  p += buffer - linebuffer->buffer;
+	  end += buffer - linebuffer->buffer;
+	  linebuffer->buffer = buffer;
+	}
+      if (c < 0 || c == '\n')
+	{
+	  *p = 0;
+	  break;
+	}
+      *p++ = c;
+    }
+
+  return p - buffer;
+}
+
+/* Sort an input file too big to sort in core.  */
+
+void
+sort_offline (infile, nfiles, total, outfile)
+     char *infile;
+     int nfiles;
+     long total;
+     char *outfile;
+{
+  /* More than enough. */
+  int ntemps = 2 * (total + MAX_IN_CORE_SORT - 1) / MAX_IN_CORE_SORT;
+  char **tempfiles = (char **) xmalloc (ntemps * sizeof (char *));
+  FILE *istream = fopen (infile, "r");
+  int i;
+  struct linebuffer lb;
+  long linelength;
+  int failure = 0;
+
+  initbuffer (&lb);
+
+  /* Read in one line of input data.  */
+
+  linelength = readline (&lb, istream);
+
+  if (lb.buffer[0] != '\\' && lb.buffer[0] != '@')
+    {
+      error ("%s: not a texinfo index file", infile);
+      return;
+    }
+
+  /* Split up the input into `ntemps' temporary files, or maybe fewer,
+     and put the new files' names into `tempfiles' */
+
+  for (i = 0; i < ntemps; i++)
+    {
+      char *outname = maketempname (++tempcount);
+      FILE *ostream = fopen (outname, "w");
+      long tempsize = 0;
+
+      if (!ostream)
+	pfatal_with_name (outname);
+      tempfiles[i] = outname;
+
+      /* Copy lines into this temp file as long as it does not make file
+	 "too big" or until there are no more lines.  */
+
+      while (tempsize + linelength + 1 <= MAX_IN_CORE_SORT)
+	{
+	  tempsize += linelength + 1;
+	  fputs (lb.buffer, ostream);
+	  putc ('\n', ostream);
+
+	  /* Read another line of input data.  */
+
+	  linelength = readline (&lb, istream);
+	  if (!linelength && feof (istream))
+	    break;
+
+	  if (lb.buffer[0] != '\\' && lb.buffer[0] != '@')
+	    {
+	      error ("%s: not a texinfo index file", infile);
+	      failure = 1;
+	      goto fail;
+	    }
+	}
+      fclose (ostream);
+      if (feof (istream))
+	break;
+    }
+
+  free (lb.buffer);
+
+fail:
+  /* Record number of temp files we actually needed.  */
+
+  ntemps = i;
+
+  /* Sort each tempfile into another tempfile.
+    Delete the first set of tempfiles and put the names of the second
+    into `tempfiles'. */
+
+  for (i = 0; i < ntemps; i++)
+    {
+      char *newtemp = maketempname (++tempcount);
+      sort_in_core (&tempfiles[i], MAX_IN_CORE_SORT, newtemp);
+      if (!keep_tempfiles)
+	unlink (tempfiles[i]);
+      tempfiles[i] = newtemp;
+    }
+
+  if (failure)
+    return;
+
+  /* Merge the tempfiles together and indexify. */
+
+  merge_files (tempfiles, ntemps, outfile);
+}
+
+/* Sort INFILE, whose size is TOTAL,
+   assuming that is small enough to be done in-core,
+   then indexify it and send the output to OUTFILE (or to stdout).  */
+
+void
+sort_in_core (infile, total, outfile)
+     char *infile;
+     long total;
+     char *outfile;
+{
+  char **nextline;
+  char *data = (char *) xmalloc (total + 1);
+  char *file_data;
+  long file_size;
+  int i;
+  FILE *ostream = stdout;
+  struct lineinfo *lineinfo;
+
+  /* Read the contents of the file into the moby array `data'. */
+
+  int desc = open (infile, O_RDONLY, 0);
+
+  if (desc < 0)
+    fatal ("failure reopening %s", infile);
+  for (file_size = 0;;)
+    {
+      i = read (desc, data + file_size, total - file_size);
+      if (i <= 0)
+	break;
+      file_size += i;
+    }
+  file_data = data;
+  data[file_size] = 0;
+
+  close (desc);
+
+  if (file_size > 0 && data[0] != '\\' && data[0] != '@')
+    {
+      error ("%s: not a texinfo index file", infile);
+      return;
+    }
+
+  init_char_order ();
+
+  /* Sort routines want to know this address. */
+
+  text_base = data;
+
+  /* Create the array of pointers to lines, with a default size
+     frequently enough.  */
+
+  nlines = total / 50;
+  if (!nlines)
+    nlines = 2;
+  linearray = (char **) xmalloc (nlines * sizeof (char *));
+
+  /* `nextline' points to the next free slot in this array.
+     `nlines' is the allocated size.  */
+
+  nextline = linearray;
+
+  /* Parse the input file's data, and make entries for the lines.  */
+
+  nextline = parsefile (infile, nextline, file_data, file_size);
+  if (nextline == 0)
+    {
+      error ("%s: not a texinfo index file", infile);
+      return;
+    }
+
+  /* Sort the lines. */
+
+  /* If we have enough space, find the first keyfield of each line in advance.
+     Make a `struct lineinfo' for each line, which records the keyfield
+     as well as the line, and sort them.  */
+
+  lineinfo = (struct lineinfo *) malloc ((nextline - linearray) * sizeof (struct lineinfo));
+
+  if (lineinfo)
+    {
+      struct lineinfo *lp;
+      char **p;
+
+      for (lp = lineinfo, p = linearray; p != nextline; lp++, p++)
+	{
+	  lp->text = *p;
+	  lp->key.text = find_field (keyfields, *p, &lp->keylen);
+	  if (keyfields->numeric)
+	    lp->key.number = find_value (lp->key.text, lp->keylen);
+	}
+
+      qsort (lineinfo, nextline - linearray, sizeof (struct lineinfo), compare_prepared);
+
+      for (lp = lineinfo, p = linearray; p != nextline; lp++, p++)
+	*p = lp->text;
+
+      free (lineinfo);
+    }
+  else
+    qsort (linearray, nextline - linearray, sizeof (char *), compare_full);
+
+  /* Open the output file. */
+
+  if (outfile)
+    {
+      ostream = fopen (outfile, "w");
+      if (!ostream)
+	pfatal_with_name (outfile);
+    }
+
+  writelines (linearray, nextline - linearray, ostream);
+  if (outfile)
+    fclose (ostream);
+
+  free (linearray);
+  free (data);
+}
+
+/* Parse an input string in core into lines.
+   DATA is the input string, and SIZE is its length.
+   Data goes in LINEARRAY starting at NEXTLINE.
+   The value returned is the first entry in LINEARRAY still unused.
+   Value 0 means input file contents are invalid.  */
+
+char **
+parsefile (filename, nextline, data, size)
+     char *filename;
+     char **nextline;
+     char *data;
+     long size;
+{
+  char *p, *end;
+  char **line = nextline;
+
+  p = data;
+  end = p + size;
+  *end = 0;
+
+  while (p != end)
+    {
+      if (p[0] != '\\' && p[0] != '@')
+	return 0;
+
+      *line = p;
+      while (*p && *p != '\n')
+	p++;
+      if (p != end)
+	p++;
+
+      line++;
+      if (line == linearray + nlines)
+	{
+	  char **old = linearray;
+	  linearray = (char **) xrealloc (linearray, sizeof (char *) * (nlines *= 4));
+	  line += linearray - old;
+	}
+    }
+
+  return line;
+}
+
+/* Indexification is a filter applied to the sorted lines
+   as they are being written to the output file.
+   Multiple entries for the same name, with different page numbers,
+   get combined into a single entry with multiple page numbers.
+   The first braced field, which is used for sorting, is discarded.
+   However, its first character is examined, folded to lower case,
+   and if it is different from that in the previous line fed to us
+   a \initial line is written with one argument, the new initial.
+
+   If an entry has four braced fields, then the second and third
+   constitute primary and secondary names.
+   In this case, each change of primary name
+   generates a \primary line which contains only the primary name,
+   and in between these are \secondary lines which contain
+   just a secondary name and page numbers. */
+
+/* The last primary name we wrote a \primary entry for.
+   If only one level of indexing is being done, this is the last name seen. */
+char *lastprimary;
+/* Length of storage allocated for lastprimary. */
+int lastprimarylength;
+
+/* Similar, for the secondary name. */
+char *lastsecondary;
+int lastsecondarylength;
+
+/* Zero if we are not in the middle of writing an entry.
+   One if we have written the beginning of an entry but have not
+   yet written any page numbers into it.
+   Greater than one if we have written the beginning of an entry
+   plus at least one page number. */
+int pending;
+
+/* The initial (for sorting purposes) of the last primary entry written.
+   When this changes, a \initial {c} line is written */
+
+char *lastinitial;
+
+int lastinitiallength;
+
+/* When we need a string of length 1 for the value of lastinitial,
+   store it here.  */
+
+char lastinitial1[2];
+
+/* Initialize static storage for writing an index. */
+
+static void
+xbzero(s, n)
+     char *s;
+     int n;
+{
+  register char *p;
+  for (p = s; n--; )
+    *p++ = '\0';
+}
+
+void
+init_index ()
+{
+  pending = 0;
+  lastinitial = lastinitial1;
+  lastinitial1[0] = 0;
+  lastinitial1[1] = 0;
+  lastinitiallength = 0;
+  lastprimarylength = 100;
+  lastprimary = (char *) xmalloc (lastprimarylength + 1);
+  xbzero (lastprimary, lastprimarylength + 1);
+  lastsecondarylength = 100;
+  lastsecondary = (char *) xmalloc (lastsecondarylength + 1);
+  xbzero (lastsecondary, lastsecondarylength + 1);
+}
+
+/* Indexify.  Merge entries for the same name,
+   insert headers for each initial character, etc.  */
+
+void
+indexify (line, ostream)
+     char *line;
+     FILE *ostream;
+{
+  char *primary, *secondary, *pagenumber;
+  int primarylength, secondarylength = 0, pagelength;
+  int nosecondary;
+  int initiallength;
+  char *initial;
+  char initial1[2];
+  register char *p;
+
+  /* First, analyze the parts of the entry fed to us this time. */
+
+  p = find_braced_pos (line, 0, 0, 0);
+  if (*p == '{')
+    {
+      initial = p;
+      /* Get length of inner pair of braces starting at `p',
+	 including that inner pair of braces.  */
+      initiallength = find_braced_end (p + 1) + 1 - p;
+    }
+  else
+    {
+      initial = initial1;
+      initial1[0] = *p;
+      initial1[1] = 0;
+      initiallength = 1;
+
+      if (initial1[0] >= 'a' && initial1[0] <= 'z')
+	initial1[0] -= 040;
+    }
+
+  pagenumber = find_braced_pos (line, 1, 0, 0);
+  pagelength = find_braced_end (pagenumber) - pagenumber;
+  if (pagelength == 0)
+    abort ();
+
+  primary = find_braced_pos (line, 2, 0, 0);
+  primarylength = find_braced_end (primary) - primary;
+
+  secondary = find_braced_pos (line, 3, 0, 0);
+  nosecondary = !*secondary;
+  if (!nosecondary)
+    secondarylength = find_braced_end (secondary) - secondary;
+
+  /* If the primary is different from before, make a new primary entry. */
+  if (strncmp (primary, lastprimary, primarylength))
+    {
+      /* Close off current secondary entry first, if one is open. */
+      if (pending)
+	{
+	  fputs ("}\n", ostream);
+	  pending = 0;
+	}
+
+      /* If this primary has a different initial, include an entry for
+	 the initial. */
+      if (initiallength != lastinitiallength ||
+	  strncmp (initial, lastinitial, initiallength))
+	{
+	  fprintf (ostream, "\\initial {");
+	  fwrite (initial, 1, initiallength, ostream);
+	  fprintf (ostream, "}\n", initial);
+	  if (initial == initial1)
+	    {
+	      lastinitial = lastinitial1;
+	      *lastinitial1 = *initial1;
+	    }
+	  else
+	    {
+	      lastinitial = initial;
+	    }
+	  lastinitiallength = initiallength;
+	}
+
+      /* Make the entry for the primary.  */
+      if (nosecondary)
+	fputs ("\\entry {", ostream);
+      else
+	fputs ("\\primary {", ostream);
+      fwrite (primary, primarylength, 1, ostream);
+      if (nosecondary)
+	{
+	  fputs ("}{", ostream);
+	  pending = 1;
+	}
+      else
+	fputs ("}\n", ostream);
+
+      /* Record name of most recent primary. */
+      if (lastprimarylength < primarylength)
+	{
+	  lastprimarylength = primarylength + 100;
+	  lastprimary = (char *) xrealloc (lastprimary,
+					   1 + lastprimarylength);
+	}
+      strncpy (lastprimary, primary, primarylength);
+      lastprimary[primarylength] = 0;
+
+      /* There is no current secondary within this primary, now. */
+      lastsecondary[0] = 0;
+    }
+
+  /* Should not have an entry with no subtopic following one with a subtopic. */
+
+  if (nosecondary && *lastsecondary)
+    error ("entry %s follows an entry with a secondary name", line);
+
+  /* Start a new secondary entry if necessary. */
+  if (!nosecondary && strncmp (secondary, lastsecondary, secondarylength))
+    {
+      if (pending)
+	{
+	  fputs ("}\n", ostream);
+	  pending = 0;
+	}
+
+      /* Write the entry for the secondary.  */
+      fputs ("\\secondary {", ostream);
+      fwrite (secondary, secondarylength, 1, ostream);
+      fputs ("}{", ostream);
+      pending = 1;
+
+      /* Record name of most recent secondary. */
+      if (lastsecondarylength < secondarylength)
+	{
+	  lastsecondarylength = secondarylength + 100;
+	  lastsecondary = (char *) xrealloc (lastsecondary,
+					     1 + lastsecondarylength);
+	}
+      strncpy (lastsecondary, secondary, secondarylength);
+      lastsecondary[secondarylength] = 0;
+    }
+
+  /* Here to add one more page number to the current entry. */
+  if (pending++ != 1)
+    fputs (", ", ostream);	/* Punctuate first, if this is not the first. */
+  fwrite (pagenumber, pagelength, 1, ostream);
+}
+
+/* Close out any unfinished output entry. */
+
+void
+finish_index (ostream)
+     FILE *ostream;
+{
+  if (pending)
+    fputs ("}\n", ostream);
+  free (lastprimary);
+  free (lastsecondary);
+}
+
+/* Copy the lines in the sorted order.
+   Each line is copied out of the input file it was found in. */
+
+void
+writelines (linearray, nlines, ostream)
+     char **linearray;
+     int nlines;
+     FILE *ostream;
+{
+  char **stop_line = linearray + nlines;
+  char **next_line;
+
+  init_index ();
+
+  /* Output the text of the lines, and free the buffer space. */
+
+  for (next_line = linearray; next_line != stop_line; next_line++)
+    {
+      /* If -u was specified, output the line only if distinct from previous one.  */
+      if (next_line == linearray
+      /* Compare previous line with this one, using only the
+         explicitly specd keyfields. */
+	  || compare_general (*(next_line - 1), *next_line, 0L, 0L, num_keyfields - 1))
+	{
+	  char *p = *next_line;
+	  char c;
+
+	  while ((c = *p++) && c != '\n')
+	    /* Do nothing. */ ;
+	  *(p - 1) = 0;
+	  indexify (*next_line, ostream);
+	}
+    }
+
+  finish_index (ostream);
+}
+
+/* Assume (and optionally verify) that each input file is sorted;
+   merge them and output the result.
+   Returns nonzero if any input file fails to be sorted.
+
+   This is the high-level interface that can handle an unlimited
+   number of files.  */
+
+#define MAX_DIRECT_MERGE 10
+
+int
+merge_files (infiles, nfiles, outfile)
+     char **infiles;
+     int nfiles;
+     char *outfile;
+{
+  char **tempfiles;
+  int ntemps;
+  int i;
+  int value = 0;
+  int start_tempcount = tempcount;
+
+  if (nfiles <= MAX_DIRECT_MERGE)
+    return merge_direct (infiles, nfiles, outfile);
+
+  /* Merge groups of MAX_DIRECT_MERGE input files at a time,
+     making a temporary file to hold each group's result.  */
+
+  ntemps = (nfiles + MAX_DIRECT_MERGE - 1) / MAX_DIRECT_MERGE;
+  tempfiles = (char **) xmalloc (ntemps * sizeof (char *));
+  for (i = 0; i < ntemps; i++)
+    {
+      int nf = MAX_DIRECT_MERGE;
+      if (i + 1 == ntemps)
+	nf = nfiles - i * MAX_DIRECT_MERGE;
+      tempfiles[i] = maketempname (++tempcount);
+      value |= merge_direct (&infiles[i * MAX_DIRECT_MERGE], nf, tempfiles[i]);
+    }
+
+  /* All temporary files that existed before are no longer needed
+     since their contents have been merged into our new tempfiles.
+     So delete them.  */
+  flush_tempfiles (start_tempcount);
+
+  /* Now merge the temporary files we created.  */
+
+  merge_files (tempfiles, ntemps, outfile);
+
+  free (tempfiles);
+
+  return value;
+}
+
+/* Assume (and optionally verify) that each input file is sorted;
+   merge them and output the result.
+   Returns nonzero if any input file fails to be sorted.
+
+   This version of merging will not work if the number of
+   input files gets too high.  Higher level functions
+   use it only with a bounded number of input files.  */
+
+int
+merge_direct (infiles, nfiles, outfile)
+     char **infiles;
+     int nfiles;
+     char *outfile;
+{
+  struct linebuffer *lb1, *lb2;
+  struct linebuffer **thisline, **prevline;
+  FILE **streams;
+  int i;
+  int nleft;
+  int lossage = 0;
+  int *file_lossage;
+  struct linebuffer *prev_out = 0;
+  FILE *ostream = stdout;
+
+  if (outfile)
+    {
+      ostream = fopen (outfile, "w");
+    }
+  if (!ostream)
+    pfatal_with_name (outfile);
+
+  init_index ();
+
+  if (nfiles == 0)
+    {
+      if (outfile)
+	fclose (ostream);
+      return 0;
+    }
+
+  /* For each file, make two line buffers.
+     Also, for each file, there is an element of `thisline'
+     which points at any time to one of the file's two buffers,
+     and an element of `prevline' which points to the other buffer.
+     `thisline' is supposed to point to the next available line from the file,
+     while `prevline' holds the last file line used,
+     which is remembered so that we can verify that the file is properly sorted. */
+
+  /* lb1 and lb2 contain one buffer each per file. */
+  lb1 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer));
+  lb2 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer));
+
+  /* thisline[i] points to the linebuffer holding the next available line in file i,
+     or is zero if there are no lines left in that file.  */
+  thisline = (struct linebuffer **)
+    xmalloc (nfiles * sizeof (struct linebuffer *));
+  /* prevline[i] points to the linebuffer holding the last used line
+     from file i.  This is just for verifying that file i is properly
+     sorted.  */
+  prevline = (struct linebuffer **)
+    xmalloc (nfiles * sizeof (struct linebuffer *));
+  /* streams[i] holds the input stream for file i.  */
+  streams = (FILE **) xmalloc (nfiles * sizeof (FILE *));
+  /* file_lossage[i] is nonzero if we already know file i is not
+     properly sorted.  */
+  file_lossage = (int *) xmalloc (nfiles * sizeof (int));
+
+  /* Allocate and initialize all that storage. */
+
+  for (i = 0; i < nfiles; i++)
+    {
+      initbuffer (&lb1[i]);
+      initbuffer (&lb2[i]);
+      thisline[i] = &lb1[i];
+      prevline[i] = &lb2[i];
+      file_lossage[i] = 0;
+      streams[i] = fopen (infiles[i], "r");
+      if (!streams[i])
+	pfatal_with_name (infiles[i]);
+
+      readline (thisline[i], streams[i]);
+    }
+
+  /* Keep count of number of files not at eof. */
+  nleft = nfiles;
+
+  while (nleft)
+    {
+      struct linebuffer *best = 0;
+      struct linebuffer *exch;
+      int bestfile = -1;
+      int i;
+
+      /* Look at the next avail line of each file; choose the least one.  */
+
+      for (i = 0; i < nfiles; i++)
+	{
+	  if (thisline[i] &&
+	      (!best ||
+	       0 < compare_general (best->buffer, thisline[i]->buffer,
+				 (long) bestfile, (long) i, num_keyfields)))
+	    {
+	      best = thisline[i];
+	      bestfile = i;
+	    }
+	}
+
+      /* Output that line, unless it matches the previous one and we
+	 don't want duplicates. */
+
+      if (!(prev_out &&
+	    !compare_general (prev_out->buffer,
+			      best->buffer, 0L, 1L, num_keyfields - 1)))
+	indexify (best->buffer, ostream);
+      prev_out = best;
+
+      /* Now make the line the previous of its file, and fetch a new
+	 line from that file.  */
+
+      exch = prevline[bestfile];
+      prevline[bestfile] = thisline[bestfile];
+      thisline[bestfile] = exch;
+
+      while (1)
+	{
+	  /* If the file has no more, mark it empty. */
+
+	  if (feof (streams[bestfile]))
+	    {
+	      thisline[bestfile] = 0;
+	      /* Update the number of files still not empty. */
+	      nleft--;
+	      break;
+	    }
+	  readline (thisline[bestfile], streams[bestfile]);
+	  if (thisline[bestfile]->buffer[0] || !feof (streams[bestfile]))
+	    break;
+	}
+    }
+
+  finish_index (ostream);
+
+  /* Free all storage and close all input streams. */
+
+  for (i = 0; i < nfiles; i++)
+    {
+      fclose (streams[i]);
+      free (lb1[i].buffer);
+      free (lb2[i].buffer);
+    }
+  free (file_lossage);
+  free (lb1);
+  free (lb2);
+  free (thisline);
+  free (prevline);
+  free (streams);
+
+  if (outfile)
+    fclose (ostream);
+
+  return lossage;
+}
+
+/* Print error message and exit.  */
+
+void
+fatal (s1, s2)
+     char *s1, *s2;
+{
+  error (s1, s2);
+  exit (TI_FATAL_ERROR);
+}
+
+/* Print error message.  S1 is printf control string, S2 is arg for it. */
+
+void
+error (s1, s2)
+     char *s1, *s2;
+{
+  printf ("%s: ", program_name);
+  printf (s1, s2);
+  printf ("\n");
+}
+
+#if !defined (HAVE_STRERROR)
+static char *
+strerror (n)
+     int n;
+{
+  static char ebuf[40];
+
+  if (n < sys_nerr)
+    return sys_errlist[n];
+  else
+    {
+      sprintf (ebuf, "Unknown error %d", n);
+      return ebuf;
+    }
+}
+#endif
+
+void
+perror_with_name (name)
+     char *name;
+{
+  char *s;
+
+  s = concat ("", strerror (errno), " for %s");
+  error (s, name);
+}
+
+void
+pfatal_with_name (name)
+     char *name;
+{
+  char *s;
+
+  s = concat ("", strerror (errno), " for %s");
+  fatal (s, name);
+}
+
+/* Return a newly-allocated string whose contents concatenate those of
+   S1, S2, S3.  */
+
+char *
+concat (s1, s2, s3)
+     char *s1, *s2, *s3;
+{
+  int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+  char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+  strcpy (result, s1);
+  strcpy (result + len1, s2);
+  strcpy (result + len1 + len2, s3);
+  *(result + len1 + len2 + len3) = 0;
+
+  return result;
+}
+
+/* Just like malloc, but kills the program in case of fatal error. */
+void *
+xmalloc (nbytes)
+     int nbytes;
+{
+  void *temp = (void *) malloc (nbytes);
+
+  if (nbytes && temp == (void *)NULL)
+    memory_error ("xmalloc", nbytes);
+
+  return (temp);
+}
+
+/* Like realloc (), but barfs if there isn't enough memory. */
+void *
+xrealloc (pointer, nbytes)
+     void *pointer;
+     int nbytes;
+{
+  void *temp;
+
+  if (!pointer)
+    temp = (void *)xmalloc (nbytes);
+  else
+    temp = (void *)realloc (pointer, nbytes);
+
+  if (nbytes && !temp)
+    memory_error ("xrealloc", nbytes);
+
+  return (temp);
+}
+
+memory_error (callers_name, bytes_wanted)
+     char *callers_name;
+     int bytes_wanted;
+{
+  char printable_string[80];
+
+  sprintf (printable_string,
+	   "Virtual memory exhausted in %s ()!  Needed %d bytes.",
+	   callers_name, bytes_wanted);
+
+  error (printable_string, "");
+  abort ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/emacs_keymap.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,885 @@
+/* emacs_keymap.c -- the keymap for emacs_mode in readline (). */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (BUFSIZ)
+#include <stdio.h>
+#endif /* !BUFSIZ */
+
+#include "readline.h"
+
+/* An array of function pointers, one for each possible key.
+   If the type byte is ISKMAP, then the pointer is the address of
+   a keymap. */
+
+KEYMAP_ENTRY_ARRAY emacs_standard_keymap = {
+
+  /* Control keys. */
+  { ISFUNC, (Function *)0x0 },		/* Control-@ */
+  { ISFUNC, rl_beg_of_line },		/* Control-a */
+  { ISFUNC, rl_backward },		/* Control-b */
+  { ISFUNC, (Function *)0x0 },		/* Control-c */
+  { ISFUNC, rl_delete },		/* Control-d */
+  { ISFUNC, rl_end_of_line },		/* Control-e */
+  { ISFUNC, rl_forward },		/* Control-f */
+  { ISFUNC, rl_abort },			/* Control-g */
+  { ISFUNC, rl_rubout },		/* Control-h */
+  { ISFUNC, rl_complete },		/* Control-i */
+  { ISFUNC, rl_newline },		/* Control-j */
+  { ISFUNC, rl_kill_line },		/* Control-k */
+  { ISFUNC, rl_clear_screen },		/* Control-l */
+  { ISFUNC, rl_newline },		/* Control-m */
+  { ISFUNC, rl_get_next_history },	/* Control-n */
+  { ISFUNC, (Function *)0x0 },		/* Control-o */
+  { ISFUNC, rl_get_previous_history },	/* Control-p */
+  { ISFUNC, rl_quoted_insert },		/* Control-q */
+  { ISFUNC, rl_reverse_search_history }, /* Control-r */
+  { ISFUNC, rl_forward_search_history }, /* Control-s */
+  { ISFUNC, rl_transpose_chars },	/* Control-t */
+  { ISFUNC, rl_unix_line_discard },	/* Control-u */
+  { ISFUNC, rl_quoted_insert },		/* Control-v */
+  { ISFUNC, rl_unix_word_rubout },	/* Control-w */
+  { ISKMAP, (Function *)emacs_ctlx_keymap },	/* Control-x */
+  { ISFUNC, rl_yank },			/* Control-y */
+  { ISFUNC, (Function *)0x0 },		/* Control-z */
+  { ISKMAP, (Function *)emacs_meta_keymap }, /* Control-[ */
+  { ISFUNC, (Function *)0x0 },		/* Control-\ */
+  { ISFUNC, (Function *)0x0 },		/* Control-] */
+  { ISFUNC, (Function *)0x0 },		/* Control-^ */
+  { ISFUNC, rl_undo_command },		/* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, rl_insert },	/* SPACE */
+  { ISFUNC, rl_insert },	/* ! */
+  { ISFUNC, rl_insert },	/* " */
+  { ISFUNC, rl_insert },	/* # */
+  { ISFUNC, rl_insert },	/* $ */
+  { ISFUNC, rl_insert },	/* % */
+  { ISFUNC, rl_insert },	/* & */
+  { ISFUNC, rl_insert },	/* ' */
+  { ISFUNC, rl_insert },	/* ( */
+#if defined (PAREN_MATCHING)
+  { ISFUNC, rl_insert_close },	/* ) */
+#else
+  { ISFUNC, rl_insert },	/* ) */
+#endif /* !PAREN_MATCHING */
+  { ISFUNC, rl_insert },	/* * */
+  { ISFUNC, rl_insert },	/* + */
+  { ISFUNC, rl_insert },	/* , */
+  { ISFUNC, rl_insert },	/* - */
+  { ISFUNC, rl_insert },	/* . */
+  { ISFUNC, rl_insert },	/* / */
+
+  /* Regular digits. */
+  { ISFUNC, rl_insert },	/* 0 */
+  { ISFUNC, rl_insert },	/* 1 */
+  { ISFUNC, rl_insert },	/* 2 */
+  { ISFUNC, rl_insert },	/* 3 */
+  { ISFUNC, rl_insert },	/* 4 */
+  { ISFUNC, rl_insert },	/* 5 */
+  { ISFUNC, rl_insert },	/* 6 */
+  { ISFUNC, rl_insert },	/* 7 */
+  { ISFUNC, rl_insert },	/* 8 */
+  { ISFUNC, rl_insert },	/* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, rl_insert },	/* : */
+  { ISFUNC, rl_insert },	/* ; */
+  { ISFUNC, rl_insert },	/* < */
+  { ISFUNC, rl_insert },	/* = */
+  { ISFUNC, rl_insert },	/* > */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_insert },	/* A */
+  { ISFUNC, rl_insert },	/* B */
+  { ISFUNC, rl_insert },	/* C */
+  { ISFUNC, rl_insert },	/* D */
+  { ISFUNC, rl_insert },	/* E */
+  { ISFUNC, rl_insert },	/* F */
+  { ISFUNC, rl_insert },	/* G */
+  { ISFUNC, rl_insert },	/* H */
+  { ISFUNC, rl_insert },	/* I */
+  { ISFUNC, rl_insert },	/* J */
+  { ISFUNC, rl_insert },	/* K */
+  { ISFUNC, rl_insert },	/* L */
+  { ISFUNC, rl_insert },	/* M */
+  { ISFUNC, rl_insert },	/* N */
+  { ISFUNC, rl_insert },	/* O */
+  { ISFUNC, rl_insert },	/* P */
+  { ISFUNC, rl_insert },	/* Q */
+  { ISFUNC, rl_insert },	/* R */
+  { ISFUNC, rl_insert },	/* S */
+  { ISFUNC, rl_insert },	/* T */
+  { ISFUNC, rl_insert },	/* U */
+  { ISFUNC, rl_insert },	/* V */
+  { ISFUNC, rl_insert },	/* W */
+  { ISFUNC, rl_insert },	/* X */
+  { ISFUNC, rl_insert },	/* Y */
+  { ISFUNC, rl_insert },	/* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, rl_insert },	/* [ */
+  { ISFUNC, rl_insert },	/* \ */
+#if defined (PAREN_MATCHING)
+  { ISFUNC, rl_insert_close },	/* ] */
+#else
+  { ISFUNC, rl_insert },	/* ] */
+#endif /* !PAREN_MATCHING */
+  { ISFUNC, rl_insert },	/* ^ */
+  { ISFUNC, rl_insert },	/* _ */
+  { ISFUNC, rl_insert },	/* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, rl_insert },	/* a */
+  { ISFUNC, rl_insert },	/* b */
+  { ISFUNC, rl_insert },	/* c */
+  { ISFUNC, rl_insert },	/* d */
+  { ISFUNC, rl_insert },	/* e */
+  { ISFUNC, rl_insert },	/* f */
+  { ISFUNC, rl_insert },	/* g */
+  { ISFUNC, rl_insert },	/* h */
+  { ISFUNC, rl_insert },	/* i */
+  { ISFUNC, rl_insert },	/* j */
+  { ISFUNC, rl_insert },	/* k */
+  { ISFUNC, rl_insert },	/* l */
+  { ISFUNC, rl_insert },	/* m */
+  { ISFUNC, rl_insert },	/* n */
+  { ISFUNC, rl_insert },	/* o */
+  { ISFUNC, rl_insert },	/* p */
+  { ISFUNC, rl_insert },	/* q */
+  { ISFUNC, rl_insert },	/* r */
+  { ISFUNC, rl_insert },	/* s */
+  { ISFUNC, rl_insert },	/* t */
+  { ISFUNC, rl_insert },	/* u */
+  { ISFUNC, rl_insert },	/* v */
+  { ISFUNC, rl_insert },	/* w */
+  { ISFUNC, rl_insert },	/* x */
+  { ISFUNC, rl_insert },	/* y */
+  { ISFUNC, rl_insert },	/* z */
+
+  /* Final punctuation. */
+  { ISFUNC, rl_insert },	/* { */
+  { ISFUNC, rl_insert },	/* | */
+#if defined (PAREN_MATCHING)
+  { ISFUNC, rl_insert_close },	/* } */
+#else
+  { ISFUNC, rl_insert },	/* } */
+#endif /* !PAREN_MATCHING */
+  { ISFUNC, rl_insert },	/* ~ */
+  { ISFUNC, rl_rubout },	/* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+  /* Pure 8-bit characters (128 - 159).
+     These might be used in some
+     character sets. */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+
+  /* ISO Latin-1 characters (160 - 255) */
+  { ISFUNC, rl_insert },	/* No-break space */
+  { ISFUNC, rl_insert },	/* Inverted exclamation mark */
+  { ISFUNC, rl_insert },	/* Cent sign */
+  { ISFUNC, rl_insert },	/* Pound sign */
+  { ISFUNC, rl_insert },	/* Currency sign */
+  { ISFUNC, rl_insert },	/* Yen sign */
+  { ISFUNC, rl_insert },	/* Broken bar */
+  { ISFUNC, rl_insert },	/* Section sign */
+  { ISFUNC, rl_insert },	/* Diaeresis */
+  { ISFUNC, rl_insert },	/* Copyright sign */
+  { ISFUNC, rl_insert },	/* Feminine ordinal indicator */
+  { ISFUNC, rl_insert },	/* Left pointing double angle quotation mark */
+  { ISFUNC, rl_insert },	/* Not sign */
+  { ISFUNC, rl_insert },	/* Soft hyphen */
+  { ISFUNC, rl_insert },	/* Registered sign */
+  { ISFUNC, rl_insert },	/* Macron */
+  { ISFUNC, rl_insert },	/* Degree sign */
+  { ISFUNC, rl_insert },	/* Plus-minus sign */
+  { ISFUNC, rl_insert },	/* Superscript two */
+  { ISFUNC, rl_insert },	/* Superscript three */
+  { ISFUNC, rl_insert },	/* Acute accent */
+  { ISFUNC, rl_insert },	/* Micro sign */
+  { ISFUNC, rl_insert },	/* Pilcrow sign */
+  { ISFUNC, rl_insert },	/* Middle dot */
+  { ISFUNC, rl_insert },	/* Cedilla */
+  { ISFUNC, rl_insert },	/* Superscript one */
+  { ISFUNC, rl_insert },	/* Masculine ordinal indicator */
+  { ISFUNC, rl_insert },	/* Right pointing double angle quotation mark */
+  { ISFUNC, rl_insert },	/* Vulgar fraction one quarter */
+  { ISFUNC, rl_insert },	/* Vulgar fraction one half */
+  { ISFUNC, rl_insert },	/* Vulgar fraction three quarters */
+  { ISFUNC, rl_insert },	/* Inverted questionk mark */
+  { ISFUNC, rl_insert },	/* Latin capital letter a with grave */
+  { ISFUNC, rl_insert },	/* Latin capital letter a with acute */
+  { ISFUNC, rl_insert },	/* Latin capital letter a with circumflex */
+  { ISFUNC, rl_insert },	/* Latin capital letter a with tilde */
+  { ISFUNC, rl_insert },	/* Latin capital letter a with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin capital letter a with ring above */
+  { ISFUNC, rl_insert },	/* Latin capital letter ae */
+  { ISFUNC, rl_insert },	/* Latin capital letter c with cedilla */
+  { ISFUNC, rl_insert },	/* Latin capital letter e with grave */
+  { ISFUNC, rl_insert },	/* Latin capital letter e with acute */
+  { ISFUNC, rl_insert },	/* Latin capital letter e with circumflex */
+  { ISFUNC, rl_insert },	/* Latin capital letter e with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin capital letter i with grave */
+  { ISFUNC, rl_insert },	/* Latin capital letter i with acute */
+  { ISFUNC, rl_insert },	/* Latin capital letter i with circumflex */
+  { ISFUNC, rl_insert },	/* Latin capital letter i with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin capital letter eth (Icelandic) */
+  { ISFUNC, rl_insert },	/* Latin capital letter n with tilde */
+  { ISFUNC, rl_insert },	/* Latin capital letter o with grave */
+  { ISFUNC, rl_insert },	/* Latin capital letter o with acute */
+  { ISFUNC, rl_insert },	/* Latin capital letter o with circumflex */
+  { ISFUNC, rl_insert },	/* Latin capital letter o with tilde */
+  { ISFUNC, rl_insert },	/* Latin capital letter o with diaeresis */
+  { ISFUNC, rl_insert },	/* Multiplication sign */
+  { ISFUNC, rl_insert },	/* Latin capital letter o with stroke */
+  { ISFUNC, rl_insert },	/* Latin capital letter u with grave */
+  { ISFUNC, rl_insert },	/* Latin capital letter u with acute */
+  { ISFUNC, rl_insert },	/* Latin capital letter u with circumflex */
+  { ISFUNC, rl_insert },	/* Latin capital letter u with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin capital letter Y with acute */
+  { ISFUNC, rl_insert },	/* Latin capital letter thorn (Icelandic) */
+  { ISFUNC, rl_insert },	/* Latin small letter sharp s (German) */
+  { ISFUNC, rl_insert },	/* Latin small letter a with grave */
+  { ISFUNC, rl_insert },	/* Latin small letter a with acute */
+  { ISFUNC, rl_insert },	/* Latin small letter a with circumflex */
+  { ISFUNC, rl_insert },	/* Latin small letter a with tilde */
+  { ISFUNC, rl_insert },	/* Latin small letter a with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin small letter a with ring above */
+  { ISFUNC, rl_insert },	/* Latin small letter ae */
+  { ISFUNC, rl_insert },	/* Latin small letter c with cedilla */
+  { ISFUNC, rl_insert },	/* Latin small letter e with grave */
+  { ISFUNC, rl_insert },	/* Latin small letter e with acute */
+  { ISFUNC, rl_insert },	/* Latin small letter e with circumflex */
+  { ISFUNC, rl_insert },	/* Latin small letter e with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin small letter i with grave */
+  { ISFUNC, rl_insert },	/* Latin small letter i with acute */
+  { ISFUNC, rl_insert },	/* Latin small letter i with circumflex */
+  { ISFUNC, rl_insert },	/* Latin small letter i with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin small letter eth (Icelandic) */
+  { ISFUNC, rl_insert },	/* Latin small letter n with tilde */
+  { ISFUNC, rl_insert },	/* Latin small letter o with grave */
+  { ISFUNC, rl_insert },	/* Latin small letter o with acute */
+  { ISFUNC, rl_insert },	/* Latin small letter o with circumflex */
+  { ISFUNC, rl_insert },	/* Latin small letter o with tilde */
+  { ISFUNC, rl_insert },	/* Latin small letter o with diaeresis */
+  { ISFUNC, rl_insert },	/* Division sign */
+  { ISFUNC, rl_insert },	/* Latin small letter o with stroke */
+  { ISFUNC, rl_insert },	/* Latin small letter u with grave */
+  { ISFUNC, rl_insert },	/* Latin small letter u with acute */
+  { ISFUNC, rl_insert },	/* Latin small letter u with circumflex */
+  { ISFUNC, rl_insert },	/* Latin small letter u with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin small letter y with acute */
+  { ISFUNC, rl_insert },	/* Latin small letter thorn (Icelandic) */
+  { ISFUNC, rl_insert }		/* Latin small letter y with diaeresis */
+#endif /* KEYMAP_SIZE > 128 */
+};
+
+KEYMAP_ENTRY_ARRAY emacs_meta_keymap = {
+
+  /* Meta keys.  Just like above, but the high bit is set. */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-@ */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-a */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-b */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-c */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-d */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-e */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-f */
+  { ISFUNC, rl_abort },		/* Meta-Control-g */
+  { ISFUNC, rl_backward_kill_word },	/* Meta-Control-h */
+  { ISFUNC, rl_tab_insert },	/* Meta-Control-i */
+  { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-j */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-k */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-l */
+  { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-m */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-n */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-o */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-p */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-q */
+  { ISFUNC, rl_revert_line },	/* Meta-Control-r */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-s */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-t */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-u */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-v */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-w */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-x */
+  { ISFUNC, rl_yank_nth_arg },	/* Meta-Control-y */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-z */
+
+  { ISFUNC, rl_complete },	/* Meta-Control-[ */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-\ */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-] */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-^ */
+  { ISFUNC, (Function *)0x0 },	/* Meta-Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, (Function *)0x0 },	/* Meta-SPACE */
+  { ISFUNC, (Function *)0x0 },	/* Meta-! */
+  { ISFUNC, (Function *)0x0 },	/* Meta-" */
+  { ISFUNC, (Function *)0x0 },	/* Meta-# */
+  { ISFUNC, (Function *)0x0 },	/* Meta-$ */
+  { ISFUNC, (Function *)0x0 },	/* Meta-% */
+  { ISFUNC, rl_tilde_expand },	/* Meta-& */
+  { ISFUNC, (Function *)0x0 },	/* Meta-' */
+  { ISFUNC, (Function *)0x0 },	/* Meta-( */
+  { ISFUNC, (Function *)0x0 },	/* Meta-) */
+  { ISFUNC, (Function *)0x0 },	/* Meta-* */
+  { ISFUNC, (Function *)0x0 },	/* Meta-+ */
+  { ISFUNC, (Function *)0x0 },	/* Meta-, */
+  { ISFUNC, rl_digit_argument }, /* Meta-- */
+  { ISFUNC, rl_yank_last_arg},	/* Meta-. */
+  { ISFUNC, (Function *)0x0 },	/* Meta-/ */
+
+  /* Regular digits. */
+  { ISFUNC, rl_digit_argument }, /* Meta-0 */
+  { ISFUNC, rl_digit_argument }, /* Meta-1 */
+  { ISFUNC, rl_digit_argument }, /* Meta-2 */
+  { ISFUNC, rl_digit_argument }, /* Meta-3 */
+  { ISFUNC, rl_digit_argument }, /* Meta-4 */
+  { ISFUNC, rl_digit_argument }, /* Meta-5 */
+  { ISFUNC, rl_digit_argument }, /* Meta-6 */
+  { ISFUNC, rl_digit_argument }, /* Meta-7 */
+  { ISFUNC, rl_digit_argument }, /* Meta-8 */
+  { ISFUNC, rl_digit_argument }, /* Meta-9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, (Function *)0x0 },		/* Meta-: */
+  { ISFUNC, (Function *)0x0 },		/* Meta-; */
+  { ISFUNC, rl_beginning_of_history },	/* Meta-< */
+  { ISFUNC, (Function *)0x0 },		/* Meta-= */
+  { ISFUNC, rl_end_of_history },	/* Meta-> */
+  { ISFUNC, rl_possible_completions },	/* Meta-? */
+  { ISFUNC, (Function *)0x0 },		/* Meta-@ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-A */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-B */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-C */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-D */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-E */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-F */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-G */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-H */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-I */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-J */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-K */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-L */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-M */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-N */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-O */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-P */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-Q */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-R */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-S */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-T */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-U */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-V */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-W */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-X */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-Y */
+  { ISFUNC, rl_do_lowercase_version },	/* Meta-Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, (Function *)0x0 },		/* Meta-[ */	/* was rl_arrow_keys */
+  { ISFUNC, rl_delete_horizontal_space },	/* Meta-\ */
+  { ISFUNC, (Function *)0x0 },		/* Meta-] */
+  { ISFUNC, (Function *)0x0 },		/* Meta-^ */
+  { ISFUNC, rl_yank_last_arg },		/* Meta-_ */
+  { ISFUNC, (Function *)0x0 },		/* Meta-` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, (Function *)0x0 },	/* Meta-a */
+  { ISFUNC, rl_backward_word },	/* Meta-b */
+  { ISFUNC, rl_capitalize_word }, /* Meta-c */
+  { ISFUNC, rl_kill_word },	/* Meta-d */
+  { ISFUNC, (Function *)0x0 },	/* Meta-e */
+  { ISFUNC, rl_forward_word },	/* Meta-f */
+  { ISFUNC, (Function *)0x0 },	/* Meta-g */
+  { ISFUNC, (Function *)0x0 },	/* Meta-h */
+  { ISFUNC, (Function *)0x0 },	/* Meta-i */
+  { ISFUNC, (Function *)0x0 },	/* Meta-j */
+  { ISFUNC, (Function *)0x0 },	/* Meta-k */
+  { ISFUNC, rl_downcase_word },	/* Meta-l */
+  { ISFUNC, (Function *)0x0 },	/* Meta-m */
+  { ISFUNC, rl_noninc_forward_search },	/* Meta-n */
+  { ISFUNC, (Function *)0x0 },	/* Meta-o */	/* was rl_arrow_keys */
+  { ISFUNC, rl_noninc_reverse_search },	/* Meta-p */
+  { ISFUNC, (Function *)0x0 },	/* Meta-q */
+  { ISFUNC, rl_revert_line },	/* Meta-r */
+  { ISFUNC, (Function *)0x0 },	/* Meta-s */
+  { ISFUNC, rl_transpose_words }, /* Meta-t */
+  { ISFUNC, rl_upcase_word },	/* Meta-u */
+  { ISFUNC, (Function *)0x0 },	/* Meta-v */
+  { ISFUNC, (Function *)0x0 },	/* Meta-w */
+  { ISFUNC, (Function *)0x0 },	/* Meta-x */
+  { ISFUNC, rl_yank_pop },	/* Meta-y */
+  { ISFUNC, (Function *)0x0 },	/* Meta-z */
+
+  /* Final punctuation. */
+  { ISFUNC, (Function *)0x0 },	/* Meta-{ */
+  { ISFUNC, (Function *)0x0 },	/* Meta-| */
+  { ISFUNC, (Function *)0x0 },	/* Meta-} */
+  { ISFUNC, rl_tilde_expand },	/* Meta-~ */
+  { ISFUNC, rl_backward_kill_word }, /* Meta-rubout */
+
+#if KEYMAP_SIZE > 128
+  /* Undefined keys. */
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 }
+#endif /* KEYMAP_SIZE > 128 */
+};
+
+KEYMAP_ENTRY_ARRAY emacs_ctlx_keymap = {
+
+  /* Control keys. */
+  { ISFUNC, (Function *)0x0 },		/* Control-@ */
+  { ISFUNC, (Function *)0x0 },		/* Control-a */
+  { ISFUNC, (Function *)0x0 },		/* Control-b */
+  { ISFUNC, (Function *)0x0 },		/* Control-c */
+  { ISFUNC, (Function *)0x0 },		/* Control-d */
+  { ISFUNC, (Function *)0x0 },		/* Control-e */
+  { ISFUNC, (Function *)0x0 },		/* Control-f */
+  { ISFUNC, rl_abort },			/* Control-g */
+  { ISFUNC, (Function *)0x0 },		/* Control-h */
+  { ISFUNC, (Function *)0x0 },		/* Control-i */
+  { ISFUNC, (Function *)0x0 },		/* Control-j */
+  { ISFUNC, (Function *)0x0 },		/* Control-k */
+  { ISFUNC, (Function *)0x0 },		/* Control-l */
+  { ISFUNC, (Function *)0x0 },		/* Control-m */
+  { ISFUNC, (Function *)0x0 },		/* Control-n */
+  { ISFUNC, (Function *)0x0 },		/* Control-o */
+  { ISFUNC, (Function *)0x0 },		/* Control-p */
+  { ISFUNC, (Function *)0x0 },		/* Control-q */
+  { ISFUNC, rl_re_read_init_file },	/* Control-r */
+  { ISFUNC, (Function *)0x0 },		/* Control-s */
+  { ISFUNC, (Function *)0x0 },		/* Control-t */
+  { ISFUNC, rl_undo_command },		/* Control-u */
+  { ISFUNC, (Function *)0x0 },		/* Control-v */
+  { ISFUNC, (Function *)0x0 },		/* Control-w */
+  { ISFUNC, (Function *)0x0 },		/* Control-x */
+  { ISFUNC, (Function *)0x0 },		/* Control-y */
+  { ISFUNC, (Function *)0x0 },		/* Control-z */
+  { ISFUNC, (Function *)0x0 },		/* Control-[ */
+  { ISFUNC, (Function *)0x0 },		/* Control-\ */
+  { ISFUNC, (Function *)0x0 },		/* Control-] */
+  { ISFUNC, (Function *)0x0 },		/* Control-^ */
+  { ISFUNC, (Function *)0x0 },		/* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, (Function *)0x0 },		/* SPACE */
+  { ISFUNC, (Function *)0x0 },		/* ! */
+  { ISFUNC, (Function *)0x0 },		/* " */
+  { ISFUNC, (Function *)0x0 },		/* # */
+  { ISFUNC, (Function *)0x0 },		/* $ */
+  { ISFUNC, (Function *)0x0 },		/* % */
+  { ISFUNC, (Function *)0x0 },		/* & */
+  { ISFUNC, (Function *)0x0 },		/* ' */
+  { ISFUNC, rl_start_kbd_macro },	/* ( */
+  { ISFUNC, rl_end_kbd_macro  },	/* ) */
+  { ISFUNC, (Function *)0x0 },		/* * */
+  { ISFUNC, (Function *)0x0 },		/* + */
+  { ISFUNC, (Function *)0x0 },		/* , */
+  { ISFUNC, (Function *)0x0 },		/* - */
+  { ISFUNC, (Function *)0x0 },		/* . */
+  { ISFUNC, (Function *)0x0 },		/* / */
+
+  /* Regular digits. */
+  { ISFUNC, (Function *)0x0 },		/* 0 */
+  { ISFUNC, (Function *)0x0 },		/* 1 */
+  { ISFUNC, (Function *)0x0 },		/* 2 */
+  { ISFUNC, (Function *)0x0 },		/* 3 */
+  { ISFUNC, (Function *)0x0 },		/* 4 */
+  { ISFUNC, (Function *)0x0 },		/* 5 */
+  { ISFUNC, (Function *)0x0 },		/* 6 */
+  { ISFUNC, (Function *)0x0 },		/* 7 */
+  { ISFUNC, (Function *)0x0 },		/* 8 */
+  { ISFUNC, (Function *)0x0 },		/* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, (Function *)0x0 },	/* : */
+  { ISFUNC, (Function *)0x0 },	/* ; */
+  { ISFUNC, (Function *)0x0 },	/* < */
+  { ISFUNC, (Function *)0x0 },	/* = */
+  { ISFUNC, (Function *)0x0 },	/* > */
+  { ISFUNC, (Function *)0x0 },	/* ? */
+  { ISFUNC, (Function *)0x0 },	/* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_do_lowercase_version },	/* A */
+  { ISFUNC, rl_do_lowercase_version },	/* B */
+  { ISFUNC, rl_do_lowercase_version },	/* C */
+  { ISFUNC, rl_do_lowercase_version },	/* D */
+  { ISFUNC, rl_do_lowercase_version },	/* E */
+  { ISFUNC, rl_do_lowercase_version },	/* F */
+  { ISFUNC, rl_do_lowercase_version },	/* G */
+  { ISFUNC, rl_do_lowercase_version },	/* H */
+  { ISFUNC, rl_do_lowercase_version },	/* I */
+  { ISFUNC, rl_do_lowercase_version },	/* J */
+  { ISFUNC, rl_do_lowercase_version },	/* K */
+  { ISFUNC, rl_do_lowercase_version },	/* L */
+  { ISFUNC, rl_do_lowercase_version },	/* M */
+  { ISFUNC, rl_do_lowercase_version },	/* N */
+  { ISFUNC, rl_do_lowercase_version },	/* O */
+  { ISFUNC, rl_do_lowercase_version },	/* P */
+  { ISFUNC, rl_do_lowercase_version },	/* Q */
+  { ISFUNC, rl_do_lowercase_version },	/* R */
+  { ISFUNC, rl_do_lowercase_version },	/* S */
+  { ISFUNC, rl_do_lowercase_version },	/* T */
+  { ISFUNC, rl_do_lowercase_version },	/* U */
+  { ISFUNC, rl_do_lowercase_version },	/* V */
+  { ISFUNC, rl_do_lowercase_version },	/* W */
+  { ISFUNC, rl_do_lowercase_version },	/* X */
+  { ISFUNC, rl_do_lowercase_version },	/* Y */
+  { ISFUNC, rl_do_lowercase_version },	/* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, (Function *)0x0 },		/* [ */
+  { ISFUNC, (Function *)0x0 },		/* \ */
+  { ISFUNC, (Function *)0x0 },		/* ] */
+  { ISFUNC, (Function *)0x0 },		/* ^ */
+  { ISFUNC, (Function *)0x0 },		/* _ */
+  { ISFUNC, (Function *)0x0 },		/* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, (Function *)0x0 },		/* a */
+  { ISFUNC, (Function *)0x0 },		/* b */
+  { ISFUNC, (Function *)0x0 },		/* c */
+  { ISFUNC, (Function *)0x0 },		/* d */
+  { ISFUNC, rl_call_last_kbd_macro },	/* e */
+  { ISFUNC, (Function *)0x0 },		/* f */
+  { ISFUNC, (Function *)0x0 },		/* g */
+  { ISFUNC, (Function *)0x0 },		/* h */
+  { ISFUNC, (Function *)0x0 },		/* i */
+  { ISFUNC, (Function *)0x0 },		/* j */
+  { ISFUNC, (Function *)0x0 },		/* k */
+  { ISFUNC, (Function *)0x0 },		/* l */
+  { ISFUNC, (Function *)0x0 },		/* m */
+  { ISFUNC, (Function *)0x0 },		/* n */
+  { ISFUNC, (Function *)0x0 },		/* o */
+  { ISFUNC, (Function *)0x0 },		/* p */
+  { ISFUNC, (Function *)0x0 },		/* q */
+  { ISFUNC, (Function *)0x0 },		/* r */
+  { ISFUNC, (Function *)0x0 },		/* s */
+  { ISFUNC, (Function *)0x0 },		/* t */
+  { ISFUNC, (Function *)0x0 },		/* u */
+  { ISFUNC, (Function *)0x0 },		/* v */
+  { ISFUNC, (Function *)0x0 },		/* w */
+  { ISFUNC, (Function *)0x0 },		/* x */
+  { ISFUNC, (Function *)0x0 },		/* y */
+  { ISFUNC, (Function *)0x0 },		/* z */
+
+  /* Final punctuation. */
+  { ISFUNC, (Function *)0x0 },		/* { */
+  { ISFUNC, (Function *)0x0 },		/* | */
+  { ISFUNC, (Function *)0x0 },		/* } */
+  { ISFUNC, (Function *)0x0 },		/* ~ */
+  { ISFUNC, rl_backward_kill_line },	/* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+  /* Undefined keys. */
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 }
+#endif /* KEYMAP_SIZE > 128 */
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/examples/Inputrc	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,65 @@
+# My ~/.inputrc file is in -*- text -*- for easy editing with Emacs.
+#
+# Notice the various bindings which are conditionalized depending
+# on which program is running, or what terminal is active.
+#
+
+# In all programs, all terminals, make sure this is bound.
+"\C-x\C-r": re-read-init-file
+
+# Hp terminals (and some others) have ugly default behaviour for C-h.
+"\C-h": backward-delete-char
+"\e\C-h": backward-kill-word
+"\C-xd": dump-functions
+
+# In xterm windows, make the arrow keys do the right thing.
+$if TERM=xterm
+"\e[A": previous-history
+"\e[B": next-history
+"\e[C": forward-char
+"\e[D": backward-char
+
+# alternate arrow key prefix
+"\eOA": previous-history
+"\eOB": next-history
+"\eOC": forward-char
+"\eOD": backward-char
+
+# Under Xterm in Bash, we bind local Function keys to do something useful.
+$if Bash
+"\e[11~": "Function Key 1"
+"\e[12~": "Function Key 2"
+"\e[13~": "Function Key 3"
+"\e[14~": "Function Key 4"
+"\e[15~": "Function Key 5"
+
+# I know the following escape sequence numbers are 1 greater than
+# the function key.  Don't ask me why, I didn't design the xterm terminal.
+"\e[17~": "Function Key 6"
+"\e[18~": "Function Key 7"
+"\e[19~": "Function Key 8"
+"\e[20~": "Function Key 9"
+"\e[21~": "Function Key 10"
+$endif
+$endif
+
+# For Bash, all terminals, add some Bash specific hacks.
+$if Bash
+"\C-xv": show-bash-version
+"\C-x\C-e": shell-expand-line
+
+# Here is one for editing my path.
+"\C-xp": "$PATH\C-x\C-e\C-e\"\C-aPATH=\":\C-b"
+
+# Make C-x r read my mail in emacs.
+# "\C-xr": "emacs -f rmail\C-j"
+$endif
+
+# For FTP, different hacks:
+$if Ftp
+"\C-xg": "get \M-?"
+"\C-xt": "put \M-?"
+"\M-.": yank-last-arg
+$endif
+
+" ": self-insert
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/examples/fileman.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,425 @@
+/* fileman.c -- A tiny application which demonstrates how to use the
+   GNU Readline library.  This application interactively allows users
+   to manipulate files and their modes. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+extern char *getwd ();
+extern char *xmalloc ();
+
+/* The names of functions that actually do the manipulation. */
+int com_list (), com_view (), com_rename (), com_stat (), com_pwd ();
+int com_delete (), com_help (), com_cd (), com_quit ();
+
+/* A structure which contains information on the commands this program
+   can understand. */
+
+typedef struct {
+  char *name;			/* User printable name of the function. */
+  Function *func;		/* Function to call to do the job. */
+  char *doc;			/* Documentation for this function.  */
+} COMMAND;
+
+COMMAND commands[] = {
+  { "cd", com_cd, "Change to directory DIR" },
+  { "delete", com_delete, "Delete FILE" },
+  { "help", com_help, "Display this text" },
+  { "?", com_help, "Synonym for `help'" },
+  { "list", com_list, "List files in DIR" },
+  { "ls", com_list, "Synonym for `list'" },
+  { "pwd", com_pwd, "Print the current working directory" },
+  { "quit", com_quit, "Quit using Fileman" },
+  { "rename", com_rename, "Rename FILE to NEWNAME" },
+  { "stat", com_stat, "Print out statistics on FILE" },
+  { "view", com_view, "View the contents of FILE" },
+  { (char *)NULL, (Function *)NULL, (char *)NULL }
+};
+
+/* Forward declarations. */
+char *stripwhite ();
+COMMAND *find_command ();
+
+/* The name of this program, as taken from argv[0]. */
+char *progname;
+
+/* When non-zero, this global means the user is done using this program. */
+int done;
+
+char *
+dupstr (s)
+     int s;
+{
+  char *r;
+
+  r = xmalloc (strlen (s) + 1);
+  strcpy (r, s);
+  return (r);
+}
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char *line, *s;
+
+  progname = argv[0];
+
+  initialize_readline ();	/* Bind our completer. */
+
+  /* Loop reading and executing lines until the user quits. */
+  for ( ; done == 0; )
+    {
+      line = readline ("FileMan: ");
+
+      if (!line)
+        break;
+
+      /* Remove leading and trailing whitespace from the line.
+         Then, if there is anything left, add it to the history list
+         and execute it. */
+      s = stripwhite (line);
+
+      if (*s)
+        {
+          add_history (s);
+          execute_line (s);
+        }
+
+      free (line);
+    }
+  exit (0);
+}
+
+/* Execute a command line. */
+int
+execute_line (line)
+     char *line;
+{
+  register int i;
+  COMMAND *command;
+  char *word;
+
+  /* Isolate the command word. */
+  i = 0;
+  while (line[i] && whitespace (line[i]))
+    i++;
+  word = line + i;
+
+  while (line[i] && !whitespace (line[i]))
+    i++;
+
+  if (line[i])
+    line[i++] = '\0';
+
+  command = find_command (word);
+
+  if (!command)
+    {
+      fprintf (stderr, "%s: No such command for FileMan.\n", word);
+      return (-1);
+    }
+
+  /* Get argument to command, if any. */
+  while (whitespace (line[i]))
+    i++;
+
+  word = line + i;
+
+  /* Call the function. */
+  return ((*(command->func)) (word));
+}
+
+/* Look up NAME as the name of a command, and return a pointer to that
+   command.  Return a NULL pointer if NAME isn't a command name. */
+COMMAND *
+find_command (name)
+     char *name;
+{
+  register int i;
+
+  for (i = 0; commands[i].name; i++)
+    if (strcmp (name, commands[i].name) == 0)
+      return (&commands[i]);
+
+  return ((COMMAND *)NULL);
+}
+
+/* Strip whitespace from the start and end of STRING.  Return a pointer
+   into STRING. */
+char *
+stripwhite (string)
+     char *string;
+{
+  register char *s, *t;
+
+  for (s = string; whitespace (*s); s++)
+    ;
+    
+  if (*s == 0)
+    return (s);
+
+  t = s + strlen (s) - 1;
+  while (t > s && whitespace (*t))
+    t--;
+  *++t = '\0';
+
+  return s;
+}
+
+/* **************************************************************** */
+/*                                                                  */
+/*                  Interface to Readline Completion                */
+/*                                                                  */
+/* **************************************************************** */
+
+char *command_generator ();
+char **fileman_completion ();
+
+/* Tell the GNU Readline library how to complete.  We want to try to complete
+   on command names if this is the first word in the line, or on filenames
+   if not. */
+initialize_readline ()
+{
+  /* Allow conditional parsing of the ~/.inputrc file. */
+  rl_readline_name = "FileMan";
+
+  /* Tell the completer that we want a crack first. */
+  rl_attempted_completion_function = (CPPFunction *)fileman_completion;
+}
+
+/* Attempt to complete on the contents of TEXT.  START and END show the
+   region of TEXT that contains the word to complete.  We can use the
+   entire line in case we want to do some simple parsing.  Return the
+   array of matches, or NULL if there aren't any. */
+char **
+fileman_completion (text, start, end)
+     char *text;
+     int start, end;
+{
+  char **matches;
+
+  matches = (char **)NULL;
+
+  /* If this word is at the start of the line, then it is a command
+     to complete.  Otherwise it is the name of a file in the current
+     directory. */
+  if (start == 0)
+    matches = completion_matches (text, command_generator);
+
+  return (matches);
+}
+
+/* Generator function for command completion.  STATE lets us know whether
+   to start from scratch; without any state (i.e. STATE == 0), then we
+   start at the top of the list. */
+char *
+command_generator (text, state)
+     char *text;
+     int state;
+{
+  static int list_index, len;
+  char *name;
+
+  /* If this is a new word to complete, initialize now.  This includes
+     saving the length of TEXT for efficiency, and initializing the index
+     variable to 0. */
+  if (!state)
+    {
+      list_index = 0;
+      len = strlen (text);
+    }
+
+  /* Return the next name which partially matches from the command list. */
+  while (name = commands[list_index].name)
+    {
+      list_index++;
+
+      if (strncmp (name, text, len) == 0)
+        return (dupstr(name));
+    }
+
+  /* If no names matched, then return NULL. */
+  return ((char *)NULL);
+}
+
+/* **************************************************************** */
+/*                                                                  */
+/*                       FileMan Commands                           */
+/*                                                                  */
+/* **************************************************************** */
+
+/* String to pass to system ().  This is for the LIST, VIEW and RENAME
+   commands. */
+static char syscom[1024];
+
+/* List the file(s) named in arg. */
+com_list (arg)
+     char *arg;
+{
+  if (!arg)
+    arg = "";
+
+  sprintf (syscom, "ls -FClg %s", arg);
+  return (system (syscom));
+}
+
+com_view (arg)
+     char *arg;
+{
+  if (!valid_argument ("view", arg))
+    return 1;
+
+  sprintf (syscom, "more %s", arg);
+  return (system (syscom));
+}
+
+com_rename (arg)
+     char *arg;
+{
+  too_dangerous ("rename");
+  return (1);
+}
+
+com_stat (arg)
+     char *arg;
+{
+  struct stat finfo;
+
+  if (!valid_argument ("stat", arg))
+    return (1);
+
+  if (stat (arg, &finfo) == -1)
+    {
+      perror (arg);
+      return (1);
+    }
+
+  printf ("Statistics for `%s':\n", arg);
+
+  printf ("%s has %d link%s, and is %d byte%s in length.\n", arg,
+          finfo.st_nlink,
+          (finfo.st_nlink == 1) ? "" : "s",
+          finfo.st_size,
+          (finfo.st_size == 1) ? "" : "s");
+  printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime));
+  printf ("      Last access at: %s", ctime (&finfo.st_atime));
+  printf ("    Last modified at: %s", ctime (&finfo.st_mtime));
+  return (0);
+}
+
+com_delete (arg)
+     char *arg;
+{
+  too_dangerous ("delete");
+  return (1);
+}
+
+/* Print out help for ARG, or for all of the commands if ARG is
+   not present. */
+com_help (arg)
+     char *arg;
+{
+  register int i;
+  int printed = 0;
+
+  for (i = 0; commands[i].name; i++)
+    {
+      if (!*arg || (strcmp (arg, commands[i].name) == 0))
+        {
+          printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
+          printed++;
+        }
+    }
+
+  if (!printed)
+    {
+      printf ("No commands match `%s'.  Possibilties are:\n", arg);
+
+      for (i = 0; commands[i].name; i++)
+        {
+          /* Print in six columns. */
+          if (printed == 6)
+            {
+              printed = 0;
+              printf ("\n");
+            }
+
+          printf ("%s\t", commands[i].name);
+          printed++;
+        }
+
+      if (printed)
+        printf ("\n");
+    }
+  return (0);
+}
+
+/* Change to the directory ARG. */
+com_cd (arg)
+     char *arg;
+{
+  if (chdir (arg) == -1)
+    {
+      perror (arg);
+      return 1;
+    }
+
+  com_pwd ("");
+  return (0);
+}
+
+/* Print out the current working directory. */
+com_pwd (ignore)
+     char *ignore;
+{
+  char dir[1024], *s;
+
+  s = getwd (dir);
+  if (s == 0)
+    {
+      printf ("Error getting pwd: %s\n", dir);
+      return 1;
+    }
+
+  printf ("Current directory is %s\n", dir);
+  return 0;
+}
+
+/* The user wishes to quit using this program.  Just set DONE non-zero. */
+com_quit (arg)
+     char *arg;
+{
+  done = 1;
+  return (0);
+}
+
+/* Function which tells you that you can't do this. */
+too_dangerous (caller)
+     char *caller;
+{
+  fprintf (stderr,
+           "%s: Too dangerous for me to distribute.  Write it yourself.\n",
+           caller);
+}
+
+/* Return non-zero if ARG is a valid argument for CALLER, else print
+   an error message and return zero. */
+int
+valid_argument (caller, arg)
+     char *caller, *arg;
+{
+  if (!arg || !*arg)
+    {
+      fprintf (stderr, "%s: Argument required.\n", caller);
+      return (0);
+    }
+
+  return (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/examples/histexamp.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,82 @@
+main ()
+{
+  char line[1024], *t;
+  int len, done = 0;
+
+  line[0] = 0;
+
+  using_history ();
+  while (!done)
+    {
+      printf ("history$ ");
+      fflush (stdout);
+      t = fgets (line, sizeof (line) - 1, stdin);
+      if (t && *t)
+        {
+          len = strlen (t);
+          if (t[len - 1] == '\n')
+            t[len - 1] = '\0';
+        }
+
+      if (!t)
+        strcpy (line, "quit");
+
+      if (line[0])
+        {
+          char *expansion;
+          int result;
+
+          using_history ();
+
+          result = history_expand (line, &expansion);
+          if (result)
+            fprintf (stderr, "%s\n", expansion);
+
+          if (result < 0 || result == 2)
+            {
+              free (expansion);
+              continue;
+            }
+
+          add_history (expansion);
+          strncpy (line, expansion, sizeof (line) - 1);
+          free (expansion);
+        }
+
+      if (strcmp (line, "quit") == 0)
+        done = 1;
+      else if (strcmp (line, "save") == 0)
+        write_history ("history_file");
+      else if (strcmp (line, "read") == 0)
+        read_history ("history_file");
+      else if (strcmp (line, "list") == 0)
+        {
+          register HIST_ENTRY **the_list;
+          register int i;
+
+          the_list = history_list ();
+          if (the_list)
+            for (i = 0; the_list[i]; i++)
+              printf ("%d: %s\n", i + history_base, the_list[i]->line);
+        }
+      else if (strncmp (line, "delete", 6) == 0)
+        {
+          int which;
+          if ((sscanf (line + 6, "%d", &which)) == 1)
+            {
+              HIST_ENTRY *entry = remove_history (which);
+              if (!entry)
+                fprintf (stderr, "No such entry %d\n", which);
+              else
+                {
+                  free (entry->line);
+                  free (entry);
+                }
+            }
+          else
+            {
+              fprintf (stderr, "non-numeric arg given to `delete'\n");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/examples/manexamp.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,94 @@
+/* manexamp.c -- The examples which appear in the documentation are here. */
+
+#include <stdio.h>
+#include <readline/readline.h>
+
+
+/* **************************************************************** */
+/*                                                                  */
+*   			How to Emulate gets ()			    */
+/*                                                                  */
+/* **************************************************************** */
+
+/* A static variable for holding the line. */
+static char *line_read = (char *)NULL;
+
+/* Read a string, and return a pointer to it.  Returns NULL on EOF. */
+char *
+rl_gets ()
+{
+  /* If the buffer has already been allocated, return the memory
+     to the free pool. */
+  if (line_read)
+    {
+      free (line_read);
+      line_read = (char *)NULL;
+    }
+
+  /* Get a line from the user. */
+  line_read = readline ("");
+
+  /* If the line has any text in it, save it on the history. */
+  if (line_read && *line_read)
+    add_history (line_read);
+
+  return (line_read);
+}
+
+/* **************************************************************** */
+/*                                                                  */
+/*        Writing a Function to be Called by Readline.              */
+/*                                                                  */
+/* **************************************************************** */
+
+/* Invert the case of the COUNT following characters. */
+invert_case_line (count, key)
+     int count, key;
+{
+  register int start, end;
+
+  start = rl_point;
+
+  if (count < 0)
+    {
+      direction = -1;
+      count = -count;
+    }
+  else
+    direction = 1;
+      
+  /* Find the end of the range to modify. */
+  end = start + (count * direction);
+
+  /* Force it to be within range. */
+  if (end > rl_end)
+    end = rl_end;
+  else if (end < 0)
+    end = -1;
+
+  if (start > end)
+    {
+      int temp = start;
+      start = end;
+      end = temp;
+    }
+
+  if (start == end)
+    return;
+
+  /* Tell readline that we are modifying the line, so save the undo
+     information. */
+  rl_modifying (start, end);
+
+  for (; start != end; start += direction)
+    {
+      if (uppercase_p (rl_line_buffer[start]))
+	rl_line_buffer[start] = to_lower (rl_line_buffer[start]);
+      else if (lowercase_p (rl_line_buffer[start]))
+	rl_line_buffer[start] = to_upper (rl_line_buffer[start]);
+    }
+
+  /* Move point to on top of the last character changed. */
+  rl_point = end - direction;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/funmap.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,299 @@
+/* funmap.c -- attach names to functions. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+#if !defined (BUFSIZ)
+#include <stdio.h>
+#endif /* BUFSIZ */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "rlconf.h"
+#include "readline.h"
+
+static int qsort_string_compare ();
+
+FUNMAP **funmap = (FUNMAP **)NULL;
+static int funmap_size = 0;
+static int funmap_entry = 0;
+
+/* After initializing the function map, this is the index of the first
+   program specific function. */
+int funmap_program_specific_entry_start;
+
+static FUNMAP default_funmap[] = {
+
+  { "abort", rl_abort },
+  { "accept-line", rl_newline },
+  { "arrow-key-prefix", rl_arrow_keys },
+  { "backward-char", rl_backward },
+  { "backward-delete-char", rl_rubout },
+  { "backward-kill-line", rl_backward_kill_line },
+  { "backward-kill-word", rl_backward_kill_word },
+  { "backward-word", rl_backward_word },
+  { "beginning-of-history", rl_beginning_of_history },
+  { "beginning-of-line", rl_beg_of_line },
+  { "call-last-kbd-macro", rl_call_last_kbd_macro },
+  { "capitalize-word", rl_capitalize_word },
+  { "clear-screen", rl_clear_screen },
+  { "complete", rl_complete },
+  { "delete-char", rl_delete },
+  { "delete-horizontal-space", rl_delete_horizontal_space },
+  { "digit-argument", rl_digit_argument },
+  { "do-lowercase-version", rl_do_lowercase_version },
+  { "downcase-word", rl_downcase_word },
+  { "dump-functions", rl_dump_functions },
+  { "emacs-editing-mode", rl_emacs_editing_mode },
+  { "end-kbd-macro", rl_end_kbd_macro },
+  { "end-of-history", rl_end_of_history },
+  { "end-of-line", rl_end_of_line },
+  { "forward-char", rl_forward },
+  { "forward-search-history", rl_forward_search_history },
+  { "forward-word", rl_forward_word },
+  { "history-search-backward", rl_history_search_backward },
+  { "history-search-forward", rl_history_search_forward },
+  { "insert-completions", rl_insert_completions },
+  { "kill-whole-line", rl_kill_full_line },
+  { "kill-line", rl_kill_line },
+  { "kill-word", rl_kill_word },
+  { "next-history", rl_get_next_history },
+  { "non-incremental-forward-search-history", rl_noninc_forward_search },
+  { "non-incremental-reverse-search-history", rl_noninc_reverse_search },
+  { "non-incremental-forward-search-history-again", rl_noninc_forward_search_again },
+  { "non-incremental-reverse-search-history-again", rl_noninc_reverse_search_again },
+  { "possible-completions", rl_possible_completions },
+  { "previous-history", rl_get_previous_history },
+  { "quoted-insert", rl_quoted_insert },
+  { "re-read-init-file", rl_re_read_init_file },
+  { "redraw-current-line", rl_refresh_line},
+  { "reverse-search-history", rl_reverse_search_history },
+  { "revert-line", rl_revert_line },
+  { "self-insert", rl_insert },
+  { "start-kbd-macro", rl_start_kbd_macro },
+  { "tab-insert", rl_tab_insert },
+  { "tilde-expand", rl_tilde_expand },
+  { "transpose-chars", rl_transpose_chars },
+  { "transpose-words", rl_transpose_words },
+  { "tty-status", rl_tty_status },
+  { "undo", rl_undo_command },
+  { "universal-argument", rl_universal_argument },
+  { "unix-line-discard", rl_unix_line_discard },
+  { "unix-word-rubout", rl_unix_word_rubout },
+  { "upcase-word", rl_upcase_word },
+  { "yank", rl_yank },
+  { "yank-last-arg", rl_yank_last_arg },
+  { "yank-nth-arg", rl_yank_nth_arg },
+  { "yank-pop", rl_yank_pop },
+
+#if defined (VI_MODE)
+  { "vi-append-eol", rl_vi_append_eol },
+  { "vi-append-mode", rl_vi_append_mode },
+  { "vi-arg-digit", rl_vi_arg_digit },
+  { "vi-bWord", rl_vi_bWord },
+  { "vi-bracktype", rl_vi_bracktype },
+  { "vi-bword", rl_vi_bword },
+  { "vi-change-case", rl_vi_change_case },
+  { "vi-change-char", rl_vi_change_char },
+  { "vi-change-to", rl_vi_change_to },
+  { "vi-char-search", rl_vi_char_search },
+  { "vi-column", rl_vi_column },
+  { "vi-comment", rl_vi_comment },
+  { "vi-complete", rl_vi_complete },
+  { "vi-delete", rl_vi_delete },
+  { "vi-delete-to", rl_vi_delete_to },
+  { "vi-eWord", rl_vi_eWord },
+  { "vi-editing-mode", rl_vi_editing_mode },
+  { "vi-end-word", rl_vi_end_word },
+  { "vi-eof-maybe", rl_vi_eof_maybe },
+  { "vi-eword", rl_vi_eword },
+  { "vi-fWord", rl_vi_fWord },
+  { "vi-first-print", rl_vi_first_print },
+  { "vi-fword", rl_vi_fword },
+  { "vi-insert-beg", rl_vi_insert_beg },
+  { "vi-insertion-mode", rl_vi_insertion_mode },
+  { "vi-match", rl_vi_match },
+  { "vi-movement-mode", rl_vi_movement_mode },
+  { "vi-next-word", rl_vi_next_word },
+  { "vi-overstrike", rl_vi_overstrike },
+  { "vi-overstrike-delete", rl_vi_overstrike_delete },
+  { "vi-prev-word", rl_vi_prev_word },
+  { "vi-put", rl_vi_put },
+  { "vi-redo", rl_vi_redo },
+  { "vi-replace", rl_vi_replace },
+  { "vi-search", rl_vi_search },
+  { "vi-search-again", rl_vi_search_again },
+  { "vi-subst", rl_vi_subst },
+  { "vi-tilde-expand", rl_vi_tilde_expand },
+  { "vi-yank-arg", rl_vi_yank_arg },
+  { "vi-yank-to", rl_vi_yank_to },
+#endif /* VI_MODE */
+
+ {(char *)NULL, (Function *)NULL }
+};
+
+rl_add_funmap_entry (name, function)
+     char *name;
+     Function *function;
+{
+  if (funmap_entry + 2 >= funmap_size)
+    if (!funmap)
+      funmap = (FUNMAP **)xmalloc ((funmap_size = 80) * sizeof (FUNMAP *));
+    else
+      funmap =
+	(FUNMAP **)xrealloc (funmap, (funmap_size += 80) * sizeof (FUNMAP *));
+  
+  funmap[funmap_entry] = (FUNMAP *)xmalloc (sizeof (FUNMAP));
+  funmap[funmap_entry]->name = name;
+  funmap[funmap_entry]->function = function;
+
+  funmap[++funmap_entry] = (FUNMAP *)NULL;
+  return funmap_entry;
+}
+
+static int funmap_initialized = 0;
+
+/* Make the funmap contain all of the default entries. */
+void
+rl_initialize_funmap ()
+{
+  register int i;
+
+  if (funmap_initialized)
+    return;
+
+  for (i = 0; default_funmap[i].name; i++)
+    rl_add_funmap_entry (default_funmap[i].name, default_funmap[i].function);
+
+  funmap_initialized = 1;
+  funmap_program_specific_entry_start = i;
+}
+
+/* Produce a NULL terminated array of known function names.  The array
+   is sorted.  The array itself is allocated, but not the strings inside.
+   You should free () the array when you done, but not the pointrs. */
+char **
+rl_funmap_names ()
+{
+  char **result = (char **)NULL;
+  int result_size, result_index;
+
+  result_size = result_index = 0;
+
+  /* Make sure that the function map has been initialized. */
+  rl_initialize_funmap ();
+
+  for (result_index = 0; funmap[result_index]; result_index++)
+    {
+      if (result_index + 2 > result_size)
+	{
+	  if (!result)
+	    result = (char **)xmalloc ((result_size = 20) * sizeof (char *));
+	  else
+	    result = (char **)
+	      xrealloc (result, (result_size += 20) * sizeof (char *));
+	}
+
+      result[result_index] = funmap[result_index]->name;
+      result[result_index + 1] = (char *)NULL;
+    }
+
+  qsort (result, result_index, sizeof (char *), qsort_string_compare);
+  return (result);
+}
+
+/* Stupid comparison routine for qsort () ing strings. */
+static int
+qsort_string_compare (s1, s2)
+     register char **s1, **s2;
+{
+  int r;
+
+  r = **s1 - **s2;
+  if (r == 0)
+    r = strcmp (*s1, *s2);
+  return r;
+}
+
+/* Things that mean `Control'. */
+char *possible_control_prefixes[] = {
+  "Control-", "C-", "CTRL-", (char *)NULL
+};
+
+char *possible_meta_prefixes[] = {
+  "Meta", "M-", (char *)NULL
+};
+
+#if defined (STATIC_MALLOC)
+
+/* **************************************************************** */
+/*								    */
+/*			xmalloc and xrealloc ()		     	    */
+/*								    */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "history: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/history.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,2216 @@
+/* History.c -- standalone history library */
+
+/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+
+   This file contains the GNU History Library (the Library), a set of
+   routines for managing the text of previously typed lines.
+
+   The Library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   The Library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* The goal is to make the implementation transparent, so that you
+   don't have to know what data types are used, just what functions
+   you can call.  I think I have done that. */
+#define READLINE_LIBRARY
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+#include <errno.h>
+
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "memalloc.h"
+#include "history.h"
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+#define STREQ(a, b)	(((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0))
+#define STREQN(a, b, n)	(((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0))
+
+#ifndef savestring
+#  ifndef strcpy
+extern char *strcpy ();
+#  endif
+#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
+#endif
+
+#ifndef whitespace
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#endif
+
+#ifndef digit_p
+#define digit_p(c)  ((c) >= '0' && (c) <= '9')
+#endif
+
+#ifndef digit_value
+#define digit_value(c) ((c) - '0')
+#endif
+
+#ifndef member
+#  ifndef strchr
+extern char *strchr ();
+#  endif
+#define member(c, s) ((c) ? ((char *)strchr ((s), (c)) != (char *)NULL) : 0)
+#endif
+
+/* Possible history errors passed to hist_error. */
+#define EVENT_NOT_FOUND 0
+#define BAD_WORD_SPEC	1
+#define SUBST_FAILED	2
+#define BAD_MODIFIER	3
+
+static char error_pointer;
+
+static char *subst_lhs;
+static char *subst_rhs;
+static int subst_lhs_len = 0;
+static int subst_rhs_len = 0;
+
+static char *get_history_word_specifier ();
+static char *history_find_word ();
+
+#if defined (SHELL)
+extern char *single_quote ();
+#endif
+
+/* **************************************************************** */
+/*								    */
+/*			History Functions			    */
+/*								    */
+/* **************************************************************** */
+
+/* An array of HIST_ENTRY.  This is where we store the history. */
+static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
+
+/* Non-zero means that we have enforced a limit on the amount of
+   history that we save. */
+static int history_stifled = 0;
+
+/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
+   entries to remember. */
+int max_input_history;
+
+/* The current location of the interactive history pointer.  Just makes
+   life easier for outside callers. */
+static int history_offset = 0;
+
+/* The number of strings currently stored in the input_history list. */
+int history_length = 0;
+
+/* The current number of slots allocated to the input_history. */
+static int history_size = 0;
+
+/* The number of slots to increase the_history by. */
+#define DEFAULT_HISTORY_GROW_SIZE 50
+
+/* The character that represents the start of a history expansion
+   request.  This is usually `!'. */
+char history_expansion_char = '!';
+
+/* The character that invokes word substitution if found at the start of
+   a line.  This is usually `^'. */
+char history_subst_char = '^';
+
+/* During tokenization, if this character is seen as the first character
+   of a word, then it, and all subsequent characters upto a newline are
+   ignored.  For a Bourne shell, this should be '#'.  Bash special cases
+   the interactive comment character to not be a comment delimiter. */
+char history_comment_char = '\0';
+
+/* The list of characters which inhibit the expansion of text if found
+   immediately following history_expansion_char. */
+char *history_no_expand_chars = " \t\n\r=";
+
+/* The logical `base' of the history array.  It defaults to 1. */
+int history_base = 1;
+
+/* Return the current HISTORY_STATE of the history. */
+HISTORY_STATE *
+history_get_history_state ()
+{
+  HISTORY_STATE *state;
+
+  state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
+  state->entries = the_history;
+  state->offset = history_offset;
+  state->length = history_length;
+  state->size = history_size;
+  state->flags = 0;
+  if (history_stifled)
+    state->flags |= HS_STIFLED;
+
+  return (state);
+}
+
+/* Set the state of the current history array to STATE. */
+void
+history_set_history_state (state)
+     HISTORY_STATE *state;
+{
+  the_history = state->entries;
+  history_offset = state->offset;
+  history_length = state->length;
+  history_size = state->size;
+  if (state->flags & HS_STIFLED)
+    history_stifled = 1;
+}
+
+/* Begin a session in which the history functions might be used.  This
+   initializes interactive variables. */
+void
+using_history ()
+{
+  history_offset = history_length;
+}
+
+/* Return the number of bytes that the primary history entries are using.
+   This just adds up the lengths of the_history->lines. */
+int
+history_total_bytes ()
+{
+  register int i, result;
+
+  result = 0;
+
+  for (i = 0; the_history && the_history[i]; i++)
+    result += strlen (the_history[i]->line);
+
+  return (result);
+}
+
+/* Place STRING at the end of the history list.  The data field
+   is  set to NULL. */
+void
+add_history (string)
+     char *string;
+{
+  HIST_ENTRY *temp;
+
+  if (history_stifled && (history_length == max_input_history))
+    {
+      register int i;
+
+      /* If the history is stifled, and history_length is zero,
+	 and it equals max_input_history, we don't save items. */
+      if (history_length == 0)
+	return;
+
+      /* If there is something in the slot, then remove it. */
+      if (the_history[0])
+	{
+	  free (the_history[0]->line);
+	  free (the_history[0]);
+	}
+
+      /* Copy the rest of the entries, moving down one slot. */
+      for (i = 0; i < history_length; i++)
+	the_history[i] = the_history[i + 1];
+
+      history_base++;
+
+    }
+  else
+    {
+      if (!history_size)
+	{
+	  history_size = DEFAULT_HISTORY_GROW_SIZE;
+	  the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
+	  history_length = 1;
+
+	}
+      else
+	{
+	  if (history_length == (history_size - 1))
+	    {
+	      history_size += DEFAULT_HISTORY_GROW_SIZE;
+	      the_history = (HIST_ENTRY **)
+		xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
+	    }
+	  history_length++;
+	}
+    }
+
+  temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+  temp->line = savestring (string);
+  temp->data = (char *)NULL;
+
+  the_history[history_length] = (HIST_ENTRY *)NULL;
+  the_history[history_length - 1] = temp;
+}
+
+/* Make the history entry at WHICH have LINE and DATA.  This returns
+   the old entry so you can dispose of the data.  In the case of an
+   invalid WHICH, a NULL pointer is returned. */
+HIST_ENTRY *
+replace_history_entry (which, line, data)
+     int which;
+     char *line;
+     char *data;
+{
+  HIST_ENTRY *temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+  HIST_ENTRY *old_value;
+
+  if (which >= history_length)
+    return ((HIST_ENTRY *)NULL);
+
+  old_value = the_history[which];
+
+  temp->line = savestring (line);
+  temp->data = data;
+  the_history[which] = temp;
+
+  return (old_value);
+}
+
+/* Returns the magic number which says what history element we are
+   looking at now.  In this implementation, it returns history_offset. */
+int
+where_history ()
+{
+  return (history_offset);
+}
+
+/* Search the history for STRING, starting at history_offset.
+   If DIRECTION < 0, then the search is through previous entries, else
+   through subsequent.  If ANCHORED is non-zero, the string must
+   appear at the beginning of a history line, otherwise, the string
+   may appear anywhere in the line.  If the string is found, then
+   current_history () is the history entry, and the value of this
+   function is the offset in the line of that history entry that the
+   string was found in.  Otherwise, nothing is changed, and a -1 is
+   returned. */
+
+#define ANCHORED_SEARCH 1
+#define NON_ANCHORED_SEARCH 0
+
+static int
+history_search_internal (string, direction, anchored)
+     char *string;
+     int direction, anchored;
+{
+  register int i, reverse;
+  register char *line;
+  register int line_index;
+  int string_len;
+
+  i = history_offset;
+  reverse = (direction < 0);
+
+  /* Take care of trivial cases first. */
+
+  if (!history_length || ((i == history_length) && !reverse))
+    return (-1);
+
+  if (reverse && (i == history_length))
+    i--;
+
+#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0)
+
+  string_len = strlen (string);
+  while (1)
+    {
+      /* Search each line in the history list for STRING. */
+
+      /* At limit for direction? */
+      if ((reverse && i < 0) || (!reverse && i == history_length))
+	return (-1);
+
+      line = the_history[i]->line;
+      line_index = strlen (line);
+
+      /* If STRING is longer than line, no match. */
+      if (string_len > line_index)
+	{
+	  NEXT_LINE ();
+	  continue;
+	}
+
+      /* Handle anchored searches first. */
+      if (anchored == ANCHORED_SEARCH)
+	{
+	  if (STREQN (string, line, string_len))
+	    {
+	      history_offset = i;
+	      return (0);
+	    }
+
+	  NEXT_LINE ();
+	  continue;
+	}
+
+      /* Do substring search. */
+      if (reverse)
+	{
+	  line_index -= string_len;
+
+	  while (line_index >= 0)
+	    {
+	      if (STREQN (string, line + line_index, string_len))
+		{
+		  history_offset = i;
+		  return (line_index);
+		}
+	      line_index--;
+	    }
+	}
+      else
+	{
+	  register int limit = line_index - string_len + 1;
+	  line_index = 0;
+
+	  while (line_index < limit)
+	    {
+	      if (STREQN (string, line + line_index, string_len))
+		{
+		  history_offset = i;
+		  return (line_index);
+		}
+	      line_index++;
+	    }
+	}
+      NEXT_LINE ();
+    }
+}
+
+/* Do a non-anchored search for STRING through the history in DIRECTION. */
+int
+history_search (string, direction)
+     char *string;
+     int direction;
+{
+  return (history_search_internal (string, direction, NON_ANCHORED_SEARCH));
+}
+
+/* Do an anchored search for string through the history in DIRECTION. */
+int
+history_search_prefix (string, direction)
+     char *string;
+     int direction;
+{
+  return (history_search_internal (string, direction, ANCHORED_SEARCH));
+}
+
+/* Remove history element WHICH from the history.  The removed
+   element is returned to you so you can free the line, data,
+   and containing structure. */
+HIST_ENTRY *
+remove_history (which)
+     int which;
+{
+  HIST_ENTRY *return_value;
+
+  if (which >= history_length || !history_length)
+    return_value = (HIST_ENTRY *)NULL;
+  else
+    {
+      register int i;
+      return_value = the_history[which];
+
+      for (i = which; i < history_length; i++)
+	the_history[i] = the_history[i + 1];
+
+      history_length--;
+    }
+
+  return (return_value);
+}
+
+/* Stifle the history list, remembering only MAX number of lines. */
+void
+stifle_history (max)
+     int max;
+{
+  if (max < 0)
+    max = 0;
+
+  if (history_length > max)
+    {
+      register int i, j;
+
+      /* This loses because we cannot free the data. */
+      for (i = 0; i < (history_length - max); i++)
+	{
+	  free (the_history[i]->line);
+	  free (the_history[i]);
+	}
+
+      history_base = i;
+      for (j = 0, i = history_length - max; j < max; i++, j++)
+	the_history[j] = the_history[i];
+      the_history[j] = (HIST_ENTRY *)NULL;
+      history_length = j;
+    }
+
+  history_stifled = 1;
+  max_input_history = max;
+}
+
+/* Stop stifling the history.  This returns the previous amount the history
+ was stifled by.  The value is positive if the history was stifled, negative
+ if it wasn't. */
+int
+unstifle_history ()
+{
+  int result = max_input_history;
+
+  if (history_stifled)
+    {
+      result = -result;
+      history_stifled = 0;
+    }
+
+  return (result);
+}
+
+int
+history_is_stifled ()
+{
+  return (history_stifled);
+}
+
+/* Return the string that should be used in the place of this
+   filename.  This only matters when you don't specify the
+   filename to read_history (), or write_history (). */
+static char *
+history_filename (filename)
+     char *filename;
+{
+  char *return_val = filename ? savestring (filename) : (char *)NULL;
+
+  if (!return_val)
+    {
+      char *home;
+      int home_len;
+
+      home = getenv ("HOME");
+
+      if (!home)
+	home = ".";
+
+      home_len = strlen (home);
+      /* strlen(".history") == 8 */
+      return_val = xmalloc (2 + home_len + 8);
+
+      strcpy (return_val, home);
+      return_val[home_len] = '/';
+      strcpy (return_val + home_len + 1, ".history");
+    }
+
+  return (return_val);
+}
+
+/* Add the contents of FILENAME to the history list, a line at a time.
+   If FILENAME is NULL, then read from ~/.history.  Returns 0 if
+   successful, or errno if not. */
+int
+read_history (filename)
+     char *filename;
+{
+  return (read_history_range (filename, 0, -1));
+}
+
+/* Read a range of lines from FILENAME, adding them to the history list.
+   Start reading at the FROM'th line and end at the TO'th.  If FROM
+   is zero, start at the beginning.  If TO is less than FROM, read
+   until the end of the file.  If FILENAME is NULL, then read from
+   ~/.history.  Returns 0 if successful, or errno if not. */
+int
+read_history_range (filename, from, to)
+     char *filename;
+     int from, to;
+{
+  register int line_start, line_end;
+  char *input, *buffer = (char *)NULL;
+  int file, current_line;
+  struct stat finfo;
+
+  input = history_filename (filename);
+  file = open (input, O_RDONLY, 0666);
+
+  if ((file < 0) || (fstat (file, &finfo) == -1))
+    goto error_and_exit;
+
+  buffer = xmalloc ((int)finfo.st_size + 1);
+
+  if (read (file, buffer, finfo.st_size) != finfo.st_size)
+    {
+  error_and_exit:
+      if (file >= 0)
+	close (file);
+
+      if (input)
+	free (input);
+
+      if (buffer)
+	free (buffer);
+
+      return (errno);
+    }
+
+  close (file);
+
+  /* Set TO to larger than end of file if negative. */
+  if (to < 0)
+    to = finfo.st_size;
+
+  /* Start at beginning of file, work to end. */
+  line_start = line_end = current_line = 0;
+
+  /* Skip lines until we are at FROM. */
+  while (line_start < finfo.st_size && current_line < from)
+    {
+      for (line_end = line_start; line_end < finfo.st_size; line_end++)
+	if (buffer[line_end] == '\n')
+	  {
+	    current_line++;
+	    line_start = line_end + 1;
+	    if (current_line == from)
+	      break;
+	  }
+    }
+
+  /* If there are lines left to gobble, then gobble them now. */
+  for (line_end = line_start; line_end < finfo.st_size; line_end++)
+    if (buffer[line_end] == '\n')
+      {
+	buffer[line_end] = '\0';
+
+	if (buffer[line_start])
+	  add_history (buffer + line_start);
+
+	current_line++;
+
+	if (current_line >= to)
+	  break;
+
+	line_start = line_end + 1;
+      }
+
+  if (input)
+    free (input);
+
+  if (buffer)
+    free (buffer);
+
+  return (0);
+}
+
+/* Truncate the history file FNAME, leaving only LINES trailing lines.
+   If FNAME is NULL, then use ~/.history. */
+int
+history_truncate_file (fname, lines)
+     char *fname;
+     register int lines;
+{
+  register int i;
+  int file, chars_read;
+  char *buffer = (char *)NULL, *filename;
+  struct stat finfo;
+
+  filename = history_filename (fname);
+  file = open (filename, O_RDONLY, 0666);
+
+  if (file == -1 || fstat (file, &finfo) == -1)
+    goto truncate_exit;
+
+  buffer = xmalloc ((int)finfo.st_size + 1);
+  chars_read = read (file, buffer, finfo.st_size);
+  close (file);
+
+  if (chars_read <= 0)
+    goto truncate_exit;
+
+  /* Count backwards from the end of buffer until we have passed
+     LINES lines. */
+  for (i = chars_read - 1; lines && i; i--)
+    {
+      if (buffer[i] == '\n')
+	lines--;
+    }
+
+  /* If this is the first line, then the file contains exactly the
+     number of lines we want to truncate to, so we don't need to do
+     anything.  It's the first line if we don't find a newline between
+     the current value of i and 0.  Otherwise, write from the start of
+     this line until the end of the buffer. */
+  for ( ; i; i--)
+    if (buffer[i] == '\n')
+      {
+	i++;
+	break;
+      }
+
+  /* Write only if there are more lines in the file than we want to
+     truncate to. */
+  if (i && ((file = open (filename, O_WRONLY|O_TRUNC, 0666)) != -1))
+    {
+      write (file, buffer + i, finfo.st_size - i);
+      close (file);
+    }
+
+ truncate_exit:
+  if (buffer)
+    free (buffer);
+
+  free (filename);
+  return 0;
+}
+
+#define HISTORY_APPEND 0
+#define HISTORY_OVERWRITE 1
+
+/* Workhorse function for writing history.  Writes NELEMENT entries
+   from the history list to FILENAME.  OVERWRITE is non-zero if you
+   wish to replace FILENAME with the entries. */
+static int
+history_do_write (filename, nelements, overwrite)
+     char *filename;
+     int nelements, overwrite;
+{
+  register int i;
+  char *output = history_filename (filename);
+  int file, mode;
+
+  mode = overwrite ? O_WRONLY | O_CREAT | O_TRUNC : O_WRONLY | O_APPEND;
+
+  if ((file = open (output, mode, 0666)) == -1)
+    {
+      if (output)
+	free (output);
+
+      return (errno);
+    }
+
+  if (nelements > history_length)
+    nelements = history_length;
+
+  /* Build a buffer of all the lines to write, and write them in one syscall.
+     Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
+  {
+    register int j = 0;
+    int buffer_size = 0;
+    char *buffer;
+
+    /* Calculate the total number of bytes to write. */
+    for (i = history_length - nelements; i < history_length; i++)
+      buffer_size += 1 + strlen (the_history[i]->line);
+
+    /* Allocate the buffer, and fill it. */
+    buffer = xmalloc (buffer_size);
+
+    for (i = history_length - nelements; i < history_length; i++)
+      {
+	strcpy (buffer + j, the_history[i]->line);
+	j += strlen (the_history[i]->line);
+	buffer[j++] = '\n';
+      }
+
+    write (file, buffer, buffer_size);
+    free (buffer);
+  }
+
+  close (file);
+
+  if (output)
+    free (output);
+
+  return (0);
+}
+
+/* Append NELEMENT entries to FILENAME.  The entries appended are from
+   the end of the list minus NELEMENTs up to the end of the list. */
+int
+append_history (nelements, filename)
+     int nelements;
+     char *filename;
+{
+  return (history_do_write (filename, nelements, HISTORY_APPEND));
+}
+
+/* Overwrite FILENAME with the current history.  If FILENAME is NULL,
+   then write the history list to ~/.history.  Values returned
+   are as in read_history ().*/
+int
+write_history (filename)
+     char *filename;
+{
+  return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
+}
+
+/* Return the history entry at the current position, as determined by
+   history_offset.  If there is no entry there, return a NULL pointer. */
+HIST_ENTRY *
+current_history ()
+{
+  if ((history_offset == history_length) || !the_history)
+    return ((HIST_ENTRY *)NULL);
+  else
+    return (the_history[history_offset]);
+}
+
+/* Back up history_offset to the previous history entry, and return
+   a pointer to that entry.  If there is no previous entry then return
+   a NULL pointer. */
+HIST_ENTRY *
+previous_history ()
+{
+  if (!history_offset)
+    return ((HIST_ENTRY *)NULL);
+  else
+    return (the_history[--history_offset]);
+}
+
+/* Move history_offset forward to the next history entry, and return
+   a pointer to that entry.  If there is no next entry then return a
+   NULL pointer. */
+HIST_ENTRY *
+next_history ()
+{
+  if (history_offset == history_length)
+    return ((HIST_ENTRY *)NULL);
+  else
+    return (the_history[++history_offset]);
+}
+
+/* Return the current history array.  The caller has to be carefull, since this
+   is the actual array of data, and could be bashed or made corrupt easily.
+   The array is terminated with a NULL pointer. */
+HIST_ENTRY **
+history_list ()
+{
+  return (the_history);
+}
+
+/* Return the history entry which is logically at OFFSET in the history array.
+   OFFSET is relative to history_base. */
+HIST_ENTRY *
+history_get (offset)
+     int offset;
+{
+  int local_index = offset - history_base;
+
+  if (local_index >= history_length ||
+      local_index < 0 ||
+      !the_history)
+    return ((HIST_ENTRY *)NULL);
+  return (the_history[local_index]);
+}
+
+/* Search for STRING in the history list.  DIR is < 0 for searching
+   backwards.  POS is an absolute index into the history list at
+   which point to begin searching. */
+int
+history_search_pos (string, dir, pos)
+     char *string;
+     int dir, pos;
+{
+  int ret, old = where_history ();
+  history_set_pos (pos);
+  if (history_search (string, dir) == -1)
+    {
+      history_set_pos (old);
+      return (-1);
+    }
+  ret = where_history ();
+  history_set_pos (old);
+  return ret;
+}
+
+/* Make the current history item be the one at POS, an absolute index.
+   Returns zero if POS is out of range, else non-zero. */
+int
+history_set_pos (pos)
+     int pos;
+{
+  if (pos > history_length || pos < 0 || !the_history)
+    return (0);
+  history_offset = pos;
+  return (1);
+}
+ 
+
+/* **************************************************************** */
+/*								    */
+/*			History Expansion			    */
+/*								    */
+/* **************************************************************** */
+
+/* Hairy history expansion on text, not tokens.  This is of general
+   use, and thus belongs in this library. */
+
+/* The last string searched for in a !?string? search. */
+static char *search_string = (char *)NULL;
+
+/* The last string matched by a !?string? search. */
+static char *search_match = (char *)NULL;
+
+/* Return the event specified at TEXT + OFFSET modifying OFFSET to
+   point to after the event specifier.  Just a pointer to the history
+   line is returned; NULL is returned in the event of a bad specifier.
+   You pass STRING with *INDEX equal to the history_expansion_char that
+   begins this specification.
+   DELIMITING_QUOTE is a character that is allowed to end the string
+   specification for what to search for in addition to the normal
+   characters `:', ` ', `\t', `\n', and sometimes `?'.
+   So you might call this function like:
+   line = get_history_event ("!echo:p", &index, 0);  */
+char *
+get_history_event (string, caller_index, delimiting_quote)
+     char *string;
+     int *caller_index;
+     int delimiting_quote;
+{
+  register int i = *caller_index;
+  register char c;
+  HIST_ENTRY *entry;
+  int which, sign = 1;
+  int local_index, search_mode, substring_okay = 0;
+  char *temp;
+
+  /* The event can be specified in a number of ways.
+
+     !!   the previous command
+     !n   command line N
+     !-n  current command-line minus N
+     !str the most recent command starting with STR
+     !?str[?]
+	  the most recent command containing STR
+
+     All values N are determined via HISTORY_BASE. */
+
+  if (string[i] != history_expansion_char)
+    return ((char *)NULL);
+
+  /* Move on to the specification. */
+  i++;
+
+#define RETURN_ENTRY(e, w) \
+	return ((e = history_get (w)) ? e->line : (char *)NULL)
+
+  /* Handle !! case. */
+  if (string[i] == history_expansion_char)
+    {
+      i++;
+      which = history_base + (history_length - 1);
+      *caller_index = i;
+      RETURN_ENTRY (entry, which);
+    }
+
+  /* Hack case of numeric line specification. */
+  if (string[i] == '-')
+    {
+      sign = -1;
+      i++;
+    }
+
+  if (digit_p (string[i]))
+    {
+      /* Get the extent of the digits and compute the value. */
+      for (which = 0; digit_p (string[i]); i++)
+	which = (which * 10) + digit_value (string[i]);
+
+      *caller_index = i;
+
+      if (sign < 0)
+	which = (history_length + history_base) - which;
+
+      RETURN_ENTRY (entry, which);
+    }
+
+  /* This must be something to search for.  If the spec begins with
+     a '?', then the string may be anywhere on the line.  Otherwise,
+     the string must be found at the start of a line. */
+  if (string[i] == '?')
+    {
+      substring_okay++;
+      i++;
+    }
+
+  /* Only a closing `?' or a newline delimit a substring search string. */
+  for (local_index = i; c = string[i]; i++)
+    if ((!substring_okay && (whitespace (c) || c == ':' ||
+#if defined (SHELL)
+	  member (c, ";&()|<>") ||
+#endif /* SHELL */
+	  string[i] == delimiting_quote)) ||
+	string[i] == '\n' ||
+	(substring_okay && string[i] == '?'))
+      break;
+
+  temp = xmalloc (1 + (i - local_index));
+  strncpy (temp, &string[local_index], (i - local_index));
+  temp[i - local_index] = '\0';
+
+  if (substring_okay && string[i] == '?')
+    i++;
+
+  *caller_index = i;
+
+#define FAIL_SEARCH() \
+  do { history_offset = history_length; free (temp) ; return (char *)NULL; } while (0)
+
+  search_mode = substring_okay ? NON_ANCHORED_SEARCH : ANCHORED_SEARCH;
+  while (1)
+    {
+      local_index = history_search_internal (temp, -1, search_mode);
+
+      if (local_index < 0)
+	FAIL_SEARCH ();
+
+      if (local_index == 0 || substring_okay)
+	{
+	  entry = current_history ();
+	  history_offset = history_length;
+	
+	  /* If this was a substring search, then remember the
+	     string that we matched for word substitution. */
+	  if (substring_okay)
+	    {
+	      if (search_string)
+		free (search_string);
+	      search_string = temp;
+
+	      if (search_match)
+		free (search_match);
+	      search_match = history_find_word (entry->line, local_index);
+	    }
+	  else
+	    free (temp);
+	  return (entry->line);
+	}
+
+      if (history_offset)
+	history_offset--;
+      else
+	FAIL_SEARCH ();
+    }
+#undef FAIL_SEARCH
+#undef RETURN_ENTRY
+}
+#if defined (SHELL)
+/* Function for extracting single-quoted strings.  Used for inhibiting
+   history expansion within single quotes. */
+
+/* Extract the contents of STRING as if it is enclosed in single quotes.
+   SINDEX, when passed in, is the offset of the character immediately
+   following the opening single quote; on exit, SINDEX is left pointing
+   to the closing single quote. */
+static void
+rl_string_extract_single_quoted (string, sindex)
+     char *string;
+     int *sindex;
+{
+  register int i = *sindex;
+
+  while (string[i] && string[i] != '\'')
+    i++;
+
+  *sindex = i;
+}
+
+static char *
+quote_breaks (s)
+     char *s;
+{
+  register char *p, *r;
+  char *ret;
+  int len = 3;
+
+  for (p = s; p && *p; p++, len++)
+    {
+      if (*p == '\'')
+	len += 3;
+      else if (whitespace (*p) || *p == '\n')
+	len += 2;
+    }
+
+  r = ret = xmalloc (len);
+  *r++ = '\'';
+  for (p = s; p && *p; )
+    {
+      if (*p == '\'')
+	{
+	  *r++ = '\'';
+	  *r++ = '\\';
+	  *r++ = '\'';
+	  *r++ = '\'';
+	  p++;
+	}
+      else if (whitespace (*p) || *p == '\n')
+	{
+	  *r++ = '\'';
+	  *r++ = *p++;
+	  *r++ = '\'';
+	}
+      else
+	*r++ = *p++;
+    }
+  *r++ = '\'';
+  *r = '\0';
+  return ret;
+}
+#endif /* SHELL */
+
+static char *
+hist_error(s, start, current, errtype)
+      char *s;
+      int start, current, errtype;
+{
+  char *temp, *emsg;
+  int ll, elen;
+
+  ll = current - start;
+
+  switch (errtype)
+    {
+    case EVENT_NOT_FOUND:
+      emsg = "event not found";
+      elen = 15;
+      break;
+    case BAD_WORD_SPEC:
+      emsg = "bad word specifier";
+      elen = 18;
+      break;
+    case SUBST_FAILED:
+      emsg = "substitution failed";
+      elen = 19;
+      break;
+    case BAD_MODIFIER:
+      emsg = "unrecognized history modifier";
+      elen = 29;
+      break;
+    default:
+      emsg = "unknown expansion error";
+      elen = 23;
+      break;
+    }
+
+  temp = xmalloc (ll + elen + 3);
+  strncpy (temp, s + start, ll);
+  temp[ll] = ':';
+  temp[ll + 1] = ' ';
+  strcpy (temp + ll + 2, emsg);
+  return (temp);
+}
+
+/* Get a history substitution string from STR starting at *IPTR
+   and return it.  The length is returned in LENPTR.
+
+   A backslash can quote the delimiter.  If the string is the
+   empty string, the previous pattern is used.  If there is
+   no previous pattern for the lhs, the last history search
+   string is used.
+
+   If IS_RHS is 1, we ignore empty strings and set the pattern
+   to "" anyway.  subst_lhs is not changed if the lhs is empty;
+   subst_rhs is allowed to be set to the empty string. */
+
+static char *
+get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr)
+     char *str;
+     int *iptr, delimiter, is_rhs, *lenptr;
+{
+  register int si, i, j, k;
+  char *s = (char *) NULL;
+
+  i = *iptr;
+
+  for (si = i; str[si] && str[si] != delimiter; si++)
+    if (str[si] == '\\' && str[si + 1] == delimiter)
+      si++;
+
+  if (si > i || is_rhs)
+    {
+      s = xmalloc (si - i + 1);
+      for (j = 0, k = i; k < si; j++, k++)
+	{
+	  /* Remove a backslash quoting the search string delimiter. */
+	  if (str[k] == '\\' && str[k + 1] == delimiter)
+	    k++;
+	  s[j] = str[k];
+	}
+      s[j] = '\0';
+      if (lenptr)
+        *lenptr = j;
+    }
+
+  i = si;
+  if (str[i])
+    i++;
+  *iptr = i;
+
+  return s;
+}
+
+static void
+postproc_subst_rhs ()
+{
+  char *new;
+  int i, j, new_size;
+
+  new = xmalloc (new_size = subst_rhs_len + subst_lhs_len);
+  for (i = j = 0; i < subst_rhs_len; i++)
+    {
+      if (subst_rhs[i] == '&')
+	{
+	  if (j + subst_lhs_len >= new_size)
+	    new = xrealloc (new, (new_size = new_size * 2 + subst_lhs_len));
+	  strcpy (new + j, subst_lhs);
+	  j += subst_lhs_len;
+	}
+      else
+	{
+	  /* a single backslash protects the `&' from lhs interpolation */
+	  if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&')
+	    i++;
+	  if (j >= new_size)
+	    new = xrealloc (new, new_size *= 2);
+	  new[j++] = subst_rhs[i];
+	}
+    }
+  new[j] = '\0';
+  free (subst_rhs);
+  subst_rhs = new;
+  subst_rhs_len = j;
+}
+
+/* Expand the bulk of a history specifier starting at STRING[START].
+   Returns 0 if everything is OK, -1 if an error occurred, and 1
+   if the `p' modifier was supplied and the caller should just print
+   the returned string.  Returns the new index into string in
+   *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
+static int
+history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
+     char *string;
+     int start, *end_index_ptr;
+     char **ret_string;
+     char *current_line;	/* for !# */
+{
+  int i, n, starting_index;
+  int substitute_globally, want_quotes, print_only;
+  char *event, *temp, *result, *tstr, *t, c, *word_spec;
+  int result_len;
+
+  result = xmalloc (result_len = 128);
+
+  i = start;
+
+  /* If it is followed by something that starts a word specifier,
+     then !! is implied as the event specifier. */
+
+  if (member (string[i + 1], ":$*%^"))
+    {
+      char fake_s[3];
+      int fake_i = 0;
+      i++;
+      fake_s[0] = fake_s[1] = history_expansion_char;
+      fake_s[2] = '\0';
+      event = get_history_event (fake_s, &fake_i, 0);
+    }
+  else if (string[i + 1] == '#')
+    {
+      i += 2;
+      event = current_line;
+    }
+  else
+    {
+      int quoted_search_delimiter = 0;
+
+      /* If the character before this `!' is a double or single
+	 quote, then this expansion takes place inside of the
+	 quoted string.  If we have to search for some text ("!foo"),
+	 allow the delimiter to end the search string. */
+      if (i && (string[i - 1] == '\'' || string[i - 1] == '"'))
+	quoted_search_delimiter = string[i - 1];
+      event = get_history_event (string, &i, quoted_search_delimiter);
+    }
+	  
+  if (!event)
+    {
+      *ret_string = hist_error (string, start, i, EVENT_NOT_FOUND);
+      free (result);
+      return (-1);
+    }
+
+  /* If a word specifier is found, then do what that requires. */
+  starting_index = i;
+  word_spec = get_history_word_specifier (string, event, &i);
+
+  /* There is no such thing as a `malformed word specifier'.  However,
+     it is possible for a specifier that has no match.  In that case,
+     we complain. */
+  if (word_spec == (char *)&error_pointer)
+    {
+      *ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC);
+      free (result);
+      return (-1);
+    }
+
+  /* If no word specifier, than the thing of interest was the event. */
+  if (!word_spec)
+    temp = savestring (event);
+  else
+    {
+      temp = savestring (word_spec);
+      free (word_spec);
+    }
+
+  /* Perhaps there are other modifiers involved.  Do what they say. */
+  want_quotes = substitute_globally = print_only = 0;
+  starting_index = i;
+
+  while (string[i] == ':')
+    {
+      c = string[i + 1];
+
+      if (c == 'g')
+	{
+	  substitute_globally = 1;
+	  i++;
+	  c = string[i + 1];
+	}
+
+      switch (c)
+	{
+	default:
+	  *ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER);
+	  free (result);
+	  free (temp);
+	  return -1;
+
+#if defined (SHELL)
+	case 'q':
+	  want_quotes = 'q';
+	  break;
+
+	case 'x':
+	  want_quotes = 'x';
+	  break;
+#endif /* SHELL */
+
+	  /* :p means make this the last executed line.  So we
+	     return an error state after adding this line to the
+	     history. */
+	case 'p':
+	  print_only++;
+	  break;
+
+	  /* :t discards all but the last part of the pathname. */
+	case 't':
+	  tstr = strrchr (temp, '/');
+	  if (tstr)
+	    {
+	      tstr++;
+	      t = savestring (tstr);
+	      free (temp);
+	      temp = t;
+	    }
+	  break;
+
+	  /* :h discards the last part of a pathname. */
+	case 'h':
+	  tstr = strrchr (temp, '/');
+	  if (tstr)
+	    *tstr = '\0';
+	  break;
+
+	  /* :r discards the suffix. */
+	case 'r':
+	  tstr = strrchr (temp, '.');
+	  if (tstr)
+	    *tstr = '\0';
+	  break;
+
+	  /* :e discards everything but the suffix. */
+	case 'e':
+	  tstr = strrchr (temp, '.');
+	  if (tstr)
+	    {
+	      t = savestring (tstr);
+	      free (temp);
+	      temp = t;
+	    }
+	  break;
+
+	/* :s/this/that substitutes `that' for the first
+	   occurrence of `this'.  :gs/this/that substitutes `that'
+	   for each occurrence of `this'.  :& repeats the last
+	   substitution.  :g& repeats the last substitution
+	   globally. */
+
+	case '&':
+	case 's':
+	  {
+	    char *new_event, *t;
+	    int delimiter, failed, si, l_temp;
+
+	    if (c == 's')
+	      {
+		if (i + 2 < (int)strlen (string))
+		  delimiter = string[i + 2];
+		else
+		  break;	/* no search delimiter */
+
+		i += 3;
+
+		t = get_subst_pattern (string, &i, delimiter, 0, &subst_lhs_len);
+		/* An empty substitution lhs with no previous substitution
+		   uses the last search string as the lhs. */
+		if (t)
+		  {
+		    if (subst_lhs)
+		      free (subst_lhs);
+		    subst_lhs = t;
+		  }
+		else if (!subst_lhs)
+		  {
+		    if (search_string && *search_string)
+		      {
+			subst_lhs = savestring (search_string);
+			subst_lhs_len = strlen (subst_lhs);
+		      }
+		    else
+		      {
+		        subst_lhs = (char *) NULL;
+		        subst_lhs_len = 0;
+		      }
+		  }
+
+		/* If there is no lhs, the substitution can't succeed. */
+		if (subst_lhs_len == 0)
+		  {
+		    *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
+		    free (result);
+		    free (temp);
+		    return -1;
+		  }
+
+		if (subst_rhs)
+		  free (subst_rhs);
+		subst_rhs = get_subst_pattern (string, &i, delimiter, 1, &subst_rhs_len);
+
+		/* If `&' appears in the rhs, it's supposed to be replaced
+		   with the lhs. */
+		if (member ('&', subst_rhs))
+		  postproc_subst_rhs ();
+	      }
+	    else
+	      i += 2;
+
+	    l_temp = strlen (temp);
+	    /* Ignore impossible cases. */
+	    if (subst_lhs_len > l_temp)
+	      {
+		*ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
+		free (result);
+		free (temp);
+		return (-1);
+	      }
+
+	    /* Find the first occurrence of THIS in TEMP. */
+	    si = 0;
+	    for (failed = 1; (si + subst_lhs_len) <= l_temp; si++)
+	      if (STREQN (temp+si, subst_lhs, subst_lhs_len))
+		{
+		  int len = subst_rhs_len - subst_lhs_len + l_temp;
+		  new_event = xmalloc (1 + len);
+		  strncpy (new_event, temp, si);
+		  strncpy (new_event + si, subst_rhs, subst_rhs_len);
+		  strncpy (new_event + si + subst_rhs_len,
+			   temp + si + subst_lhs_len,
+			   l_temp - (si + subst_lhs_len));
+		  new_event[len] = '\0';
+		  free (temp);
+		  temp = new_event;
+
+		  failed = 0;
+
+		  if (substitute_globally)
+		    {
+		      si += subst_rhs_len;
+		      l_temp = strlen (temp);
+		      substitute_globally++;
+		      continue;
+		    }
+		  else
+		    break;
+		}
+
+	    if (substitute_globally > 1)
+	      {
+		substitute_globally = 0;
+		continue;	/* don't want to increment i */
+	      }
+
+	    if (failed == 0)
+	      continue;		/* don't want to increment i */
+
+	    *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
+	    free (result);
+	    free (temp);
+	    return (-1);
+	  }
+	}
+      i += 2;
+    }
+  /* Done with modfiers. */
+  /* Believe it or not, we have to back the pointer up by one. */
+  --i;
+
+#if defined (SHELL)
+  if (want_quotes)
+    {
+      char *x;
+
+      if (want_quotes == 'q')
+	x = single_quote (temp);
+      else if (want_quotes == 'x')
+	x = quote_breaks (temp);
+      else
+	x = savestring (temp);
+
+      free (temp);
+      temp = x;
+    }
+#endif /* SHELL */
+
+  n = strlen (temp);
+  if (n > result_len)
+    result = xrealloc (result, n + 2);
+  strcpy (result, temp);
+  free (temp);
+
+  *end_index_ptr = i;
+  *ret_string = result;
+  return (print_only);
+}
+
+/* Expand the string STRING, placing the result into OUTPUT, a pointer
+   to a string.  Returns:
+
+  -1) If there was an error in expansion.
+   0) If no expansions took place (or, if the only change in
+      the text was the de-slashifying of the history expansion
+      character)
+   1) If expansions did take place
+   2) If the `p' modifier was given and the caller should print the result
+
+  If an error ocurred in expansion, then OUTPUT contains a descriptive
+  error message. */
+
+#define ADD_STRING(s) \
+	do \
+	  { \
+	    int sl = strlen (s); \
+	    j += sl; \
+	    if (j >= result_len) \
+	      { \
+		while (j >= result_len) \
+		  result_len += 128; \
+		result = xrealloc (result, result_len); \
+	      } \
+	    strcpy (result + j - sl, s); \
+	  } \
+	while (0)
+
+#define ADD_CHAR(c) \
+	do \
+	  { \
+	    if (j >= result_len - 1) \
+	      result = xrealloc (result, result_len += 64); \
+	    result[j++] = c; \
+	    result[j] = '\0'; \
+	  } \
+	while (0)
+
+int
+history_expand (hstring, output)
+     char *hstring;
+     char **output;
+{
+  register int j;
+  int i, r, l, passc, cc, modified, eindex, only_printing;
+  char *string;
+
+  /* The output string, and its length. */
+  int result_len;
+  char *result;
+
+  /* Used when adding the string. */
+  char *temp;
+
+  /* Setting the history expansion character to 0 inhibits all
+     history expansion. */
+  if (history_expansion_char == 0)
+    {
+      *output = savestring (hstring);
+      return (0);
+    }
+    
+  /* Prepare the buffer for printing error messages. */
+  result = xmalloc (result_len = 256);
+  result[0] = '\0';
+
+  only_printing = modified = 0;
+  l = strlen (hstring);
+
+  /* Grovel the string.  Only backslash can quote the history escape
+     character.  We also handle arg specifiers. */
+
+  /* Before we grovel forever, see if the history_expansion_char appears
+     anywhere within the text. */
+
+  /* The quick substitution character is a history expansion all right.  That
+     is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
+     that is the substitution that we do. */
+  if (hstring[0] == history_subst_char)
+    {
+      string = xmalloc (l + 5);
+
+      string[0] = string[1] = history_expansion_char;
+      string[2] = ':';
+      string[3] = 's';
+      strcpy (string + 4, hstring);
+      l += 4;
+    }
+  else
+    {
+      string = hstring;
+      /* If not quick substitution, still maybe have to do expansion. */
+
+      /* `!' followed by one of the characters in history_no_expand_chars
+	 is NOT an expansion. */
+      for (i = 0; string[i]; i++)
+	{
+	  cc = string[i + 1];
+          if (string[i] == history_expansion_char)
+	    {
+	      if (!cc || member (cc, history_no_expand_chars))
+		continue;
+#if defined (SHELL)
+	      /* The shell uses ! as a pattern negation character
+	         in globbing [...] expressions, so let those pass
+	         without expansion. */
+	      else if (i > 0 && (string[i - 1] == '[') &&
+		       member (']', string + i + 1))
+		continue;
+#endif /* SHELL */
+	      else
+		break;
+	    }
+#if defined (SHELL)
+	  else if (string[i] == '\'')
+	    {
+	      /* If this is bash, single quotes inhibit history expansion. */
+	      i++;
+	      rl_string_extract_single_quoted (string, &i);
+	    }
+	  else if (string[i] == '\\')
+	    {
+	      /* If this is bash, allow backslashes to quote single
+		 quotes and
+		 the history expansion character. */
+	      if (cc == '\'' || cc == history_expansion_char)
+		i++;
+	    }
+#endif /* SHELL */
+	}
+	  
+      if (string[i] != history_expansion_char)
+	{
+	  free (result);
+	  *output = savestring (string);
+	  return (0);
+	}
+    }
+
+  /* Extract and perform the substitution. */
+  for (passc = i = j = 0; i < l; i++)
+    {
+      int tchar = string[i];
+
+      if (passc)
+	{
+	  passc = 0;
+	  ADD_CHAR (tchar);
+	  continue;
+	}
+
+      if (tchar == history_expansion_char)
+	tchar = -3;
+
+      switch (tchar)
+	{
+	default:
+	  ADD_CHAR (string[i]);
+	  break;
+
+	case '\\':
+	  passc++;
+	  ADD_CHAR (tchar);
+	  break;
+
+#if defined (SHELL)
+	case '\'':
+	  {
+	    /* If this is bash, single quotes inhibit history expansion. */
+	    int quote, slen;
+
+	    quote = i++;
+	    rl_string_extract_single_quoted (string, &i);
+
+	    slen = i - quote + 2;
+	    temp = xmalloc (slen);
+	    strncpy (temp, string + quote, slen);
+	    temp[slen - 1] = '\0';
+	    ADD_STRING (temp);
+	    free (temp);
+	    break;
+	  }
+#endif /* SHELL */
+
+	case -3:		/* history_expansion_char */
+	  cc = string[i + 1];
+
+	  /* If the history_expansion_char is followed by one of the
+	     characters in history_no_expand_chars, then it is not a
+	     candidate for expansion of any kind. */
+	  if (member (cc, history_no_expand_chars))
+	    {
+	      ADD_CHAR (string[i]);
+	      break;
+	    }
+
+#if defined (NO_BANG_HASH_MODIFIERS)
+	  /* There is something that is listed as a `word specifier' in csh
+	     documentation which means `the expanded text to this point'.
+	     That is not a word specifier, it is an event specifier.  If we
+	     don't want to allow modifiers with `!#', just stick the current
+	     output line in again. */
+	  if (cc == '#')
+	    {
+	      if (result)
+		{
+		  temp = xmalloc (1 + strlen (result));
+		  strcpy (temp, result);
+		  ADD_STRING (temp);
+		  free (temp);
+		}
+	      i++;
+	      break;
+	    }
+#endif
+
+	  r = history_expand_internal (string, i, &eindex, &temp, result);
+	  if (r < 0)
+	    {
+	      *output = temp;
+	      free (result);
+	      if (string != hstring)
+		free (string);
+	      return -1;
+	    }
+	  else
+	    {
+	      if (temp)
+		{
+		  modified++;
+		  if (*temp)
+		    ADD_STRING (temp);
+		  free (temp);
+		}
+	      only_printing = r == 1;
+	      i = eindex;
+	    }
+	  break;
+	}
+    }
+
+  *output = result;
+  if (string != hstring)
+    free (string);
+
+  if (only_printing)
+    {
+      add_history (result);
+      return (2);
+    }
+
+  return (modified != 0);
+}
+
+/* Return a consed string which is the word specified in SPEC, and found
+   in FROM.  NULL is returned if there is no spec.  The address of
+   ERROR_POINTER is returned if the word specified cannot be found.
+   CALLER_INDEX is the offset in SPEC to start looking; it is updated
+   to point to just after the last character parsed. */
+static char *
+get_history_word_specifier (spec, from, caller_index)
+     char *spec, *from;
+     int *caller_index;
+{
+  register int i = *caller_index;
+  int first, last;
+  int expecting_word_spec = 0;
+  char *result;
+
+  /* The range of words to return doesn't exist yet. */
+  first = last = 0;
+  result = (char *)NULL;
+
+  /* If we found a colon, then this *must* be a word specification.  If
+     it isn't, then it is an error. */
+  if (spec[i] == ':')
+    {
+      i++;
+      expecting_word_spec++;
+    }
+
+  /* Handle special cases first. */
+
+  /* `%' is the word last searched for. */
+  if (spec[i] == '%')
+    {
+      *caller_index = i + 1;
+      return (search_match ? savestring (search_match) : savestring (""));
+    }
+
+  /* `*' matches all of the arguments, but not the command. */
+  if (spec[i] == '*')
+    {
+      *caller_index = i + 1;
+      result = history_arg_extract (1, '$', from);
+      return (result ? result : savestring (""));
+    }
+
+  /* `$' is last arg. */
+  if (spec[i] == '$')
+    {
+      *caller_index = i + 1;
+      return (history_arg_extract ('$', '$', from));
+    }
+
+  /* Try to get FIRST and LAST figured out. */
+
+  if (spec[i] == '-')
+    first = 0;
+  else if (spec[i] == '^')
+    first = 1;
+  else if (digit_p (spec[i]) && expecting_word_spec)
+    {
+      for (first = 0; digit_p (spec[i]); i++)
+	first = (first * 10) + digit_value (spec[i]);
+    }
+  else
+    return ((char *)NULL);	/* no valid `first' for word specifier */
+
+  if (spec[i] == '^' || spec[i] == '*')
+    {
+      last = (spec[i] == '^') ? 1 : '$';	/* x* abbreviates x-$ */
+      i++;
+    }
+  else if (spec[i] != '-')
+    last = first;
+  else
+    {
+      i++;
+
+      if (digit_p (spec[i]))
+	{
+	  for (last = 0; digit_p (spec[i]); i++)
+	    last = (last * 10) + digit_value (spec[i]);
+	}
+      else if (spec[i] == '$')
+	{
+	  i++;
+	  last = '$';
+	}
+      else if (!spec[i] || spec[i] == ':')  /* could be modifier separator */
+	last = -1;		/* x- abbreviates x-$ omitting word `$' */
+    }
+
+  *caller_index = i;
+
+  if (last >= first || last == '$' || last < 0)
+    result = history_arg_extract (first, last, from);
+
+  return (result ? result : (char *)&error_pointer);
+}
+
+/* Extract the args specified, starting at FIRST, and ending at LAST.
+   The args are taken from STRING.  If either FIRST or LAST is < 0,
+   then make that arg count from the right (subtract from the number of
+   tokens, so that FIRST = -1 means the next to last token on the line).
+   If LAST is `$' the last arg from STRING is used. */
+char *
+history_arg_extract (first, last, string)
+     int first, last;
+     char *string;
+{
+  register int i, len;
+  char *result = (char *)NULL;
+  int size = 0, offset = 0;
+  char **list;
+
+  /* XXX - think about making history_tokenize return a struct array,
+     each struct in array being a string and a length to avoid the
+     calls to strlen below. */
+  if ((list = history_tokenize (string)) == NULL)
+    return ((char *)NULL);
+
+  for (len = 0; list[len]; len++)
+    ;
+
+  if (last < 0)
+    last = len + last - 1;
+
+  if (first < 0)
+    first = len + first - 1;
+
+  if (last == '$')
+    last = len - 1;
+
+  if (first == '$')
+    first = len - 1;
+
+  last++;
+
+  if (first >= len || last > len || first < 0 || last < 0 || first > last)
+    result = ((char *)NULL);
+  else
+    {
+      for (size = 0, i = first; i < last; i++)
+	size += strlen (list[i]) + 1;
+      result = xmalloc (size + 1);
+      result[0] = '\0';
+
+      for (i = first; i < last; i++)
+	{
+	  strcpy (result + offset, list[i]);
+	  offset += strlen (list[i]);
+	  if (i + 1 < last)
+	    {
+      	      result[offset++] = ' ';
+	      result[offset] = 0;
+	    }
+	}
+    }
+
+  for (i = 0; i < len; i++)
+    free (list[i]);
+  free (list);
+
+  return (result);
+}
+
+#define slashify_in_quotes "\\`\"$"
+
+/* Parse STRING into tokens and return an array of strings.  If WIND is
+   not -1 and INDP is not null, we also want the word surrounding index
+   WIND.  The position in the returned array of strings is returned in
+   *INDP. */
+static char **
+history_tokenize_internal (string, wind, indp)
+     char *string;
+     int wind, *indp;
+{
+  char **result = (char **)NULL;
+  register int i, start, result_index, size;
+  int len;
+
+  i = result_index = size = 0;
+
+  /* Get a token, and stuff it into RESULT.  The tokens are split
+     exactly where the shell would split them. */
+  while (string[i])
+    {
+      int delimiter = 0;
+
+      /* Skip leading whitespace. */
+      for (; string[i] && whitespace (string[i]); i++)
+	;
+      if (!string[i] || string[i] == history_comment_char)
+	return (result);
+
+      start = i;
+      
+      if (member (string[i], "()\n"))
+	{
+	  i++;
+	  goto got_token;
+	}
+
+      if (member (string[i], "<>;&|$"))
+	{
+	  int peek = string[i + 1];
+
+	  if (peek == string[i] && peek != '$')
+	    {
+	      if (peek == '<' && string[i + 2] == '-')
+		i++;
+	      i += 2;
+	      goto got_token;
+	    }
+	  else
+	    {
+	      if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
+		  ((peek == '>') && (string[i] == '&')) ||
+		  ((peek == '(') && (string[i] == '$')))
+		{
+		  i += 2;
+		  goto got_token;
+		}
+	    }
+	  if (string[i] != '$')
+	    {
+	      i++;
+	      goto got_token;
+	    }
+	}
+
+      /* Get word from string + i; */
+
+      if (member (string[i], "\"'`"))
+	delimiter = string[i++];
+
+      for (; string[i]; i++)
+	{
+	  if (string[i] == '\\' && string[i + 1] == '\n')
+	    {
+	      i++;
+	      continue;
+	    }
+
+	  if (string[i] == '\\' && delimiter != '\'' &&
+	      (delimiter != '"' || member (string[i], slashify_in_quotes)))
+	    {
+	      i++;
+	      continue;
+	    }
+
+	  if (delimiter && string[i] == delimiter)
+	    {
+	      delimiter = 0;
+	      continue;
+	    }
+
+	  if (!delimiter && (member (string[i], " \t\n;&()|<>")))
+	    break;
+
+	  if (!delimiter && member (string[i], "\"'`"))
+	    delimiter = string[i];
+	}
+    got_token:
+
+      /* If we are looking for the word in which the character at a
+	 particular index falls, remember it. */
+      if (indp && wind >= 0 && wind >= start && wind < i)
+        *indp = result_index;
+
+      len = i - start;
+      if (result_index + 2 >= size)
+	result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));
+      result[result_index] = xmalloc (1 + len);
+      strncpy (result[result_index], string + start, len);
+      result[result_index][len] = '\0';
+      result[++result_index] = (char *)NULL;
+    }
+
+  return (result);
+}
+
+/* Return an array of tokens, much as the shell might.  The tokens are
+   parsed out of STRING. */
+char **
+history_tokenize (string)
+     char *string;
+{
+  return (history_tokenize_internal (string, -1, (int *)NULL));
+}
+
+/* Find and return the word which contains the character at index IND
+   in the history line LINE.  Used to save the word matched by the
+   last history !?string? search. */
+static char *
+history_find_word (line, ind)
+     char *line;
+     int ind;
+{
+  char **words, *s;
+  int i, wind;
+
+  words = history_tokenize_internal (line, ind, &wind);
+  if (wind == -1)
+    return ((char *)NULL);
+  s = words[wind];
+  for (i = 0; i < wind; i++)
+    free (words[i]);
+  for (i = wind + 1; words[i]; i++)
+    free (words[i]);
+  free (words);
+  return s;
+}
+
+#if defined (STATIC_MALLOC)
+
+/* **************************************************************** */
+/*								    */
+/*			xmalloc and xrealloc ()		     	    */
+/*								    */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)xmalloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "history: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
+
+/* **************************************************************** */
+/*								    */
+/*				Test Code			    */
+/*								    */
+/* **************************************************************** */
+#ifdef TEST
+main ()
+{
+  char line[1024], *t;
+  int done = 0;
+
+  line[0] = 0;
+
+  while (!done)
+    {
+      fprintf (stdout, "history%% ");
+      t = gets (line);
+
+      if (!t)
+	strcpy (line, "quit");
+
+      if (line[0])
+	{
+	  char *expansion;
+	  int result;
+
+	  using_history ();
+
+	  result = history_expand (line, &expansion);
+	  strcpy (line, expansion);
+	  free (expansion);
+	  if (result)
+	    fprintf (stderr, "%s\n", line);
+
+	  if (result < 0)
+	    continue;
+
+	  add_history (line);
+	}
+
+      if (strcmp (line, "quit") == 0) done = 1;
+      if (strcmp (line, "save") == 0) write_history (0);
+      if (strcmp (line, "read") == 0) read_history (0);
+      if (strcmp (line, "list") == 0)
+	{
+	  register HIST_ENTRY **the_list = history_list ();
+	  register int i;
+
+	  if (the_list)
+	    for (i = 0; the_list[i]; i++)
+	      fprintf (stdout, "%d: %s\n", i + history_base, the_list[i]->line);
+	}
+      if (strncmp (line, "delete", strlen ("delete")) == 0)
+	{
+	  int which;
+	  if ((sscanf (line + strlen ("delete"), "%d", &which)) == 1)
+	    {
+	      HIST_ENTRY *entry = remove_history (which);
+	      if (!entry)
+		fprintf (stderr, "No such entry %d\n", which);
+	      else
+		{
+		  free (entry->line);
+		  free (entry);
+		}
+	    }
+	  else
+	    {
+	      fprintf (stderr, "non-numeric arg given to `delete'\n");
+	    }
+	}
+    }
+}
+
+#endif /* TEST */
+
+/*
+* Local variables:
+* compile-command: "gcc -g -DTEST -o history history.c"
+* end:
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/history.h	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,181 @@
+/* History.h -- the names of functions that you can call in history. */
+
+/* The structure used to store a history entry. */
+typedef struct _hist_entry {
+  char *line;
+  char *data;
+} HIST_ENTRY;
+
+/* A structure used to pass the current state of the history stuff around. */
+typedef struct _hist_state {
+  HIST_ENTRY **entries;		/* Pointer to the entries themselves. */
+  int offset;			/* The location pointer within this array. */
+  int length;			/* Number of elements within this array. */
+  int size;			/* Number of slots allocated to this array. */
+  int flags;
+} HISTORY_STATE;
+
+/* Flag values for the `flags' member of HISTORY_STATE. */
+#define HS_STIFLED	0x01
+
+/* Initialization and state management. */
+
+/* Begin a session in which the history functions might be used.  This
+   just initializes the interactive variables. */
+extern void using_history ();
+
+/* Return the current HISTORY_STATE of the history. */
+extern HISTORY_STATE *history_get_history_state ();
+
+/* Set the state of the current history array to STATE. */
+extern void history_set_history_state ();
+
+/* Manage the history list. */
+
+/* Place STRING at the end of the history list.
+   The associated data field (if any) is set to NULL. */
+extern void add_history ();
+
+/* A reasonably useless function, only here for completeness.  WHICH
+   is the magic number that tells us which element to delete.  The
+   elements are numbered from 0. */
+extern HIST_ENTRY *remove_history ();
+
+/* Make the history entry at WHICH have LINE and DATA.  This returns
+   the old entry so you can dispose of the data.  In the case of an
+   invalid WHICH, a NULL pointer is returned. */
+extern HIST_ENTRY *replace_history_entry ();
+
+/* Stifle the history list, remembering only MAX number of entries. */
+extern void stifle_history ();
+
+/* Stop stifling the history.  This returns the previous amount the
+   history was stifled by.  The value is positive if the history was
+   stifled, negative if it wasn't. */
+extern int unstifle_history ();
+
+/* Return 1 if the history is stifled, 0 if it is not. */
+extern int history_is_stifled ();
+
+/* Information about the history list. */
+
+/* Return a NULL terminated array of HIST_ENTRY which is the current input
+   history.  Element 0 of this list is the beginning of time.  If there
+   is no history, return NULL. */
+extern HIST_ENTRY **history_list ();
+
+/* Returns the number which says what history element we are now
+   looking at.  */
+extern int where_history ();
+  
+/* Return the history entry at the current position, as determined by
+   history_offset.  If there is no entry there, return a NULL pointer. */
+HIST_ENTRY *current_history ();
+
+/* Return the history entry which is logically at OFFSET in the history
+   array.  OFFSET is relative to history_base. */
+extern HIST_ENTRY *history_get ();
+
+/* Return the number of bytes that the primary history entries are using.
+   This just adds up the lengths of the_history->lines. */
+extern int history_total_bytes ();
+
+/* Moving around the history list. */
+
+/* Set the position in the history list to POS. */
+int history_set_pos ();
+
+/* Back up history_offset to the previous history entry, and return
+   a pointer to that entry.  If there is no previous entry, return
+   a NULL pointer. */
+extern HIST_ENTRY *previous_history ();
+
+/* Move history_offset forward to the next item in the input_history,
+   and return the a pointer to that entry.  If there is no next entry,
+   return a NULL pointer. */
+extern HIST_ENTRY *next_history ();
+
+/* Searching the history list. */
+
+/* Search the history for STRING, starting at history_offset.
+   If DIRECTION < 0, then the search is through previous entries,
+   else through subsequent.  If the string is found, then
+   current_history () is the history entry, and the value of this function
+   is the offset in the line of that history entry that the string was
+   found in.  Otherwise, nothing is changed, and a -1 is returned. */
+extern int history_search ();
+
+/* Search the history for STRING, starting at history_offset.
+   The search is anchored: matching lines must begin with string. */
+extern int history_search_prefix ();
+
+/* Search for STRING in the history list, starting at POS, an
+   absolute index into the list.  DIR, if negative, says to search
+   backwards from POS, else forwards.
+   Returns the absolute index of the history element where STRING
+   was found, or -1 otherwise. */
+extern int history_search_pos ();
+
+/* Managing the history file. */
+
+/* Add the contents of FILENAME to the history list, a line at a time.
+   If FILENAME is NULL, then read from ~/.history.  Returns 0 if
+   successful, or errno if not. */
+extern int read_history ();
+
+/* Read a range of lines from FILENAME, adding them to the history list.
+   Start reading at the FROM'th line and end at the TO'th.  If FROM
+   is zero, start at the beginning.  If TO is less than FROM, read
+   until the end of the file.  If FILENAME is NULL, then read from
+   ~/.history.  Returns 0 if successful, or errno if not. */
+extern int read_history_range ();
+
+/* Write the current history to FILENAME.  If FILENAME is NULL,
+   then write the history list to ~/.history.  Values returned
+   are as in read_history ().  */
+extern int write_history ();
+
+/* Append NELEMENT entries to FILENAME.  The entries appended are from
+   the end of the list minus NELEMENTs up to the end of the list. */
+int append_history ();
+
+/* Truncate the history file, leaving only the last NLINES lines. */
+extern int history_truncate_file ();
+
+/* History expansion. */
+
+/* Expand the string STRING, placing the result into OUTPUT, a pointer
+   to a string.  Returns:
+
+   0) If no expansions took place (or, if the only change in
+      the text was the de-slashifying of the history expansion
+      character)
+   1) If expansions did take place
+  -1) If there was an error in expansion.
+   2) If the returned line should just be printed.
+
+  If an error ocurred in expansion, then OUTPUT contains a descriptive
+  error message. */
+extern int history_expand ();
+
+/* Extract a string segment consisting of the FIRST through LAST
+   arguments present in STRING.  Arguments are broken up as in
+   the shell. */
+extern char *history_arg_extract ();
+
+/* Return the text of the history event beginning at the current
+   offset into STRING. */
+extern char *get_history_event ();
+
+/* Return an array of tokens, much as the shell might.  The tokens are
+   parsed out of STRING. */
+extern char **history_tokenize ();
+
+/* Exported history variables. */
+extern int history_base;
+extern int history_length;
+extern int max_input_history;
+extern char history_expansion_char;
+extern char history_subst_char;
+extern char history_comment_char;
+extern char *history_no_expand_chars;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/isearch.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,378 @@
+/* **************************************************************** */
+/*								    */
+/*			I-Search and Searching			    */
+/*								    */
+/* **************************************************************** */
+
+/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+   This file contains the Readline Library (the Library), a set of
+   routines for providing Emacs style line input to programs that ask
+   for it.
+
+   The Library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   The Library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include "memalloc.h"
+#include "readline.h"
+#include "history.h"
+
+#define STREQ(a, b)	(((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0))
+#define STREQN(a, b, n)	(((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0))
+
+/* Variables imported from other files in the readline library. */
+extern Keymap _rl_keymap;
+extern HIST_ENTRY *saved_line_for_history;
+extern int rl_line_buffer_len;
+extern int rl_point, rl_end;
+extern char *rl_line_buffer;
+
+extern char *xmalloc (), *xrealloc ();
+
+static int rl_search_history ();
+
+/* Last line found by the current incremental search, so we don't `find'
+   identical lines many times in a row. */
+static char *prev_line_found;
+
+/* Search backwards through the history looking for a string which is typed
+   interactively.  Start with the current line. */
+rl_reverse_search_history (sign, key)
+     int sign;
+     int key;
+{
+  return (rl_search_history (-sign, key));
+}
+
+/* Search forwards through the history looking for a string which is typed
+   interactively.  Start with the current line. */
+rl_forward_search_history (sign, key)
+     int sign;
+     int key;
+{
+  return (rl_search_history (sign, key));
+}
+
+/* Display the current state of the search in the echo-area.
+   SEARCH_STRING contains the string that is being searched for,
+   DIRECTION is zero for forward, or 1 for reverse,
+   WHERE is the history list number of the current line.  If it is
+   -1, then this line is the starting one. */
+static void
+rl_display_search (search_string, reverse_p, where)
+     char *search_string;
+     int reverse_p, where;
+{
+  char *message;
+
+  message = xmalloc (1 + (search_string ? strlen (search_string) : 0) + 30);
+  *message = '\0';
+
+#if defined (NOTDEF)
+  if (where != -1)
+    sprintf (message, "[%d]", where + history_base);
+#endif /* NOTDEF */
+
+  strcat (message, "(");
+
+  if (reverse_p)
+    strcat (message, "reverse-");
+
+  strcat (message, "i-search)`");
+
+  if (search_string)
+    strcat (message, search_string);
+
+  strcat (message, "': ");
+  rl_message ("%s", message, 0);
+  free (message);
+  rl_redisplay ();
+}
+
+/* Search through the history looking for an interactively typed string.
+   This is analogous to i-search.  We start the search in the current line.
+   DIRECTION is which direction to search; >= 0 means forward, < 0 means
+   backwards. */
+static int
+rl_search_history (direction, invoking_key)
+     int direction;
+     int invoking_key;
+{
+  /* The string that the user types in to search for. */
+  char *search_string;
+
+  /* The current length of SEARCH_STRING. */
+  int search_string_index;
+
+  /* The amount of space that SEARCH_STRING has allocated to it. */
+  int search_string_size;
+
+  /* The list of lines to search through. */
+  char **lines, *allocated_line = (char *)NULL;
+
+  /* The length of LINES. */
+  int hlen;
+
+  /* Where we get LINES from. */
+  HIST_ENTRY **hlist = history_list ();
+
+  register int i = 0;
+  int orig_point = rl_point;
+  int orig_line = where_history ();
+  int last_found_line = orig_line;
+  int c, done = 0, found, failed, sline_len;
+
+  /* The line currently being searched. */
+  char *sline;
+
+  /* Offset in that line. */
+  int line_index;
+
+  /* Non-zero if we are doing a reverse search. */
+  int reverse = (direction < 0);
+
+  /* Create an arrary of pointers to the lines that we want to search. */
+  maybe_replace_line ();
+  if (hlist)
+    for (i = 0; hlist[i]; i++);
+
+  /* Allocate space for this many lines, +1 for the current input line,
+     and remember those lines. */
+  lines = (char **)xmalloc ((1 + (hlen = i)) * sizeof (char *));
+  for (i = 0; i < hlen; i++)
+    lines[i] = hlist[i]->line;
+
+  if (saved_line_for_history)
+    lines[i] = saved_line_for_history->line;
+  else
+    {
+      /* Keep track of this so we can free it. */
+      allocated_line = xmalloc (1 + strlen (rl_line_buffer));
+      strcpy (allocated_line, &rl_line_buffer[0]);
+      lines[i] = allocated_line;
+    }
+
+  hlen++;
+
+  /* The line where we start the search. */
+  i = orig_line;
+
+  /* Initialize search parameters. */
+  search_string = xmalloc (search_string_size = 128);
+  *search_string = '\0';
+  search_string_index = 0;
+  prev_line_found = (char *)0;		/* XXX */
+
+  /* Normalize DIRECTION into 1 or -1. */
+  direction = (direction >= 0) ? 1 : -1;
+
+  rl_display_search (search_string, reverse, -1);
+
+  sline = rl_line_buffer;
+  sline_len = strlen (sline);
+  line_index = rl_point;
+
+  found = failed = 0;
+  while (!done)
+    {
+      Function *f = (Function *)NULL;
+
+      /* Read a key and decide how to proceed. */
+      c = rl_read_key ();
+
+      /* Hack C to Do What I Mean. */
+      if (_rl_keymap[c].type == ISFUNC)
+	{
+	  f = _rl_keymap[c].function;
+
+	  if (f == rl_reverse_search_history)
+	    c = reverse ? -1 : -2;
+	  else if (f == rl_forward_search_history)
+	    c =  !reverse ? -1 : -2;
+	}
+
+      switch (c)
+	{
+	case ESC:
+	  done = 1;
+	  continue;
+
+	case -1:
+	  if (!search_string_index)
+	    continue;
+	  else
+	    {
+	      if (reverse)
+		--line_index;
+	      else
+		{
+		  if (line_index != sline_len)
+		    ++line_index;
+		  else
+		    ding ();
+		}
+	    }
+	  break;
+
+	  /* switch directions */
+	case -2:
+	  direction = -direction;
+	  reverse = (direction < 0);
+	  break;
+
+	case CTRL ('G'):
+	  strcpy (rl_line_buffer, lines[orig_line]);
+	  rl_point = orig_point;
+	  rl_end = strlen (rl_line_buffer);
+	  rl_clear_message ();
+	  free (allocated_line);
+	  free (lines);
+	  return 0;
+
+	default:
+	  if (CTRL_CHAR (c) || META_CHAR (c) || c == RUBOUT)
+	    {
+	      rl_execute_next (c);
+	      done = 1;
+	      continue;
+	    }
+	  else
+	    {
+	      /* Add character to search string and continue search. */
+	      if (search_string_index + 2 >= search_string_size)
+		{
+		  search_string_size += 128;
+		  search_string = xrealloc (search_string, search_string_size);
+		}
+	      search_string[search_string_index++] = c;
+	      search_string[search_string_index] = '\0';
+	      break;
+	    }
+	}
+
+      found = failed = 0;
+      while (1)
+	{
+	  int limit = sline_len - search_string_index + 1;
+
+	  /* Search the current line. */
+	  while (reverse ? (line_index >= 0) : (line_index < limit))
+	    {
+	      if (STREQN(search_string, sline + line_index, search_string_index))
+		  {
+		    found++;
+		    break;
+		  }
+	      else
+		line_index += direction;
+	    }
+	  if (found)
+	    break;
+
+	  /* Move to the next line, but skip new copies of the line
+	     we just found and lines shorter than the string we're
+	     searching for. */
+	  do
+	    {
+	      /* Move to the next line. */
+	      i += direction;
+
+	      /* At limit for direction? */
+	      if (reverse ? (i < 0) : (i == hlen))
+		{
+		  failed++;
+		  break;
+		}
+
+	      /* We will need these later. */
+	      sline = lines[i];
+	      sline_len = strlen (sline);
+	    }
+	  while ((prev_line_found && STREQ (prev_line_found, lines[i])) ||
+		 (search_string_index > sline_len));
+
+	  if (failed)
+	    break;
+
+	  /* Now set up the line for searching... */
+	  if (reverse)
+	    line_index = sline_len - search_string_index;
+	  else
+	    line_index = 0;
+	}
+
+      if (failed)
+	{
+	  /* We cannot find the search string.  Ding the bell. */
+	  ding ();
+	  i = last_found_line;
+	  continue; 		/* XXX - was break */
+	}
+
+      /* We have found the search string.  Just display it.  But don't
+	 actually move there in the history list until the user accepts
+	 the location. */
+      if (found)
+	{
+	  int line_len;
+
+	  prev_line_found = lines[i];
+	  line_len = strlen (lines[i]);
+
+	  if (line_len >= rl_line_buffer_len)
+	    rl_extend_line_buffer (line_len);
+
+	  strcpy (rl_line_buffer, lines[i]);
+	  rl_point = line_index;
+	  rl_end = line_len;
+	  last_found_line = i;
+	  rl_display_search (search_string, reverse, (i == orig_line) ? -1 : i);
+	}
+    }
+
+  /* The searching is over.  The user may have found the string that she
+     was looking for, or else she may have exited a failing search.  If
+     LINE_INDEX is -1, then that shows that the string searched for was
+     not found.  We use this to determine where to place rl_point. */
+
+  /* First put back the original state. */
+  strcpy (rl_line_buffer, lines[orig_line]);
+
+  /* Free the search string. */
+  free (search_string);
+
+  if (last_found_line < orig_line)
+    rl_get_previous_history (orig_line - last_found_line);
+  else
+    rl_get_next_history (last_found_line - orig_line);
+
+  /* If the string was not found, put point at the end of the line. */
+  if (line_index < 0)
+    line_index = strlen (rl_line_buffer);
+  rl_point = line_index;
+  rl_clear_message ();
+
+  free (allocated_line);
+  free (lines);
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/keymaps.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,200 @@
+/* keymaps.c -- Functions and keymaps for the GNU Readline library. */
+
+/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+   This file is part of GNU Readline, a library for reading lines
+   of text with interactive input and history editing.
+
+   Readline is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 1, or (at your option) any
+   later version.
+
+   Readline is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "rlconf.h"
+#include "keymaps.h"
+#include "emacs_keymap.c"
+
+#if defined (VI_MODE)
+#include "vi_keymap.c"
+#endif
+
+extern int rl_do_lowercase_version ();
+extern int rl_rubout (), rl_insert ();
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+/* **************************************************************** */
+/*								    */
+/*		      Functions for manipulating Keymaps.	    */
+/*								    */
+/* **************************************************************** */
+
+
+/* Return a new, empty keymap.
+   Free it with free() when you are done. */
+Keymap
+rl_make_bare_keymap ()
+{
+  register int i;
+  Keymap keymap = (Keymap)xmalloc (KEYMAP_SIZE * sizeof (KEYMAP_ENTRY));
+
+  for (i = 0; i < KEYMAP_SIZE; i++)
+    {
+      keymap[i].type = ISFUNC;
+      keymap[i].function = (Function *)NULL;
+    }
+
+  for (i = 'A'; i < ('Z' + 1); i++)
+    {
+      keymap[i].type = ISFUNC;
+      keymap[i].function = rl_do_lowercase_version;
+    }
+
+  return (keymap);
+}
+
+/* Return a new keymap which is a copy of MAP. */
+Keymap
+rl_copy_keymap (map)
+     Keymap map;
+{
+  register int i;
+  Keymap temp = rl_make_bare_keymap ();
+
+  for (i = 0; i < KEYMAP_SIZE; i++)
+    {
+      temp[i].type = map[i].type;
+      temp[i].function = map[i].function;
+    }
+  return (temp);
+}
+
+/* Return a new keymap with the printing characters bound to rl_insert,
+   the uppercase Meta characters bound to run their lowercase equivalents,
+   and the Meta digits bound to produce numeric arguments. */
+Keymap
+rl_make_keymap ()
+{
+  register int i;
+  Keymap newmap;
+
+  newmap = rl_make_bare_keymap ();
+
+  /* All ASCII printing characters are self-inserting. */
+  for (i = ' '; i < 127; i++)
+    newmap[i].function = rl_insert;
+
+  newmap[TAB].function = rl_insert;
+  newmap[RUBOUT].function = rl_rubout;
+  newmap[CTRL('H')].function = rl_rubout;
+
+#if KEYMAP_SIZE > 128
+  /* Printing characters in some 8-bit character sets. */
+  for (i = 128; i < 160; i++)
+    newmap[i].function = rl_insert;
+
+  /* ISO Latin-1 printing characters should self-insert. */
+  for (i = 160; i < 256; i++)
+    newmap[i].function = rl_insert;
+#endif /* KEYMAP_SIZE > 128 */
+
+  return (newmap);
+}
+
+/* Free the storage associated with MAP. */
+void
+rl_discard_keymap (map)
+     Keymap (map);
+{
+  int i;
+
+  if (!map)
+    return;
+
+  for (i = 0; i < KEYMAP_SIZE; i++)
+    {
+      switch (map[i].type)
+	{
+	case ISFUNC:
+	  break;
+
+	case ISKMAP:
+	  rl_discard_keymap ((Keymap)map[i].function);
+	  break;
+
+	case ISMACR:
+	  free ((char *)map[i].function);
+	  break;
+	}
+    }
+}
+
+#if defined (STATIC_MALLOC)
+
+/* **************************************************************** */
+/*								    */
+/*			xmalloc and xrealloc ()		     	    */
+/*								    */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/keymaps.h	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,95 @@
+/* keymaps.h -- Manipulation of readline keymaps. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _KEYMAPS_H_
+#define _KEYMAPS_H_
+
+#if defined (READLINE_LIBRARY)
+#  include "chardefs.h"
+#else
+#  include <readline/chardefs.h>
+#endif
+
+#if !defined (__FUNCTION_DEF)
+#  define __FUNCTION_DEF
+typedef int Function ();
+typedef void VFunction ();
+typedef char *CPFunction ();
+typedef char **CPPFunction ();
+#endif
+
+/* A keymap contains one entry for each key in the ASCII set.
+   Each entry consists of a type and a pointer.
+   POINTER is the address of a function to run, or the
+   address of a keymap to indirect through.
+   TYPE says which kind of thing POINTER is. */
+typedef struct _keymap_entry {
+  char type;
+  Function *function;
+} KEYMAP_ENTRY;
+
+/* This must be large enough to hold bindings for all of the characters
+   in a desired character set (e.g, 128 for ASCII, 256 for ISO Latin-x,
+   and so on). */
+#define KEYMAP_SIZE 256
+
+/* I wanted to make the above structure contain a union of:
+   union { Function *function; struct _keymap_entry *keymap; } value;
+   but this made it impossible for me to create a static array.
+   Maybe I need C lessons. */
+
+typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE];
+typedef KEYMAP_ENTRY *Keymap;
+
+/* The values that TYPE can have in a keymap entry. */
+#define ISFUNC 0
+#define ISKMAP 1
+#define ISMACR 2
+
+extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_meta_keymap, emacs_ctlx_keymap;
+extern KEYMAP_ENTRY_ARRAY vi_insertion_keymap, vi_movement_keymap;
+
+/* Return a new, empty keymap.
+   Free it with free() when you are done. */
+extern Keymap rl_make_bare_keymap ();
+
+/* Return a new keymap which is a copy of MAP. */
+extern Keymap rl_copy_keymap ();
+
+/* Return a new keymap with the printing characters bound to rl_insert,
+   the lowercase Meta characters bound to run their equivalents, and
+   the Meta digits bound to produce numeric arguments. */
+extern Keymap rl_make_keymap ();
+
+extern void rl_discard_keymap ();
+
+/* Return the keymap corresponding to a given name.  Names look like
+   `emacs' or `emacs-meta' or `vi-insert'. */
+extern Keymap rl_get_keymap_by_name ();
+
+/* Return the current keymap. */
+extern Keymap rl_get_keymap ();
+
+/* Set the current keymap to MAP. */
+extern void rl_set_keymap ();
+
+#endif /* _KEYMAPS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/memalloc.h	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,56 @@
+/* memalloc.h -- consolidate code for including alloca.h or malloc.h and
+   defining alloca. */
+
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (__MEMALLOC_H__)
+#  define __MEMALLOC_H__
+
+#if defined (sparc) && defined (sun) && !defined (HAVE_ALLOCA_H)
+#  define HAVE_ALLOCA_H
+#endif
+
+#if defined (__GNUC__) && !defined (HAVE_ALLOCA)
+#  define HAVE_ALLOCA
+#endif
+
+#if defined (HAVE_ALLOCA_H) && !defined (HAVE_ALLOCA)
+#  define HAVE_ALLOCA
+#endif /* HAVE_ALLOCA_H && !HAVE_ALLOCA */
+
+#if !defined (BUILDING_MAKEFILE)
+
+#if defined (__GNUC__)
+#  undef alloca
+#  define alloca __builtin_alloca
+#else /* !__GNUC__ */
+#  if defined (HAVE_ALLOCA_H)
+#    if defined (IBMESA)
+#      include <malloc.h>
+#    else /* !IBMESA */
+#      include <alloca.h>
+#    endif /* !IBMESA */
+#  else
+extern char *alloca ();
+#  endif /* !HAVE_ALLOCA_H */
+#endif /* !__GNUC__ */
+
+#endif /* !BUILDING_MAKEFILE */
+
+#endif /* __MEMALLOC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/parens.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,130 @@
+/* parens.c -- Implemenation of matching parenthesis feature. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#include "rlconf.h"
+
+#if !defined (PAREN_MATCHING)
+
+rl_insert_close (count, invoking_key)
+     int count, invoking_key;
+{
+  return (rl_insert (count, invoking_key));
+}
+
+#else /* PAREN_MATCHING */
+
+#include <stdio.h>
+#include <sys/types.h>
+#if defined (FD_SET)
+#  include <sys/time.h>
+#endif /* FD_SET */
+#include "readline.h"
+
+extern int rl_explicit_arg;
+
+/* Non-zero means try to blink the matching open parenthesis when the
+   close parenthesis is inserted. */
+#if defined (FD_SET)
+int rl_blink_matching_paren = 1;
+#else /* !FD_SET */
+int rl_blink_matching_paren = 0;
+#endif /* !FD_SET */
+
+static int find_matching_open ();
+
+rl_insert_close (count, invoking_key)
+     int count, invoking_key;
+{
+  if (rl_explicit_arg || !rl_blink_matching_paren)
+    rl_insert (count, invoking_key);
+  else
+    {
+#if defined (FD_SET)
+      int orig_point, match_point, ready;
+      struct timeval timer;
+      fd_set readfds;
+
+      rl_insert (1, invoking_key);
+      rl_redisplay ();
+      match_point =
+	find_matching_open (rl_line_buffer, rl_point - 2, invoking_key);
+
+      /* Emacs might message or ring the bell here, but I don't. */
+      if (match_point < 0)
+	return -1;
+
+      FD_ZERO (&readfds);
+      FD_SET (fileno (rl_instream), &readfds);
+      timer.tv_sec = 1;
+      timer.tv_usec = 500;
+
+      orig_point = rl_point;
+      rl_point = match_point;
+      rl_redisplay ();
+      ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer);
+      rl_point = orig_point;
+#else /* !FD_SET */
+      rl_insert (count, invoking_key);
+#endif /* !FD_SET */
+    }
+  return 0;
+}
+
+static int
+find_matching_open (string, from, closer)
+     char *string;
+     int from, closer;
+{
+  register int i;
+  int opener, level, delimiter;
+
+  switch (closer)
+    {
+    case ']': opener = '['; break;
+    case '}': opener = '{'; break;
+    case ')': opener = '('; break;
+    default:
+      return (-1);
+    }
+
+  level = 1;			/* The closer passed in counts as 1. */
+  delimiter = 0;		/* Delimited state unknown. */
+
+  for (i = from; i > -1; i--)
+    {
+      if (delimiter && (string[i] == delimiter))
+	delimiter = 0;
+      else if ((string[i] == '\'') || (string[i] == '"'))
+	delimiter = rl_line_buffer[i];
+      else if (!delimiter && (string[i] == closer))
+	level++;
+      else if (!delimiter && (string[i] == opener))
+	level--;
+
+      if (!level)
+	break;
+    }
+  return (i);
+}
+
+#endif /* PAREN_MATCHING */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/posixstat.h	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,149 @@
+/* posixstat.h -- Posix stat(2) definitions for systems that
+   don't have them. */
+
+/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This file should be included instead of <sys/stat.h>.
+   It relies on the local sys/stat.h to work though. */
+#if !defined (_POSIXSTAT_H)
+#define _POSIXSTAT_H
+
+#include <sys/stat.h>
+
+#if defined (isc386)
+#  if !defined (S_IFDIR)
+#    define S_IFDIR 0040000
+#  endif /* !S_IFDIR */
+#  if !defined (S_IFMT)
+#    define S_IFMT  0170000
+#  endif /* !S_IFMT */
+#endif /* isc386 */
+
+/* This text is taken directly from the Cadmus I was trying to
+   compile on:
+    the following MACROs are defined for X/OPEN compatibility
+    however, is the param correct ??
+   #define S_ISBLK(s) ((s.st_mode & S_IFMT) == S_IFBLK)
+
+  Well, the answer is no.  Thus... */
+#if defined (BrainDeath)
+#  undef S_ISBLK
+#  undef S_ISCHR
+#  undef S_ISDIR
+#  undef S_ISFIFO
+#  undef S_ISREG
+#endif /* BrainDeath */
+
+/* Posix 1003.1 5.6.1.1 <sys/stat.h> file types */
+
+/* Some Posix-wannabe systems define _S_IF* macros instead of S_IF*, but
+   do not provide the S_IS* macros that Posix requires. */
+
+#if defined (_S_IFMT) && !defined (S_IFMT)
+#define S_IFMT _S_IFMT
+#endif
+#if defined (_S_IFIFO) && !defined (S_IFIFO)
+#define S_IFIFO _S_IFIFO
+#endif
+#if defined (_S_IFCHR) && !defined (S_IFCHR)
+#define S_IFCHR _S_IFCHR
+#endif
+#if defined (_S_IFDIR) && !defined (S_IFDIR)
+#define S_IFDIR _S_IFDIR
+#endif
+#if defined (_S_IFBLK) && !defined (S_IFBLK)
+#define S_IFBLK _S_IFBLK
+#endif
+#if defined (_S_IFREG) && !defined (S_IFREG)
+#define S_IFREG _S_IFREG
+#endif
+#if defined (_S_IFLNK) && !defined (S_IFLNK)
+#define S_IFLNK _S_IFLNK
+#endif
+#if defined (_S_IFSOCK) && !defined (S_IFSOCK)
+#define S_IFSOCK _S_IFSOCK
+#endif
+
+/* Test for each symbol individually and define the ones necessary (some
+   systems claiming Posix compatibility define some but not all). */
+
+#if defined (S_IFBLK) && !defined (S_ISBLK)
+#define	S_ISBLK(m)	(((m)&S_IFMT) == S_IFBLK)	/* block device */
+#endif
+
+#if defined (S_IFCHR) && !defined (S_ISCHR)
+#define	S_ISCHR(m)	(((m)&S_IFMT) == S_IFCHR)	/* character device */
+#endif
+
+#if defined (S_IFDIR) && !defined (S_ISDIR)
+#define	S_ISDIR(m)	(((m)&S_IFMT) == S_IFDIR)	/* directory */
+#endif
+
+#if defined (S_IFREG) && !defined (S_ISREG)
+#define	S_ISREG(m)	(((m)&S_IFMT) == S_IFREG)	/* file */
+#endif
+
+#if defined (S_IFIFO) && !defined (S_ISFIFO)
+#define	S_ISFIFO(m)	(((m)&S_IFMT) == S_IFIFO)	/* fifo - named pipe */
+#endif
+
+#if defined (S_IFLNK) && !defined (S_ISLNK)
+#define	S_ISLNK(m)	(((m)&S_IFMT) == S_IFLNK)	/* symbolic link */
+#endif
+
+#if defined (S_IFSOCK) && !defined (S_ISSOCK)
+#define	S_ISSOCK(m)	(((m)&S_IFMT) == S_IFSOCK)	/* socket */
+#endif
+
+/*
+ * POSIX 1003.1 5.6.1.2 <sys/stat.h> File Modes
+ */
+ 
+#if !defined (S_IRWXU)
+#  if !defined (S_IREAD)
+#    define S_IREAD	00400
+#    define S_IWRITE	00200
+#    define S_IEXEC	00100
+#  endif /* S_IREAD */
+
+#  if !defined (S_IRUSR)
+#    define S_IRUSR	S_IREAD			/* read, owner */
+#    define S_IWUSR	S_IWRITE		/* write, owner */
+#    define S_IXUSR	S_IEXEC			/* execute, owner */
+
+#    define S_IRGRP	(S_IREAD  >> 3)		/* read, group */
+#    define S_IWGRP	(S_IWRITE >> 3)		/* write, group */
+#    define S_IXGRP	(S_IEXEC  >> 3)		/* execute, group */
+
+#    define S_IROTH	(S_IREAD  >> 6)		/* read, other */
+#    define S_IWOTH	(S_IWRITE >> 6)		/* write, other */
+#    define S_IXOTH	(S_IEXEC  >> 6)		/* execute, other */
+#  endif /* !S_IRUSR */
+
+#  define S_IRWXU	(S_IRUSR | S_IWUSR | S_IXUSR)
+#  define S_IRWXG	(S_IRGRP | S_IWGRP | S_IXGRP)
+#  define S_IRWXO	(S_IROTH | S_IWOTH | S_IXOTH)
+#endif /* !S_IRWXU */
+
+/* These are non-standard, but are used in builtins.c$symbolic_umask() */
+#define S_IRUGO		(S_IRUSR | S_IRGRP | S_IROTH)
+#define S_IWUGO		(S_IWUSR | S_IWGRP | S_IWOTH)
+#define S_IXUGO		(S_IXUSR | S_IXGRP | S_IXOTH)
+
+#endif /* _POSIXSTAT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/readline.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,3539 @@
+/* readline.c -- a general facility for reading lines of input
+   with emacs style editing and completion. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#if !defined (NO_SYS_FILE)
+#  include <sys/file.h>
+#endif /* !NO_SYS_FILE */
+#include <signal.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <errno.h>
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include <setjmp.h>
+
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+#if defined (GWINSZ_IN_SYS_IOCTL) || (defined (VSTATUS) && !defined (SunOS4))
+#  include <sys/ioctl.h>
+#endif /* GWINSZ_IN_SYS_IOCTL || VSTATUS */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+/* NOTE: Functions and variables prefixed with `_rl_' are
+   pseudo-global: they are global so they can be shared
+   between files in the readline library, but are not intended
+   to be visible to readline callers. */
+
+/* Functions imported from other files in the library. */
+extern char *tgetstr ();
+extern void rl_prep_terminal (), rl_deprep_terminal ();
+
+extern void _rl_bind_if_unbound ();
+
+/* External redisplay functions and variables from display.c */
+extern void _rl_move_vert ();
+extern void _rl_update_final ();
+
+extern void _rl_erase_at_end_of_line ();
+extern void _rl_move_cursor_relative ();
+
+extern int _rl_vis_botlin;
+extern int _rl_last_c_pos;
+extern int _rl_horizontal_scroll_mode;
+extern int rl_display_fixed;
+extern char *rl_display_prompt;
+
+/* Variables imported from complete.c. */
+extern char *rl_completer_word_break_characters;
+extern char *rl_basic_word_break_characters;
+extern int rl_completion_query_items;
+extern int rl_complete_with_tilde_expansion;
+
+#if defined (VI_MODE)
+extern void _rl_vi_set_last ();
+extern void _rl_vi_reset_last ();
+extern void _rl_vi_done_inserting ();
+#endif /* VI_MODE */
+
+/* Forward declarations used in this file. */
+void _rl_free_history_entry ();
+
+int _rl_dispatch ();
+void _rl_set_screen_size ();
+int _rl_output_character_function ();
+
+static char *readline_internal ();
+static void readline_initialize_everything ();
+static int init_terminal_io ();
+static void start_using_history ();
+static void bind_arrow_keys ();
+
+#if !defined (__GO32__)
+static void readline_default_bindings ();
+#endif /* !__GO32__ */
+
+#if defined (__GO32__)
+#  include <sys/pc.h>
+#  undef HANDLE_SIGNALS
+#endif /* __GO32__ */
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+
+/* **************************************************************** */
+/*								    */
+/*			Line editing input utility		    */
+/*								    */
+/* **************************************************************** */
+
+static char *LibraryVersion = "2.0";
+
+/* A pointer to the keymap that is currently in use.
+   By default, it is the standard emacs keymap. */
+Keymap _rl_keymap = emacs_standard_keymap;
+
+/* The current style of editing. */
+int rl_editing_mode = emacs_mode;
+
+/* Non-zero if the previous command was a kill command. */
+static int last_command_was_kill = 0;
+
+/* The current value of the numeric argument specified by the user. */
+int rl_numeric_arg = 1;
+
+/* Non-zero if an argument was typed. */
+int rl_explicit_arg = 0;
+
+/* Temporary value used while generating the argument. */
+int rl_arg_sign = 1;
+
+/* Non-zero means we have been called at least once before. */
+static int rl_initialized = 0;
+
+/* If non-zero, this program is running in an EMACS buffer. */
+static int running_in_emacs = 0;
+
+/* The current offset in the current input line. */
+int rl_point;
+
+/* Mark in the current input line. */
+int rl_mark;
+
+/* Length of the current input line. */
+int rl_end;
+
+/* Make this non-zero to return the current input_line. */
+int rl_done;
+
+/* The last function executed by readline. */
+Function *rl_last_func = (Function *)NULL;
+
+/* Top level environment for readline_internal (). */
+static jmp_buf readline_top_level;
+
+/* The streams we interact with. */
+static FILE *in_stream, *out_stream;
+
+/* The names of the streams that we do input and output to. */
+FILE *rl_instream = (FILE *)NULL;
+FILE *rl_outstream = (FILE *)NULL;
+
+/* Non-zero means echo characters as they are read. */
+int readline_echoing_p = 1;
+
+/* Current prompt. */
+char *rl_prompt;
+int rl_visible_prompt_length = 0;
+
+/* The number of characters read in order to type this complete command. */
+int rl_key_sequence_length = 0;
+
+/* If non-zero, then this is the address of a function to call just
+   before readline_internal () prints the first prompt. */
+Function *rl_startup_hook = (Function *)NULL;
+
+/* What we use internally.  You should always refer to RL_LINE_BUFFER. */
+static char *the_line;
+
+/* The character that can generate an EOF.  Really read from
+   the terminal driver... just defaulted here. */
+int _rl_eof_char = CTRL ('D');
+
+/* Non-zero makes this the next keystroke to read. */
+int rl_pending_input = 0;
+
+/* Pointer to a useful terminal name. */
+char *rl_terminal_name = (char *)NULL;
+
+/* Non-zero means to always use horizontal scrolling in line display. */
+int _rl_horizontal_scroll_mode = 0;
+
+/* Non-zero means to display an asterisk at the starts of history lines
+   which have been modified. */
+int _rl_mark_modified_lines = 0;  
+
+/* The style of `bell' notification preferred.  This can be set to NO_BELL,
+   AUDIBLE_BELL, or VISIBLE_BELL. */
+int _rl_bell_preference = AUDIBLE_BELL;
+     
+/* Line buffer and maintenence. */
+char *rl_line_buffer = (char *)NULL;
+int rl_line_buffer_len = 0;
+#define DEFAULT_BUFFER_SIZE 256
+
+/* Forward declarations used by the display and termcap code. */
+int term_xn;
+int screenwidth, screenheight, screenchars;
+
+
+/* **************************************************************** */
+/*								    */
+/*			`Forward' declarations  		    */
+/*								    */
+/* **************************************************************** */
+
+/* Non-zero means do not parse any lines other than comments and
+   parser directives. */
+unsigned char _rl_parsing_conditionalized_out = 0;
+
+/* Non-zero means to save keys that we dispatch on in a kbd macro. */
+static int defining_kbd_macro = 0;
+
+/* Non-zero means to convert characters with the meta bit set to
+   escape-prefixed characters so we can indirect through
+   emacs_meta_keymap or vi_escape_keymap. */
+int _rl_convert_meta_chars_to_ascii = 1;
+
+/* Non-zero means to output characters with the meta bit set directly
+   rather than as a meta-prefixed escape sequence. */
+int _rl_output_meta_chars = 0;
+
+/* Non-zero tells rl_delete_text and rl_insert_text to not add to
+   the undo list. */
+static int doing_an_undo = 0;
+
+/* **************************************************************** */
+/*								    */
+/*			Top Level Functions			    */
+/*								    */
+/* **************************************************************** */
+
+/* Non-zero means treat 0200 bit in terminal input as Meta bit. */
+int _rl_meta_flag = 0;	/* Forward declaration */
+
+/* Read a line of input.  Prompt with PROMPT.  A NULL PROMPT means
+   none.  A return value of NULL means that EOF was encountered. */
+char *
+readline (prompt)
+     char *prompt;
+{
+  char *value;
+
+  rl_prompt = prompt;
+
+  /* If we are at EOF return a NULL string. */
+  if (rl_pending_input == EOF)
+    {
+      rl_pending_input = 0;
+      return ((char *)NULL);
+    }
+
+  rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
+
+  rl_initialize ();
+  rl_prep_terminal (_rl_meta_flag);
+
+#if defined (HANDLE_SIGNALS)
+  rl_set_signals ();
+#endif
+
+  value = readline_internal ();
+  rl_deprep_terminal ();
+
+#if defined (HANDLE_SIGNALS)
+  rl_clear_signals ();
+#endif
+
+  return (value);
+}
+
+/* Read a line of input from the global rl_instream, doing output on
+   the global rl_outstream.
+   If rl_prompt is non-null, then that is our prompt. */
+static char *
+readline_internal ()
+{
+  int lastc, c, eof_found;
+
+  in_stream  = rl_instream;
+  out_stream = rl_outstream;
+
+  lastc = -1;
+  eof_found = 0;
+
+  if (rl_startup_hook)
+    (*rl_startup_hook) ();
+
+  if (!readline_echoing_p)
+    {
+      if (rl_prompt)
+	{
+	  fprintf (out_stream, "%s", rl_prompt);
+	  fflush (out_stream);
+	}
+    }
+  else
+    {
+      rl_on_new_line ();
+      rl_redisplay ();
+#if defined (VI_MODE)
+      if (rl_editing_mode == vi_mode)
+	rl_vi_insertion_mode ();
+#endif /* VI_MODE */
+    }
+
+  while (!rl_done)
+    {
+      int lk = last_command_was_kill;
+      int code;
+
+      code = setjmp (readline_top_level);
+
+      if (code)
+	rl_redisplay ();
+
+      if (!rl_pending_input)
+	{
+	  /* Then initialize the argument and number of keys read. */
+	  rl_init_argument ();
+	  rl_key_sequence_length = 0;
+	}
+
+      c = rl_read_key ();
+
+      /* EOF typed to a non-blank line is a <NL>. */
+      if (c == EOF && rl_end)
+	c = NEWLINE;
+
+      /* The character _rl_eof_char typed to blank line, and not as the
+	 previous character is interpreted as EOF. */
+      if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end)
+	{
+	  eof_found = 1;
+	  break;
+	}
+
+      lastc = c;
+      _rl_dispatch (c, _rl_keymap);
+
+      /* If there was no change in last_command_was_kill, then no kill
+	 has taken place.  Note that if input is pending we are reading
+	 a prefix command, so nothing has changed yet. */
+      if (!rl_pending_input)
+	{
+	  if (lk == last_command_was_kill)
+	    last_command_was_kill = 0;
+	}
+
+#if defined (VI_MODE)
+      /* In vi mode, when you exit insert mode, the cursor moves back
+	 over the previous character.  We explicitly check for that here. */
+      if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap)
+	rl_vi_check ();
+#endif /* VI_MODE */
+
+      if (!rl_done)
+	rl_redisplay ();
+    }
+
+  /* Restore the original of this history line, iff the line that we
+     are editing was originally in the history, AND the line has changed. */
+  {
+    HIST_ENTRY *entry = current_history ();
+
+    if (entry && rl_undo_list)
+      {
+	char *temp = savestring (the_line);
+	rl_revert_line ();
+	entry = replace_history_entry (where_history (), the_line,
+				       (HIST_ENTRY *)NULL);
+	_rl_free_history_entry (entry);
+
+	strcpy (the_line, temp);
+	free (temp);
+      }
+  }
+
+  /* At any rate, it is highly likely that this line has an undo list.  Get
+     rid of it now. */
+  if (rl_undo_list)
+    free_undo_list ();
+
+  if (eof_found)
+    return (char *)NULL;
+  else
+    return (savestring (the_line));
+}
+
+/* **************************************************************** */
+/*								    */
+/*			Character Input Buffering       	    */
+/*								    */
+/* **************************************************************** */
+
+static int pop_index = 0, push_index = 0, ibuffer_len = 511;
+static unsigned char ibuffer[512];
+
+/* Non-null means it is a pointer to a function to run while waiting for
+   character input. */
+Function *rl_event_hook = (Function *)NULL;
+
+#define any_typein (push_index != pop_index)
+
+/* Add KEY to the buffer of characters to be read. */
+rl_stuff_char (key)
+     int key;
+{
+  if (key == EOF)
+    {
+      key = NEWLINE;
+      rl_pending_input = EOF;
+    }
+  ibuffer[push_index++] = key;
+  if (push_index >= ibuffer_len)
+    push_index = 0;
+  return push_index;
+}
+
+/* Return the amount of space available in the
+   buffer for stuffing characters. */
+int
+ibuffer_space ()
+{
+  if (pop_index > push_index)
+    return (pop_index - push_index);
+  else
+    return (ibuffer_len - (push_index - pop_index));
+}
+
+/* Get a key from the buffer of characters to be read.
+   Return the key in KEY.
+   Result is KEY if there was a key, or 0 if there wasn't. */
+int
+rl_get_char (key)
+     int *key;
+{
+  if (push_index == pop_index)
+    return (0);
+
+  *key = ibuffer[pop_index++];
+
+  if (pop_index >= ibuffer_len)
+    pop_index = 0;
+
+  return (1);
+}
+
+/* Stuff KEY into the *front* of the input buffer.
+   Returns non-zero if successful, zero if there is
+   no space left in the buffer. */
+int
+rl_unget_char (key)
+     int key;
+{
+  if (ibuffer_space ())
+    {
+      pop_index--;
+      if (pop_index < 0)
+	pop_index = ibuffer_len - 1;
+      ibuffer[pop_index] = key;
+      return (1);
+    }
+  return (0);
+}
+
+/* If a character is available to be read, then read it
+   and stuff it into IBUFFER.  Otherwise, just return. */
+void
+rl_gather_tyi ()
+{
+#if defined (__GO32__)
+  char input;
+
+  if (isatty (0))
+    {
+      int i = rl_getc ();
+
+      if (i != EOF)
+	rl_stuff_char (i);
+    }
+  else if (kbhit () && ibuffer_space ())
+    rl_stuff_char (getkey ());
+#else /* !__GO32__ */
+
+  int tty = fileno (in_stream);
+  register int tem, result = -1;
+  int chars_avail;
+  char input;
+
+#if defined (FIONREAD)
+  result = ioctl (tty, FIONREAD, &chars_avail);
+#endif
+
+#if defined (O_NDELAY)
+  if (result == -1)
+    {
+      int flags;
+
+      flags = fcntl (tty, F_GETFL, 0);
+
+      fcntl (tty, F_SETFL, (flags | O_NDELAY));
+      chars_avail = read (tty, &input, 1);
+
+      fcntl (tty, F_SETFL, flags);
+      if (chars_avail == -1 && errno == EAGAIN)
+	return;
+    }
+#endif /* O_NDELAY */
+
+  /* If there's nothing available, don't waste time trying to read
+     something. */
+  if (chars_avail == 0)
+    return;
+
+  tem = ibuffer_space ();
+
+  if (chars_avail > tem)
+    chars_avail = tem;
+
+  /* One cannot read all of the available input.  I can only read a single
+     character at a time, or else programs which require input can be
+     thwarted.  If the buffer is larger than one character, I lose.
+     Damn! */
+  if (tem < ibuffer_len)
+    chars_avail = 0;
+
+  if (result != -1)
+    {
+      while (chars_avail--)
+	rl_stuff_char (rl_getc (in_stream));
+    }
+  else
+    {
+      if (chars_avail)
+	rl_stuff_char (input);
+    }
+#endif /* !__GO32__ */
+}
+
+static int next_macro_key ();
+/* Read a key, including pending input. */
+int
+rl_read_key ()
+{
+  int c;
+
+  rl_key_sequence_length++;
+
+  if (rl_pending_input)
+    {
+      c = rl_pending_input;
+      rl_pending_input = 0;
+    }
+  else
+    {
+      /* If input is coming from a macro, then use that. */
+      if (c = next_macro_key ())
+	return (c);
+
+      /* If the user has an event function, then call it periodically. */
+      if (rl_event_hook)
+	{
+	  while (rl_event_hook && !rl_get_char (&c))
+	    {
+	      (*rl_event_hook) ();
+	      rl_gather_tyi ();
+	    }
+	}
+      else
+	{
+	  if (!rl_get_char (&c))
+	    c = rl_getc (in_stream);
+	}
+    }
+
+  return (c);
+}
+
+/* Found later in this file. */
+static void add_macro_char (), with_macro_input ();
+
+/* Do the command associated with KEY in MAP.
+   If the associated command is really a keymap, then read
+   another key, and dispatch into that map. */
+int
+_rl_dispatch (key, map)
+     register int key;
+     Keymap map;
+{
+  int r = 0;
+
+  if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
+    {
+      if (map[ESC].type == ISKMAP)
+	{
+	  if (defining_kbd_macro)
+	    add_macro_char (ESC);
+	  map = FUNCTION_TO_KEYMAP (map, ESC);
+	  key = UNMETA (key);
+	  rl_key_sequence_length += 2;
+	  return (_rl_dispatch (key, map));
+	}
+      else
+	ding ();
+      return 0;
+    }
+
+  if (defining_kbd_macro)
+    add_macro_char (key);
+
+  switch (map[key].type)
+    {
+    case ISFUNC:
+      {
+	Function *func = map[key].function;
+
+	if (func != (Function *)NULL)
+	  {
+	    /* Special case rl_do_lowercase_version (). */
+	    if (func == rl_do_lowercase_version)
+	      return (_rl_dispatch (to_lower (key), map));
+
+	    r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key);
+
+	    /* If we have input pending, then the last command was a prefix
+	       command.  Don't change the state of rl_last_func.  Otherwise,
+	       remember the last command executed in this variable. */
+	    if (!rl_pending_input)
+	      rl_last_func = map[key].function;
+	  }
+	else
+	  {
+	    rl_abort ();
+	    return -1;
+	  }
+      }
+      break;
+
+    case ISKMAP:
+      if (map[key].function != (Function *)NULL)
+	{
+	  int newkey;
+
+	  rl_key_sequence_length++;
+	  newkey = rl_read_key ();
+	  r = _rl_dispatch (newkey, FUNCTION_TO_KEYMAP (map, key));
+	}
+      else
+	{
+	  rl_abort ();
+	  return -1;
+	}
+      break;
+
+    case ISMACR:
+      if (map[key].function != (Function *)NULL)
+	{
+	  char *macro;
+
+	  macro = savestring ((char *)map[key].function);
+	  with_macro_input (macro);
+	  return 0;
+	}
+      break;
+    }
+#if defined (VI_MODE)
+  if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap &&
+      rl_vi_textmod_command (key))
+    _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);
+#endif
+  return (r);
+}
+
+
+/* **************************************************************** */
+/*								    */
+/*			Hacking Keyboard Macros 		    */
+/*								    */
+/* **************************************************************** */
+
+/* The currently executing macro string.  If this is non-zero,
+   then it is a malloc ()'ed string where input is coming from. */
+static char *executing_macro = (char *)NULL;
+
+/* The offset in the above string to the next character to be read. */
+static int executing_macro_index = 0;
+
+/* The current macro string being built.  Characters get stuffed
+   in here by add_macro_char (). */
+static char *current_macro = (char *)NULL;
+
+/* The size of the buffer allocated to current_macro. */
+static int current_macro_size = 0;
+
+/* The index at which characters are being added to current_macro. */
+static int current_macro_index = 0;
+
+/* A structure used to save nested macro strings.
+   It is a linked list of string/index for each saved macro. */
+struct saved_macro {
+  struct saved_macro *next;
+  char *string;
+  int sindex;
+};
+
+/* The list of saved macros. */
+struct saved_macro *macro_list = (struct saved_macro *)NULL;
+
+/* Forward declarations of static functions.  Thank you C. */
+static void push_executing_macro (), pop_executing_macro ();
+
+/* This one has to be declared earlier in the file. */
+/* static void add_macro_char (); */
+
+/* Set up to read subsequent input from STRING.
+   STRING is free ()'ed when we are done with it. */
+static void
+with_macro_input (string)
+     char *string;
+{
+  push_executing_macro ();
+  executing_macro = string;
+  executing_macro_index = 0;
+}
+
+/* Return the next character available from a macro, or 0 if
+   there are no macro characters. */
+static int
+next_macro_key ()
+{
+  if (!executing_macro)
+    return (0);
+
+  if (!executing_macro[executing_macro_index])
+    {
+      pop_executing_macro ();
+      return (next_macro_key ());
+    }
+
+  return (executing_macro[executing_macro_index++]);
+}
+
+/* Save the currently executing macro on a stack of saved macros. */
+static void
+push_executing_macro ()
+{
+  struct saved_macro *saver;
+
+  saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro));
+  saver->next = macro_list;
+  saver->sindex = executing_macro_index;
+  saver->string = executing_macro;
+
+  macro_list = saver;
+}
+
+/* Discard the current macro, replacing it with the one
+   on the top of the stack of saved macros. */
+static void
+pop_executing_macro ()
+{
+  if (executing_macro)
+    free (executing_macro);
+
+  executing_macro = (char *)NULL;
+  executing_macro_index = 0;
+
+  if (macro_list)
+    {
+      struct saved_macro *disposer = macro_list;
+      executing_macro = macro_list->string;
+      executing_macro_index = macro_list->sindex;
+      macro_list = macro_list->next;
+      free (disposer);
+    }
+}
+
+/* Add a character to the macro being built. */
+static void
+add_macro_char (c)
+     int c;
+{
+  if (current_macro_index + 1 >= current_macro_size)
+    {
+      if (!current_macro)
+	current_macro = xmalloc (current_macro_size = 25);
+      else
+	current_macro = xrealloc (current_macro, current_macro_size += 25);
+    }
+
+  current_macro[current_macro_index++] = c;
+  current_macro[current_macro_index] = '\0';
+}
+
+/* Begin defining a keyboard macro.
+   Keystrokes are recorded as they are executed.
+   End the definition with rl_end_kbd_macro ().
+   If a numeric argument was explicitly typed, then append this
+   definition to the end of the existing macro, and start by
+   re-executing the existing macro. */
+rl_start_kbd_macro (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  if (defining_kbd_macro)
+    {
+      rl_abort ();
+      return -1;
+    }
+
+  if (rl_explicit_arg)
+    {
+      if (current_macro)
+	with_macro_input (savestring (current_macro));
+    }
+  else
+    current_macro_index = 0;
+
+  defining_kbd_macro = 1;
+  return 0;
+}
+
+/* Stop defining a keyboard macro.
+   A numeric argument says to execute the macro right now,
+   that many times, counting the definition as the first time. */
+rl_end_kbd_macro (count, ignore)
+     int count, ignore;
+{
+  if (!defining_kbd_macro)
+    {
+      rl_abort ();
+      return -1;
+    }
+
+  current_macro_index -= (rl_key_sequence_length - 1);
+  current_macro[current_macro_index] = '\0';
+
+  defining_kbd_macro = 0;
+
+  return (rl_call_last_kbd_macro (--count, 0));
+}
+
+/* Execute the most recently defined keyboard macro.
+   COUNT says how many times to execute it. */
+rl_call_last_kbd_macro (count, ignore)
+     int count, ignore;
+{
+  if (!current_macro)
+    rl_abort ();
+
+  if (defining_kbd_macro)
+    {
+      ding ();		/* no recursive macros */
+      current_macro[--current_macro_index] = '\0';	/* erase this char */
+      return 0;
+    }
+
+  while (count--)
+    with_macro_input (savestring (current_macro));
+  return 0;
+}
+
+void
+_rl_kill_kbd_macro ()
+{
+  if (current_macro)
+    {
+      free (current_macro);
+      current_macro = (char *) NULL;
+    }
+  current_macro_size = current_macro_index = 0;
+
+  if (executing_macro)
+    {
+      free (executing_macro);
+      executing_macro = (char *) NULL;
+    }
+  executing_macro_index = 0;
+
+  defining_kbd_macro = 0;
+}
+
+/* **************************************************************** */
+/*								    */
+/*			Initializations 			    */
+/*								    */
+/* **************************************************************** */
+
+/* Initliaze readline (and terminal if not already). */
+rl_initialize ()
+{
+  /* If we have never been called before, initialize the
+     terminal and data structures. */
+  if (!rl_initialized)
+    {
+      readline_initialize_everything ();
+      rl_initialized++;
+    }
+
+  /* Initalize the current line information. */
+  rl_point = rl_end = 0;
+  the_line = rl_line_buffer;
+  the_line[0] = 0;
+
+  /* We aren't done yet.  We haven't even gotten started yet! */
+  rl_done = 0;
+
+  /* Tell the history routines what is going on. */
+  start_using_history ();
+
+  /* Make the display buffer match the state of the line. */
+  rl_reset_line_state ();
+
+  /* No such function typed yet. */
+  rl_last_func = (Function *)NULL;
+
+  /* Parsing of key-bindings begins in an enabled state. */
+  _rl_parsing_conditionalized_out = 0;
+
+  return 0;
+}
+
+/* Initialize the entire state of the world. */
+static void
+readline_initialize_everything ()
+{
+  char *t;
+
+  /* Find out if we are running in Emacs. */
+  running_in_emacs = getenv ("EMACS") != (char *)0;
+
+  /* Set up input and output if they are not already set up. */
+  if (!rl_instream)
+    rl_instream = stdin;
+
+  if (!rl_outstream)
+    rl_outstream = stdout;
+
+  /* Bind in_stream and out_stream immediately.  These values may change,
+     but they may also be used before readline_internal () is called. */
+  in_stream = rl_instream;
+  out_stream = rl_outstream;
+
+  /* Allocate data structures. */
+  if (!rl_line_buffer)
+    rl_line_buffer = xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
+
+  /* Initialize the terminal interface. */
+  init_terminal_io ((char *)NULL);
+
+#if !defined (__GO32__)
+  /* Bind tty characters to readline functions. */
+  readline_default_bindings ();
+#endif /* !__GO32__ */
+
+  /* Initialize the function names. */
+  rl_initialize_funmap ();
+
+  /* Check for LC_CTYPE and use its value to decide the defaults for
+     8-bit character input and output. */
+  t = getenv ("LC_CTYPE");
+  if (t && (strcmp (t, "iso-8859-1") == 0 || strcmp (t, "iso_8859_1") == 0 ||
+  	    strcmp (t, "ISO-8859-1") == 0))
+    {
+      _rl_meta_flag = 1;
+      _rl_convert_meta_chars_to_ascii = 0;
+      _rl_output_meta_chars = 1;
+    }
+      
+  /* Read in the init file. */
+  rl_read_init_file ((char *)NULL);
+
+  /* XXX */
+  if (_rl_horizontal_scroll_mode && term_xn)
+    {
+      screenwidth--;
+      screenchars -= screenheight;
+    }
+
+  /* Override the effect of any `set keymap' assignments in the
+     inputrc file. */
+  rl_set_keymap_from_edit_mode ();
+
+  /* Try to bind a common arrow key prefix, if not already bound. */
+  bind_arrow_keys ();
+
+  /* If the completion parser's default word break characters haven't
+     been set yet, then do so now. */
+  if (rl_completer_word_break_characters == (char *)NULL)
+    rl_completer_word_break_characters = rl_basic_word_break_characters;
+}
+
+/* If this system allows us to look at the values of the regular
+   input editing characters, then bind them to their readline
+   equivalents, iff the characters are not bound to keymaps. */
+static void
+readline_default_bindings ()
+{
+  rltty_set_default_bindings (_rl_keymap);
+}
+
+static void
+bind_arrow_keys_internal ()
+{
+  Function *f;
+
+  f = rl_function_of_keyseq ("\033[A", _rl_keymap, (int *)NULL);
+  if (!f || f == rl_do_lowercase_version)
+    {
+      _rl_bind_if_unbound ("\033[A", rl_get_previous_history);
+      _rl_bind_if_unbound ("\033[B", rl_get_next_history);
+      _rl_bind_if_unbound ("\033[C", rl_forward);
+      _rl_bind_if_unbound ("\033[D", rl_backward);
+    }
+
+  f = rl_function_of_keyseq ("\033OA", _rl_keymap, (int *)NULL);
+  if (!f || f == rl_do_lowercase_version)
+    {
+      _rl_bind_if_unbound ("\033OA", rl_get_previous_history);
+      _rl_bind_if_unbound ("\033OB", rl_get_next_history);
+      _rl_bind_if_unbound ("\033OC", rl_forward);
+      _rl_bind_if_unbound ("\033OD", rl_backward);
+    }
+}
+
+/* Try and bind the common arrow key prefix after giving termcap and
+   the inputrc file a chance to bind them and create `real' keymaps
+   for the arrow key prefix. */
+static void
+bind_arrow_keys ()
+{
+  Keymap xkeymap;
+
+  xkeymap = _rl_keymap;
+
+  _rl_keymap = emacs_standard_keymap;
+  bind_arrow_keys_internal ();
+
+#if defined (VI_MODE)
+  _rl_keymap = vi_movement_keymap;
+  bind_arrow_keys_internal ();
+#endif
+
+  _rl_keymap = xkeymap;
+}
+
+
+/* **************************************************************** */
+/*								    */
+/*			Numeric Arguments			    */
+/*								    */
+/* **************************************************************** */
+
+/* Handle C-u style numeric args, as well as M--, and M-digits. */
+static int
+rl_digit_loop ()
+{
+  int key, c;
+
+  while (1)
+    {
+      rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
+      key = c = rl_read_key ();
+
+      if (_rl_keymap[c].type == ISFUNC &&
+	  _rl_keymap[c].function == rl_universal_argument)
+	{
+	  rl_numeric_arg *= 4;
+	  continue;
+	}
+      c = UNMETA (c);
+      if (digit_p (c))
+	{
+	  if (rl_explicit_arg)
+	    rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
+	  else
+	    rl_numeric_arg = (c - '0');
+	  rl_explicit_arg = 1;
+	}
+      else
+	{
+	  if (c == '-' && !rl_explicit_arg)
+	    {
+	      rl_numeric_arg = 1;
+	      rl_arg_sign = -1;
+	    }
+	  else
+	    {
+	      rl_clear_message ();
+	      return (_rl_dispatch (key, _rl_keymap));
+	    }
+	}
+    }
+  return 0;
+}
+
+/* Add the current digit to the argument in progress. */
+rl_digit_argument (ignore, key)
+     int ignore, key;
+{
+  rl_pending_input = key;
+  return (rl_digit_loop ());
+}
+
+/* What to do when you abort reading an argument. */
+rl_discard_argument ()
+{
+  ding ();
+  rl_clear_message ();
+  rl_init_argument ();
+  return 0;
+}
+
+/* Create a default argument. */
+rl_init_argument ()
+{
+  rl_numeric_arg = rl_arg_sign = 1;
+  rl_explicit_arg = 0;
+  return 0;
+}
+
+/* C-u, universal argument.  Multiply the current argument by 4.
+   Read a key.  If the key has nothing to do with arguments, then
+   dispatch on it.  If the key is the abort character then abort. */
+rl_universal_argument ()
+{
+  rl_numeric_arg *= 4;
+  return (rl_digit_loop ());
+}
+
+/* **************************************************************** */
+/*								    */
+/*			Terminal and Termcap			    */
+/*								    */
+/* **************************************************************** */
+
+static char *term_buffer = (char *)NULL;
+static char *term_string_buffer = (char *)NULL;
+
+static int tcap_initialized = 0;
+
+/* Non-zero means this terminal can't really do anything. */
+int dumb_term = 0;
+/* On Solaris2, sys/types.h #includes sys/reg.h, which #defines PC.
+   Unfortunately, PC is a global variable used by the termcap library. */
+#undef PC
+
+#if !defined (__linux__)
+/* If this causes problems, add back the `extern'. */
+/*extern*/ char PC, *BC, *UP;
+#endif /* __linux__ */
+
+/* Some strings to control terminal actions.  These are output by tputs (). */
+char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace;
+char *term_pc;
+
+/* Non-zero if we determine that the terminal can do character insertion. */
+int terminal_can_insert = 0;
+
+/* How to insert characters. */
+char *term_im, *term_ei, *term_ic, *term_ip, *term_IC;
+
+/* How to delete characters. */
+char *term_dc, *term_DC;
+
+#if defined (HACK_TERMCAP_MOTION)
+char *term_forward_char;
+#endif  /* HACK_TERMCAP_MOTION */
+
+/* How to go up a line. */
+char *term_up;
+
+/* A visible bell, if the terminal can be made to flash the screen. */
+char *visible_bell;
+
+/* Non-zero means that this terminal has a meta key. */
+int term_has_meta;
+
+/* The string to write to turn on the meta key, if this term has one. */
+char *term_mm;
+
+/* The string to write to turn off the meta key, if this term has one. */
+char *term_mo;
+
+/* The key sequences output by the arrow keys, if this terminal has any. */
+char *term_ku, *term_kd, *term_kr, *term_kl;
+
+/* How to initialize and reset the arrow keys, if this terminal has any. */
+char *term_ks, *term_ke;
+
+/* Re-initialize the terminal considering that the TERM/TERMCAP variable
+   has changed. */
+rl_reset_terminal (terminal_name)
+     char *terminal_name;
+{
+  init_terminal_io (terminal_name);
+  return 0;
+}
+
+/* Set readline's idea of the screen size.  TTY is a file descriptor open
+   to the terminal.  If IGNORE_ENV is true, we do not pay attention to the
+   values of $LINES and $COLUMNS.  The tests for TERM_STRING_BUFFER being
+   non-null serve to check whether or not we have initialized termcap. */
+void
+_rl_set_screen_size (tty, ignore_env)
+     int tty, ignore_env;
+{
+#if defined (TIOCGWINSZ)
+  struct winsize window_size;
+#endif /* TIOCGWINSZ */
+
+#if defined (TIOCGWINSZ)
+  if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
+    {
+      screenwidth = (int) window_size.ws_col;
+      screenheight = (int) window_size.ws_row;
+    }
+#endif /* TIOCGWINSZ */
+
+  /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
+     is unset. */
+  if (screenwidth <= 0)
+    {
+      char *sw;
+
+      if (!ignore_env && (sw = getenv ("COLUMNS")))
+	screenwidth = atoi (sw);
+
+      if (screenwidth <= 0 && term_string_buffer)
+	screenwidth = tgetnum ("co");
+    }
+
+  /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
+     is unset. */
+  if (screenheight <= 0)
+    {
+      char *sh;
+
+      if (!ignore_env && (sh = getenv ("LINES")))
+	screenheight = atoi (sh);
+
+      if (screenheight <= 0 && term_string_buffer)
+	screenheight = tgetnum ("li");
+    }
+
+  /* If all else fails, default to 80x24 terminal. */
+  if (screenwidth <= 1)
+    screenwidth = 80;
+
+  if (screenheight <= 0)
+    screenheight = 24;
+
+#if defined (SHELL)
+  /* If we're being compiled as part of bash, set the environment
+     variables $LINES and $COLUMNS to new values. */
+  set_lines_and_columns (screenheight, screenwidth);
+#endif
+
+  if (!term_xn)
+    screenwidth--;
+
+  screenchars = screenwidth * screenheight;
+}
+
+struct _tc_string {
+     char *tc_var;
+     char **tc_value;
+};
+
+/* This should be kept sorted, just in case we decide to change the
+   search algorithm to something smarter. */
+static struct _tc_string tc_strings[] =
+{
+  "DC", &term_DC,
+  "IC", &term_IC,
+  "ce", &term_clreol,
+  "cl", &term_clrpag,
+  "cr", &term_cr,
+  "dc", &term_dc,
+  "ei", &term_ei,
+  "ic", &term_ic,
+  "im", &term_im,
+  "kd", &term_kd,
+  "kl", &term_kl,
+  "kr", &term_kr,
+  "ku", &term_ku,
+  "ks", &term_ks,
+  "ke", &term_ke,
+  "le", &term_backspace,
+  "mm", &term_mm,
+  "mo", &term_mo,
+#if defined (HACK_TERMCAP_MOTION)
+  "nd", &term_forward_char,
+#endif
+  "pc", &term_pc,
+  "up", &term_up,
+  "vb", &visible_bell,
+};
+
+#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
+
+/* Read the desired terminal capability strings into BP.  The capabilities
+   are described in the TC_STRINGS table. */
+static void
+get_term_capabilities (bp)
+     char **bp;
+{
+  register int i;
+
+  for (i = 0; i < NUM_TC_STRINGS; i++)
+    *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
+  tcap_initialized = 1;
+}
+
+static int
+init_terminal_io (terminal_name)
+     char *terminal_name;
+{
+#if defined (__GO32__)
+  screenwidth = ScreenCols ();
+  screenheight = ScreenRows ();
+  screenchars = screenwidth * screenheight;
+  term_cr = "\r";
+  term_im = term_ei = term_ic = term_IC = (char *)NULL;
+  term_up = term_dc = term_DC = visible_bell = (char *)NULL;
+
+  /* Does the __GO32__ have a meta key?  I don't know. */
+  term_has_meta = 0;
+  term_mm = term_mo = (char *)NULL;
+
+  /* It probably has arrow keys, but I don't know what they are. */
+  term_ku = term_kd = term_kr = term_kl = (char *)NULL;
+
+#if defined (HACK_TERMCAP_MOTION)
+  term_forward_char = (char *)NULL;
+#endif /* HACK_TERMCAP_MOTION */
+  terminal_can_insert = term_xn = 0;
+  return;
+#else /* !__GO32__ */
+
+  char *term, *buffer;
+  int tty;
+  Keymap xkeymap;
+
+  term = terminal_name ? terminal_name : getenv ("TERM");
+
+  if (!term_string_buffer)
+    term_string_buffer = xmalloc (2048);
+
+  if (!term_buffer)
+    term_buffer = xmalloc (2048);
+
+  buffer = term_string_buffer;
+
+  term_clrpag = term_cr = term_clreol = (char *)NULL;
+
+  if (!term)
+    term = "dumb";
+
+  if (tgetent (term_buffer, term) <= 0)
+    {
+      dumb_term = 1;
+      screenwidth = 79;
+      screenheight = 24;
+      screenchars = 79 * 24;
+      term_cr = "\r";
+      term_im = term_ei = term_ic = term_IC = (char *)NULL;
+      term_up = term_dc = term_DC = visible_bell = (char *)NULL;
+      term_ku = term_kd = term_kl = term_kr = (char *)NULL;
+#if defined (HACK_TERMCAP_MOTION)
+      term_forward_char = (char *)NULL;
+#endif
+      terminal_can_insert = 0;
+      return 0;
+    }
+
+  get_term_capabilities (&buffer);
+
+  /* Set up the variables that the termcap library expects the application
+     to provide. */
+  PC = term_pc ? *term_pc : 0;
+  BC = term_backspace;
+  UP = term_up;
+
+  if (!term_cr)
+    term_cr =  "\r";
+
+  if (rl_instream)
+    tty = fileno (rl_instream);
+  else
+    tty = 0;
+
+  screenwidth = screenheight = 0;
+
+  term_xn = tgetflag ("am") && tgetflag ("xn");
+
+  _rl_set_screen_size (tty, 0);
+
+  /* "An application program can assume that the terminal can do
+      character insertion if *any one of* the capabilities `IC',
+      `im', `ic' or `ip' is provided."  But we can't do anything if
+      only `ip' is provided, so... */
+  terminal_can_insert = (term_IC || term_im || term_ic);
+
+  /* Check to see if this terminal has a meta key and clear the capability
+     variables if there is none. */
+  term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
+  if (!term_has_meta)
+    {
+      term_mm = (char *)NULL;
+      term_mo = (char *)NULL;
+    }
+
+  /* Attempt to find and bind the arrow keys.  Do not override already
+     bound keys in an overzealous attempt, however. */
+  xkeymap = _rl_keymap;
+
+  _rl_keymap = emacs_standard_keymap;
+  _rl_bind_if_unbound (term_ku, rl_get_previous_history);
+  _rl_bind_if_unbound (term_kd, rl_get_next_history);
+  _rl_bind_if_unbound (term_kr, rl_forward);
+  _rl_bind_if_unbound (term_kl, rl_backward);
+
+#if defined (VI_MODE)
+  _rl_keymap = vi_movement_keymap;
+  _rl_bind_if_unbound (term_ku, rl_get_previous_history);
+  _rl_bind_if_unbound (term_kd, rl_get_next_history);
+  _rl_bind_if_unbound (term_kr, rl_forward);
+  _rl_bind_if_unbound (term_kl, rl_backward);
+#endif /* VI_MODE */
+
+  _rl_keymap = xkeymap;
+
+#endif /* !__GO32__ */
+  return 0;
+}
+
+char *
+rl_get_termcap (cap)
+     char *cap;
+{
+  register int i;
+
+  if (tcap_initialized == 0)
+    return ((char *)NULL);
+  for (i = 0; i < NUM_TC_STRINGS; i++)
+    {
+      if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
+        return *(tc_strings[i].tc_value);
+    }
+  return ((char *)NULL);
+}
+
+/* A function for the use of tputs () */
+int
+_rl_output_character_function (c)
+     int c;
+{
+  return putc (c, out_stream);
+}
+
+/* Write COUNT characters from STRING to the output stream. */
+void
+_rl_output_some_chars (string, count)
+     char *string;
+     int count;
+{
+  fwrite (string, 1, count, out_stream);
+}
+
+/* Move the cursor back. */
+backspace (count)
+     int count;
+{
+  register int i;
+
+#if !defined (__GO32__)
+  if (term_backspace)
+    for (i = 0; i < count; i++)
+      tputs (term_backspace, 1, _rl_output_character_function);
+  else
+#endif /* !__GO32__ */
+    for (i = 0; i < count; i++)
+      putc ('\b', out_stream);
+  return 0;
+}
+
+/* Move to the start of the next line. */
+crlf ()
+{
+#if defined (NEW_TTY_DRIVER)
+  tputs (term_cr, 1, _rl_output_character_function);
+#endif /* NEW_TTY_DRIVER */
+  putc ('\n', out_stream);
+  return 0;
+}
+
+rl_tty_status (count, key)
+     int count, key;
+{
+#if defined (TIOCSTAT)
+  ioctl (1, TIOCSTAT, (char *)0);
+  rl_refresh_line ();
+#else
+  ding ();
+#endif
+  return 0;
+}
+
+
+/* **************************************************************** */
+/*								    */
+/*			Utility Functions			    */
+/*								    */
+/* **************************************************************** */
+
+/* Return 0 if C is not a member of the class of characters that belong
+   in words, or 1 if it is. */
+
+int allow_pathname_alphabetic_chars = 0;
+char *pathname_alphabetic_chars = "/-_=~.#$";
+
+int
+alphabetic (c)
+     int c;
+{
+  if (pure_alphabetic (c) || (digit_p (c)))
+    return (1);
+
+  if (allow_pathname_alphabetic_chars)
+    return (strchr (pathname_alphabetic_chars, c) != NULL);
+  else
+    return (0);
+}
+
+/* Ring the terminal bell. */
+int
+ding ()
+{
+  if (readline_echoing_p)
+    {
+#if !defined (__GO32__)
+      switch (_rl_bell_preference)
+        {
+	case NO_BELL:
+	default:
+	  break;
+	case VISIBLE_BELL:
+	  if (visible_bell)
+	    {
+	      tputs (visible_bell, 1, _rl_output_character_function);
+	      break;
+	    }
+	  /* FALLTHROUGH */
+	case AUDIBLE_BELL:
+	  fprintf (stderr, "\007");
+	  fflush (stderr);
+	  break;
+        }
+#else /* __GO32__ */
+      fprintf (stderr, "\007");
+      fflush (stderr);
+#endif /* __GO32__ */
+      return (0);
+    }
+  return (-1);
+}
+
+/* How to abort things. */
+rl_abort (count, key)
+     int count, key;
+{
+  ding ();
+  rl_clear_message ();
+  rl_init_argument ();
+  rl_pending_input = 0;
+
+  defining_kbd_macro = 0;
+  while (executing_macro)
+    pop_executing_macro ();
+
+  rl_last_func = (Function *)NULL;
+  longjmp (readline_top_level, 1);
+}
+
+/* Return a copy of the string between FROM and TO.
+   FROM is inclusive, TO is not. */
+char *
+rl_copy_text (from, to)
+     int from, to;
+{
+  register int length;
+  char *copy;
+
+  /* Fix it if the caller is confused. */
+  if (from > to)
+    {
+      int t = from;
+      from = to;
+      to = t;
+    }
+
+  length = to - from;
+  copy = xmalloc (1 + length);
+  strncpy (copy, the_line + from, length);
+  copy[length] = '\0';
+  return (copy);
+}
+
+/* Increase the size of RL_LINE_BUFFER until it has enough space to hold
+   LEN characters. */
+void
+rl_extend_line_buffer (len)
+     int len;
+{
+  while (len >= rl_line_buffer_len)
+    {
+      rl_line_buffer_len += DEFAULT_BUFFER_SIZE;
+      rl_line_buffer = xrealloc (rl_line_buffer, rl_line_buffer_len);
+    }
+
+  the_line = rl_line_buffer;
+}
+
+
+/* **************************************************************** */
+/*								    */
+/*			Insert and Delete			    */
+/*								    */
+/* **************************************************************** */
+
+/* Insert a string of text into the line at point.  This is the only
+   way that you should do insertion.  rl_insert () calls this
+   function. */
+rl_insert_text (string)
+     char *string;
+{
+  register int i, l = strlen (string);
+
+  if (rl_end + l >= rl_line_buffer_len)
+    rl_extend_line_buffer (rl_end + l);
+
+  for (i = rl_end; i >= rl_point; i--)
+    the_line[i + l] = the_line[i];
+  strncpy (the_line + rl_point, string, l);
+
+  /* Remember how to undo this if we aren't undoing something. */
+  if (!doing_an_undo)
+    {
+      /* If possible and desirable, concatenate the undos. */
+      if ((l == 1) &&
+	  rl_undo_list &&
+	  (rl_undo_list->what == UNDO_INSERT) &&
+	  (rl_undo_list->end == rl_point) &&
+	  (rl_undo_list->end - rl_undo_list->start < 20))
+	rl_undo_list->end++;
+      else
+	rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
+    }
+  rl_point += l;
+  rl_end += l;
+  the_line[rl_end] = '\0';
+  return l;
+}
+
+/* Delete the string between FROM and TO.  FROM is
+   inclusive, TO is not. */
+rl_delete_text (from, to)
+     int from, to;
+{
+  register char *text;
+  register int diff, i;
+
+  /* Fix it if the caller is confused. */
+  if (from > to)
+    {
+      int t = from;
+      from = to;
+      to = t;
+    }
+
+  if (to > rl_end)
+    to = rl_end;
+
+  text = rl_copy_text (from, to);
+
+  /* Some versions of strncpy() can't handle overlapping arguments. */
+  diff = to - from;
+  for (i = from; i < rl_end - diff; i++)
+    the_line[i] = the_line[i + diff];
+
+  /* Remember how to undo this delete. */
+  if (!doing_an_undo)
+    rl_add_undo (UNDO_DELETE, from, to, text);
+  else
+    free (text);
+
+  rl_end -= diff;
+  the_line[rl_end] = '\0';
+  return (diff);
+}
+
+
+/* **************************************************************** */
+/*								    */
+/*			Readline character functions		    */
+/*								    */
+/* **************************************************************** */
+
+/* This is not a gap editor, just a stupid line input routine.  No hair
+   is involved in writing any of the functions, and none should be. */
+
+/* Note that:
+
+   rl_end is the place in the string that we would place '\0';
+   i.e., it is always safe to place '\0' there.
+
+   rl_point is the place in the string where the cursor is.  Sometimes
+   this is the same as rl_end.
+
+   Any command that is called interactively receives two arguments.
+   The first is a count: the numeric arg pased to this command.
+   The second is the key which invoked this command.
+*/
+
+
+/* **************************************************************** */
+/*								    */
+/*			Movement Commands			    */
+/*								    */
+/* **************************************************************** */
+
+/* Note that if you `optimize' the display for these functions, you cannot
+   use said functions in other functions which do not do optimizing display.
+   I.e., you will have to update the data base for rl_redisplay, and you
+   might as well let rl_redisplay do that job. */
+
+/* Move forward COUNT characters. */
+rl_forward (count, key)
+     int count, key;
+{
+  if (count < 0)
+    rl_backward (-count);
+  else if (count > 0)
+    {
+      int end = rl_point + count;
+#if defined (VI_MODE)
+      int lend = rl_end - (rl_editing_mode == vi_mode);
+#else
+      int lend = rl_end;
+#endif
+
+      if (end > lend)
+	{
+	  rl_point = lend;
+	  ding ();
+	}
+      else
+	rl_point = end;
+    }
+  return 0;
+}
+
+/* Move backward COUNT characters. */
+rl_backward (count, key)
+     int count, key;
+{
+  if (count < 0)
+    rl_forward (-count);
+  else if (count > 0)
+    {
+      if (rl_point < count)
+	{
+	  rl_point = 0;
+	  ding ();
+	}
+      else
+        rl_point -= count;
+    }
+  return 0;
+}
+
+/* Move to the beginning of the line. */
+rl_beg_of_line (count, key)
+     int count, key;
+{
+  rl_point = 0;
+  return 0;
+}
+
+/* Move to the end of the line. */
+rl_end_of_line (count, key)
+     int count, key;
+{
+  rl_point = rl_end;
+  return 0;
+}
+
+/* Move forward a word.  We do what Emacs does. */
+rl_forward_word (count, key)
+     int count, key;
+{
+  int c;
+
+  if (count < 0)
+    {
+      rl_backward_word (-count);
+      return 0;
+    }
+
+  while (count)
+    {
+      if (rl_point == rl_end)
+	return 0;
+
+      /* If we are not in a word, move forward until we are in one.
+	 Then, move forward until we hit a non-alphabetic character. */
+      c = the_line[rl_point];
+      if (!alphabetic (c))
+	{
+	  while (++rl_point < rl_end)
+	    {
+	      c = the_line[rl_point];
+	      if (alphabetic (c))
+		break;
+	    }
+	}
+      if (rl_point == rl_end)
+	return 0;
+      while (++rl_point < rl_end)
+	{
+	  c = the_line[rl_point];
+	  if (!alphabetic (c))
+	    break;
+	}
+      --count;
+    }
+  return 0;
+}
+
+/* Move backward a word.  We do what Emacs does. */
+rl_backward_word (count, key)
+     int count, key;
+{
+  int c;
+
+  if (count < 0)
+    {
+      rl_forward_word (-count);
+      return 0;
+    }
+
+  while (count)
+    {
+      if (!rl_point)
+	return 0;
+
+      /* Like rl_forward_word (), except that we look at the characters
+	 just before point. */
+
+      c = the_line[rl_point - 1];
+      if (!alphabetic (c))
+	{
+	  while (--rl_point)
+	    {
+	      c = the_line[rl_point - 1];
+	      if (alphabetic (c))
+		break;
+	    }
+	}
+
+      while (rl_point)
+	{
+	  c = the_line[rl_point - 1];
+	  if (!alphabetic (c))
+	    break;
+	  else
+	    --rl_point;
+	}
+      --count;
+    }
+  return 0;
+}
+
+/* Clear the current line.  Numeric argument to C-l does this. */
+rl_refresh_line ()
+{
+  int curr_line, nleft;
+
+  /* Find out whether or not there might be invisible characters in the
+     editing buffer. */
+  if (rl_display_prompt == rl_prompt)
+    nleft = _rl_last_c_pos - screenwidth - rl_visible_prompt_length;
+  else
+    nleft = _rl_last_c_pos - screenwidth;
+
+  if (nleft > 0)
+    curr_line = 1 + nleft / screenwidth;
+  else
+    curr_line = 0;
+
+  _rl_move_vert (curr_line);
+  _rl_move_cursor_relative (0, the_line);   /* XXX is this right */
+
+#if defined (__GO32__)
+  {
+    int row, col, width, row_start;
+
+    ScreenGetCursor (&row, &col);
+    width = ScreenCols ();
+    row_start = ScreenPrimary + (row * width);
+    memset (row_start + col, 0, (width - col) * 2);
+  }
+#else /* !__GO32__ */
+  if (term_clreol)
+    tputs (term_clreol, 1, _rl_output_character_function);
+#endif /* !__GO32__ */
+
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+/* C-l typed to a line without quoting clears the screen, and then reprints
+   the prompt and the current input line.  Given a numeric arg, redraw only
+   the current line. */
+rl_clear_screen (count, key)
+     int count, key;
+{
+  if (rl_explicit_arg)
+    {
+      rl_refresh_line ();
+      return 0;
+    }
+
+#if !defined (__GO32__)
+  if (term_clrpag)
+    tputs (term_clrpag, 1, _rl_output_character_function);
+  else
+#endif /* !__GO32__ */
+    crlf ();
+
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+rl_arrow_keys (count, c)
+     int count, c;
+{
+  int ch;
+
+  ch = rl_read_key ();
+
+  switch (to_upper (ch))
+    {
+    case 'A':
+      rl_get_previous_history (count);
+      break;
+
+    case 'B':
+      rl_get_next_history (count);
+      break;
+
+    case 'C':
+      rl_forward (count);
+      break;
+
+    case 'D':
+      rl_backward (count);
+      break;
+
+    default:
+      ding ();
+    }
+  return 0;
+}
+
+
+/* **************************************************************** */
+/*								    */
+/*			Text commands				    */
+/*								    */
+/* **************************************************************** */
+
+/* Insert the character C at the current location, moving point forward. */
+rl_insert (count, c)
+     int count, c;
+{
+  register int i;
+  char *string;
+
+  if (count <= 0)
+    return 0;
+
+  /* If we can optimize, then do it.  But don't let people crash
+     readline because of extra large arguments. */
+  if (count > 1 && count < 1024)
+    {
+      string = xmalloc (1 + count);
+
+      for (i = 0; i < count; i++)
+	string[i] = c;
+
+      string[i] = '\0';
+      rl_insert_text (string);
+      free (string);
+
+      return 0;
+    }
+
+  if (count > 1024)
+    {
+      int decreaser;
+      char str[1024+1];
+
+      for (i = 0; i < 1024; i++)
+	str[i] = c;
+
+      while (count)
+	{
+	  decreaser = (count > 1024 ? 1024 : count);
+	  str[decreaser] = '\0';
+	  rl_insert_text (str);
+	  count -= decreaser;
+	}
+
+      return 0;
+    }
+
+  /* We are inserting a single character.
+     If there is pending input, then make a string of all of the
+     pending characters that are bound to rl_insert, and insert
+     them all. */
+  if (any_typein)
+    {
+      int key = 0, t;
+
+      i = 0;
+      string = xmalloc (ibuffer_len + 1);
+      string[i++] = c;
+
+      while ((t = rl_get_char (&key)) &&
+	     (_rl_keymap[key].type == ISFUNC &&
+	      _rl_keymap[key].function == rl_insert))
+	string[i++] = key;
+
+      if (t)
+	rl_unget_char (key);
+
+      string[i] = '\0';
+      rl_insert_text (string);
+      free (string);
+    }
+  else
+    {
+      /* Inserting a single character. */
+      char str[2];
+
+      str[1] = '\0';
+      str[0] = c;
+      rl_insert_text (str);
+    }
+  return 0;
+}
+
+/* Insert the next typed character verbatim. */
+rl_quoted_insert (count, key)
+     int count, key;
+{
+  int c;
+
+  c = rl_read_key ();
+  return (rl_insert (count, c));  
+}
+
+/* Insert a tab character. */
+rl_tab_insert (count, key)
+     int count, key;
+{
+  return (rl_insert (count, '\t'));
+}
+
+/* What to do when a NEWLINE is pressed.  We accept the whole line.
+   KEY is the key that invoked this command.  I guess it could have
+   meaning in the future. */
+rl_newline (count, key)
+     int count, key;
+{
+  rl_done = 1;
+
+#if defined (VI_MODE)
+  _rl_vi_done_inserting ();
+  _rl_vi_reset_last ();
+
+#endif /* VI_MODE */
+
+  if (readline_echoing_p)
+    _rl_update_final ();
+  return 0;
+}
+
+rl_clean_up_for_exit ()
+{
+  if (readline_echoing_p)
+    {
+      _rl_move_vert (_rl_vis_botlin);
+      _rl_vis_botlin = 0;
+      fflush (out_stream);
+      rl_restart_output ();
+    }
+  return 0;
+}
+
+/* What to do for some uppercase characters, like meta characters,
+   and some characters appearing in emacs_ctlx_keymap.  This function
+   is just a stub, you bind keys to it and the code in _rl_dispatch ()
+   is special cased. */
+rl_do_lowercase_version (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  return 0;
+}
+
+/* Rubout the character behind point. */
+rl_rubout (count, key)
+     int count, key;
+{
+  if (count < 0)
+    {
+      rl_delete (-count);
+      return 0;
+    }
+
+  if (!rl_point)
+    {
+      ding ();
+      return -1;
+    }
+
+  if (count > 1 || rl_explicit_arg)
+    {
+      int orig_point = rl_point;
+      rl_backward (count);
+      rl_kill_text (orig_point, rl_point);
+    }
+  else
+    {
+      int c = the_line[--rl_point];
+      rl_delete_text (rl_point, rl_point + 1);
+
+      if (rl_point == rl_end && isprint (c) && _rl_last_c_pos)
+	{
+	  int l;
+	  l = rl_character_len (c, rl_point);
+	  _rl_erase_at_end_of_line (l);
+	}
+    }
+  return 0;
+}
+
+/* Delete the character under the cursor.  Given a numeric argument,
+   kill that many characters instead. */
+rl_delete (count, invoking_key)
+     int count, invoking_key;
+{
+  if (count < 0)
+    {
+      return (rl_rubout (-count));
+    }
+
+  if (rl_point == rl_end)
+    {
+      ding ();
+      return -1;
+    }
+
+  if (count > 1 || rl_explicit_arg)
+    {
+      int orig_point = rl_point;
+      rl_forward (count);
+      rl_kill_text (orig_point, rl_point);
+      rl_point = orig_point;
+      return 0;
+    }
+  else
+    return (rl_delete_text (rl_point, rl_point + 1));
+  
+}
+
+/* Delete all spaces and tabs around point. */
+rl_delete_horizontal_space (count, ignore)
+     int count, ignore;
+{
+  int start = rl_point;
+
+  while (rl_point && whitespace (the_line[rl_point - 1]))
+    rl_point--;
+
+  start = rl_point;
+
+  while (rl_point < rl_end && whitespace (the_line[rl_point]))
+    rl_point++;
+
+  if (start != rl_point)
+    {
+      rl_delete_text (start, rl_point);
+      rl_point = start;
+    }
+  return 0;
+}
+
+
+/* **************************************************************** */
+/*								    */
+/*			Kill commands				    */
+/*								    */
+/* **************************************************************** */
+
+/* The next two functions mimic unix line editing behaviour, except they
+   save the deleted text on the kill ring.  This is safer than not saving
+   it, and since we have a ring, nobody should get screwed. */
+
+/* This does what C-w does in Unix.  We can't prevent people from
+   using behaviour that they expect. */
+rl_unix_word_rubout (count, key)
+     int count, key;
+{
+  if (!rl_point)
+    ding ();
+  else
+    {
+      int orig_point = rl_point;
+      if (count <= 0)
+	count = 1;
+
+      while (count--)
+	{
+	  while (rl_point && whitespace (the_line[rl_point - 1]))
+	    rl_point--;
+
+	  while (rl_point && !whitespace (the_line[rl_point - 1]))
+	    rl_point--;
+	}
+
+      rl_kill_text (orig_point, rl_point);
+    }
+  return 0;
+}
+
+/* Here is C-u doing what Unix does.  You don't *have* to use these
+   key-bindings.  We have a choice of killing the entire line, or
+   killing from where we are to the start of the line.  We choose the
+   latter, because if you are a Unix weenie, then you haven't backspaced
+   into the line at all, and if you aren't, then you know what you are
+   doing. */
+rl_unix_line_discard (count, key)
+     int count, key;
+{
+  if (!rl_point)
+    ding ();
+  else
+    {
+      rl_kill_text (rl_point, 0);
+      rl_point = 0;
+    }
+  return 0;
+}
+
+
+/* **************************************************************** */
+/*								    */
+/*			Commands For Typos			    */
+/*								    */
+/* **************************************************************** */
+
+/* Random and interesting things in here.  */
+
+/* **************************************************************** */
+/*								    */
+/*			Changing Case				    */
+/*								    */
+/* **************************************************************** */
+
+/* The three kinds of things that we know how to do. */
+#define UpCase 1
+#define DownCase 2
+#define CapCase 3
+
+static int rl_change_case ();
+
+/* Uppercase the word at point. */
+rl_upcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, UpCase));
+}
+
+/* Lowercase the word at point. */
+rl_downcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, DownCase));
+}
+
+/* Upcase the first letter, downcase the rest. */
+rl_capitalize_word (count, key)
+     int count, key;
+{
+ return (rl_change_case (count, CapCase));
+}
+
+/* The meaty function.
+   Change the case of COUNT words, performing OP on them.
+   OP is one of UpCase, DownCase, or CapCase.
+   If a negative argument is given, leave point where it started,
+   otherwise, leave it where it moves to. */
+static int
+rl_change_case (count, op)
+     int count, op;
+{
+  register int start = rl_point, end;
+  int state = 0;
+
+  rl_forward_word (count);
+  end = rl_point;
+
+  if (count < 0)
+    {
+      int temp = start;
+      start = end;
+      end = temp;
+    }
+
+  /* We are going to modify some text, so let's prepare to undo it. */
+  rl_modifying (start, end);
+
+  for (; start < end; start++)
+    {
+      switch (op)
+	{
+	case UpCase:
+	  the_line[start] = to_upper (the_line[start]);
+	  break;
+
+	case DownCase:
+	  the_line[start] = to_lower (the_line[start]);
+	  break;
+
+	case CapCase:
+	  if (state == 0)
+	    {
+	      the_line[start] = to_upper (the_line[start]);
+	      state = 1;
+	    }
+	  else
+	    {
+	      the_line[start] = to_lower (the_line[start]);
+	    }
+	  if (!pure_alphabetic (the_line[start]))
+	    state = 0;
+	  break;
+
+	default:
+	  ding ();
+	  return -1;
+	}
+    }
+  rl_point = end;
+  return 0;
+}
+
+/* **************************************************************** */
+/*								    */
+/*			Transposition				    */
+/*								    */
+/* **************************************************************** */
+
+/* Transpose the words at point. */
+rl_transpose_words (count, key)
+     int count, key;
+{
+  char *word1, *word2;
+  int w1_beg, w1_end, w2_beg, w2_end;
+  int orig_point = rl_point;
+
+  if (!count)
+    return 0;
+
+  /* Find the two words. */
+  rl_forward_word (count);
+  w2_end = rl_point;
+  rl_backward_word (1);
+  w2_beg = rl_point;
+  rl_backward_word (count);
+  w1_beg = rl_point;
+  rl_forward_word (1);
+  w1_end = rl_point;
+
+  /* Do some check to make sure that there really are two words. */
+  if ((w1_beg == w2_beg) || (w2_beg < w1_end))
+    {
+      ding ();
+      rl_point = orig_point;
+      return -1;
+    }
+
+  /* Get the text of the words. */
+  word1 = rl_copy_text (w1_beg, w1_end);
+  word2 = rl_copy_text (w2_beg, w2_end);
+
+  /* We are about to do many insertions and deletions.  Remember them
+     as one operation. */
+  rl_begin_undo_group ();
+
+  /* Do the stuff at word2 first, so that we don't have to worry
+     about word1 moving. */
+  rl_point = w2_beg;
+  rl_delete_text (w2_beg, w2_end);
+  rl_insert_text (word1);
+
+  rl_point = w1_beg;
+  rl_delete_text (w1_beg, w1_end);
+  rl_insert_text (word2);
+
+  /* This is exactly correct since the text before this point has not
+     changed in length. */
+  rl_point = w2_end;
+
+  /* I think that does it. */
+  rl_end_undo_group ();
+  free (word1);
+  free (word2);
+
+  return 0;
+}
+
+/* Transpose the characters at point.  If point is at the end of the line,
+   then transpose the characters before point. */
+rl_transpose_chars (count, key)
+     int count, key;
+{
+  char dummy[2];
+
+  if (!count)
+    return 0;
+
+  if (!rl_point || rl_end < 2)
+    {
+      ding ();
+      return -1;
+    }
+
+  rl_begin_undo_group ();
+
+  if (rl_point == rl_end)
+    {
+      --rl_point;
+      count = 1;
+    }
+  rl_point--;
+
+  dummy[0] = the_line[rl_point];
+  dummy[1] = '\0';
+
+  rl_delete_text (rl_point, rl_point + 1);
+
+  rl_point += count;
+  if (rl_point > rl_end)
+    rl_point = rl_end;
+  else if (rl_point < 0)
+    rl_point = 0;
+  rl_insert_text (dummy);
+
+  rl_end_undo_group ();
+  return 0;
+}
+
+/* **************************************************************** */
+/*								    */
+/*			Undo, and Undoing			    */
+/*								    */
+/* **************************************************************** */
+
+/* The current undo list for THE_LINE. */
+UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
+
+/* Remember how to undo something.  Concatenate some undos if that
+   seems right. */
+void
+rl_add_undo (what, start, end, text)
+     enum undo_code what;
+     int start, end;
+     char *text;
+{
+  UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
+  temp->what = what;
+  temp->start = start;
+  temp->end = end;
+  temp->text = text;
+  temp->next = rl_undo_list;
+  rl_undo_list = temp;
+}
+
+/* Free the existing undo list. */
+void
+free_undo_list ()
+{
+  while (rl_undo_list)
+    {
+      UNDO_LIST *release = rl_undo_list;
+      rl_undo_list = rl_undo_list->next;
+
+      if (release->what == UNDO_DELETE)
+	free (release->text);
+
+      free (release);
+    }
+  rl_undo_list = (UNDO_LIST *)NULL;
+}
+
+/* Undo the next thing in the list.  Return 0 if there
+   is nothing to undo, or non-zero if there was. */
+int
+rl_do_undo ()
+{
+  UNDO_LIST *release;
+  int waiting_for_begin = 0;
+
+undo_thing:
+  if (!rl_undo_list)
+    return (0);
+
+  doing_an_undo = 1;
+
+  switch (rl_undo_list->what) {
+
+    /* Undoing deletes means inserting some text. */
+  case UNDO_DELETE:
+    rl_point = rl_undo_list->start;
+    rl_insert_text (rl_undo_list->text);
+    free (rl_undo_list->text);
+    break;
+
+    /* Undoing inserts means deleting some text. */
+  case UNDO_INSERT:
+    rl_delete_text (rl_undo_list->start, rl_undo_list->end);
+    rl_point = rl_undo_list->start;
+    break;
+
+    /* Undoing an END means undoing everything 'til we get to
+       a BEGIN. */
+  case UNDO_END:
+    waiting_for_begin++;
+    break;
+
+    /* Undoing a BEGIN means that we are done with this group. */
+  case UNDO_BEGIN:
+    if (waiting_for_begin)
+      waiting_for_begin--;
+    else
+      ding ();
+    break;
+  }
+
+  doing_an_undo = 0;
+
+  release = rl_undo_list;
+  rl_undo_list = rl_undo_list->next;
+  free (release);
+
+  if (waiting_for_begin)
+    goto undo_thing;
+
+  return (1);
+}
+
+/* Begin a group.  Subsequent undos are undone as an atomic operation. */
+int
+rl_begin_undo_group ()
+{
+  rl_add_undo (UNDO_BEGIN, 0, 0, 0);
+  return 0;
+}
+
+/* End an undo group started with rl_begin_undo_group (). */
+int
+rl_end_undo_group ()
+{
+  rl_add_undo (UNDO_END, 0, 0, 0);
+  return 0;
+}
+
+/* Save an undo entry for the text from START to END. */
+rl_modifying (start, end)
+     int start, end;
+{
+  if (start > end)
+    {
+      int t = start;
+      start = end;
+      end = t;
+    }
+
+  if (start != end)
+    {
+      char *temp = rl_copy_text (start, end);
+      rl_begin_undo_group ();
+      rl_add_undo (UNDO_DELETE, start, end, temp);
+      rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
+      rl_end_undo_group ();
+    }
+  return 0;
+}
+
+/* Revert the current line to its previous state. */
+int
+rl_revert_line (count, key)
+     int count, key;
+{
+  if (!rl_undo_list)
+    ding ();
+  else
+    {
+      while (rl_undo_list)
+	rl_do_undo ();
+    }
+  return 0;
+}
+
+/* Do some undoing of things that were done. */
+int
+rl_undo_command (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return 0;	/* Nothing to do. */
+
+  while (count)
+    {
+      if (rl_do_undo ())
+	count--;
+      else
+	{
+	  ding ();
+	  break;
+	}
+    }
+  return 0;
+}
+
+/* **************************************************************** */
+/*								    */
+/*			History Utilities			    */
+/*								    */
+/* **************************************************************** */
+
+/* We already have a history library, and that is what we use to control
+   the history features of readline.  However, this is our local interface
+   to the history mechanism. */
+
+/* While we are editing the history, this is the saved
+   version of the original line. */
+HIST_ENTRY *saved_line_for_history = (HIST_ENTRY *)NULL;
+
+/* Set the history pointer back to the last entry in the history. */
+static void
+start_using_history ()
+{
+  using_history ();
+  if (saved_line_for_history)
+    _rl_free_history_entry (saved_line_for_history);
+
+  saved_line_for_history = (HIST_ENTRY *)NULL;
+}
+
+/* Free the contents (and containing structure) of a HIST_ENTRY. */
+void
+_rl_free_history_entry (entry)
+     HIST_ENTRY *entry;
+{
+  if (!entry)
+    return;
+  if (entry->line)
+    free (entry->line);
+  free (entry);
+}
+
+/* Perhaps put back the current line if it has changed. */
+maybe_replace_line ()
+{
+  HIST_ENTRY *temp = current_history ();
+
+  /* If the current line has changed, save the changes. */
+  if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
+    {
+      temp = replace_history_entry (where_history (), the_line, rl_undo_list);
+      free (temp->line);
+      free (temp);
+    }
+  return 0;
+}
+
+/* Put back the saved_line_for_history if there is one. */
+maybe_unsave_line ()
+{
+  if (saved_line_for_history)
+    {
+      int line_len;
+
+      line_len = strlen (saved_line_for_history->line);
+
+      if (line_len >= rl_line_buffer_len)
+	rl_extend_line_buffer (line_len);
+
+      strcpy (the_line, saved_line_for_history->line);
+      rl_undo_list = (UNDO_LIST *)saved_line_for_history->data;
+      _rl_free_history_entry (saved_line_for_history);
+      saved_line_for_history = (HIST_ENTRY *)NULL;
+      rl_end = rl_point = strlen (the_line);
+    }
+  else
+    ding ();
+  return 0;
+}
+
+/* Save the current line in saved_line_for_history. */
+maybe_save_line ()
+{
+  if (!saved_line_for_history)
+    {
+      saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+      saved_line_for_history->line = savestring (the_line);
+      saved_line_for_history->data = (char *)rl_undo_list;
+    }
+  return 0;
+}
+
+/* **************************************************************** */
+/*								    */
+/*			History Commands			    */
+/*								    */
+/* **************************************************************** */
+
+/* Meta-< goes to the start of the history. */
+rl_beginning_of_history (count, key)
+     int count, key;
+{
+  return (rl_get_previous_history (1 + where_history ()));
+}
+
+/* Meta-> goes to the end of the history.  (The current line). */
+rl_end_of_history (count, key)
+     int count, key;
+{
+  maybe_replace_line ();
+  using_history ();
+  maybe_unsave_line ();
+  return 0;
+}
+
+/* Move down to the next history line. */
+rl_get_next_history (count, key)
+     int count, key;
+{
+  HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
+
+  if (count < 0)
+    return (rl_get_previous_history (-count));
+
+  if (!count)
+    return 0;
+
+  maybe_replace_line ();
+
+  while (count)
+    {
+      temp = next_history ();
+      if (!temp)
+	break;
+      --count;
+    }
+
+  if (!temp)
+    maybe_unsave_line ();
+  else
+    {
+      int line_len;
+
+      line_len = strlen (temp->line);
+
+      if (line_len >= rl_line_buffer_len)
+	rl_extend_line_buffer (line_len);
+
+      strcpy (the_line, temp->line);
+      rl_undo_list = (UNDO_LIST *)temp->data;
+      rl_end = rl_point = strlen (the_line);
+#if defined (VI_MODE)
+      if (rl_editing_mode == vi_mode)
+	rl_point = 0;
+#endif /* VI_MODE */
+    }
+  return 0;
+}
+
+/* Get the previous item out of our interactive history, making it the current
+   line.  If there is no previous history, just ding. */
+rl_get_previous_history (count, key)
+     int count, key;
+{
+  HIST_ENTRY *old_temp = (HIST_ENTRY *)NULL;
+  HIST_ENTRY *temp = (HIST_ENTRY *)NULL;
+
+  if (count < 0)
+    return (rl_get_next_history (-count));
+
+  if (!count)
+    return 0;
+
+  /* If we don't have a line saved, then save this one. */
+  maybe_save_line ();
+
+  /* If the current line has changed, save the changes. */
+  maybe_replace_line ();
+
+  while (count)
+    {
+      temp = previous_history ();
+      if (!temp)
+	break;
+      else
+	old_temp = temp;
+      --count;
+    }
+
+  /* If there was a large argument, and we moved back to the start of the
+     history, that is not an error.  So use the last value found. */
+  if (!temp && old_temp)
+    temp = old_temp;
+
+  if (!temp)
+    ding ();
+  else
+    {
+      int line_len;
+
+      line_len = strlen (temp->line);
+
+      if (line_len >= rl_line_buffer_len)
+	rl_extend_line_buffer (line_len);
+
+      strcpy (the_line, temp->line);
+      rl_undo_list = (UNDO_LIST *)temp->data;
+      rl_end = rl_point = line_len;
+
+#if defined (VI_MODE)
+      if (rl_editing_mode == vi_mode)
+	rl_point = 0;
+#endif /* VI_MODE */
+    }
+  return 0;
+}
+
+/* Make C be the next command to be executed. */
+rl_execute_next (c)
+     int c;
+{
+  rl_pending_input = c;
+  return 0;
+}
+
+/* **************************************************************** */
+/*								    */
+/*		   The Mark and the Region.			    */
+/*								    */
+/* **************************************************************** */
+
+/* Set the mark at POSITION. */
+rl_set_mark (position)
+     int position;
+{
+  if (position > rl_end)
+    return -1;
+
+  rl_mark = position;
+  return 0;
+}
+
+/* Exchange the position of mark and point. */
+rl_exchange_mark_and_point (count, key)
+     int count, key;
+{
+  if (rl_mark > rl_end)
+    rl_mark = -1;
+
+  if (rl_mark == -1)
+    {
+      ding ();
+      return -1;
+    }
+  else
+    {
+      int temp = rl_point;
+
+      rl_point = rl_mark;
+      rl_mark = temp;
+    }
+  return 0;
+}
+
+
+/* **************************************************************** */
+/*								    */
+/*			Killing Mechanism			    */
+/*								    */
+/* **************************************************************** */
+
+/* What we assume for a max number of kills. */
+#define DEFAULT_MAX_KILLS 10
+
+/* The real variable to look at to find out when to flush kills. */
+int rl_max_kills =  DEFAULT_MAX_KILLS;
+
+/* Where to store killed text. */
+char **rl_kill_ring = (char **)NULL;
+
+/* Where we are in the kill ring. */
+int rl_kill_index = 0;
+
+/* How many slots we have in the kill ring. */
+int rl_kill_ring_length = 0;
+
+/* How to say that you only want to save a certain amount
+   of kill material. */
+rl_set_retained_kills (num)
+     int num;
+{
+  return 0;
+}
+
+/* The way to kill something.  This appends or prepends to the last
+   kill, if the last command was a kill command.  if FROM is less
+   than TO, then the text is appended, otherwise prepended.  If the
+   last command was not a kill command, then a new slot is made for
+   this kill. */
+rl_kill_text (from, to)
+     int from, to;
+{
+  int slot;
+  char *text;
+
+  /* Is there anything to kill? */
+  if (from == to)
+    {
+      last_command_was_kill++;
+      return 0;
+    }
+
+  text = rl_copy_text (from, to);
+
+  /* Delete the copied text from the line. */
+  rl_delete_text (from, to);
+
+  /* First, find the slot to work with. */
+  if (!last_command_was_kill)
+    {
+      /* Get a new slot.  */
+      if (!rl_kill_ring)
+	{
+	  /* If we don't have any defined, then make one. */
+	  rl_kill_ring = (char **)
+	    xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *));
+	  rl_kill_ring[slot = 0] = (char *)NULL;
+	}
+      else
+	{
+	  /* We have to add a new slot on the end, unless we have
+	     exceeded the max limit for remembering kills. */
+	  slot = rl_kill_ring_length;
+	  if (slot == rl_max_kills)
+	    {
+	      register int i;
+	      free (rl_kill_ring[0]);
+	      for (i = 0; i < slot; i++)
+		rl_kill_ring[i] = rl_kill_ring[i + 1];
+	    }
+	  else
+	    {
+	      slot = rl_kill_ring_length += 1;
+	      rl_kill_ring = (char **)xrealloc (rl_kill_ring, slot * sizeof (char *));
+	    }
+	  rl_kill_ring[--slot] = (char *)NULL;
+	}
+    }
+  else
+    slot = rl_kill_ring_length - 1;
+
+  /* If the last command was a kill, prepend or append. */
+  if (last_command_was_kill && rl_editing_mode != vi_mode)
+    {
+      char *old = rl_kill_ring[slot];
+      char *new = xmalloc (1 + strlen (old) + strlen (text));
+
+      if (from < to)
+	{
+	  strcpy (new, old);
+	  strcat (new, text);
+	}
+      else
+	{
+	  strcpy (new, text);
+	  strcat (new, old);
+	}
+      free (old);
+      free (text);
+      rl_kill_ring[slot] = new;
+    }
+  else
+    {
+      rl_kill_ring[slot] = text;
+    }
+  rl_kill_index = slot;
+  last_command_was_kill++;
+  return 0;
+}
+
+/* Now REMEMBER!  In order to do prepending or appending correctly, kill
+   commands always make rl_point's original position be the FROM argument,
+   and rl_point's extent be the TO argument. */
+
+/* **************************************************************** */
+/*								    */
+/*			Killing Commands			    */
+/*								    */
+/* **************************************************************** */
+
+/* Delete the word at point, saving the text in the kill ring. */
+rl_kill_word (count, key)
+     int count, key;
+{
+  int orig_point = rl_point;
+
+  if (count < 0)
+    return (rl_backward_kill_word (-count));
+  else
+    {
+      rl_forward_word (count);
+
+      if (rl_point != orig_point)
+	rl_kill_text (orig_point, rl_point);
+
+      rl_point = orig_point;
+    }
+  return 0;
+}
+
+/* Rubout the word before point, placing it on the kill ring. */
+rl_backward_kill_word (count, ignore)
+     int count, ignore;
+{
+  int orig_point = rl_point;
+
+  if (count < 0)
+    return (rl_kill_word (-count));
+  else
+    {
+      rl_backward_word (count);
+
+      if (rl_point != orig_point)
+	rl_kill_text (orig_point, rl_point);
+    }
+  return 0;
+}
+
+/* Kill from here to the end of the line.  If DIRECTION is negative, kill
+   back to the line start instead. */
+rl_kill_line (direction, ignore)
+     int direction, ignore;
+{
+  int orig_point = rl_point;
+
+  if (direction < 0)
+    return (rl_backward_kill_line (1));
+  else
+    {
+      rl_end_of_line (1, ignore);
+      if (orig_point != rl_point)
+	rl_kill_text (orig_point, rl_point);
+      rl_point = orig_point;
+    }
+  return 0;
+}
+
+/* Kill backwards to the start of the line.  If DIRECTION is negative, kill
+   forwards to the line end instead. */
+rl_backward_kill_line (direction, ignore)
+     int direction, ignore;
+{
+  int orig_point = rl_point;
+
+  if (direction < 0)
+    return (rl_kill_line (1));
+  else
+    {
+      if (!rl_point)
+	ding ();
+      else
+	{
+	  rl_beg_of_line (1, ignore);
+	  rl_kill_text (orig_point, rl_point);
+	}
+    }
+  return 0;
+}
+
+/* Kill the whole line, no matter where point is. */
+rl_kill_full_line (count, ignore)
+     int count, ignore;
+{
+  rl_begin_undo_group ();
+  rl_point = 0;
+  rl_kill_text (rl_point, rl_end);
+  rl_end_undo_group ();
+  return 0;
+}
+
+/* Yank back the last killed text.  This ignores arguments. */
+rl_yank (count, ignore)
+     int count, ignore;
+{
+  if (!rl_kill_ring)
+    {
+      rl_abort (count, ignore);
+      return -1;
+    }
+
+  rl_set_mark (rl_point);
+  rl_insert_text (rl_kill_ring[rl_kill_index]);
+  return 0;
+}
+
+/* If the last command was yank, or yank_pop, and the text just
+   before point is identical to the current kill item, then
+   delete that text from the line, rotate the index down, and
+   yank back some other text. */
+rl_yank_pop (count, key)
+     int count, key;
+{
+  int l;
+
+  if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) ||
+      !rl_kill_ring)
+    {
+      rl_abort (1, key);
+      return -1;
+    }
+
+  l = strlen (rl_kill_ring[rl_kill_index]);
+  if (((rl_point - l) >= 0) &&
+      (strncmp (the_line + (rl_point - l),
+		rl_kill_ring[rl_kill_index], l) == 0))
+    {
+      rl_delete_text ((rl_point - l), rl_point);
+      rl_point -= l;
+      rl_kill_index--;
+      if (rl_kill_index < 0)
+	rl_kill_index = rl_kill_ring_length - 1;
+      rl_yank (1, 0);
+      return 0;
+    }
+  else
+    {
+      rl_abort (1, key);
+      return -1;
+    }
+}
+
+/* Yank the COUNTth argument from the previous history line. */
+rl_yank_nth_arg (count, ignore)
+     int count, ignore;
+{
+  register HIST_ENTRY *entry = previous_history ();
+  char *arg;
+
+  if (entry)
+    next_history ();
+  else
+    {
+      ding ();
+      return -1;
+    }
+
+  arg = history_arg_extract (count, count, entry->line);
+  if (!arg || !*arg)
+    {
+      ding ();
+      return -1;
+    }
+
+  rl_begin_undo_group ();
+
+#if defined (VI_MODE)
+  /* Vi mode always inserts a space before yanking the argument, and it
+     inserts it right *after* rl_point. */
+  if (rl_editing_mode == vi_mode)
+    {
+      rl_vi_append_mode ();
+      rl_insert_text (" ");
+    }
+#endif /* VI_MODE */
+
+  rl_insert_text (arg);
+  free (arg);
+
+  rl_end_undo_group ();
+  return 0;
+}
+
+/* Yank the last argument from the previous history line.  This `knows'
+   how rl_yank_nth_arg treats a count of `$'.  With an argument, this
+   behaves the same as rl_yank_nth_arg. */
+int
+rl_yank_last_arg (count, key)
+     int count, key;
+{
+  if (rl_explicit_arg)
+    return (rl_yank_nth_arg (count, key));
+  else
+    return (rl_yank_nth_arg ('$', key));
+}
+
+/* How to toggle back and forth between editing modes. */
+rl_vi_editing_mode (count, key)
+     int count, key;
+{
+#if defined (VI_MODE)
+  rl_editing_mode = vi_mode;
+  rl_vi_insertion_mode ();
+  return 0;
+#endif /* VI_MODE */
+}
+
+rl_emacs_editing_mode (count, key)
+     int count, key;
+{
+  rl_editing_mode = emacs_mode;
+  _rl_keymap = emacs_standard_keymap;
+  return 0;
+}
+
+
+/* **************************************************************** */
+/*								    */
+/*			USG (System V) Support			    */
+/*								    */
+/* **************************************************************** */
+
+int
+rl_getc (stream)
+     FILE *stream;
+{
+  int result;
+  unsigned char c;
+
+#if defined (__GO32__)
+  if (isatty (0))
+    return (getkey () & 0x7F);
+#endif /* __GO32__ */
+
+  while (1)
+    {
+      result = read (fileno (stream), &c, sizeof (unsigned char));
+
+      if (result == sizeof (unsigned char))
+	return (c);
+
+      /* If zero characters are returned, then the file that we are
+	 reading from is empty!  Return EOF in that case. */
+      if (result == 0)
+	return (EOF);
+
+#if defined (EWOULDBLOCK)
+      if (errno == EWOULDBLOCK)
+	{
+	  int flags;
+
+	  if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0)
+	    return (EOF);
+	  if (flags & O_NDELAY)
+	    {
+	      flags &= ~O_NDELAY;
+	      fcntl (fileno (stream), F_SETFL, flags);
+	      continue;
+	    }
+	  continue;
+	}
+#endif /* EWOULDBLOCK */
+
+#if defined (_POSIX_VERSION) && defined (EAGAIN) && defined (O_NONBLOCK)
+      if (errno == EAGAIN)
+	{
+	  int flags;
+
+	  if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0)
+	    return (EOF);
+	  if (flags & O_NONBLOCK)
+	    {
+	      flags &= ~O_NONBLOCK;
+	      fcntl (fileno (stream), F_SETFL, flags);
+	      continue;
+	    }
+	}
+#endif /* _POSIX_VERSION && EAGAIN && O_NONBLOCK */
+
+#if !defined (__GO32__)
+      /* If the error that we received was SIGINT, then try again,
+	 this is simply an interrupted system call to read ().
+	 Otherwise, some error ocurred, also signifying EOF. */
+      if (errno != EINTR)
+	return (EOF);
+#endif /* !__GO32__ */
+    }
+}
+
+#if !defined (SHELL)
+#ifdef savestring
+#undef savestring
+#endif
+/* Backwards compatibilty, now that savestring has been removed from
+   all `public' readline header files. */
+char *
+savestring (s)
+     char *s;
+{
+  return ((char *)strcpy (xmalloc (1 + (int)strlen (s)), (s)));
+}
+#endif
+
+/* Function equivalents for the macros defined in chartypes.h. */
+#undef uppercase_p
+int
+uppercase_p (c)
+     int c;
+{
+  return (isupper (c));
+}
+
+#undef lowercase_p
+int
+lowercase_p (c)
+     int c;
+{
+  return (islower (c));
+}
+
+#undef pure_alphabetic
+int
+pure_alphabetic (c)
+     int c;
+{
+  return (isupper (c) || islower (c));
+}
+
+#undef digit_p
+int
+digit_p (c)
+     int c;
+{
+  return (isdigit (c));
+}
+
+#undef to_lower
+int
+to_lower (c)
+     int c;
+{
+  return (isupper (c) ? tolower (c) : c);
+}
+
+#undef to_upper
+int
+to_upper (c)
+     int c;
+{
+  return (islower (c) ? toupper (c) : c);
+}
+
+#undef digit_value
+int
+digit_value (c)
+     int c;
+{
+  return (isdigit (c) ? c - '0' : c);
+}
+
+#if defined (STATIC_MALLOC)
+
+/* **************************************************************** */
+/*								    */
+/*			xmalloc and xrealloc ()		     	    */
+/*								    */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
+
+
+/* **************************************************************** */
+/*								    */
+/*			Testing Readline			    */
+/*								    */
+/* **************************************************************** */
+
+#if defined (TEST)
+
+main ()
+{
+  HIST_ENTRY **history_list ();
+  char *temp = (char *)NULL;
+  char *prompt = "readline% ";
+  int done = 0;
+
+  while (!done)
+    {
+      temp = readline (prompt);
+
+      /* Test for EOF. */
+      if (!temp)
+	exit (1);
+
+      /* If there is anything on the line, print it and remember it. */
+      if (*temp)
+	{
+	  fprintf (stderr, "%s\r\n", temp);
+	  add_history (temp);
+	}
+
+      /* Check for `command' that we handle. */
+      if (strcmp (temp, "quit") == 0)
+	done = 1;
+
+      if (strcmp (temp, "list") == 0)
+	{
+	  HIST_ENTRY **list = history_list ();
+	  register int i;
+	  if (list)
+	    {
+	      for (i = 0; list[i]; i++)
+		{
+		  fprintf (stderr, "%d: %s\r\n", i, list[i]->line);
+		  free (list[i]->line);
+		}
+	      free (list);
+	    }
+	}
+      free (temp);
+    }
+}
+
+#endif /* TEST */
+
+
+/*
+ * Local variables:
+ * compile-command: "gcc -g -traditional -I. -I.. -DTEST -o readline readline.c keymaps.o funmap.o history.o -ltermcap"
+ * end:
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/readline.h	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,289 @@
+/* Readline.h -- the names of functions callable from within readline. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_READLINE_H_)
+#define _READLINE_H_
+
+#if defined (READLINE_LIBRARY)
+#  include "keymaps.h"
+#  include "tilde.h"
+#else
+#  include <readline/keymaps.h>
+#  include <readline/tilde.h>
+#endif
+
+/* The functions for manipulating the text of the line within readline.
+Most of these functions are bound to keys by default. */
+extern int
+  rl_tilde_expand (),
+  rl_beg_of_line (), rl_backward (), rl_delete (), rl_end_of_line (),
+  rl_forward (), ding (), rl_backward (), rl_newline (), rl_kill_line (),
+  rl_clear_screen (), rl_get_next_history (), rl_get_previous_history (),
+  rl_quoted_insert (), rl_reverse_search_history (), rl_transpose_chars (),
+  rl_unix_line_discard (), rl_quoted_insert (), rl_unix_word_rubout (),
+  rl_yank (), rl_rubout (), rl_backward_word (), rl_kill_word (),
+  rl_forward_word (), rl_tab_insert (), rl_yank_pop (), rl_yank_nth_arg (),
+  rl_backward_kill_word (), rl_backward_kill_line (), rl_transpose_words (),
+  rl_complete (), rl_possible_completions (), rl_insert_completions (),
+  rl_do_lowercase_version (), rl_kill_full_line (),
+  rl_digit_argument (), rl_universal_argument (), rl_abort (),
+  rl_undo_command (), rl_revert_line (), rl_beginning_of_history (),
+  rl_end_of_history (), rl_forward_search_history (), rl_insert (),
+  rl_upcase_word (), rl_downcase_word (), rl_capitalize_word (),
+  rl_restart_output (), rl_re_read_init_file (), rl_dump_functions (),
+  rl_delete_horizontal_space (), rl_history_search_forward (),
+  rl_history_search_backward (), rl_tty_status (), rl_yank_last_arg ();
+
+/* `Public' utility functions. */
+extern int rl_insert_text (), rl_delete_text (), rl_kill_text ();
+extern int rl_complete_internal ();
+extern int rl_expand_prompt ();
+extern int rl_initialize ();
+extern int rl_set_signals (), rl_clear_signals ();
+extern int rl_init_argument (), rl_digit_argument ();
+extern int rl_read_key (), rl_getc (), rl_stuff_char ();
+extern int maybe_save_line (), maybe_unsave_line (), maybe_replace_line ();
+extern int rl_modifying ();
+
+extern int rl_begin_undo_group (), rl_end_undo_group ();
+extern void rl_add_undo (), free_undo_list ();
+extern int rl_do_undo ();
+
+/* Not available unless readline is compiled -DPAREN_MATCHING. */
+extern int rl_insert_close ();
+
+/* These are *both* defined even when VI_MODE is not. */
+extern int rl_vi_editing_mode (), rl_emacs_editing_mode ();
+
+/* Non incremental history searching. */
+extern int
+  rl_noninc_forward_search (), rl_noninc_reverse_search (),
+  rl_noninc_forward_search_again (), rl_noninc_reverse_search_again ();
+
+/* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */
+extern int rl_vi_check (), rl_vi_textmod_command ();
+extern int
+  rl_vi_redo (), rl_vi_tilde_expand (),
+  rl_vi_movement_mode (), rl_vi_insertion_mode (), rl_vi_arg_digit (),
+  rl_vi_prev_word (), rl_vi_next_word (), rl_vi_char_search (),
+  rl_vi_eof_maybe (), rl_vi_append_mode (), rl_vi_put (),
+  rl_vi_append_eol (), rl_vi_insert_beg (), rl_vi_delete (), rl_vi_comment (),
+  rl_vi_first_print (), rl_vi_fword (), rl_vi_fWord (), rl_vi_bword (),
+  rl_vi_bWord (), rl_vi_eword (), rl_vi_eWord (), rl_vi_end_word (),
+  rl_vi_change_case (), rl_vi_match (), rl_vi_bracktype (),
+  rl_vi_change_char (), rl_vi_yank_arg (), rl_vi_search (),
+  rl_vi_search_again (),  rl_vi_subst (), rl_vi_overstrike (),
+  rl_vi_overstrike_delete (), rl_vi_replace(), rl_vi_column (),
+  rl_vi_delete_to (), rl_vi_change_to (), rl_vi_yank_to (),
+  rl_vi_complete (), rl_vi_fetch_history ();
+
+/* Keyboard macro commands. */
+extern int rl_start_kbd_macro (), rl_end_kbd_macro ();
+extern int rl_call_last_kbd_macro ();
+
+extern int rl_arrow_keys(), rl_refresh_line ();
+
+/* Maintaining the state of undo.  We remember individual deletes and inserts
+   on a chain of things to do. */
+
+/* The actions that undo knows how to undo.  Notice that UNDO_DELETE means
+   to insert some text, and UNDO_INSERT means to delete some text.   I.e.,
+   the code tells undo what to undo, not how to undo it. */
+enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END };
+
+/* What an element of THE_UNDO_LIST looks like. */
+typedef struct undo_list {
+  struct undo_list *next;
+  int start, end;		/* Where the change took place. */
+  char *text;			/* The text to insert, if undoing a delete. */
+  enum undo_code what;		/* Delete, Insert, Begin, End. */
+} UNDO_LIST;
+
+/* The current undo list for RL_LINE_BUFFER. */
+extern UNDO_LIST *rl_undo_list;
+
+/* The data structure for mapping textual names to code addresses. */
+typedef struct {
+  char *name;
+  Function *function;
+} FUNMAP;
+
+extern FUNMAP **funmap;
+
+/* **************************************************************** */
+/*								    */
+/*			Well Published Variables		    */
+/*								    */
+/* **************************************************************** */
+
+/* The name of the calling program.  You should initialize this to
+   whatever was in argv[0].  It is used when parsing conditionals. */
+extern char *rl_readline_name;
+
+/* The line buffer that is in use. */
+extern char *rl_line_buffer;
+
+/* The location of point, and end. */
+extern int rl_point, rl_end;
+
+/* The name of the terminal to use. */
+extern char *rl_terminal_name;
+
+/* The input and output streams. */
+extern FILE *rl_instream, *rl_outstream;
+
+/* The basic list of characters that signal a break between words for the
+   completer routine.  The initial contents of this variable is what
+   breaks words in the shell, i.e. "n\"\\'`@$>". */
+extern char *rl_basic_word_break_characters;
+
+/* The list of characters that signal a break between words for
+   rl_complete_internal.  The default list is the contents of
+   rl_basic_word_break_characters.  */
+extern char *rl_completer_word_break_characters;
+
+/* List of characters which can be used to quote a substring of the line.
+   Completion occurs on the entire substring, and within the substring   
+   rl_completer_word_break_characters are treated as any other character,
+   unless they also appear within this list. */
+extern char *rl_completer_quote_characters;
+
+/* List of characters that are word break characters, but should be left
+   in TEXT when it is passed to the completion function.  The shell uses
+   this to help determine what kind of completing to do. */
+extern char *rl_special_prefixes;
+
+/* Pointer to the generator function for completion_matches ().
+   NULL means to use filename_entry_function (), the default filename
+   completer. */
+extern Function *rl_completion_entry_function;
+
+/* If rl_ignore_some_completions_function is non-NULL it is the address
+   of a function to call after all of the possible matches have been
+   generated, but before the actual completion is done to the input line.
+   The function is called with one argument; a NULL terminated array
+   of (char *).  If your function removes any of the elements, they
+   must be free()'ed. */
+extern Function *rl_ignore_some_completions_function;
+
+/* Pointer to alternative function to create matches.
+   Function is called with TEXT, START, and END.
+   START and END are indices in RL_LINE_BUFFER saying what the boundaries
+   of TEXT are.
+   If this function exists and returns NULL then call the value of
+   rl_completion_entry_function to try to match, otherwise use the
+   array of strings returned. */
+extern CPPFunction *rl_attempted_completion_function;
+
+/* If non-zero, then this is the address of a function to call just
+   before readline_internal () prints the first prompt. */
+extern Function *rl_startup_hook;
+
+/* If non-zero, then this is the address of a function to call when
+   completing on a directory name.  The function is called with
+   the address of a string (the current directory name) as an arg. */
+extern Function *rl_directory_completion_hook;
+
+/* Backwards compatibility with previous versions of readline. */
+#define rl_symbolic_link_hook rl_directory_completion_hook
+
+/* The address of a function to call periodically while Readline is
+   awaiting character input, or NULL, for no event handling. */
+extern Function *rl_event_hook;
+
+/* Non-zero means that modified history lines are preceded
+   with an asterisk. */
+extern int rl_show_star;
+
+/* Non-zero means that the results of the matches are to be treated
+   as filenames.  This is ALWAYS zero on entry, and can only be changed
+   within a completion entry finder function. */
+extern int rl_filename_completion_desired;
+
+/* Non-zero means that the results of the matches are to be quoted using
+   double quotes (or an application-specific quoting mechanism) if the
+   filename contains any characters in rl_word_break_chars.  This is
+   ALWAYS non-zero on entry, and can only be changed within a completion
+   entry finder function. */
+extern int rl_filename_quoting_desired;
+
+/* Non-zero means to suppress normal filename completion after the
+   user-specified completion function has been called. */
+extern int rl_attempted_completion_over;
+
+/* **************************************************************** */
+/*								    */
+/*			Well Published Functions		    */
+/*								    */
+/* **************************************************************** */
+
+/* Read a line of input.  Prompt with PROMPT.  A NULL PROMPT means none. */
+extern char *readline ();
+
+/* These functions are from complete.c. */
+/* Return an array of strings which are the result of repeatadly calling
+   FUNC with TEXT. */
+extern char **completion_matches ();
+extern char *username_completion_function ();
+extern char *filename_completion_function ();
+
+/* These functions are from bind.c. */
+/* rl_add_defun (char *name, Function *function, int key)
+   Add NAME to the list of named functions.  Make FUNCTION
+   be the function that gets called.
+   If KEY is not -1, then bind it. */
+extern int rl_add_defun ();
+extern int rl_bind_key (), rl_bind_key_in_map ();
+extern int rl_unbind_key (), rl_unbind_key_in_map ();
+extern int rl_set_key ();
+extern int rl_macro_bind (), rl_generic_bind (), rl_variable_bind ();
+extern int rl_translate_keyseq ();
+extern Function *rl_named_function (), *rl_function_of_keyseq ();
+extern int rl_parse_and_bind ();
+extern Keymap rl_get_keymap (), rl_get_keymap_by_name ();
+extern void rl_set_keymap ();
+extern char **rl_invoking_keyseqs (), **rl_invoking_keyseqs_in_map ();
+extern void rl_function_dumper ();
+extern int rl_read_init_file ();
+
+/* Functions in funmap.c */
+extern void rl_list_funmap_names ();
+extern void rl_initialize_funmap ();
+
+/* Functions in display.c */
+extern void rl_redisplay ();
+extern int rl_message (), rl_clear_message ();
+extern int rl_reset_line_state ();
+extern int rl_character_len ();
+extern int rl_show_char ();
+extern int crlf (), rl_on_new_line ();
+extern int rl_forced_update_display ();
+
+/* Definitions available for use by readline clients. */
+#define RL_PROMPT_START_IGNORE	'\001'
+#define RL_PROMPT_END_IGNORE	'\002'
+
+#if !defined (savestring)
+extern char *savestring ();	/* XXX backwards compatibility */
+#endif
+
+#endif /* _READLINE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/rlconf.h	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,57 @@
+/* rlconf.h -- readline configuration definitions */
+
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+
+   This file contains the Readline Library (the Library), a set of
+   routines for providing Emacs style line input to programs that ask
+   for it.
+
+   The Library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   The Library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_RLCONF_H_)
+#define _RLCONF_H_
+
+/* Define this if you want the vi-mode editing available. */
+#define VI_MODE
+
+/* Define this to get an indication of file type when listing completions. */
+#define VISIBLE_STATS
+
+/* If defined, readline shows opening parens and braces when closing
+   paren or brace entered. */
+/* #define PAREN_MATCHING */
+
+/* This definition is needed by readline.c, rltty.c, and signals.c. */
+/* If on, then readline handles signals in a way that doesn't screw. */
+#define HANDLE_SIGNALS
+
+/* Ugly but working hack for binding prefix meta. */
+#define PREFIX_META_HACK
+
+/* The final, last-ditch effort file name for an init file. */
+#define DEFAULT_INPUTRC "~/.inputrc"
+
+/* If defined, expand tabs to spaces. */
+#define DISPLAY_TABS
+
+/* If defined, use the terminal escape sequence to move the cursor forward
+   over a character when updating the line rather than rewriting it. */
+/* #define HACK_TERMCAP_MOTION */
+
+/* The string inserted by the vi-mode `insert comment' command. */
+#define VI_COMMENT_BEGIN_DEFAULT "#"
+
+#endif /* _RLCONF_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/rldefs.h	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,212 @@
+/* rldefs.h -- an attempt to isolate some of the system-specific defines
+   for readline.  This should be included after any files that define
+   system-specific constants like _POSIX_VERSION or USG. */
+
+/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+   This file contains the Readline Library (the Library), a set of
+   routines for providing Emacs style line input to programs that ask
+   for it.
+
+   The Library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   The Library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (_RLDEFS_H)
+#define _RLDEFS_H
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#if !defined (PRAGMA_ALLOCA)
+#  include "memalloc.h"
+#endif
+
+#define NEW_TTY_DRIVER
+#define HAVE_BSD_SIGNALS
+/* #define USE_XON_XOFF */
+
+#if defined (__linux__) || defined (HAVE_TERMCAP_H)
+#  include <termcap.h>
+#endif /* __linux__ || HAVE_TERMCAP_H */
+
+/* Some USG machines have BSD signal handling (sigblock, sigsetmask, etc.) */
+#if defined (USG) && !defined (hpux)
+#  undef HAVE_BSD_SIGNALS
+#endif
+
+/* System V machines use termio. */
+#if !defined (_POSIX_VERSION)
+#  if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || \
+      defined (DGUX) || defined (HAVE_TERMIO_H)
+#    undef NEW_TTY_DRIVER
+#    define TERMIO_TTY_DRIVER
+#    include <termio.h>
+#    if !defined (TCOON)
+#      define TCOON 1
+#    endif
+#  endif /* USG || hpux || Xenix || sgi || DUGX || HAVE_TERMIO_H */
+#endif /* !_POSIX_VERSION */
+
+/* Posix systems use termios and the Posix signal functions. */
+#if defined (_POSIX_VERSION)
+#  if !defined (TERMIOS_MISSING)
+#    undef NEW_TTY_DRIVER
+#    define TERMIOS_TTY_DRIVER
+#    include <termios.h>
+#  endif /* !TERMIOS_MISSING */
+#  define HAVE_POSIX_SIGNALS
+#  if !defined (O_NDELAY)
+#    define O_NDELAY O_NONBLOCK	/* Posix-style non-blocking i/o */
+#  endif /* O_NDELAY */
+#endif /* _POSIX_VERSION */
+
+/* System V.3 machines have the old 4.1 BSD `reliable' signal interface. */
+#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
+#  if defined (USGr3) && !defined (XENIX_22)
+#    if !defined (HAVE_USG_SIGHOLD)
+#      define HAVE_USG_SIGHOLD
+#    endif /* !HAVE_USG_SIGHOLD */
+#  endif /* USGr3 && !XENIX_22 */
+#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
+
+/* Other (BSD) machines use sgtty. */
+#if defined (NEW_TTY_DRIVER)
+#  include <sgtty.h>
+#endif
+
+#if !defined (SHELL) && (defined (_POSIX_VERSION) || defined (USGr3))
+#  if !defined (HAVE_DIRENT_H)
+#    define HAVE_DIRENT_H
+#  endif /* !HAVE_DIRENT_H */
+#endif /* !SHELL && (_POSIX_VERSION || USGr3) */
+
+#if defined (HAVE_DIRENT_H)
+#  include <dirent.h>
+#  define D_NAMLEN(d) strlen ((d)->d_name)
+#else /* !HAVE_DIRENT_H */
+#  define D_NAMLEN(d) ((d)->d_namlen)
+#  if defined (USG)
+#    if defined (Xenix)
+#      include <sys/ndir.h>
+#    else /* !Xenix (but USG...) */
+#      include "ndir.h"
+#    endif /* !Xenix */
+#  else /* !USG */
+#    include <sys/dir.h>
+#  endif /* !USG */
+#  if !defined (dirent)
+#    define dirent direct
+#  endif /* !dirent */
+#endif /* !HAVE_DIRENT_H */
+
+#if defined (USG) && defined (TIOCGWINSZ) && !defined (Linux)
+#  if defined (HAVE_SYS_STREAM_H)
+#    include <sys/stream.h>
+#  endif /* HAVE_SYS_STREAM_H */
+#  if defined (HAVE_SYS_PTEM_H)
+#    include <sys/ptem.h>
+#  endif /* HAVE_SYS_PTEM_H */
+#  if defined (HAVE_SYS_PTE_H)
+#    include <sys/pte.h>
+#  endif /* HAVE_SYS_PTE_H */
+#endif /* USG && TIOCGWINSZ && !Linux */
+
+/* Posix macro to check file in statbuf for directory-ness.
+   This requires that <sys/stat.h> be included before this test. */
+#if defined (S_IFDIR) && !defined (S_ISDIR)
+#  define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
+#endif
+
+/* Decide which flavor of the header file describing the C library
+   string functions to include and include it. */
+
+#if defined (USG) || defined (NeXT)
+#  if !defined (HAVE_STRING_H)
+#    define HAVE_STRING_H
+#  endif /* !HAVE_STRING_H */
+#endif /* USG || NeXT */
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+#if defined (HAVE_VARARGS_H)
+#  include <varargs.h>
+#endif /* HAVE_VARARGS_H */
+
+/* This is needed to include support for TIOCGWINSZ and window resizing. */
+#if defined (OSF1) || defined (BSD386) || defined (NetBSD) || \
+    defined (__BSD_4_4__) || defined (FreeBSD) || defined (_386BSD) || \
+    defined (AIX)
+#  define GWINSZ_IN_SYS_IOCTL
+#endif
+
+/* Define _POSIX_VDISABLE if we are not using the `new' tty driver and
+   it is not already defined.  It is used both to determine if a
+   special character is disabled and to disable certain special
+   characters.  Posix systems should set to 0, USG systems to -1. */
+#if !defined (NEW_TTY_DRIVER) && !defined (_POSIX_VDISABLE)
+#  if defined (_SVR4_VDISABLE)
+#    define _POSIX_VDISABLE _SVR4_VDISABLE
+#  else
+#    if defined (_POSIX_VERSION)
+#      define _POSIX_VDISABLE 0
+#    else /* !_POSIX_VERSION */
+#      define _POSIX_VDISABLE -1
+#    endif /* !_POSIX_VERSION */
+#  endif /* !_SVR4_VDISABLE */
+#endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */
+
+
+#if !defined (emacs_mode)
+#  define no_mode -1
+#  define vi_mode 0
+#  define emacs_mode 1
+#endif
+
+/* If you cast map[key].function to type (Keymap) on a Cray,
+   the compiler takes the value of map[key].function and
+   divides it by 4 to convert between pointer types (pointers
+   to functions and pointers to structs are different sizes).
+   This is not what is wanted. */
+#if defined (CRAY)
+#  define FUNCTION_TO_KEYMAP(map, key)	(Keymap)((int)map[key].function)
+#  define KEYMAP_TO_FUNCTION(data)	(Function *)((int)(data))
+#else
+#  define FUNCTION_TO_KEYMAP(map, key)	(Keymap)(map[key].function)
+#  define KEYMAP_TO_FUNCTION(data)	(Function *)(data)
+#endif
+
+#ifndef savestring
+extern char *xmalloc ();
+#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
+#endif
+
+/* Possible values for _rl_bell_preference. */
+#define NO_BELL 0
+#define AUDIBLE_BELL 1
+#define VISIBLE_BELL 2
+
+/* CONFIGURATION SECTION */
+#include "rlconf.h"
+
+#endif /* !_RLDEFS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/rltty.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,705 @@
+/* rltty.c -- functions to prepare and restore the terminal for readline's
+   use. */
+
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include "rldefs.h"
+#include "readline.h"
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+extern int readline_echoing_p;
+extern int _rl_eof_char;
+
+#if defined (__GO32__)
+#  include <sys/pc.h>
+#  undef HANDLE_SIGNALS
+#endif /* __GO32__ */
+
+/* **************************************************************** */
+/*								    */
+/*			   Signal Management			    */
+/*								    */
+/* **************************************************************** */
+
+#if defined (HAVE_POSIX_SIGNALS)
+static sigset_t sigint_set, sigint_oset;
+#else /* !HAVE_POSIX_SIGNALS */
+#  if defined (HAVE_BSD_SIGNALS)
+static int sigint_oldmask;
+#  endif /* HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+static int sigint_blocked = 0;
+
+/* Cause SIGINT to not be delivered until the corresponding call to
+   release_sigint(). */
+static void
+block_sigint ()
+{
+  if (sigint_blocked)
+    return;
+
+#if defined (HAVE_POSIX_SIGNALS)
+  sigemptyset (&sigint_set);
+  sigemptyset (&sigint_oset);
+  sigaddset (&sigint_set, SIGINT);
+  sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
+#else /* !HAVE_POSIX_SIGNALS */
+#  if defined (HAVE_BSD_SIGNALS)
+  sigint_oldmask = sigblock (sigmask (SIGINT));
+#  else /* !HAVE_BSD_SIGNALS */
+#    if defined (HAVE_USG_SIGHOLD)
+  sighold (SIGINT);
+#    endif /* HAVE_USG_SIGHOLD */
+#  endif /* !HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+  sigint_blocked = 1;
+}
+
+/* Allow SIGINT to be delivered. */
+static void
+release_sigint ()
+{
+  if (!sigint_blocked)
+    return;
+
+#if defined (HAVE_POSIX_SIGNALS)
+  sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
+#else
+#  if defined (HAVE_BSD_SIGNALS)
+  sigsetmask (sigint_oldmask);
+#  else /* !HAVE_BSD_SIGNALS */
+#    if defined (HAVE_USG_SIGHOLD)
+  sigrelse (SIGINT);
+#    endif /* HAVE_USG_SIGHOLD */
+#  endif /* !HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+  sigint_blocked = 0;
+}
+
+/* **************************************************************** */
+/*								    */
+/*	 	Controlling the Meta Key and Keypad		    */
+/*								    */
+/* **************************************************************** */
+
+extern int term_has_meta;
+extern char *term_mm;
+extern char *term_mo;
+
+extern char *term_ks;
+extern char *term_ke;
+
+static int
+outchar (c)
+     int c;
+{
+  return putc (c, rl_outstream);
+}
+
+/* Turn on/off the meta key depending on ON. */
+static void
+control_meta_key (on)
+     int on;
+{
+  if (term_has_meta)
+    {
+      if (on && term_mm)
+	tputs (term_mm, 1, outchar);
+      else if (!on && term_mo)
+	tputs (term_mo, 1, outchar);
+    }
+}
+
+#if 0
+static void
+control_keypad (on)
+     int on;
+{
+  if (on && term_ks)
+    tputs (term_ks, 1, outchar);
+  else if (!on && term_ke)
+    tputs (term_ke, 1, outchar);
+}
+#endif
+
+/* **************************************************************** */
+/*								    */
+/*		      Saving and Restoring the TTY	    	    */
+/*								    */
+/* **************************************************************** */
+
+/* Non-zero means that the terminal is in a prepped state. */
+static int terminal_prepped = 0;
+
+/* If non-zero, means that this process has called tcflow(fd, TCOOFF)
+   and output is suspended. */
+#if defined (__ksr1__)
+static int ksrflow = 0;
+#endif
+#if defined (NEW_TTY_DRIVER)
+
+/* Values for the `flags' field of a struct bsdtty.  This tells which
+   elements of the struct bsdtty have been fetched from the system and
+   are valid. */
+#define SGTTY_SET	0x01
+#define LFLAG_SET	0x02
+#define TCHARS_SET	0x04
+#define LTCHARS_SET	0x08
+
+struct bsdtty {
+  struct sgttyb sgttyb;	/* Basic BSD tty driver information. */
+  int lflag;		/* Local mode flags, like LPASS8. */
+#if defined (TIOCGETC)
+  struct tchars tchars;	/* Terminal special characters, including ^S and ^Q. */
+#endif
+#if defined (TIOCGLTC)
+  struct ltchars ltchars; /* 4.2 BSD editing characters */
+#endif
+  int flags;		/* Bitmap saying which parts of the struct are valid. */
+};
+
+#define TIOTYPE struct bsdtty
+
+static TIOTYPE otio;
+
+static int
+get_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+#if !defined (SHELL) && defined (TIOCGWINSZ)
+  struct winsize w;
+
+  if (ioctl (tty, TIOCGWINSZ, &w) == 0)
+      (void) ioctl (tty, TIOCSWINSZ, &w);
+#endif
+
+  tiop->flags = tiop->lflag = 0;
+
+  ioctl (tty, TIOCGETP, &(tiop->sgttyb));
+  tiop->flags |= SGTTY_SET;
+
+#if defined (TIOCLGET)
+  ioctl (tty, TIOCLGET, &(tiop->lflag));
+  tiop->flags |= LFLAG_SET;
+#endif
+
+#if defined (TIOCGETC)
+  ioctl (tty, TIOCGETC, &(tiop->tchars));
+  tiop->flags |= TCHARS_SET;
+#endif
+
+#if defined (TIOCGLTC)
+  ioctl (tty, TIOCGLTC, &(tiop->ltchars));
+  tiop->flags |= LTCHARS_SET;
+#endif
+
+  return 0;
+}
+
+set_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+  if (tiop->flags & SGTTY_SET)
+    {
+      ioctl (tty, TIOCSETN, &(tiop->sgttyb));
+      tiop->flags &= ~SGTTY_SET;
+    }
+  readline_echoing_p = 1;
+
+#if defined (TIOCLSET)
+  if (tiop->flags & LFLAG_SET)
+    {
+      ioctl (tty, TIOCLSET, &(tiop->lflag));
+      tiop->flags &= ~LFLAG_SET;
+    }
+#endif
+
+#if defined (TIOCSETC)
+  if (tiop->flags & TCHARS_SET)
+    {
+      ioctl (tty, TIOCSETC, &(tiop->tchars));
+      tiop->flags &= ~TCHARS_SET;
+    }
+#endif
+
+#if defined (TIOCSLTC)
+  if (tiop->flags & LTCHARS_SET)
+    {
+      ioctl (tty, TIOCSLTC, &(tiop->ltchars));
+      tiop->flags &= ~LTCHARS_SET;
+    }
+#endif
+
+  return 0;
+}
+
+static void
+prepare_terminal_settings (meta_flag, otio, tiop)
+     int meta_flag;
+     TIOTYPE otio, *tiop;
+{
+#if !defined (__GO32__)
+  readline_echoing_p = (otio.sgttyb.sg_flags & ECHO);
+
+  /* Copy the original settings to the structure we're going to use for
+     our settings. */
+  tiop->sgttyb = otio.sgttyb;
+  tiop->lflag = otio.lflag;
+#if defined (TIOCGETC)
+  tiop->tchars = otio.tchars;
+#endif
+#if defined (TIOCGLTC)
+  tiop->ltchars = otio.ltchars;
+#endif
+  tiop->flags = otio.flags;
+
+  /* First, the basic settings to put us into character-at-a-time, no-echo
+     input mode. */
+  tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD);
+  tiop->sgttyb.sg_flags |= CBREAK;
+
+  /* If this terminal doesn't care how the 8th bit is used, then we can
+     use it for the meta-key.  If only one of even or odd parity is
+     specified, then the terminal is using parity, and we cannot. */
+#if !defined (ANYP)
+#  define ANYP (EVENP | ODDP)
+#endif
+  if (((otio.sgttyb.sg_flags & ANYP) == ANYP) ||
+      ((otio.sgttyb.sg_flags & ANYP) == 0))
+    {
+      tiop->sgttyb.sg_flags |= ANYP;
+
+      /* Hack on local mode flags if we can. */
+#if defined (TIOCLGET)
+#  if defined (LPASS8)
+      tiop->lflag |= LPASS8;
+#  endif /* LPASS8 */
+#endif /* TIOCLGET */
+    }
+
+#if defined (TIOCGETC)
+#  if defined (USE_XON_XOFF)
+  /* Get rid of terminal output start and stop characters. */
+  tiop->tchars.t_stopc = -1; /* C-s */
+  tiop->tchars.t_startc = -1; /* C-q */
+
+  /* If there is an XON character, bind it to restart the output. */
+  if (otio.tchars.t_startc != -1)
+    rl_bind_key (otio.tchars.t_startc, rl_restart_output);
+#  endif /* USE_XON_XOFF */
+
+  /* If there is an EOF char, bind _rl_eof_char to it. */
+  if (otio.tchars.t_eofc != -1)
+    _rl_eof_char = otio.tchars.t_eofc;
+
+#  if defined (NO_KILL_INTR)
+  /* Get rid of terminal-generated SIGQUIT and SIGINT. */
+  tiop->tchars.t_quitc = -1; /* C-\ */
+  tiop->tchars.t_intrc = -1; /* C-c */
+#  endif /* NO_KILL_INTR */
+#endif /* TIOCGETC */
+
+#if defined (TIOCGLTC)
+  /* Make the interrupt keys go away.  Just enough to make people happy. */
+  tiop->ltchars.t_dsuspc = -1;	/* C-y */
+  tiop->ltchars.t_lnextc = -1;	/* C-v */
+#endif /* TIOCGLTC */
+#endif /* !__GO32__ */
+}
+
+#else  /* !defined (NEW_TTY_DRIVER) */
+
+#if !defined (VMIN)
+#  define VMIN VEOF
+#endif
+
+#if !defined (VTIME)
+#  define VTIME VEOL
+#endif
+
+#if defined (TERMIOS_TTY_DRIVER)
+#  define TIOTYPE struct termios
+#  define DRAIN_OUTPUT(fd)	tcdrain (fd)
+#  define GETATTR(tty, tiop)	(tcgetattr (tty, tiop))
+#  define SETATTR(tty, tiop)	(tcsetattr (tty, TCSANOW, tiop))
+#else
+#  define TIOTYPE struct termio
+#  define DRAIN_OUTPUT(fd)
+#  define GETATTR(tty, tiop)	(ioctl (tty, TCGETA, tiop))
+#  define SETATTR(tty, tiop)	(ioctl (tty, TCSETA, tiop))
+#endif /* !TERMIOS_TTY_DRIVER */
+
+static TIOTYPE otio;
+
+#if defined (FLUSHO)
+#  define OUTPUT_BEING_FLUSHED(tp)  (tp->c_lflag & FLUSHO)
+#else
+#  define OUTPUT_BEING_FLUSHED(tp)  0
+#endif
+
+static int
+get_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+  int ioctl_ret;
+#if !defined (SHELL) && defined (TIOCGWINSZ)
+  struct winsize w;
+
+  if (ioctl (tty, TIOCGWINSZ, &w) == 0)
+      (void) ioctl (tty, TIOCSWINSZ, &w);
+#endif
+
+  /* Keep looping if output is being flushed after a ^O (or whatever
+     the flush character is). */
+  while ((ioctl_ret = GETATTR (tty, tiop)) < 0 || OUTPUT_BEING_FLUSHED (tiop))
+    {
+      if (ioctl_ret < 0 && errno != EINTR)
+	return -1;
+      if (OUTPUT_BEING_FLUSHED (tiop))
+        continue;
+      errno = 0;
+    }
+  return 0;
+}
+
+static int
+set_tty_settings (tty, tiop)
+     int tty;
+     TIOTYPE *tiop;
+{
+  while (SETATTR (tty, tiop) < 0)
+    {
+      if (errno != EINTR)
+	return -1;
+      errno = 0;
+    }
+
+#if 0
+
+#if defined (TERMIOS_TTY_DRIVER)
+#  if defined (__ksr1__)
+  if (ksrflow)
+    {
+      ksrflow = 0;
+      tcflow (tty, TCOON);
+    }
+#  else /* !ksr1 */
+  tcflow (tty, TCOON);		/* Simulate a ^Q. */
+#  endif /* !ksr1 */
+#else
+  ioctl (tty, TCXONC, 1);	/* Simulate a ^Q. */
+#endif /* !TERMIOS_TTY_DRIVER */
+
+#endif
+
+  return 0;
+}
+
+static void
+prepare_terminal_settings (meta_flag, otio, tiop)
+     int meta_flag;
+     TIOTYPE otio, *tiop;
+{
+  readline_echoing_p = (otio.c_lflag & ECHO);
+
+  tiop->c_lflag &= ~(ICANON | ECHO);
+
+  if ((unsigned char) otio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
+    _rl_eof_char = otio.c_cc[VEOF];
+
+#if defined (USE_XON_XOFF)
+#if defined (IXANY)
+  tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
+#else
+  /* `strict' Posix systems do not define IXANY. */
+  tiop->c_iflag &= ~(IXON | IXOFF);
+#endif /* IXANY */
+#endif /* USE_XON_XOFF */
+
+  /* Only turn this off if we are using all 8 bits. */
+  if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
+    tiop->c_iflag &= ~(ISTRIP | INPCK);
+
+  /* Make sure we differentiate between CR and NL on input. */
+  tiop->c_iflag &= ~(ICRNL | INLCR);
+
+#if !defined (HANDLE_SIGNALS)
+  tiop->c_lflag &= ~ISIG;
+#else
+  tiop->c_lflag |= ISIG;
+#endif
+
+  tiop->c_cc[VMIN] = 1;
+  tiop->c_cc[VTIME] = 0;
+
+#if defined (FLUSHO)
+  if (OUTPUT_BEING_FLUSHED (tiop))
+    {
+      tiop->c_lflag &= ~FLUSHO;
+      otio.c_lflag &= ~FLUSHO;
+    }
+#endif
+
+  /* Turn off characters that we need on Posix systems with job control,
+     just to be sure.  This includes ^Y and ^V.  This should not really
+     be necessary.  */
+#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE)
+
+#if defined (VLNEXT)
+  tiop->c_cc[VLNEXT] = _POSIX_VDISABLE;
+#endif
+
+#if defined (VDSUSP)
+  tiop->c_cc[VDSUSP] = _POSIX_VDISABLE;
+#endif
+
+#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */
+}
+#endif  /* NEW_TTY_DRIVER */
+
+/* Put the terminal in CBREAK mode so that we can detect key presses. */
+void
+rl_prep_terminal (meta_flag)
+     int meta_flag;
+{
+#if !defined (__GO32__)
+  int tty = fileno (rl_instream);
+  TIOTYPE tio;
+
+  if (terminal_prepped)
+    return;
+
+  /* Try to keep this function from being INTerrupted. */
+  block_sigint ();
+
+  if (get_tty_settings (tty, &tio) < 0)
+    {
+      release_sigint ();
+      return;
+    }
+
+  otio = tio;
+
+  prepare_terminal_settings (meta_flag, otio, &tio);
+
+  if (set_tty_settings (tty, &tio) < 0)
+    {
+      release_sigint ();
+      return;
+    }
+
+  control_meta_key (1);
+#if 0
+  control_keypad (1);
+#endif
+  fflush (rl_outstream);
+  terminal_prepped = 1;
+
+  release_sigint ();
+#endif /* !__GO32__ */
+}
+
+/* Restore the terminal's normal settings and modes. */
+void
+rl_deprep_terminal ()
+{
+#if !defined (__GO32__)
+  int tty = fileno (rl_instream);
+
+  if (!terminal_prepped)
+    return;
+
+  /* Try to keep this function from being INTerrupted. */
+  block_sigint ();
+
+  control_meta_key (0);
+#if 0
+  control_keypad (0);
+#endif
+  fflush (rl_outstream);
+
+  if (set_tty_settings (tty, &otio) < 0)
+    {
+      release_sigint ();
+      return;
+    }
+
+  terminal_prepped = 0;
+
+  release_sigint ();
+#endif /* !__GO32__ */
+}
+
+/* **************************************************************** */
+/*								    */
+/*			Bogus Flow Control      		    */
+/*								    */
+/* **************************************************************** */
+
+rl_restart_output (count, key)
+     int count, key;
+{
+  int fildes = fileno (rl_outstream);
+#if defined (TIOCSTART)
+#if defined (apollo)
+  ioctl (&fildes, TIOCSTART, 0);
+#else
+  ioctl (fildes, TIOCSTART, 0);
+#endif /* apollo */
+
+#else /* !TIOCSTART */
+#  if defined (TERMIOS_TTY_DRIVER)
+#    if defined (__ksr1__)
+  if (ksrflow)
+    {
+      ksrflow = 0;
+      tcflow (fildes, TCOON);
+    }
+#    else /* !ksr1 */
+  tcflow (fildes, TCOON);		/* Simulate a ^Q. */
+#    endif /* !ksr1 */
+#  else /* !TERMIOS_TTY_DRIVER */
+#    if defined (TCXONC)
+  ioctl (fildes, TCXONC, TCOON);
+#    endif /* TCXONC */
+#  endif /* !TERMIOS_TTY_DRIVER */
+#endif /* !TIOCSTART */
+
+  return 0;
+}
+
+rl_stop_output (count, key)
+     int count, key;
+{
+  int fildes = fileno (rl_instream);
+
+#if defined (TIOCSTOP)
+# if defined (apollo)
+  ioctl (&fildes, TIOCSTOP, 0);
+# else
+  ioctl (fildes, TIOCSTOP, 0);
+# endif /* apollo */
+#else /* !TIOCSTOP */
+# if defined (TERMIOS_TTY_DRIVER)
+#  if defined (__ksr1__)
+  ksrflow = 1;
+#  endif /* ksr1 */
+  tcflow (fildes, TCOOFF);
+# else
+#   if defined (TCXONC)
+  ioctl (fildes, TCXONC, TCOON);
+#   endif /* TCXONC */
+# endif /* !TERMIOS_TTY_DRIVER */
+#endif /* !TIOCSTOP */
+
+  return 0;
+}
+
+/* **************************************************************** */
+/*								    */
+/*			Default Key Bindings			    */
+/*								    */
+/* **************************************************************** */
+void
+rltty_set_default_bindings (kmap)
+     Keymap kmap;
+{
+  TIOTYPE ttybuff;
+  int tty = fileno (rl_instream);
+
+#if defined (NEW_TTY_DRIVER)
+
+#define SET_SPECIAL(sc, func) \
+  do \
+    { \
+      int ic; \
+      ic = sc; \
+      if (ic != -1 && kmap[ic].type == ISFUNC) \
+	kmap[ic].function = func; \
+    } \
+  while (0)
+
+  if (get_tty_settings (tty, &ttybuff) == 0)
+    {
+      if (ttybuff.flags & SGTTY_SET)
+	{
+	  SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
+	  SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
+	}
+
+#  if defined (TIOCGLTC)
+      if (ttybuff.flags & LTCHARS_SET)
+	{
+	  SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
+	  SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
+	}
+#  endif /* TIOCGLTC */
+    }
+
+#else /* !NEW_TTY_DRIVER */
+
+#define SET_SPECIAL(sc, func) \
+  do \
+    { \
+      unsigned char uc; \
+      uc = ttybuff.c_cc[sc]; \
+      if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
+	kmap[uc].function = func; \
+    } \
+  while (0)
+
+  if (get_tty_settings (tty, &ttybuff) == 0)
+    {
+      SET_SPECIAL (VERASE, rl_rubout);
+      SET_SPECIAL (VKILL, rl_unix_line_discard);
+
+#  if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
+      SET_SPECIAL (VLNEXT, rl_quoted_insert);
+#  endif /* VLNEXT && TERMIOS_TTY_DRIVER */
+
+#  if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
+      SET_SPECIAL (VWERASE, rl_unix_word_rubout);
+#  endif /* VWERASE && TERMIOS_TTY_DRIVER */
+    }
+#endif /* !NEW_TTY_DRIVER */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/search.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,370 @@
+/* search.c - code for non-incremental searching in emacs and vi modes. */
+
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+
+   This file is part of the Readline Library (the Library), a set of
+   routines for providing Emacs style line input to programs that ask
+   for it.
+
+   The Library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   The Library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#include <sys/types.h>
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include "rldefs.h"
+#include "readline.h"
+#include "history.h"
+
+#define STREQ(a, b)	(((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0))
+#define STREQN(a, b, n)	(((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0))
+
+#define abs(x)		(((x) > 0) ? (x) : -(x))
+
+extern char *xmalloc (), *xrealloc ();
+
+/* Variables imported from readline.c */
+extern int rl_point, rl_end, rl_line_buffer_len;
+extern Keymap _rl_keymap;
+extern int rl_editing_mode;
+extern char *rl_prompt;
+extern char *rl_line_buffer;
+extern HIST_ENTRY *saved_line_for_history;
+extern Function *rl_last_func;
+
+/* Functions imported from the rest of the library. */
+extern int _rl_free_history_entry ();
+
+static char *noninc_search_string = (char *) NULL;
+static int noninc_history_pos = 0;
+static char *prev_line_found = (char *) NULL;
+
+/* Search the history list for STRING starting at absolute history position
+   POS.  If STRING begins with `^', the search must match STRING at the
+   beginning of a history line, otherwise a full substring match is performed
+   for STRING.  DIR < 0 means to search backwards through the history list,
+   DIR >= 0 means to search forward. */
+static int
+noninc_search_from_pos (string, pos, dir)
+     char *string;
+     int pos, dir;
+{
+  int ret, old;
+
+  old = where_history ();
+  history_set_pos (pos);
+
+  if (*string == '^')
+    ret = history_search_prefix (string + 1, dir);
+  else
+    ret = history_search (string, dir);
+
+  if (ret != -1)
+    ret = where_history ();
+
+  history_set_pos (old);
+  return (ret);
+}
+
+/* Search for a line in the history containing STRING.  If DIR is < 0, the
+   search is backwards through previous entries, else through subsequent
+   entries. */
+static void
+noninc_dosearch (string, dir)
+     char *string;
+     int dir;
+{
+  int oldpos, pos;
+  HIST_ENTRY *entry;
+
+  if (string == 0 || *string == '\0' || noninc_history_pos < 0)
+    {
+      ding ();
+      return;
+    }
+
+  pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
+  if (pos == -1)
+    {
+      /* Search failed, current history position unchanged. */
+      maybe_unsave_line ();
+      rl_clear_message ();
+      rl_point = 0;
+      ding ();
+      return;
+    }
+
+  noninc_history_pos = pos;
+
+  oldpos = where_history ();
+  history_set_pos (noninc_history_pos);
+  entry = current_history ();
+#if defined (VI_MODE)
+  if (rl_editing_mode != vi_mode)
+#endif
+  history_set_pos (oldpos);
+
+  {
+    int line_len;
+
+    line_len = strlen (entry->line);
+    if (line_len >= rl_line_buffer_len)
+      rl_extend_line_buffer (line_len);
+    strcpy (rl_line_buffer, entry->line);
+  }
+
+  rl_undo_list = (UNDO_LIST *)entry->data;
+  rl_end = strlen (rl_line_buffer);
+  rl_point = 0;
+  rl_clear_message ();
+
+  if (saved_line_for_history)
+    _rl_free_history_entry (saved_line_for_history);
+  saved_line_for_history = (HIST_ENTRY *)NULL;
+}
+
+/* Search non-interactively through the history list.  DIR < 0 means to
+   search backwards through the history of previous commands; otherwise
+   the search is for commands subsequent to the current position in the
+   history list.  PCHAR is the character to use for prompting when reading
+   the search string; if not specified (0), it defaults to `:'. */
+static void
+noninc_search (dir, pchar)
+     int dir;
+     int pchar;
+{
+  int saved_point, c, pmtlen;
+  char *p;
+
+  maybe_save_line ();
+  saved_point = rl_point;
+
+  /* Use the line buffer to read the search string. */
+  rl_line_buffer[0] = 0;
+  rl_end = rl_point = 0;
+
+  /* XXX - this needs fixing to work with the prompt expansion stuff - XXX */
+  pmtlen = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
+  p = xmalloc (2 + pmtlen);
+  if (pmtlen)
+    strcpy (p, rl_prompt);
+  p[pmtlen] = pchar ? pchar : ':';
+  p[pmtlen + 1]  = '\0';
+
+  rl_message (p, 0, 0);
+  free (p);
+
+  /* Read the search string. */
+  while (c = rl_read_key ())
+    {
+      switch (c)
+	{
+	case CTRL('H'):
+	case RUBOUT:
+	  if (rl_point == 0)
+	    {
+	      maybe_unsave_line ();
+	      rl_clear_message ();
+	      rl_point = saved_point;
+	      return;
+	    }
+	  rl_rubout (1);
+	  break;
+
+	case CTRL('W'):
+	  rl_unix_word_rubout (1, c);
+	  break;
+
+	case CTRL('U'):
+	  rl_unix_line_discard (1, c);
+	  break;
+
+	case RETURN:
+	case NEWLINE:
+	  goto dosearch;
+	  /* NOTREACHED */
+	  break;
+
+	case CTRL('C'):
+	case CTRL('G'):
+	  maybe_unsave_line ();
+	  rl_clear_message ();
+	  rl_point = saved_point;
+	  ding ();
+	  return;
+
+	default:
+	  rl_insert (1, c);
+	  break;
+	}
+      rl_redisplay ();
+    }
+
+ dosearch:
+  /* If rl_point == 0, we want to re-use the previous search string and
+     start from the saved history position.  If there's no previous search
+     string, punt. */
+  if (rl_point == 0)
+    {
+      if (!noninc_search_string)
+	{
+	  ding ();
+	  return;
+	}
+    }
+  else
+    {
+      /* We want to start the search from the current history position. */
+      noninc_history_pos = where_history ();
+      if (noninc_search_string)
+	free (noninc_search_string);
+      noninc_search_string = savestring (rl_line_buffer);
+    }
+
+  noninc_dosearch (noninc_search_string, dir);
+}
+
+/* Search forward through the history list for a string.  If the vi-mode
+   code calls this, KEY will be `?'. */
+rl_noninc_forward_search (count, key)
+     int count, key;
+{
+  if (key == '?')
+    noninc_search (1, '?');
+  else
+    noninc_search (1, 0);
+  return 0;
+}
+
+/* Reverse search the history list for a string.  If the vi-mode code
+   calls this, KEY will be `/'. */
+rl_noninc_reverse_search (count, key)
+     int count, key;
+{
+  if (key == '/')
+    noninc_search (-1, '/');
+  else
+    noninc_search (-1, 0);
+  return 0;
+}
+
+/* Search forward through the history list for the last string searched
+   for.  If there is no saved search string, abort. */
+rl_noninc_forward_search_again (count, key)
+     int count, key;
+{
+  if (!noninc_search_string)
+    {
+      ding ();
+      return (-1);
+    }
+  noninc_dosearch (noninc_search_string, 1);
+  return 0;
+}
+
+/* Reverse search in the history list for the last string searched
+   for.  If there is no saved search string, abort. */
+rl_noninc_reverse_search_again (count, key)
+     int count, key;
+{
+  if (!noninc_search_string)
+    {
+      ding ();
+      return (-1);
+    }
+  noninc_dosearch (noninc_search_string, -1);
+  return 0;
+}
+
+static int
+rl_history_search_internal (count, direction)
+     int count, direction;
+{
+  HIST_ENTRY *temp, *old_temp;
+  int line_len;
+
+  maybe_save_line ();
+
+  temp = old_temp = (HIST_ENTRY *)NULL;
+  while (count)
+    {
+      temp = (direction < 0) ? previous_history () : next_history ();
+      if (!temp)
+        break;
+      if (STREQN (rl_line_buffer, temp->line, rl_point))
+	{
+	  /* Don't find multiple instances of the same line. */
+	  if (prev_line_found && STREQ (prev_line_found, temp->line))
+	    continue;
+          if (direction < 0)
+            old_temp = temp;
+          prev_line_found = temp->line;
+          count--;
+	}
+    }
+
+  if (!temp)
+    {
+      if (direction < 0 && old_temp)
+	temp = old_temp;
+      else
+	{
+	  maybe_unsave_line ();
+	  ding ();
+	  return 1;
+	}
+    }
+
+  line_len = strlen (temp->line);
+  if (line_len >= rl_line_buffer_len)
+    rl_extend_line_buffer (line_len);
+  strcpy (rl_line_buffer, temp->line);
+  rl_undo_list = (UNDO_LIST *)temp->data;
+  rl_end = line_len;
+  return 0;
+}
+
+/* Search forward in the history for the string of characters
+   from the start of the line to rl_point.  This is a non-incremental
+   search. */
+int
+rl_history_search_forward (count, ignore)
+     int count, ignore;
+{
+  if (count == 0)
+    return (0);
+  if (rl_last_func != rl_history_search_forward)
+    prev_line_found = (char *)NULL;
+  return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
+}
+
+/* Search backward through the history for the string of characters
+   from the start of the line to rl_point.  This is a non-incremental
+   search. */
+int
+rl_history_search_backward (count, ignore)
+     int count, ignore;
+{
+  if (count == 0)
+    return (0);
+  if (rl_last_func != rl_history_search_backward)
+    prev_line_found = (char *)NULL;
+  return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/signals.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,287 @@
+/* signals.c -- signal handling support for readline. */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#if !defined (NO_SYS_FILE)
+#  include <sys/file.h>
+#endif /* !NO_SYS_FILE */
+#include <signal.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <errno.h>
+/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+#if defined (GWINSZ_IN_SYS_IOCTL)
+#  include <sys/ioctl.h>
+#endif /* GWINSZ_IN_SYS_IOCTL */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+extern int readline_echoing_p;
+extern int rl_pending_input;
+extern int _rl_meta_flag;
+
+extern void free_undo_list ();
+
+#if defined (VOID_SIGHANDLER)
+#  define sighandler void
+#else
+#  define sighandler int
+#endif /* VOID_SIGHANDLER */
+
+/* This typedef is equivalant to the one for Function; it allows us
+   to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
+typedef sighandler SigHandler ();
+
+#if defined (__GO32__)
+#  undef HANDLE_SIGNALS
+#endif /* __GO32__ */
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+
+/* **************************************************************** */
+/*					        		    */
+/*			   Signal Handling                          */
+/*								    */
+/* **************************************************************** */
+
+#if defined (SIGWINCH)
+static SigHandler *old_sigwinch = (SigHandler *)NULL;
+
+static sighandler
+rl_handle_sigwinch (sig)
+     int sig;
+{
+  if (readline_echoing_p)
+    {
+      _rl_set_screen_size (fileno (rl_instream), 1);
+      _rl_redisplay_after_sigwinch ();
+    }
+
+  if (old_sigwinch &&
+      old_sigwinch != (SigHandler *)SIG_IGN &&
+      old_sigwinch != (SigHandler *)SIG_DFL)
+    (*old_sigwinch) (sig);
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* VOID_SIGHANDLER */
+}
+#endif  /* SIGWINCH */
+
+#if defined (HANDLE_SIGNALS)
+/* Interrupt handling. */
+static SigHandler
+  *old_int  = (SigHandler *)NULL,
+  *old_alrm = (SigHandler *)NULL;
+#if !defined (SHELL)
+static SigHandler
+  *old_tstp = (SigHandler *)NULL,
+  *old_ttou = (SigHandler *)NULL,
+  *old_ttin = (SigHandler *)NULL,
+  *old_cont = (SigHandler *)NULL;
+#endif /* !SHELL */
+
+/* Handle an interrupt character. */
+static sighandler
+rl_signal_handler (sig)
+     int sig;
+{
+#if defined (HAVE_POSIX_SIGNALS)
+  sigset_t set;
+#else /* !HAVE_POSIX_SIGNALS */
+#  if defined (HAVE_BSD_SIGNALS)
+  long omask;
+#  endif /* HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
+  /* Since the signal will not be blocked while we are in the signal
+     handler, ignore it until rl_clear_signals resets the catcher. */
+  if (sig == SIGINT)
+    signal (sig, SIG_IGN);
+#endif /* !HAVE_BSD_SIGNALS */
+
+  switch (sig)
+    {
+    case SIGINT:
+      {
+	register HIST_ENTRY *entry;
+
+	free_undo_list ();
+
+	entry = current_history ();
+	if (entry)
+	  entry->data = (char *)NULL;
+      }
+      _rl_kill_kbd_macro ();
+      rl_clear_message ();
+      rl_init_argument ();
+
+#if defined (SIGTSTP)
+    case SIGTSTP:
+    case SIGTTOU:
+    case SIGTTIN:
+#endif /* SIGTSTP */
+    case SIGALRM:
+      rl_clean_up_for_exit ();
+      rl_deprep_terminal ();
+      rl_clear_signals ();
+      rl_pending_input = 0;
+
+#if defined (HAVE_POSIX_SIGNALS)
+      sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
+      sigdelset (&set, sig);
+#else /* !HAVE_POSIX_SIGNALS */
+#  if defined (HAVE_BSD_SIGNALS)
+      omask = sigblock (0);
+#  endif /* HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+      kill (getpid (), sig);
+
+      /* Let the signal that we just sent through.  */
+#if defined (HAVE_POSIX_SIGNALS)
+      sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
+#else /* !HAVE_POSIX_SIGNALS */
+#  if defined (HAVE_BSD_SIGNALS)
+      sigsetmask (omask & ~(sigmask (sig)));
+#  endif /* HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+      rl_prep_terminal (_rl_meta_flag);
+      rl_set_signals ();
+    }
+
+#if !defined (VOID_SIGHANDLER)
+  return (0);
+#endif /* !VOID_SIGHANDLER */
+}
+
+#if defined (HAVE_POSIX_SIGNALS)
+static SigHandler *
+rl_set_sighandler (sig, handler)
+     int sig;
+     SigHandler *handler;
+{
+  struct sigaction act, oact;
+
+  act.sa_handler = handler;
+  act.sa_flags = 0;
+  sigemptyset (&act.sa_mask);
+  sigemptyset (&oact.sa_mask);
+  sigaction (sig, &act, &oact);
+  return (oact.sa_handler);
+}
+
+#else /* !HAVE_POSIX_SIGNALS */
+#  define rl_set_sighandler(sig, handler) (SigHandler *)signal (sig, handler)
+#endif /* !HAVE_POSIX_SIGNALS */
+
+rl_set_signals ()
+{
+  old_int = (SigHandler *)rl_set_sighandler (SIGINT, rl_signal_handler);
+  if (old_int == (SigHandler *)SIG_IGN)
+    signal (SIGINT, SIG_IGN);
+
+  old_alrm = (SigHandler *)rl_set_sighandler (SIGALRM, rl_signal_handler);
+  if (old_alrm == (SigHandler *)SIG_IGN)
+    signal (SIGALRM, SIG_IGN);
+
+#if !defined (SHELL)
+
+#if defined (SIGTSTP)
+  old_tstp = (SigHandler *)rl_set_sighandler (SIGTSTP, rl_signal_handler);
+  if (old_tstp == (SigHandler *)SIG_IGN)
+    signal (SIGTSTP, SIG_IGN);
+#endif /* SIGTSTP */
+#if defined (SIGTTOU)
+  old_ttou = (SigHandler *)rl_set_sighandler (SIGTTOU, rl_signal_handler);
+  old_ttin = (SigHandler *)rl_set_sighandler (SIGTTIN, rl_signal_handler);
+
+  if (old_tstp == (SigHandler *)SIG_IGN)
+    {
+      signal (SIGTTOU, SIG_IGN);
+      signal (SIGTTIN, SIG_IGN);
+    }
+#endif /* SIGTTOU */
+
+#endif /* !SHELL */
+
+#if defined (SIGWINCH)
+  old_sigwinch =
+    (SigHandler *) rl_set_sighandler (SIGWINCH, rl_handle_sigwinch);
+#endif /* SIGWINCH */
+  return 0;
+}
+
+rl_clear_signals ()
+{
+  rl_set_sighandler (SIGINT, old_int);
+  rl_set_sighandler (SIGALRM, old_alrm);
+
+#if !defined (SHELL)
+
+#if defined (SIGTSTP)
+  rl_set_sighandler (SIGTSTP, old_tstp);
+#endif
+
+#if defined (SIGTTOU)
+  rl_set_sighandler (SIGTTOU, old_ttou);
+  rl_set_sighandler (SIGTTIN, old_ttin);
+#endif /* SIGTTOU */
+
+#endif /* !SHELL */
+
+#if defined (SIGWINCH)
+  rl_set_sighandler (SIGWINCH, old_sigwinch);
+#endif
+
+  return 0;
+}
+#endif  /* HANDLE_SIGNALS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/tilde.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,380 @@
+/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
+
+/* Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+   This file is part of GNU Readline, a library for reading lines
+   of text with interactive input and history editing.
+
+   Readline is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 1, or (at your option) any
+   later version.
+
+   Readline is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else /* !HAVE_STRING_H */
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */  
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include "tilde.h"
+#include <sys/types.h>
+#include <pwd.h>
+
+#if defined (USG) && !defined (HAVE_GETPW_DECLS)
+extern struct passwd *getpwuid (), *getpwnam ();
+#endif /* USG && !defined (HAVE_GETPW_DECLS) */
+
+#if !defined (savestring)
+extern char *xmalloc ();
+#  ifndef strcpy
+extern char *strcpy ();
+#  endif
+#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
+#endif /* !savestring */
+
+#if !defined (NULL)
+#  if defined (__STDC__)
+#    define NULL ((void *) 0)
+#  else
+#    define NULL 0x0
+#  endif /* !__STDC__ */
+#endif /* !NULL */
+
+#if defined (TEST) || defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* TEST || STATIC_MALLOC */
+
+/* The default value of tilde_additional_prefixes.  This is set to
+   whitespace preceding a tilde so that simple programs which do not
+   perform any word separation get desired behaviour. */
+static char *default_prefixes[] =
+  { " ~", "\t~", (char *)NULL };
+
+/* The default value of tilde_additional_suffixes.  This is set to
+   whitespace or newline so that simple programs which do not
+   perform any word separation get desired behaviour. */
+static char *default_suffixes[] =
+  { " ", "\n", (char *)NULL };
+
+/* If non-null, this contains the address of a function to call if the
+   standard meaning for expanding a tilde fails.  The function is called
+   with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
+   which is the expansion, or a NULL pointer if there is no expansion. */
+CPFunction *tilde_expansion_failure_hook = (CPFunction *)NULL;
+
+/* When non-null, this is a NULL terminated array of strings which
+   are duplicates for a tilde prefix.  Bash uses this to expand
+   `=~' and `:~'. */
+char **tilde_additional_prefixes = default_prefixes;
+
+/* When non-null, this is a NULL terminated array of strings which match
+   the end of a username, instead of just "/".  Bash sets this to
+   `:' and `=~'. */
+char **tilde_additional_suffixes = default_suffixes;
+
+/* Find the start of a tilde expansion in STRING, and return the index of
+   the tilde which starts the expansion.  Place the length of the text
+   which identified this tilde starter in LEN, excluding the tilde itself. */
+static int
+tilde_find_prefix (string, len)
+     char *string;
+     int *len;
+{
+  register int i, j, string_len;
+  register char **prefixes = tilde_additional_prefixes;
+
+  string_len = strlen (string);
+  *len = 0;
+
+  if (!*string || *string == '~')
+    return (0);
+
+  if (prefixes)
+    {
+      for (i = 0; i < string_len; i++)
+	{
+	  for (j = 0; prefixes[j]; j++)
+	    {
+	      if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0)
+		{
+		  *len = strlen (prefixes[j]) - 1;
+		  return (i + *len);
+		}
+	    }
+	}
+    }
+  return (string_len);
+}
+
+/* Find the end of a tilde expansion in STRING, and return the index of
+   the character which ends the tilde definition.  */
+static int
+tilde_find_suffix (string)
+     char *string;
+{
+  register int i, j, string_len;
+  register char **suffixes = tilde_additional_suffixes;
+
+  string_len = strlen (string);
+
+  for (i = 0; i < string_len; i++)
+    {
+      if (string[i] == '/' || !string[i])
+	break;
+
+      for (j = 0; suffixes && suffixes[j]; j++)
+	{
+	  if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0)
+	    return (i);
+	}
+    }
+  return (i);
+}
+
+/* Return a new string which is the result of tilde expanding STRING. */
+char *
+tilde_expand (string)
+     char *string;
+{
+  char *result, *tilde_expand_word ();
+  int result_size, result_index;
+
+  result_size = result_index = 0;
+  result = (char *)NULL;
+
+  /* Scan through STRING expanding tildes as we come to them. */
+  while (1)
+    {
+      register int start, end;
+      char *tilde_word, *expansion;
+      int len;
+
+      /* Make START point to the tilde which starts the expansion. */
+      start = tilde_find_prefix (string, &len);
+
+      /* Copy the skipped text into the result. */
+      if ((result_index + start + 1) > result_size)
+	result = (char *)xrealloc (result, 1 + (result_size += (start + 20)));
+
+      strncpy (result + result_index, string, start);
+      result_index += start;
+
+      /* Advance STRING to the starting tilde. */
+      string += start;
+
+      /* Make END be the index of one after the last character of the
+	 username. */
+      end = tilde_find_suffix (string);
+
+      /* If both START and END are zero, we are all done. */
+      if (!start && !end)
+	break;
+
+      /* Expand the entire tilde word, and copy it into RESULT. */
+      tilde_word = (char *)xmalloc (1 + end);
+      strncpy (tilde_word, string, end);
+      tilde_word[end] = '\0';
+      string += end;
+
+      expansion = tilde_expand_word (tilde_word);
+      free (tilde_word);
+
+      len = strlen (expansion);
+      if ((result_index + len + 1) > result_size)
+	result = (char *)xrealloc (result, 1 + (result_size += (len + 20)));
+
+      strcpy (result + result_index, expansion);
+      result_index += len;
+      free (expansion);
+    }
+
+  result[result_index] = '\0';
+
+  return (result);
+}
+
+/* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
+   tilde.  If there is no expansion, call tilde_expansion_failure_hook. */
+char *
+tilde_expand_word (filename)
+     char *filename;
+{
+  char *dirname;
+
+  dirname = filename ? savestring (filename) : (char *)NULL;
+
+  if (dirname && *dirname == '~')
+    {
+      char *temp_name;
+      if (!dirname[1] || dirname[1] == '/')
+	{
+	  /* Prepend $HOME to the rest of the string. */
+	  char *temp_home = (char *)getenv ("HOME");
+
+	  /* If there is no HOME variable, look up the directory in
+	     the password database. */
+	  if (!temp_home)
+	    {
+	      struct passwd *entry;
+
+	      entry = getpwuid (getuid ());
+	      if (entry)
+		temp_home = entry->pw_dir;
+	    }
+
+	  temp_name = xmalloc (1 + strlen (&dirname[1])
+				 + (temp_home ? strlen (temp_home) : 0));
+	  temp_name[0] = '\0';
+	  if (temp_home)
+	    strcpy (temp_name, temp_home);
+	  strcat (temp_name, dirname + 1);
+	  free (dirname);
+	  dirname = temp_name;
+	}
+      else
+	{
+	  char *username;
+	  struct passwd *user_entry;
+	  int i;
+
+	  username = xmalloc (strlen (dirname));
+	  for (i = 1; dirname[i] && dirname[i] != '/'; i++)
+	    username[i - 1] = dirname[i];
+	  username[i - 1] = '\0';
+
+	  if ((user_entry = getpwnam (username)) == 0)
+	    {
+	      /* If the calling program has a special syntax for
+		 expanding tildes, and we couldn't find a standard
+		 expansion, then let them try. */
+	      if (tilde_expansion_failure_hook)
+		{
+		  char *expansion;
+
+		  expansion = (*tilde_expansion_failure_hook) (username);
+
+		  if (expansion)
+		    {
+		      temp_name = xmalloc (1 + strlen (expansion)
+						  + strlen (&dirname[i]));
+		      strcpy (temp_name, expansion);
+		      strcat (temp_name, &dirname[i]);
+		      free (expansion);
+		      free (dirname);
+		      dirname = temp_name;
+		    }
+		}
+	      /* We shouldn't report errors. */
+	    }
+	  else
+	    {
+	      temp_name = xmalloc (1 + strlen (user_entry->pw_dir)
+				     + strlen (&dirname[i]));
+	      strcpy (temp_name, user_entry->pw_dir);
+	      strcat (temp_name, &dirname[i]);
+	      free (dirname);
+	      dirname = temp_name;
+	    }
+	  endpwent ();
+	  free (username);
+	}
+    }
+  return (dirname);
+}
+
+
+#if defined (TEST)
+#undef NULL
+#include <stdio.h>
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char *result, line[512];
+  int done = 0;
+
+  while (!done)
+    {
+      printf ("~expand: ");
+      fflush (stdout);
+
+      if (!gets (line))
+	strcpy (line, "done");
+
+      if ((strcmp (line, "done") == 0) ||
+	  (strcmp (line, "quit") == 0) ||
+	  (strcmp (line, "exit") == 0))
+	{
+	  done = 1;
+	  break;
+	}
+
+      result = tilde_expand (line);
+      printf ("  --> %s\n", result);
+      free (result);
+    }
+  exit (0);
+}
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+
+/*
+ * Local variables:
+ * compile-command: "gcc -g -DTEST -o tilde tilde.c"
+ * end:
+ */
+#endif /* TEST */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/tilde.h	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,38 @@
+/* tilde.h: Externally available variables and function in libtilde.a. */
+
+#if !defined (__TILDE_H__)
+#  define __TILDE_H__
+
+/* Function pointers can be declared as (Function *)foo. */
+#if !defined (__FUNCTION_DEF)
+#  define __FUNCTION_DEF
+typedef int Function ();
+typedef void VFunction ();
+typedef char *CPFunction ();
+typedef char **CPPFunction ();
+#endif /* _FUNCTION_DEF */
+
+/* If non-null, this contains the address of a function to call if the
+   standard meaning for expanding a tilde fails.  The function is called
+   with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
+   which is the expansion, or a NULL pointer if there is no expansion. */
+extern CPFunction *tilde_expansion_failure_hook;
+
+/* When non-null, this is a NULL terminated array of strings which
+   are duplicates for a tilde prefix.  Bash uses this to expand
+   `=~' and `:~'. */
+extern char **tilde_additional_prefixes;
+
+/* When non-null, this is a NULL terminated array of strings which match
+   the end of a username, instead of just "/".  Bash sets this to
+   `:' and `=~'. */
+extern char **tilde_additional_suffixes;
+
+/* Return a new string which is the result of tilde expanding STRING. */
+extern char *tilde_expand ();
+
+/* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
+   tilde.  If there is no expansion, call tilde_expansion_failure_hook. */
+extern char *tilde_expand_word ();
+
+#endif /* __TILDE_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/vi_keymap.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,877 @@
+/* vi_keymap.c -- the keymap for vi_mode in readline (). */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (BUFSIZ)
+#include <stdio.h>
+#endif /* !BUFSIZ */
+
+#include "readline.h"
+
+#if 0
+extern KEYMAP_ENTRY_ARRAY vi_escape_keymap;
+#endif
+
+/* The keymap arrays for handling vi mode. */
+KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
+  /* The regular control keys come first. */
+  { ISFUNC, (Function *)0x0 },		/* Control-@ */
+  { ISFUNC, (Function *)0x0 },		/* Control-a */
+  { ISFUNC, (Function *)0x0 },		/* Control-b */
+  { ISFUNC, (Function *)0x0 },		/* Control-c */
+  { ISFUNC, rl_vi_eof_maybe },		/* Control-d */
+  { ISFUNC, rl_emacs_editing_mode },	/* Control-e */
+  { ISFUNC, (Function *)0x0 },		/* Control-f */
+  { ISFUNC, rl_abort },			/* Control-g */
+  { ISFUNC, rl_backward },		/* Control-h */
+  { ISFUNC, (Function *)0x0 },		/* Control-i */
+  { ISFUNC, rl_newline },		/* Control-j */
+  { ISFUNC, rl_kill_line },		/* Control-k */
+  { ISFUNC, rl_clear_screen },		/* Control-l */
+  { ISFUNC, rl_newline },		/* Control-m */
+  { ISFUNC, rl_get_next_history },	/* Control-n */
+  { ISFUNC, (Function *)0x0 },		/* Control-o */
+  { ISFUNC, rl_get_previous_history },	/* Control-p */
+  { ISFUNC, rl_quoted_insert },		/* Control-q */
+  { ISFUNC, rl_reverse_search_history }, /* Control-r */
+  { ISFUNC, rl_forward_search_history }, /* Control-s */
+  { ISFUNC, rl_transpose_chars },	/* Control-t */
+  { ISFUNC, rl_unix_line_discard },	/* Control-u */
+  { ISFUNC, rl_quoted_insert },		/* Control-v */
+  { ISFUNC, rl_unix_word_rubout },	/* Control-w */
+  { ISFUNC, (Function *)0x0 },		/* Control-x */
+  { ISFUNC, rl_yank },			/* Control-y */
+  { ISFUNC, (Function *)0x0 },		/* Control-z */
+
+  { ISFUNC, (Function *)0x0 },		/* Control-[ */	/* vi_escape_keymap */
+  { ISFUNC, (Function *)0x0 },		/* Control-\ */
+  { ISFUNC, (Function *)0x0 },		/* Control-] */
+  { ISFUNC, (Function *)0x0 },		/* Control-^ */
+  { ISFUNC, rl_undo_command },		/* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, rl_forward },		/* SPACE */
+  { ISFUNC, (Function *)0x0 },		/* ! */
+  { ISFUNC, (Function *)0x0 },		/* " */
+  { ISFUNC, rl_vi_comment },		/* # */
+  { ISFUNC, rl_end_of_line },		/* $ */
+  { ISFUNC, rl_vi_match },		/* % */
+  { ISFUNC, rl_vi_tilde_expand },	/* & */
+  { ISFUNC, (Function *)0x0 },		/* ' */
+  { ISFUNC, (Function *)0x0 },		/* ( */
+  { ISFUNC, (Function *)0x0 },		/* ) */
+  { ISFUNC, rl_vi_complete },		/* * */
+  { ISFUNC, rl_get_next_history},	/* + */
+  { ISFUNC, rl_vi_char_search },	/* , */
+  { ISFUNC, rl_get_previous_history },	/* - */
+  { ISFUNC, rl_vi_redo },		/* . */
+  { ISFUNC, rl_vi_search },		/* / */
+
+  /* Regular digits. */
+  { ISFUNC, rl_beg_of_line },		/* 0 */
+  { ISFUNC, rl_vi_arg_digit },		/* 1 */
+  { ISFUNC, rl_vi_arg_digit },		/* 2 */
+  { ISFUNC, rl_vi_arg_digit },		/* 3 */
+  { ISFUNC, rl_vi_arg_digit },		/* 4 */
+  { ISFUNC, rl_vi_arg_digit },		/* 5 */
+  { ISFUNC, rl_vi_arg_digit },		/* 6 */
+  { ISFUNC, rl_vi_arg_digit },		/* 7 */
+  { ISFUNC, rl_vi_arg_digit },		/* 8 */
+  { ISFUNC, rl_vi_arg_digit },		/* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, (Function *)0x0 },		/* : */
+  { ISFUNC, rl_vi_char_search },	/* ; */
+  { ISFUNC, (Function *)0x0 },		/* < */
+  { ISFUNC, rl_vi_complete },		/* = */
+  { ISFUNC, (Function *)0x0 },		/* > */
+  { ISFUNC, rl_vi_search },		/* ? */
+  { ISFUNC, (Function *)0x0 },		/* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_vi_append_eol },		/* A */
+  { ISFUNC, rl_vi_prev_word},		/* B */
+  { ISFUNC, rl_vi_change_to },		/* C */
+  { ISFUNC, rl_vi_delete_to },		/* D */
+  { ISFUNC, rl_vi_end_word },		/* E */
+  { ISFUNC, rl_vi_char_search },	/* F */
+  { ISFUNC, rl_vi_fetch_history },	/* G */
+  { ISFUNC, (Function *)0x0 },		/* H */
+  { ISFUNC, rl_vi_insert_beg },		/* I */
+  { ISFUNC, (Function *)0x0 },		/* J */
+  { ISFUNC, (Function *)0x0 },		/* K */
+  { ISFUNC, (Function *)0x0 },		/* L */
+  { ISFUNC, (Function *)0x0 },		/* M */
+  { ISFUNC, rl_vi_search_again },	/* N */
+  { ISFUNC, (Function *)0x0 },		/* O */
+  { ISFUNC, rl_vi_put },		/* P */
+  { ISFUNC, (Function *)0x0 },		/* Q */
+  { ISFUNC, rl_vi_replace },		/* R */
+  { ISFUNC, rl_vi_subst },		/* S */
+  { ISFUNC, rl_vi_char_search },	/* T */
+  { ISFUNC, rl_revert_line },		/* U */
+  { ISFUNC, (Function *)0x0 },		/* V */
+  { ISFUNC, rl_vi_next_word },		/* W */
+  { ISFUNC, rl_rubout },		/* X */
+  { ISFUNC, rl_vi_yank_to },		/* Y */
+  { ISFUNC, (Function *)0x0 },		/* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, (Function *)0x0 },		/* [ */
+  { ISFUNC, rl_vi_complete },		/* \ */
+  { ISFUNC, (Function *)0x0 },		/* ] */
+  { ISFUNC, rl_vi_first_print },	/* ^ */
+  { ISFUNC, rl_vi_yank_arg },		/* _ */
+  { ISFUNC, (Function *)0x0 },		/* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, rl_vi_append_mode },	/* a */
+  { ISFUNC, rl_vi_prev_word },		/* b */
+  { ISFUNC, rl_vi_change_to },		/* c */
+  { ISFUNC, rl_vi_delete_to },		/* d */
+  { ISFUNC, rl_vi_end_word },		/* e */
+  { ISFUNC, rl_vi_char_search },	/* f */
+  { ISFUNC, (Function *)0x0 },		/* g */
+  { ISFUNC, rl_backward },		/* h */
+  { ISFUNC, rl_vi_insertion_mode },	/* i */
+  { ISFUNC, rl_get_next_history },	/* j */
+  { ISFUNC, rl_get_previous_history },	/* k */
+  { ISFUNC, rl_forward },		/* l */
+  { ISFUNC, (Function *)0x0 },		/* m */
+  { ISFUNC, rl_vi_search_again },	/* n */
+  { ISFUNC, (Function *)0x0 },		/* o */
+  { ISFUNC, rl_vi_put },		/* p */
+  { ISFUNC, (Function *)0x0 },		/* q */
+  { ISFUNC, rl_vi_change_char },	/* r */
+  { ISFUNC, rl_vi_subst },		/* s */
+  { ISFUNC, rl_vi_char_search },	/* t */
+  { ISFUNC, rl_undo_command },		/* u */
+  { ISFUNC, (Function *)0x0 },		/* v */
+  { ISFUNC, rl_vi_next_word },		/* w */
+  { ISFUNC, rl_vi_delete },		/* x */
+  { ISFUNC, rl_vi_yank_to },		/* y */
+  { ISFUNC, (Function *)0x0 },		/* z */
+
+  /* Final punctuation. */
+  { ISFUNC, (Function *)0x0 },		/* { */
+  { ISFUNC, rl_vi_column },		/* | */
+  { ISFUNC, (Function *)0x0 },		/* } */
+  { ISFUNC, rl_vi_change_case },	/* ~ */
+  { ISFUNC, (Function *)0x0 },		/* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+  /* Undefined keys. */
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 }
+#endif /* KEYMAP_SIZE > 128 */
+};
+
+
+KEYMAP_ENTRY_ARRAY vi_insertion_keymap = {
+  /* The regular control keys come first. */
+  { ISFUNC, (Function *)0x0 },		/* Control-@ */
+  { ISFUNC, rl_insert },		/* Control-a */
+  { ISFUNC, rl_insert },		/* Control-b */
+  { ISFUNC, rl_insert },		/* Control-c */
+  { ISFUNC, rl_vi_eof_maybe },		/* Control-d */
+  { ISFUNC, rl_insert },		/* Control-e */
+  { ISFUNC, rl_insert },		/* Control-f */
+  { ISFUNC, rl_insert },		/* Control-g */
+  { ISFUNC, rl_rubout },		/* Control-h */
+  { ISFUNC, rl_complete },		/* Control-i */
+  { ISFUNC, rl_newline },		/* Control-j */
+  { ISFUNC, rl_insert },		/* Control-k */
+  { ISFUNC, rl_insert },		/* Control-l */
+  { ISFUNC, rl_newline },		/* Control-m */
+  { ISFUNC, rl_insert },		/* Control-n */
+  { ISFUNC, rl_insert },		/* Control-o */
+  { ISFUNC, rl_insert },		/* Control-p */
+  { ISFUNC, rl_insert },		/* Control-q */
+  { ISFUNC, rl_reverse_search_history }, /* Control-r */
+  { ISFUNC, rl_forward_search_history }, /* Control-s */
+  { ISFUNC, rl_transpose_chars },	/* Control-t */
+  { ISFUNC, rl_unix_line_discard },	/* Control-u */
+  { ISFUNC, rl_quoted_insert },		/* Control-v */
+  { ISFUNC, rl_unix_word_rubout },	/* Control-w */
+  { ISFUNC, rl_insert },		/* Control-x */
+  { ISFUNC, rl_yank },			/* Control-y */
+  { ISFUNC, rl_insert },		/* Control-z */
+
+  { ISFUNC, rl_vi_movement_mode },	/* Control-[ */
+  { ISFUNC, rl_insert },		/* Control-\ */
+  { ISFUNC, rl_insert },		/* Control-] */
+  { ISFUNC, rl_insert },		/* Control-^ */
+  { ISFUNC, rl_undo_command },		/* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, rl_insert },		/* SPACE */
+  { ISFUNC, rl_insert },		/* ! */
+  { ISFUNC, rl_insert },		/* " */
+  { ISFUNC, rl_insert },		/* # */
+  { ISFUNC, rl_insert },		/* $ */
+  { ISFUNC, rl_insert },		/* % */
+  { ISFUNC, rl_insert },		/* & */
+  { ISFUNC, rl_insert },		/* ' */
+  { ISFUNC, rl_insert },		/* ( */
+  { ISFUNC, rl_insert },		/* ) */
+  { ISFUNC, rl_insert },		/* * */
+  { ISFUNC, rl_insert },		/* + */
+  { ISFUNC, rl_insert },		/* , */
+  { ISFUNC, rl_insert },		/* - */
+  { ISFUNC, rl_insert },		/* . */
+  { ISFUNC, rl_insert },		/* / */
+
+  /* Regular digits. */
+  { ISFUNC, rl_insert },		/* 0 */
+  { ISFUNC, rl_insert },		/* 1 */
+  { ISFUNC, rl_insert },		/* 2 */
+  { ISFUNC, rl_insert },		/* 3 */
+  { ISFUNC, rl_insert },		/* 4 */
+  { ISFUNC, rl_insert },		/* 5 */
+  { ISFUNC, rl_insert },		/* 6 */
+  { ISFUNC, rl_insert },		/* 7 */
+  { ISFUNC, rl_insert },		/* 8 */
+  { ISFUNC, rl_insert },		/* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, rl_insert },		/* : */
+  { ISFUNC, rl_insert },		/* ; */
+  { ISFUNC, rl_insert },		/* < */
+  { ISFUNC, rl_insert },		/* = */
+  { ISFUNC, rl_insert },		/* > */
+  { ISFUNC, rl_insert },		/* ? */
+  { ISFUNC, rl_insert },		/* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_insert },		/* A */
+  { ISFUNC, rl_insert },		/* B */
+  { ISFUNC, rl_insert },		/* C */
+  { ISFUNC, rl_insert },		/* D */
+  { ISFUNC, rl_insert },		/* E */
+  { ISFUNC, rl_insert },		/* F */
+  { ISFUNC, rl_insert },		/* G */
+  { ISFUNC, rl_insert },		/* H */
+  { ISFUNC, rl_insert },		/* I */
+  { ISFUNC, rl_insert },		/* J */
+  { ISFUNC, rl_insert },		/* K */
+  { ISFUNC, rl_insert },		/* L */
+  { ISFUNC, rl_insert },		/* M */
+  { ISFUNC, rl_insert },		/* N */
+  { ISFUNC, rl_insert },		/* O */
+  { ISFUNC, rl_insert },		/* P */
+  { ISFUNC, rl_insert },		/* Q */
+  { ISFUNC, rl_insert },		/* R */
+  { ISFUNC, rl_insert },		/* S */
+  { ISFUNC, rl_insert },		/* T */
+  { ISFUNC, rl_insert },		/* U */
+  { ISFUNC, rl_insert },		/* V */
+  { ISFUNC, rl_insert },		/* W */
+  { ISFUNC, rl_insert },		/* X */
+  { ISFUNC, rl_insert },		/* Y */
+  { ISFUNC, rl_insert },		/* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, rl_insert },		/* [ */
+  { ISFUNC, rl_insert },		/* \ */
+  { ISFUNC, rl_insert },		/* ] */
+  { ISFUNC, rl_insert },		/* ^ */
+  { ISFUNC, rl_insert },		/* _ */
+  { ISFUNC, rl_insert },		/* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, rl_insert },		/* a */
+  { ISFUNC, rl_insert },		/* b */
+  { ISFUNC, rl_insert },		/* c */
+  { ISFUNC, rl_insert },		/* d */
+  { ISFUNC, rl_insert },		/* e */
+  { ISFUNC, rl_insert },		/* f */
+  { ISFUNC, rl_insert },		/* g */
+  { ISFUNC, rl_insert },		/* h */
+  { ISFUNC, rl_insert },		/* i */
+  { ISFUNC, rl_insert },		/* j */
+  { ISFUNC, rl_insert },		/* k */
+  { ISFUNC, rl_insert },		/* l */
+  { ISFUNC, rl_insert },		/* m */
+  { ISFUNC, rl_insert },		/* n */
+  { ISFUNC, rl_insert },		/* o */
+  { ISFUNC, rl_insert },		/* p */
+  { ISFUNC, rl_insert },		/* q */
+  { ISFUNC, rl_insert },		/* r */
+  { ISFUNC, rl_insert },		/* s */
+  { ISFUNC, rl_insert },		/* t */
+  { ISFUNC, rl_insert },		/* u */
+  { ISFUNC, rl_insert },		/* v */
+  { ISFUNC, rl_insert },		/* w */
+  { ISFUNC, rl_insert },		/* x */
+  { ISFUNC, rl_insert },		/* y */
+  { ISFUNC, rl_insert },		/* z */
+
+  /* Final punctuation. */
+  { ISFUNC, rl_insert },		/* { */
+  { ISFUNC, rl_insert },		/* | */
+  { ISFUNC, rl_insert },		/* } */
+  { ISFUNC, rl_insert },		/* ~ */
+  { ISFUNC, rl_rubout },		/* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+  /* Pure 8-bit characters (128 - 159).
+     These might be used in some
+     character sets. */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+  { ISFUNC, rl_insert },	/* ? */
+
+  /* ISO Latin-1 characters (160 - 255) */
+  { ISFUNC, rl_insert },	/* No-break space */
+  { ISFUNC, rl_insert },	/* Inverted exclamation mark */
+  { ISFUNC, rl_insert },	/* Cent sign */
+  { ISFUNC, rl_insert },	/* Pound sign */
+  { ISFUNC, rl_insert },	/* Currency sign */
+  { ISFUNC, rl_insert },	/* Yen sign */
+  { ISFUNC, rl_insert },	/* Broken bar */
+  { ISFUNC, rl_insert },	/* Section sign */
+  { ISFUNC, rl_insert },	/* Diaeresis */
+  { ISFUNC, rl_insert },	/* Copyright sign */
+  { ISFUNC, rl_insert },	/* Feminine ordinal indicator */
+  { ISFUNC, rl_insert },	/* Left pointing double angle quotation mark */
+  { ISFUNC, rl_insert },	/* Not sign */
+  { ISFUNC, rl_insert },	/* Soft hyphen */
+  { ISFUNC, rl_insert },	/* Registered sign */
+  { ISFUNC, rl_insert },	/* Macron */
+  { ISFUNC, rl_insert },	/* Degree sign */
+  { ISFUNC, rl_insert },	/* Plus-minus sign */
+  { ISFUNC, rl_insert },	/* Superscript two */
+  { ISFUNC, rl_insert },	/* Superscript three */
+  { ISFUNC, rl_insert },	/* Acute accent */
+  { ISFUNC, rl_insert },	/* Micro sign */
+  { ISFUNC, rl_insert },	/* Pilcrow sign */
+  { ISFUNC, rl_insert },	/* Middle dot */
+  { ISFUNC, rl_insert },	/* Cedilla */
+  { ISFUNC, rl_insert },	/* Superscript one */
+  { ISFUNC, rl_insert },	/* Masculine ordinal indicator */
+  { ISFUNC, rl_insert },	/* Right pointing double angle quotation mark */
+  { ISFUNC, rl_insert },	/* Vulgar fraction one quarter */
+  { ISFUNC, rl_insert },	/* Vulgar fraction one half */
+  { ISFUNC, rl_insert },	/* Vulgar fraction three quarters */
+  { ISFUNC, rl_insert },	/* Inverted questionk mark */
+  { ISFUNC, rl_insert },	/* Latin capital letter a with grave */
+  { ISFUNC, rl_insert },	/* Latin capital letter a with acute */
+  { ISFUNC, rl_insert },	/* Latin capital letter a with circumflex */
+  { ISFUNC, rl_insert },	/* Latin capital letter a with tilde */
+  { ISFUNC, rl_insert },	/* Latin capital letter a with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin capital letter a with ring above */
+  { ISFUNC, rl_insert },	/* Latin capital letter ae */
+  { ISFUNC, rl_insert },	/* Latin capital letter c with cedilla */
+  { ISFUNC, rl_insert },	/* Latin capital letter e with grave */
+  { ISFUNC, rl_insert },	/* Latin capital letter e with acute */
+  { ISFUNC, rl_insert },	/* Latin capital letter e with circumflex */
+  { ISFUNC, rl_insert },	/* Latin capital letter e with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin capital letter i with grave */
+  { ISFUNC, rl_insert },	/* Latin capital letter i with acute */
+  { ISFUNC, rl_insert },	/* Latin capital letter i with circumflex */
+  { ISFUNC, rl_insert },	/* Latin capital letter i with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin capital letter eth (Icelandic) */
+  { ISFUNC, rl_insert },	/* Latin capital letter n with tilde */
+  { ISFUNC, rl_insert },	/* Latin capital letter o with grave */
+  { ISFUNC, rl_insert },	/* Latin capital letter o with acute */
+  { ISFUNC, rl_insert },	/* Latin capital letter o with circumflex */
+  { ISFUNC, rl_insert },	/* Latin capital letter o with tilde */
+  { ISFUNC, rl_insert },	/* Latin capital letter o with diaeresis */
+  { ISFUNC, rl_insert },	/* Multiplication sign */
+  { ISFUNC, rl_insert },	/* Latin capital letter o with stroke */
+  { ISFUNC, rl_insert },	/* Latin capital letter u with grave */
+  { ISFUNC, rl_insert },	/* Latin capital letter u with acute */
+  { ISFUNC, rl_insert },	/* Latin capital letter u with circumflex */
+  { ISFUNC, rl_insert },	/* Latin capital letter u with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin capital letter Y with acute */
+  { ISFUNC, rl_insert },	/* Latin capital letter thorn (Icelandic) */
+  { ISFUNC, rl_insert },	/* Latin small letter sharp s (German) */
+  { ISFUNC, rl_insert },	/* Latin small letter a with grave */
+  { ISFUNC, rl_insert },	/* Latin small letter a with acute */
+  { ISFUNC, rl_insert },	/* Latin small letter a with circumflex */
+  { ISFUNC, rl_insert },	/* Latin small letter a with tilde */
+  { ISFUNC, rl_insert },	/* Latin small letter a with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin small letter a with ring above */
+  { ISFUNC, rl_insert },	/* Latin small letter ae */
+  { ISFUNC, rl_insert },	/* Latin small letter c with cedilla */
+  { ISFUNC, rl_insert },	/* Latin small letter e with grave */
+  { ISFUNC, rl_insert },	/* Latin small letter e with acute */
+  { ISFUNC, rl_insert },	/* Latin small letter e with circumflex */
+  { ISFUNC, rl_insert },	/* Latin small letter e with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin small letter i with grave */
+  { ISFUNC, rl_insert },	/* Latin small letter i with acute */
+  { ISFUNC, rl_insert },	/* Latin small letter i with circumflex */
+  { ISFUNC, rl_insert },	/* Latin small letter i with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin small letter eth (Icelandic) */
+  { ISFUNC, rl_insert },	/* Latin small letter n with tilde */
+  { ISFUNC, rl_insert },	/* Latin small letter o with grave */
+  { ISFUNC, rl_insert },	/* Latin small letter o with acute */
+  { ISFUNC, rl_insert },	/* Latin small letter o with circumflex */
+  { ISFUNC, rl_insert },	/* Latin small letter o with tilde */
+  { ISFUNC, rl_insert },	/* Latin small letter o with diaeresis */
+  { ISFUNC, rl_insert },	/* Division sign */
+  { ISFUNC, rl_insert },	/* Latin small letter o with stroke */
+  { ISFUNC, rl_insert },	/* Latin small letter u with grave */
+  { ISFUNC, rl_insert },	/* Latin small letter u with acute */
+  { ISFUNC, rl_insert },	/* Latin small letter u with circumflex */
+  { ISFUNC, rl_insert },	/* Latin small letter u with diaeresis */
+  { ISFUNC, rl_insert },	/* Latin small letter y with acute */
+  { ISFUNC, rl_insert },	/* Latin small letter thorn (Icelandic) */
+  { ISFUNC, rl_insert }		/* Latin small letter y with diaeresis */
+#endif /* KEYMAP_SIZE > 128 */
+};
+
+/* Unused for the time being. */
+#if 0
+KEYMAP_ENTRY_ARRAY vi_escape_keymap = {
+  /* The regular control keys come first. */
+  { ISFUNC, (Function *)0x0 },		/* Control-@ */
+  { ISFUNC, (Function *)0x0 },		/* Control-a */
+  { ISFUNC, (Function *)0x0 },		/* Control-b */
+  { ISFUNC, (Function *)0x0 },		/* Control-c */
+  { ISFUNC, (Function *)0x0 },		/* Control-d */
+  { ISFUNC, (Function *)0x0 },		/* Control-e */
+  { ISFUNC, (Function *)0x0 },		/* Control-f */
+  { ISFUNC, (Function *)0x0 },		/* Control-g */
+  { ISFUNC, (Function *)0x0 },		/* Control-h */
+  { ISFUNC, rl_tab_insert},		/* Control-i */
+  { ISFUNC, rl_emacs_editing_mode},	/* Control-j */
+  { ISFUNC, rl_kill_line },		/* Control-k */
+  { ISFUNC, (Function *)0x0 },		/* Control-l */
+  { ISFUNC, rl_emacs_editing_mode},	/* Control-m */
+  { ISFUNC, (Function *)0x0 },		/* Control-n */
+  { ISFUNC, (Function *)0x0 },		/* Control-o */
+  { ISFUNC, (Function *)0x0 },		/* Control-p */
+  { ISFUNC, (Function *)0x0 },		/* Control-q */
+  { ISFUNC, (Function *)0x0 },		/* Control-r */
+  { ISFUNC, (Function *)0x0 },		/* Control-s */
+  { ISFUNC, (Function *)0x0 },		/* Control-t */
+  { ISFUNC, (Function *)0x0 },		/* Control-u */
+  { ISFUNC, (Function *)0x0 },		/* Control-v */
+  { ISFUNC, (Function *)0x0 },		/* Control-w */
+  { ISFUNC, (Function *)0x0 },		/* Control-x */
+  { ISFUNC, (Function *)0x0 },		/* Control-y */
+  { ISFUNC, (Function *)0x0 },		/* Control-z */
+
+  { ISFUNC, rl_vi_movement_mode },	/* Control-[ */
+  { ISFUNC, (Function *)0x0 },		/* Control-\ */
+  { ISFUNC, (Function *)0x0 },		/* Control-] */
+  { ISFUNC, (Function *)0x0 },		/* Control-^ */
+  { ISFUNC, rl_undo_command },		/* Control-_ */
+
+  /* The start of printing characters. */
+  { ISFUNC, (Function *)0x0 },		/* SPACE */
+  { ISFUNC, (Function *)0x0 },		/* ! */
+  { ISFUNC, (Function *)0x0 },		/* " */
+  { ISFUNC, (Function *)0x0 },		/* # */
+  { ISFUNC, (Function *)0x0 },		/* $ */
+  { ISFUNC, (Function *)0x0 },		/* % */
+  { ISFUNC, (Function *)0x0 },		/* & */
+  { ISFUNC, (Function *)0x0 },		/* ' */
+  { ISFUNC, (Function *)0x0 },		/* ( */
+  { ISFUNC, (Function *)0x0 },		/* ) */
+  { ISFUNC, (Function *)0x0 },		/* * */
+  { ISFUNC, (Function *)0x0 },		/* + */
+  { ISFUNC, (Function *)0x0 },		/* , */
+  { ISFUNC, (Function *)0x0 },		/* - */
+  { ISFUNC, (Function *)0x0 },		/* . */
+  { ISFUNC, (Function *)0x0 },		/* / */
+
+  /* Regular digits. */
+  { ISFUNC, rl_vi_arg_digit },		/* 0 */
+  { ISFUNC, rl_vi_arg_digit },		/* 1 */
+  { ISFUNC, rl_vi_arg_digit },		/* 2 */
+  { ISFUNC, rl_vi_arg_digit },		/* 3 */
+  { ISFUNC, rl_vi_arg_digit },		/* 4 */
+  { ISFUNC, rl_vi_arg_digit },		/* 5 */
+  { ISFUNC, rl_vi_arg_digit },		/* 6 */
+  { ISFUNC, rl_vi_arg_digit },		/* 7 */
+  { ISFUNC, rl_vi_arg_digit },		/* 8 */
+  { ISFUNC, rl_vi_arg_digit },		/* 9 */
+
+  /* A little more punctuation. */
+  { ISFUNC, (Function *)0x0 },		/* : */
+  { ISFUNC, (Function *)0x0 },		/* ; */
+  { ISFUNC, (Function *)0x0 },		/* < */
+  { ISFUNC, (Function *)0x0 },		/* = */
+  { ISFUNC, (Function *)0x0 },		/* > */
+  { ISFUNC, (Function *)0x0 },		/* ? */
+  { ISFUNC, (Function *)0x0 },		/* @ */
+
+  /* Uppercase alphabet. */
+  { ISFUNC, rl_do_lowercase_version },	/* A */
+  { ISFUNC, rl_do_lowercase_version },	/* B */
+  { ISFUNC, rl_do_lowercase_version },	/* C */
+  { ISFUNC, rl_do_lowercase_version },	/* D */
+  { ISFUNC, rl_do_lowercase_version },	/* E */
+  { ISFUNC, rl_do_lowercase_version },	/* F */
+  { ISFUNC, rl_do_lowercase_version },	/* G */
+  { ISFUNC, rl_do_lowercase_version },	/* H */
+  { ISFUNC, rl_do_lowercase_version },	/* I */
+  { ISFUNC, rl_do_lowercase_version },	/* J */
+  { ISFUNC, rl_do_lowercase_version },	/* K */
+  { ISFUNC, rl_do_lowercase_version },	/* L */
+  { ISFUNC, rl_do_lowercase_version },	/* M */
+  { ISFUNC, rl_do_lowercase_version },	/* N */
+  { ISFUNC, rl_do_lowercase_version },	/* O */
+  { ISFUNC, rl_do_lowercase_version },	/* P */
+  { ISFUNC, rl_do_lowercase_version },	/* Q */
+  { ISFUNC, rl_do_lowercase_version },	/* R */
+  { ISFUNC, rl_do_lowercase_version },	/* S */
+  { ISFUNC, rl_do_lowercase_version },	/* T */
+  { ISFUNC, rl_do_lowercase_version },	/* U */
+  { ISFUNC, rl_do_lowercase_version },	/* V */
+  { ISFUNC, rl_do_lowercase_version },	/* W */
+  { ISFUNC, rl_do_lowercase_version },	/* X */
+  { ISFUNC, rl_do_lowercase_version },	/* Y */
+  { ISFUNC, rl_do_lowercase_version },	/* Z */
+
+  /* Some more punctuation. */
+  { ISFUNC, rl_arrow_keys },		/* [ */
+  { ISFUNC, (Function *)0x0 },		/* \ */
+  { ISFUNC, (Function *)0x0 },		/* ] */
+  { ISFUNC, (Function *)0x0 },		/* ^ */
+  { ISFUNC, (Function *)0x0 },		/* _ */
+  { ISFUNC, (Function *)0x0 },		/* ` */
+
+  /* Lowercase alphabet. */
+  { ISFUNC, (Function *)0x0 },		/* a */
+  { ISFUNC, (Function *)0x0 },		/* b */
+  { ISFUNC, (Function *)0x0 },		/* c */
+  { ISFUNC, (Function *)0x0 },		/* d */
+  { ISFUNC, (Function *)0x0 },		/* e */
+  { ISFUNC, (Function *)0x0 },		/* f */
+  { ISFUNC, (Function *)0x0 },		/* g */
+  { ISFUNC, (Function *)0x0 },		/* h */
+  { ISFUNC, (Function *)0x0 },		/* i */
+  { ISFUNC, (Function *)0x0 },		/* j */
+  { ISFUNC, (Function *)0x0 },		/* k */
+  { ISFUNC, (Function *)0x0 },		/* l */
+  { ISFUNC, (Function *)0x0 },		/* m */
+  { ISFUNC, (Function *)0x0 },		/* n */
+  { ISFUNC, rl_arrow_keys },		/* o */
+  { ISFUNC, (Function *)0x0 },		/* p */
+  { ISFUNC, (Function *)0x0 },		/* q */
+  { ISFUNC, (Function *)0x0 },		/* r */
+  { ISFUNC, (Function *)0x0 },		/* s */
+  { ISFUNC, (Function *)0x0 },		/* t */
+  { ISFUNC, (Function *)0x0 },		/* u */
+  { ISFUNC, (Function *)0x0 },		/* v */
+  { ISFUNC, (Function *)0x0 },		/* w */
+  { ISFUNC, (Function *)0x0 },		/* x */
+  { ISFUNC, (Function *)0x0 },		/* y */
+  { ISFUNC, (Function *)0x0 },		/* z */
+
+  /* Final punctuation. */
+  { ISFUNC, (Function *)0x0 },		/* { */
+  { ISFUNC, (Function *)0x0 },		/* | */
+  { ISFUNC, (Function *)0x0 },		/* } */
+  { ISFUNC, (Function *)0x0 },		/* ~ */
+  { ISFUNC, rl_backward_kill_word },	/* RUBOUT */
+
+#if KEYMAP_SIZE > 128
+  /* Undefined keys. */
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 },
+  { ISFUNC, (Function *)0x0 }
+#endif /* KEYMAP_SIZE > 128 */
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/vi_mode.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,1329 @@
+/* vi_mode.c -- A vi emulation mode for Bash.
+   Derived from code written by Jeff Sparkes (jsparkes@bnr.ca).  */
+
+/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 1, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
+
+/* **************************************************************** */
+/*								    */
+/*			VI Emulation Mode			    */
+/*								    */
+/* **************************************************************** */
+#include "rlconf.h"
+
+#if defined (VI_MODE)
+
+#include <sys/types.h>
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include <stdio.h>
+
+/* Some standard library routines. */
+#include "rldefs.h"
+#include "readline.h"
+#include "history.h"
+
+#ifndef digit_p
+#define digit_p(c)  ((c) >= '0' && (c) <= '9')
+#endif
+
+#ifndef digit_value
+#define digit_value(c) ((c) - '0')
+#endif
+
+#ifndef member
+#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
+#endif
+
+#ifndef isident
+#define isident(c) ((pure_alphabetic (c) || digit_p (c) || c == '_'))
+#endif
+
+#ifndef exchange
+#define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0)
+#endif
+
+#ifndef VI_COMMENT_BEGIN_DEFAULT
+#define VI_COMMENT_BEGIN_DEFAULT "#"
+#endif
+
+#if defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+extern char *xmalloc (), *xrealloc ();
+#endif /* STATIC_MALLOC */
+
+/* Variables imported from readline.c */
+extern int rl_point, rl_end, rl_mark, rl_done;
+extern FILE *rl_instream;
+extern int rl_line_buffer_len, rl_explicit_arg, rl_numeric_arg;
+extern Keymap _rl_keymap;
+extern char *rl_prompt;
+extern char *rl_line_buffer;
+extern int rl_arg_sign;
+
+extern void _rl_dispatch ();
+
+extern void rl_extend_line_buffer ();
+extern int rl_vi_check ();
+
+/* Non-zero means enter insertion mode. */
+static int _rl_vi_doing_insert = 0;
+
+/* String inserted into the line by rl_vi_comment (). */
+char *rl_vi_comment_begin = (char *)NULL;
+
+/* *** UNCLEAN *** */
+/* Command keys which do movement for xxx_to commands. */
+static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
+
+/* Keymap used for vi replace characters.  Created dynamically since
+   rarely used. */
+static Keymap vi_replace_map = (Keymap)NULL;
+
+/* The number of characters inserted in the last replace operation. */
+static int vi_replace_count = 0;
+
+/* If non-zero, we have text inserted after a c[motion] command that put
+   us implicitly into insert mode.  Some people want this text to be
+   attached to the command so that it is `redoable' with `.'. */
+static int vi_continued_command = 0;
+
+static int _rl_vi_last_command = 'i';	/* default `.' puts you in insert mode */
+static int _rl_vi_last_repeat = 1;
+static int _rl_vi_last_arg_sign = 1;
+static int _rl_vi_last_motion = 0;
+static int _rl_vi_last_search_char = 0;
+static int _rl_vi_last_replacement = 0;
+
+static int vi_redoing = 0;
+
+/* Text modification commands.  These are the `redoable' commands. */
+static char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
+
+static int rl_digit_loop1 ();
+
+void
+_rl_vi_reset_last ()
+{
+  _rl_vi_last_command = 'i';
+  _rl_vi_last_repeat = 1;
+  _rl_vi_last_arg_sign = 1;
+  _rl_vi_last_motion = 0;
+}
+
+void
+_rl_vi_set_last (key, repeat, sign)
+     int key, repeat, sign;
+{
+  _rl_vi_last_command = key;
+  _rl_vi_last_repeat = repeat;
+  _rl_vi_last_arg_sign = sign;
+}
+
+/* Is the command C a VI mode text modification command? */
+int
+rl_vi_textmod_command (c)
+     int c;
+{
+  return (member (c, vi_textmod));
+}
+
+/* Bound to `.'.  Called from command mode, so we know that we have to
+   redo a text modification command.  The default for _rl_vi_last_command
+   puts you back into insert mode. */
+rl_vi_redo (count, c)
+     int count, c;
+{
+  if (!rl_explicit_arg)
+    {
+      rl_numeric_arg = _rl_vi_last_repeat;
+      rl_arg_sign = _rl_vi_last_arg_sign;
+    }
+
+  vi_redoing = 1;
+  _rl_dispatch (_rl_vi_last_command, _rl_keymap);
+  vi_redoing = 0;
+
+  return (0);
+}
+    
+/* Yank the nth arg from the previous line into this line at point. */
+rl_vi_yank_arg (count, key)
+     int count, key;
+{
+  /* Readline thinks that the first word on a line is the 0th, while vi
+     thinks the first word on a line is the 1st.  Compensate. */
+  if (rl_explicit_arg)
+    rl_yank_nth_arg (count - 1, 0);
+  else
+    rl_yank_nth_arg ('$', 0);
+
+  return (0);
+}
+
+/* With an argument, move back that many history lines, else move to the
+   beginning of history. */
+rl_vi_fetch_history (count, c)
+     int count, c;
+{
+  int current = where_history ();
+
+  /* Giving an argument of n means we want the nth command in the history
+     file.  The command number is interpreted the same way that the bash
+     `history' command does it -- that is, giving an argument count of 450
+     to this command would get the command listed as number 450 in the
+     output of `history'. */
+  if (rl_explicit_arg)
+    {
+      int wanted = history_base + current - count;
+      if (wanted <= 0)
+        rl_beginning_of_history (0, 0);
+      else
+        rl_get_previous_history (wanted);
+    }
+  else
+    rl_beginning_of_history (count, 0);
+  return (0);
+}
+
+/* Search again for the last thing searched for. */
+rl_vi_search_again (count, key)
+     int count, key;
+{
+  switch (key)
+    {
+    case 'n':
+      rl_noninc_reverse_search_again (count, key);
+      break;
+
+    case 'N':
+      rl_noninc_forward_search_again (count, key);
+      break;
+    }
+  return (0);
+}
+
+/* Do a vi style search. */
+rl_vi_search (count, key)
+     int count, key;
+{
+  switch (key)
+    {
+    case '?':
+      rl_noninc_forward_search (count, key);
+      break;
+
+    case '/':
+      rl_noninc_reverse_search (count, key);
+      break;
+
+    default:
+      ding ();
+      break;
+    }
+  return (0);
+}
+
+/* Completion, from vi's point of view. */
+rl_vi_complete (ignore, key)
+     int ignore, key;
+{
+  if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
+    {
+      if (!whitespace (rl_line_buffer[rl_point + 1]))
+	rl_vi_end_word (1, 'E');
+      rl_point++;
+    }
+
+  if (key == '*')
+    rl_complete_internal ('*');	/* Expansion and replacement. */
+  else if (key == '=')
+    rl_complete_internal ('?');	/* List possible completions. */
+  else if (key == '\\')
+    rl_complete_internal (TAB);	/* Standard Readline completion. */
+  else
+    rl_complete (0, key);
+
+  if (key == '*' || key == '\\')
+    {
+      _rl_vi_set_last (key, 1, rl_arg_sign);
+      rl_vi_insertion_mode (1, key);
+    }
+  return (0);
+}
+
+/* Tilde expansion for vi mode. */
+rl_vi_tilde_expand (ignore, key)
+     int ignore, key;
+{
+  rl_tilde_expand (0, key);
+  _rl_vi_set_last (key, 1, rl_arg_sign);	/* XXX */
+  rl_vi_insertion_mode (1, key);
+  return (0);
+}
+
+/* Previous word in vi mode. */
+rl_vi_prev_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_vi_next_word (-count, key));
+
+  if (rl_point == 0)
+    {
+      ding ();
+      return (0);
+    }
+
+  if (uppercase_p (key))
+    rl_vi_bWord (count);
+  else
+    rl_vi_bword (count);
+
+  return (0);
+}
+
+/* Next word in vi mode. */
+rl_vi_next_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_vi_prev_word (-count, key));
+
+  if (rl_point >= (rl_end - 1))
+    {
+      ding ();
+      return (0);
+    }
+
+  if (uppercase_p (key))
+    rl_vi_fWord (count);
+  else
+    rl_vi_fword (count);
+  return (0);
+}
+
+/* Move to the end of the ?next? word. */
+rl_vi_end_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    {
+      ding ();
+      return -1;
+    }
+
+  if (uppercase_p (key))
+    rl_vi_eWord (count);
+  else
+    rl_vi_eword (count);
+  return (0);
+}
+
+/* Move forward a word the way that 'W' does. */
+rl_vi_fWord (count)
+     int count;
+{
+  while (count-- && rl_point < (rl_end - 1))
+    {
+      /* Skip until whitespace. */
+      while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+	rl_point++;
+
+      /* Now skip whitespace. */
+      while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+	rl_point++;
+    }
+  return (0);
+}
+
+rl_vi_bWord (count)
+     int count;
+{
+  while (count-- && rl_point > 0)
+    {
+      /* If we are at the start of a word, move back to whitespace so
+	 we will go back to the start of the previous word. */
+      if (!whitespace (rl_line_buffer[rl_point]) &&
+	  whitespace (rl_line_buffer[rl_point - 1]))
+	rl_point--;
+
+      while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
+	rl_point--;
+
+      if (rl_point > 0)
+	{
+	  while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
+	  rl_point++;
+	}
+    }
+  return (0);
+}
+
+rl_vi_eWord (count)
+     int count;
+{
+  while (count-- && rl_point < (rl_end - 1))
+    {
+      if (!whitespace (rl_line_buffer[rl_point]))
+	rl_point++;
+
+      /* Move to the next non-whitespace character (to the start of the
+	 next word). */
+      while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point]));
+
+      if (rl_point && rl_point < rl_end)
+	{
+	  /* Skip whitespace. */
+	  while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+	    rl_point++;
+
+	  /* Skip until whitespace. */
+	  while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
+	    rl_point++;
+
+	  /* Move back to the last character of the word. */
+	  rl_point--;
+	}
+    }
+  return (0);
+}
+
+rl_vi_fword (count)
+     int count;
+{
+  while (count-- && rl_point < (rl_end - 1))
+    {
+      /* Move to white space (really non-identifer). */
+      if (isident (rl_line_buffer[rl_point]))
+	{
+	  while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
+	    rl_point++;
+	}
+      else /* if (!whitespace (rl_line_buffer[rl_point])) */
+	{
+	  while (!isident (rl_line_buffer[rl_point]) &&
+		 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+	    rl_point++;
+	}
+
+      /* Move past whitespace. */
+      while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+	rl_point++;
+    }
+  return (0);
+}
+
+rl_vi_bword (count)
+     int count;
+{
+  while (count-- && rl_point > 0)
+    {
+      int last_is_ident;
+
+      /* If we are at the start of a word, move back to whitespace
+	 so we will go back to the start of the previous word. */
+      if (!whitespace (rl_line_buffer[rl_point]) &&
+	  whitespace (rl_line_buffer[rl_point - 1]))
+	rl_point--;
+
+      /* If this character and the previous character are `opposite', move
+	 back so we don't get messed up by the rl_point++ down there in
+	 the while loop.  Without this code, words like `l;' screw up the
+	 function. */
+      last_is_ident = isident (rl_line_buffer[rl_point - 1]);
+      if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
+	  (!isident (rl_line_buffer[rl_point]) && last_is_ident))
+	rl_point--;
+
+      while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
+	rl_point--;
+
+      if (rl_point > 0)
+	{
+	  if (isident (rl_line_buffer[rl_point]))
+	    while (--rl_point >= 0 && isident (rl_line_buffer[rl_point]));
+	  else
+	    while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) &&
+		   !whitespace (rl_line_buffer[rl_point]));
+	  rl_point++;
+	}
+    }
+  return (0);
+}
+
+rl_vi_eword (count)
+     int count;
+{
+  while (count-- && rl_point < rl_end - 1)
+    {
+      if (!whitespace (rl_line_buffer[rl_point]))
+	rl_point++;
+
+      while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+	rl_point++;
+
+      if (rl_point < rl_end)
+	{
+	  if (isident (rl_line_buffer[rl_point]))
+	    while (++rl_point < rl_end && isident (rl_line_buffer[rl_point]));
+	  else
+	    while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point])
+		   && !whitespace (rl_line_buffer[rl_point]));
+	}
+      rl_point--;
+    }
+  return (0);
+}
+
+rl_vi_insert_beg (count, key)
+     int count, key;
+{
+  rl_beg_of_line (1, key);
+  rl_vi_insertion_mode (1, key);
+  return (0);
+}
+
+rl_vi_append_mode (count, key)
+     int count, key;
+{
+  if (rl_point < rl_end)
+    rl_point++;
+  rl_vi_insertion_mode (1, key);
+  return (0);
+}
+
+rl_vi_append_eol (count, key)
+     int count, key;
+{
+  rl_end_of_line (1, key);
+  rl_vi_append_mode (1, key);
+  return (0);
+}
+
+/* What to do in the case of C-d. */
+rl_vi_eof_maybe (count, c)
+     int count, c;
+{
+  return (rl_newline (1, '\n'));
+}
+
+/* Insertion mode stuff. */
+
+/* Switching from one mode to the other really just involves
+   switching keymaps. */
+rl_vi_insertion_mode (count, key)
+     int count, key;
+{
+  _rl_keymap = vi_insertion_keymap;
+  return (0);
+}
+
+void
+_rl_vi_done_inserting ()
+{
+  if (_rl_vi_doing_insert)
+    {
+      rl_end_undo_group ();
+      /* Now, the text between rl_undo_list->next->start and
+	 rl_undo_list->next->end is what was inserted while in insert
+	 mode. */
+      _rl_vi_doing_insert = 0;
+      vi_continued_command = 1;
+    }
+  else
+    vi_continued_command = 0;
+}
+
+rl_vi_movement_mode (count, key)
+     int count, key;
+{
+  if (rl_point > 0)
+    rl_backward (1);
+
+#if 0
+  _rl_vi_reset_last ();
+#endif
+
+  _rl_keymap = vi_movement_keymap;
+  _rl_vi_done_inserting ();
+  return (0);
+}
+
+rl_vi_arg_digit (count, c)
+     int count, c;
+{
+  if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
+    return (rl_beg_of_line ());
+  else
+    return (rl_digit_argument (count, c));
+}
+
+rl_vi_change_case (count, ignore)
+     int count, ignore;
+{
+  char c = 0;
+
+  /* Don't try this on an empty line. */
+  if (rl_point >= rl_end)
+    return (0);
+
+  while (count-- && rl_point < rl_end)
+    {
+      if (uppercase_p (rl_line_buffer[rl_point]))
+	c = to_lower (rl_line_buffer[rl_point]);
+      else if (lowercase_p (rl_line_buffer[rl_point]))
+	c = to_upper (rl_line_buffer[rl_point]);
+      else
+	{
+	  /* Just skip over characters neither upper nor lower case. */
+	  rl_forward (1);
+	  continue;
+	}
+
+      /* Vi is kind of strange here. */
+      if (c)
+	{
+	  rl_begin_undo_group ();
+	  rl_delete (1, c);
+	  rl_insert (1, c);
+	  rl_end_undo_group ();
+	  rl_vi_check ();
+        }
+      else
+	rl_forward (1);
+    }
+  return (0);
+}
+
+rl_vi_put (count, key)
+     int count, key;
+{
+  if (!uppercase_p (key) && (rl_point + 1 <= rl_end))
+    rl_point++;
+
+  rl_yank ();
+  rl_backward (1);
+  return (0);
+}
+
+rl_vi_check ()
+{
+  if (rl_point && rl_point == rl_end)
+    rl_point--;
+  return (0);
+}
+
+rl_vi_column (count, key)
+     int count, key;
+{
+  if (count > rl_end)
+    rl_end_of_line ();
+  else
+    rl_point = count - 1;
+  return (0);
+}
+
+int
+rl_vi_domove (key, nextkey)
+     int key, *nextkey;
+{
+  int c, save;
+  int old_end;
+
+  rl_mark = rl_point;
+  c = rl_read_key ();
+  *nextkey = c;
+
+  if (!member (c, vi_motion))
+    {
+      if (digit_p (c))
+	{
+	  save = rl_numeric_arg;
+	  rl_numeric_arg = digit_value (c);
+	  rl_digit_loop1 ();
+	  rl_numeric_arg *= save;
+	  c = rl_read_key ();	/* real command */
+	  *nextkey = c;
+	}
+      else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
+	{
+	  rl_mark = rl_end;
+	  rl_beg_of_line ();
+	  _rl_vi_last_motion = c;
+	  return (0);
+	}
+      else
+	return (-1);
+    }
+
+  _rl_vi_last_motion = c;
+
+  /* Append a blank character temporarily so that the motion routines
+     work right at the end of the line. */
+  old_end = rl_end;
+  rl_line_buffer[rl_end++] = ' ';
+  rl_line_buffer[rl_end] = '\0';
+
+  _rl_dispatch (c, _rl_keymap);
+
+  /* Remove the blank that we added. */
+  rl_end = old_end;
+  rl_line_buffer[rl_end] = '\0';
+  if (rl_point > rl_end)
+    rl_point = rl_end;
+
+  /* No change in position means the command failed. */
+  if (rl_mark == rl_point)
+    return (-1);
+
+  /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
+     word.  If we are not at the end of the line, and we are on a
+     non-whitespace character, move back one (presumably to whitespace). */
+  if ((to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
+      !whitespace (rl_line_buffer[rl_point]))
+    rl_point--;
+
+  /* If cw or cW, back up to the end of a word, so the behaviour of ce
+     or cE is the actual result.  Brute-force, no subtlety. */
+  if (key == 'c' && rl_point >= rl_mark && (to_upper (c) == 'W'))
+    {
+      /* Don't move farther back than where we started. */
+      while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
+	rl_point--;
+
+      /* Posix.2 says that if cw or cW moves the cursor towards the end of
+	 the line, the character under the cursor should be deleted. */
+      if (rl_point == rl_mark)
+        rl_point++;
+      else
+	{
+	  /* Move past the end of the word so that the kill doesn't
+	     remove the last letter of the previous word.  Only do this
+	     if we are not at the end of the line. */
+	  if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
+	    rl_point++;
+	}
+    }
+
+  if (rl_mark < rl_point)
+    exchange (rl_point, rl_mark);
+
+  return (0);
+}
+
+/* A simplified loop for vi. Don't dispatch key at end.
+   Don't recognize minus sign? */
+static int
+rl_digit_loop1 ()
+{
+  int key, c;
+
+  while (1)
+    {
+      rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0);
+      key = c = rl_read_key ();
+
+      if (_rl_keymap[c].type == ISFUNC &&
+	  _rl_keymap[c].function == rl_universal_argument)
+	{
+	  rl_numeric_arg *= 4;
+	  continue;
+	}
+
+      c = UNMETA (c);
+      if (digit_p (c))
+	{
+	  if (rl_explicit_arg)
+	    rl_numeric_arg = (rl_numeric_arg * 10) + digit_value (c);
+	  else
+	    rl_numeric_arg = digit_value (c);
+	  rl_explicit_arg = 1;
+	}
+      else
+	{
+	  rl_clear_message ();
+	  rl_stuff_char (key);
+	  break;
+	}
+    }
+  return (0);
+}
+
+rl_vi_delete_to (count, key)
+     int count, key;
+{
+  int c;
+
+  if (uppercase_p (key))
+    rl_stuff_char ('$');
+  else if (vi_redoing)
+    rl_stuff_char (_rl_vi_last_motion);
+
+  if (rl_vi_domove (key, &c))
+    {
+      ding ();
+      return -1;
+    }
+
+  /* These are the motion commands that do not require adjusting the
+     mark. */
+  if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end))
+    rl_mark++;
+
+  rl_kill_text (rl_point, rl_mark);
+  return (0);
+}
+
+rl_vi_change_to (count, key)
+     int count, key;
+{
+  int c, start_pos;
+
+  if (uppercase_p (key))
+    rl_stuff_char ('$');
+  else if (vi_redoing)
+    rl_stuff_char (_rl_vi_last_motion);
+
+  start_pos = rl_point;
+
+  if (rl_vi_domove (key, &c))
+    {
+      ding ();
+      return -1;
+    }
+
+  /* These are the motion commands that do not require adjusting the
+     mark.  c[wW] are handled by special-case code in rl_vi_domove(),
+     and already leave the mark at the correct location. */
+  if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end))
+    rl_mark++;
+
+  /* The cursor never moves with c[wW]. */
+  if ((to_upper (c) == 'W') && rl_point < start_pos)
+    rl_point = start_pos;
+
+  rl_kill_text (rl_point, rl_mark);
+
+  rl_begin_undo_group ();
+  _rl_vi_doing_insert = 1;
+  _rl_vi_set_last (key, count, rl_arg_sign);
+  rl_vi_insertion_mode (1, key);
+
+  return (0);
+}
+
+rl_vi_yank_to (count, key)
+     int count, key;
+{
+  int c, save = rl_point;
+
+  if (uppercase_p (key))
+    rl_stuff_char ('$');
+
+  if (rl_vi_domove (key, &c))
+    {
+      ding ();
+      return -1;
+    }
+
+  /* These are the motion commands that do not require adjusting the
+     mark. */
+  if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end))
+    rl_mark++;
+
+  rl_begin_undo_group ();
+  rl_kill_text (rl_point, rl_mark);
+  rl_end_undo_group ();
+  rl_do_undo ();
+  rl_point = save;
+
+  return (0);
+}
+
+rl_vi_delete (count, key)
+     int count, key;
+{
+  int end;
+
+  if (rl_end == 0)
+    {
+      ding ();
+      return -1;
+    }
+
+  end = rl_point + count;
+
+  if (end >= rl_end)
+    end = rl_end;
+
+  rl_kill_text (rl_point, end);
+  
+  if (rl_point > 0 && rl_point == rl_end)
+    rl_backward (1);
+  return (0);
+}
+
+/* Turn the current line into a comment in shell history.
+   A K*rn shell style function. */
+rl_vi_comment (count, key)
+     int count, key;
+{
+  rl_beg_of_line ();
+
+  if (rl_vi_comment_begin != (char *)NULL)
+    rl_insert_text (rl_vi_comment_begin);
+  else
+    rl_insert_text (VI_COMMENT_BEGIN_DEFAULT);	/* Default. */
+
+  rl_redisplay ();
+  rl_newline (1, '\n');
+  return (0);
+}
+
+rl_vi_first_print (count, key)
+     int count, key;
+{
+  return (rl_back_to_indent ());
+}
+
+rl_back_to_indent (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  rl_beg_of_line ();
+  while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+    rl_point++;
+  return (0);
+}
+
+/* NOTE: it is necessary that opposite directions are inverses */
+#define	FTO	 1		/* forward to */
+#define BTO	-1		/* backward to */
+#define FFIND	 2		/* forward find */
+#define BFIND	-2		/* backward find */
+
+rl_vi_char_search (count, key)
+     int count, key;
+{
+  static char target;
+  static int orig_dir, dir;
+  int pos;
+
+  if (key == ';' || key == ',')
+    dir = (key == ';' ? orig_dir : -orig_dir);
+  else
+    {
+      if (vi_redoing)
+	target = _rl_vi_last_search_char;
+      else
+	_rl_vi_last_search_char = target = rl_getc (rl_instream);
+
+      switch (key)
+        {
+        case 't':
+          orig_dir = dir = FTO;
+          break;
+
+        case 'T':
+          orig_dir = dir = BTO;
+          break;
+
+        case 'f':
+          orig_dir = dir = FFIND;
+          break;
+
+        case 'F':
+          orig_dir = dir = BFIND;
+          break;
+        }
+    }
+
+  pos = rl_point;
+
+  while (count--)
+    {
+      if (dir < 0)
+	{
+	  if (pos == 0)
+	    {
+	      ding ();
+	      return -1;
+	    }
+
+	  pos--;
+	  do
+	    {
+	      if (rl_line_buffer[pos] == target)
+		{
+		  if (dir == BTO)
+		    rl_point = pos + 1;
+		  else
+		    rl_point = pos;
+		  break;
+		}
+	    }
+	  while (pos--);
+
+	  if (pos < 0)
+	    {
+	      ding ();
+	      return -1;
+	    }
+	}
+      else
+	{			/* dir > 0 */
+	  if (pos >= rl_end)
+	    {
+	      ding ();
+	      return -1;
+	    }
+
+	  pos++;
+	  do
+	    {
+	      if (rl_line_buffer[pos] == target)
+		{
+		  if (dir == FTO)
+		    rl_point = pos - 1;
+		  else
+		    rl_point = pos;
+		  break;
+		}
+	    }
+	  while (++pos < rl_end);
+
+	  if (pos >= (rl_end - 1))
+	    {
+	      ding ();
+	      return -1;
+	    }
+	}
+    }
+  return (0);
+}
+
+/* Match brackets */
+rl_vi_match (ignore, key)
+     int ignore, key;
+{
+  int count = 1, brack, pos;
+
+  pos = rl_point;
+  if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
+    {
+      while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
+	     rl_point < rl_end - 1)
+	rl_forward (1);
+
+      if (brack <= 0)
+	{
+	  rl_point = pos;
+	  ding ();
+	  return -1;
+	}
+    }
+
+  pos = rl_point;
+
+  if (brack < 0)
+    {
+      while (count)
+	{
+	  if (--pos >= 0)
+	    {
+	      int b = rl_vi_bracktype (rl_line_buffer[pos]);
+	      if (b == -brack)
+		count--;
+	      else if (b == brack)
+		count++;
+	    }
+	  else
+	    {
+	      ding ();
+	      return -1;
+	    }
+	}
+    }
+  else
+    {			/* brack > 0 */
+      while (count)
+	{
+	  if (++pos < rl_end)
+	    {
+	      int b = rl_vi_bracktype (rl_line_buffer[pos]);
+	      if (b == -brack)
+		count--;
+	      else if (b == brack)
+		count++;
+	    }
+	  else
+	    {
+	      ding ();
+	      return -1;
+	    }
+	}
+    }
+  rl_point = pos;
+  return (0);
+}
+
+int
+rl_vi_bracktype (c)
+     int c;
+{
+  switch (c)
+    {
+    case '(': return  1;
+    case ')': return -1;
+    case '[': return  2;
+    case ']': return -2;
+    case '{': return  3;
+    case '}': return -3;
+    default:  return  0;
+    }
+}
+
+rl_vi_change_char (count, key)
+     int count, key;
+{
+  int c;
+
+  if (vi_redoing)
+    c = _rl_vi_last_replacement;
+  else
+    _rl_vi_last_replacement = c = rl_getc (rl_instream);
+
+  if (c == '\033' || c == CTRL ('C'))
+    return -1;
+
+  while (count-- && rl_point < rl_end)
+    {
+      rl_begin_undo_group ();
+
+      rl_delete (1, c);
+      rl_insert (1, c);
+      if (count == 0)
+	rl_backward (1);
+
+      rl_end_undo_group ();
+    }
+  return (0);
+}
+
+rl_vi_subst (count, key)
+     int count, key;
+{
+  rl_begin_undo_group ();
+
+  if (uppercase_p (key))
+    {
+      rl_beg_of_line ();
+      rl_kill_line (1);
+    }
+  else
+    rl_delete_text (rl_point, rl_point+count);
+
+  rl_end_undo_group ();
+
+  _rl_vi_set_last (key, count, rl_arg_sign);
+
+  rl_begin_undo_group ();
+  _rl_vi_doing_insert = 1;
+  rl_vi_insertion_mode (1, key);
+
+  return (0);
+}
+
+rl_vi_overstrike (count, key)
+     int count, key;
+{
+  int i;
+
+  if (_rl_vi_doing_insert == 0)
+    {
+      _rl_vi_doing_insert = 1;
+      rl_begin_undo_group ();
+    }
+
+  for (i = 0; i < count; i++)
+    {
+      vi_replace_count++;
+      rl_begin_undo_group ();
+
+      if (rl_point < rl_end)
+	{
+	  rl_delete (1, key);
+	  rl_insert (1, key);
+	}
+      else
+	rl_insert (1, key);
+
+      rl_end_undo_group ();
+    }
+  return (0);
+}
+
+rl_vi_overstrike_delete (count)
+     int count;
+{
+  int i, s;
+
+  for (i = 0; i < count; i++)
+    {
+      if (vi_replace_count == 0)
+	{
+	  ding ();
+	  break;
+	}
+      s = rl_point;
+
+      if (rl_do_undo ())
+	vi_replace_count--;
+
+      if (rl_point == s)
+	rl_backward (1);
+    }
+
+  if (vi_replace_count == 0 && _rl_vi_doing_insert)
+    {
+      rl_end_undo_group ();
+      rl_do_undo ();
+      _rl_vi_doing_insert = 0;
+    }
+  return (0);
+}
+
+rl_vi_replace (count, key)
+     int count, key;
+{
+  int i;
+
+  vi_replace_count = 0;
+
+  if (!vi_replace_map)
+    {
+      vi_replace_map = rl_make_bare_keymap ();
+
+      for (i = ' '; i < KEYMAP_SIZE; i++)
+	vi_replace_map[i].function = rl_vi_overstrike;
+
+      vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
+      vi_replace_map[ESC].function = rl_vi_movement_mode;
+      vi_replace_map[RETURN].function = rl_newline;
+      vi_replace_map[NEWLINE].function = rl_newline;
+
+      /* If the normal vi insertion keymap has ^H bound to erase, do the
+         same here.  Probably should remove the assignment to RUBOUT up
+         there, but I don't think it will make a difference in real life. */
+      if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
+	  vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
+	vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
+
+    }
+  _rl_keymap = vi_replace_map;
+  return (0);
+}
+
+#if 0
+/* Try to complete the word we are standing on or the word that ends with
+   the previous character.  A space matches everything.  Word delimiters are
+   space and ;. */
+rl_vi_possible_completions()
+{
+  int save_pos = rl_point;
+
+  if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
+    {
+      while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
+	     rl_line_buffer[rl_point] != ';')
+	rl_point++;
+    }
+  else if (rl_line_buffer[rl_point - 1] == ';')
+    {
+      ding ();
+      return (0);
+    }
+
+  rl_possible_completions ();
+  rl_point = save_pos;
+
+  return (0);
+}
+#endif
+
+#if defined (STATIC_MALLOC)
+
+/* **************************************************************** */
+/*								    */
+/*			xmalloc and xrealloc ()		     	    */
+/*								    */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+  return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)xmalloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ();
+
+  return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+  fprintf (stderr, "readline: Out of virtual memory!\n");
+  abort ();
+}
+#endif /* STATIC_MALLOC */
+
+#endif /* VI_MODE */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readline/xmalloc.c	Tue Sep 19 07:21:00 1995 +0000
@@ -0,0 +1,78 @@
+/* xmalloc.c -- safe versions of malloc and realloc */
+
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+
+   This file is part of GNU Readline, a library for reading lines
+   of text with interactive input and history editing.
+
+   Readline is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 1, or (at your option) any
+   later version.
+
+   Readline is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if defined (ALREADY_HAVE_XMALLOC)
+#else
+#include <stdio.h>
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+static void memory_error_and_abort ();
+
+/* **************************************************************** */
+/*								    */
+/*		   Memory Allocation and Deallocation.		    */
+/*								    */
+/* **************************************************************** */
+
+/* Return a pointer to free()able block of memory large enough
+   to hold BYTES number of bytes.  If the memory cannot be allocated,
+   print an error message and abort. */
+char *
+xmalloc (bytes)
+     int bytes;
+{
+  char *temp = (char *)malloc (bytes);
+
+  if (!temp)
+    memory_error_and_abort ("xmalloc");
+  return (temp);
+}
+
+char *
+xrealloc (pointer, bytes)
+     char *pointer;
+     int bytes;
+{
+  char *temp;
+
+  if (!pointer)
+    temp = (char *)malloc (bytes);
+  else
+    temp = (char *)realloc (pointer, bytes);
+
+  if (!temp)
+    memory_error_and_abort ("xrealloc");
+  return (temp);
+}
+
+static void
+memory_error_and_abort (fname)
+     char *fname;
+{
+  fprintf (stderr, "%s: Out of virtual memory!\n", fname);
+  abort ();
+}
+#endif /* !ALREADY_HAVE_XMALLOC */