xref: /openbsd-src/gnu/lib/libreadline/bind.c (revision 9704b281e65e1189747652d0ba55eee892cff5f7)
11acd27e7Smillert /* bind.c -- key binding and startup file support for the readline library. */
21acd27e7Smillert 
31acd27e7Smillert /* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
41acd27e7Smillert 
51acd27e7Smillert    This file is part of the GNU Readline Library, a library for
61acd27e7Smillert    reading lines of text with interactive input and history editing.
71acd27e7Smillert 
81acd27e7Smillert    The GNU Readline Library is free software; you can redistribute it
91acd27e7Smillert    and/or modify it under the terms of the GNU General Public License
101acd27e7Smillert    as published by the Free Software Foundation; either version 2, or
111acd27e7Smillert    (at your option) any later version.
121acd27e7Smillert 
131acd27e7Smillert    The GNU Readline Library is distributed in the hope that it will be
141acd27e7Smillert    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
151acd27e7Smillert    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161acd27e7Smillert    GNU General Public License for more details.
171acd27e7Smillert 
181acd27e7Smillert    The GNU General Public License is often shipped with GNU software, and
191acd27e7Smillert    is generally kept in a file called COPYING or LICENSE.  If you do not
201acd27e7Smillert    have a copy of the license, write to the Free Software Foundation,
211acd27e7Smillert    59 Temple Place, Suite 330, Boston, MA 02111 USA. */
221acd27e7Smillert #define READLINE_LIBRARY
231acd27e7Smillert 
241acd27e7Smillert #if defined (HAVE_CONFIG_H)
251acd27e7Smillert #  include <config.h>
261acd27e7Smillert #endif
271acd27e7Smillert 
281acd27e7Smillert #include <stdio.h>
291acd27e7Smillert #include <sys/types.h>
301acd27e7Smillert #include <fcntl.h>
311acd27e7Smillert #if defined (HAVE_SYS_FILE_H)
321acd27e7Smillert #  include <sys/file.h>
331acd27e7Smillert #endif /* HAVE_SYS_FILE_H */
341acd27e7Smillert 
351acd27e7Smillert #if defined (HAVE_UNISTD_H)
361acd27e7Smillert #  include <unistd.h>
371acd27e7Smillert #endif /* HAVE_UNISTD_H */
381acd27e7Smillert 
391acd27e7Smillert #if defined (HAVE_STDLIB_H)
401acd27e7Smillert #  include <stdlib.h>
411acd27e7Smillert #else
421acd27e7Smillert #  include "ansi_stdlib.h"
431acd27e7Smillert #endif /* HAVE_STDLIB_H */
441acd27e7Smillert 
451acd27e7Smillert #include <errno.h>
461acd27e7Smillert 
471acd27e7Smillert #if !defined (errno)
481acd27e7Smillert extern int errno;
491acd27e7Smillert #endif /* !errno */
501acd27e7Smillert 
511acd27e7Smillert #include "posixstat.h"
521acd27e7Smillert 
531acd27e7Smillert /* System-specific feature definitions and include files. */
541acd27e7Smillert #include "rldefs.h"
551acd27e7Smillert 
561acd27e7Smillert /* Some standard library routines. */
571acd27e7Smillert #include "readline.h"
581acd27e7Smillert #include "history.h"
591acd27e7Smillert 
601acd27e7Smillert #include "rlprivate.h"
611acd27e7Smillert #include "rlshell.h"
621acd27e7Smillert #include "xmalloc.h"
631acd27e7Smillert 
641acd27e7Smillert #if !defined (strchr) && !defined (__STDC__)
651acd27e7Smillert extern char *strchr (), *strrchr ();
661acd27e7Smillert #endif /* !strchr && !__STDC__ */
671acd27e7Smillert 
681acd27e7Smillert /* Variables exported by this file. */
691acd27e7Smillert Keymap rl_binding_keymap;
701acd27e7Smillert 
71af70c2dfSkettenis static char *_rl_read_file PARAMS((char *, size_t *));
72af70c2dfSkettenis static void _rl_init_file_error PARAMS((const char *));
73af70c2dfSkettenis static int _rl_read_init_file PARAMS((const char *, int));
74af70c2dfSkettenis static int glean_key_from_name PARAMS((char *));
75af70c2dfSkettenis static int substring_member_of_array PARAMS((char *, const char **));
761acd27e7Smillert 
771acd27e7Smillert static int currently_reading_init_file;
781acd27e7Smillert 
791acd27e7Smillert /* used only in this file */
801acd27e7Smillert static int _rl_prefer_visible_bell = 1;
811acd27e7Smillert 
821acd27e7Smillert /* **************************************************************** */
831acd27e7Smillert /*								    */
841acd27e7Smillert /*			Binding keys				    */
851acd27e7Smillert /*								    */
861acd27e7Smillert /* **************************************************************** */
871acd27e7Smillert 
88af70c2dfSkettenis /* rl_add_defun (char *name, rl_command_func_t *function, int key)
891acd27e7Smillert    Add NAME to the list of named functions.  Make FUNCTION be the function
901acd27e7Smillert    that gets called.  If KEY is not -1, then bind it. */
911acd27e7Smillert int
rl_add_defun(name,function,key)921acd27e7Smillert rl_add_defun (name, function, key)
93af70c2dfSkettenis      const char *name;
94af70c2dfSkettenis      rl_command_func_t *function;
951acd27e7Smillert      int key;
961acd27e7Smillert {
971acd27e7Smillert   if (key != -1)
981acd27e7Smillert     rl_bind_key (key, function);
991acd27e7Smillert   rl_add_funmap_entry (name, function);
1001acd27e7Smillert   return 0;
1011acd27e7Smillert }
1021acd27e7Smillert 
1031acd27e7Smillert /* Bind KEY to FUNCTION.  Returns non-zero if KEY is out of range. */
1041acd27e7Smillert int
rl_bind_key(key,function)1051acd27e7Smillert rl_bind_key (key, function)
1061acd27e7Smillert      int key;
107af70c2dfSkettenis      rl_command_func_t *function;
1081acd27e7Smillert {
1091acd27e7Smillert   if (key < 0)
1101acd27e7Smillert     return (key);
1111acd27e7Smillert 
1121acd27e7Smillert   if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
1131acd27e7Smillert     {
1141acd27e7Smillert       if (_rl_keymap[ESC].type == ISKMAP)
1151acd27e7Smillert 	{
1161acd27e7Smillert 	  Keymap escmap;
1171acd27e7Smillert 
1181acd27e7Smillert 	  escmap = FUNCTION_TO_KEYMAP (_rl_keymap, ESC);
1191acd27e7Smillert 	  key = UNMETA (key);
1201acd27e7Smillert 	  escmap[key].type = ISFUNC;
1211acd27e7Smillert 	  escmap[key].function = function;
1221acd27e7Smillert 	  return (0);
1231acd27e7Smillert 	}
1241acd27e7Smillert       return (key);
1251acd27e7Smillert     }
1261acd27e7Smillert 
1271acd27e7Smillert   _rl_keymap[key].type = ISFUNC;
1281acd27e7Smillert   _rl_keymap[key].function = function;
1291acd27e7Smillert   rl_binding_keymap = _rl_keymap;
1301acd27e7Smillert   return (0);
1311acd27e7Smillert }
1321acd27e7Smillert 
1331acd27e7Smillert /* Bind KEY to FUNCTION in MAP.  Returns non-zero in case of invalid
1341acd27e7Smillert    KEY. */
1351acd27e7Smillert int
rl_bind_key_in_map(key,function,map)1361acd27e7Smillert rl_bind_key_in_map (key, function, map)
1371acd27e7Smillert      int key;
138af70c2dfSkettenis      rl_command_func_t *function;
1391acd27e7Smillert      Keymap map;
1401acd27e7Smillert {
1411acd27e7Smillert   int result;
1421acd27e7Smillert   Keymap oldmap;
1431acd27e7Smillert 
1441acd27e7Smillert   oldmap = _rl_keymap;
1451acd27e7Smillert   _rl_keymap = map;
1461acd27e7Smillert   result = rl_bind_key (key, function);
1471acd27e7Smillert   _rl_keymap = oldmap;
1481acd27e7Smillert   return (result);
1491acd27e7Smillert }
1501acd27e7Smillert 
1511acd27e7Smillert /* Make KEY do nothing in the currently selected keymap.
1521acd27e7Smillert    Returns non-zero in case of error. */
1531acd27e7Smillert int
rl_unbind_key(key)1541acd27e7Smillert rl_unbind_key (key)
1551acd27e7Smillert      int key;
1561acd27e7Smillert {
157af70c2dfSkettenis   return (rl_bind_key (key, (rl_command_func_t *)NULL));
1581acd27e7Smillert }
1591acd27e7Smillert 
1601acd27e7Smillert /* Make KEY do nothing in MAP.
1611acd27e7Smillert    Returns non-zero in case of error. */
1621acd27e7Smillert int
rl_unbind_key_in_map(key,map)1631acd27e7Smillert rl_unbind_key_in_map (key, map)
1641acd27e7Smillert      int key;
1651acd27e7Smillert      Keymap map;
1661acd27e7Smillert {
167af70c2dfSkettenis   return (rl_bind_key_in_map (key, (rl_command_func_t *)NULL, map));
1681acd27e7Smillert }
1691acd27e7Smillert 
1701acd27e7Smillert /* Unbind all keys bound to FUNCTION in MAP. */
1711acd27e7Smillert int
rl_unbind_function_in_map(func,map)1721acd27e7Smillert rl_unbind_function_in_map (func, map)
173af70c2dfSkettenis      rl_command_func_t *func;
1741acd27e7Smillert      Keymap map;
1751acd27e7Smillert {
1761acd27e7Smillert   register int i, rval;
1771acd27e7Smillert 
1781acd27e7Smillert   for (i = rval = 0; i < KEYMAP_SIZE; i++)
1791acd27e7Smillert     {
1801acd27e7Smillert       if (map[i].type == ISFUNC && map[i].function == func)
1811acd27e7Smillert 	{
182af70c2dfSkettenis 	  map[i].function = (rl_command_func_t *)NULL;
1831acd27e7Smillert 	  rval = 1;
1841acd27e7Smillert 	}
1851acd27e7Smillert     }
1861acd27e7Smillert   return rval;
1871acd27e7Smillert }
1881acd27e7Smillert 
1891acd27e7Smillert int
rl_unbind_command_in_map(command,map)1901acd27e7Smillert rl_unbind_command_in_map (command, map)
191af70c2dfSkettenis      const char *command;
1921acd27e7Smillert      Keymap map;
1931acd27e7Smillert {
194af70c2dfSkettenis   rl_command_func_t *func;
1951acd27e7Smillert 
1961acd27e7Smillert   func = rl_named_function (command);
1971acd27e7Smillert   if (func == 0)
1981acd27e7Smillert     return 0;
1991acd27e7Smillert   return (rl_unbind_function_in_map (func, map));
2001acd27e7Smillert }
2011acd27e7Smillert 
2021acd27e7Smillert /* Bind the key sequence represented by the string KEYSEQ to
2031acd27e7Smillert    FUNCTION.  This makes new keymaps as necessary.  The initial
2041acd27e7Smillert    place to do bindings is in MAP. */
2051acd27e7Smillert int
rl_set_key(keyseq,function,map)2061acd27e7Smillert rl_set_key (keyseq, function, map)
207af70c2dfSkettenis      const char *keyseq;
208af70c2dfSkettenis      rl_command_func_t *function;
2091acd27e7Smillert      Keymap map;
2101acd27e7Smillert {
2111acd27e7Smillert   return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
2121acd27e7Smillert }
2131acd27e7Smillert 
2141acd27e7Smillert /* Bind the key sequence represented by the string KEYSEQ to
2151acd27e7Smillert    the string of characters MACRO.  This makes new keymaps as
2161acd27e7Smillert    necessary.  The initial place to do bindings is in MAP. */
2171acd27e7Smillert int
rl_macro_bind(keyseq,macro,map)2181acd27e7Smillert rl_macro_bind (keyseq, macro, map)
219af70c2dfSkettenis      const char *keyseq, *macro;
2201acd27e7Smillert      Keymap map;
2211acd27e7Smillert {
2221acd27e7Smillert   char *macro_keys;
2231acd27e7Smillert   int macro_keys_len;
2241acd27e7Smillert 
2251acd27e7Smillert   macro_keys = (char *)xmalloc ((2 * strlen (macro)) + 1);
2261acd27e7Smillert 
2271acd27e7Smillert   if (rl_translate_keyseq (macro, macro_keys, &macro_keys_len))
2281acd27e7Smillert     {
2291acd27e7Smillert       free (macro_keys);
2301acd27e7Smillert       return -1;
2311acd27e7Smillert     }
2321acd27e7Smillert   rl_generic_bind (ISMACR, keyseq, macro_keys, map);
2331acd27e7Smillert   return 0;
2341acd27e7Smillert }
2351acd27e7Smillert 
2361acd27e7Smillert /* Bind the key sequence represented by the string KEYSEQ to
2371acd27e7Smillert    the arbitrary pointer DATA.  TYPE says what kind of data is
2381acd27e7Smillert    pointed to by DATA, right now this can be a function (ISFUNC),
2391acd27e7Smillert    a macro (ISMACR), or a keymap (ISKMAP).  This makes new keymaps
2401acd27e7Smillert    as necessary.  The initial place to do bindings is in MAP. */
2411acd27e7Smillert int
rl_generic_bind(type,keyseq,data,map)2421acd27e7Smillert rl_generic_bind (type, keyseq, data, map)
2431acd27e7Smillert      int type;
244af70c2dfSkettenis      const char *keyseq;
245af70c2dfSkettenis      char *data;
2461acd27e7Smillert      Keymap map;
2471acd27e7Smillert {
2481acd27e7Smillert   char *keys;
2491acd27e7Smillert   int keys_len;
2501acd27e7Smillert   register int i;
251af70c2dfSkettenis   KEYMAP_ENTRY k;
252af70c2dfSkettenis 
253af70c2dfSkettenis   k.function = 0;
2541acd27e7Smillert 
2551acd27e7Smillert   /* If no keys to bind to, exit right away. */
2561acd27e7Smillert   if (!keyseq || !*keyseq)
2571acd27e7Smillert     {
2581acd27e7Smillert       if (type == ISMACR)
2591acd27e7Smillert 	free (data);
2601acd27e7Smillert       return -1;
2611acd27e7Smillert     }
2621acd27e7Smillert 
263af70c2dfSkettenis   keys = (char *)xmalloc (1 + (2 * strlen (keyseq)));
2641acd27e7Smillert 
2651acd27e7Smillert   /* Translate the ASCII representation of KEYSEQ into an array of
2661acd27e7Smillert      characters.  Stuff the characters into KEYS, and the length of
2671acd27e7Smillert      KEYS into KEYS_LEN. */
2681acd27e7Smillert   if (rl_translate_keyseq (keyseq, keys, &keys_len))
2691acd27e7Smillert     {
2701acd27e7Smillert       free (keys);
2711acd27e7Smillert       return -1;
2721acd27e7Smillert     }
2731acd27e7Smillert 
2741acd27e7Smillert   /* Bind keys, making new keymaps as necessary. */
2751acd27e7Smillert   for (i = 0; i < keys_len; i++)
2761acd27e7Smillert     {
277af70c2dfSkettenis       unsigned char uc = keys[i];
278af70c2dfSkettenis       int ic;
279af70c2dfSkettenis 
280af70c2dfSkettenis       ic = uc;
281af70c2dfSkettenis       if (ic < 0 || ic >= KEYMAP_SIZE)
282af70c2dfSkettenis 	return -1;
2831acd27e7Smillert 
2841acd27e7Smillert       if (_rl_convert_meta_chars_to_ascii && META_CHAR (ic))
2851acd27e7Smillert 	{
2861acd27e7Smillert 	  ic = UNMETA (ic);
2871acd27e7Smillert 	  if (map[ESC].type == ISKMAP)
2881acd27e7Smillert 	    map = FUNCTION_TO_KEYMAP (map, ESC);
2891acd27e7Smillert 	}
2901acd27e7Smillert 
2911acd27e7Smillert       if ((i + 1) < keys_len)
2921acd27e7Smillert 	{
2931acd27e7Smillert 	  if (map[ic].type != ISKMAP)
2941acd27e7Smillert 	    {
295af70c2dfSkettenis 	      /* We allow subsequences of keys.  If a keymap is being
296af70c2dfSkettenis 		 created that will `shadow' an existing function or macro
297af70c2dfSkettenis 		 key binding, we save that keybinding into the ANYOTHERKEY
298af70c2dfSkettenis 		 index in the new map.  The dispatch code will look there
299af70c2dfSkettenis 		 to find the function to execute if the subsequence is not
300af70c2dfSkettenis 		 matched.  ANYOTHERKEY was chosen to be greater than
301af70c2dfSkettenis 		 UCHAR_MAX. */
302af70c2dfSkettenis 	      k = map[ic];
3031acd27e7Smillert 
3041acd27e7Smillert 	      map[ic].type = ISKMAP;
3051acd27e7Smillert 	      map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap());
3061acd27e7Smillert 	    }
3071acd27e7Smillert 	  map = FUNCTION_TO_KEYMAP (map, ic);
308af70c2dfSkettenis 	  /* The dispatch code will return this function if no matching
309af70c2dfSkettenis 	     key sequence is found in the keymap.  This (with a little
310af70c2dfSkettenis 	     help from the dispatch code in readline.c) allows `a' to be
311af70c2dfSkettenis 	     mapped to something, `abc' to be mapped to something else,
312af70c2dfSkettenis 	     and the function bound  to `a' to be executed when the user
313af70c2dfSkettenis 	     types `abx', leaving `bx' in the input queue. */
314af70c2dfSkettenis 	  if (k.function && ((k.type == ISFUNC && k.function != rl_do_lowercase_version) || k.type == ISMACR))
315af70c2dfSkettenis 	    {
316af70c2dfSkettenis 	      map[ANYOTHERKEY] = k;
317af70c2dfSkettenis 	      k.function = 0;
318af70c2dfSkettenis 	    }
3191acd27e7Smillert 	}
3201acd27e7Smillert       else
3211acd27e7Smillert 	{
3221acd27e7Smillert 	  if (map[ic].type == ISMACR)
3231acd27e7Smillert 	    free ((char *)map[ic].function);
324af70c2dfSkettenis 	  else if (map[ic].type == ISKMAP)
325af70c2dfSkettenis 	    {
326af70c2dfSkettenis 	      map = FUNCTION_TO_KEYMAP (map, ic);
327af70c2dfSkettenis 	      ic = ANYOTHERKEY;
328af70c2dfSkettenis 	    }
3291acd27e7Smillert 
3301acd27e7Smillert 	  map[ic].function = KEYMAP_TO_FUNCTION (data);
3311acd27e7Smillert 	  map[ic].type = type;
3321acd27e7Smillert 	}
3331acd27e7Smillert 
3341acd27e7Smillert       rl_binding_keymap = map;
3351acd27e7Smillert     }
3361acd27e7Smillert   free (keys);
3371acd27e7Smillert   return 0;
3381acd27e7Smillert }
3391acd27e7Smillert 
3401acd27e7Smillert /* Translate the ASCII representation of SEQ, stuffing the values into ARRAY,
3411acd27e7Smillert    an array of characters.  LEN gets the final length of ARRAY.  Return
3421acd27e7Smillert    non-zero if there was an error parsing SEQ. */
3431acd27e7Smillert int
rl_translate_keyseq(seq,array,len)3441acd27e7Smillert rl_translate_keyseq (seq, array, len)
345af70c2dfSkettenis      const char *seq;
346af70c2dfSkettenis      char *array;
3471acd27e7Smillert      int *len;
3481acd27e7Smillert {
3491acd27e7Smillert   register int i, c, l, temp;
3501acd27e7Smillert 
351*af1e7b8cSkrw   for (i = l = 0; (c = seq[i]); i++)
3521acd27e7Smillert     {
3531acd27e7Smillert       if (c == '\\')
3541acd27e7Smillert 	{
3551acd27e7Smillert 	  c = seq[++i];
3561acd27e7Smillert 
3571acd27e7Smillert 	  if (c == 0)
3581acd27e7Smillert 	    break;
3591acd27e7Smillert 
3601acd27e7Smillert 	  /* Handle \C- and \M- prefixes. */
3611acd27e7Smillert 	  if ((c == 'C' || c == 'M') && seq[i + 1] == '-')
3621acd27e7Smillert 	    {
3631acd27e7Smillert 	      /* Handle special case of backwards define. */
3641acd27e7Smillert 	      if (strncmp (&seq[i], "C-\\M-", 5) == 0)
3651acd27e7Smillert 		{
366af70c2dfSkettenis 		  array[l++] = ESC;	/* ESC is meta-prefix */
3671acd27e7Smillert 		  i += 5;
3681acd27e7Smillert 		  array[l++] = CTRL (_rl_to_upper (seq[i]));
3691acd27e7Smillert 		  if (seq[i] == '\0')
3701acd27e7Smillert 		    i--;
3711acd27e7Smillert 		}
3721acd27e7Smillert 	      else if (c == 'M')
3731acd27e7Smillert 		{
3741acd27e7Smillert 		  i++;
375af70c2dfSkettenis 		  array[l++] = ESC;	/* ESC is meta-prefix */
3761acd27e7Smillert 		}
3771acd27e7Smillert 	      else if (c == 'C')
3781acd27e7Smillert 		{
3791acd27e7Smillert 		  i += 2;
3801acd27e7Smillert 		  /* Special hack for C-?... */
3811acd27e7Smillert 		  array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
3821acd27e7Smillert 		}
3831acd27e7Smillert 	      continue;
3841acd27e7Smillert 	    }
3851acd27e7Smillert 
3861acd27e7Smillert 	  /* Translate other backslash-escaped characters.  These are the
3871acd27e7Smillert 	     same escape sequences that bash's `echo' and `printf' builtins
3881acd27e7Smillert 	     handle, with the addition of \d -> RUBOUT.  A backslash
3891acd27e7Smillert 	     preceding a character that is not special is stripped. */
3901acd27e7Smillert 	  switch (c)
3911acd27e7Smillert 	    {
3921acd27e7Smillert 	    case 'a':
3931acd27e7Smillert 	      array[l++] = '\007';
3941acd27e7Smillert 	      break;
3951acd27e7Smillert 	    case 'b':
3961acd27e7Smillert 	      array[l++] = '\b';
3971acd27e7Smillert 	      break;
3981acd27e7Smillert 	    case 'd':
3991acd27e7Smillert 	      array[l++] = RUBOUT;	/* readline-specific */
4001acd27e7Smillert 	      break;
4011acd27e7Smillert 	    case 'e':
4021acd27e7Smillert 	      array[l++] = ESC;
4031acd27e7Smillert 	      break;
4041acd27e7Smillert 	    case 'f':
4051acd27e7Smillert 	      array[l++] = '\f';
4061acd27e7Smillert 	      break;
4071acd27e7Smillert 	    case 'n':
4081acd27e7Smillert 	      array[l++] = NEWLINE;
4091acd27e7Smillert 	      break;
4101acd27e7Smillert 	    case 'r':
4111acd27e7Smillert 	      array[l++] = RETURN;
4121acd27e7Smillert 	      break;
4131acd27e7Smillert 	    case 't':
4141acd27e7Smillert 	      array[l++] = TAB;
4151acd27e7Smillert 	      break;
4161acd27e7Smillert 	    case 'v':
4171acd27e7Smillert 	      array[l++] = 0x0B;
4181acd27e7Smillert 	      break;
4191acd27e7Smillert 	    case '\\':
4201acd27e7Smillert 	      array[l++] = '\\';
4211acd27e7Smillert 	      break;
4221acd27e7Smillert 	    case '0': case '1': case '2': case '3':
4231acd27e7Smillert 	    case '4': case '5': case '6': case '7':
4241acd27e7Smillert 	      i++;
4251acd27e7Smillert 	      for (temp = 2, c -= '0'; ISOCTAL (seq[i]) && temp--; i++)
4261acd27e7Smillert 	        c = (c * 8) + OCTVALUE (seq[i]);
4271acd27e7Smillert 	      i--;	/* auto-increment in for loop */
428af70c2dfSkettenis 	      array[l++] = c & largest_char;
4291acd27e7Smillert 	      break;
4301acd27e7Smillert 	    case 'x':
4311acd27e7Smillert 	      i++;
432af70c2dfSkettenis 	      for (temp = 2, c = 0; ISXDIGIT ((unsigned char)seq[i]) && temp--; i++)
4331acd27e7Smillert 	        c = (c * 16) + HEXVALUE (seq[i]);
434af70c2dfSkettenis 	      if (temp == 2)
4351acd27e7Smillert 	        c = 'x';
4361acd27e7Smillert 	      i--;	/* auto-increment in for loop */
437af70c2dfSkettenis 	      array[l++] = c & largest_char;
4381acd27e7Smillert 	      break;
4391acd27e7Smillert 	    default:	/* backslashes before non-special chars just add the char */
4401acd27e7Smillert 	      array[l++] = c;
4411acd27e7Smillert 	      break;	/* the backslash is stripped */
4421acd27e7Smillert 	    }
4431acd27e7Smillert 	  continue;
4441acd27e7Smillert 	}
4451acd27e7Smillert 
4461acd27e7Smillert       array[l++] = c;
4471acd27e7Smillert     }
4481acd27e7Smillert 
4491acd27e7Smillert   *len = l;
4501acd27e7Smillert   array[l] = '\0';
4511acd27e7Smillert   return (0);
4521acd27e7Smillert }
4531acd27e7Smillert 
4541acd27e7Smillert char *
rl_untranslate_keyseq(seq)4551acd27e7Smillert rl_untranslate_keyseq (seq)
4561acd27e7Smillert      int seq;
4571acd27e7Smillert {
4581acd27e7Smillert   static char kseq[16];
4591acd27e7Smillert   int i, c;
4601acd27e7Smillert 
4611acd27e7Smillert   i = 0;
4621acd27e7Smillert   c = seq;
4631acd27e7Smillert   if (META_CHAR (c))
4641acd27e7Smillert     {
4651acd27e7Smillert       kseq[i++] = '\\';
4661acd27e7Smillert       kseq[i++] = 'M';
4671acd27e7Smillert       kseq[i++] = '-';
4681acd27e7Smillert       c = UNMETA (c);
4691acd27e7Smillert     }
4701acd27e7Smillert   else if (CTRL_CHAR (c))
4711acd27e7Smillert     {
4721acd27e7Smillert       kseq[i++] = '\\';
4731acd27e7Smillert       kseq[i++] = 'C';
4741acd27e7Smillert       kseq[i++] = '-';
4751acd27e7Smillert       c = _rl_to_lower (UNCTRL (c));
4761acd27e7Smillert     }
4771acd27e7Smillert   else if (c == RUBOUT)
4781acd27e7Smillert     {
4791acd27e7Smillert       kseq[i++] = '\\';
4801acd27e7Smillert       kseq[i++] = 'C';
4811acd27e7Smillert       kseq[i++] = '-';
4821acd27e7Smillert       c = '?';
4831acd27e7Smillert     }
4841acd27e7Smillert 
4851acd27e7Smillert   if (c == ESC)
4861acd27e7Smillert     {
4871acd27e7Smillert       kseq[i++] = '\\';
4881acd27e7Smillert       c = 'e';
4891acd27e7Smillert     }
4901acd27e7Smillert   else if (c == '\\' || c == '"')
4911acd27e7Smillert     {
4921acd27e7Smillert       kseq[i++] = '\\';
4931acd27e7Smillert     }
4941acd27e7Smillert 
4951acd27e7Smillert   kseq[i++] = (unsigned char) c;
4961acd27e7Smillert   kseq[i] = '\0';
4971acd27e7Smillert   return kseq;
4981acd27e7Smillert }
4991acd27e7Smillert 
5001acd27e7Smillert static char *
_rl_untranslate_macro_value(seq)5011acd27e7Smillert _rl_untranslate_macro_value (seq)
5021acd27e7Smillert      char *seq;
5031acd27e7Smillert {
5041acd27e7Smillert   char *ret, *r, *s;
5051acd27e7Smillert   int c;
5061acd27e7Smillert 
507af70c2dfSkettenis   r = ret = (char *)xmalloc (7 * strlen (seq) + 1);
5081acd27e7Smillert   for (s = seq; *s; s++)
5091acd27e7Smillert     {
5101acd27e7Smillert       c = *s;
5111acd27e7Smillert       if (META_CHAR (c))
5121acd27e7Smillert 	{
5131acd27e7Smillert 	  *r++ = '\\';
5141acd27e7Smillert 	  *r++ = 'M';
5151acd27e7Smillert 	  *r++ = '-';
5161acd27e7Smillert 	  c = UNMETA (c);
5171acd27e7Smillert 	}
5181acd27e7Smillert       else if (CTRL_CHAR (c) && c != ESC)
5191acd27e7Smillert 	{
5201acd27e7Smillert 	  *r++ = '\\';
5211acd27e7Smillert 	  *r++ = 'C';
5221acd27e7Smillert 	  *r++ = '-';
5231acd27e7Smillert 	  c = _rl_to_lower (UNCTRL (c));
5241acd27e7Smillert 	}
5251acd27e7Smillert       else if (c == RUBOUT)
5261acd27e7Smillert 	{
5271acd27e7Smillert 	  *r++ = '\\';
5281acd27e7Smillert 	  *r++ = 'C';
5291acd27e7Smillert 	  *r++ = '-';
5301acd27e7Smillert 	  c = '?';
5311acd27e7Smillert 	}
5321acd27e7Smillert 
5331acd27e7Smillert       if (c == ESC)
5341acd27e7Smillert 	{
5351acd27e7Smillert 	  *r++ = '\\';
5361acd27e7Smillert 	  c = 'e';
5371acd27e7Smillert 	}
5381acd27e7Smillert       else if (c == '\\' || c == '"')
5391acd27e7Smillert 	*r++ = '\\';
5401acd27e7Smillert 
5411acd27e7Smillert       *r++ = (unsigned char)c;
5421acd27e7Smillert     }
5431acd27e7Smillert   *r = '\0';
5441acd27e7Smillert   return ret;
5451acd27e7Smillert }
5461acd27e7Smillert 
5471acd27e7Smillert /* Return a pointer to the function that STRING represents.
5481acd27e7Smillert    If STRING doesn't have a matching function, then a NULL pointer
5491acd27e7Smillert    is returned. */
550af70c2dfSkettenis rl_command_func_t *
rl_named_function(string)5511acd27e7Smillert rl_named_function (string)
552af70c2dfSkettenis      const char *string;
5531acd27e7Smillert {
5541acd27e7Smillert   register int i;
5551acd27e7Smillert 
5561acd27e7Smillert   rl_initialize_funmap ();
5571acd27e7Smillert 
5581acd27e7Smillert   for (i = 0; funmap[i]; i++)
5591acd27e7Smillert     if (_rl_stricmp (funmap[i]->name, string) == 0)
5601acd27e7Smillert       return (funmap[i]->function);
561af70c2dfSkettenis   return ((rl_command_func_t *)NULL);
5621acd27e7Smillert }
5631acd27e7Smillert 
5641acd27e7Smillert /* Return the function (or macro) definition which would be invoked via
5651acd27e7Smillert    KEYSEQ if executed in MAP.  If MAP is NULL, then the current keymap is
5661acd27e7Smillert    used.  TYPE, if non-NULL, is a pointer to an int which will receive the
5671acd27e7Smillert    type of the object pointed to.  One of ISFUNC (function), ISKMAP (keymap),
5681acd27e7Smillert    or ISMACR (macro). */
569af70c2dfSkettenis rl_command_func_t *
rl_function_of_keyseq(keyseq,map,type)5701acd27e7Smillert rl_function_of_keyseq (keyseq, map, type)
571af70c2dfSkettenis      const char *keyseq;
5721acd27e7Smillert      Keymap map;
5731acd27e7Smillert      int *type;
5741acd27e7Smillert {
5751acd27e7Smillert   register int i;
5761acd27e7Smillert 
5771acd27e7Smillert   if (!map)
5781acd27e7Smillert     map = _rl_keymap;
5791acd27e7Smillert 
5801acd27e7Smillert   for (i = 0; keyseq && keyseq[i]; i++)
5811acd27e7Smillert     {
582af70c2dfSkettenis       unsigned char ic = keyseq[i];
5831acd27e7Smillert 
5841acd27e7Smillert       if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
5851acd27e7Smillert 	{
5861acd27e7Smillert 	  if (map[ESC].type != ISKMAP)
5871acd27e7Smillert 	    {
5881acd27e7Smillert 	      if (type)
5891acd27e7Smillert 		*type = map[ESC].type;
5901acd27e7Smillert 
5911acd27e7Smillert 	      return (map[ESC].function);
5921acd27e7Smillert 	    }
5931acd27e7Smillert 	  else
5941acd27e7Smillert 	    {
5951acd27e7Smillert 	      map = FUNCTION_TO_KEYMAP (map, ESC);
5961acd27e7Smillert 	      ic = UNMETA (ic);
5971acd27e7Smillert 	    }
5981acd27e7Smillert 	}
5991acd27e7Smillert 
6001acd27e7Smillert       if (map[ic].type == ISKMAP)
6011acd27e7Smillert 	{
6021acd27e7Smillert 	  /* If this is the last key in the key sequence, return the
6031acd27e7Smillert 	     map. */
6041acd27e7Smillert 	  if (!keyseq[i + 1])
6051acd27e7Smillert 	    {
6061acd27e7Smillert 	      if (type)
6071acd27e7Smillert 		*type = ISKMAP;
6081acd27e7Smillert 
6091acd27e7Smillert 	      return (map[ic].function);
6101acd27e7Smillert 	    }
6111acd27e7Smillert 	  else
6121acd27e7Smillert 	    map = FUNCTION_TO_KEYMAP (map, ic);
6131acd27e7Smillert 	}
6141acd27e7Smillert       else
6151acd27e7Smillert 	{
6161acd27e7Smillert 	  if (type)
6171acd27e7Smillert 	    *type = map[ic].type;
6181acd27e7Smillert 
6191acd27e7Smillert 	  return (map[ic].function);
6201acd27e7Smillert 	}
6211acd27e7Smillert     }
622af70c2dfSkettenis   return ((rl_command_func_t *) NULL);
6231acd27e7Smillert }
6241acd27e7Smillert 
6251acd27e7Smillert /* The last key bindings file read. */
6261acd27e7Smillert static char *last_readline_init_file = (char *)NULL;
6271acd27e7Smillert 
6281acd27e7Smillert /* The file we're currently reading key bindings from. */
629af70c2dfSkettenis static const char *current_readline_init_file;
6301acd27e7Smillert static int current_readline_init_include_level;
6311acd27e7Smillert static int current_readline_init_lineno;
6321acd27e7Smillert 
6331acd27e7Smillert /* Read FILENAME into a locally-allocated buffer and return the buffer.
6341acd27e7Smillert    The size of the buffer is returned in *SIZEP.  Returns NULL if any
6351acd27e7Smillert    errors were encountered. */
6361acd27e7Smillert static char *
_rl_read_file(filename,sizep)6371acd27e7Smillert _rl_read_file (filename, sizep)
6381acd27e7Smillert      char *filename;
6391acd27e7Smillert      size_t *sizep;
6401acd27e7Smillert {
6411acd27e7Smillert   struct stat finfo;
6421acd27e7Smillert   size_t file_size;
6431acd27e7Smillert   char *buffer;
6441acd27e7Smillert   int i, file;
6451acd27e7Smillert 
6461acd27e7Smillert   if ((stat (filename, &finfo) < 0) || (file = open (filename, O_RDONLY, 0666)) < 0)
6471acd27e7Smillert     return ((char *)NULL);
6481acd27e7Smillert 
6491acd27e7Smillert   file_size = (size_t)finfo.st_size;
6501acd27e7Smillert 
6511acd27e7Smillert   /* check for overflow on very large files */
6521acd27e7Smillert   if (file_size != finfo.st_size || file_size + 1 < file_size)
6531acd27e7Smillert     {
6541acd27e7Smillert       if (file >= 0)
6551acd27e7Smillert 	close (file);
6561acd27e7Smillert #if defined (EFBIG)
6571acd27e7Smillert       errno = EFBIG;
6581acd27e7Smillert #endif
6591acd27e7Smillert       return ((char *)NULL);
6601acd27e7Smillert     }
6611acd27e7Smillert 
6621acd27e7Smillert   /* Read the file into BUFFER. */
6631acd27e7Smillert   buffer = (char *)xmalloc (file_size + 1);
6641acd27e7Smillert   i = read (file, buffer, file_size);
6651acd27e7Smillert   close (file);
6661acd27e7Smillert 
6671acd27e7Smillert   if (i < 0)
6681acd27e7Smillert     {
6691acd27e7Smillert       free (buffer);
6701acd27e7Smillert       return ((char *)NULL);
6711acd27e7Smillert     }
6721acd27e7Smillert 
6731acd27e7Smillert   buffer[i] = '\0';
6741acd27e7Smillert   if (sizep)
6751acd27e7Smillert     *sizep = i;
6761acd27e7Smillert 
6771acd27e7Smillert   return (buffer);
6781acd27e7Smillert }
6791acd27e7Smillert 
6801acd27e7Smillert /* Re-read the current keybindings file. */
6811acd27e7Smillert int
rl_re_read_init_file(count,ignore)6821acd27e7Smillert rl_re_read_init_file (count, ignore)
6831acd27e7Smillert      int count, ignore;
6841acd27e7Smillert {
6851acd27e7Smillert   int r;
686af70c2dfSkettenis   r = rl_read_init_file ((const char *)NULL);
6871acd27e7Smillert   rl_set_keymap_from_edit_mode ();
6881acd27e7Smillert   return r;
6891acd27e7Smillert }
6901acd27e7Smillert 
6911acd27e7Smillert /* Do key bindings from a file.  If FILENAME is NULL it defaults
6921acd27e7Smillert    to the first non-null filename from this list:
6931acd27e7Smillert      1. the filename used for the previous call
6941acd27e7Smillert      2. the value of the shell variable `INPUTRC'
6951acd27e7Smillert      3. ~/.inputrc
6961acd27e7Smillert    If the file existed and could be opened and read, 0 is returned,
6971acd27e7Smillert    otherwise errno is returned. */
6981acd27e7Smillert int
rl_read_init_file(filename)6991acd27e7Smillert rl_read_init_file (filename)
700af70c2dfSkettenis      const char *filename;
7011acd27e7Smillert {
7021acd27e7Smillert   /* Default the filename. */
7031acd27e7Smillert   if (filename == 0)
7041acd27e7Smillert     {
7051acd27e7Smillert       filename = last_readline_init_file;
7061acd27e7Smillert       if (filename == 0)
707af70c2dfSkettenis         filename = sh_get_env_value ("INPUTRC");
70894bc1d69Smillert       if (filename == 0 || *filename == '\0')
7091acd27e7Smillert 	filename = DEFAULT_INPUTRC;
7101acd27e7Smillert     }
7111acd27e7Smillert 
7121acd27e7Smillert   if (*filename == 0)
7131acd27e7Smillert     filename = DEFAULT_INPUTRC;
7141acd27e7Smillert 
7151acd27e7Smillert #if defined (__MSDOS__)
7161acd27e7Smillert   if (_rl_read_init_file (filename, 0) == 0)
7171acd27e7Smillert     return 0;
7181acd27e7Smillert   filename = "~/_inputrc";
7191acd27e7Smillert #endif
7201acd27e7Smillert   return (_rl_read_init_file (filename, 0));
7211acd27e7Smillert }
7221acd27e7Smillert 
7231acd27e7Smillert static int
_rl_read_init_file(filename,include_level)7241acd27e7Smillert _rl_read_init_file (filename, include_level)
725af70c2dfSkettenis      const char *filename;
7261acd27e7Smillert      int include_level;
7271acd27e7Smillert {
7281acd27e7Smillert   register int i;
7291acd27e7Smillert   char *buffer, *openname, *line, *end;
7301acd27e7Smillert   size_t file_size;
7311acd27e7Smillert 
7321acd27e7Smillert   current_readline_init_file = filename;
7331acd27e7Smillert   current_readline_init_include_level = include_level;
7341acd27e7Smillert 
7351acd27e7Smillert   openname = tilde_expand (filename);
7361acd27e7Smillert   buffer = _rl_read_file (openname, &file_size);
7371acd27e7Smillert   free (openname);
7381acd27e7Smillert 
7391acd27e7Smillert   if (buffer == 0)
7401acd27e7Smillert     return (errno);
7411acd27e7Smillert 
7421acd27e7Smillert   if (include_level == 0 && filename != last_readline_init_file)
7431acd27e7Smillert     {
7441acd27e7Smillert       FREE (last_readline_init_file);
7451acd27e7Smillert       last_readline_init_file = savestring (filename);
7461acd27e7Smillert     }
7471acd27e7Smillert 
7481acd27e7Smillert   currently_reading_init_file = 1;
7491acd27e7Smillert 
7501acd27e7Smillert   /* Loop over the lines in the file.  Lines that start with `#' are
7511acd27e7Smillert      comments; all other lines are commands for readline initialization. */
7521acd27e7Smillert   current_readline_init_lineno = 1;
7531acd27e7Smillert   line = buffer;
7541acd27e7Smillert   end = buffer + file_size;
7551acd27e7Smillert   while (line < end)
7561acd27e7Smillert     {
7571acd27e7Smillert       /* Find the end of this line. */
7581acd27e7Smillert       for (i = 0; line + i != end && line[i] != '\n'; i++);
7591acd27e7Smillert 
760af70c2dfSkettenis #if defined (__CYGWIN__)
7611acd27e7Smillert       /* ``Be liberal in what you accept.'' */
7621acd27e7Smillert       if (line[i] == '\n' && line[i-1] == '\r')
7631acd27e7Smillert 	line[i - 1] = '\0';
7641acd27e7Smillert #endif
7651acd27e7Smillert 
7661acd27e7Smillert       /* Mark end of line. */
7671acd27e7Smillert       line[i] = '\0';
7681acd27e7Smillert 
7691acd27e7Smillert       /* Skip leading whitespace. */
7701acd27e7Smillert       while (*line && whitespace (*line))
7711acd27e7Smillert         {
7721acd27e7Smillert 	  line++;
7731acd27e7Smillert 	  i--;
7741acd27e7Smillert         }
7751acd27e7Smillert 
7761acd27e7Smillert       /* If the line is not a comment, then parse it. */
7771acd27e7Smillert       if (*line && *line != '#')
7781acd27e7Smillert 	rl_parse_and_bind (line);
7791acd27e7Smillert 
7801acd27e7Smillert       /* Move to the next line. */
7811acd27e7Smillert       line += i + 1;
7821acd27e7Smillert       current_readline_init_lineno++;
7831acd27e7Smillert     }
7841acd27e7Smillert 
7851acd27e7Smillert   free (buffer);
7861acd27e7Smillert   currently_reading_init_file = 0;
7871acd27e7Smillert   return (0);
7881acd27e7Smillert }
7891acd27e7Smillert 
7901acd27e7Smillert static void
_rl_init_file_error(msg)7911acd27e7Smillert _rl_init_file_error (msg)
792af70c2dfSkettenis      const char *msg;
7931acd27e7Smillert {
7941acd27e7Smillert   if (currently_reading_init_file)
7951acd27e7Smillert     fprintf (stderr, "readline: %s: line %d: %s\n", current_readline_init_file,
7961acd27e7Smillert 		     current_readline_init_lineno, msg);
7971acd27e7Smillert   else
7981acd27e7Smillert     fprintf (stderr, "readline: %s\n", msg);
7991acd27e7Smillert }
8001acd27e7Smillert 
8011acd27e7Smillert /* **************************************************************** */
8021acd27e7Smillert /*								    */
8031acd27e7Smillert /*			Parser Directives			    */
8041acd27e7Smillert /*								    */
8051acd27e7Smillert /* **************************************************************** */
8061acd27e7Smillert 
807af70c2dfSkettenis typedef int _rl_parser_func_t PARAMS((char *));
808af70c2dfSkettenis 
809af70c2dfSkettenis /* Things that mean `Control'. */
810af70c2dfSkettenis const char *_rl_possible_control_prefixes[] = {
811af70c2dfSkettenis   "Control-", "C-", "CTRL-", (const char *)NULL
812af70c2dfSkettenis };
813af70c2dfSkettenis 
814af70c2dfSkettenis const char *_rl_possible_meta_prefixes[] = {
815af70c2dfSkettenis   "Meta", "M-", (const char *)NULL
816af70c2dfSkettenis };
817af70c2dfSkettenis 
8181acd27e7Smillert /* Conditionals. */
8191acd27e7Smillert 
8201acd27e7Smillert /* Calling programs set this to have their argv[0]. */
821af70c2dfSkettenis const char *rl_readline_name = "other";
8221acd27e7Smillert 
8231acd27e7Smillert /* Stack of previous values of parsing_conditionalized_out. */
8241acd27e7Smillert static unsigned char *if_stack = (unsigned char *)NULL;
8251acd27e7Smillert static int if_stack_depth;
8261acd27e7Smillert static int if_stack_size;
8271acd27e7Smillert 
8281acd27e7Smillert /* Push _rl_parsing_conditionalized_out, and set parser state based
8291acd27e7Smillert    on ARGS. */
8301acd27e7Smillert static int
parser_if(args)8311acd27e7Smillert parser_if (args)
8321acd27e7Smillert      char *args;
8331acd27e7Smillert {
8341acd27e7Smillert   register int i;
8351acd27e7Smillert 
8361acd27e7Smillert   /* Push parser state. */
8371acd27e7Smillert   if (if_stack_depth + 1 >= if_stack_size)
8381acd27e7Smillert     {
8391acd27e7Smillert       if (!if_stack)
8401acd27e7Smillert 	if_stack = (unsigned char *)xmalloc (if_stack_size = 20);
8411acd27e7Smillert       else
8421acd27e7Smillert 	if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20);
8431acd27e7Smillert     }
8441acd27e7Smillert   if_stack[if_stack_depth++] = _rl_parsing_conditionalized_out;
8451acd27e7Smillert 
8461acd27e7Smillert   /* If parsing is turned off, then nothing can turn it back on except
8471acd27e7Smillert      for finding the matching endif.  In that case, return right now. */
8481acd27e7Smillert   if (_rl_parsing_conditionalized_out)
8491acd27e7Smillert     return 0;
8501acd27e7Smillert 
8511acd27e7Smillert   /* Isolate first argument. */
8521acd27e7Smillert   for (i = 0; args[i] && !whitespace (args[i]); i++);
8531acd27e7Smillert 
8541acd27e7Smillert   if (args[i])
8551acd27e7Smillert     args[i++] = '\0';
8561acd27e7Smillert 
8571acd27e7Smillert   /* Handle "$if term=foo" and "$if mode=emacs" constructs.  If this
8581acd27e7Smillert      isn't term=foo, or mode=emacs, then check to see if the first
8591acd27e7Smillert      word in ARGS is the same as the value stored in rl_readline_name. */
8601acd27e7Smillert   if (rl_terminal_name && _rl_strnicmp (args, "term=", 5) == 0)
8611acd27e7Smillert     {
8621acd27e7Smillert       char *tem, *tname;
8631acd27e7Smillert 
8641acd27e7Smillert       /* Terminals like "aaa-60" are equivalent to "aaa". */
8651acd27e7Smillert       tname = savestring (rl_terminal_name);
8661acd27e7Smillert       tem = strchr (tname, '-');
8671acd27e7Smillert       if (tem)
8681acd27e7Smillert 	*tem = '\0';
8691acd27e7Smillert 
8701acd27e7Smillert       /* Test the `long' and `short' forms of the terminal name so that
8711acd27e7Smillert 	 if someone has a `sun-cmd' and does not want to have bindings
8721acd27e7Smillert 	 that will be executed if the terminal is a `sun', they can put
8731acd27e7Smillert 	 `$if term=sun-cmd' into their .inputrc. */
8741acd27e7Smillert       _rl_parsing_conditionalized_out = _rl_stricmp (args + 5, tname) &&
8751acd27e7Smillert 					_rl_stricmp (args + 5, rl_terminal_name);
8761acd27e7Smillert       free (tname);
8771acd27e7Smillert     }
8781acd27e7Smillert #if defined (VI_MODE)
8791acd27e7Smillert   else if (_rl_strnicmp (args, "mode=", 5) == 0)
8801acd27e7Smillert     {
8811acd27e7Smillert       int mode;
8821acd27e7Smillert 
8831acd27e7Smillert       if (_rl_stricmp (args + 5, "emacs") == 0)
8841acd27e7Smillert 	mode = emacs_mode;
8851acd27e7Smillert       else if (_rl_stricmp (args + 5, "vi") == 0)
8861acd27e7Smillert 	mode = vi_mode;
8871acd27e7Smillert       else
8881acd27e7Smillert 	mode = no_mode;
8891acd27e7Smillert 
8901acd27e7Smillert       _rl_parsing_conditionalized_out = mode != rl_editing_mode;
8911acd27e7Smillert     }
8921acd27e7Smillert #endif /* VI_MODE */
8931acd27e7Smillert   /* Check to see if the first word in ARGS is the same as the
8941acd27e7Smillert      value stored in rl_readline_name. */
8951acd27e7Smillert   else if (_rl_stricmp (args, rl_readline_name) == 0)
8961acd27e7Smillert     _rl_parsing_conditionalized_out = 0;
8971acd27e7Smillert   else
8981acd27e7Smillert     _rl_parsing_conditionalized_out = 1;
8991acd27e7Smillert   return 0;
9001acd27e7Smillert }
9011acd27e7Smillert 
9021acd27e7Smillert /* Invert the current parser state if there is anything on the stack. */
9031acd27e7Smillert static int
parser_else(args)9041acd27e7Smillert parser_else (args)
9051acd27e7Smillert      char *args;
9061acd27e7Smillert {
9071acd27e7Smillert   register int i;
9081acd27e7Smillert 
9091acd27e7Smillert   if (if_stack_depth == 0)
9101acd27e7Smillert     {
9111acd27e7Smillert       _rl_init_file_error ("$else found without matching $if");
9121acd27e7Smillert       return 0;
9131acd27e7Smillert     }
9141acd27e7Smillert 
9151acd27e7Smillert   /* Check the previous (n - 1) levels of the stack to make sure that
9161acd27e7Smillert      we haven't previously turned off parsing. */
9171acd27e7Smillert   for (i = 0; i < if_stack_depth - 1; i++)
9181acd27e7Smillert     if (if_stack[i] == 1)
9191acd27e7Smillert       return 0;
9201acd27e7Smillert 
9211acd27e7Smillert   /* Invert the state of parsing if at top level. */
9221acd27e7Smillert   _rl_parsing_conditionalized_out = !_rl_parsing_conditionalized_out;
9231acd27e7Smillert   return 0;
9241acd27e7Smillert }
9251acd27e7Smillert 
9261acd27e7Smillert /* Terminate a conditional, popping the value of
9271acd27e7Smillert    _rl_parsing_conditionalized_out from the stack. */
9281acd27e7Smillert static int
parser_endif(args)9291acd27e7Smillert parser_endif (args)
9301acd27e7Smillert      char *args;
9311acd27e7Smillert {
9321acd27e7Smillert   if (if_stack_depth)
9331acd27e7Smillert     _rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
9341acd27e7Smillert   else
9351acd27e7Smillert     _rl_init_file_error ("$endif without matching $if");
9361acd27e7Smillert   return 0;
9371acd27e7Smillert }
9381acd27e7Smillert 
9391acd27e7Smillert static int
parser_include(args)9401acd27e7Smillert parser_include (args)
9411acd27e7Smillert      char *args;
9421acd27e7Smillert {
943af70c2dfSkettenis   const char *old_init_file;
944af70c2dfSkettenis   char *e;
9451acd27e7Smillert   int old_line_number, old_include_level, r;
9461acd27e7Smillert 
9471acd27e7Smillert   if (_rl_parsing_conditionalized_out)
9481acd27e7Smillert     return (0);
9491acd27e7Smillert 
9501acd27e7Smillert   old_init_file = current_readline_init_file;
9511acd27e7Smillert   old_line_number = current_readline_init_lineno;
9521acd27e7Smillert   old_include_level = current_readline_init_include_level;
9531acd27e7Smillert 
9541acd27e7Smillert   e = strchr (args, '\n');
9551acd27e7Smillert   if (e)
9561acd27e7Smillert     *e = '\0';
957af70c2dfSkettenis   r = _rl_read_init_file ((const char *)args, old_include_level + 1);
9581acd27e7Smillert 
9591acd27e7Smillert   current_readline_init_file = old_init_file;
9601acd27e7Smillert   current_readline_init_lineno = old_line_number;
9611acd27e7Smillert   current_readline_init_include_level = old_include_level;
9621acd27e7Smillert 
9631acd27e7Smillert   return r;
9641acd27e7Smillert }
9651acd27e7Smillert 
9661acd27e7Smillert /* Associate textual names with actual functions. */
9671acd27e7Smillert static struct {
968af70c2dfSkettenis   const char *name;
969af70c2dfSkettenis   _rl_parser_func_t *function;
9701acd27e7Smillert } parser_directives [] = {
9711acd27e7Smillert   { "if", parser_if },
9721acd27e7Smillert   { "endif", parser_endif },
9731acd27e7Smillert   { "else", parser_else },
9741acd27e7Smillert   { "include", parser_include },
975af70c2dfSkettenis   { (char *)0x0, (_rl_parser_func_t *)0x0 }
9761acd27e7Smillert };
9771acd27e7Smillert 
9781acd27e7Smillert /* Handle a parser directive.  STATEMENT is the line of the directive
9791acd27e7Smillert    without any leading `$'. */
9801acd27e7Smillert static int
handle_parser_directive(statement)9811acd27e7Smillert handle_parser_directive (statement)
9821acd27e7Smillert      char *statement;
9831acd27e7Smillert {
9841acd27e7Smillert   register int i;
9851acd27e7Smillert   char *directive, *args;
9861acd27e7Smillert 
9871acd27e7Smillert   /* Isolate the actual directive. */
9881acd27e7Smillert 
9891acd27e7Smillert   /* Skip whitespace. */
9901acd27e7Smillert   for (i = 0; whitespace (statement[i]); i++);
9911acd27e7Smillert 
9921acd27e7Smillert   directive = &statement[i];
9931acd27e7Smillert 
9941acd27e7Smillert   for (; statement[i] && !whitespace (statement[i]); i++);
9951acd27e7Smillert 
9961acd27e7Smillert   if (statement[i])
9971acd27e7Smillert     statement[i++] = '\0';
9981acd27e7Smillert 
9991acd27e7Smillert   for (; statement[i] && whitespace (statement[i]); i++);
10001acd27e7Smillert 
10011acd27e7Smillert   args = &statement[i];
10021acd27e7Smillert 
10031acd27e7Smillert   /* Lookup the command, and act on it. */
10041acd27e7Smillert   for (i = 0; parser_directives[i].name; i++)
10051acd27e7Smillert     if (_rl_stricmp (directive, parser_directives[i].name) == 0)
10061acd27e7Smillert       {
10071acd27e7Smillert 	(*parser_directives[i].function) (args);
10081acd27e7Smillert 	return (0);
10091acd27e7Smillert       }
10101acd27e7Smillert 
10111acd27e7Smillert   /* display an error message about the unknown parser directive */
10121acd27e7Smillert   _rl_init_file_error ("unknown parser directive");
10131acd27e7Smillert   return (1);
10141acd27e7Smillert }
10151acd27e7Smillert 
10161acd27e7Smillert /* Read the binding command from STRING and perform it.
10171acd27e7Smillert    A key binding command looks like: Keyname: function-name\0,
10181acd27e7Smillert    a variable binding command looks like: set variable value.
10191acd27e7Smillert    A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */
10201acd27e7Smillert int
rl_parse_and_bind(string)10211acd27e7Smillert rl_parse_and_bind (string)
10221acd27e7Smillert      char *string;
10231acd27e7Smillert {
10241acd27e7Smillert   char *funname, *kname;
10251acd27e7Smillert   register int c, i;
10261acd27e7Smillert   int key, equivalency;
10271acd27e7Smillert 
10281acd27e7Smillert   while (string && whitespace (*string))
10291acd27e7Smillert     string++;
10301acd27e7Smillert 
10311acd27e7Smillert   if (!string || !*string || *string == '#')
10321acd27e7Smillert     return 0;
10331acd27e7Smillert 
10341acd27e7Smillert   /* If this is a parser directive, act on it. */
10351acd27e7Smillert   if (*string == '$')
10361acd27e7Smillert     {
10371acd27e7Smillert       handle_parser_directive (&string[1]);
10381acd27e7Smillert       return 0;
10391acd27e7Smillert     }
10401acd27e7Smillert 
10411acd27e7Smillert   /* If we aren't supposed to be parsing right now, then we're done. */
10421acd27e7Smillert   if (_rl_parsing_conditionalized_out)
10431acd27e7Smillert     return 0;
10441acd27e7Smillert 
10451acd27e7Smillert   i = 0;
10461acd27e7Smillert   /* If this keyname is a complex key expression surrounded by quotes,
10471acd27e7Smillert      advance to after the matching close quote.  This code allows the
10481acd27e7Smillert      backslash to quote characters in the key expression. */
10491acd27e7Smillert   if (*string == '"')
10501acd27e7Smillert     {
10511acd27e7Smillert       int passc = 0;
10521acd27e7Smillert 
1053*af1e7b8cSkrw       for (i = 1; (c = string[i]); i++)
10541acd27e7Smillert 	{
10551acd27e7Smillert 	  if (passc)
10561acd27e7Smillert 	    {
10571acd27e7Smillert 	      passc = 0;
10581acd27e7Smillert 	      continue;
10591acd27e7Smillert 	    }
10601acd27e7Smillert 
10611acd27e7Smillert 	  if (c == '\\')
10621acd27e7Smillert 	    {
10631acd27e7Smillert 	      passc++;
10641acd27e7Smillert 	      continue;
10651acd27e7Smillert 	    }
10661acd27e7Smillert 
10671acd27e7Smillert 	  if (c == '"')
10681acd27e7Smillert 	    break;
10691acd27e7Smillert 	}
10701acd27e7Smillert       /* If we didn't find a closing quote, abort the line. */
10711acd27e7Smillert       if (string[i] == '\0')
10721acd27e7Smillert         {
10731acd27e7Smillert           _rl_init_file_error ("no closing `\"' in key binding");
10741acd27e7Smillert           return 1;
10751acd27e7Smillert         }
10761acd27e7Smillert     }
10771acd27e7Smillert 
10781acd27e7Smillert   /* Advance to the colon (:) or whitespace which separates the two objects. */
10791acd27e7Smillert   for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
10801acd27e7Smillert 
10811acd27e7Smillert   equivalency = (c == ':' && string[i + 1] == '=');
10821acd27e7Smillert 
10831acd27e7Smillert   /* Mark the end of the command (or keyname). */
10841acd27e7Smillert   if (string[i])
10851acd27e7Smillert     string[i++] = '\0';
10861acd27e7Smillert 
10871acd27e7Smillert   /* If doing assignment, skip the '=' sign as well. */
10881acd27e7Smillert   if (equivalency)
10891acd27e7Smillert     string[i++] = '\0';
10901acd27e7Smillert 
10911acd27e7Smillert   /* If this is a command to set a variable, then do that. */
10921acd27e7Smillert   if (_rl_stricmp (string, "set") == 0)
10931acd27e7Smillert     {
10941acd27e7Smillert       char *var = string + i;
10951acd27e7Smillert       char *value;
10961acd27e7Smillert 
10971acd27e7Smillert       /* Make VAR point to start of variable name. */
10981acd27e7Smillert       while (*var && whitespace (*var)) var++;
10991acd27e7Smillert 
1100af70c2dfSkettenis       /* Make VALUE point to start of value string. */
11011acd27e7Smillert       value = var;
11021acd27e7Smillert       while (*value && !whitespace (*value)) value++;
11031acd27e7Smillert       if (*value)
11041acd27e7Smillert 	*value++ = '\0';
11051acd27e7Smillert       while (*value && whitespace (*value)) value++;
11061acd27e7Smillert 
11071acd27e7Smillert       rl_variable_bind (var, value);
11081acd27e7Smillert       return 0;
11091acd27e7Smillert     }
11101acd27e7Smillert 
11111acd27e7Smillert   /* Skip any whitespace between keyname and funname. */
11121acd27e7Smillert   for (; string[i] && whitespace (string[i]); i++);
11131acd27e7Smillert   funname = &string[i];
11141acd27e7Smillert 
11151acd27e7Smillert   /* Now isolate funname.
11161acd27e7Smillert      For straight function names just look for whitespace, since
11171acd27e7Smillert      that will signify the end of the string.  But this could be a
11181acd27e7Smillert      macro definition.  In that case, the string is quoted, so skip
11191acd27e7Smillert      to the matching delimiter.  We allow the backslash to quote the
11201acd27e7Smillert      delimiter characters in the macro body. */
11211acd27e7Smillert   /* This code exists to allow whitespace in macro expansions, which
11221acd27e7Smillert      would otherwise be gobbled up by the next `for' loop.*/
11231acd27e7Smillert   /* XXX - it may be desirable to allow backslash quoting only if " is
11241acd27e7Smillert      the quoted string delimiter, like the shell. */
11251acd27e7Smillert   if (*funname == '\'' || *funname == '"')
11261acd27e7Smillert     {
11271acd27e7Smillert       int delimiter = string[i++], passc;
11281acd27e7Smillert 
1129*af1e7b8cSkrw       for (passc = 0; (c = string[i]); i++)
11301acd27e7Smillert 	{
11311acd27e7Smillert 	  if (passc)
11321acd27e7Smillert 	    {
11331acd27e7Smillert 	      passc = 0;
11341acd27e7Smillert 	      continue;
11351acd27e7Smillert 	    }
11361acd27e7Smillert 
11371acd27e7Smillert 	  if (c == '\\')
11381acd27e7Smillert 	    {
11391acd27e7Smillert 	      passc = 1;
11401acd27e7Smillert 	      continue;
11411acd27e7Smillert 	    }
11421acd27e7Smillert 
11431acd27e7Smillert 	  if (c == delimiter)
11441acd27e7Smillert 	    break;
11451acd27e7Smillert 	}
11461acd27e7Smillert       if (c)
11471acd27e7Smillert 	i++;
11481acd27e7Smillert     }
11491acd27e7Smillert 
11501acd27e7Smillert   /* Advance to the end of the string.  */
11511acd27e7Smillert   for (; string[i] && !whitespace (string[i]); i++);
11521acd27e7Smillert 
11531acd27e7Smillert   /* No extra whitespace at the end of the string. */
11541acd27e7Smillert   string[i] = '\0';
11551acd27e7Smillert 
11561acd27e7Smillert   /* Handle equivalency bindings here.  Make the left-hand side be exactly
11571acd27e7Smillert      whatever the right-hand evaluates to, including keymaps. */
11581acd27e7Smillert   if (equivalency)
11591acd27e7Smillert     {
11601acd27e7Smillert       return 0;
11611acd27e7Smillert     }
11621acd27e7Smillert 
11631acd27e7Smillert   /* If this is a new-style key-binding, then do the binding with
11641acd27e7Smillert      rl_set_key ().  Otherwise, let the older code deal with it. */
11651acd27e7Smillert   if (*string == '"')
11661acd27e7Smillert     {
11671acd27e7Smillert       char *seq;
11681acd27e7Smillert       register int j, k, passc;
11691acd27e7Smillert 
1170af70c2dfSkettenis       seq = (char *)xmalloc (1 + strlen (string));
11711acd27e7Smillert       for (j = 1, k = passc = 0; string[j]; j++)
11721acd27e7Smillert 	{
11731acd27e7Smillert 	  /* Allow backslash to quote characters, but leave them in place.
11741acd27e7Smillert 	     This allows a string to end with a backslash quoting another
11751acd27e7Smillert 	     backslash, or with a backslash quoting a double quote.  The
11761acd27e7Smillert 	     backslashes are left in place for rl_translate_keyseq (). */
11771acd27e7Smillert 	  if (passc || (string[j] == '\\'))
11781acd27e7Smillert 	    {
11791acd27e7Smillert 	      seq[k++] = string[j];
11801acd27e7Smillert 	      passc = !passc;
11811acd27e7Smillert 	      continue;
11821acd27e7Smillert 	    }
11831acd27e7Smillert 
11841acd27e7Smillert 	  if (string[j] == '"')
11851acd27e7Smillert 	    break;
11861acd27e7Smillert 
11871acd27e7Smillert 	  seq[k++] = string[j];
11881acd27e7Smillert 	}
11891acd27e7Smillert       seq[k] = '\0';
11901acd27e7Smillert 
11911acd27e7Smillert       /* Binding macro? */
11921acd27e7Smillert       if (*funname == '\'' || *funname == '"')
11931acd27e7Smillert 	{
11941acd27e7Smillert 	  j = strlen (funname);
11951acd27e7Smillert 
11961acd27e7Smillert 	  /* Remove the delimiting quotes from each end of FUNNAME. */
11971acd27e7Smillert 	  if (j && funname[j - 1] == *funname)
11981acd27e7Smillert 	    funname[j - 1] = '\0';
11991acd27e7Smillert 
12001acd27e7Smillert 	  rl_macro_bind (seq, &funname[1], _rl_keymap);
12011acd27e7Smillert 	}
12021acd27e7Smillert       else
12031acd27e7Smillert 	rl_set_key (seq, rl_named_function (funname), _rl_keymap);
12041acd27e7Smillert 
12051acd27e7Smillert       free (seq);
12061acd27e7Smillert       return 0;
12071acd27e7Smillert     }
12081acd27e7Smillert 
12091acd27e7Smillert   /* Get the actual character we want to deal with. */
12101acd27e7Smillert   kname = strrchr (string, '-');
12111acd27e7Smillert   if (!kname)
12121acd27e7Smillert     kname = string;
12131acd27e7Smillert   else
12141acd27e7Smillert     kname++;
12151acd27e7Smillert 
12161acd27e7Smillert   key = glean_key_from_name (kname);
12171acd27e7Smillert 
12181acd27e7Smillert   /* Add in control and meta bits. */
1219af70c2dfSkettenis   if (substring_member_of_array (string, _rl_possible_control_prefixes))
12201acd27e7Smillert     key = CTRL (_rl_to_upper (key));
12211acd27e7Smillert 
1222af70c2dfSkettenis   if (substring_member_of_array (string, _rl_possible_meta_prefixes))
12231acd27e7Smillert     key = META (key);
12241acd27e7Smillert 
12251acd27e7Smillert   /* Temporary.  Handle old-style keyname with macro-binding. */
12261acd27e7Smillert   if (*funname == '\'' || *funname == '"')
12271acd27e7Smillert     {
1228af70c2dfSkettenis       char useq[2];
12291acd27e7Smillert       int fl = strlen (funname);
12301acd27e7Smillert 
12311acd27e7Smillert       useq[0] = key; useq[1] = '\0';
12321acd27e7Smillert       if (fl && funname[fl - 1] == *funname)
12331acd27e7Smillert 	funname[fl - 1] = '\0';
12341acd27e7Smillert 
12351acd27e7Smillert       rl_macro_bind (useq, &funname[1], _rl_keymap);
12361acd27e7Smillert     }
12371acd27e7Smillert #if defined (PREFIX_META_HACK)
12381acd27e7Smillert   /* Ugly, but working hack to keep prefix-meta around. */
12391acd27e7Smillert   else if (_rl_stricmp (funname, "prefix-meta") == 0)
12401acd27e7Smillert     {
12411acd27e7Smillert       char seq[2];
12421acd27e7Smillert 
12431acd27e7Smillert       seq[0] = key;
12441acd27e7Smillert       seq[1] = '\0';
12451acd27e7Smillert       rl_generic_bind (ISKMAP, seq, (char *)emacs_meta_keymap, _rl_keymap);
12461acd27e7Smillert     }
12471acd27e7Smillert #endif /* PREFIX_META_HACK */
12481acd27e7Smillert   else
12491acd27e7Smillert     rl_bind_key (key, rl_named_function (funname));
12501acd27e7Smillert   return 0;
12511acd27e7Smillert }
12521acd27e7Smillert 
12531acd27e7Smillert /* Simple structure for boolean readline variables (i.e., those that can
12541acd27e7Smillert    have one of two values; either "On" or 1 for truth, or "Off" or 0 for
12551acd27e7Smillert    false. */
12561acd27e7Smillert 
12571acd27e7Smillert #define V_SPECIAL	0x1
12581acd27e7Smillert 
12591acd27e7Smillert static struct {
1260af70c2dfSkettenis   const char *name;
12611acd27e7Smillert   int *value;
12621acd27e7Smillert   int flags;
12631acd27e7Smillert } boolean_varlist [] = {
12641acd27e7Smillert   { "blink-matching-paren",	&rl_blink_matching_paren,	V_SPECIAL },
1265af70c2dfSkettenis   { "byte-oriented",		&rl_byte_oriented,		0 },
12661acd27e7Smillert   { "completion-ignore-case",	&_rl_completion_case_fold,	0 },
12671acd27e7Smillert   { "convert-meta",		&_rl_convert_meta_chars_to_ascii, 0 },
12681acd27e7Smillert   { "disable-completion",	&rl_inhibit_completion,		0 },
12691acd27e7Smillert   { "enable-keypad",		&_rl_enable_keypad,		0 },
12701acd27e7Smillert   { "expand-tilde",		&rl_complete_with_tilde_expansion, 0 },
1271af70c2dfSkettenis   { "history-preserve-point",	&_rl_history_preserve_point,	0 },
12721acd27e7Smillert   { "horizontal-scroll-mode",	&_rl_horizontal_scroll_mode,	0 },
12731acd27e7Smillert   { "input-meta",		&_rl_meta_flag,			0 },
12741acd27e7Smillert   { "mark-directories",		&_rl_complete_mark_directories,	0 },
12751acd27e7Smillert   { "mark-modified-lines",	&_rl_mark_modified_lines,	0 },
1276af70c2dfSkettenis   { "mark-symlinked-directories", &_rl_complete_mark_symlink_dirs, 0 },
1277af70c2dfSkettenis   { "match-hidden-files",	&_rl_match_hidden_files,	0 },
12781acd27e7Smillert   { "meta-flag",		&_rl_meta_flag,			0 },
12791acd27e7Smillert   { "output-meta",		&_rl_output_meta_chars,		0 },
1280af70c2dfSkettenis   { "page-completions",		&_rl_page_completions,		0 },
12811acd27e7Smillert   { "prefer-visible-bell",	&_rl_prefer_visible_bell,	V_SPECIAL },
12821acd27e7Smillert   { "print-completions-horizontally", &_rl_print_completions_horizontally, 0 },
12831acd27e7Smillert   { "show-all-if-ambiguous",	&_rl_complete_show_all,		0 },
12841acd27e7Smillert #if defined (VISIBLE_STATS)
12851acd27e7Smillert   { "visible-stats",		&rl_visible_stats,		0 },
12861acd27e7Smillert #endif /* VISIBLE_STATS */
12871acd27e7Smillert   { (char *)NULL, (int *)NULL }
12881acd27e7Smillert };
12891acd27e7Smillert 
12901acd27e7Smillert static int
find_boolean_var(name)12911acd27e7Smillert find_boolean_var (name)
1292af70c2dfSkettenis      const char *name;
12931acd27e7Smillert {
12941acd27e7Smillert   register int i;
12951acd27e7Smillert 
12961acd27e7Smillert   for (i = 0; boolean_varlist[i].name; i++)
12971acd27e7Smillert     if (_rl_stricmp (name, boolean_varlist[i].name) == 0)
12981acd27e7Smillert       return i;
12991acd27e7Smillert   return -1;
13001acd27e7Smillert }
13011acd27e7Smillert 
13021acd27e7Smillert /* Hooks for handling special boolean variables, where a
13031acd27e7Smillert    function needs to be called or another variable needs
13041acd27e7Smillert    to be changed when they're changed. */
13051acd27e7Smillert static void
hack_special_boolean_var(i)13061acd27e7Smillert hack_special_boolean_var (i)
13071acd27e7Smillert      int i;
13081acd27e7Smillert {
1309af70c2dfSkettenis   const char *name;
13101acd27e7Smillert 
13111acd27e7Smillert   name = boolean_varlist[i].name;
13121acd27e7Smillert 
13131acd27e7Smillert   if (_rl_stricmp (name, "blink-matching-paren") == 0)
13141acd27e7Smillert     _rl_enable_paren_matching (rl_blink_matching_paren);
13151acd27e7Smillert   else if (_rl_stricmp (name, "prefer-visible-bell") == 0)
13161acd27e7Smillert     {
13171acd27e7Smillert       if (_rl_prefer_visible_bell)
13181acd27e7Smillert 	_rl_bell_preference = VISIBLE_BELL;
13191acd27e7Smillert       else
13201acd27e7Smillert 	_rl_bell_preference = AUDIBLE_BELL;
13211acd27e7Smillert     }
13221acd27e7Smillert }
13231acd27e7Smillert 
1324af70c2dfSkettenis typedef int _rl_sv_func_t PARAMS((const char *));
1325af70c2dfSkettenis 
13261acd27e7Smillert /* These *must* correspond to the array indices for the appropriate
13271acd27e7Smillert    string variable.  (Though they're not used right now.) */
13281acd27e7Smillert #define V_BELLSTYLE	0
13291acd27e7Smillert #define V_COMBEGIN	1
13301acd27e7Smillert #define V_EDITMODE	2
13311acd27e7Smillert #define V_ISRCHTERM	3
13321acd27e7Smillert #define V_KEYMAP	4
13331acd27e7Smillert 
13341acd27e7Smillert #define	V_STRING	1
13351acd27e7Smillert #define V_INT		2
13361acd27e7Smillert 
13371acd27e7Smillert /* Forward declarations */
1338af70c2dfSkettenis static int sv_bell_style PARAMS((const char *));
1339af70c2dfSkettenis static int sv_combegin PARAMS((const char *));
1340af70c2dfSkettenis static int sv_compquery PARAMS((const char *));
1341af70c2dfSkettenis static int sv_editmode PARAMS((const char *));
1342af70c2dfSkettenis static int sv_isrchterm PARAMS((const char *));
1343af70c2dfSkettenis static int sv_keymap PARAMS((const char *));
13441acd27e7Smillert 
13451acd27e7Smillert static struct {
1346af70c2dfSkettenis   const char *name;
13471acd27e7Smillert   int flags;
1348af70c2dfSkettenis   _rl_sv_func_t *set_func;
13491acd27e7Smillert } string_varlist[] = {
13501acd27e7Smillert   { "bell-style",	V_STRING,	sv_bell_style },
13511acd27e7Smillert   { "comment-begin",	V_STRING,	sv_combegin },
13521acd27e7Smillert   { "completion-query-items", V_INT,	sv_compquery },
13531acd27e7Smillert   { "editing-mode",	V_STRING,	sv_editmode },
13541acd27e7Smillert   { "isearch-terminators", V_STRING,	sv_isrchterm },
13551acd27e7Smillert   { "keymap",		V_STRING,	sv_keymap },
13561acd27e7Smillert   { (char *)NULL,	0 }
13571acd27e7Smillert };
13581acd27e7Smillert 
13591acd27e7Smillert static int
find_string_var(name)13601acd27e7Smillert find_string_var (name)
1361af70c2dfSkettenis      const char *name;
13621acd27e7Smillert {
13631acd27e7Smillert   register int i;
13641acd27e7Smillert 
13651acd27e7Smillert   for (i = 0; string_varlist[i].name; i++)
13661acd27e7Smillert     if (_rl_stricmp (name, string_varlist[i].name) == 0)
13671acd27e7Smillert       return i;
13681acd27e7Smillert   return -1;
13691acd27e7Smillert }
13701acd27e7Smillert 
13711acd27e7Smillert /* A boolean value that can appear in a `set variable' command is true if
13721acd27e7Smillert    the value is null or empty, `on' (case-insenstive), or "1".  Any other
13731acd27e7Smillert    values result in 0 (false). */
13741acd27e7Smillert static int
bool_to_int(value)13751acd27e7Smillert bool_to_int (value)
1376*af1e7b8cSkrw      const char *value;
13771acd27e7Smillert {
13781acd27e7Smillert   return (value == 0 || *value == '\0' ||
13791acd27e7Smillert 		(_rl_stricmp (value, "on") == 0) ||
13801acd27e7Smillert 		(value[0] == '1' && value[1] == '\0'));
13811acd27e7Smillert }
13821acd27e7Smillert 
13831acd27e7Smillert int
rl_variable_bind(name,value)13841acd27e7Smillert rl_variable_bind (name, value)
1385af70c2dfSkettenis      const char *name, *value;
13861acd27e7Smillert {
13871acd27e7Smillert   register int i;
13881acd27e7Smillert   int	v;
13891acd27e7Smillert 
13901acd27e7Smillert   /* Check for simple variables first. */
13911acd27e7Smillert   i = find_boolean_var (name);
13921acd27e7Smillert   if (i >= 0)
13931acd27e7Smillert     {
13941acd27e7Smillert       *boolean_varlist[i].value = bool_to_int (value);
13951acd27e7Smillert       if (boolean_varlist[i].flags & V_SPECIAL)
13961acd27e7Smillert 	hack_special_boolean_var (i);
13971acd27e7Smillert       return 0;
13981acd27e7Smillert     }
13991acd27e7Smillert 
14001acd27e7Smillert   i = find_string_var (name);
14011acd27e7Smillert 
14021acd27e7Smillert   /* For the time being, unknown variable names or string names without a
14031acd27e7Smillert      handler function are simply ignored. */
14041acd27e7Smillert   if (i < 0 || string_varlist[i].set_func == 0)
14051acd27e7Smillert     return 0;
14061acd27e7Smillert 
14071acd27e7Smillert   v = (*string_varlist[i].set_func) (value);
14081acd27e7Smillert   return v;
14091acd27e7Smillert }
14101acd27e7Smillert 
14111acd27e7Smillert static int
sv_editmode(value)14121acd27e7Smillert sv_editmode (value)
1413af70c2dfSkettenis      const char *value;
14141acd27e7Smillert {
14151acd27e7Smillert   if (_rl_strnicmp (value, "vi", 2) == 0)
14161acd27e7Smillert     {
14171acd27e7Smillert #if defined (VI_MODE)
14181acd27e7Smillert       _rl_keymap = vi_insertion_keymap;
14191acd27e7Smillert       rl_editing_mode = vi_mode;
14201acd27e7Smillert #endif /* VI_MODE */
14211acd27e7Smillert       return 0;
14221acd27e7Smillert     }
14231acd27e7Smillert   else if (_rl_strnicmp (value, "emacs", 5) == 0)
14241acd27e7Smillert     {
14251acd27e7Smillert       _rl_keymap = emacs_standard_keymap;
14261acd27e7Smillert       rl_editing_mode = emacs_mode;
14271acd27e7Smillert       return 0;
14281acd27e7Smillert     }
14291acd27e7Smillert   return 1;
14301acd27e7Smillert }
14311acd27e7Smillert 
14321acd27e7Smillert static int
sv_combegin(value)14331acd27e7Smillert sv_combegin (value)
1434af70c2dfSkettenis      const char *value;
14351acd27e7Smillert {
14361acd27e7Smillert   if (value && *value)
14371acd27e7Smillert     {
14381acd27e7Smillert       FREE (_rl_comment_begin);
14391acd27e7Smillert       _rl_comment_begin = savestring (value);
14401acd27e7Smillert       return 0;
14411acd27e7Smillert     }
14421acd27e7Smillert   return 1;
14431acd27e7Smillert }
14441acd27e7Smillert 
14451acd27e7Smillert static int
sv_compquery(value)14461acd27e7Smillert sv_compquery (value)
1447af70c2dfSkettenis      const char *value;
14481acd27e7Smillert {
14491acd27e7Smillert   int nval = 100;
14501acd27e7Smillert 
14511acd27e7Smillert   if (value && *value)
14521acd27e7Smillert     {
14531acd27e7Smillert       nval = atoi (value);
14541acd27e7Smillert       if (nval < 0)
14551acd27e7Smillert 	nval = 0;
14561acd27e7Smillert     }
14571acd27e7Smillert   rl_completion_query_items = nval;
14581acd27e7Smillert   return 0;
14591acd27e7Smillert }
14601acd27e7Smillert 
14611acd27e7Smillert static int
sv_keymap(value)14621acd27e7Smillert sv_keymap (value)
1463af70c2dfSkettenis      const char *value;
14641acd27e7Smillert {
14651acd27e7Smillert   Keymap kmap;
14661acd27e7Smillert 
14671acd27e7Smillert   kmap = rl_get_keymap_by_name (value);
14681acd27e7Smillert   if (kmap)
14691acd27e7Smillert     {
14701acd27e7Smillert       rl_set_keymap (kmap);
14711acd27e7Smillert       return 0;
14721acd27e7Smillert     }
14731acd27e7Smillert   return 1;
14741acd27e7Smillert }
14751acd27e7Smillert 
14761acd27e7Smillert static int
sv_bell_style(value)14771acd27e7Smillert sv_bell_style (value)
1478af70c2dfSkettenis      const char *value;
14791acd27e7Smillert {
14801acd27e7Smillert   if (value == 0 || *value == '\0')
1481af70c2dfSkettenis     _rl_bell_preference = AUDIBLE_BELL;
14821acd27e7Smillert   else if (_rl_stricmp (value, "none") == 0 || _rl_stricmp (value, "off") == 0)
1483af70c2dfSkettenis     _rl_bell_preference = NO_BELL;
14841acd27e7Smillert   else if (_rl_stricmp (value, "audible") == 0 || _rl_stricmp (value, "on") == 0)
1485af70c2dfSkettenis     _rl_bell_preference = AUDIBLE_BELL;
14861acd27e7Smillert   else if (_rl_stricmp (value, "visible") == 0)
1487af70c2dfSkettenis     _rl_bell_preference = VISIBLE_BELL;
14881acd27e7Smillert   else
14891acd27e7Smillert     return 1;
1490af70c2dfSkettenis   return 0;
14911acd27e7Smillert }
14921acd27e7Smillert 
14931acd27e7Smillert static int
sv_isrchterm(value)14941acd27e7Smillert sv_isrchterm (value)
1495af70c2dfSkettenis      const char *value;
14961acd27e7Smillert {
14971acd27e7Smillert   int beg, end, delim;
14981acd27e7Smillert   char *v;
14991acd27e7Smillert 
15001acd27e7Smillert   if (value == 0)
15011acd27e7Smillert     return 1;
15021acd27e7Smillert 
15031acd27e7Smillert   /* Isolate the value and translate it into a character string. */
15041acd27e7Smillert   v = savestring (value);
15051acd27e7Smillert   FREE (_rl_isearch_terminators);
15061acd27e7Smillert   if (v[0] == '"' || v[0] == '\'')
15071acd27e7Smillert     {
15081acd27e7Smillert       delim = v[0];
15091acd27e7Smillert       for (beg = end = 1; v[end] && v[end] != delim; end++)
15101acd27e7Smillert 	;
15111acd27e7Smillert     }
15121acd27e7Smillert   else
15131acd27e7Smillert     {
15141acd27e7Smillert       for (beg = end = 0; whitespace (v[end]) == 0; end++)
15151acd27e7Smillert 	;
15161acd27e7Smillert     }
15171acd27e7Smillert 
15181acd27e7Smillert   v[end] = '\0';
15191acd27e7Smillert 
15201acd27e7Smillert   /* The value starts at v + beg.  Translate it into a character string. */
1521af70c2dfSkettenis   _rl_isearch_terminators = (char *)xmalloc (2 * strlen (v) + 1);
15221acd27e7Smillert   rl_translate_keyseq (v + beg, _rl_isearch_terminators, &end);
15231acd27e7Smillert   _rl_isearch_terminators[end] = '\0';
15241acd27e7Smillert 
15251acd27e7Smillert   free (v);
15261acd27e7Smillert   return 0;
15271acd27e7Smillert }
15281acd27e7Smillert 
15291acd27e7Smillert /* Return the character which matches NAME.
15301acd27e7Smillert    For example, `Space' returns ' '. */
15311acd27e7Smillert 
15321acd27e7Smillert typedef struct {
1533af70c2dfSkettenis   const char *name;
15341acd27e7Smillert   int value;
15351acd27e7Smillert } assoc_list;
15361acd27e7Smillert 
15371acd27e7Smillert static assoc_list name_key_alist[] = {
15381acd27e7Smillert   { "DEL", 0x7f },
15391acd27e7Smillert   { "ESC", '\033' },
15401acd27e7Smillert   { "Escape", '\033' },
15411acd27e7Smillert   { "LFD", '\n' },
15421acd27e7Smillert   { "Newline", '\n' },
15431acd27e7Smillert   { "RET", '\r' },
15441acd27e7Smillert   { "Return", '\r' },
15451acd27e7Smillert   { "Rubout", 0x7f },
15461acd27e7Smillert   { "SPC", ' ' },
15471acd27e7Smillert   { "Space", ' ' },
15481acd27e7Smillert   { "Tab", 0x09 },
15491acd27e7Smillert   { (char *)0x0, 0 }
15501acd27e7Smillert };
15511acd27e7Smillert 
15521acd27e7Smillert static int
glean_key_from_name(name)15531acd27e7Smillert glean_key_from_name (name)
15541acd27e7Smillert      char *name;
15551acd27e7Smillert {
15561acd27e7Smillert   register int i;
15571acd27e7Smillert 
15581acd27e7Smillert   for (i = 0; name_key_alist[i].name; i++)
15591acd27e7Smillert     if (_rl_stricmp (name, name_key_alist[i].name) == 0)
15601acd27e7Smillert       return (name_key_alist[i].value);
15611acd27e7Smillert 
15621acd27e7Smillert   return (*(unsigned char *)name);	/* XXX was return (*name) */
15631acd27e7Smillert }
15641acd27e7Smillert 
15651acd27e7Smillert /* Auxiliary functions to manage keymaps. */
15661acd27e7Smillert static struct {
1567af70c2dfSkettenis   const char *name;
15681acd27e7Smillert   Keymap map;
15691acd27e7Smillert } keymap_names[] = {
15701acd27e7Smillert   { "emacs", emacs_standard_keymap },
15711acd27e7Smillert   { "emacs-standard", emacs_standard_keymap },
15721acd27e7Smillert   { "emacs-meta", emacs_meta_keymap },
15731acd27e7Smillert   { "emacs-ctlx", emacs_ctlx_keymap },
15741acd27e7Smillert #if defined (VI_MODE)
15751acd27e7Smillert   { "vi", vi_movement_keymap },
15761acd27e7Smillert   { "vi-move", vi_movement_keymap },
15771acd27e7Smillert   { "vi-command", vi_movement_keymap },
15781acd27e7Smillert   { "vi-insert", vi_insertion_keymap },
15791acd27e7Smillert #endif /* VI_MODE */
15801acd27e7Smillert   { (char *)0x0, (Keymap)0x0 }
15811acd27e7Smillert };
15821acd27e7Smillert 
15831acd27e7Smillert Keymap
rl_get_keymap_by_name(name)15841acd27e7Smillert rl_get_keymap_by_name (name)
1585af70c2dfSkettenis      const char *name;
15861acd27e7Smillert {
15871acd27e7Smillert   register int i;
15881acd27e7Smillert 
15891acd27e7Smillert   for (i = 0; keymap_names[i].name; i++)
1590af70c2dfSkettenis     if (_rl_stricmp (name, keymap_names[i].name) == 0)
15911acd27e7Smillert       return (keymap_names[i].map);
15921acd27e7Smillert   return ((Keymap) NULL);
15931acd27e7Smillert }
15941acd27e7Smillert 
15951acd27e7Smillert char *
rl_get_keymap_name(map)15961acd27e7Smillert rl_get_keymap_name (map)
15971acd27e7Smillert      Keymap map;
15981acd27e7Smillert {
15991acd27e7Smillert   register int i;
16001acd27e7Smillert   for (i = 0; keymap_names[i].name; i++)
16011acd27e7Smillert     if (map == keymap_names[i].map)
1602af70c2dfSkettenis       return ((char *)keymap_names[i].name);
16031acd27e7Smillert   return ((char *)NULL);
16041acd27e7Smillert }
16051acd27e7Smillert 
16061acd27e7Smillert void
rl_set_keymap(map)16071acd27e7Smillert rl_set_keymap (map)
16081acd27e7Smillert      Keymap map;
16091acd27e7Smillert {
16101acd27e7Smillert   if (map)
16111acd27e7Smillert     _rl_keymap = map;
16121acd27e7Smillert }
16131acd27e7Smillert 
16141acd27e7Smillert Keymap
rl_get_keymap()16151acd27e7Smillert rl_get_keymap ()
16161acd27e7Smillert {
16171acd27e7Smillert   return (_rl_keymap);
16181acd27e7Smillert }
16191acd27e7Smillert 
16201acd27e7Smillert void
rl_set_keymap_from_edit_mode()16211acd27e7Smillert rl_set_keymap_from_edit_mode ()
16221acd27e7Smillert {
16231acd27e7Smillert   if (rl_editing_mode == emacs_mode)
16241acd27e7Smillert     _rl_keymap = emacs_standard_keymap;
16251acd27e7Smillert #if defined (VI_MODE)
16261acd27e7Smillert   else if (rl_editing_mode == vi_mode)
16271acd27e7Smillert     _rl_keymap = vi_insertion_keymap;
16281acd27e7Smillert #endif /* VI_MODE */
16291acd27e7Smillert }
16301acd27e7Smillert 
16311acd27e7Smillert char *
rl_get_keymap_name_from_edit_mode()16321acd27e7Smillert rl_get_keymap_name_from_edit_mode ()
16331acd27e7Smillert {
16341acd27e7Smillert   if (rl_editing_mode == emacs_mode)
16351acd27e7Smillert     return "emacs";
16361acd27e7Smillert #if defined (VI_MODE)
16371acd27e7Smillert   else if (rl_editing_mode == vi_mode)
16381acd27e7Smillert     return "vi";
16391acd27e7Smillert #endif /* VI_MODE */
16401acd27e7Smillert   else
16411acd27e7Smillert     return "none";
16421acd27e7Smillert }
16431acd27e7Smillert 
16441acd27e7Smillert /* **************************************************************** */
16451acd27e7Smillert /*								    */
16461acd27e7Smillert /*		  Key Binding and Function Information		    */
16471acd27e7Smillert /*								    */
16481acd27e7Smillert /* **************************************************************** */
16491acd27e7Smillert 
16501acd27e7Smillert /* Each of the following functions produces information about the
16511acd27e7Smillert    state of keybindings and functions known to Readline.  The info
16521acd27e7Smillert    is always printed to rl_outstream, and in such a way that it can
16531acd27e7Smillert    be read back in (i.e., passed to rl_parse_and_bind (). */
16541acd27e7Smillert 
16551acd27e7Smillert /* Print the names of functions known to Readline. */
16561acd27e7Smillert void
rl_list_funmap_names()16571acd27e7Smillert rl_list_funmap_names ()
16581acd27e7Smillert {
16591acd27e7Smillert   register int i;
1660af70c2dfSkettenis   const char **funmap_names;
16611acd27e7Smillert 
16621acd27e7Smillert   funmap_names = rl_funmap_names ();
16631acd27e7Smillert 
16641acd27e7Smillert   if (!funmap_names)
16651acd27e7Smillert     return;
16661acd27e7Smillert 
16671acd27e7Smillert   for (i = 0; funmap_names[i]; i++)
16681acd27e7Smillert     fprintf (rl_outstream, "%s\n", funmap_names[i]);
16691acd27e7Smillert 
16701acd27e7Smillert   free (funmap_names);
16711acd27e7Smillert }
16721acd27e7Smillert 
16731acd27e7Smillert static char *
_rl_get_keyname(key)16741acd27e7Smillert _rl_get_keyname (key)
16751acd27e7Smillert      int key;
16761acd27e7Smillert {
16771acd27e7Smillert   char *keyname;
16781acd27e7Smillert   int i, c;
16791acd27e7Smillert 
16801acd27e7Smillert   keyname = (char *)xmalloc (8);
16811acd27e7Smillert 
16821acd27e7Smillert   c = key;
16831acd27e7Smillert   /* Since this is going to be used to write out keysequence-function
16841acd27e7Smillert      pairs for possible inclusion in an inputrc file, we don't want to
16851acd27e7Smillert      do any special meta processing on KEY. */
16861acd27e7Smillert 
1687af70c2dfSkettenis #if 1
1688af70c2dfSkettenis   /* XXX - Experimental */
16891acd27e7Smillert   /* We might want to do this, but the old version of the code did not. */
16901acd27e7Smillert 
16911acd27e7Smillert   /* If this is an escape character, we don't want to do any more processing.
16921acd27e7Smillert      Just add the special ESC key sequence and return. */
16931acd27e7Smillert   if (c == ESC)
16941acd27e7Smillert     {
1695af70c2dfSkettenis       keyname[0] = '\\';
1696af70c2dfSkettenis       keyname[1] = 'e';
1697af70c2dfSkettenis       keyname[2] = '\0';
1698af70c2dfSkettenis       return keyname;
16991acd27e7Smillert     }
17001acd27e7Smillert #endif
17011acd27e7Smillert 
17021acd27e7Smillert   /* RUBOUT is translated directly into \C-? */
17031acd27e7Smillert   if (key == RUBOUT)
17041acd27e7Smillert     {
17051acd27e7Smillert       keyname[0] = '\\';
17061acd27e7Smillert       keyname[1] = 'C';
17071acd27e7Smillert       keyname[2] = '-';
17081acd27e7Smillert       keyname[3] = '?';
17091acd27e7Smillert       keyname[4] = '\0';
17101acd27e7Smillert       return keyname;
17111acd27e7Smillert     }
17121acd27e7Smillert 
17131acd27e7Smillert   i = 0;
17141acd27e7Smillert   /* Now add special prefixes needed for control characters.  This can
17151acd27e7Smillert      potentially change C. */
17161acd27e7Smillert   if (CTRL_CHAR (c))
17171acd27e7Smillert     {
17181acd27e7Smillert       keyname[i++] = '\\';
17191acd27e7Smillert       keyname[i++] = 'C';
17201acd27e7Smillert       keyname[i++] = '-';
17211acd27e7Smillert       c = _rl_to_lower (UNCTRL (c));
17221acd27e7Smillert     }
17231acd27e7Smillert 
17241acd27e7Smillert   /* XXX experimental code.  Turn the characters that are not ASCII or
17251acd27e7Smillert      ISO Latin 1 (128 - 159) into octal escape sequences (\200 - \237).
17261acd27e7Smillert      This changes C. */
17271acd27e7Smillert   if (c >= 128 && c <= 159)
17281acd27e7Smillert     {
17291acd27e7Smillert       keyname[i++] = '\\';
17301acd27e7Smillert       keyname[i++] = '2';
17311acd27e7Smillert       c -= 128;
17321acd27e7Smillert       keyname[i++] = (c / 8) + '0';
17331acd27e7Smillert       c = (c % 8) + '0';
17341acd27e7Smillert     }
17351acd27e7Smillert 
17361acd27e7Smillert   /* Now, if the character needs to be quoted with a backslash, do that. */
17371acd27e7Smillert   if (c == '\\' || c == '"')
17381acd27e7Smillert     keyname[i++] = '\\';
17391acd27e7Smillert 
17401acd27e7Smillert   /* Now add the key, terminate the string, and return it. */
17411acd27e7Smillert   keyname[i++] = (char) c;
17421acd27e7Smillert   keyname[i] = '\0';
17431acd27e7Smillert 
17441acd27e7Smillert   return keyname;
17451acd27e7Smillert }
17461acd27e7Smillert 
17471acd27e7Smillert /* Return a NULL terminated array of strings which represent the key
17481acd27e7Smillert    sequences that are used to invoke FUNCTION in MAP. */
17491acd27e7Smillert char **
rl_invoking_keyseqs_in_map(function,map)17501acd27e7Smillert rl_invoking_keyseqs_in_map (function, map)
1751af70c2dfSkettenis      rl_command_func_t *function;
17521acd27e7Smillert      Keymap map;
17531acd27e7Smillert {
17541acd27e7Smillert   register int key;
17551acd27e7Smillert   char **result;
17561acd27e7Smillert   int result_index, result_size;
17571acd27e7Smillert 
17581acd27e7Smillert   result = (char **)NULL;
17591acd27e7Smillert   result_index = result_size = 0;
17601acd27e7Smillert 
17611acd27e7Smillert   for (key = 0; key < KEYMAP_SIZE; key++)
17621acd27e7Smillert     {
17631acd27e7Smillert       switch (map[key].type)
17641acd27e7Smillert 	{
17651acd27e7Smillert 	case ISMACR:
17661acd27e7Smillert 	  /* Macros match, if, and only if, the pointers are identical.
17671acd27e7Smillert 	     Thus, they are treated exactly like functions in here. */
17681acd27e7Smillert 	case ISFUNC:
17691acd27e7Smillert 	  /* If the function in the keymap is the one we are looking for,
17701acd27e7Smillert 	     then add the current KEY to the list of invoking keys. */
17711acd27e7Smillert 	  if (map[key].function == function)
17721acd27e7Smillert 	    {
17731acd27e7Smillert 	      char *keyname;
17741acd27e7Smillert 
17751acd27e7Smillert 	      keyname = _rl_get_keyname (key);
17761acd27e7Smillert 
17771acd27e7Smillert 	      if (result_index + 2 > result_size)
17781acd27e7Smillert 	        {
17791acd27e7Smillert 	          result_size += 10;
17801acd27e7Smillert 		  result = (char **)xrealloc (result, result_size * sizeof (char *));
17811acd27e7Smillert 	        }
17821acd27e7Smillert 
17831acd27e7Smillert 	      result[result_index++] = keyname;
17841acd27e7Smillert 	      result[result_index] = (char *)NULL;
17851acd27e7Smillert 	    }
17861acd27e7Smillert 	  break;
17871acd27e7Smillert 
17881acd27e7Smillert 	case ISKMAP:
17891acd27e7Smillert 	  {
17901acd27e7Smillert 	    char **seqs;
17911acd27e7Smillert 	    register int i;
17921acd27e7Smillert 
17931acd27e7Smillert 	    /* Find the list of keyseqs in this map which have FUNCTION as
17941acd27e7Smillert 	       their target.  Add the key sequences found to RESULT. */
17951acd27e7Smillert 	    if (map[key].function)
17961acd27e7Smillert 	      seqs =
17971acd27e7Smillert 	        rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
17981acd27e7Smillert 	    else
17991acd27e7Smillert 	      break;
18001acd27e7Smillert 
18011acd27e7Smillert 	    if (seqs == 0)
18021acd27e7Smillert 	      break;
18031acd27e7Smillert 
18041acd27e7Smillert 	    for (i = 0; seqs[i]; i++)
18051acd27e7Smillert 	      {
180663bef317Sbeck 		int len = 6 + strlen(seqs[i]);
180763bef317Sbeck 		char *keyname = (char *)xmalloc (len);
18081acd27e7Smillert 
18091acd27e7Smillert 		if (key == ESC)
1810af70c2dfSkettenis #if 0
181163bef317Sbeck 		  snprintf(keyname, len, "\\e");
1812af70c2dfSkettenis #else
1813af70c2dfSkettenis 		/* XXX - experimental */
1814af70c2dfSkettenis 		  snprintf(keyname, len, "\\M-");
1815af70c2dfSkettenis #endif
18161acd27e7Smillert 		else if (CTRL_CHAR (key))
181763bef317Sbeck 		  snprintf(keyname, len, "\\C-%c", _rl_to_lower (UNCTRL (key)));
18181acd27e7Smillert 		else if (key == RUBOUT)
181963bef317Sbeck 		  snprintf(keyname, len, "\\C-?");
18201acd27e7Smillert 		else if (key == '\\' || key == '"')
18211acd27e7Smillert 		  {
18221acd27e7Smillert 		    keyname[0] = '\\';
18231acd27e7Smillert 		    keyname[1] = (char) key;
18241acd27e7Smillert 		    keyname[2] = '\0';
18251acd27e7Smillert 		  }
18261acd27e7Smillert 		else
18271acd27e7Smillert 		  {
18281acd27e7Smillert 		    keyname[0] = (char) key;
18291acd27e7Smillert 		    keyname[1] = '\0';
18301acd27e7Smillert 		  }
18311acd27e7Smillert 
183263bef317Sbeck 		strlcat (keyname, seqs[i], len);
18331acd27e7Smillert 		free (seqs[i]);
18341acd27e7Smillert 
18351acd27e7Smillert 		if (result_index + 2 > result_size)
18361acd27e7Smillert 		  {
18371acd27e7Smillert 		    result_size += 10;
18381acd27e7Smillert 		    result = (char **)xrealloc (result, result_size * sizeof (char *));
18391acd27e7Smillert 		  }
18401acd27e7Smillert 
18411acd27e7Smillert 		result[result_index++] = keyname;
18421acd27e7Smillert 		result[result_index] = (char *)NULL;
18431acd27e7Smillert 	      }
18441acd27e7Smillert 
18451acd27e7Smillert 	    free (seqs);
18461acd27e7Smillert 	  }
18471acd27e7Smillert 	  break;
18481acd27e7Smillert 	}
18491acd27e7Smillert     }
18501acd27e7Smillert   return (result);
18511acd27e7Smillert }
18521acd27e7Smillert 
18531acd27e7Smillert /* Return a NULL terminated array of strings which represent the key
18541acd27e7Smillert    sequences that can be used to invoke FUNCTION using the current keymap. */
18551acd27e7Smillert char **
rl_invoking_keyseqs(function)18561acd27e7Smillert rl_invoking_keyseqs (function)
1857af70c2dfSkettenis      rl_command_func_t *function;
18581acd27e7Smillert {
18591acd27e7Smillert   return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
18601acd27e7Smillert }
18611acd27e7Smillert 
18621acd27e7Smillert /* Print all of the functions and their bindings to rl_outstream.  If
18631acd27e7Smillert    PRINT_READABLY is non-zero, then print the output in such a way
18641acd27e7Smillert    that it can be read back in. */
18651acd27e7Smillert void
rl_function_dumper(print_readably)18661acd27e7Smillert rl_function_dumper (print_readably)
18671acd27e7Smillert      int print_readably;
18681acd27e7Smillert {
18691acd27e7Smillert   register int i;
1870af70c2dfSkettenis   const char **names;
1871af70c2dfSkettenis   const char *name;
18721acd27e7Smillert 
18731acd27e7Smillert   names = rl_funmap_names ();
18741acd27e7Smillert 
18751acd27e7Smillert   fprintf (rl_outstream, "\n");
18761acd27e7Smillert 
1877*af1e7b8cSkrw   for (i = 0; (name = names[i]); i++)
18781acd27e7Smillert     {
1879af70c2dfSkettenis       rl_command_func_t *function;
18801acd27e7Smillert       char **invokers;
18811acd27e7Smillert 
18821acd27e7Smillert       function = rl_named_function (name);
18831acd27e7Smillert       invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap);
18841acd27e7Smillert 
18851acd27e7Smillert       if (print_readably)
18861acd27e7Smillert 	{
18871acd27e7Smillert 	  if (!invokers)
18881acd27e7Smillert 	    fprintf (rl_outstream, "# %s (not bound)\n", name);
18891acd27e7Smillert 	  else
18901acd27e7Smillert 	    {
18911acd27e7Smillert 	      register int j;
18921acd27e7Smillert 
18931acd27e7Smillert 	      for (j = 0; invokers[j]; j++)
18941acd27e7Smillert 		{
18951acd27e7Smillert 		  fprintf (rl_outstream, "\"%s\": %s\n",
18961acd27e7Smillert 			   invokers[j], name);
18971acd27e7Smillert 		  free (invokers[j]);
18981acd27e7Smillert 		}
18991acd27e7Smillert 
19001acd27e7Smillert 	      free (invokers);
19011acd27e7Smillert 	    }
19021acd27e7Smillert 	}
19031acd27e7Smillert       else
19041acd27e7Smillert 	{
19051acd27e7Smillert 	  if (!invokers)
19061acd27e7Smillert 	    fprintf (rl_outstream, "%s is not bound to any keys\n",
19071acd27e7Smillert 		     name);
19081acd27e7Smillert 	  else
19091acd27e7Smillert 	    {
19101acd27e7Smillert 	      register int j;
19111acd27e7Smillert 
19121acd27e7Smillert 	      fprintf (rl_outstream, "%s can be found on ", name);
19131acd27e7Smillert 
19141acd27e7Smillert 	      for (j = 0; invokers[j] && j < 5; j++)
19151acd27e7Smillert 		{
19161acd27e7Smillert 		  fprintf (rl_outstream, "\"%s\"%s", invokers[j],
19171acd27e7Smillert 			   invokers[j + 1] ? ", " : ".\n");
19181acd27e7Smillert 		}
19191acd27e7Smillert 
19201acd27e7Smillert 	      if (j == 5 && invokers[j])
19211acd27e7Smillert 		fprintf (rl_outstream, "...\n");
19221acd27e7Smillert 
19231acd27e7Smillert 	      for (j = 0; invokers[j]; j++)
19241acd27e7Smillert 		free (invokers[j]);
19251acd27e7Smillert 
19261acd27e7Smillert 	      free (invokers);
19271acd27e7Smillert 	    }
19281acd27e7Smillert 	}
19291acd27e7Smillert     }
19301acd27e7Smillert }
19311acd27e7Smillert 
19321acd27e7Smillert /* Print all of the current functions and their bindings to
19331acd27e7Smillert    rl_outstream.  If an explicit argument is given, then print
19341acd27e7Smillert    the output in such a way that it can be read back in. */
19351acd27e7Smillert int
rl_dump_functions(count,key)19361acd27e7Smillert rl_dump_functions (count, key)
19371acd27e7Smillert      int count, key;
19381acd27e7Smillert {
19391acd27e7Smillert   if (rl_dispatching)
19401acd27e7Smillert     fprintf (rl_outstream, "\r\n");
19411acd27e7Smillert   rl_function_dumper (rl_explicit_arg);
19421acd27e7Smillert   rl_on_new_line ();
19431acd27e7Smillert   return (0);
19441acd27e7Smillert }
19451acd27e7Smillert 
19461acd27e7Smillert static void
_rl_macro_dumper_internal(print_readably,map,prefix)19471acd27e7Smillert _rl_macro_dumper_internal (print_readably, map, prefix)
19481acd27e7Smillert      int print_readably;
19491acd27e7Smillert      Keymap map;
19501acd27e7Smillert      char *prefix;
19511acd27e7Smillert {
19521acd27e7Smillert   register int key;
19531acd27e7Smillert   char *keyname, *out;
19541acd27e7Smillert   int prefix_len;
19551acd27e7Smillert 
19561acd27e7Smillert   for (key = 0; key < KEYMAP_SIZE; key++)
19571acd27e7Smillert     {
19581acd27e7Smillert       switch (map[key].type)
19591acd27e7Smillert 	{
19601acd27e7Smillert 	case ISMACR:
19611acd27e7Smillert 	  keyname = _rl_get_keyname (key);
19621acd27e7Smillert 	  out = _rl_untranslate_macro_value ((char *)map[key].function);
1963af70c2dfSkettenis 
19641acd27e7Smillert 	  if (print_readably)
19651acd27e7Smillert 	    fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
19661acd27e7Smillert 						         keyname,
19671acd27e7Smillert 						         out ? out : "");
19681acd27e7Smillert 	  else
19691acd27e7Smillert 	    fprintf (rl_outstream, "%s%s outputs %s\n", prefix ? prefix : "",
19701acd27e7Smillert 							keyname,
19711acd27e7Smillert 							out ? out : "");
19721acd27e7Smillert 	  free (keyname);
19731acd27e7Smillert 	  free (out);
19741acd27e7Smillert 	  break;
19751acd27e7Smillert 	case ISFUNC:
19761acd27e7Smillert 	  break;
19771acd27e7Smillert 	case ISKMAP:
19781acd27e7Smillert 	  prefix_len = prefix ? strlen (prefix) : 0;
19791acd27e7Smillert 	  if (key == ESC)
19801acd27e7Smillert 	    {
198163bef317Sbeck 	      int len = 3 + prefix_len;
1982af70c2dfSkettenis 	      keyname = (char *)xmalloc (len);
19831acd27e7Smillert 	      if (prefix)
198463bef317Sbeck 		strlcpy (keyname, prefix, len);
19851acd27e7Smillert 	      keyname[prefix_len] = '\\';
19861acd27e7Smillert 	      keyname[prefix_len + 1] = 'e';
19871acd27e7Smillert 	      keyname[prefix_len + 2] = '\0';
19881acd27e7Smillert 	    }
19891acd27e7Smillert 	  else
19901acd27e7Smillert 	    {
19911acd27e7Smillert 	      keyname = _rl_get_keyname (key);
19921acd27e7Smillert 	      if (prefix)
19931acd27e7Smillert 		{
199463bef317Sbeck 		  if (asprintf(&out, "%s%s", prefix, keyname) == -1)
199563bef317Sbeck 		    memory_error_and_abort("asprintf");
19961acd27e7Smillert 		  free (keyname);
19971acd27e7Smillert 		  keyname = out;
19981acd27e7Smillert 		}
19991acd27e7Smillert 	    }
20001acd27e7Smillert 
20011acd27e7Smillert 	  _rl_macro_dumper_internal (print_readably, FUNCTION_TO_KEYMAP (map, key), keyname);
20021acd27e7Smillert 	  free (keyname);
20031acd27e7Smillert 	  break;
20041acd27e7Smillert 	}
20051acd27e7Smillert     }
20061acd27e7Smillert }
20071acd27e7Smillert 
20081acd27e7Smillert void
rl_macro_dumper(print_readably)20091acd27e7Smillert rl_macro_dumper (print_readably)
20101acd27e7Smillert      int print_readably;
20111acd27e7Smillert {
20121acd27e7Smillert   _rl_macro_dumper_internal (print_readably, _rl_keymap, (char *)NULL);
20131acd27e7Smillert }
20141acd27e7Smillert 
20151acd27e7Smillert int
rl_dump_macros(count,key)20161acd27e7Smillert rl_dump_macros (count, key)
20171acd27e7Smillert      int count, key;
20181acd27e7Smillert {
20191acd27e7Smillert   if (rl_dispatching)
20201acd27e7Smillert     fprintf (rl_outstream, "\r\n");
20211acd27e7Smillert   rl_macro_dumper (rl_explicit_arg);
20221acd27e7Smillert   rl_on_new_line ();
20231acd27e7Smillert   return (0);
20241acd27e7Smillert }
20251acd27e7Smillert 
20261acd27e7Smillert void
rl_variable_dumper(print_readably)20271acd27e7Smillert rl_variable_dumper (print_readably)
20281acd27e7Smillert      int print_readably;
20291acd27e7Smillert {
20301acd27e7Smillert   int i;
2031af70c2dfSkettenis   const char *kname;
20321acd27e7Smillert 
20331acd27e7Smillert   for (i = 0; boolean_varlist[i].name; i++)
20341acd27e7Smillert     {
20351acd27e7Smillert       if (print_readably)
20361acd27e7Smillert         fprintf (rl_outstream, "set %s %s\n", boolean_varlist[i].name,
20371acd27e7Smillert 			       *boolean_varlist[i].value ? "on" : "off");
20381acd27e7Smillert       else
20391acd27e7Smillert         fprintf (rl_outstream, "%s is set to `%s'\n", boolean_varlist[i].name,
20401acd27e7Smillert 			       *boolean_varlist[i].value ? "on" : "off");
20411acd27e7Smillert     }
20421acd27e7Smillert 
20431acd27e7Smillert   /* bell-style */
20441acd27e7Smillert   switch (_rl_bell_preference)
20451acd27e7Smillert     {
20461acd27e7Smillert     case NO_BELL:
20471acd27e7Smillert       kname = "none"; break;
20481acd27e7Smillert     case VISIBLE_BELL:
20491acd27e7Smillert       kname = "visible"; break;
20501acd27e7Smillert     case AUDIBLE_BELL:
20511acd27e7Smillert     default:
20521acd27e7Smillert       kname = "audible"; break;
20531acd27e7Smillert     }
20541acd27e7Smillert   if (print_readably)
20551acd27e7Smillert     fprintf (rl_outstream, "set bell-style %s\n", kname);
20561acd27e7Smillert   else
20571acd27e7Smillert     fprintf (rl_outstream, "bell-style is set to `%s'\n", kname);
20581acd27e7Smillert 
20591acd27e7Smillert   /* comment-begin */
20601acd27e7Smillert   if (print_readably)
20611acd27e7Smillert     fprintf (rl_outstream, "set comment-begin %s\n", _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
20621acd27e7Smillert   else
2063af70c2dfSkettenis     fprintf (rl_outstream, "comment-begin is set to `%s'\n", _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
20641acd27e7Smillert 
20651acd27e7Smillert   /* completion-query-items */
20661acd27e7Smillert   if (print_readably)
20671acd27e7Smillert     fprintf (rl_outstream, "set completion-query-items %d\n", rl_completion_query_items);
20681acd27e7Smillert   else
20691acd27e7Smillert     fprintf (rl_outstream, "completion-query-items is set to `%d'\n", rl_completion_query_items);
20701acd27e7Smillert 
20711acd27e7Smillert   /* editing-mode */
20721acd27e7Smillert   if (print_readably)
20731acd27e7Smillert     fprintf (rl_outstream, "set editing-mode %s\n", (rl_editing_mode == emacs_mode) ? "emacs" : "vi");
20741acd27e7Smillert   else
20751acd27e7Smillert     fprintf (rl_outstream, "editing-mode is set to `%s'\n", (rl_editing_mode == emacs_mode) ? "emacs" : "vi");
20761acd27e7Smillert 
20771acd27e7Smillert   /* isearch-terminators */
20781acd27e7Smillert   if (_rl_isearch_terminators)
20791acd27e7Smillert     {
20801acd27e7Smillert       char *disp;
20811acd27e7Smillert 
20821acd27e7Smillert       disp = _rl_untranslate_macro_value (_rl_isearch_terminators);
20831acd27e7Smillert 
20841acd27e7Smillert       if (print_readably)
20851acd27e7Smillert 	fprintf (rl_outstream, "set isearch-terminators \"%s\"\n", disp);
20861acd27e7Smillert       else
20871acd27e7Smillert 	fprintf (rl_outstream, "isearch-terminators is set to \"%s\"\n", disp);
20881acd27e7Smillert 
20891acd27e7Smillert       free (disp);
20901acd27e7Smillert     }
2091af70c2dfSkettenis 
2092af70c2dfSkettenis   /* keymap */
2093af70c2dfSkettenis   kname = rl_get_keymap_name (_rl_keymap);
2094af70c2dfSkettenis   if (kname == 0)
2095af70c2dfSkettenis     kname = rl_get_keymap_name_from_edit_mode ();
2096af70c2dfSkettenis   if (print_readably)
2097af70c2dfSkettenis     fprintf (rl_outstream, "set keymap %s\n", kname ? kname : "none");
2098af70c2dfSkettenis   else
2099af70c2dfSkettenis     fprintf (rl_outstream, "keymap is set to `%s'\n", kname ? kname : "none");
21001acd27e7Smillert }
21011acd27e7Smillert 
21021acd27e7Smillert /* Print all of the current variables and their values to
21031acd27e7Smillert    rl_outstream.  If an explicit argument is given, then print
21041acd27e7Smillert    the output in such a way that it can be read back in. */
21051acd27e7Smillert int
rl_dump_variables(count,key)21061acd27e7Smillert rl_dump_variables (count, key)
21071acd27e7Smillert      int count, key;
21081acd27e7Smillert {
21091acd27e7Smillert   if (rl_dispatching)
21101acd27e7Smillert     fprintf (rl_outstream, "\r\n");
21111acd27e7Smillert   rl_variable_dumper (rl_explicit_arg);
21121acd27e7Smillert   rl_on_new_line ();
21131acd27e7Smillert   return (0);
21141acd27e7Smillert }
21151acd27e7Smillert 
2116af70c2dfSkettenis /* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound.  Right
2117af70c2dfSkettenis    now, this is always used to attempt to bind the arrow keys, hence the
2118af70c2dfSkettenis    check for rl_vi_movement_mode. */
21191acd27e7Smillert void
_rl_bind_if_unbound(keyseq,default_func)21201acd27e7Smillert _rl_bind_if_unbound (keyseq, default_func)
2121af70c2dfSkettenis      const char *keyseq;
2122af70c2dfSkettenis      rl_command_func_t *default_func;
21231acd27e7Smillert {
2124af70c2dfSkettenis   rl_command_func_t *func;
21251acd27e7Smillert 
21261acd27e7Smillert   if (keyseq)
21271acd27e7Smillert     {
21281acd27e7Smillert       func = rl_function_of_keyseq (keyseq, _rl_keymap, (int *)NULL);
2129af70c2dfSkettenis #if defined (VI_MODE)
2130af70c2dfSkettenis       if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode)
2131af70c2dfSkettenis #else
21321acd27e7Smillert       if (!func || func == rl_do_lowercase_version)
2133af70c2dfSkettenis #endif
21341acd27e7Smillert 	rl_set_key (keyseq, default_func, _rl_keymap);
21351acd27e7Smillert     }
21361acd27e7Smillert }
21371acd27e7Smillert 
21381acd27e7Smillert /* Return non-zero if any members of ARRAY are a substring in STRING. */
21391acd27e7Smillert static int
substring_member_of_array(string,array)21401acd27e7Smillert substring_member_of_array (string, array)
2141af70c2dfSkettenis      char *string;
2142af70c2dfSkettenis      const char **array;
21431acd27e7Smillert {
21441acd27e7Smillert   while (*array)
21451acd27e7Smillert     {
21461acd27e7Smillert       if (_rl_strindex (string, *array))
21471acd27e7Smillert 	return (1);
21481acd27e7Smillert       array++;
21491acd27e7Smillert     }
21501acd27e7Smillert   return (0);
21511acd27e7Smillert }
2152