121308Sache/* bind.c -- key binding and startup file support for the readline library. */
221308Sache
3165670Sache/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
421308Sache
521308Sache   This file is part of the GNU Readline Library, a library for
621308Sache   reading lines of text with interactive input and history editing.
721308Sache
821308Sache   The GNU Readline Library is free software; you can redistribute it
921308Sache   and/or modify it under the terms of the GNU General Public License
1058310Sache   as published by the Free Software Foundation; either version 2, or
1121308Sache   (at your option) any later version.
1221308Sache
1321308Sache   The GNU Readline Library is distributed in the hope that it will be
1421308Sache   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
1521308Sache   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1621308Sache   GNU General Public License for more details.
1721308Sache
1821308Sache   The GNU General Public License is often shipped with GNU software, and
1921308Sache   is generally kept in a file called COPYING or LICENSE.  If you do not
2021308Sache   have a copy of the license, write to the Free Software Foundation,
2158310Sache   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
22136644Sache
2321308Sache#define READLINE_LIBRARY
2421308Sache
25136644Sache#if defined (__TANDEM)
26136644Sache#  include <floss.h>
27136644Sache#endif
28136644Sache
2921308Sache#if defined (HAVE_CONFIG_H)
3021308Sache#  include <config.h>
3121308Sache#endif
3221308Sache
3321308Sache#include <stdio.h>
3421308Sache#include <sys/types.h>
3521308Sache#include <fcntl.h>
3621308Sache#if defined (HAVE_SYS_FILE_H)
3721308Sache#  include <sys/file.h>
3821308Sache#endif /* HAVE_SYS_FILE_H */
3921308Sache
4021308Sache#if defined (HAVE_UNISTD_H)
4121308Sache#  include <unistd.h>
4221308Sache#endif /* HAVE_UNISTD_H */
4321308Sache
4421308Sache#if defined (HAVE_STDLIB_H)
4521308Sache#  include <stdlib.h>
4621308Sache#else
4721308Sache#  include "ansi_stdlib.h"
4821308Sache#endif /* HAVE_STDLIB_H */
4921308Sache
5021308Sache#include <errno.h>
5121308Sache
5221308Sache#if !defined (errno)
5321308Sacheextern int errno;
5421308Sache#endif /* !errno */
5521308Sache
5621308Sache#include "posixstat.h"
5721308Sache
5821308Sache/* System-specific feature definitions and include files. */
5921308Sache#include "rldefs.h"
6021308Sache
6121308Sache/* Some standard library routines. */
6221308Sache#include "readline.h"
6321308Sache#include "history.h"
6421308Sache
6558310Sache#include "rlprivate.h"
6658310Sache#include "rlshell.h"
6758310Sache#include "xmalloc.h"
6858310Sache
6921308Sache#if !defined (strchr) && !defined (__STDC__)
7021308Sacheextern char *strchr (), *strrchr ();
7121308Sache#endif /* !strchr && !__STDC__ */
7221308Sache
7321308Sache/* Variables exported by this file. */
7421308SacheKeymap rl_binding_keymap;
7521308Sache
76119610Sachestatic char *_rl_read_file PARAMS((char *, size_t *));
77119610Sachestatic void _rl_init_file_error PARAMS((const char *));
78119610Sachestatic int _rl_read_init_file PARAMS((const char *, int));
79119610Sachestatic int glean_key_from_name PARAMS((char *));
80157184Sachestatic int find_boolean_var PARAMS((const char *));
81157184Sache
82157184Sachestatic char *_rl_get_string_variable_value PARAMS((const char *));
83119610Sachestatic int substring_member_of_array PARAMS((char *, const char **));
8421308Sache
8558310Sachestatic int currently_reading_init_file;
8621308Sache
8758310Sache/* used only in this file */
8858310Sachestatic int _rl_prefer_visible_bell = 1;
8921308Sache
9021308Sache/* **************************************************************** */
9121308Sache/*								    */
9221308Sache/*			Binding keys				    */
9321308Sache/*								    */
9421308Sache/* **************************************************************** */
9521308Sache
9675406Sache/* rl_add_defun (char *name, rl_command_func_t *function, int key)
9721308Sache   Add NAME to the list of named functions.  Make FUNCTION be the function
9821308Sache   that gets called.  If KEY is not -1, then bind it. */
9921308Sacheint
10021308Sacherl_add_defun (name, function, key)
10175406Sache     const char *name;
10275406Sache     rl_command_func_t *function;
10321308Sache     int key;
10421308Sache{
10521308Sache  if (key != -1)
10621308Sache    rl_bind_key (key, function);
10721308Sache  rl_add_funmap_entry (name, function);
10821308Sache  return 0;
10921308Sache}
11021308Sache
11121308Sache/* Bind KEY to FUNCTION.  Returns non-zero if KEY is out of range. */
11221308Sacheint
11321308Sacherl_bind_key (key, function)
11421308Sache     int key;
11575406Sache     rl_command_func_t *function;
11621308Sache{
11721308Sache  if (key < 0)
11821308Sache    return (key);
11921308Sache
12021308Sache  if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
12121308Sache    {
12221308Sache      if (_rl_keymap[ESC].type == ISKMAP)
12321308Sache	{
12421308Sache	  Keymap escmap;
12521308Sache
12621308Sache	  escmap = FUNCTION_TO_KEYMAP (_rl_keymap, ESC);
12721308Sache	  key = UNMETA (key);
12821308Sache	  escmap[key].type = ISFUNC;
12921308Sache	  escmap[key].function = function;
13021308Sache	  return (0);
13121308Sache	}
13221308Sache      return (key);
13321308Sache    }
13421308Sache
13521308Sache  _rl_keymap[key].type = ISFUNC;
13621308Sache  _rl_keymap[key].function = function;
13721308Sache  rl_binding_keymap = _rl_keymap;
13821308Sache  return (0);
13921308Sache}
14021308Sache
14121308Sache/* Bind KEY to FUNCTION in MAP.  Returns non-zero in case of invalid
14221308Sache   KEY. */
14321308Sacheint
14421308Sacherl_bind_key_in_map (key, function, map)
14521308Sache     int key;
14675406Sache     rl_command_func_t *function;
14721308Sache     Keymap map;
14821308Sache{
14921308Sache  int result;
15021308Sache  Keymap oldmap;
15121308Sache
15221308Sache  oldmap = _rl_keymap;
15321308Sache  _rl_keymap = map;
15421308Sache  result = rl_bind_key (key, function);
15521308Sache  _rl_keymap = oldmap;
15621308Sache  return (result);
15721308Sache}
15821308Sache
159136644Sache/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound.  Right
160136644Sache   now, this is always used to attempt to bind the arrow keys, hence the
161136644Sache   check for rl_vi_movement_mode. */
162136644Sacheint
163136644Sacherl_bind_key_if_unbound_in_map (key, default_func, kmap)
164136644Sache     int key;
165136644Sache     rl_command_func_t *default_func;
166136644Sache     Keymap kmap;
167136644Sache{
168136644Sache  char keyseq[2];
169136644Sache
170136644Sache  keyseq[0] = (unsigned char)key;
171136644Sache  keyseq[1] = '\0';
172136644Sache  return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap));
173136644Sache}
174136644Sache
175136644Sacheint
176136644Sacherl_bind_key_if_unbound (key, default_func)
177136644Sache     int key;
178136644Sache     rl_command_func_t *default_func;
179136644Sache{
180136644Sache  char keyseq[2];
181136644Sache
182136644Sache  keyseq[0] = (unsigned char)key;
183136644Sache  keyseq[1] = '\0';
184136644Sache  return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
185136644Sache}
186136644Sache
18721308Sache/* Make KEY do nothing in the currently selected keymap.
18821308Sache   Returns non-zero in case of error. */
18921308Sacheint
19021308Sacherl_unbind_key (key)
19121308Sache     int key;
19221308Sache{
19375406Sache  return (rl_bind_key (key, (rl_command_func_t *)NULL));
19421308Sache}
19521308Sache
19621308Sache/* Make KEY do nothing in MAP.
19721308Sache   Returns non-zero in case of error. */
19821308Sacheint
19921308Sacherl_unbind_key_in_map (key, map)
20021308Sache     int key;
20121308Sache     Keymap map;
20221308Sache{
20375406Sache  return (rl_bind_key_in_map (key, (rl_command_func_t *)NULL, map));
20421308Sache}
20521308Sache
20635486Sache/* Unbind all keys bound to FUNCTION in MAP. */
20735486Sacheint
20835486Sacherl_unbind_function_in_map (func, map)
20975406Sache     rl_command_func_t *func;
21035486Sache     Keymap map;
21135486Sache{
21247558Sache  register int i, rval;
21335486Sache
21447558Sache  for (i = rval = 0; i < KEYMAP_SIZE; i++)
21535486Sache    {
21635486Sache      if (map[i].type == ISFUNC && map[i].function == func)
21747558Sache	{
21875406Sache	  map[i].function = (rl_command_func_t *)NULL;
21947558Sache	  rval = 1;
22047558Sache	}
22135486Sache    }
22247558Sache  return rval;
22335486Sache}
22435486Sache
22535486Sacheint
22635486Sacherl_unbind_command_in_map (command, map)
22775406Sache     const char *command;
22835486Sache     Keymap map;
22935486Sache{
23075406Sache  rl_command_func_t *func;
23135486Sache
23235486Sache  func = rl_named_function (command);
23335486Sache  if (func == 0)
23435486Sache    return 0;
23535486Sache  return (rl_unbind_function_in_map (func, map));
23635486Sache}
23735486Sache
23821308Sache/* Bind the key sequence represented by the string KEYSEQ to
239136644Sache   FUNCTION, starting in the current keymap.  This makes new
240136644Sache   keymaps as necessary. */
241136644Sacheint
242136644Sacherl_bind_keyseq (keyseq, function)
243136644Sache     const char *keyseq;
244136644Sache     rl_command_func_t *function;
245136644Sache{
246136644Sache  return (rl_generic_bind (ISFUNC, keyseq, (char *)function, _rl_keymap));
247136644Sache}
248136644Sache
249136644Sache/* Bind the key sequence represented by the string KEYSEQ to
25021308Sache   FUNCTION.  This makes new keymaps as necessary.  The initial
25121308Sache   place to do bindings is in MAP. */
25221308Sacheint
253136644Sacherl_bind_keyseq_in_map (keyseq, function, map)
254136644Sache     const char *keyseq;
255136644Sache     rl_command_func_t *function;
256136644Sache     Keymap map;
257136644Sache{
258136644Sache  return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
259136644Sache}
260136644Sache
261136644Sache/* Backwards compatibility; equivalent to rl_bind_keyseq_in_map() */
262136644Sacheint
26321308Sacherl_set_key (keyseq, function, map)
26475406Sache     const char *keyseq;
26575406Sache     rl_command_func_t *function;
26621308Sache     Keymap map;
26721308Sache{
26826497Sache  return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
26921308Sache}
27021308Sache
271136644Sache/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound.  Right
272136644Sache   now, this is always used to attempt to bind the arrow keys, hence the
273136644Sache   check for rl_vi_movement_mode. */
274136644Sacheint
275136644Sacherl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap)
276136644Sache     const char *keyseq;
277136644Sache     rl_command_func_t *default_func;
278136644Sache     Keymap kmap;
279136644Sache{
280136644Sache  rl_command_func_t *func;
281136644Sache
282136644Sache  if (keyseq)
283136644Sache    {
284136644Sache      func = rl_function_of_keyseq (keyseq, kmap, (int *)NULL);
285136644Sache#if defined (VI_MODE)
286136644Sache      if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode)
287136644Sache#else
288136644Sache      if (!func || func == rl_do_lowercase_version)
289136644Sache#endif
290136644Sache	return (rl_bind_keyseq_in_map (keyseq, default_func, kmap));
291136644Sache      else
292136644Sache	return 1;
293136644Sache    }
294136644Sache  return 0;
295136644Sache}
296136644Sache
297136644Sacheint
298136644Sacherl_bind_keyseq_if_unbound (keyseq, default_func)
299136644Sache     const char *keyseq;
300136644Sache     rl_command_func_t *default_func;
301136644Sache{
302136644Sache  return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
303136644Sache}
304136644Sache
30521308Sache/* Bind the key sequence represented by the string KEYSEQ to
30621308Sache   the string of characters MACRO.  This makes new keymaps as
30721308Sache   necessary.  The initial place to do bindings is in MAP. */
30821308Sacheint
30921308Sacherl_macro_bind (keyseq, macro, map)
31075406Sache     const char *keyseq, *macro;
31121308Sache     Keymap map;
31221308Sache{
31321308Sache  char *macro_keys;
31421308Sache  int macro_keys_len;
31521308Sache
31621308Sache  macro_keys = (char *)xmalloc ((2 * strlen (macro)) + 1);
31721308Sache
31821308Sache  if (rl_translate_keyseq (macro, macro_keys, &macro_keys_len))
31921308Sache    {
32021308Sache      free (macro_keys);
32121308Sache      return -1;
32221308Sache    }
32321308Sache  rl_generic_bind (ISMACR, keyseq, macro_keys, map);
32421308Sache  return 0;
32521308Sache}
32621308Sache
32721308Sache/* Bind the key sequence represented by the string KEYSEQ to
32821308Sache   the arbitrary pointer DATA.  TYPE says what kind of data is
32921308Sache   pointed to by DATA, right now this can be a function (ISFUNC),
33021308Sache   a macro (ISMACR), or a keymap (ISKMAP).  This makes new keymaps
33121308Sache   as necessary.  The initial place to do bindings is in MAP. */
33221308Sacheint
33321308Sacherl_generic_bind (type, keyseq, data, map)
33421308Sache     int type;
33575406Sache     const char *keyseq;
33675406Sache     char *data;
33721308Sache     Keymap map;
33821308Sache{
33921308Sache  char *keys;
34021308Sache  int keys_len;
34121308Sache  register int i;
342119610Sache  KEYMAP_ENTRY k;
34321308Sache
344119610Sache  k.function = 0;
345119610Sache
34621308Sache  /* If no keys to bind to, exit right away. */
347157184Sache  if (keyseq == 0 || *keyseq == 0)
34821308Sache    {
34921308Sache      if (type == ISMACR)
35021308Sache	free (data);
35121308Sache      return -1;
35221308Sache    }
35321308Sache
354119610Sache  keys = (char *)xmalloc (1 + (2 * strlen (keyseq)));
35521308Sache
35621308Sache  /* Translate the ASCII representation of KEYSEQ into an array of
35721308Sache     characters.  Stuff the characters into KEYS, and the length of
35821308Sache     KEYS into KEYS_LEN. */
35921308Sache  if (rl_translate_keyseq (keyseq, keys, &keys_len))
36021308Sache    {
36121308Sache      free (keys);
36221308Sache      return -1;
36321308Sache    }
36421308Sache
36521308Sache  /* Bind keys, making new keymaps as necessary. */
36621308Sache  for (i = 0; i < keys_len; i++)
36721308Sache    {
368119610Sache      unsigned char uc = keys[i];
369119610Sache      int ic;
37021308Sache
371119610Sache      ic = uc;
372119610Sache      if (ic < 0 || ic >= KEYMAP_SIZE)
373165670Sache        {
374165670Sache          free (keys);
375165670Sache	  return -1;
376165670Sache        }
377119610Sache
378157184Sache      if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
37921308Sache	{
38021308Sache	  ic = UNMETA (ic);
38121308Sache	  if (map[ESC].type == ISKMAP)
38221308Sache	    map = FUNCTION_TO_KEYMAP (map, ESC);
38321308Sache	}
38421308Sache
38521308Sache      if ((i + 1) < keys_len)
38621308Sache	{
38721308Sache	  if (map[ic].type != ISKMAP)
38821308Sache	    {
389119610Sache	      /* We allow subsequences of keys.  If a keymap is being
390119610Sache		 created that will `shadow' an existing function or macro
391119610Sache		 key binding, we save that keybinding into the ANYOTHERKEY
392119610Sache		 index in the new map.  The dispatch code will look there
393119610Sache		 to find the function to execute if the subsequence is not
394119610Sache		 matched.  ANYOTHERKEY was chosen to be greater than
395119610Sache		 UCHAR_MAX. */
396119610Sache	      k = map[ic];
39721308Sache
39821308Sache	      map[ic].type = ISKMAP;
39921308Sache	      map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap());
40021308Sache	    }
40121308Sache	  map = FUNCTION_TO_KEYMAP (map, ic);
402119610Sache	  /* The dispatch code will return this function if no matching
403119610Sache	     key sequence is found in the keymap.  This (with a little
404119610Sache	     help from the dispatch code in readline.c) allows `a' to be
405119610Sache	     mapped to something, `abc' to be mapped to something else,
406119610Sache	     and the function bound  to `a' to be executed when the user
407119610Sache	     types `abx', leaving `bx' in the input queue. */
408125759Sache	  if (k.function && ((k.type == ISFUNC && k.function != rl_do_lowercase_version) || k.type == ISMACR))
409119610Sache	    {
410119610Sache	      map[ANYOTHERKEY] = k;
411119610Sache	      k.function = 0;
412119610Sache	    }
41321308Sache	}
41421308Sache      else
41521308Sache	{
41621308Sache	  if (map[ic].type == ISMACR)
41721308Sache	    free ((char *)map[ic].function);
418119610Sache	  else if (map[ic].type == ISKMAP)
419119610Sache	    {
420119610Sache	      map = FUNCTION_TO_KEYMAP (map, ic);
421119610Sache	      ic = ANYOTHERKEY;
422119610Sache	    }
42321308Sache
42421308Sache	  map[ic].function = KEYMAP_TO_FUNCTION (data);
42521308Sache	  map[ic].type = type;
42621308Sache	}
42721308Sache
42821308Sache      rl_binding_keymap = map;
42921308Sache    }
43021308Sache  free (keys);
43121308Sache  return 0;
43221308Sache}
43321308Sache
43421308Sache/* Translate the ASCII representation of SEQ, stuffing the values into ARRAY,
43521308Sache   an array of characters.  LEN gets the final length of ARRAY.  Return
43621308Sache   non-zero if there was an error parsing SEQ. */
43721308Sacheint
43821308Sacherl_translate_keyseq (seq, array, len)
43975406Sache     const char *seq;
44075406Sache     char *array;
44121308Sache     int *len;
44221308Sache{
44335486Sache  register int i, c, l, temp;
44421308Sache
44521308Sache  for (i = l = 0; c = seq[i]; i++)
44621308Sache    {
44721308Sache      if (c == '\\')
44821308Sache	{
44921308Sache	  c = seq[++i];
45021308Sache
45121308Sache	  if (c == 0)
45221308Sache	    break;
45321308Sache
45435486Sache	  /* Handle \C- and \M- prefixes. */
45535486Sache	  if ((c == 'C' || c == 'M') && seq[i + 1] == '-')
45621308Sache	    {
45721308Sache	      /* Handle special case of backwards define. */
45821308Sache	      if (strncmp (&seq[i], "C-\\M-", 5) == 0)
45921308Sache		{
460119610Sache		  array[l++] = ESC;	/* ESC is meta-prefix */
46121308Sache		  i += 5;
46221308Sache		  array[l++] = CTRL (_rl_to_upper (seq[i]));
46335486Sache		  if (seq[i] == '\0')
46421308Sache		    i--;
46521308Sache		}
46635486Sache	      else if (c == 'M')
46721308Sache		{
468165670Sache		  i++;		/* seq[i] == '-' */
469165670Sache		  /* XXX - obey convert-meta setting */
470157184Sache		  if (_rl_convert_meta_chars_to_ascii && _rl_keymap[ESC].type == ISKMAP)
471157184Sache		    array[l++] = ESC;	/* ESC is meta-prefix */
472165670Sache		  else if (seq[i+1] == '\\' && seq[i+2] == 'C' && seq[i+3] == '-')
473165670Sache		    {
474165670Sache		      i += 4;
475165670Sache		      temp = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
476165670Sache		      array[l++] = META (temp);
477165670Sache		    }
478157184Sache		  else
479157184Sache		    {
480165670Sache		      /* This doesn't yet handle things like \M-\a, which may
481165670Sache			 or may not have any reasonable meaning.  You're
482165670Sache			 probably better off using straight octal or hex. */
483157184Sache		      i++;
484157184Sache		      array[l++] = META (seq[i]);
485157184Sache		    }
48635486Sache		}
48735486Sache	      else if (c == 'C')
48835486Sache		{
48921308Sache		  i += 2;
49021308Sache		  /* Special hack for C-?... */
49121308Sache		  array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
49221308Sache		}
49335486Sache	      continue;
49435486Sache	    }
49521308Sache
49635486Sache	  /* Translate other backslash-escaped characters.  These are the
49735486Sache	     same escape sequences that bash's `echo' and `printf' builtins
49835486Sache	     handle, with the addition of \d -> RUBOUT.  A backslash
49935486Sache	     preceding a character that is not special is stripped. */
50035486Sache	  switch (c)
50135486Sache	    {
50235486Sache	    case 'a':
50335486Sache	      array[l++] = '\007';
50435486Sache	      break;
50535486Sache	    case 'b':
50635486Sache	      array[l++] = '\b';
50735486Sache	      break;
50835486Sache	    case 'd':
50935486Sache	      array[l++] = RUBOUT;	/* readline-specific */
51035486Sache	      break;
51135486Sache	    case 'e':
51235486Sache	      array[l++] = ESC;
51335486Sache	      break;
51435486Sache	    case 'f':
51535486Sache	      array[l++] = '\f';
51635486Sache	      break;
51735486Sache	    case 'n':
51835486Sache	      array[l++] = NEWLINE;
51935486Sache	      break;
52035486Sache	    case 'r':
52135486Sache	      array[l++] = RETURN;
52235486Sache	      break;
52335486Sache	    case 't':
52435486Sache	      array[l++] = TAB;
52535486Sache	      break;
52635486Sache	    case 'v':
52735486Sache	      array[l++] = 0x0B;
52835486Sache	      break;
52935486Sache	    case '\\':
53035486Sache	      array[l++] = '\\';
53135486Sache	      break;
53235486Sache	    case '0': case '1': case '2': case '3':
53335486Sache	    case '4': case '5': case '6': case '7':
53435486Sache	      i++;
53535486Sache	      for (temp = 2, c -= '0'; ISOCTAL (seq[i]) && temp--; i++)
53635486Sache	        c = (c * 8) + OCTVALUE (seq[i]);
53735486Sache	      i--;	/* auto-increment in for loop */
538119610Sache	      array[l++] = c & largest_char;
53935486Sache	      break;
54035486Sache	    case 'x':
54135486Sache	      i++;
542119610Sache	      for (temp = 2, c = 0; ISXDIGIT ((unsigned char)seq[i]) && temp--; i++)
54335486Sache	        c = (c * 16) + HEXVALUE (seq[i]);
544119610Sache	      if (temp == 2)
54535486Sache	        c = 'x';
54635486Sache	      i--;	/* auto-increment in for loop */
547119610Sache	      array[l++] = c & largest_char;
54835486Sache	      break;
54935486Sache	    default:	/* backslashes before non-special chars just add the char */
55035486Sache	      array[l++] = c;
55135486Sache	      break;	/* the backslash is stripped */
55221308Sache	    }
55335486Sache	  continue;
55421308Sache	}
55535486Sache
55621308Sache      array[l++] = c;
55721308Sache    }
55821308Sache
55921308Sache  *len = l;
56021308Sache  array[l] = '\0';
56121308Sache  return (0);
56221308Sache}
56321308Sache
56421308Sachechar *
56521308Sacherl_untranslate_keyseq (seq)
56621308Sache     int seq;
56721308Sache{
56821308Sache  static char kseq[16];
56921308Sache  int i, c;
57021308Sache
57121308Sache  i = 0;
57221308Sache  c = seq;
57321308Sache  if (META_CHAR (c))
57421308Sache    {
57521308Sache      kseq[i++] = '\\';
57621308Sache      kseq[i++] = 'M';
57721308Sache      kseq[i++] = '-';
57821308Sache      c = UNMETA (c);
57921308Sache    }
580165670Sache  else if (c == ESC)
581165670Sache    {
582165670Sache      kseq[i++] = '\\';
583165670Sache      c = 'e';
584165670Sache    }
58521308Sache  else if (CTRL_CHAR (c))
58621308Sache    {
58721308Sache      kseq[i++] = '\\';
58821308Sache      kseq[i++] = 'C';
58921308Sache      kseq[i++] = '-';
59026497Sache      c = _rl_to_lower (UNCTRL (c));
59121308Sache    }
59221308Sache  else if (c == RUBOUT)
59321308Sache    {
59421308Sache      kseq[i++] = '\\';
59521308Sache      kseq[i++] = 'C';
59621308Sache      kseq[i++] = '-';
59721308Sache      c = '?';
59821308Sache    }
59921308Sache
60021308Sache  if (c == ESC)
60121308Sache    {
60221308Sache      kseq[i++] = '\\';
60326497Sache      c = 'e';
60421308Sache    }
60521308Sache  else if (c == '\\' || c == '"')
60621308Sache    {
60721308Sache      kseq[i++] = '\\';
60821308Sache    }
60921308Sache
61021308Sache  kseq[i++] = (unsigned char) c;
61121308Sache  kseq[i] = '\0';
61221308Sache  return kseq;
61321308Sache}
61421308Sache
61526497Sachestatic char *
61626497Sache_rl_untranslate_macro_value (seq)
61726497Sache     char *seq;
61826497Sache{
61926497Sache  char *ret, *r, *s;
62026497Sache  int c;
62126497Sache
622119610Sache  r = ret = (char *)xmalloc (7 * strlen (seq) + 1);
62326497Sache  for (s = seq; *s; s++)
62426497Sache    {
62526497Sache      c = *s;
62626497Sache      if (META_CHAR (c))
62726497Sache	{
62826497Sache	  *r++ = '\\';
62926497Sache	  *r++ = 'M';
63026497Sache	  *r++ = '-';
63126497Sache	  c = UNMETA (c);
63226497Sache	}
633165670Sache      else if (c == ESC)
63426497Sache	{
63526497Sache	  *r++ = '\\';
636165670Sache	  c = 'e';
637165670Sache	}
638165670Sache      else if (CTRL_CHAR (c))
639165670Sache	{
640165670Sache	  *r++ = '\\';
64126497Sache	  *r++ = 'C';
64226497Sache	  *r++ = '-';
64326497Sache	  c = _rl_to_lower (UNCTRL (c));
64426497Sache	}
64526497Sache      else if (c == RUBOUT)
64626497Sache 	{
64726497Sache 	  *r++ = '\\';
64826497Sache 	  *r++ = 'C';
64926497Sache 	  *r++ = '-';
65026497Sache 	  c = '?';
65126497Sache 	}
65226497Sache
65326497Sache      if (c == ESC)
65426497Sache	{
65526497Sache	  *r++ = '\\';
65626497Sache	  c = 'e';
65726497Sache	}
65826497Sache      else if (c == '\\' || c == '"')
65926497Sache	*r++ = '\\';
66026497Sache
66126497Sache      *r++ = (unsigned char)c;
66226497Sache    }
66326497Sache  *r = '\0';
66426497Sache  return ret;
66526497Sache}
66626497Sache
66721308Sache/* Return a pointer to the function that STRING represents.
66821308Sache   If STRING doesn't have a matching function, then a NULL pointer
66921308Sache   is returned. */
67075406Sacherl_command_func_t *
67121308Sacherl_named_function (string)
67275406Sache     const char *string;
67321308Sache{
67421308Sache  register int i;
67521308Sache
67621308Sache  rl_initialize_funmap ();
67721308Sache
67821308Sache  for (i = 0; funmap[i]; i++)
67921308Sache    if (_rl_stricmp (funmap[i]->name, string) == 0)
68021308Sache      return (funmap[i]->function);
68175406Sache  return ((rl_command_func_t *)NULL);
68221308Sache}
68321308Sache
68421308Sache/* Return the function (or macro) definition which would be invoked via
68521308Sache   KEYSEQ if executed in MAP.  If MAP is NULL, then the current keymap is
68621308Sache   used.  TYPE, if non-NULL, is a pointer to an int which will receive the
68721308Sache   type of the object pointed to.  One of ISFUNC (function), ISKMAP (keymap),
68821308Sache   or ISMACR (macro). */
68975406Sacherl_command_func_t *
69021308Sacherl_function_of_keyseq (keyseq, map, type)
69175406Sache     const char *keyseq;
69221308Sache     Keymap map;
69321308Sache     int *type;
69421308Sache{
69521308Sache  register int i;
69621308Sache
697165670Sache  if (map == 0)
69821308Sache    map = _rl_keymap;
69921308Sache
70021308Sache  for (i = 0; keyseq && keyseq[i]; i++)
70121308Sache    {
702119610Sache      unsigned char ic = keyseq[i];
70321308Sache
70421308Sache      if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
70521308Sache	{
706165670Sache	  if (map[ESC].type == ISKMAP)
70721308Sache	    {
708165670Sache	      map = FUNCTION_TO_KEYMAP (map, ESC);
709165670Sache	      ic = UNMETA (ic);
710165670Sache	    }
711165670Sache	  /* XXX - should we just return NULL here, since this obviously
712165670Sache	     doesn't match? */
713165670Sache	  else
714165670Sache	    {
71521308Sache	      if (type)
71621308Sache		*type = map[ESC].type;
71721308Sache
71821308Sache	      return (map[ESC].function);
71921308Sache	    }
72021308Sache	}
72121308Sache
72221308Sache      if (map[ic].type == ISKMAP)
72321308Sache	{
72421308Sache	  /* If this is the last key in the key sequence, return the
72521308Sache	     map. */
726165670Sache	  if (keyseq[i + 1] == '\0')
72721308Sache	    {
72821308Sache	      if (type)
72921308Sache		*type = ISKMAP;
73021308Sache
73121308Sache	      return (map[ic].function);
73221308Sache	    }
73321308Sache	  else
73421308Sache	    map = FUNCTION_TO_KEYMAP (map, ic);
73521308Sache	}
736165670Sache      /* If we're not at the end of the key sequence, and the current key
737165670Sache	 is bound to something other than a keymap, then the entire key
738165670Sache	 sequence is not bound. */
739165670Sache      else if (map[ic].type != ISKMAP && keyseq[i+1])
740165670Sache	return ((rl_command_func_t *)NULL);
741165670Sache      else	/* map[ic].type != ISKMAP && keyseq[i+1] == 0 */
74221308Sache	{
74321308Sache	  if (type)
74421308Sache	    *type = map[ic].type;
74521308Sache
74621308Sache	  return (map[ic].function);
74721308Sache	}
74821308Sache    }
74975406Sache  return ((rl_command_func_t *) NULL);
75021308Sache}
75121308Sache
75221308Sache/* The last key bindings file read. */
75321308Sachestatic char *last_readline_init_file = (char *)NULL;
75421308Sache
75521308Sache/* The file we're currently reading key bindings from. */
75675406Sachestatic const char *current_readline_init_file;
75735486Sachestatic int current_readline_init_include_level;
75821308Sachestatic int current_readline_init_lineno;
75921308Sache
76035486Sache/* Read FILENAME into a locally-allocated buffer and return the buffer.
76135486Sache   The size of the buffer is returned in *SIZEP.  Returns NULL if any
76235486Sache   errors were encountered. */
76335486Sachestatic char *
76435486Sache_rl_read_file (filename, sizep)
76535486Sache     char *filename;
76635486Sache     size_t *sizep;
76735486Sache{
76835486Sache  struct stat finfo;
76935486Sache  size_t file_size;
77035486Sache  char *buffer;
77135486Sache  int i, file;
77235486Sache
77335486Sache  if ((stat (filename, &finfo) < 0) || (file = open (filename, O_RDONLY, 0666)) < 0)
77435486Sache    return ((char *)NULL);
77535486Sache
77635486Sache  file_size = (size_t)finfo.st_size;
77735486Sache
77835486Sache  /* check for overflow on very large files */
77935486Sache  if (file_size != finfo.st_size || file_size + 1 < file_size)
78035486Sache    {
78135486Sache      if (file >= 0)
78235486Sache	close (file);
78335486Sache#if defined (EFBIG)
78435486Sache      errno = EFBIG;
78535486Sache#endif
78635486Sache      return ((char *)NULL);
78735486Sache    }
78835486Sache
78935486Sache  /* Read the file into BUFFER. */
79035486Sache  buffer = (char *)xmalloc (file_size + 1);
79135486Sache  i = read (file, buffer, file_size);
79235486Sache  close (file);
79335486Sache
79447558Sache  if (i < 0)
79535486Sache    {
79635486Sache      free (buffer);
79735486Sache      return ((char *)NULL);
79835486Sache    }
79935486Sache
80058310Sache  buffer[i] = '\0';
80158310Sache  if (sizep)
80258310Sache    *sizep = i;
80358310Sache
80435486Sache  return (buffer);
80535486Sache}
80635486Sache
80721308Sache/* Re-read the current keybindings file. */
80821308Sacheint
80921308Sacherl_re_read_init_file (count, ignore)
81021308Sache     int count, ignore;
81121308Sache{
81221308Sache  int r;
81375406Sache  r = rl_read_init_file ((const char *)NULL);
81421308Sache  rl_set_keymap_from_edit_mode ();
81521308Sache  return r;
81621308Sache}
81721308Sache
81821308Sache/* Do key bindings from a file.  If FILENAME is NULL it defaults
81921308Sache   to the first non-null filename from this list:
82021308Sache     1. the filename used for the previous call
82121308Sache     2. the value of the shell variable `INPUTRC'
82221308Sache     3. ~/.inputrc
823165670Sache     4. /etc/inputrc
82421308Sache   If the file existed and could be opened and read, 0 is returned,
82521308Sache   otherwise errno is returned. */
82621308Sacheint
82721308Sacherl_read_init_file (filename)
82875406Sache     const char *filename;
82921308Sache{
83021308Sache  /* Default the filename. */
83121308Sache  if (filename == 0)
832165670Sache    filename = last_readline_init_file;
833165670Sache  if (filename == 0)
834165670Sache    filename = sh_get_env_value ("INPUTRC");
835165670Sache  if (filename == 0 || *filename == 0)
83621308Sache    {
837165670Sache      filename = DEFAULT_INPUTRC;
838165670Sache      /* Try to read DEFAULT_INPUTRC; fall back to SYS_INPUTRC on failure */
839165670Sache      if (_rl_read_init_file (filename, 0) == 0)
840165670Sache	return 0;
841165670Sache      filename = SYS_INPUTRC;
84221308Sache    }
84321308Sache
84458310Sache#if defined (__MSDOS__)
84558310Sache  if (_rl_read_init_file (filename, 0) == 0)
84658310Sache    return 0;
84758310Sache  filename = "~/_inputrc";
84858310Sache#endif
84935486Sache  return (_rl_read_init_file (filename, 0));
85035486Sache}
85135486Sache
85235486Sachestatic int
85335486Sache_rl_read_init_file (filename, include_level)
85475406Sache     const char *filename;
85535486Sache     int include_level;
85635486Sache{
85735486Sache  register int i;
85835486Sache  char *buffer, *openname, *line, *end;
85935486Sache  size_t file_size;
86035486Sache
86121308Sache  current_readline_init_file = filename;
86235486Sache  current_readline_init_include_level = include_level;
86335486Sache
86421308Sache  openname = tilde_expand (filename);
86535486Sache  buffer = _rl_read_file (openname, &file_size);
86647558Sache  free (openname);
86747558Sache
86835486Sache  if (buffer == 0)
86935486Sache    return (errno);
87035486Sache
87135486Sache  if (include_level == 0 && filename != last_readline_init_file)
87221308Sache    {
87335486Sache      FREE (last_readline_init_file);
87421308Sache      last_readline_init_file = savestring (filename);
87521308Sache    }
87621308Sache
87758310Sache  currently_reading_init_file = 1;
87858310Sache
87921308Sache  /* Loop over the lines in the file.  Lines that start with `#' are
88021308Sache     comments; all other lines are commands for readline initialization. */
88121308Sache  current_readline_init_lineno = 1;
88221308Sache  line = buffer;
88335486Sache  end = buffer + file_size;
88421308Sache  while (line < end)
88521308Sache    {
88621308Sache      /* Find the end of this line. */
88721308Sache      for (i = 0; line + i != end && line[i] != '\n'; i++);
88821308Sache
88975406Sache#if defined (__CYGWIN__)
89058310Sache      /* ``Be liberal in what you accept.'' */
89158310Sache      if (line[i] == '\n' && line[i-1] == '\r')
89258310Sache	line[i - 1] = '\0';
89358310Sache#endif
89458310Sache
89521308Sache      /* Mark end of line. */
89621308Sache      line[i] = '\0';
89721308Sache
89821308Sache      /* Skip leading whitespace. */
89921308Sache      while (*line && whitespace (*line))
90021308Sache        {
90121308Sache	  line++;
90221308Sache	  i--;
90321308Sache        }
90421308Sache
90521308Sache      /* If the line is not a comment, then parse it. */
90621308Sache      if (*line && *line != '#')
90721308Sache	rl_parse_and_bind (line);
90821308Sache
90921308Sache      /* Move to the next line. */
91021308Sache      line += i + 1;
91121308Sache      current_readline_init_lineno++;
91221308Sache    }
91335486Sache
91421308Sache  free (buffer);
91558310Sache  currently_reading_init_file = 0;
91621308Sache  return (0);
91721308Sache}
91821308Sache
91921308Sachestatic void
92021308Sache_rl_init_file_error (msg)
921119610Sache     const char *msg;
92221308Sache{
92358310Sache  if (currently_reading_init_file)
92458310Sache    fprintf (stderr, "readline: %s: line %d: %s\n", current_readline_init_file,
92558310Sache		     current_readline_init_lineno, msg);
92658310Sache  else
92758310Sache    fprintf (stderr, "readline: %s\n", msg);
92821308Sache}
92921308Sache
93021308Sache/* **************************************************************** */
93121308Sache/*								    */
93221308Sache/*			Parser Directives       		    */
93321308Sache/*								    */
93421308Sache/* **************************************************************** */
93521308Sache
936119610Sachetypedef int _rl_parser_func_t PARAMS((char *));
93775406Sache
93875406Sache/* Things that mean `Control'. */
93975406Sacheconst char *_rl_possible_control_prefixes[] = {
94075406Sache  "Control-", "C-", "CTRL-", (const char *)NULL
94175406Sache};
94275406Sache
94375406Sacheconst char *_rl_possible_meta_prefixes[] = {
94475406Sache  "Meta", "M-", (const char *)NULL
94575406Sache};
94675406Sache
94721308Sache/* Conditionals. */
94821308Sache
94921308Sache/* Calling programs set this to have their argv[0]. */
95075406Sacheconst char *rl_readline_name = "other";
95121308Sache
95221308Sache/* Stack of previous values of parsing_conditionalized_out. */
95321308Sachestatic unsigned char *if_stack = (unsigned char *)NULL;
95421308Sachestatic int if_stack_depth;
95521308Sachestatic int if_stack_size;
95621308Sache
95721308Sache/* Push _rl_parsing_conditionalized_out, and set parser state based
95821308Sache   on ARGS. */
95921308Sachestatic int
96021308Sacheparser_if (args)
96121308Sache     char *args;
96221308Sache{
96321308Sache  register int i;
96421308Sache
96521308Sache  /* Push parser state. */
96621308Sache  if (if_stack_depth + 1 >= if_stack_size)
96721308Sache    {
96821308Sache      if (!if_stack)
96921308Sache	if_stack = (unsigned char *)xmalloc (if_stack_size = 20);
97021308Sache      else
97121308Sache	if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20);
97221308Sache    }
97321308Sache  if_stack[if_stack_depth++] = _rl_parsing_conditionalized_out;
97421308Sache
97521308Sache  /* If parsing is turned off, then nothing can turn it back on except
97621308Sache     for finding the matching endif.  In that case, return right now. */
97721308Sache  if (_rl_parsing_conditionalized_out)
97821308Sache    return 0;
97921308Sache
98021308Sache  /* Isolate first argument. */
98121308Sache  for (i = 0; args[i] && !whitespace (args[i]); i++);
98221308Sache
98321308Sache  if (args[i])
98421308Sache    args[i++] = '\0';
98521308Sache
98635486Sache  /* Handle "$if term=foo" and "$if mode=emacs" constructs.  If this
98721308Sache     isn't term=foo, or mode=emacs, then check to see if the first
98821308Sache     word in ARGS is the same as the value stored in rl_readline_name. */
98921308Sache  if (rl_terminal_name && _rl_strnicmp (args, "term=", 5) == 0)
99021308Sache    {
99121308Sache      char *tem, *tname;
99221308Sache
99321308Sache      /* Terminals like "aaa-60" are equivalent to "aaa". */
99421308Sache      tname = savestring (rl_terminal_name);
99521308Sache      tem = strchr (tname, '-');
99621308Sache      if (tem)
99721308Sache	*tem = '\0';
99821308Sache
99921308Sache      /* Test the `long' and `short' forms of the terminal name so that
100021308Sache	 if someone has a `sun-cmd' and does not want to have bindings
100121308Sache	 that will be executed if the terminal is a `sun', they can put
100221308Sache	 `$if term=sun-cmd' into their .inputrc. */
100321308Sache      _rl_parsing_conditionalized_out = _rl_stricmp (args + 5, tname) &&
100421308Sache					_rl_stricmp (args + 5, rl_terminal_name);
100521308Sache      free (tname);
100621308Sache    }
100721308Sache#if defined (VI_MODE)
100821308Sache  else if (_rl_strnicmp (args, "mode=", 5) == 0)
100921308Sache    {
101021308Sache      int mode;
101121308Sache
101221308Sache      if (_rl_stricmp (args + 5, "emacs") == 0)
101321308Sache	mode = emacs_mode;
101421308Sache      else if (_rl_stricmp (args + 5, "vi") == 0)
101521308Sache	mode = vi_mode;
101621308Sache      else
101721308Sache	mode = no_mode;
101821308Sache
101921308Sache      _rl_parsing_conditionalized_out = mode != rl_editing_mode;
102021308Sache    }
102121308Sache#endif /* VI_MODE */
102221308Sache  /* Check to see if the first word in ARGS is the same as the
102321308Sache     value stored in rl_readline_name. */
102421308Sache  else if (_rl_stricmp (args, rl_readline_name) == 0)
102521308Sache    _rl_parsing_conditionalized_out = 0;
102621308Sache  else
102721308Sache    _rl_parsing_conditionalized_out = 1;
102821308Sache  return 0;
102921308Sache}
103021308Sache
103121308Sache/* Invert the current parser state if there is anything on the stack. */
103221308Sachestatic int
103321308Sacheparser_else (args)
103421308Sache     char *args;
103521308Sache{
103621308Sache  register int i;
103721308Sache
103835486Sache  if (if_stack_depth == 0)
103921308Sache    {
104035486Sache      _rl_init_file_error ("$else found without matching $if");
104121308Sache      return 0;
104221308Sache    }
104321308Sache
1044136644Sache#if 0
104521308Sache  /* Check the previous (n - 1) levels of the stack to make sure that
104621308Sache     we haven't previously turned off parsing. */
104721308Sache  for (i = 0; i < if_stack_depth - 1; i++)
1048136644Sache#else
1049136644Sache  /* Check the previous (n) levels of the stack to make sure that
1050136644Sache     we haven't previously turned off parsing. */
1051136644Sache  for (i = 0; i < if_stack_depth; i++)
1052136644Sache#endif
105321308Sache    if (if_stack[i] == 1)
105421308Sache      return 0;
105521308Sache
105621308Sache  /* Invert the state of parsing if at top level. */
105721308Sache  _rl_parsing_conditionalized_out = !_rl_parsing_conditionalized_out;
105821308Sache  return 0;
105921308Sache}
106021308Sache
106121308Sache/* Terminate a conditional, popping the value of
106221308Sache   _rl_parsing_conditionalized_out from the stack. */
106321308Sachestatic int
106421308Sacheparser_endif (args)
106521308Sache     char *args;
106621308Sache{
106721308Sache  if (if_stack_depth)
106821308Sache    _rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
106921308Sache  else
107035486Sache    _rl_init_file_error ("$endif without matching $if");
107121308Sache  return 0;
107221308Sache}
107321308Sache
107435486Sachestatic int
107535486Sacheparser_include (args)
107635486Sache     char *args;
107735486Sache{
107875406Sache  const char *old_init_file;
107975406Sache  char *e;
108035486Sache  int old_line_number, old_include_level, r;
108135486Sache
108235486Sache  if (_rl_parsing_conditionalized_out)
108335486Sache    return (0);
108435486Sache
108535486Sache  old_init_file = current_readline_init_file;
108635486Sache  old_line_number = current_readline_init_lineno;
108735486Sache  old_include_level = current_readline_init_include_level;
108835486Sache
108935486Sache  e = strchr (args, '\n');
109035486Sache  if (e)
109135486Sache    *e = '\0';
109275406Sache  r = _rl_read_init_file ((const char *)args, old_include_level + 1);
109335486Sache
109435486Sache  current_readline_init_file = old_init_file;
109535486Sache  current_readline_init_lineno = old_line_number;
109635486Sache  current_readline_init_include_level = old_include_level;
109735486Sache
109835486Sache  return r;
109935486Sache}
110035486Sache
110121308Sache/* Associate textual names with actual functions. */
110221308Sachestatic struct {
110375406Sache  const char *name;
110475406Sache  _rl_parser_func_t *function;
110521308Sache} parser_directives [] = {
110621308Sache  { "if", parser_if },
110721308Sache  { "endif", parser_endif },
110821308Sache  { "else", parser_else },
110935486Sache  { "include", parser_include },
111075406Sache  { (char *)0x0, (_rl_parser_func_t *)0x0 }
111121308Sache};
111221308Sache
111321308Sache/* Handle a parser directive.  STATEMENT is the line of the directive
111421308Sache   without any leading `$'. */
111521308Sachestatic int
111621308Sachehandle_parser_directive (statement)
111721308Sache     char *statement;
111821308Sache{
111921308Sache  register int i;
112021308Sache  char *directive, *args;
112121308Sache
112221308Sache  /* Isolate the actual directive. */
112321308Sache
112421308Sache  /* Skip whitespace. */
112521308Sache  for (i = 0; whitespace (statement[i]); i++);
112621308Sache
112721308Sache  directive = &statement[i];
112821308Sache
112921308Sache  for (; statement[i] && !whitespace (statement[i]); i++);
113021308Sache
113121308Sache  if (statement[i])
113221308Sache    statement[i++] = '\0';
113321308Sache
113421308Sache  for (; statement[i] && whitespace (statement[i]); i++);
113521308Sache
113621308Sache  args = &statement[i];
113721308Sache
113821308Sache  /* Lookup the command, and act on it. */
113921308Sache  for (i = 0; parser_directives[i].name; i++)
114021308Sache    if (_rl_stricmp (directive, parser_directives[i].name) == 0)
114121308Sache      {
114221308Sache	(*parser_directives[i].function) (args);
114321308Sache	return (0);
114421308Sache      }
114521308Sache
114635486Sache  /* display an error message about the unknown parser directive */
114735486Sache  _rl_init_file_error ("unknown parser directive");
114821308Sache  return (1);
114921308Sache}
115021308Sache
115121308Sache/* Read the binding command from STRING and perform it.
115221308Sache   A key binding command looks like: Keyname: function-name\0,
115321308Sache   a variable binding command looks like: set variable value.
115421308Sache   A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */
115521308Sacheint
115621308Sacherl_parse_and_bind (string)
115721308Sache     char *string;
115821308Sache{
115921308Sache  char *funname, *kname;
116021308Sache  register int c, i;
116121308Sache  int key, equivalency;
116221308Sache
116321308Sache  while (string && whitespace (*string))
116421308Sache    string++;
116521308Sache
116621308Sache  if (!string || !*string || *string == '#')
116721308Sache    return 0;
116821308Sache
116921308Sache  /* If this is a parser directive, act on it. */
117021308Sache  if (*string == '$')
117121308Sache    {
117221308Sache      handle_parser_directive (&string[1]);
117321308Sache      return 0;
117421308Sache    }
117521308Sache
117621308Sache  /* If we aren't supposed to be parsing right now, then we're done. */
117721308Sache  if (_rl_parsing_conditionalized_out)
117821308Sache    return 0;
117921308Sache
118021308Sache  i = 0;
118121308Sache  /* If this keyname is a complex key expression surrounded by quotes,
118221308Sache     advance to after the matching close quote.  This code allows the
118321308Sache     backslash to quote characters in the key expression. */
118421308Sache  if (*string == '"')
118521308Sache    {
118621308Sache      int passc = 0;
118721308Sache
118821308Sache      for (i = 1; c = string[i]; i++)
118921308Sache	{
119021308Sache	  if (passc)
119121308Sache	    {
119221308Sache	      passc = 0;
119321308Sache	      continue;
119421308Sache	    }
119521308Sache
119621308Sache	  if (c == '\\')
119721308Sache	    {
119821308Sache	      passc++;
119921308Sache	      continue;
120021308Sache	    }
120121308Sache
120221308Sache	  if (c == '"')
120321308Sache	    break;
120421308Sache	}
120521308Sache      /* If we didn't find a closing quote, abort the line. */
120621308Sache      if (string[i] == '\0')
120721308Sache        {
120821308Sache          _rl_init_file_error ("no closing `\"' in key binding");
120921308Sache          return 1;
121021308Sache        }
121121308Sache    }
121221308Sache
121321308Sache  /* Advance to the colon (:) or whitespace which separates the two objects. */
121421308Sache  for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
121521308Sache
121621308Sache  equivalency = (c == ':' && string[i + 1] == '=');
121721308Sache
121821308Sache  /* Mark the end of the command (or keyname). */
121921308Sache  if (string[i])
122021308Sache    string[i++] = '\0';
122121308Sache
122221308Sache  /* If doing assignment, skip the '=' sign as well. */
122321308Sache  if (equivalency)
122421308Sache    string[i++] = '\0';
122521308Sache
122621308Sache  /* If this is a command to set a variable, then do that. */
122721308Sache  if (_rl_stricmp (string, "set") == 0)
122821308Sache    {
1229157184Sache      char *var, *value, *e;
123021308Sache
1231157184Sache      var = string + i;
123221308Sache      /* Make VAR point to start of variable name. */
123321308Sache      while (*var && whitespace (*var)) var++;
123421308Sache
1235119610Sache      /* Make VALUE point to start of value string. */
123621308Sache      value = var;
123721308Sache      while (*value && !whitespace (*value)) value++;
123821308Sache      if (*value)
123921308Sache	*value++ = '\0';
124021308Sache      while (*value && whitespace (*value)) value++;
124121308Sache
1242157184Sache      /* Strip trailing whitespace from values to boolean variables.  Temp
1243157184Sache	 fix until I get a real quoted-string parser here. */
1244157184Sache      i = find_boolean_var (var);
1245157184Sache      if (i >= 0)
1246157184Sache	{
1247157184Sache	  /* remove trailing whitespace */
1248157184Sache	  e = value + strlen (value) - 1;
1249157184Sache	  while (e >= value && whitespace (*e))
1250157184Sache	    e--;
1251157184Sache	  e++;		/* skip back to whitespace or EOS */
1252157184Sache	  if (*e && e >= value)
1253157184Sache	    *e = '\0';
1254157184Sache	}
1255157184Sache
125621308Sache      rl_variable_bind (var, value);
125721308Sache      return 0;
125821308Sache    }
125921308Sache
126021308Sache  /* Skip any whitespace between keyname and funname. */
126121308Sache  for (; string[i] && whitespace (string[i]); i++);
126221308Sache  funname = &string[i];
126321308Sache
126421308Sache  /* Now isolate funname.
126521308Sache     For straight function names just look for whitespace, since
126621308Sache     that will signify the end of the string.  But this could be a
126721308Sache     macro definition.  In that case, the string is quoted, so skip
126821308Sache     to the matching delimiter.  We allow the backslash to quote the
126921308Sache     delimiter characters in the macro body. */
127021308Sache  /* This code exists to allow whitespace in macro expansions, which
127121308Sache     would otherwise be gobbled up by the next `for' loop.*/
127221308Sache  /* XXX - it may be desirable to allow backslash quoting only if " is
127321308Sache     the quoted string delimiter, like the shell. */
127421308Sache  if (*funname == '\'' || *funname == '"')
127521308Sache    {
1276157184Sache      int delimiter, passc;
127721308Sache
1278157184Sache      delimiter = string[i++];
127935486Sache      for (passc = 0; c = string[i]; i++)
128021308Sache	{
128121308Sache	  if (passc)
128221308Sache	    {
128321308Sache	      passc = 0;
128421308Sache	      continue;
128521308Sache	    }
128621308Sache
128721308Sache	  if (c == '\\')
128821308Sache	    {
128921308Sache	      passc = 1;
129021308Sache	      continue;
129121308Sache	    }
129221308Sache
129321308Sache	  if (c == delimiter)
129421308Sache	    break;
129521308Sache	}
129621308Sache      if (c)
129721308Sache	i++;
129821308Sache    }
129921308Sache
130021308Sache  /* Advance to the end of the string.  */
130121308Sache  for (; string[i] && !whitespace (string[i]); i++);
130221308Sache
130321308Sache  /* No extra whitespace at the end of the string. */
130421308Sache  string[i] = '\0';
130521308Sache
130621308Sache  /* Handle equivalency bindings here.  Make the left-hand side be exactly
130721308Sache     whatever the right-hand evaluates to, including keymaps. */
130821308Sache  if (equivalency)
130921308Sache    {
131021308Sache      return 0;
131121308Sache    }
131221308Sache
131321308Sache  /* If this is a new-style key-binding, then do the binding with
1314136644Sache     rl_bind_keyseq ().  Otherwise, let the older code deal with it. */
131521308Sache  if (*string == '"')
131621308Sache    {
131735486Sache      char *seq;
131835486Sache      register int j, k, passc;
131921308Sache
1320119610Sache      seq = (char *)xmalloc (1 + strlen (string));
132135486Sache      for (j = 1, k = passc = 0; string[j]; j++)
132221308Sache	{
132321308Sache	  /* Allow backslash to quote characters, but leave them in place.
132421308Sache	     This allows a string to end with a backslash quoting another
132521308Sache	     backslash, or with a backslash quoting a double quote.  The
132621308Sache	     backslashes are left in place for rl_translate_keyseq (). */
132721308Sache	  if (passc || (string[j] == '\\'))
132821308Sache	    {
132921308Sache	      seq[k++] = string[j];
133021308Sache	      passc = !passc;
133121308Sache	      continue;
133221308Sache	    }
133321308Sache
133421308Sache	  if (string[j] == '"')
133521308Sache	    break;
133621308Sache
133721308Sache	  seq[k++] = string[j];
133821308Sache	}
133921308Sache      seq[k] = '\0';
134021308Sache
134121308Sache      /* Binding macro? */
134221308Sache      if (*funname == '\'' || *funname == '"')
134321308Sache	{
134421308Sache	  j = strlen (funname);
134521308Sache
134621308Sache	  /* Remove the delimiting quotes from each end of FUNNAME. */
134721308Sache	  if (j && funname[j - 1] == *funname)
134821308Sache	    funname[j - 1] = '\0';
134921308Sache
135021308Sache	  rl_macro_bind (seq, &funname[1], _rl_keymap);
135121308Sache	}
135221308Sache      else
1353136644Sache	rl_bind_keyseq (seq, rl_named_function (funname));
135421308Sache
135521308Sache      free (seq);
135621308Sache      return 0;
135721308Sache    }
135821308Sache
135921308Sache  /* Get the actual character we want to deal with. */
136021308Sache  kname = strrchr (string, '-');
136121308Sache  if (!kname)
136221308Sache    kname = string;
136321308Sache  else
136421308Sache    kname++;
136521308Sache
136621308Sache  key = glean_key_from_name (kname);
136721308Sache
136821308Sache  /* Add in control and meta bits. */
136975406Sache  if (substring_member_of_array (string, _rl_possible_control_prefixes))
137021308Sache    key = CTRL (_rl_to_upper (key));
137121308Sache
137275406Sache  if (substring_member_of_array (string, _rl_possible_meta_prefixes))
137321308Sache    key = META (key);
137421308Sache
137521308Sache  /* Temporary.  Handle old-style keyname with macro-binding. */
137621308Sache  if (*funname == '\'' || *funname == '"')
137721308Sache    {
1378119610Sache      char useq[2];
137921308Sache      int fl = strlen (funname);
138021308Sache
138126497Sache      useq[0] = key; useq[1] = '\0';
138221308Sache      if (fl && funname[fl - 1] == *funname)
138321308Sache	funname[fl - 1] = '\0';
138421308Sache
138526497Sache      rl_macro_bind (useq, &funname[1], _rl_keymap);
138621308Sache    }
138721308Sache#if defined (PREFIX_META_HACK)
138821308Sache  /* Ugly, but working hack to keep prefix-meta around. */
138921308Sache  else if (_rl_stricmp (funname, "prefix-meta") == 0)
139021308Sache    {
139121308Sache      char seq[2];
139221308Sache
139321308Sache      seq[0] = key;
139421308Sache      seq[1] = '\0';
139521308Sache      rl_generic_bind (ISKMAP, seq, (char *)emacs_meta_keymap, _rl_keymap);
139621308Sache    }
139721308Sache#endif /* PREFIX_META_HACK */
139821308Sache  else
139921308Sache    rl_bind_key (key, rl_named_function (funname));
140021308Sache  return 0;
140121308Sache}
140221308Sache
140321308Sache/* Simple structure for boolean readline variables (i.e., those that can
140421308Sache   have one of two values; either "On" or 1 for truth, or "Off" or 0 for
140521308Sache   false. */
140621308Sache
140758310Sache#define V_SPECIAL	0x1
140858310Sache
140921308Sachestatic struct {
141075406Sache  const char *name;
141121308Sache  int *value;
141258310Sache  int flags;
141321308Sache} boolean_varlist [] = {
1414157184Sache  { "bind-tty-special-chars",	&_rl_bind_stty_chars,		0 },
141558310Sache  { "blink-matching-paren",	&rl_blink_matching_paren,	V_SPECIAL },
1416119610Sache  { "byte-oriented",		&rl_byte_oriented,		0 },
141758310Sache  { "completion-ignore-case",	&_rl_completion_case_fold,	0 },
141858310Sache  { "convert-meta",		&_rl_convert_meta_chars_to_ascii, 0 },
141958310Sache  { "disable-completion",	&rl_inhibit_completion,		0 },
142058310Sache  { "enable-keypad",		&_rl_enable_keypad,		0 },
142158310Sache  { "expand-tilde",		&rl_complete_with_tilde_expansion, 0 },
1422119610Sache  { "history-preserve-point",	&_rl_history_preserve_point,	0 },
142358310Sache  { "horizontal-scroll-mode",	&_rl_horizontal_scroll_mode,	0 },
142458310Sache  { "input-meta",		&_rl_meta_flag,			0 },
142558310Sache  { "mark-directories",		&_rl_complete_mark_directories,	0 },
142658310Sache  { "mark-modified-lines",	&_rl_mark_modified_lines,	0 },
1427119610Sache  { "mark-symlinked-directories", &_rl_complete_mark_symlink_dirs, 0 },
1428119610Sache  { "match-hidden-files",	&_rl_match_hidden_files,	0 },
142958310Sache  { "meta-flag",		&_rl_meta_flag,			0 },
143058310Sache  { "output-meta",		&_rl_output_meta_chars,		0 },
1431119610Sache  { "page-completions",		&_rl_page_completions,		0 },
143258310Sache  { "prefer-visible-bell",	&_rl_prefer_visible_bell,	V_SPECIAL },
143358310Sache  { "print-completions-horizontally", &_rl_print_completions_horizontally, 0 },
143458310Sache  { "show-all-if-ambiguous",	&_rl_complete_show_all,		0 },
1435136644Sache  { "show-all-if-unmodified",	&_rl_complete_show_unmodified,	0 },
143621308Sache#if defined (VISIBLE_STATS)
143758310Sache  { "visible-stats",		&rl_visible_stats,		0 },
143821308Sache#endif /* VISIBLE_STATS */
143921308Sache  { (char *)NULL, (int *)NULL }
144021308Sache};
144121308Sache
144258310Sachestatic int
144358310Sachefind_boolean_var (name)
1444119610Sache     const char *name;
144558310Sache{
144658310Sache  register int i;
144758310Sache
144858310Sache  for (i = 0; boolean_varlist[i].name; i++)
144958310Sache    if (_rl_stricmp (name, boolean_varlist[i].name) == 0)
145058310Sache      return i;
145158310Sache  return -1;
145258310Sache}
145358310Sache
145458310Sache/* Hooks for handling special boolean variables, where a
145558310Sache   function needs to be called or another variable needs
145658310Sache   to be changed when they're changed. */
145758310Sachestatic void
145858310Sachehack_special_boolean_var (i)
145958310Sache     int i;
146058310Sache{
146175406Sache  const char *name;
146258310Sache
146358310Sache  name = boolean_varlist[i].name;
146458310Sache
146558310Sache  if (_rl_stricmp (name, "blink-matching-paren") == 0)
146658310Sache    _rl_enable_paren_matching (rl_blink_matching_paren);
146758310Sache  else if (_rl_stricmp (name, "prefer-visible-bell") == 0)
146858310Sache    {
146958310Sache      if (_rl_prefer_visible_bell)
147058310Sache	_rl_bell_preference = VISIBLE_BELL;
147158310Sache      else
147258310Sache	_rl_bell_preference = AUDIBLE_BELL;
147358310Sache    }
147458310Sache}
147558310Sache
1476119610Sachetypedef int _rl_sv_func_t PARAMS((const char *));
147775406Sache
147858310Sache/* These *must* correspond to the array indices for the appropriate
147958310Sache   string variable.  (Though they're not used right now.) */
148058310Sache#define V_BELLSTYLE	0
148158310Sache#define V_COMBEGIN	1
148258310Sache#define V_EDITMODE	2
148358310Sache#define V_ISRCHTERM	3
148458310Sache#define V_KEYMAP	4
148558310Sache
148658310Sache#define	V_STRING	1
148758310Sache#define V_INT		2
148858310Sache
148958310Sache/* Forward declarations */
1490119610Sachestatic int sv_bell_style PARAMS((const char *));
1491119610Sachestatic int sv_combegin PARAMS((const char *));
1492119610Sachestatic int sv_compquery PARAMS((const char *));
1493119610Sachestatic int sv_editmode PARAMS((const char *));
1494119610Sachestatic int sv_isrchterm PARAMS((const char *));
1495119610Sachestatic int sv_keymap PARAMS((const char *));
149658310Sache
149758310Sachestatic struct {
149875406Sache  const char *name;
149958310Sache  int flags;
150075406Sache  _rl_sv_func_t *set_func;
150158310Sache} string_varlist[] = {
150258310Sache  { "bell-style",	V_STRING,	sv_bell_style },
150358310Sache  { "comment-begin",	V_STRING,	sv_combegin },
150458310Sache  { "completion-query-items", V_INT,	sv_compquery },
150558310Sache  { "editing-mode",	V_STRING,	sv_editmode },
150658310Sache  { "isearch-terminators", V_STRING,	sv_isrchterm },
150758310Sache  { "keymap",		V_STRING,	sv_keymap },
150858310Sache  { (char *)NULL,	0 }
150958310Sache};
151058310Sache
151158310Sachestatic int
151258310Sachefind_string_var (name)
1513119610Sache     const char *name;
151458310Sache{
151558310Sache  register int i;
151658310Sache
151758310Sache  for (i = 0; string_varlist[i].name; i++)
151858310Sache    if (_rl_stricmp (name, string_varlist[i].name) == 0)
151958310Sache      return i;
152058310Sache  return -1;
152158310Sache}
152258310Sache
152358310Sache/* A boolean value that can appear in a `set variable' command is true if
152458310Sache   the value is null or empty, `on' (case-insenstive), or "1".  Any other
152558310Sache   values result in 0 (false). */
152658310Sachestatic int
152758310Sachebool_to_int (value)
1528157184Sache     const char *value;
152958310Sache{
153058310Sache  return (value == 0 || *value == '\0' ||
153158310Sache		(_rl_stricmp (value, "on") == 0) ||
153258310Sache		(value[0] == '1' && value[1] == '\0'));
153358310Sache}
153458310Sache
1535157184Sachechar *
1536157184Sacherl_variable_value (name)
1537157184Sache     const char *name;
1538157184Sache{
1539157184Sache  register int i;
1540157184Sache
1541157184Sache  /* Check for simple variables first. */
1542157184Sache  i = find_boolean_var (name);
1543157184Sache  if (i >= 0)
1544157184Sache    return (*boolean_varlist[i].value ? "on" : "off");
1545157184Sache
1546157184Sache  i = find_string_var (name);
1547157184Sache  if (i >= 0)
1548157184Sache    return (_rl_get_string_variable_value (string_varlist[i].name));
1549157184Sache
1550157184Sache  /* Unknown variable names return NULL. */
1551157184Sache  return 0;
1552157184Sache}
1553157184Sache
155421308Sacheint
155521308Sacherl_variable_bind (name, value)
155675406Sache     const char *name, *value;
155721308Sache{
155821308Sache  register int i;
155958310Sache  int	v;
156021308Sache
156121308Sache  /* Check for simple variables first. */
156258310Sache  i = find_boolean_var (name);
156358310Sache  if (i >= 0)
156421308Sache    {
156558310Sache      *boolean_varlist[i].value = bool_to_int (value);
156658310Sache      if (boolean_varlist[i].flags & V_SPECIAL)
156758310Sache	hack_special_boolean_var (i);
156858310Sache      return 0;
156921308Sache    }
157021308Sache
157158310Sache  i = find_string_var (name);
157221308Sache
157358310Sache  /* For the time being, unknown variable names or string names without a
157458310Sache     handler function are simply ignored. */
157558310Sache  if (i < 0 || string_varlist[i].set_func == 0)
157658310Sache    return 0;
157758310Sache
157858310Sache  v = (*string_varlist[i].set_func) (value);
157958310Sache  return v;
158058310Sache}
158158310Sache
158258310Sachestatic int
158358310Sachesv_editmode (value)
158475406Sache     const char *value;
158558310Sache{
158658310Sache  if (_rl_strnicmp (value, "vi", 2) == 0)
158721308Sache    {
158821308Sache#if defined (VI_MODE)
158958310Sache      _rl_keymap = vi_insertion_keymap;
159058310Sache      rl_editing_mode = vi_mode;
159121308Sache#endif /* VI_MODE */
159258310Sache      return 0;
159321308Sache    }
159458310Sache  else if (_rl_strnicmp (value, "emacs", 5) == 0)
159558310Sache    {
159658310Sache      _rl_keymap = emacs_standard_keymap;
159758310Sache      rl_editing_mode = emacs_mode;
159858310Sache      return 0;
159958310Sache    }
160058310Sache  return 1;
160158310Sache}
160221308Sache
160358310Sachestatic int
160458310Sachesv_combegin (value)
160575406Sache     const char *value;
160658310Sache{
160758310Sache  if (value && *value)
160821308Sache    {
160958310Sache      FREE (_rl_comment_begin);
161058310Sache      _rl_comment_begin = savestring (value);
161158310Sache      return 0;
161258310Sache    }
161358310Sache  return 1;
161458310Sache}
161521308Sache
161658310Sachestatic int
161758310Sachesv_compquery (value)
161875406Sache     const char *value;
161958310Sache{
162058310Sache  int nval = 100;
162158310Sache
162258310Sache  if (value && *value)
162321308Sache    {
162458310Sache      nval = atoi (value);
162558310Sache      if (nval < 0)
162658310Sache	nval = 0;
162721308Sache    }
162858310Sache  rl_completion_query_items = nval;
162958310Sache  return 0;
163058310Sache}
163158310Sache
163258310Sachestatic int
163358310Sachesv_keymap (value)
163475406Sache     const char *value;
163558310Sache{
163658310Sache  Keymap kmap;
163758310Sache
163858310Sache  kmap = rl_get_keymap_by_name (value);
163958310Sache  if (kmap)
164021308Sache    {
164158310Sache      rl_set_keymap (kmap);
164258310Sache      return 0;
164321308Sache    }
164458310Sache  return 1;
164558310Sache}
164658310Sache
164758310Sachestatic int
164858310Sachesv_bell_style (value)
164975406Sache     const char *value;
165058310Sache{
165158310Sache  if (value == 0 || *value == '\0')
1652119610Sache    _rl_bell_preference = AUDIBLE_BELL;
165358310Sache  else if (_rl_stricmp (value, "none") == 0 || _rl_stricmp (value, "off") == 0)
1654119610Sache    _rl_bell_preference = NO_BELL;
165558310Sache  else if (_rl_stricmp (value, "audible") == 0 || _rl_stricmp (value, "on") == 0)
1656119610Sache    _rl_bell_preference = AUDIBLE_BELL;
165758310Sache  else if (_rl_stricmp (value, "visible") == 0)
1658119610Sache    _rl_bell_preference = VISIBLE_BELL;
165958310Sache  else
166058310Sache    return 1;
1661119610Sache  return 0;
166258310Sache}
166358310Sache
166458310Sachestatic int
166558310Sachesv_isrchterm (value)
166675406Sache     const char *value;
166758310Sache{
166858310Sache  int beg, end, delim;
166958310Sache  char *v;
167058310Sache
167158310Sache  if (value == 0)
167258310Sache    return 1;
167358310Sache
167458310Sache  /* Isolate the value and translate it into a character string. */
167558310Sache  v = savestring (value);
167658310Sache  FREE (_rl_isearch_terminators);
167758310Sache  if (v[0] == '"' || v[0] == '\'')
167821308Sache    {
167958310Sache      delim = v[0];
168058310Sache      for (beg = end = 1; v[end] && v[end] != delim; end++)
168158310Sache	;
168221308Sache    }
168358310Sache  else
168421308Sache    {
168558310Sache      for (beg = end = 0; whitespace (v[end]) == 0; end++)
168658310Sache	;
168721308Sache    }
168821308Sache
168958310Sache  v[end] = '\0';
169047558Sache
169158310Sache  /* The value starts at v + beg.  Translate it into a character string. */
1692119610Sache  _rl_isearch_terminators = (char *)xmalloc (2 * strlen (v) + 1);
169358310Sache  rl_translate_keyseq (v + beg, _rl_isearch_terminators, &end);
169458310Sache  _rl_isearch_terminators[end] = '\0';
169558310Sache
169658310Sache  free (v);
169721308Sache  return 0;
169821308Sache}
169958310Sache
170021308Sache/* Return the character which matches NAME.
170121308Sache   For example, `Space' returns ' '. */
170221308Sache
170321308Sachetypedef struct {
170475406Sache  const char *name;
170521308Sache  int value;
170621308Sache} assoc_list;
170721308Sache
170821308Sachestatic assoc_list name_key_alist[] = {
170921308Sache  { "DEL", 0x7f },
171021308Sache  { "ESC", '\033' },
171121308Sache  { "Escape", '\033' },
171221308Sache  { "LFD", '\n' },
171321308Sache  { "Newline", '\n' },
171421308Sache  { "RET", '\r' },
171521308Sache  { "Return", '\r' },
171621308Sache  { "Rubout", 0x7f },
171721308Sache  { "SPC", ' ' },
171821308Sache  { "Space", ' ' },
171921308Sache  { "Tab", 0x09 },
172021308Sache  { (char *)0x0, 0 }
172121308Sache};
172221308Sache
172321308Sachestatic int
172421308Sacheglean_key_from_name (name)
172521308Sache     char *name;
172621308Sache{
172721308Sache  register int i;
172821308Sache
172921308Sache  for (i = 0; name_key_alist[i].name; i++)
173021308Sache    if (_rl_stricmp (name, name_key_alist[i].name) == 0)
173121308Sache      return (name_key_alist[i].value);
173221308Sache
173321308Sache  return (*(unsigned char *)name);	/* XXX was return (*name) */
173421308Sache}
173521308Sache
173621308Sache/* Auxiliary functions to manage keymaps. */
173721308Sachestatic struct {
173875406Sache  const char *name;
173921308Sache  Keymap map;
174021308Sache} keymap_names[] = {
174121308Sache  { "emacs", emacs_standard_keymap },
174221308Sache  { "emacs-standard", emacs_standard_keymap },
174321308Sache  { "emacs-meta", emacs_meta_keymap },
174421308Sache  { "emacs-ctlx", emacs_ctlx_keymap },
174521308Sache#if defined (VI_MODE)
174621308Sache  { "vi", vi_movement_keymap },
174721308Sache  { "vi-move", vi_movement_keymap },
174821308Sache  { "vi-command", vi_movement_keymap },
174921308Sache  { "vi-insert", vi_insertion_keymap },
175021308Sache#endif /* VI_MODE */
175121308Sache  { (char *)0x0, (Keymap)0x0 }
175221308Sache};
175321308Sache
175421308SacheKeymap
175521308Sacherl_get_keymap_by_name (name)
175675406Sache     const char *name;
175721308Sache{
175821308Sache  register int i;
175921308Sache
176021308Sache  for (i = 0; keymap_names[i].name; i++)
176175406Sache    if (_rl_stricmp (name, keymap_names[i].name) == 0)
176221308Sache      return (keymap_names[i].map);
176321308Sache  return ((Keymap) NULL);
176421308Sache}
176521308Sache
176621308Sachechar *
176721308Sacherl_get_keymap_name (map)
176821308Sache     Keymap map;
176921308Sache{
177021308Sache  register int i;
177121308Sache  for (i = 0; keymap_names[i].name; i++)
177221308Sache    if (map == keymap_names[i].map)
177375406Sache      return ((char *)keymap_names[i].name);
177421308Sache  return ((char *)NULL);
177521308Sache}
177621308Sache
177721308Sachevoid
177821308Sacherl_set_keymap (map)
177921308Sache     Keymap map;
178021308Sache{
178121308Sache  if (map)
178221308Sache    _rl_keymap = map;
178321308Sache}
178421308Sache
178521308SacheKeymap
178621308Sacherl_get_keymap ()
178721308Sache{
178821308Sache  return (_rl_keymap);
178921308Sache}
179021308Sache
179121308Sachevoid
179221308Sacherl_set_keymap_from_edit_mode ()
179321308Sache{
179421308Sache  if (rl_editing_mode == emacs_mode)
179521308Sache    _rl_keymap = emacs_standard_keymap;
179621308Sache#if defined (VI_MODE)
179721308Sache  else if (rl_editing_mode == vi_mode)
179821308Sache    _rl_keymap = vi_insertion_keymap;
179921308Sache#endif /* VI_MODE */
180021308Sache}
180121308Sache
180221308Sachechar *
180321308Sacherl_get_keymap_name_from_edit_mode ()
180421308Sache{
180521308Sache  if (rl_editing_mode == emacs_mode)
180621308Sache    return "emacs";
180721308Sache#if defined (VI_MODE)
180821308Sache  else if (rl_editing_mode == vi_mode)
180921308Sache    return "vi";
181021308Sache#endif /* VI_MODE */
181121308Sache  else
181221308Sache    return "none";
181321308Sache}
181421308Sache
181521308Sache/* **************************************************************** */
181621308Sache/*								    */
181721308Sache/*		  Key Binding and Function Information		    */
181821308Sache/*								    */
181921308Sache/* **************************************************************** */
182021308Sache
182121308Sache/* Each of the following functions produces information about the
182221308Sache   state of keybindings and functions known to Readline.  The info
182321308Sache   is always printed to rl_outstream, and in such a way that it can
1824136644Sache   be read back in (i.e., passed to rl_parse_and_bind ()). */
182521308Sache
182621308Sache/* Print the names of functions known to Readline. */
182721308Sachevoid
182821308Sacherl_list_funmap_names ()
182921308Sache{
183021308Sache  register int i;
183175406Sache  const char **funmap_names;
183221308Sache
183321308Sache  funmap_names = rl_funmap_names ();
183421308Sache
183521308Sache  if (!funmap_names)
183621308Sache    return;
183721308Sache
183821308Sache  for (i = 0; funmap_names[i]; i++)
183921308Sache    fprintf (rl_outstream, "%s\n", funmap_names[i]);
184021308Sache
184121308Sache  free (funmap_names);
184221308Sache}
184321308Sache
184421308Sachestatic char *
184521308Sache_rl_get_keyname (key)
184621308Sache     int key;
184721308Sache{
184821308Sache  char *keyname;
184947558Sache  int i, c;
185021308Sache
185121308Sache  keyname = (char *)xmalloc (8);
185221308Sache
185321308Sache  c = key;
185421308Sache  /* Since this is going to be used to write out keysequence-function
185521308Sache     pairs for possible inclusion in an inputrc file, we don't want to
185621308Sache     do any special meta processing on KEY. */
185721308Sache
1858119610Sache#if 1
1859119610Sache  /* XXX - Experimental */
186021308Sache  /* We might want to do this, but the old version of the code did not. */
186121308Sache
186221308Sache  /* If this is an escape character, we don't want to do any more processing.
186321308Sache     Just add the special ESC key sequence and return. */
186421308Sache  if (c == ESC)
186521308Sache    {
1866119610Sache      keyname[0] = '\\';
1867119610Sache      keyname[1] = 'e';
1868119610Sache      keyname[2] = '\0';
1869119610Sache      return keyname;
187021308Sache    }
187121308Sache#endif
187221308Sache
187321308Sache  /* RUBOUT is translated directly into \C-? */
187421308Sache  if (key == RUBOUT)
187521308Sache    {
187621308Sache      keyname[0] = '\\';
187721308Sache      keyname[1] = 'C';
187821308Sache      keyname[2] = '-';
187921308Sache      keyname[3] = '?';
188021308Sache      keyname[4] = '\0';
188121308Sache      return keyname;
188221308Sache    }
188321308Sache
188421308Sache  i = 0;
188521308Sache  /* Now add special prefixes needed for control characters.  This can
188621308Sache     potentially change C. */
188721308Sache  if (CTRL_CHAR (c))
188821308Sache    {
188921308Sache      keyname[i++] = '\\';
189021308Sache      keyname[i++] = 'C';
189121308Sache      keyname[i++] = '-';
189221308Sache      c = _rl_to_lower (UNCTRL (c));
189321308Sache    }
189421308Sache
189535486Sache  /* XXX experimental code.  Turn the characters that are not ASCII or
189635486Sache     ISO Latin 1 (128 - 159) into octal escape sequences (\200 - \237).
189735486Sache     This changes C. */
189835486Sache  if (c >= 128 && c <= 159)
189935486Sache    {
190035486Sache      keyname[i++] = '\\';
190135486Sache      keyname[i++] = '2';
190235486Sache      c -= 128;
190335486Sache      keyname[i++] = (c / 8) + '0';
190435486Sache      c = (c % 8) + '0';
190535486Sache    }
190635486Sache
190721308Sache  /* Now, if the character needs to be quoted with a backslash, do that. */
190821308Sache  if (c == '\\' || c == '"')
190921308Sache    keyname[i++] = '\\';
191021308Sache
191121308Sache  /* Now add the key, terminate the string, and return it. */
191221308Sache  keyname[i++] = (char) c;
191321308Sache  keyname[i] = '\0';
191421308Sache
191521308Sache  return keyname;
191621308Sache}
191721308Sache
191821308Sache/* Return a NULL terminated array of strings which represent the key
191921308Sache   sequences that are used to invoke FUNCTION in MAP. */
192021308Sachechar **
192121308Sacherl_invoking_keyseqs_in_map (function, map)
192275406Sache     rl_command_func_t *function;
192321308Sache     Keymap map;
192421308Sache{
192521308Sache  register int key;
192621308Sache  char **result;
192721308Sache  int result_index, result_size;
192821308Sache
192921308Sache  result = (char **)NULL;
193021308Sache  result_index = result_size = 0;
193121308Sache
193221308Sache  for (key = 0; key < KEYMAP_SIZE; key++)
193321308Sache    {
193421308Sache      switch (map[key].type)
193521308Sache	{
193621308Sache	case ISMACR:
193721308Sache	  /* Macros match, if, and only if, the pointers are identical.
193821308Sache	     Thus, they are treated exactly like functions in here. */
193921308Sache	case ISFUNC:
194021308Sache	  /* If the function in the keymap is the one we are looking for,
194121308Sache	     then add the current KEY to the list of invoking keys. */
194221308Sache	  if (map[key].function == function)
194321308Sache	    {
194421308Sache	      char *keyname;
194521308Sache
194621308Sache	      keyname = _rl_get_keyname (key);
194721308Sache
194821308Sache	      if (result_index + 2 > result_size)
194921308Sache	        {
195021308Sache	          result_size += 10;
1951119610Sache		  result = (char **)xrealloc (result, result_size * sizeof (char *));
195221308Sache	        }
195321308Sache
195421308Sache	      result[result_index++] = keyname;
195521308Sache	      result[result_index] = (char *)NULL;
195621308Sache	    }
195721308Sache	  break;
195821308Sache
195921308Sache	case ISKMAP:
196021308Sache	  {
196121308Sache	    char **seqs;
196221308Sache	    register int i;
196321308Sache
196421308Sache	    /* Find the list of keyseqs in this map which have FUNCTION as
196521308Sache	       their target.  Add the key sequences found to RESULT. */
196621308Sache	    if (map[key].function)
196721308Sache	      seqs =
196821308Sache	        rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
196921308Sache	    else
197021308Sache	      break;
197121308Sache
197221308Sache	    if (seqs == 0)
197321308Sache	      break;
197421308Sache
197521308Sache	    for (i = 0; seqs[i]; i++)
197621308Sache	      {
197721308Sache		char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
197821308Sache
197921308Sache		if (key == ESC)
1980165670Sache		  {
1981165670Sache		    /* If ESC is the meta prefix and we're converting chars
1982165670Sache		       with the eighth bit set to ESC-prefixed sequences, then
1983165670Sache		       we can use \M-.  Otherwise we need to use the sequence
1984165670Sache		       for ESC. */
1985165670Sache		    if (_rl_convert_meta_chars_to_ascii && map[ESC].type == ISKMAP)
1986165670Sache		      sprintf (keyname, "\\M-");
1987165670Sache		    else
1988165670Sache		      sprintf (keyname, "\\e");
1989165670Sache		  }
199021308Sache		else if (CTRL_CHAR (key))
199121308Sache		  sprintf (keyname, "\\C-%c", _rl_to_lower (UNCTRL (key)));
199221308Sache		else if (key == RUBOUT)
199321308Sache		  sprintf (keyname, "\\C-?");
199421308Sache		else if (key == '\\' || key == '"')
199521308Sache		  {
199621308Sache		    keyname[0] = '\\';
199721308Sache		    keyname[1] = (char) key;
199821308Sache		    keyname[2] = '\0';
199921308Sache		  }
200021308Sache		else
200121308Sache		  {
200221308Sache		    keyname[0] = (char) key;
200321308Sache		    keyname[1] = '\0';
200421308Sache		  }
200521308Sache
200621308Sache		strcat (keyname, seqs[i]);
200721308Sache		free (seqs[i]);
200821308Sache
200921308Sache		if (result_index + 2 > result_size)
201021308Sache		  {
201121308Sache		    result_size += 10;
2012119610Sache		    result = (char **)xrealloc (result, result_size * sizeof (char *));
201321308Sache		  }
201421308Sache
201521308Sache		result[result_index++] = keyname;
201621308Sache		result[result_index] = (char *)NULL;
201721308Sache	      }
201821308Sache
201921308Sache	    free (seqs);
202021308Sache	  }
202121308Sache	  break;
202221308Sache	}
202321308Sache    }
202421308Sache  return (result);
202521308Sache}
202621308Sache
202721308Sache/* Return a NULL terminated array of strings which represent the key
202821308Sache   sequences that can be used to invoke FUNCTION using the current keymap. */
202921308Sachechar **
203021308Sacherl_invoking_keyseqs (function)
203175406Sache     rl_command_func_t *function;
203221308Sache{
203321308Sache  return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
203421308Sache}
203521308Sache
203621308Sache/* Print all of the functions and their bindings to rl_outstream.  If
203721308Sache   PRINT_READABLY is non-zero, then print the output in such a way
203821308Sache   that it can be read back in. */
203921308Sachevoid
204021308Sacherl_function_dumper (print_readably)
204121308Sache     int print_readably;
204221308Sache{
204321308Sache  register int i;
204475406Sache  const char **names;
204575406Sache  const char *name;
204621308Sache
204721308Sache  names = rl_funmap_names ();
204821308Sache
204921308Sache  fprintf (rl_outstream, "\n");
205021308Sache
205121308Sache  for (i = 0; name = names[i]; i++)
205221308Sache    {
205375406Sache      rl_command_func_t *function;
205421308Sache      char **invokers;
205521308Sache
205621308Sache      function = rl_named_function (name);
205721308Sache      invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap);
205821308Sache
205921308Sache      if (print_readably)
206021308Sache	{
206121308Sache	  if (!invokers)
206221308Sache	    fprintf (rl_outstream, "# %s (not bound)\n", name);
206321308Sache	  else
206421308Sache	    {
206521308Sache	      register int j;
206621308Sache
206721308Sache	      for (j = 0; invokers[j]; j++)
206821308Sache		{
206921308Sache		  fprintf (rl_outstream, "\"%s\": %s\n",
207021308Sache			   invokers[j], name);
207121308Sache		  free (invokers[j]);
207221308Sache		}
207321308Sache
207421308Sache	      free (invokers);
207521308Sache	    }
207621308Sache	}
207721308Sache      else
207821308Sache	{
207921308Sache	  if (!invokers)
208021308Sache	    fprintf (rl_outstream, "%s is not bound to any keys\n",
208121308Sache		     name);
208221308Sache	  else
208321308Sache	    {
208421308Sache	      register int j;
208521308Sache
208621308Sache	      fprintf (rl_outstream, "%s can be found on ", name);
208721308Sache
208821308Sache	      for (j = 0; invokers[j] && j < 5; j++)
208921308Sache		{
209021308Sache		  fprintf (rl_outstream, "\"%s\"%s", invokers[j],
209121308Sache			   invokers[j + 1] ? ", " : ".\n");
209221308Sache		}
209321308Sache
209421308Sache	      if (j == 5 && invokers[j])
209521308Sache		fprintf (rl_outstream, "...\n");
209621308Sache
209721308Sache	      for (j = 0; invokers[j]; j++)
209821308Sache		free (invokers[j]);
209921308Sache
210021308Sache	      free (invokers);
210121308Sache	    }
210221308Sache	}
210321308Sache    }
210421308Sache}
210521308Sache
210621308Sache/* Print all of the current functions and their bindings to
210721308Sache   rl_outstream.  If an explicit argument is given, then print
210821308Sache   the output in such a way that it can be read back in. */
210921308Sacheint
211021308Sacherl_dump_functions (count, key)
211121308Sache     int count, key;
211221308Sache{
211326497Sache  if (rl_dispatching)
211426497Sache    fprintf (rl_outstream, "\r\n");
211521308Sache  rl_function_dumper (rl_explicit_arg);
211621308Sache  rl_on_new_line ();
211721308Sache  return (0);
211821308Sache}
211921308Sache
212021308Sachestatic void
212121308Sache_rl_macro_dumper_internal (print_readably, map, prefix)
212221308Sache     int print_readably;
212321308Sache     Keymap map;
212421308Sache     char *prefix;
212521308Sache{
212621308Sache  register int key;
212721308Sache  char *keyname, *out;
212821308Sache  int prefix_len;
212921308Sache
213021308Sache  for (key = 0; key < KEYMAP_SIZE; key++)
213121308Sache    {
213221308Sache      switch (map[key].type)
213321308Sache	{
213421308Sache	case ISMACR:
213521308Sache	  keyname = _rl_get_keyname (key);
213626497Sache	  out = _rl_untranslate_macro_value ((char *)map[key].function);
2137119610Sache
213821308Sache	  if (print_readably)
213921308Sache	    fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
214021308Sache						         keyname,
214121308Sache						         out ? out : "");
214221308Sache	  else
214321308Sache	    fprintf (rl_outstream, "%s%s outputs %s\n", prefix ? prefix : "",
214421308Sache							keyname,
214521308Sache							out ? out : "");
214621308Sache	  free (keyname);
214726497Sache	  free (out);
214821308Sache	  break;
214921308Sache	case ISFUNC:
215021308Sache	  break;
215121308Sache	case ISKMAP:
215221308Sache	  prefix_len = prefix ? strlen (prefix) : 0;
215321308Sache	  if (key == ESC)
215421308Sache	    {
2155119610Sache	      keyname = (char *)xmalloc (3 + prefix_len);
215621308Sache	      if (prefix)
215721308Sache		strcpy (keyname, prefix);
215821308Sache	      keyname[prefix_len] = '\\';
215921308Sache	      keyname[prefix_len + 1] = 'e';
216021308Sache	      keyname[prefix_len + 2] = '\0';
216121308Sache	    }
216221308Sache	  else
216321308Sache	    {
216421308Sache	      keyname = _rl_get_keyname (key);
216521308Sache	      if (prefix)
216621308Sache		{
2167119610Sache		  out = (char *)xmalloc (strlen (keyname) + prefix_len + 1);
216821308Sache		  strcpy (out, prefix);
216921308Sache		  strcpy (out + prefix_len, keyname);
217021308Sache		  free (keyname);
217121308Sache		  keyname = out;
217221308Sache		}
217321308Sache	    }
217421308Sache
217521308Sache	  _rl_macro_dumper_internal (print_readably, FUNCTION_TO_KEYMAP (map, key), keyname);
217621308Sache	  free (keyname);
217721308Sache	  break;
217821308Sache	}
217921308Sache    }
218021308Sache}
218121308Sache
218221308Sachevoid
218321308Sacherl_macro_dumper (print_readably)
218421308Sache     int print_readably;
218521308Sache{
218621308Sache  _rl_macro_dumper_internal (print_readably, _rl_keymap, (char *)NULL);
218721308Sache}
218821308Sache
218921308Sacheint
219021308Sacherl_dump_macros (count, key)
219121308Sache     int count, key;
219221308Sache{
219326497Sache  if (rl_dispatching)
219426497Sache    fprintf (rl_outstream, "\r\n");
219521308Sache  rl_macro_dumper (rl_explicit_arg);
219621308Sache  rl_on_new_line ();
219721308Sache  return (0);
219821308Sache}
219921308Sache
2200157184Sachestatic char *
2201157184Sache_rl_get_string_variable_value (name)
2202157184Sache     const char *name;
2203157184Sache{
2204157184Sache  static char numbuf[32];
2205157184Sache  char *ret;
2206157184Sache
2207157184Sache  if (_rl_stricmp (name, "bell-style") == 0)
2208157184Sache    {
2209157184Sache      switch (_rl_bell_preference)
2210157184Sache	{
2211157184Sache	  case NO_BELL:
2212157184Sache	    return "none";
2213157184Sache	  case VISIBLE_BELL:
2214157184Sache	    return "visible";
2215157184Sache	  case AUDIBLE_BELL:
2216157184Sache	  default:
2217157184Sache	    return "audible";
2218157184Sache	}
2219157184Sache    }
2220157184Sache  else if (_rl_stricmp (name, "comment-begin") == 0)
2221157184Sache    return (_rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
2222157184Sache  else if (_rl_stricmp (name, "completion-query-items") == 0)
2223157184Sache    {
2224157184Sache      sprintf (numbuf, "%d", rl_completion_query_items);
2225157184Sache      return (numbuf);
2226157184Sache    }
2227157184Sache  else if (_rl_stricmp (name, "editing-mode") == 0)
2228157184Sache    return (rl_get_keymap_name_from_edit_mode ());
2229157184Sache  else if (_rl_stricmp (name, "isearch-terminators") == 0)
2230157184Sache    {
2231157184Sache      if (_rl_isearch_terminators == 0)
2232157184Sache	return 0;
2233157184Sache      ret = _rl_untranslate_macro_value (_rl_isearch_terminators);
2234157184Sache      if (ret)
2235157184Sache	{
2236157184Sache	  strncpy (numbuf, ret, sizeof (numbuf) - 1);
2237157184Sache	  free (ret);
2238157184Sache	  numbuf[sizeof(numbuf) - 1] = '\0';
2239157184Sache	}
2240157184Sache      else
2241157184Sache	numbuf[0] = '\0';
2242157184Sache      return numbuf;
2243157184Sache    }
2244157184Sache  else if (_rl_stricmp (name, "keymap") == 0)
2245157184Sache    {
2246157184Sache      ret = rl_get_keymap_name (_rl_keymap);
2247157184Sache      if (ret == 0)
2248157184Sache	ret = rl_get_keymap_name_from_edit_mode ();
2249157184Sache      return (ret ? ret : "none");
2250157184Sache    }
2251157184Sache  else
2252157184Sache    return (0);
2253157184Sache}
2254157184Sache
225521308Sachevoid
225621308Sacherl_variable_dumper (print_readably)
225721308Sache     int print_readably;
225821308Sache{
225921308Sache  int i;
2260157184Sache  char *v;
226121308Sache
226221308Sache  for (i = 0; boolean_varlist[i].name; i++)
226321308Sache    {
226421308Sache      if (print_readably)
226521308Sache        fprintf (rl_outstream, "set %s %s\n", boolean_varlist[i].name,
226621308Sache			       *boolean_varlist[i].value ? "on" : "off");
226721308Sache      else
226821308Sache        fprintf (rl_outstream, "%s is set to `%s'\n", boolean_varlist[i].name,
226921308Sache			       *boolean_varlist[i].value ? "on" : "off");
227021308Sache    }
227121308Sache
2272157184Sache  for (i = 0; string_varlist[i].name; i++)
227321308Sache    {
2274157184Sache      v = _rl_get_string_variable_value (string_varlist[i].name);
2275157184Sache      if (v == 0)	/* _rl_isearch_terminators can be NULL */
2276157184Sache	continue;
227747558Sache      if (print_readably)
2278157184Sache        fprintf (rl_outstream, "set %s %s\n", string_varlist[i].name, v);
227947558Sache      else
2280157184Sache        fprintf (rl_outstream, "%s is set to `%s'\n", string_varlist[i].name, v);
228147558Sache    }
228221308Sache}
228321308Sache
228421308Sache/* Print all of the current variables and their values to
228521308Sache   rl_outstream.  If an explicit argument is given, then print
228621308Sache   the output in such a way that it can be read back in. */
228721308Sacheint
228821308Sacherl_dump_variables (count, key)
228921308Sache     int count, key;
229021308Sache{
229126497Sache  if (rl_dispatching)
229226497Sache    fprintf (rl_outstream, "\r\n");
229321308Sache  rl_variable_dumper (rl_explicit_arg);
229421308Sache  rl_on_new_line ();
229521308Sache  return (0);
229621308Sache}
229721308Sache
229821308Sache/* Return non-zero if any members of ARRAY are a substring in STRING. */
229921308Sachestatic int
230021308Sachesubstring_member_of_array (string, array)
230175406Sache     char *string;
230275406Sache     const char **array;
230321308Sache{
230421308Sache  while (*array)
230521308Sache    {
230621308Sache      if (_rl_strindex (string, *array))
230721308Sache	return (1);
230821308Sache      array++;
230921308Sache    }
231021308Sache  return (0);
231121308Sache}
2312