File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / readline / bind.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 01:01:01 2021 UTC (3 years, 3 months ago) by misho
Branches: readline, MAIN
CVS tags: v8_2p0, v8_1p0, HEAD
readline 8.1

    1: /* bind.c -- key binding and startup file support for the readline library. */
    2: 
    3: /* Copyright (C) 1987-2020 Free Software Foundation, Inc.
    4: 
    5:    This file is part of the GNU Readline Library (Readline), a library
    6:    for reading lines of text with interactive input and history editing.
    7: 
    8:    Readline is free software: you can redistribute it and/or modify
    9:    it under the terms of the GNU General Public License as published by
   10:    the Free Software Foundation, either version 3 of the License, or
   11:    (at your option) any later version.
   12: 
   13:    Readline is distributed in the hope that it will be useful,
   14:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:    GNU General Public License for more details.
   17: 
   18:    You should have received a copy of the GNU General Public License
   19:    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
   20: */
   21: 
   22: #define READLINE_LIBRARY
   23: 
   24: #if defined (__TANDEM)
   25: #  include <floss.h>
   26: #endif
   27: 
   28: #if defined (HAVE_CONFIG_H)
   29: #  include <config.h>
   30: #endif
   31: 
   32: #include <stdio.h>
   33: #include <sys/types.h>
   34: #include <fcntl.h>
   35: #if defined (HAVE_SYS_FILE_H)
   36: #  include <sys/file.h>
   37: #endif /* HAVE_SYS_FILE_H */
   38: 
   39: #if defined (HAVE_UNISTD_H)
   40: #  include <unistd.h>
   41: #endif /* HAVE_UNISTD_H */
   42: 
   43: #if defined (HAVE_STDLIB_H)
   44: #  include <stdlib.h>
   45: #else
   46: #  include "ansi_stdlib.h"
   47: #endif /* HAVE_STDLIB_H */
   48: 
   49: #include <errno.h>
   50: 
   51: #if !defined (errno)
   52: extern int errno;
   53: #endif /* !errno */
   54: 
   55: #include "posixstat.h"
   56: 
   57: /* System-specific feature definitions and include files. */
   58: #include "rldefs.h"
   59: 
   60: /* Some standard library routines. */
   61: #include "readline.h"
   62: #include "history.h"
   63: 
   64: #include "rlprivate.h"
   65: #include "rlshell.h"
   66: #include "xmalloc.h"
   67: 
   68: #if !defined (strchr) && !defined (__STDC__)
   69: extern char *strchr (), *strrchr ();
   70: #endif /* !strchr && !__STDC__ */
   71: 
   72: /* Variables exported by this file. */
   73: Keymap rl_binding_keymap;
   74: 
   75: static int _rl_skip_to_delim PARAMS((char *, int, int));
   76: 
   77: #if defined (USE_VARARGS) && defined (PREFER_STDARG)
   78: static void _rl_init_file_error (const char *, ...)  __attribute__((__format__ (printf, 1, 2)));
   79: #else
   80: static void _rl_init_file_error ();
   81: #endif
   82: 
   83: static rl_command_func_t *_rl_function_of_keyseq_internal PARAMS((const char *, size_t, Keymap, int *));
   84: 
   85: static char *_rl_read_file PARAMS((char *, size_t *));
   86: static int _rl_read_init_file PARAMS((const char *, int));
   87: static int glean_key_from_name PARAMS((char *));
   88: 
   89: static int find_boolean_var PARAMS((const char *));
   90: static int find_string_var PARAMS((const char *));
   91: 
   92: static const char *boolean_varname PARAMS((int));
   93: static const char *string_varname PARAMS((int));
   94: 
   95: static char *_rl_get_string_variable_value PARAMS((const char *));
   96: static int substring_member_of_array PARAMS((const char *, const char * const *));
   97: 
   98: static int _rl_get_keymap_by_name PARAMS((const char *));
   99: static int _rl_get_keymap_by_map PARAMS((Keymap));
  100: 
  101: static int currently_reading_init_file;
  102: 
  103: /* used only in this file */
  104: static int _rl_prefer_visible_bell = 1;
  105: 
  106: #define OP_EQ	1
  107: #define OP_NE	2
  108: #define OP_GT	3
  109: #define OP_GE	4
  110: #define OP_LT	5
  111: #define OP_LE	6
  112: 
  113: #define OPSTART(c)	((c) == '=' || (c) == '!' || (c) == '<' || (c) == '>')
  114: #define CMPSTART(c)	((c) == '=' || (c) == '!')
  115: 
  116: /* **************************************************************** */
  117: /*								    */
  118: /*			Binding keys				    */
  119: /*								    */
  120: /* **************************************************************** */
  121: 
  122: /* rl_add_defun (char *name, rl_command_func_t *function, int key)
  123:    Add NAME to the list of named functions.  Make FUNCTION be the function
  124:    that gets called.  If KEY is not -1, then bind it. */
  125: int
  126: rl_add_defun (const char *name, rl_command_func_t *function, int key)
  127: {
  128:   if (key != -1)
  129:     rl_bind_key (key, function);
  130:   rl_add_funmap_entry (name, function);
  131:   return 0;
  132: }
  133: 
  134: /* Bind KEY to FUNCTION.  Returns non-zero if KEY is out of range. */
  135: int
  136: rl_bind_key (int key, rl_command_func_t *function)
  137: {
  138:   char keyseq[4];
  139:   int l;
  140: 
  141:   if (key < 0 || key > largest_char)
  142:     return (key);
  143: 
  144:   /* Want to make this a multi-character key sequence with an ESC prefix */
  145:   if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
  146:     {
  147:       if (_rl_keymap[ESC].type == ISKMAP)
  148: 	{
  149: 	  Keymap escmap;
  150: 
  151: 	  escmap = FUNCTION_TO_KEYMAP (_rl_keymap, ESC);
  152: 	  key = UNMETA (key);
  153: 	  escmap[key].type = ISFUNC;
  154: 	  escmap[key].function = function;
  155: 	  return (0);
  156: 	}
  157: 
  158:       /* Otherwise, let's just let rl_generic_bind handle the key sequence.
  159: 	 We start it off with ESC here and let the code below add the rest
  160: 	 of the sequence. */
  161:       keyseq[0] = ESC;
  162:       l = 1;
  163:       key = UNMETA(key);
  164:       goto bind_keyseq;
  165:     }
  166: 
  167:   /* If it's bound to a function or macro, just overwrite.  Otherwise we have
  168:      to treat it as a key sequence so rl_generic_bind handles shadow keymaps
  169:      for us.  If we are binding '\' or \C-@ (NUL) make sure to escape it so
  170:      it makes it through the call to rl_translate_keyseq. */
  171:   if (_rl_keymap[key].type != ISKMAP)
  172:     {
  173:       if (_rl_keymap[key].type == ISMACR)
  174: 	xfree ((char *)_rl_keymap[key].function);
  175:       _rl_keymap[key].type = ISFUNC;
  176:       _rl_keymap[key].function = function;
  177:     }
  178:   else
  179:     {
  180:       l = 0;
  181: bind_keyseq:
  182:       if (key == '\\')
  183: 	{
  184: 	  keyseq[l++] = '\\';
  185: 	  keyseq[l++] = '\\';
  186: 	}
  187:       else if (key == '\0')	  
  188: 	{
  189: 	  keyseq[l++] = '\\';
  190: 	  keyseq[l++] = '0';
  191: 	}
  192:       else
  193: 	keyseq[l++] = key;
  194:       keyseq[l] = '\0';
  195:       rl_bind_keyseq (keyseq, function);
  196:     }
  197:   rl_binding_keymap = _rl_keymap;
  198:   return (0);
  199: }
  200: 
  201: /* Bind KEY to FUNCTION in MAP.  Returns non-zero in case of invalid
  202:    KEY. */
  203: int
  204: rl_bind_key_in_map (int key, rl_command_func_t *function, Keymap map)
  205: {
  206:   int result;
  207:   Keymap oldmap;
  208: 
  209:   oldmap = _rl_keymap;
  210:   _rl_keymap = map;
  211:   result = rl_bind_key (key, function);
  212:   _rl_keymap = oldmap;
  213:   return (result);
  214: }
  215: 
  216: /* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound.  Right
  217:    now, this is always used to attempt to bind the arrow keys. */
  218: int
  219: rl_bind_key_if_unbound_in_map (int key, rl_command_func_t *default_func, Keymap kmap)
  220: {
  221:   char *keyseq;
  222: 
  223:   keyseq = rl_untranslate_keyseq ((unsigned char)key);
  224:   return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap));
  225: }
  226: 
  227: int
  228: rl_bind_key_if_unbound (int key, rl_command_func_t *default_func)
  229: {
  230:   char *keyseq;
  231: 
  232:   keyseq = rl_untranslate_keyseq ((unsigned char)key);
  233:   return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
  234: }
  235: 
  236: /* Make KEY do nothing in the currently selected keymap.
  237:    Returns non-zero in case of error.  This is not the same as self-insert;
  238:    this makes it a dead key. */
  239: int
  240: rl_unbind_key (int key)
  241: {
  242:   return (rl_bind_key (key, (rl_command_func_t *)NULL));
  243: }
  244: 
  245: /* Make KEY do nothing in MAP. Returns non-zero in case of error. */
  246: int
  247: rl_unbind_key_in_map (int key, Keymap map)
  248: {
  249:   return (rl_bind_key_in_map (key, (rl_command_func_t *)NULL, map));
  250: }
  251: 
  252: /* Unbind all keys bound to FUNCTION in MAP. */
  253: int
  254: rl_unbind_function_in_map (rl_command_func_t *func, Keymap map)
  255: {
  256:   register int i, rval;
  257: 
  258:   for (i = rval = 0; i < KEYMAP_SIZE; i++)
  259:     {
  260:       if (map[i].type == ISFUNC && map[i].function == func)
  261: 	{
  262: 	  map[i].function = (rl_command_func_t *)NULL;
  263: 	  rval = 1;
  264: 	}
  265:       else if (map[i].type == ISKMAP)		/* TAG:readline-8.1 */
  266: 	{
  267: 	  int r;
  268: 	  r = rl_unbind_function_in_map (func, FUNCTION_TO_KEYMAP (map, i));
  269: 	  if (r == 1)
  270: 	    rval = 1;
  271: 	}
  272:     }
  273:   return rval;
  274: }
  275: 
  276: /* Unbind all keys bound to COMMAND, which is a bindable command name, in MAP */
  277: int
  278: rl_unbind_command_in_map (const char *command, Keymap map)
  279: {
  280:   rl_command_func_t *func;
  281: 
  282:   func = rl_named_function (command);
  283:   if (func == 0)
  284:     return 0;
  285:   return (rl_unbind_function_in_map (func, map));
  286: }
  287: 
  288: /* Bind the key sequence represented by the string KEYSEQ to
  289:    FUNCTION, starting in the current keymap.  This makes new
  290:    keymaps as necessary. */
  291: int
  292: rl_bind_keyseq (const char *keyseq, rl_command_func_t *function)
  293: {
  294:   return (rl_generic_bind (ISFUNC, keyseq, (char *)function, _rl_keymap));
  295: }
  296: 
  297: /* Bind the key sequence represented by the string KEYSEQ to
  298:    FUNCTION.  This makes new keymaps as necessary.  The initial
  299:    place to do bindings is in MAP. */
  300: int
  301: rl_bind_keyseq_in_map (const char *keyseq, rl_command_func_t *function, Keymap map)
  302: {
  303:   return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
  304: }
  305: 
  306: /* Backwards compatibility; equivalent to rl_bind_keyseq_in_map() */
  307: int
  308: rl_set_key (const char *keyseq, rl_command_func_t *function, Keymap map)
  309: {
  310:   return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
  311: }
  312: 
  313: /* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound.  Right
  314:    now, this is always used to attempt to bind the arrow keys, hence the
  315:    check for rl_vi_movement_mode. */
  316: int
  317: rl_bind_keyseq_if_unbound_in_map (const char *keyseq, rl_command_func_t *default_func, Keymap kmap)
  318: {
  319:   rl_command_func_t *func;
  320:   char *keys;
  321:   int keys_len;
  322: 
  323:   if (keyseq)
  324:     {
  325:       /* Handle key sequences that require translations and `raw' ones that
  326: 	 don't. This might be a problem with backslashes. */
  327:       keys = (char *)xmalloc (1 + (2 * strlen (keyseq)));
  328:       if (rl_translate_keyseq (keyseq, keys, &keys_len))
  329: 	{
  330: 	  xfree (keys);
  331: 	  return -1;
  332: 	}
  333:       func = rl_function_of_keyseq_len (keys, keys_len, kmap, (int *)NULL);
  334:       xfree (keys);
  335: #if defined (VI_MODE)
  336:       if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode)
  337: #else
  338:       if (!func || func == rl_do_lowercase_version)
  339: #endif
  340: 	return (rl_bind_keyseq_in_map (keyseq, default_func, kmap));
  341:       else
  342: 	return 1;
  343:     }
  344:   return 0;
  345: }
  346: 
  347: int
  348: rl_bind_keyseq_if_unbound (const char *keyseq, rl_command_func_t *default_func)
  349: {
  350:   return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
  351: }
  352: 
  353: /* Bind the key sequence represented by the string KEYSEQ to
  354:    the string of characters MACRO.  This makes new keymaps as
  355:    necessary.  The initial place to do bindings is in MAP. */
  356: int
  357: rl_macro_bind (const char *keyseq, const char *macro, Keymap map)
  358: {
  359:   char *macro_keys;
  360:   int macro_keys_len;
  361: 
  362:   macro_keys = (char *)xmalloc ((2 * strlen (macro)) + 1);
  363: 
  364:   if (rl_translate_keyseq (macro, macro_keys, &macro_keys_len))
  365:     {
  366:       xfree (macro_keys);
  367:       return -1;
  368:     }
  369:   rl_generic_bind (ISMACR, keyseq, macro_keys, map);
  370:   return 0;
  371: }
  372: 
  373: /* Bind the key sequence represented by the string KEYSEQ to
  374:    the arbitrary pointer DATA.  TYPE says what kind of data is
  375:    pointed to by DATA, right now this can be a function (ISFUNC),
  376:    a macro (ISMACR), or a keymap (ISKMAP).  This makes new keymaps
  377:    as necessary.  The initial place to do bindings is in MAP. */
  378: int
  379: rl_generic_bind (int type, const char *keyseq, char *data, Keymap map)
  380: {
  381:   char *keys;
  382:   int keys_len, prevkey, ic;
  383:   register int i;
  384:   KEYMAP_ENTRY k;
  385:   Keymap prevmap;  
  386: 
  387:   k.function = 0;
  388: 
  389:   /* If no keys to bind to, exit right away. */
  390:   if (keyseq == 0 || *keyseq == 0)
  391:     {
  392:       if (type == ISMACR)
  393: 	xfree (data);
  394:       return -1;
  395:     }
  396: 
  397:   keys = (char *)xmalloc (1 + (2 * strlen (keyseq)));
  398: 
  399:   /* Translate the ASCII representation of KEYSEQ into an array of
  400:      characters.  Stuff the characters into KEYS, and the length of
  401:      KEYS into KEYS_LEN. */
  402:   if (rl_translate_keyseq (keyseq, keys, &keys_len))
  403:     {
  404:       xfree (keys);
  405:       return -1;
  406:     }
  407: 
  408:   prevmap = map;
  409:   prevkey = keys[0];
  410: 
  411:   /* Bind keys, making new keymaps as necessary. */
  412:   for (i = 0; i < keys_len; i++)
  413:     {
  414:       unsigned char uc = keys[i];
  415: 
  416:       if (i > 0)
  417: 	prevkey = ic;
  418: 
  419:       ic = uc;
  420:       if (ic < 0 || ic >= KEYMAP_SIZE)
  421:         {
  422:           xfree (keys);
  423: 	  return -1;
  424:         }
  425: 
  426:       /* We now rely on rl_translate_keyseq to do this conversion, so this
  427: 	 check is superfluous. */
  428: #if 0
  429:       if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
  430: 	{
  431: 	  ic = UNMETA (ic);
  432: 	  if (map[ESC].type == ISKMAP)
  433: 	    {
  434: 	      prevmap = map;
  435: 	      map = FUNCTION_TO_KEYMAP (map, ESC);
  436: 	    }
  437: 	}
  438: #endif
  439: 
  440:       if ((i + 1) < keys_len)
  441: 	{
  442: 	  if (map[ic].type != ISKMAP)
  443: 	    {
  444: 	      /* We allow subsequences of keys.  If a keymap is being
  445: 		 created that will `shadow' an existing function or macro
  446: 		 key binding, we save that keybinding into the ANYOTHERKEY
  447: 		 index in the new map.  The dispatch code will look there
  448: 		 to find the function to execute if the subsequence is not
  449: 		 matched.  ANYOTHERKEY was chosen to be greater than
  450: 		 UCHAR_MAX. */
  451: 	      k = map[ic];
  452: 
  453: 	      map[ic].type = ISKMAP;
  454: 	      map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap());
  455: 	    }
  456: 	  prevmap = map;
  457: 	  map = FUNCTION_TO_KEYMAP (map, ic);
  458: 	  /* The dispatch code will return this function if no matching
  459: 	     key sequence is found in the keymap.  This (with a little
  460: 	     help from the dispatch code in readline.c) allows `a' to be
  461: 	     mapped to something, `abc' to be mapped to something else,
  462: 	     and the function bound  to `a' to be executed when the user
  463: 	     types `abx', leaving `bx' in the input queue. */
  464: 	  if (k.function && ((k.type == ISFUNC && k.function != rl_do_lowercase_version) || k.type == ISMACR))
  465: 	    {
  466: 	      map[ANYOTHERKEY] = k;
  467: 	      k.function = 0;
  468: 	    }
  469: 	}
  470:       else
  471: 	{
  472: 	  if (map[ic].type == ISKMAP)
  473: 	    {
  474: 	      prevmap = map;
  475: 	      map = FUNCTION_TO_KEYMAP (map, ic);
  476: 	      ic = ANYOTHERKEY;
  477: 	      /* If we're trying to override a keymap with a null function
  478: 		 (e.g., trying to unbind it), we can't use a null pointer
  479: 		 here because that's indistinguishable from having not been
  480: 		 overridden.  We use a special bindable function that does
  481: 		 nothing. */
  482: 	      if (type == ISFUNC && data == 0)
  483: 		data = (char *)_rl_null_function;
  484: 	    }
  485: 	  if (map[ic].type == ISMACR)
  486: 	    xfree ((char *)map[ic].function);
  487: 
  488: 	  map[ic].function = KEYMAP_TO_FUNCTION (data);
  489: 	  map[ic].type = type;
  490: 	}
  491: 
  492:       rl_binding_keymap = map;
  493: 
  494:     }
  495: 
  496:   /* If we unbound a key (type == ISFUNC, data == 0), and the prev keymap
  497:      points to the keymap where we unbound the key (sanity check), and the
  498:      current binding keymap is empty (rl_empty_keymap() returns non-zero),
  499:      and the binding keymap has ANYOTHERKEY set with type == ISFUNC
  500:      (overridden function), delete the now-empty keymap, take the previously-
  501:      overridden function and remove the override. */
  502:   /* Right now, this only works one level back. */
  503:   if (type == ISFUNC && data == 0 &&
  504:       prevmap[prevkey].type == ISKMAP &&
  505:       (FUNCTION_TO_KEYMAP(prevmap, prevkey) == rl_binding_keymap) &&
  506:       rl_binding_keymap[ANYOTHERKEY].type == ISFUNC &&
  507:       rl_empty_keymap (rl_binding_keymap))
  508:     {
  509:       prevmap[prevkey].type = rl_binding_keymap[ANYOTHERKEY].type;
  510:       prevmap[prevkey].function = rl_binding_keymap[ANYOTHERKEY].function;
  511:       rl_discard_keymap (rl_binding_keymap);
  512:       rl_binding_keymap = prevmap;
  513:     }
  514: 
  515:   xfree (keys);
  516:   return 0;
  517: }
  518: 
  519: /* Translate the ASCII representation of SEQ, stuffing the values into ARRAY,
  520:    an array of characters.  LEN gets the final length of ARRAY.  Return
  521:    non-zero if there was an error parsing SEQ. */
  522: int
  523: rl_translate_keyseq (const char *seq, char *array, int *len)
  524: {
  525:   register int i, l, temp;
  526:   int has_control, has_meta;
  527:   unsigned char c;
  528: 
  529:   has_control = 0;
  530:   has_meta = 0;
  531: 
  532:   /* When there are incomplete prefixes \C- or \M- (has_control || has_meta)
  533:      without base character at the end of SEQ, they are processed as the
  534:      prefixes for '\0'.
  535:   */
  536:   for (i = l = 0; (c = seq[i]) || has_control || has_meta; i++)
  537:     {
  538:       /* Only backslashes followed by a non-null character are handled
  539: 	 specially.  Trailing backslash (backslash followed by '\0') is
  540: 	 processed as a normal character.
  541:       */
  542:       if (c == '\\' && seq[i + 1] != '\0')
  543: 	{
  544: 	  c = seq[++i];
  545: 
  546: 	  /* Handle \C- and \M- prefixes. */
  547: 	  if (c == 'C' && seq[i + 1] == '-')
  548: 	    {
  549: 	      i++;
  550: 	      has_control = 1;
  551: 	      continue;
  552: 	    }
  553: 	  else if (c == 'M' && seq[i + 1] == '-')
  554: 	    {
  555: 	      i++;
  556: 	      has_meta = 1;
  557: 	      continue;
  558: 	    }	      
  559: 
  560: 	  /* Translate other backslash-escaped characters.  These are the
  561: 	     same escape sequences that bash's `echo' and `printf' builtins
  562: 	     handle, with the addition of \d -> RUBOUT.  A backslash
  563: 	     preceding a character that is not special is stripped. */
  564: 	  switch (c)
  565: 	    {
  566: 	    case 'a':
  567: 	      c = '\007';
  568: 	      break;
  569: 	    case 'b':
  570: 	      c = '\b';
  571: 	      break;
  572: 	    case 'd':
  573: 	      c = RUBOUT;	/* readline-specific */
  574: 	      break;
  575: 	    case 'e':
  576: 	      c = ESC;
  577: 	      break;
  578: 	    case 'f':
  579: 	      c = '\f';
  580: 	      break;
  581: 	    case 'n':
  582: 	      c = NEWLINE;
  583: 	      break;
  584: 	    case 'r':
  585: 	      c = RETURN;
  586: 	      break;
  587: 	    case 't':
  588: 	      c = TAB;
  589: 	      break;
  590: 	    case 'v':
  591: 	      c = 0x0B;
  592: 	      break;
  593: 	    case '\\':
  594: 	      c = '\\';
  595: 	      break;
  596: 	    case '0': case '1': case '2': case '3':
  597: 	    case '4': case '5': case '6': case '7':
  598: 	      i++;
  599: 	      for (temp = 2, c -= '0'; ISOCTAL ((unsigned char)seq[i]) && temp--; i++)
  600: 	        c = (c * 8) + OCTVALUE (seq[i]);
  601: 	      i--;	/* auto-increment in for loop */
  602: 	      c &= largest_char;
  603: 	      break;
  604: 	    case 'x':
  605: 	      i++;
  606: 	      for (temp = 2, c = 0; ISXDIGIT ((unsigned char)seq[i]) && temp--; i++)
  607: 	        c = (c * 16) + HEXVALUE (seq[i]);
  608: 	      if (temp == 2)
  609: 	        c = 'x';
  610: 	      i--;	/* auto-increment in for loop */
  611: 	      c &= largest_char;
  612: 	      break;
  613: 	    default:	/* backslashes before non-special chars just add the char */
  614: 	      c &= largest_char;
  615: 	      break;	/* the backslash is stripped */
  616: 	    }
  617: 	}
  618: 
  619:       /* Process \C- and \M- flags */
  620:       if (has_control)
  621: 	{
  622: 	  /* Special treatment for C-? */
  623: 	  c = (c == '?') ? RUBOUT : CTRL (_rl_to_upper (c));
  624: 	  has_control = 0;
  625: 	}
  626:       if (has_meta)
  627: 	{
  628: 	  c = META (c);
  629: 	  has_meta = 0;
  630: 	}
  631: 
  632:       /* If convert-meta is turned on, convert a meta char to a key sequence  */
  633:       if (META_CHAR (c) && _rl_convert_meta_chars_to_ascii)
  634: 	{
  635: 	  array[l++] = ESC;	/* ESC is meta-prefix */
  636: 	  array[l++] = UNMETA (c);
  637: 	}
  638:       else
  639: 	array[l++] = (c);
  640: 
  641:       /* Null characters may be processed for incomplete prefixes at the end of
  642: 	 sequence */
  643:       if (seq[i] == '\0')
  644: 	break;
  645:     }
  646: 
  647:   *len = l;
  648:   array[l] = '\0';
  649:   return (0);
  650: }
  651: 
  652: static int
  653: _rl_isescape (int c)
  654: {
  655:   switch (c)
  656:     {
  657:     case '\007':
  658:     case '\b':
  659:     case '\f':
  660:     case '\n':
  661:     case '\r':
  662:     case TAB:
  663:     case 0x0b:  return (1);
  664:     default: return (0);
  665:     }
  666: }
  667: 
  668: static int
  669: _rl_escchar (int c)
  670: {
  671:   switch (c)
  672:     {
  673:     case '\007':  return ('a');
  674:     case '\b':  return ('b');
  675:     case '\f':  return ('f');
  676:     case '\n':  return ('n');
  677:     case '\r':  return ('r');
  678:     case TAB:  return ('t');
  679:     case 0x0b:  return ('v');
  680:     default: return (c);
  681:     }
  682: }
  683: 
  684: char *
  685: rl_untranslate_keyseq (int seq)
  686: {
  687:   static char kseq[16];
  688:   int i, c;
  689: 
  690:   i = 0;
  691:   c = seq;
  692:   if (META_CHAR (c))
  693:     {
  694:       kseq[i++] = '\\';
  695:       kseq[i++] = 'M';
  696:       kseq[i++] = '-';
  697:       c = UNMETA (c);
  698:     }
  699:   else if (c == ESC)
  700:     {
  701:       kseq[i++] = '\\';
  702:       c = 'e';
  703:     }
  704:   else if (CTRL_CHAR (c))
  705:     {
  706:       kseq[i++] = '\\';
  707:       kseq[i++] = 'C';
  708:       kseq[i++] = '-';
  709:       c = _rl_to_lower (UNCTRL (c));
  710:     }
  711:   else if (c == RUBOUT)
  712:     {
  713:       kseq[i++] = '\\';
  714:       kseq[i++] = 'C';
  715:       kseq[i++] = '-';
  716:       c = '?';
  717:     }
  718: 
  719:   if (c == ESC)
  720:     {
  721:       kseq[i++] = '\\';
  722:       c = 'e';
  723:     }
  724:   else if (c == '\\' || c == '"')
  725:     {
  726:       kseq[i++] = '\\';
  727:     }
  728: 
  729:   kseq[i++] = (unsigned char) c;
  730:   kseq[i] = '\0';
  731:   return kseq;
  732: }
  733: 
  734: char *
  735: _rl_untranslate_macro_value (char *seq, int use_escapes)
  736: {
  737:   char *ret, *r, *s;
  738:   int c;
  739: 
  740:   r = ret = (char *)xmalloc (7 * strlen (seq) + 1);
  741:   for (s = seq; *s; s++)
  742:     {
  743:       c = *s;
  744:       if (META_CHAR (c))
  745: 	{
  746: 	  *r++ = '\\';
  747: 	  *r++ = 'M';
  748: 	  *r++ = '-';
  749: 	  c = UNMETA (c);
  750: 	}
  751:       else if (c == ESC)
  752: 	{
  753: 	  *r++ = '\\';
  754: 	  c = 'e';
  755: 	}
  756:       else if (CTRL_CHAR (c))
  757: 	{
  758: 	  *r++ = '\\';
  759: 	  if (use_escapes && _rl_isescape (c))
  760: 	    c = _rl_escchar (c);
  761: 	  else
  762: 	    {
  763: 	      *r++ = 'C';
  764: 	      *r++ = '-';
  765: 	      c = _rl_to_lower (UNCTRL (c));
  766: 	    }
  767: 	}
  768:       else if (c == RUBOUT)
  769:  	{
  770:  	  *r++ = '\\';
  771:  	  *r++ = 'C';
  772:  	  *r++ = '-';
  773:  	  c = '?';
  774:  	}
  775: 
  776:       if (c == ESC)
  777: 	{
  778: 	  *r++ = '\\';
  779: 	  c = 'e';
  780: 	}
  781:       else if (c == '\\' || c == '"')
  782: 	*r++ = '\\';
  783: 
  784:       *r++ = (unsigned char)c;
  785:     }
  786:   *r = '\0';
  787:   return ret;
  788: }
  789: 
  790: /* Return a pointer to the function that STRING represents.
  791:    If STRING doesn't have a matching function, then a NULL pointer
  792:    is returned. The string match is case-insensitive. */
  793: rl_command_func_t *
  794: rl_named_function (const char *string)
  795: {
  796:   register int i;
  797: 
  798:   rl_initialize_funmap ();
  799: 
  800:   for (i = 0; funmap[i]; i++)
  801:     if (_rl_stricmp (funmap[i]->name, string) == 0)
  802:       return (funmap[i]->function);
  803:   return ((rl_command_func_t *)NULL);
  804: }
  805: 
  806: /* Return the function (or macro) definition which would be invoked via
  807:    KEYSEQ if executed in MAP.  If MAP is NULL, then the current keymap is
  808:    used.  TYPE, if non-NULL, is a pointer to an int which will receive the
  809:    type of the object pointed to.  One of ISFUNC (function), ISKMAP (keymap),
  810:    or ISMACR (macro). */
  811: static rl_command_func_t *
  812: _rl_function_of_keyseq_internal (const char *keyseq, size_t len, Keymap map, int *type)
  813: {
  814:   register int i;
  815: 
  816:   if (map == 0)
  817:     map = _rl_keymap;
  818: 
  819:   for (i = 0; keyseq && i < len; i++)
  820:     {
  821:       unsigned char ic = keyseq[i];
  822: 
  823:       if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
  824: 	{
  825: 	  if (map[ESC].type == ISKMAP)
  826: 	    {
  827: 	      map = FUNCTION_TO_KEYMAP (map, ESC);
  828: 	      ic = UNMETA (ic);
  829: 	    }
  830: 	  /* XXX - should we just return NULL here, since this obviously
  831: 	     doesn't match? */
  832: 	  else
  833: 	    {
  834: 	      if (type)
  835: 		*type = map[ESC].type;
  836: 
  837: 	      return (map[ESC].function);
  838: 	    }
  839: 	}
  840: 
  841:       if (map[ic].type == ISKMAP)
  842: 	{
  843: 	  /* If this is the last key in the key sequence, return the
  844: 	     map. */
  845: 	  if (i + 1 == len)
  846: 	    {
  847: 	      if (type)
  848: 		*type = ISKMAP;
  849: 
  850: 	      return (map[ic].function);
  851: 	    }
  852: 	  else
  853: 	    map = FUNCTION_TO_KEYMAP (map, ic);
  854: 	}
  855:       /* If we're not at the end of the key sequence, and the current key
  856: 	 is bound to something other than a keymap, then the entire key
  857: 	 sequence is not bound. */
  858:       else if (map[ic].type != ISKMAP && i+1 < len)
  859: 	return ((rl_command_func_t *)NULL);
  860:       else	/* map[ic].type != ISKMAP && i+1 == len */
  861: 	{
  862: 	  if (type)
  863: 	    *type = map[ic].type;
  864: 
  865: 	  return (map[ic].function);
  866: 	}
  867:     }
  868:   return ((rl_command_func_t *) NULL);
  869: }
  870: 
  871: rl_command_func_t *
  872: rl_function_of_keyseq (const char *keyseq, Keymap map, int *type)
  873: {
  874:   return _rl_function_of_keyseq_internal (keyseq, strlen (keyseq), map, type);
  875: }
  876: 
  877: rl_command_func_t *
  878: rl_function_of_keyseq_len (const char *keyseq, size_t len, Keymap map, int *type)
  879: {
  880:   return _rl_function_of_keyseq_internal (keyseq, len, map, type);
  881: }
  882: 
  883: /* The last key bindings file read. */
  884: static char *last_readline_init_file = (char *)NULL;
  885: 
  886: /* The file we're currently reading key bindings from. */
  887: static const char *current_readline_init_file;
  888: static int current_readline_init_include_level;
  889: static int current_readline_init_lineno;
  890: 
  891: /* Read FILENAME into a locally-allocated buffer and return the buffer.
  892:    The size of the buffer is returned in *SIZEP.  Returns NULL if any
  893:    errors were encountered. */
  894: static char *
  895: _rl_read_file (char *filename, size_t *sizep)
  896: {
  897:   struct stat finfo;
  898:   size_t file_size;
  899:   char *buffer;
  900:   int i, file;
  901: 
  902:   file = -1;
  903:   if (((file = open (filename, O_RDONLY, 0666)) < 0) || (fstat (file, &finfo) < 0))
  904:     {
  905:       if (file >= 0)
  906: 	close (file);
  907:       return ((char *)NULL);
  908:     }
  909: 
  910:   file_size = (size_t)finfo.st_size;
  911: 
  912:   /* check for overflow on very large files */
  913:   if (file_size != finfo.st_size || file_size + 1 < file_size)
  914:     {
  915:       if (file >= 0)
  916: 	close (file);
  917: #if defined (EFBIG)
  918:       errno = EFBIG;
  919: #endif
  920:       return ((char *)NULL);
  921:     }
  922: 
  923:   /* Read the file into BUFFER. */
  924:   buffer = (char *)xmalloc (file_size + 1);
  925:   i = read (file, buffer, file_size);
  926:   close (file);
  927: 
  928:   if (i < 0)
  929:     {
  930:       xfree (buffer);
  931:       return ((char *)NULL);
  932:     }
  933: 
  934:   RL_CHECK_SIGNALS ();
  935: 
  936:   buffer[i] = '\0';
  937:   if (sizep)
  938:     *sizep = i;
  939: 
  940:   return (buffer);
  941: }
  942: 
  943: /* Re-read the current keybindings file. */
  944: int
  945: rl_re_read_init_file (int count, int ignore)
  946: {
  947:   int r;
  948:   r = rl_read_init_file ((const char *)NULL);
  949:   rl_set_keymap_from_edit_mode ();
  950:   return r;
  951: }
  952: 
  953: /* Do key bindings from a file.  If FILENAME is NULL it defaults
  954:    to the first non-null filename from this list:
  955:      1. the filename used for the previous call
  956:      2. the value of the shell variable `INPUTRC'
  957:      3. ~/.inputrc
  958:      4. /etc/inputrc
  959:    If the file existed and could be opened and read, 0 is returned,
  960:    otherwise errno is returned. */
  961: int
  962: rl_read_init_file (const char *filename)
  963: {
  964:   /* Default the filename. */
  965:   if (filename == 0)
  966:     filename = last_readline_init_file;
  967:   if (filename == 0)
  968:     filename = sh_get_env_value ("INPUTRC");
  969:   if (filename == 0 || *filename == 0)
  970:     {
  971:       filename = DEFAULT_INPUTRC;
  972:       /* Try to read DEFAULT_INPUTRC; fall back to SYS_INPUTRC on failure */
  973:       if (_rl_read_init_file (filename, 0) == 0)
  974: 	return 0;
  975:       filename = SYS_INPUTRC;
  976:     }
  977: 
  978: #if defined (__MSDOS__)
  979:   if (_rl_read_init_file (filename, 0) == 0)
  980:     return 0;
  981:   filename = "~/_inputrc";
  982: #endif
  983:   return (_rl_read_init_file (filename, 0));
  984: }
  985: 
  986: static int
  987: _rl_read_init_file (const char *filename, int include_level)
  988: {
  989:   register int i;
  990:   char *buffer, *openname, *line, *end;
  991:   size_t file_size;
  992: 
  993:   current_readline_init_file = filename;
  994:   current_readline_init_include_level = include_level;
  995: 
  996:   openname = tilde_expand (filename);
  997:   buffer = _rl_read_file (openname, &file_size);
  998:   xfree (openname);
  999: 
 1000:   RL_CHECK_SIGNALS ();
 1001:   if (buffer == 0)
 1002:     return (errno);
 1003:   
 1004:   if (include_level == 0 && filename != last_readline_init_file)
 1005:     {
 1006:       FREE (last_readline_init_file);
 1007:       last_readline_init_file = savestring (filename);
 1008:     }
 1009: 
 1010:   currently_reading_init_file = 1;
 1011: 
 1012:   /* Loop over the lines in the file.  Lines that start with `#' are
 1013:      comments; all other lines are commands for readline initialization. */
 1014:   current_readline_init_lineno = 1;
 1015:   line = buffer;
 1016:   end = buffer + file_size;
 1017:   while (line < end)
 1018:     {
 1019:       /* Find the end of this line. */
 1020:       for (i = 0; line + i != end && line[i] != '\n'; i++);
 1021: 
 1022: #if defined (__CYGWIN__)
 1023:       /* ``Be liberal in what you accept.'' */
 1024:       if (line[i] == '\n' && line[i-1] == '\r')
 1025: 	line[i - 1] = '\0';
 1026: #endif
 1027: 
 1028:       /* Mark end of line. */
 1029:       line[i] = '\0';
 1030: 
 1031:       /* Skip leading whitespace. */
 1032:       while (*line && whitespace (*line))
 1033:         {
 1034: 	  line++;
 1035: 	  i--;
 1036:         }
 1037: 
 1038:       /* If the line is not a comment, then parse it. */
 1039:       if (*line && *line != '#')
 1040: 	rl_parse_and_bind (line);
 1041: 
 1042:       /* Move to the next line. */
 1043:       line += i + 1;
 1044:       current_readline_init_lineno++;
 1045:     }
 1046: 
 1047:   xfree (buffer);
 1048:   currently_reading_init_file = 0;
 1049:   return (0);
 1050: }
 1051: 
 1052: static void
 1053: #if defined (PREFER_STDARG)
 1054: _rl_init_file_error (const char *format, ...)
 1055: #else
 1056: _rl_init_file_error (va_alist)
 1057:      va_dcl
 1058: #endif
 1059: {
 1060:   va_list args;
 1061: #if defined (PREFER_VARARGS)
 1062:   char *format;
 1063: #endif
 1064: 
 1065: #if defined (PREFER_STDARG)
 1066:   va_start (args, format);
 1067: #else
 1068:   va_start (args);
 1069:   format = va_arg (args, char *);
 1070: #endif
 1071: 
 1072:   fprintf (stderr, "readline: ");
 1073:   if (currently_reading_init_file)
 1074:     fprintf (stderr, "%s: line %d: ", current_readline_init_file,
 1075: 		     current_readline_init_lineno);
 1076: 
 1077:   vfprintf (stderr, format, args);
 1078:   fprintf (stderr, "\n");
 1079:   fflush (stderr);
 1080: 
 1081:   va_end (args);
 1082: }
 1083: 
 1084: /* **************************************************************** */
 1085: /*								    */
 1086: /*			Parser Helper Functions       		    */
 1087: /*								    */
 1088: /* **************************************************************** */
 1089: 
 1090: static int
 1091: parse_comparison_op (s, indp)
 1092:      const char *s;
 1093:      int *indp;
 1094: {
 1095:   int i, peekc, op;
 1096: 
 1097:   if (OPSTART (s[*indp]) == 0)
 1098:     return -1;
 1099:   i = *indp;
 1100:   peekc = s[i] ? s[i+1] : 0;
 1101:   op = -1;
 1102: 
 1103:   if (s[i] == '=')
 1104:     {
 1105:       op = OP_EQ;
 1106:       if (peekc == '=')
 1107:         i++;
 1108:       i++;
 1109:     }
 1110:   else if (s[i] == '!' && peekc == '=')
 1111:     {
 1112:       op = OP_NE;
 1113:       i += 2;
 1114:     }
 1115:   else if (s[i] == '<' && peekc == '=')
 1116:     {
 1117:       op = OP_LE;
 1118:       i += 2;
 1119:     }
 1120:   else if (s[i] == '>' && peekc == '=')
 1121:     {
 1122:       op = OP_GE;
 1123:       i += 2;
 1124:     }
 1125:   else if (s[i] == '<')
 1126:     {
 1127:       op = OP_LT;
 1128:       i += 1;
 1129:     }
 1130:   else if (s[i] == '>')
 1131:     {
 1132:       op = OP_GT;
 1133:       i += 1;
 1134:     }
 1135: 
 1136:   *indp = i;
 1137:   return op;        
 1138: }
 1139: 
 1140: /* **************************************************************** */
 1141: /*								    */
 1142: /*			Parser Directives       		    */
 1143: /*								    */
 1144: /* **************************************************************** */
 1145: 
 1146: typedef int _rl_parser_func_t PARAMS((char *));
 1147: 
 1148: /* Things that mean `Control'. */
 1149: const char * const _rl_possible_control_prefixes[] = {
 1150:   "Control-", "C-", "CTRL-", (const char *)NULL
 1151: };
 1152: 
 1153: const char * const _rl_possible_meta_prefixes[] = {
 1154:   "Meta", "M-", (const char *)NULL
 1155: };
 1156: 
 1157: /* Conditionals. */
 1158: 
 1159: /* Calling programs set this to have their argv[0]. */
 1160: const char *rl_readline_name = "other";
 1161: 
 1162: /* Stack of previous values of parsing_conditionalized_out. */
 1163: static unsigned char *if_stack = (unsigned char *)NULL;
 1164: static int if_stack_depth;
 1165: static int if_stack_size;
 1166: 
 1167: /* Push _rl_parsing_conditionalized_out, and set parser state based
 1168:    on ARGS. */
 1169: static int
 1170: parser_if (char *args)
 1171: {
 1172:   int i, llen, boolvar, strvar;
 1173: 
 1174:   boolvar = strvar = -1;
 1175: 
 1176:   /* Push parser state. */
 1177:   if (if_stack_depth + 1 >= if_stack_size)
 1178:     {
 1179:       if (!if_stack)
 1180: 	if_stack = (unsigned char *)xmalloc (if_stack_size = 20);
 1181:       else
 1182: 	if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20);
 1183:     }
 1184:   if_stack[if_stack_depth++] = _rl_parsing_conditionalized_out;
 1185: 
 1186:   /* If parsing is turned off, then nothing can turn it back on except
 1187:      for finding the matching endif.  In that case, return right now. */
 1188:   if (_rl_parsing_conditionalized_out)
 1189:     return 0;
 1190: 
 1191:   llen = strlen (args);
 1192: 
 1193:   /* Isolate first argument. */
 1194:   for (i = 0; args[i] && !whitespace (args[i]); i++);
 1195: 
 1196:   if (args[i])
 1197:     args[i++] = '\0';
 1198: 
 1199:   /* Handle "$if term=foo" and "$if mode=emacs" constructs.  If this
 1200:      isn't term=foo, or mode=emacs, then check to see if the first
 1201:      word in ARGS is the same as the value stored in rl_readline_name. */
 1202:   if (rl_terminal_name && _rl_strnicmp (args, "term=", 5) == 0)
 1203:     {
 1204:       char *tem, *tname;
 1205: 
 1206:       /* Terminals like "aaa-60" are equivalent to "aaa". */
 1207:       tname = savestring (rl_terminal_name);
 1208:       tem = strchr (tname, '-');
 1209:       if (tem)
 1210: 	*tem = '\0';
 1211: 
 1212:       /* Test the `long' and `short' forms of the terminal name so that
 1213: 	 if someone has a `sun-cmd' and does not want to have bindings
 1214: 	 that will be executed if the terminal is a `sun', they can put
 1215: 	 `$if term=sun-cmd' into their .inputrc. */
 1216:       _rl_parsing_conditionalized_out = _rl_stricmp (args + 5, tname) &&
 1217: 					_rl_stricmp (args + 5, rl_terminal_name);
 1218:       xfree (tname);
 1219:     }
 1220: #if defined (VI_MODE)
 1221:   else if (_rl_strnicmp (args, "mode=", 5) == 0)
 1222:     {
 1223:       int mode;
 1224: 
 1225:       if (_rl_stricmp (args + 5, "emacs") == 0)
 1226: 	mode = emacs_mode;
 1227:       else if (_rl_stricmp (args + 5, "vi") == 0)
 1228: 	mode = vi_mode;
 1229:       else
 1230: 	mode = no_mode;
 1231: 
 1232:       _rl_parsing_conditionalized_out = mode != rl_editing_mode;
 1233:     }
 1234: #endif /* VI_MODE */
 1235:   else if (_rl_strnicmp (args, "version", 7) == 0)
 1236:     {
 1237:       int rlversion, versionarg, op, previ, major, minor;
 1238: 
 1239:       _rl_parsing_conditionalized_out = 1;
 1240:       rlversion = RL_VERSION_MAJOR*10 + RL_VERSION_MINOR;
 1241:       /* if "version" is separated from the operator by whitespace, or the
 1242:          operand is separated from the operator by whitespace, restore it.
 1243:          We're more liberal with allowed whitespace for this variable. */
 1244:       if (i > 0 && i <= llen && args[i-1] == '\0')
 1245:         args[i-1] = ' ';
 1246:       args[llen] = '\0';		/* just in case */
 1247:       for (i = 7; whitespace (args[i]); i++)
 1248: 	;
 1249:       if (OPSTART(args[i]) == 0)
 1250: 	{
 1251: 	  _rl_init_file_error ("comparison operator expected, found `%s'", args[i] ? args + i : "end-of-line");
 1252: 	  return 0;
 1253: 	}
 1254:       previ = i;
 1255:       op = parse_comparison_op (args, &i);
 1256:       if (op <= 0)
 1257: 	{
 1258: 	  _rl_init_file_error ("comparison operator expected, found `%s'", args+previ);
 1259: 	  return 0;
 1260: 	}
 1261:       for ( ; args[i] && whitespace (args[i]); i++)
 1262: 	;
 1263:       if (args[i] == 0 || _rl_digit_p (args[i]) == 0)
 1264: 	{
 1265: 	  _rl_init_file_error ("numeric argument expected, found `%s'", args+i);
 1266: 	  return 0;
 1267: 	}
 1268:       major = minor = 0;
 1269:       previ = i;
 1270:       for ( ; args[i] && _rl_digit_p (args[i]); i++)
 1271: 	major = major*10 + _rl_digit_value (args[i]);
 1272:       if (args[i] == '.')
 1273: 	{
 1274: 	  if (args[i + 1] && _rl_digit_p (args [i + 1]) == 0)
 1275: 	    {
 1276: 	      _rl_init_file_error ("numeric argument expected, found `%s'", args+previ);
 1277: 	      return 0;
 1278: 	    }
 1279: 	  for (++i; args[i] && _rl_digit_p (args[i]); i++)
 1280: 	    minor = minor*10 + _rl_digit_value (args[i]);
 1281: 	}
 1282:       /* optional - check for trailing garbage on the line, allow whitespace
 1283: 	 and a trailing comment */
 1284:       previ = i;
 1285:       for ( ; args[i] && whitespace (args[i]); i++)
 1286: 	;
 1287:       if (args[i] && args[i] != '#')
 1288: 	{
 1289: 	  _rl_init_file_error ("trailing garbage on line: `%s'", args+previ);
 1290: 	  return 0;
 1291: 	}
 1292:       versionarg = major*10 + minor;
 1293: 
 1294:       switch (op)
 1295: 	{
 1296: 	case OP_EQ:
 1297: 	  _rl_parsing_conditionalized_out = rlversion == versionarg;
 1298: 	  break;
 1299: 	case OP_NE:
 1300: 	  _rl_parsing_conditionalized_out = rlversion != versionarg;
 1301: 	  break;
 1302: 	case OP_GT:
 1303: 	  _rl_parsing_conditionalized_out = rlversion > versionarg;
 1304: 	  break;
 1305: 	case OP_GE:
 1306: 	  _rl_parsing_conditionalized_out = rlversion >= versionarg;
 1307: 	  break;
 1308: 	case OP_LT:
 1309: 	  _rl_parsing_conditionalized_out = rlversion < versionarg;
 1310: 	  break;
 1311: 	case OP_LE:
 1312: 	  _rl_parsing_conditionalized_out = rlversion <= versionarg;
 1313: 	  break;
 1314: 	}
 1315:     }
 1316:   /* Check to see if the first word in ARGS is the same as the
 1317:      value stored in rl_readline_name. */
 1318:   else if (_rl_stricmp (args, rl_readline_name) == 0)
 1319:     _rl_parsing_conditionalized_out = 0;
 1320:   else if ((boolvar = find_boolean_var (args)) >= 0 || (strvar = find_string_var (args)) >= 0)
 1321:     {
 1322:       int op, previ;
 1323:       size_t vlen;
 1324:       const char *vname;
 1325:       char *valuearg, *vval, prevc;
 1326: 
 1327:       _rl_parsing_conditionalized_out = 1;
 1328:       vname = (boolvar >= 0) ? boolean_varname (boolvar) : string_varname (strvar);
 1329:       vlen = strlen (vname);
 1330:       if (i > 0 && i <= llen && args[i-1] == '\0')
 1331:         args[i-1] = ' ';
 1332:       args[llen] = '\0';		/* just in case */
 1333:       for (i = vlen; whitespace (args[i]); i++)
 1334: 	;
 1335:       if (CMPSTART(args[i]) == 0)
 1336: 	{
 1337: 	  _rl_init_file_error ("equality comparison operator expected, found `%s'", args[i] ? args + i : "end-of-line");
 1338: 	  return 0;
 1339: 	}
 1340:       previ = i;
 1341:       op = parse_comparison_op (args, &i);
 1342:       if (op != OP_EQ && op != OP_NE)
 1343: 	{
 1344: 	  _rl_init_file_error ("equality comparison operator expected, found `%s'", args+previ);
 1345: 	  return 0;
 1346: 	}
 1347:       for ( ; args[i] && whitespace (args[i]); i++)
 1348: 	;
 1349:       if (args[i] == 0)
 1350: 	{
 1351: 	  _rl_init_file_error ("argument expected, found `%s'", args+i);
 1352: 	  return 0;
 1353: 	}
 1354:       previ = i;
 1355:       valuearg = args + i;
 1356:       for ( ; args[i] && whitespace (args[i]) == 0; i++)
 1357: 	;
 1358:       prevc = args[i];
 1359:       args[i] = '\0';		/* null-terminate valuearg */
 1360:       vval = rl_variable_value (vname);
 1361:       if (op == OP_EQ)
 1362:         _rl_parsing_conditionalized_out = _rl_stricmp (vval, valuearg) != 0;
 1363:       else if (op == OP_NE)
 1364:         _rl_parsing_conditionalized_out = _rl_stricmp (vval, valuearg) == 0;
 1365:       args[i] = prevc;
 1366:     }
 1367:   else
 1368:     _rl_parsing_conditionalized_out = 1;
 1369:   return 0;
 1370: }
 1371: 
 1372: /* Invert the current parser state if there is anything on the stack. */
 1373: static int
 1374: parser_else (char *args)
 1375: {
 1376:   register int i;
 1377: 
 1378:   if (if_stack_depth == 0)
 1379:     {
 1380:       _rl_init_file_error ("$else found without matching $if");
 1381:       return 0;
 1382:     }
 1383: 
 1384: #if 0
 1385:   /* Check the previous (n - 1) levels of the stack to make sure that
 1386:      we haven't previously turned off parsing. */
 1387:   for (i = 0; i < if_stack_depth - 1; i++)
 1388: #else
 1389:   /* Check the previous (n) levels of the stack to make sure that
 1390:      we haven't previously turned off parsing. */
 1391:   for (i = 0; i < if_stack_depth; i++)
 1392: #endif
 1393:     if (if_stack[i] == 1)
 1394:       return 0;
 1395: 
 1396:   /* Invert the state of parsing if at top level. */
 1397:   _rl_parsing_conditionalized_out = !_rl_parsing_conditionalized_out;
 1398:   return 0;
 1399: }
 1400: 
 1401: /* Terminate a conditional, popping the value of
 1402:    _rl_parsing_conditionalized_out from the stack. */
 1403: static int
 1404: parser_endif (char *args)
 1405: {
 1406:   if (if_stack_depth)
 1407:     _rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
 1408:   else
 1409:     _rl_init_file_error ("$endif without matching $if");
 1410:   return 0;
 1411: }
 1412: 
 1413: static int
 1414: parser_include (char *args)
 1415: {
 1416:   const char *old_init_file;
 1417:   char *e;
 1418:   int old_line_number, old_include_level, r;
 1419: 
 1420:   if (_rl_parsing_conditionalized_out)
 1421:     return (0);
 1422: 
 1423:   old_init_file = current_readline_init_file;
 1424:   old_line_number = current_readline_init_lineno;
 1425:   old_include_level = current_readline_init_include_level;
 1426: 
 1427:   e = strchr (args, '\n');
 1428:   if (e)
 1429:     *e = '\0';
 1430:   r = _rl_read_init_file ((const char *)args, old_include_level + 1);
 1431: 
 1432:   current_readline_init_file = old_init_file;
 1433:   current_readline_init_lineno = old_line_number;
 1434:   current_readline_init_include_level = old_include_level;
 1435: 
 1436:   return r;
 1437: }
 1438:   
 1439: /* Associate textual names with actual functions. */
 1440: static const struct {
 1441:   const char * const name;
 1442:   _rl_parser_func_t *function;
 1443: } parser_directives [] = {
 1444:   { "if", parser_if },
 1445:   { "endif", parser_endif },
 1446:   { "else", parser_else },
 1447:   { "include", parser_include },
 1448:   { (char *)0x0, (_rl_parser_func_t *)0x0 }
 1449: };
 1450: 
 1451: /* Handle a parser directive.  STATEMENT is the line of the directive
 1452:    without any leading `$'. */
 1453: static int
 1454: handle_parser_directive (char *statement)
 1455: {
 1456:   register int i;
 1457:   char *directive, *args;
 1458: 
 1459:   /* Isolate the actual directive. */
 1460: 
 1461:   /* Skip whitespace. */
 1462:   for (i = 0; whitespace (statement[i]); i++);
 1463: 
 1464:   directive = &statement[i];
 1465: 
 1466:   for (; statement[i] && !whitespace (statement[i]); i++);
 1467: 
 1468:   if (statement[i])
 1469:     statement[i++] = '\0';
 1470: 
 1471:   for (; statement[i] && whitespace (statement[i]); i++);
 1472: 
 1473:   args = &statement[i];
 1474: 
 1475:   /* Lookup the command, and act on it. */
 1476:   for (i = 0; parser_directives[i].name; i++)
 1477:     if (_rl_stricmp (directive, parser_directives[i].name) == 0)
 1478:       {
 1479: 	(*parser_directives[i].function) (args);
 1480: 	return (0);
 1481:       }
 1482: 
 1483:   /* display an error message about the unknown parser directive */
 1484:   _rl_init_file_error ("%s: unknown parser directive", directive);
 1485:   return (1);
 1486: }
 1487: 
 1488: /* Start at STRING[START] and look for DELIM.  Return I where STRING[I] ==
 1489:    DELIM or STRING[I] == 0.  DELIM is usually a double quote. */
 1490: static int
 1491: _rl_skip_to_delim (char *string, int start, int delim)
 1492: {
 1493:   int i, c, passc;
 1494: 
 1495:   for (i = start,passc = 0; c = string[i]; i++)
 1496:     {
 1497:       if (passc)
 1498: 	{
 1499: 	  passc = 0;
 1500: 	  if (c == 0)
 1501: 	    break;
 1502: 	  continue;
 1503: 	}
 1504: 
 1505:       if (c == '\\')
 1506: 	{
 1507: 	  passc = 1;
 1508: 	  continue;
 1509: 	}
 1510: 
 1511:       if (c == delim)
 1512: 	break;
 1513:     }
 1514: 
 1515:   return i;
 1516: }
 1517: 
 1518: /* Read the binding command from STRING and perform it.
 1519:    A key binding command looks like: Keyname: function-name\0,
 1520:    a variable binding command looks like: set variable value.
 1521:    A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */
 1522: int
 1523: rl_parse_and_bind (char *string)
 1524: {
 1525:   char *funname, *kname;
 1526:   register int c, i;
 1527:   int key, equivalency, foundmod, foundsep;
 1528: 
 1529:   while (string && whitespace (*string))
 1530:     string++;
 1531: 
 1532:   if (string == 0 || *string == 0 || *string == '#')
 1533:     return 0;
 1534: 
 1535:   /* If this is a parser directive, act on it. */
 1536:   if (*string == '$')
 1537:     {
 1538:       handle_parser_directive (&string[1]);
 1539:       return 0;
 1540:     }
 1541: 
 1542:   /* If we aren't supposed to be parsing right now, then we're done. */
 1543:   if (_rl_parsing_conditionalized_out)
 1544:     return 0;
 1545: 
 1546:   i = 0;
 1547:   /* If this keyname is a complex key expression surrounded by quotes,
 1548:      advance to after the matching close quote.  This code allows the
 1549:      backslash to quote characters in the key expression. */
 1550:   if (*string == '"')
 1551:     {
 1552:       i = _rl_skip_to_delim (string, 1, '"');
 1553: 
 1554:       /* If we didn't find a closing quote, abort the line. */
 1555:       if (string[i] == '\0')
 1556:         {
 1557:           _rl_init_file_error ("%s: no closing `\"' in key binding", string);
 1558:           return 1;
 1559:         }
 1560:       else
 1561:         i++;	/* skip past closing double quote */
 1562:     }
 1563: 
 1564:   /* Advance to the colon (:) or whitespace which separates the two objects. */
 1565:   for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
 1566: 
 1567:   if (i == 0)
 1568:     {
 1569:       _rl_init_file_error ("`%s': invalid key binding: missing key sequence", string);
 1570:       return 1;
 1571:     }
 1572: 
 1573:   equivalency = (c == ':' && string[i + 1] == '=');
 1574: 
 1575:   foundsep = c != 0;
 1576: 
 1577:   /* Mark the end of the command (or keyname). */
 1578:   if (string[i])
 1579:     string[i++] = '\0';
 1580: 
 1581:   /* If doing assignment, skip the '=' sign as well. */
 1582:   if (equivalency)
 1583:     string[i++] = '\0';
 1584: 
 1585:   /* If this is a command to set a variable, then do that. */
 1586:   if (_rl_stricmp (string, "set") == 0)
 1587:     {
 1588:       char *var, *value, *e;
 1589:       int s;
 1590: 
 1591:       var = string + i;
 1592:       /* Make VAR point to start of variable name. */
 1593:       while (*var && whitespace (*var)) var++;
 1594: 
 1595:       /* Make VALUE point to start of value string. */
 1596:       value = var;
 1597:       while (*value && whitespace (*value) == 0) value++;
 1598:       if (*value)
 1599: 	*value++ = '\0';
 1600:       while (*value && whitespace (*value)) value++;
 1601: 
 1602:       /* Strip trailing whitespace from values of boolean variables. */
 1603:       if (find_boolean_var (var) >= 0)
 1604: 	{
 1605: 	  /* just read a whitespace-delimited word or empty string */
 1606: 	  for (e = value; *e && whitespace (*e) == 0; e++)
 1607: 	    ;
 1608: 	  if (e > value)
 1609: 	    *e = '\0';		/* cut off everything trailing */
 1610: 	}
 1611:       else if ((i = find_string_var (var)) >= 0)
 1612: 	{
 1613: 	  /* Allow quoted strings in variable values */
 1614: 	  if (*value == '"')
 1615: 	    {
 1616: 	      i = _rl_skip_to_delim (value, 1, *value);
 1617: 	      value[i] = '\0';
 1618: 	      value++;	/* skip past the quote */
 1619: 	    }
 1620: 	  else
 1621: 	    {
 1622: 	      /* remove trailing whitespace */
 1623: 	      e = value + strlen (value) - 1;
 1624: 	      while (e >= value && whitespace (*e))
 1625: 		e--;
 1626: 	      e++;		/* skip back to whitespace or EOS */
 1627: 	  
 1628: 	      if (*e && e >= value)
 1629: 		*e = '\0';
 1630: 	    }
 1631: 	}
 1632:       else
 1633: 	{
 1634: 	  /* avoid calling rl_variable_bind just to find this out */
 1635: 	  _rl_init_file_error ("%s: unknown variable name", var);
 1636: 	  return 1;
 1637: 	}
 1638: 
 1639:       rl_variable_bind (var, value);
 1640:       return 0;
 1641:     }
 1642: 
 1643:   /* Skip any whitespace between keyname and funname. */
 1644:   for (; string[i] && whitespace (string[i]); i++);
 1645:   funname = &string[i];
 1646: 
 1647:   /* Now isolate funname.
 1648:      For straight function names just look for whitespace, since
 1649:      that will signify the end of the string.  But this could be a
 1650:      macro definition.  In that case, the string is quoted, so skip
 1651:      to the matching delimiter.  We allow the backslash to quote the
 1652:      delimiter characters in the macro body. */
 1653:   /* This code exists to allow whitespace in macro expansions, which
 1654:      would otherwise be gobbled up by the next `for' loop.*/
 1655:   /* XXX - it may be desirable to allow backslash quoting only if " is
 1656:      the quoted string delimiter, like the shell. */
 1657:   if (*funname == '\'' || *funname == '"')
 1658:     {
 1659:       i = _rl_skip_to_delim (string, i+1, *funname);
 1660:       if (string[i])
 1661: 	i++;
 1662:       else
 1663: 	{
 1664: 	  _rl_init_file_error ("`%s': missing closing quote for macro", funname);
 1665: 	  return 1;
 1666: 	}
 1667:     }
 1668: 
 1669:   /* Advance to the end of the string.  */
 1670:   for (; string[i] && whitespace (string[i]) == 0; i++);
 1671: 
 1672:   /* No extra whitespace at the end of the string. */
 1673:   string[i] = '\0';
 1674: 
 1675:   /* Handle equivalency bindings here.  Make the left-hand side be exactly
 1676:      whatever the right-hand evaluates to, including keymaps. */
 1677:   if (equivalency)
 1678:     {
 1679:       return 0;
 1680:     }
 1681: 
 1682:   if (foundsep == 0)
 1683:     {
 1684:       _rl_init_file_error ("%s: no key sequence terminator", string);
 1685:       return 1;
 1686:     }
 1687: 
 1688:   /* If this is a new-style key-binding, then do the binding with
 1689:      rl_bind_keyseq ().  Otherwise, let the older code deal with it. */
 1690:   if (*string == '"')
 1691:     {
 1692:       char *seq;
 1693:       register int j, k, passc;
 1694: 
 1695:       seq = (char *)xmalloc (1 + strlen (string));
 1696:       for (j = 1, k = passc = 0; string[j]; j++)
 1697: 	{
 1698: 	  /* Allow backslash to quote characters, but leave them in place.
 1699: 	     This allows a string to end with a backslash quoting another
 1700: 	     backslash, or with a backslash quoting a double quote.  The
 1701: 	     backslashes are left in place for rl_translate_keyseq (). */
 1702: 	  if (passc || (string[j] == '\\'))
 1703: 	    {
 1704: 	      seq[k++] = string[j];
 1705: 	      passc = !passc;
 1706: 	      continue;
 1707: 	    }
 1708: 
 1709: 	  if (string[j] == '"')
 1710: 	    break;
 1711: 
 1712: 	  seq[k++] = string[j];
 1713: 	}
 1714:       seq[k] = '\0';
 1715: 
 1716:       /* Binding macro? */
 1717:       if (*funname == '\'' || *funname == '"')
 1718: 	{
 1719: 	  j = strlen (funname);
 1720: 
 1721: 	  /* Remove the delimiting quotes from each end of FUNNAME. */
 1722: 	  if (j && funname[j - 1] == *funname)
 1723: 	    funname[j - 1] = '\0';
 1724: 
 1725: 	  rl_macro_bind (seq, &funname[1], _rl_keymap);
 1726: 	}
 1727:       else
 1728: 	rl_bind_keyseq (seq, rl_named_function (funname));
 1729: 
 1730:       xfree (seq);
 1731:       return 0;
 1732:     }
 1733: 
 1734:   /* Get the actual character we want to deal with. */
 1735:   kname = strrchr (string, '-');
 1736:   if (kname == 0)
 1737:     kname = string;
 1738:   else
 1739:     kname++;
 1740: 
 1741:   key = glean_key_from_name (kname);
 1742: 
 1743:   /* Add in control and meta bits. */
 1744:   foundmod = 0;
 1745:   if (substring_member_of_array (string, _rl_possible_control_prefixes))
 1746:     {
 1747:       key = CTRL (_rl_to_upper (key));
 1748:       foundmod = 1;
 1749:     }
 1750: 
 1751:   if (substring_member_of_array (string, _rl_possible_meta_prefixes))
 1752:     {
 1753:       key = META (key);
 1754:       foundmod = 1;
 1755:     }
 1756: 
 1757:   if (foundmod == 0 && kname != string)
 1758:     {
 1759:       _rl_init_file_error ("%s: unknown key modifier", string);
 1760:       return 1;
 1761:     }
 1762: 
 1763:   /* Temporary.  Handle old-style keyname with macro-binding. */
 1764:   if (*funname == '\'' || *funname == '"')
 1765:     {
 1766:       char useq[2];
 1767:       int fl = strlen (funname);
 1768: 
 1769:       useq[0] = key; useq[1] = '\0';
 1770:       if (fl && funname[fl - 1] == *funname)
 1771: 	funname[fl - 1] = '\0';
 1772: 
 1773:       rl_macro_bind (useq, &funname[1], _rl_keymap);
 1774:     }
 1775: #if defined (PREFIX_META_HACK)
 1776:   /* Ugly, but working hack to keep prefix-meta around. */
 1777:   else if (_rl_stricmp (funname, "prefix-meta") == 0)
 1778:     {
 1779:       char seq[2];
 1780: 
 1781:       seq[0] = key;
 1782:       seq[1] = '\0';
 1783:       rl_generic_bind (ISKMAP, seq, (char *)emacs_meta_keymap, _rl_keymap);
 1784:     }
 1785: #endif /* PREFIX_META_HACK */
 1786:   else
 1787:     rl_bind_key (key, rl_named_function (funname));
 1788: 
 1789:   return 0;
 1790: }
 1791: 
 1792: /* Simple structure for boolean readline variables (i.e., those that can
 1793:    have one of two values; either "On" or 1 for truth, or "Off" or 0 for
 1794:    false. */
 1795: 
 1796: #define V_SPECIAL	0x1
 1797: 
 1798: static const struct {
 1799:   const char * const name;
 1800:   int *value;
 1801:   int flags;
 1802: } boolean_varlist [] = {
 1803:   { "bind-tty-special-chars",	&_rl_bind_stty_chars,		0 },
 1804:   { "blink-matching-paren",	&rl_blink_matching_paren,	V_SPECIAL },
 1805:   { "byte-oriented",		&rl_byte_oriented,		0 },
 1806: #if defined (COLOR_SUPPORT)
 1807:   { "colored-completion-prefix",&_rl_colored_completion_prefix,	0 },
 1808:   { "colored-stats",		&_rl_colored_stats,		0 },
 1809: #endif
 1810:   { "completion-ignore-case",	&_rl_completion_case_fold,	0 },
 1811:   { "completion-map-case",	&_rl_completion_case_map,	0 },
 1812:   { "convert-meta",		&_rl_convert_meta_chars_to_ascii, 0 },
 1813:   { "disable-completion",	&rl_inhibit_completion,		0 },
 1814:   { "echo-control-characters",	&_rl_echo_control_chars,	0 },
 1815:   { "enable-bracketed-paste",	&_rl_enable_bracketed_paste,	V_SPECIAL },
 1816:   { "enable-keypad",		&_rl_enable_keypad,		0 },
 1817:   { "enable-meta-key",		&_rl_enable_meta,		0 },
 1818:   { "expand-tilde",		&rl_complete_with_tilde_expansion, 0 },
 1819:   { "history-preserve-point",	&_rl_history_preserve_point,	0 },
 1820:   { "horizontal-scroll-mode",	&_rl_horizontal_scroll_mode,	0 },
 1821:   { "input-meta",		&_rl_meta_flag,			0 },
 1822:   { "mark-directories",		&_rl_complete_mark_directories,	0 },
 1823:   { "mark-modified-lines",	&_rl_mark_modified_lines,	0 },
 1824:   { "mark-symlinked-directories", &_rl_complete_mark_symlink_dirs, 0 },
 1825:   { "match-hidden-files",	&_rl_match_hidden_files,	0 },
 1826:   { "menu-complete-display-prefix", &_rl_menu_complete_prefix_first, 0 },
 1827:   { "meta-flag",		&_rl_meta_flag,			0 },
 1828:   { "output-meta",		&_rl_output_meta_chars,		0 },
 1829:   { "page-completions",		&_rl_page_completions,		0 },
 1830:   { "prefer-visible-bell",	&_rl_prefer_visible_bell,	V_SPECIAL },
 1831:   { "print-completions-horizontally", &_rl_print_completions_horizontally, 0 },
 1832:   { "revert-all-at-newline",	&_rl_revert_all_at_newline,	0 },
 1833:   { "show-all-if-ambiguous",	&_rl_complete_show_all,		0 },
 1834:   { "show-all-if-unmodified",	&_rl_complete_show_unmodified,	0 },
 1835:   { "show-mode-in-prompt",	&_rl_show_mode_in_prompt,	0 },
 1836:   { "skip-completed-text",	&_rl_skip_completed_text,	0 },
 1837: #if defined (VISIBLE_STATS)
 1838:   { "visible-stats",		&rl_visible_stats,		0 },
 1839: #endif /* VISIBLE_STATS */
 1840:   { (char *)NULL, (int *)NULL, 0 }
 1841: };
 1842: 
 1843: static int
 1844: find_boolean_var (const char *name)
 1845: {
 1846:   register int i;
 1847: 
 1848:   for (i = 0; boolean_varlist[i].name; i++)
 1849:     if (_rl_stricmp (name, boolean_varlist[i].name) == 0)
 1850:       return i;
 1851:   return -1;
 1852: }
 1853: 
 1854: static const char *
 1855: boolean_varname (int i)
 1856: {
 1857:   return ((i >= 0) ? boolean_varlist[i].name : (char *)NULL);
 1858: }  
 1859: 
 1860: /* Hooks for handling special boolean variables, where a
 1861:    function needs to be called or another variable needs
 1862:    to be changed when they're changed. */
 1863: static void
 1864: hack_special_boolean_var (int i)
 1865: {
 1866:   const char *name;
 1867: 
 1868:   name = boolean_varlist[i].name;
 1869: 
 1870:   if (_rl_stricmp (name, "blink-matching-paren") == 0)
 1871:     _rl_enable_paren_matching (rl_blink_matching_paren);
 1872:   else if (_rl_stricmp (name, "prefer-visible-bell") == 0)
 1873:     {
 1874:       if (_rl_prefer_visible_bell)
 1875: 	_rl_bell_preference = VISIBLE_BELL;
 1876:       else
 1877: 	_rl_bell_preference = AUDIBLE_BELL;
 1878:     }
 1879:   else if (_rl_stricmp (name, "show-mode-in-prompt") == 0)
 1880:     _rl_reset_prompt ();
 1881:   else if (_rl_stricmp (name, "enable-bracketed-paste") == 0)
 1882:     _rl_enable_active_region = _rl_enable_bracketed_paste;
 1883: }
 1884: 
 1885: typedef int _rl_sv_func_t PARAMS((const char *));
 1886: 
 1887: /* These *must* correspond to the array indices for the appropriate
 1888:    string variable.  (Though they're not used right now.) */
 1889: #define V_BELLSTYLE	0
 1890: #define V_COMBEGIN	1
 1891: #define V_EDITMODE	2
 1892: #define V_ISRCHTERM	3
 1893: #define V_KEYMAP	4
 1894: 
 1895: #define	V_STRING	1
 1896: #define V_INT		2
 1897: 
 1898: /* Forward declarations */
 1899: static int sv_bell_style PARAMS((const char *));
 1900: static int sv_combegin PARAMS((const char *));
 1901: static int sv_dispprefix PARAMS((const char *));
 1902: static int sv_compquery PARAMS((const char *));
 1903: static int sv_compwidth PARAMS((const char *));
 1904: static int sv_editmode PARAMS((const char *));
 1905: static int sv_emacs_modestr PARAMS((const char *));
 1906: static int sv_histsize PARAMS((const char *));
 1907: static int sv_isrchterm PARAMS((const char *));
 1908: static int sv_keymap PARAMS((const char *));
 1909: static int sv_seqtimeout PARAMS((const char *));
 1910: static int sv_viins_modestr PARAMS((const char *));
 1911: static int sv_vicmd_modestr PARAMS((const char *));
 1912: 
 1913: static const struct {
 1914:   const char * const name;
 1915:   int flags;
 1916:   _rl_sv_func_t *set_func;
 1917: } string_varlist[] = {
 1918:   { "bell-style",	V_STRING,	sv_bell_style },
 1919:   { "comment-begin",	V_STRING,	sv_combegin },
 1920:   { "completion-display-width", V_INT,	sv_compwidth },
 1921:   { "completion-prefix-display-length", V_INT,	sv_dispprefix },
 1922:   { "completion-query-items", V_INT,	sv_compquery },
 1923:   { "editing-mode",	V_STRING,	sv_editmode },
 1924:   { "emacs-mode-string", V_STRING,	sv_emacs_modestr },  
 1925:   { "history-size",	V_INT,		sv_histsize },
 1926:   { "isearch-terminators", V_STRING,	sv_isrchterm },
 1927:   { "keymap",		V_STRING,	sv_keymap },
 1928:   { "keyseq-timeout",	V_INT,		sv_seqtimeout },
 1929:   { "vi-cmd-mode-string", V_STRING,	sv_vicmd_modestr }, 
 1930:   { "vi-ins-mode-string", V_STRING,	sv_viins_modestr }, 
 1931:   { (char *)NULL,	0, (_rl_sv_func_t *)0 }
 1932: };
 1933: 
 1934: static int
 1935: find_string_var (const char *name)
 1936: {
 1937:   register int i;
 1938: 
 1939:   for (i = 0; string_varlist[i].name; i++)
 1940:     if (_rl_stricmp (name, string_varlist[i].name) == 0)
 1941:       return i;
 1942:   return -1;
 1943: }
 1944: 
 1945: static const char *
 1946: string_varname (int i)
 1947: {
 1948:   return ((i >= 0) ? string_varlist[i].name : (char *)NULL);
 1949: }  
 1950: 
 1951: /* A boolean value that can appear in a `set variable' command is true if
 1952:    the value is null or empty, `on' (case-insensitive), or "1".  All other
 1953:    values result in 0 (false). */
 1954: static int
 1955: bool_to_int (const char *value)
 1956: {
 1957:   return (value == 0 || *value == '\0' ||
 1958: 		(_rl_stricmp (value, "on") == 0) ||
 1959: 		(value[0] == '1' && value[1] == '\0'));
 1960: }
 1961: 
 1962: char *
 1963: rl_variable_value (const char *name)
 1964: {
 1965:   register int i;
 1966: 
 1967:   /* Check for simple variables first. */
 1968:   i = find_boolean_var (name);
 1969:   if (i >= 0)
 1970:     return (*boolean_varlist[i].value ? "on" : "off");
 1971: 
 1972:   i = find_string_var (name);
 1973:   if (i >= 0)
 1974:     return (_rl_get_string_variable_value (string_varlist[i].name));
 1975: 
 1976:   /* Unknown variable names return NULL. */
 1977:   return (char *)NULL;
 1978: }
 1979: 
 1980: int
 1981: rl_variable_bind (const char *name, const char *value)
 1982: {
 1983:   register int i;
 1984:   int	v;
 1985: 
 1986:   /* Check for simple variables first. */
 1987:   i = find_boolean_var (name);
 1988:   if (i >= 0)
 1989:     {
 1990:       *boolean_varlist[i].value = bool_to_int (value);
 1991:       if (boolean_varlist[i].flags & V_SPECIAL)
 1992: 	hack_special_boolean_var (i);
 1993:       return 0;
 1994:     }
 1995: 
 1996:   i = find_string_var (name);
 1997: 
 1998:   /* For the time being, string names without a handler function are simply
 1999:      ignored. */
 2000:   if (i < 0 || string_varlist[i].set_func == 0)
 2001:     {
 2002:       if (i < 0)
 2003: 	_rl_init_file_error ("%s: unknown variable name", name);
 2004:       return 0;
 2005:     }
 2006: 
 2007:   v = (*string_varlist[i].set_func) (value);
 2008:   if (v != 0)
 2009:     _rl_init_file_error ("%s: could not set value to `%s'", name, value);
 2010:   return v;
 2011: }
 2012: 
 2013: static int
 2014: sv_editmode (const char *value)
 2015: {
 2016:   if (_rl_strnicmp (value, "vi", 2) == 0)
 2017:     {
 2018: #if defined (VI_MODE)
 2019:       _rl_keymap = vi_insertion_keymap;
 2020:       rl_editing_mode = vi_mode;
 2021: #endif /* VI_MODE */
 2022:       return 0;
 2023:     }
 2024:   else if (_rl_strnicmp (value, "emacs", 5) == 0)
 2025:     {
 2026:       _rl_keymap = emacs_standard_keymap;
 2027:       rl_editing_mode = emacs_mode;
 2028:       return 0;
 2029:     }
 2030:   return 1;
 2031: }
 2032: 
 2033: static int
 2034: sv_combegin (const char *value)
 2035: {
 2036:   if (value && *value)
 2037:     {
 2038:       FREE (_rl_comment_begin);
 2039:       _rl_comment_begin = savestring (value);
 2040:       return 0;
 2041:     }
 2042:   return 1;
 2043: }
 2044: 
 2045: static int
 2046: sv_dispprefix (const char *value)
 2047: {
 2048:   int nval = 0;
 2049: 
 2050:   if (value && *value)
 2051:     {
 2052:       nval = atoi (value);
 2053:       if (nval < 0)
 2054: 	nval = 0;
 2055:     }
 2056:   _rl_completion_prefix_display_length = nval;
 2057:   return 0;
 2058: }
 2059: 
 2060: static int
 2061: sv_compquery (const char *value)
 2062: {
 2063:   int nval = 100;
 2064: 
 2065:   if (value && *value)
 2066:     {
 2067:       nval = atoi (value);
 2068:       if (nval < 0)
 2069: 	nval = 0;
 2070:     }
 2071:   rl_completion_query_items = nval;
 2072:   return 0;
 2073: }
 2074: 
 2075: static int
 2076: sv_compwidth (const char *value)
 2077: {
 2078:   int nval = -1;
 2079: 
 2080:   if (value && *value)
 2081:     nval = atoi (value);
 2082: 
 2083:   _rl_completion_columns = nval;
 2084:   return 0;
 2085: }
 2086: 
 2087: static int
 2088: sv_histsize (const char *value)
 2089: {
 2090:   int nval;
 2091: 
 2092:   nval = 500;
 2093:   if (value && *value)
 2094:     {
 2095:       nval = atoi (value);
 2096:       if (nval < 0)
 2097: 	{
 2098: 	  unstifle_history ();
 2099: 	  return 0;
 2100: 	}
 2101:     }
 2102:   stifle_history (nval);
 2103:   return 0;
 2104: }
 2105: 
 2106: static int
 2107: sv_keymap (const char *value)
 2108: {
 2109:   Keymap kmap;
 2110: 
 2111:   kmap = rl_get_keymap_by_name (value);
 2112:   if (kmap)
 2113:     {
 2114:       rl_set_keymap (kmap);
 2115:       return 0;
 2116:     }
 2117:   return 1;
 2118: }
 2119: 
 2120: static int
 2121: sv_seqtimeout (const char *value)
 2122: {
 2123:   int nval;
 2124: 
 2125:   nval = 0;
 2126:   if (value && *value)
 2127:     {
 2128:       nval = atoi (value);
 2129:       if (nval < 0)
 2130: 	nval = 0;
 2131:     }
 2132:   _rl_keyseq_timeout = nval;
 2133:   return 0;
 2134: }
 2135: 
 2136: static int
 2137: sv_bell_style (const char *value)
 2138: {
 2139:   if (value == 0 || *value == '\0')
 2140:     _rl_bell_preference = AUDIBLE_BELL;
 2141:   else if (_rl_stricmp (value, "none") == 0 || _rl_stricmp (value, "off") == 0)
 2142:     _rl_bell_preference = NO_BELL;
 2143:   else if (_rl_stricmp (value, "audible") == 0 || _rl_stricmp (value, "on") == 0)
 2144:     _rl_bell_preference = AUDIBLE_BELL;
 2145:   else if (_rl_stricmp (value, "visible") == 0)
 2146:     _rl_bell_preference = VISIBLE_BELL;
 2147:   else
 2148:     return 1;
 2149:   return 0;
 2150: }
 2151: 
 2152: static int
 2153: sv_isrchterm (const char *value)
 2154: {
 2155:   int beg, end, delim;
 2156:   char *v;
 2157: 
 2158:   if (value == 0)
 2159:     return 1;
 2160: 
 2161:   /* Isolate the value and translate it into a character string. */
 2162:   v = savestring (value);
 2163:   FREE (_rl_isearch_terminators);
 2164:   if (v[0] == '"' || v[0] == '\'')
 2165:     {
 2166:       delim = v[0];
 2167:       for (beg = end = 1; v[end] && v[end] != delim; end++)
 2168: 	;
 2169:     }
 2170:   else
 2171:     {
 2172:       for (beg = end = 0; v[end] && whitespace (v[end]) == 0; end++)
 2173: 	;
 2174:     }
 2175: 
 2176:   v[end] = '\0';
 2177: 
 2178:   /* The value starts at v + beg.  Translate it into a character string. */
 2179:   _rl_isearch_terminators = (char *)xmalloc (2 * strlen (v) + 1);
 2180:   rl_translate_keyseq (v + beg, _rl_isearch_terminators, &end);
 2181:   _rl_isearch_terminators[end] = '\0';
 2182: 
 2183:   xfree (v);
 2184:   return 0;
 2185: }
 2186: 
 2187: extern char *_rl_emacs_mode_str;
 2188: 
 2189: static int
 2190: sv_emacs_modestr (const char *value)
 2191: {
 2192:   if (value && *value)
 2193:     {
 2194:       FREE (_rl_emacs_mode_str);
 2195:       _rl_emacs_mode_str = (char *)xmalloc (2 * strlen (value) + 1);
 2196:       rl_translate_keyseq (value, _rl_emacs_mode_str, &_rl_emacs_modestr_len);
 2197:       _rl_emacs_mode_str[_rl_emacs_modestr_len] = '\0';
 2198:       return 0;
 2199:     }
 2200:   else if (value)
 2201:     {
 2202:       FREE (_rl_emacs_mode_str);
 2203:       _rl_emacs_mode_str = (char *)xmalloc (1);
 2204:       _rl_emacs_mode_str[_rl_emacs_modestr_len = 0] = '\0';
 2205:       return 0;
 2206:     }
 2207:   else if (value == 0)
 2208:     {
 2209:       FREE (_rl_emacs_mode_str);
 2210:       _rl_emacs_mode_str = 0;	/* prompt_modestr does the right thing */
 2211:       _rl_emacs_modestr_len = 0;
 2212:       return 0;
 2213:     }
 2214:   return 1;
 2215: }
 2216: 
 2217: static int
 2218: sv_viins_modestr (const char *value)
 2219: {
 2220:   if (value && *value)
 2221:     {
 2222:       FREE (_rl_vi_ins_mode_str);
 2223:       _rl_vi_ins_mode_str = (char *)xmalloc (2 * strlen (value) + 1);
 2224:       rl_translate_keyseq (value, _rl_vi_ins_mode_str, &_rl_vi_ins_modestr_len);
 2225:       _rl_vi_ins_mode_str[_rl_vi_ins_modestr_len] = '\0';
 2226:       return 0;
 2227:     }
 2228:   else if (value)
 2229:     {
 2230:       FREE (_rl_vi_ins_mode_str);
 2231:       _rl_vi_ins_mode_str = (char *)xmalloc (1);
 2232:       _rl_vi_ins_mode_str[_rl_vi_ins_modestr_len = 0] = '\0';
 2233:       return 0;
 2234:     }
 2235:   else if (value == 0)
 2236:     {
 2237:       FREE (_rl_vi_ins_mode_str);
 2238:       _rl_vi_ins_mode_str = 0;	/* prompt_modestr does the right thing */
 2239:       _rl_vi_ins_modestr_len = 0;
 2240:       return 0;
 2241:     }
 2242:   return 1;
 2243: }
 2244: 
 2245: static int
 2246: sv_vicmd_modestr (const char *value)
 2247: {
 2248:   if (value && *value)
 2249:     {
 2250:       FREE (_rl_vi_cmd_mode_str);
 2251:       _rl_vi_cmd_mode_str = (char *)xmalloc (2 * strlen (value) + 1);
 2252:       rl_translate_keyseq (value, _rl_vi_cmd_mode_str, &_rl_vi_cmd_modestr_len);
 2253:       _rl_vi_cmd_mode_str[_rl_vi_cmd_modestr_len] = '\0';
 2254:       return 0;
 2255:     }
 2256:   else if (value)
 2257:     {
 2258:       FREE (_rl_vi_cmd_mode_str);
 2259:       _rl_vi_cmd_mode_str = (char *)xmalloc (1);
 2260:       _rl_vi_cmd_mode_str[_rl_vi_cmd_modestr_len = 0] = '\0';
 2261:       return 0;
 2262:     }
 2263:   else if (value == 0)
 2264:     {
 2265:       FREE (_rl_vi_cmd_mode_str);
 2266:       _rl_vi_cmd_mode_str = 0;	/* prompt_modestr does the right thing */
 2267:       _rl_vi_cmd_modestr_len = 0;
 2268:       return 0;
 2269:     }
 2270:   return 1;
 2271: }
 2272: 
 2273: /* Return the character which matches NAME.
 2274:    For example, `Space' returns ' '. */
 2275: 
 2276: typedef struct {
 2277:   const char * const name;
 2278:   int value;
 2279: } assoc_list;
 2280: 
 2281: static const assoc_list name_key_alist[] = {
 2282:   { "DEL", 0x7f },
 2283:   { "ESC", '\033' },
 2284:   { "Escape", '\033' },
 2285:   { "LFD", '\n' },
 2286:   { "Newline", '\n' },
 2287:   { "RET", '\r' },
 2288:   { "Return", '\r' },
 2289:   { "Rubout", 0x7f },
 2290:   { "SPC", ' ' },
 2291:   { "Space", ' ' },
 2292:   { "Tab", 0x09 },
 2293:   { (char *)0x0, 0 }
 2294: };
 2295: 
 2296: static int
 2297: glean_key_from_name (char *name)
 2298: {
 2299:   register int i;
 2300: 
 2301:   for (i = 0; name_key_alist[i].name; i++)
 2302:     if (_rl_stricmp (name, name_key_alist[i].name) == 0)
 2303:       return (name_key_alist[i].value);
 2304: 
 2305:   return (*(unsigned char *)name);	/* XXX was return (*name) */
 2306: }
 2307: 
 2308: /* Auxiliary functions to manage keymaps. */
 2309: struct name_and_keymap {
 2310:   char *name;
 2311:   Keymap map;
 2312: };
 2313: 
 2314: static struct name_and_keymap builtin_keymap_names[] = {
 2315:   { "emacs", emacs_standard_keymap },
 2316:   { "emacs-standard", emacs_standard_keymap },
 2317:   { "emacs-meta", emacs_meta_keymap },
 2318:   { "emacs-ctlx", emacs_ctlx_keymap },
 2319: #if defined (VI_MODE)
 2320:   { "vi", vi_movement_keymap },
 2321:   { "vi-move", vi_movement_keymap },
 2322:   { "vi-command", vi_movement_keymap },
 2323:   { "vi-insert", vi_insertion_keymap },
 2324: #endif /* VI_MODE */
 2325:   { (char *)0x0, (Keymap)0x0 }
 2326: };
 2327: 
 2328: /* -1 for NULL entry */
 2329: #define NUM_BUILTIN_KEYMAPS (sizeof (builtin_keymap_names) / sizeof (builtin_keymap_names[0]) - 1)
 2330: 
 2331: static struct name_and_keymap *keymap_names = builtin_keymap_names;
 2332: 
 2333: static int
 2334: _rl_get_keymap_by_name (const char *name)
 2335: {
 2336:   register int i;
 2337: 
 2338:   for (i = 0; keymap_names[i].name; i++)
 2339:     if (_rl_stricmp (name, keymap_names[i].name) == 0)
 2340:       return (i);
 2341:   return -1;
 2342: }
 2343: 
 2344: Keymap
 2345: rl_get_keymap_by_name (const char *name)
 2346: {
 2347:   int i;
 2348: 
 2349:   i = _rl_get_keymap_by_name (name);
 2350:   return ((i >= 0) ? keymap_names[i].map : (Keymap) NULL);
 2351: }
 2352: 
 2353: static int
 2354: _rl_get_keymap_by_map (Keymap map)
 2355: {
 2356:   register int i;
 2357: 
 2358:   for (i = 0; keymap_names[i].name; i++)
 2359:     if (map == keymap_names[i].map)
 2360:       return (i);
 2361:   return -1;
 2362: }
 2363: 
 2364: char *
 2365: rl_get_keymap_name (Keymap map)
 2366: {
 2367:   int i;
 2368: 
 2369:   i = _rl_get_keymap_by_map (map);
 2370:   return ((i >= 0) ? keymap_names[i].name : (char *)NULL);
 2371: }
 2372: 
 2373: int
 2374: rl_set_keymap_name (const char *name, Keymap map)
 2375: {
 2376:   int i, ni, mi;
 2377: 
 2378:   /* First check whether or not we're trying to rename a builtin keymap */
 2379:   mi = _rl_get_keymap_by_map (map);
 2380:   if (mi >= 0 && mi < NUM_BUILTIN_KEYMAPS)
 2381:     return -1;
 2382: 
 2383:   /* Then reject attempts to set one of the builtin names to a new map */
 2384:   ni = _rl_get_keymap_by_name (name);
 2385:   if (ni >= 0 && ni < NUM_BUILTIN_KEYMAPS)
 2386:     return -1;
 2387: 
 2388:   /* Renaming a keymap we already added */
 2389:   if (mi >= 0)	/* XXX - could be >= NUM_BUILTIN_KEYMAPS */
 2390:     {
 2391:       xfree (keymap_names[mi].name);
 2392:       keymap_names[mi].name = savestring (name);
 2393:       return mi;
 2394:     }
 2395: 
 2396:   /* Associating new keymap with existing name */
 2397:   if (ni >= 0)
 2398:     {
 2399:       keymap_names[ni].map = map;
 2400:       return ni;
 2401:     }
 2402: 
 2403:   for (i = 0; keymap_names[i].name; i++)
 2404:     ;
 2405: 
 2406:   if (keymap_names == builtin_keymap_names)
 2407:     {
 2408:       keymap_names = xmalloc ((i + 2) * sizeof (struct name_and_keymap));
 2409:       memcpy (keymap_names, builtin_keymap_names, i * sizeof (struct name_and_keymap));
 2410:     }
 2411:   else
 2412:     keymap_names = xrealloc (keymap_names, (i + 2) * sizeof (struct name_and_keymap));
 2413: 
 2414:   keymap_names[i].name = savestring (name);
 2415:   keymap_names[i].map = map;
 2416: 
 2417:   keymap_names[i+1].name = NULL;
 2418:   keymap_names[i+1].map = NULL;
 2419: 
 2420:   return i;
 2421: }
 2422: 
 2423: void
 2424: rl_set_keymap (Keymap map)
 2425: {
 2426:   if (map)
 2427:     _rl_keymap = map;
 2428: }
 2429: 
 2430: Keymap
 2431: rl_get_keymap (void)
 2432: {
 2433:   return (_rl_keymap);
 2434: }
 2435: 
 2436: void
 2437: rl_set_keymap_from_edit_mode (void)
 2438: {
 2439:   if (rl_editing_mode == emacs_mode)
 2440:     _rl_keymap = emacs_standard_keymap;
 2441: #if defined (VI_MODE)
 2442:   else if (rl_editing_mode == vi_mode)
 2443:     _rl_keymap = vi_insertion_keymap;
 2444: #endif /* VI_MODE */
 2445: }
 2446: 
 2447: char *
 2448: rl_get_keymap_name_from_edit_mode (void)
 2449: {
 2450:   if (rl_editing_mode == emacs_mode)
 2451:     return "emacs";
 2452: #if defined (VI_MODE)
 2453:   else if (rl_editing_mode == vi_mode)
 2454:     return "vi";
 2455: #endif /* VI_MODE */
 2456:   else
 2457:     return "none";
 2458: }
 2459: 
 2460: /* **************************************************************** */
 2461: /*								    */
 2462: /*		  Key Binding and Function Information		    */
 2463: /*								    */
 2464: /* **************************************************************** */
 2465: 
 2466: /* Each of the following functions produces information about the
 2467:    state of keybindings and functions known to Readline.  The info
 2468:    is always printed to rl_outstream, and in such a way that it can
 2469:    be read back in (i.e., passed to rl_parse_and_bind ()). */
 2470: 
 2471: /* Print the names of functions known to Readline. */
 2472: void
 2473: rl_list_funmap_names (void)
 2474: {
 2475:   register int i;
 2476:   const char **funmap_names;
 2477: 
 2478:   funmap_names = rl_funmap_names ();
 2479: 
 2480:   if (!funmap_names)
 2481:     return;
 2482: 
 2483:   for (i = 0; funmap_names[i]; i++)
 2484:     fprintf (rl_outstream, "%s\n", funmap_names[i]);
 2485: 
 2486:   xfree (funmap_names);
 2487: }
 2488: 
 2489: static char *
 2490: _rl_get_keyname (int key)
 2491: {
 2492:   char *keyname;
 2493:   int i, c;
 2494: 
 2495:   keyname = (char *)xmalloc (8);
 2496: 
 2497:   c = key;
 2498:   /* Since this is going to be used to write out keysequence-function
 2499:      pairs for possible inclusion in an inputrc file, we don't want to
 2500:      do any special meta processing on KEY. */
 2501: 
 2502: #if 1
 2503:   /* XXX - Experimental */
 2504:   /* We might want to do this, but the old version of the code did not. */
 2505: 
 2506:   /* If this is an escape character, we don't want to do any more processing.
 2507:      Just add the special ESC key sequence and return. */
 2508:   if (c == ESC)
 2509:     {
 2510:       keyname[0] = '\\';
 2511:       keyname[1] = 'e';
 2512:       keyname[2] = '\0';
 2513:       return keyname;
 2514:     }
 2515: #endif
 2516: 
 2517:   /* RUBOUT is translated directly into \C-? */
 2518:   if (key == RUBOUT)
 2519:     {
 2520:       keyname[0] = '\\';
 2521:       keyname[1] = 'C';
 2522:       keyname[2] = '-';
 2523:       keyname[3] = '?';
 2524:       keyname[4] = '\0';
 2525:       return keyname;
 2526:     }
 2527: 
 2528:   i = 0;
 2529:   /* Now add special prefixes needed for control characters.  This can
 2530:      potentially change C. */
 2531:   if (CTRL_CHAR (c))
 2532:     {
 2533:       keyname[i++] = '\\';
 2534:       keyname[i++] = 'C';
 2535:       keyname[i++] = '-';
 2536:       c = _rl_to_lower (UNCTRL (c));
 2537:     }
 2538: 
 2539:   /* XXX experimental code.  Turn the characters that are not ASCII or
 2540:      ISO Latin 1 (128 - 159) into octal escape sequences (\200 - \237).
 2541:      This changes C. */
 2542:   if (c >= 128 && c <= 159)
 2543:     {
 2544:       keyname[i++] = '\\';
 2545:       keyname[i++] = '2';
 2546:       c -= 128;
 2547:       keyname[i++] = (c / 8) + '0';
 2548:       c = (c % 8) + '0';
 2549:     }
 2550: 
 2551:   /* Now, if the character needs to be quoted with a backslash, do that. */
 2552:   if (c == '\\' || c == '"')
 2553:     keyname[i++] = '\\';
 2554: 
 2555:   /* Now add the key, terminate the string, and return it. */
 2556:   keyname[i++] = (char) c;
 2557:   keyname[i] = '\0';
 2558: 
 2559:   return keyname;
 2560: }
 2561: 
 2562: /* Return a NULL terminated array of strings which represent the key
 2563:    sequences that are used to invoke FUNCTION in MAP. */
 2564: char **
 2565: rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map)
 2566: {
 2567:   register int key;
 2568:   char **result;
 2569:   int result_index, result_size;
 2570: 
 2571:   result = (char **)NULL;
 2572:   result_index = result_size = 0;
 2573: 
 2574:   for (key = 0; key < KEYMAP_SIZE; key++)
 2575:     {
 2576:       switch (map[key].type)
 2577: 	{
 2578: 	case ISMACR:
 2579: 	  /* Macros match, if, and only if, the pointers are identical.
 2580: 	     Thus, they are treated exactly like functions in here. */
 2581: 	case ISFUNC:
 2582: 	  /* If the function in the keymap is the one we are looking for,
 2583: 	     then add the current KEY to the list of invoking keys. */
 2584: 	  if (map[key].function == function)
 2585: 	    {
 2586: 	      char *keyname;
 2587: 
 2588: 	      keyname = _rl_get_keyname (key);
 2589: 
 2590: 	      if (result_index + 2 > result_size)
 2591: 	        {
 2592: 	          result_size += 10;
 2593: 		  result = (char **)xrealloc (result, result_size * sizeof (char *));
 2594: 	        }
 2595: 
 2596: 	      result[result_index++] = keyname;
 2597: 	      result[result_index] = (char *)NULL;
 2598: 	    }
 2599: 	  break;
 2600: 
 2601: 	case ISKMAP:
 2602: 	  {
 2603: 	    char **seqs;
 2604: 	    register int i;
 2605: 
 2606: 	    /* Find the list of keyseqs in this map which have FUNCTION as
 2607: 	       their target.  Add the key sequences found to RESULT. */
 2608: 	    if (map[key].function)
 2609: 	      seqs =
 2610: 	        rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
 2611: 	    else
 2612: 	      break;
 2613: 
 2614: 	    if (seqs == 0)
 2615: 	      break;
 2616: 
 2617: 	    for (i = 0; seqs[i]; i++)
 2618: 	      {
 2619: 		char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
 2620: 
 2621: 		if (key == ESC)
 2622: 		  {
 2623: 		    /* If ESC is the meta prefix and we're converting chars
 2624: 		       with the eighth bit set to ESC-prefixed sequences, then
 2625: 		       we can use \M-.  Otherwise we need to use the sequence
 2626: 		       for ESC. */
 2627: 		    if (_rl_convert_meta_chars_to_ascii && map[ESC].type == ISKMAP)
 2628: 		      sprintf (keyname, "\\M-");
 2629: 		    else
 2630: 		      sprintf (keyname, "\\e");
 2631: 		  }
 2632: 		else
 2633: 		  {
 2634: 		    int c = key, l = 0;
 2635: 		    if (CTRL_CHAR (c) || c == RUBOUT)
 2636: 		      {
 2637: 			keyname[l++] = '\\';
 2638: 			keyname[l++] = 'C';
 2639: 			keyname[l++] = '-';
 2640: 			c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c));
 2641: 		      }
 2642: 
 2643: 		    if (c == '\\' || c == '"')
 2644: 		      keyname[l++] = '\\';
 2645: 
 2646: 		    keyname[l++] = (char) c;
 2647: 		    keyname[l++] = '\0';
 2648: 		  }
 2649: 		
 2650: 		strcat (keyname, seqs[i]);
 2651: 		xfree (seqs[i]);
 2652: 
 2653: 		if (result_index + 2 > result_size)
 2654: 		  {
 2655: 		    result_size += 10;
 2656: 		    result = (char **)xrealloc (result, result_size * sizeof (char *));
 2657: 		  }
 2658: 
 2659: 		result[result_index++] = keyname;
 2660: 		result[result_index] = (char *)NULL;
 2661: 	      }
 2662: 
 2663: 	    xfree (seqs);
 2664: 	  }
 2665: 	  break;
 2666: 	}
 2667:     }
 2668:   return (result);
 2669: }
 2670: 
 2671: /* Return a NULL terminated array of strings which represent the key
 2672:    sequences that can be used to invoke FUNCTION using the current keymap. */
 2673: char **
 2674: rl_invoking_keyseqs (rl_command_func_t *function)
 2675: {
 2676:   return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
 2677: }
 2678: 
 2679: /* Print all of the functions and their bindings to rl_outstream.  If
 2680:    PRINT_READABLY is non-zero, then print the output in such a way
 2681:    that it can be read back in. */
 2682: void
 2683: rl_function_dumper (int print_readably)
 2684: {
 2685:   register int i;
 2686:   const char **names;
 2687:   const char *name;
 2688: 
 2689:   names = rl_funmap_names ();
 2690: 
 2691:   fprintf (rl_outstream, "\n");
 2692: 
 2693:   for (i = 0; name = names[i]; i++)
 2694:     {
 2695:       rl_command_func_t *function;
 2696:       char **invokers;
 2697: 
 2698:       function = rl_named_function (name);
 2699:       invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap);
 2700: 
 2701:       if (print_readably)
 2702: 	{
 2703: 	  if (!invokers)
 2704: 	    fprintf (rl_outstream, "# %s (not bound)\n", name);
 2705: 	  else
 2706: 	    {
 2707: 	      register int j;
 2708: 
 2709: 	      for (j = 0; invokers[j]; j++)
 2710: 		{
 2711: 		  fprintf (rl_outstream, "\"%s\": %s\n",
 2712: 			   invokers[j], name);
 2713: 		  xfree (invokers[j]);
 2714: 		}
 2715: 
 2716: 	      xfree (invokers);
 2717: 	    }
 2718: 	}
 2719:       else
 2720: 	{
 2721: 	  if (!invokers)
 2722: 	    fprintf (rl_outstream, "%s is not bound to any keys\n",
 2723: 		     name);
 2724: 	  else
 2725: 	    {
 2726: 	      register int j;
 2727: 
 2728: 	      fprintf (rl_outstream, "%s can be found on ", name);
 2729: 
 2730: 	      for (j = 0; invokers[j] && j < 5; j++)
 2731: 		{
 2732: 		  fprintf (rl_outstream, "\"%s\"%s", invokers[j],
 2733: 			   invokers[j + 1] ? ", " : ".\n");
 2734: 		}
 2735: 
 2736: 	      if (j == 5 && invokers[j])
 2737: 		fprintf (rl_outstream, "...\n");
 2738: 
 2739: 	      for (j = 0; invokers[j]; j++)
 2740: 		xfree (invokers[j]);
 2741: 
 2742: 	      xfree (invokers);
 2743: 	    }
 2744: 	}
 2745:     }
 2746: 
 2747:   xfree (names);
 2748: }
 2749: 
 2750: /* Print all of the current functions and their bindings to
 2751:    rl_outstream.  If an explicit argument is given, then print
 2752:    the output in such a way that it can be read back in. */
 2753: int
 2754: rl_dump_functions (int count, int key)
 2755: {
 2756:   if (rl_dispatching)
 2757:     fprintf (rl_outstream, "\r\n");
 2758:   rl_function_dumper (rl_explicit_arg);
 2759:   rl_on_new_line ();
 2760:   return (0);
 2761: }
 2762: 
 2763: static void
 2764: _rl_macro_dumper_internal (int print_readably, Keymap map, char *prefix)
 2765: {
 2766:   register int key;
 2767:   char *keyname, *out;
 2768:   int prefix_len;
 2769: 
 2770:   for (key = 0; key < KEYMAP_SIZE; key++)
 2771:     {
 2772:       switch (map[key].type)
 2773: 	{
 2774: 	case ISMACR:
 2775: 	  keyname = _rl_get_keyname (key);
 2776: 	  out = _rl_untranslate_macro_value ((char *)map[key].function, 0);
 2777: 
 2778: 	  if (print_readably)
 2779: 	    fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
 2780: 						         keyname,
 2781: 						         out ? out : "");
 2782: 	  else
 2783: 	    fprintf (rl_outstream, "%s%s outputs %s\n", prefix ? prefix : "",
 2784: 							keyname,
 2785: 							out ? out : "");
 2786: 	  xfree (keyname);
 2787: 	  xfree (out);
 2788: 	  break;
 2789: 	case ISFUNC:
 2790: 	  break;
 2791: 	case ISKMAP:
 2792: 	  prefix_len = prefix ? strlen (prefix) : 0;
 2793: 	  if (key == ESC)
 2794: 	    {
 2795: 	      keyname = (char *)xmalloc (3 + prefix_len);
 2796: 	      if (prefix)
 2797: 		strcpy (keyname, prefix);
 2798: 	      keyname[prefix_len] = '\\';
 2799: 	      keyname[prefix_len + 1] = 'e';
 2800: 	      keyname[prefix_len + 2] = '\0';
 2801: 	    }
 2802: 	  else
 2803: 	    {
 2804: 	      keyname = _rl_get_keyname (key);
 2805: 	      if (prefix)
 2806: 		{
 2807: 		  out = (char *)xmalloc (strlen (keyname) + prefix_len + 1);
 2808: 		  strcpy (out, prefix);
 2809: 		  strcpy (out + prefix_len, keyname);
 2810: 		  xfree (keyname);
 2811: 		  keyname = out;
 2812: 		}
 2813: 	    }
 2814: 
 2815: 	  _rl_macro_dumper_internal (print_readably, FUNCTION_TO_KEYMAP (map, key), keyname);
 2816: 	  xfree (keyname);
 2817: 	  break;
 2818: 	}
 2819:     }
 2820: }
 2821: 
 2822: void
 2823: rl_macro_dumper (int print_readably)
 2824: {
 2825:   _rl_macro_dumper_internal (print_readably, _rl_keymap, (char *)NULL);
 2826: }
 2827: 
 2828: int
 2829: rl_dump_macros (int count, int key)
 2830: {
 2831:   if (rl_dispatching)
 2832:     fprintf (rl_outstream, "\r\n");
 2833:   rl_macro_dumper (rl_explicit_arg);
 2834:   rl_on_new_line ();
 2835:   return (0);
 2836: }
 2837: 
 2838: static char *
 2839: _rl_get_string_variable_value (const char *name)
 2840: {
 2841:   static char numbuf[32];
 2842:   char *ret;
 2843: 
 2844:   if (_rl_stricmp (name, "bell-style") == 0)
 2845:     {
 2846:       switch (_rl_bell_preference)
 2847: 	{
 2848: 	  case NO_BELL:
 2849: 	    return "none";
 2850: 	  case VISIBLE_BELL:
 2851: 	    return "visible";
 2852: 	  case AUDIBLE_BELL:
 2853: 	  default:
 2854: 	    return "audible";
 2855: 	}
 2856:     }
 2857:   else if (_rl_stricmp (name, "comment-begin") == 0)
 2858:     return (_rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
 2859:   else if (_rl_stricmp (name, "completion-display-width") == 0)
 2860:     {
 2861:       sprintf (numbuf, "%d", _rl_completion_columns);
 2862:       return (numbuf);
 2863:     }
 2864:   else if (_rl_stricmp (name, "completion-prefix-display-length") == 0)
 2865:     {
 2866:       sprintf (numbuf, "%d", _rl_completion_prefix_display_length);
 2867:       return (numbuf);
 2868:     }
 2869:   else if (_rl_stricmp (name, "completion-query-items") == 0)
 2870:     {
 2871:       sprintf (numbuf, "%d", rl_completion_query_items);
 2872:       return (numbuf);
 2873:     }
 2874:   else if (_rl_stricmp (name, "editing-mode") == 0)
 2875:     return (rl_get_keymap_name_from_edit_mode ());
 2876:   else if (_rl_stricmp (name, "history-size") == 0)
 2877:     {
 2878:       sprintf (numbuf, "%d", history_is_stifled() ? history_max_entries : 0);
 2879:       return (numbuf);
 2880:     }
 2881:   else if (_rl_stricmp (name, "isearch-terminators") == 0)
 2882:     {
 2883:       if (_rl_isearch_terminators == 0)
 2884: 	return 0;
 2885:       ret = _rl_untranslate_macro_value (_rl_isearch_terminators, 0);
 2886:       if (ret)
 2887: 	{
 2888: 	  strncpy (numbuf, ret, sizeof (numbuf) - 1);
 2889: 	  xfree (ret);
 2890: 	  numbuf[sizeof(numbuf) - 1] = '\0';
 2891: 	}
 2892:       else
 2893: 	numbuf[0] = '\0';
 2894:       return numbuf;
 2895:     }
 2896:   else if (_rl_stricmp (name, "keymap") == 0)
 2897:     {
 2898:       ret = rl_get_keymap_name (_rl_keymap);
 2899:       if (ret == 0)
 2900: 	ret = rl_get_keymap_name_from_edit_mode ();
 2901:       return (ret ? ret : "none");
 2902:     }
 2903:   else if (_rl_stricmp (name, "keyseq-timeout") == 0)
 2904:     {
 2905:       sprintf (numbuf, "%d", _rl_keyseq_timeout);    
 2906:       return (numbuf);
 2907:     }
 2908:   else if (_rl_stricmp (name, "emacs-mode-string") == 0)
 2909:     return (_rl_emacs_mode_str ? _rl_emacs_mode_str : RL_EMACS_MODESTR_DEFAULT);
 2910:   else if (_rl_stricmp (name, "vi-cmd-mode-string") == 0)
 2911:     return (_rl_vi_cmd_mode_str ? _rl_vi_cmd_mode_str : RL_VI_CMD_MODESTR_DEFAULT);
 2912:   else if (_rl_stricmp (name, "vi-ins-mode-string") == 0)
 2913:     return (_rl_vi_ins_mode_str ? _rl_vi_ins_mode_str : RL_VI_INS_MODESTR_DEFAULT);
 2914:   else
 2915:     return (0);
 2916: }
 2917: 
 2918: void
 2919: rl_variable_dumper (int print_readably)
 2920: {
 2921:   int i;
 2922:   char *v;
 2923: 
 2924:   for (i = 0; boolean_varlist[i].name; i++)
 2925:     {
 2926:       if (print_readably)
 2927:         fprintf (rl_outstream, "set %s %s\n", boolean_varlist[i].name,
 2928: 			       *boolean_varlist[i].value ? "on" : "off");
 2929:       else
 2930:         fprintf (rl_outstream, "%s is set to `%s'\n", boolean_varlist[i].name,
 2931: 			       *boolean_varlist[i].value ? "on" : "off");
 2932:     }
 2933: 
 2934:   for (i = 0; string_varlist[i].name; i++)
 2935:     {
 2936:       v = _rl_get_string_variable_value (string_varlist[i].name);
 2937:       if (v == 0)	/* _rl_isearch_terminators can be NULL */
 2938: 	continue;
 2939:       if (print_readably)
 2940:         fprintf (rl_outstream, "set %s %s\n", string_varlist[i].name, v);
 2941:       else
 2942:         fprintf (rl_outstream, "%s is set to `%s'\n", string_varlist[i].name, v);
 2943:     }
 2944: }
 2945: 
 2946: /* Print all of the current variables and their values to
 2947:    rl_outstream.  If an explicit argument is given, then print
 2948:    the output in such a way that it can be read back in. */
 2949: int
 2950: rl_dump_variables (int count, int key)
 2951: {
 2952:   if (rl_dispatching)
 2953:     fprintf (rl_outstream, "\r\n");
 2954:   rl_variable_dumper (rl_explicit_arg);
 2955:   rl_on_new_line ();
 2956:   return (0);
 2957: }
 2958: 
 2959: /* Return non-zero if any members of ARRAY are a substring in STRING. */
 2960: static int
 2961: substring_member_of_array (const char *string, const char * const *array)
 2962: {
 2963:   while (*array)
 2964:     {
 2965:       if (_rl_strindex (string, *array))
 2966: 	return (1);
 2967:       array++;
 2968:     }
 2969:   return (0);
 2970: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>