Annotation of embedaddon/readline/bind.c, revision 1.1.1.2

1.1       misho       1: /* bind.c -- key binding and startup file support for the readline library. */
                      2: 
1.1.1.2 ! misho       3: /* Copyright (C) 1987-2020 Free Software Foundation, Inc.
1.1       misho       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: 
1.1.1.2 ! misho      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: 
1.1       misho      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: 
1.1.1.2 ! misho      92: static const char *boolean_varname PARAMS((int));
        !            93: static const char *string_varname PARAMS((int));
        !            94: 
1.1       misho      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: 
1.1.1.2 ! misho      98: static int _rl_get_keymap_by_name PARAMS((const char *));
        !            99: static int _rl_get_keymap_by_map PARAMS((Keymap));
        !           100: 
1.1       misho     101: static int currently_reading_init_file;
                    102: 
                    103: /* used only in this file */
                    104: static int _rl_prefer_visible_bell = 1;
                    105: 
1.1.1.2 ! misho     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: 
1.1       misho     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
1.1.1.2 ! misho     126: rl_add_defun (const char *name, rl_command_func_t *function, int key)
1.1       misho     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
1.1.1.2 ! misho     136: rl_bind_key (int key, rl_command_func_t *function)
1.1       misho     137: {
1.1.1.2 ! misho     138:   char keyseq[4];
        !           139:   int l;
        !           140: 
        !           141:   if (key < 0 || key > largest_char)
1.1       misho     142:     return (key);
                    143: 
1.1.1.2 ! misho     144:   /* Want to make this a multi-character key sequence with an ESC prefix */
1.1       misho     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: 
1.1.1.2 ! misho     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:     }
1.1       misho     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
1.1.1.2 ! misho     204: rl_bind_key_in_map (int key, rl_command_func_t *function, Keymap map)
1.1       misho     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
1.1.1.2 ! misho     217:    now, this is always used to attempt to bind the arrow keys. */
1.1       misho     218: int
1.1.1.2 ! misho     219: rl_bind_key_if_unbound_in_map (int key, rl_command_func_t *default_func, Keymap kmap)
1.1       misho     220: {
1.1.1.2 ! misho     221:   char *keyseq;
1.1       misho     222: 
1.1.1.2 ! misho     223:   keyseq = rl_untranslate_keyseq ((unsigned char)key);
1.1       misho     224:   return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap));
                    225: }
                    226: 
                    227: int
1.1.1.2 ! misho     228: rl_bind_key_if_unbound (int key, rl_command_func_t *default_func)
1.1       misho     229: {
1.1.1.2 ! misho     230:   char *keyseq;
1.1       misho     231: 
1.1.1.2 ! misho     232:   keyseq = rl_untranslate_keyseq ((unsigned char)key);
1.1       misho     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.
1.1.1.2 ! misho     237:    Returns non-zero in case of error.  This is not the same as self-insert;
        !           238:    this makes it a dead key. */
1.1       misho     239: int
1.1.1.2 ! misho     240: rl_unbind_key (int key)
1.1       misho     241: {
                    242:   return (rl_bind_key (key, (rl_command_func_t *)NULL));
                    243: }
                    244: 
1.1.1.2 ! misho     245: /* Make KEY do nothing in MAP. Returns non-zero in case of error. */
1.1       misho     246: int
1.1.1.2 ! misho     247: rl_unbind_key_in_map (int key, Keymap map)
1.1       misho     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
1.1.1.2 ! misho     254: rl_unbind_function_in_map (rl_command_func_t *func, Keymap map)
1.1       misho     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:        }
1.1.1.2 ! misho     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:        }
1.1       misho     272:     }
                    273:   return rval;
                    274: }
                    275: 
1.1.1.2 ! misho     276: /* Unbind all keys bound to COMMAND, which is a bindable command name, in MAP */
1.1       misho     277: int
1.1.1.2 ! misho     278: rl_unbind_command_in_map (const char *command, Keymap map)
1.1       misho     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
1.1.1.2 ! misho     292: rl_bind_keyseq (const char *keyseq, rl_command_func_t *function)
1.1       misho     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
1.1.1.2 ! misho     301: rl_bind_keyseq_in_map (const char *keyseq, rl_command_func_t *function, Keymap map)
1.1       misho     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
1.1.1.2 ! misho     308: rl_set_key (const char *keyseq, rl_command_func_t *function, Keymap map)
1.1       misho     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
1.1.1.2 ! misho     317: rl_bind_keyseq_if_unbound_in_map (const char *keyseq, rl_command_func_t *default_func, Keymap kmap)
1.1       misho     318: {
                    319:   rl_command_func_t *func;
1.1.1.2 ! misho     320:   char *keys;
        !           321:   int keys_len;
1.1       misho     322: 
                    323:   if (keyseq)
                    324:     {
1.1.1.2 ! misho     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);
1.1       misho     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
1.1.1.2 ! misho     348: rl_bind_keyseq_if_unbound (const char *keyseq, rl_command_func_t *default_func)
1.1       misho     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
1.1.1.2 ! misho     357: rl_macro_bind (const char *keyseq, const char *macro, Keymap map)
1.1       misho     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
1.1.1.2 ! misho     379: rl_generic_bind (int type, const char *keyseq, char *data, Keymap map)
1.1       misho     380: {
                    381:   char *keys;
1.1.1.2 ! misho     382:   int keys_len, prevkey, ic;
1.1       misho     383:   register int i;
                    384:   KEYMAP_ENTRY k;
1.1.1.2 ! misho     385:   Keymap prevmap;  
1.1       misho     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: 
1.1.1.2 ! misho     408:   prevmap = map;
        !           409:   prevkey = keys[0];
        !           410: 
1.1       misho     411:   /* Bind keys, making new keymaps as necessary. */
                    412:   for (i = 0; i < keys_len; i++)
                    413:     {
                    414:       unsigned char uc = keys[i];
1.1.1.2 ! misho     415: 
        !           416:       if (i > 0)
        !           417:        prevkey = ic;
1.1       misho     418: 
                    419:       ic = uc;
                    420:       if (ic < 0 || ic >= KEYMAP_SIZE)
                    421:         {
                    422:           xfree (keys);
                    423:          return -1;
                    424:         }
                    425: 
1.1.1.2 ! misho     426:       /* We now rely on rl_translate_keyseq to do this conversion, so this
        !           427:         check is superfluous. */
        !           428: #if 0
1.1       misho     429:       if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
                    430:        {
                    431:          ic = UNMETA (ic);
                    432:          if (map[ESC].type == ISKMAP)
1.1.1.2 ! misho     433:            {
        !           434:              prevmap = map;
        !           435:              map = FUNCTION_TO_KEYMAP (map, ESC);
        !           436:            }
1.1       misho     437:        }
1.1.1.2 ! misho     438: #endif
1.1       misho     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:            }
1.1.1.2 ! misho     456:          prevmap = map;
1.1       misho     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:        {
1.1.1.2 ! misho     472:          if (map[ic].type == ISKMAP)
1.1       misho     473:            {
1.1.1.2 ! misho     474:              prevmap = map;
1.1       misho     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:            }
1.1.1.2 ! misho     485:          if (map[ic].type == ISMACR)
        !           486:            xfree ((char *)map[ic].function);
1.1       misho     487: 
                    488:          map[ic].function = KEYMAP_TO_FUNCTION (data);
                    489:          map[ic].type = type;
                    490:        }
                    491: 
                    492:       rl_binding_keymap = map;
1.1.1.2 ! misho     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;
1.1       misho     513:     }
1.1.1.2 ! misho     514: 
1.1       misho     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
1.1.1.2 ! misho     523: rl_translate_keyseq (const char *seq, char *array, int *len)
1.1       misho     524: {
1.1.1.2 ! misho     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')
1.1       misho     543:        {
                    544:          c = seq[++i];
                    545: 
                    546:          /* Handle \C- and \M- prefixes. */
1.1.1.2 ! misho     547:          if (c == 'C' && seq[i + 1] == '-')
1.1       misho     548:            {
1.1.1.2 ! misho     549:              i++;
        !           550:              has_control = 1;
        !           551:              continue;
        !           552:            }
        !           553:          else if (c == 'M' && seq[i + 1] == '-')
        !           554:            {
        !           555:              i++;
        !           556:              has_meta = 1;
1.1       misho     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':
1.1.1.2 ! misho     567:              c = '\007';
1.1       misho     568:              break;
                    569:            case 'b':
1.1.1.2 ! misho     570:              c = '\b';
1.1       misho     571:              break;
                    572:            case 'd':
1.1.1.2 ! misho     573:              c = RUBOUT;       /* readline-specific */
1.1       misho     574:              break;
                    575:            case 'e':
1.1.1.2 ! misho     576:              c = ESC;
1.1       misho     577:              break;
                    578:            case 'f':
1.1.1.2 ! misho     579:              c = '\f';
1.1       misho     580:              break;
                    581:            case 'n':
1.1.1.2 ! misho     582:              c = NEWLINE;
1.1       misho     583:              break;
                    584:            case 'r':
1.1.1.2 ! misho     585:              c = RETURN;
1.1       misho     586:              break;
                    587:            case 't':
1.1.1.2 ! misho     588:              c = TAB;
1.1       misho     589:              break;
                    590:            case 'v':
1.1.1.2 ! misho     591:              c = 0x0B;
1.1       misho     592:              break;
                    593:            case '\\':
1.1.1.2 ! misho     594:              c = '\\';
1.1       misho     595:              break;
                    596:            case '0': case '1': case '2': case '3':
                    597:            case '4': case '5': case '6': case '7':
                    598:              i++;
1.1.1.2 ! misho     599:              for (temp = 2, c -= '0'; ISOCTAL ((unsigned char)seq[i]) && temp--; i++)
1.1       misho     600:                c = (c * 8) + OCTVALUE (seq[i]);
                    601:              i--;      /* auto-increment in for loop */
1.1.1.2 ! misho     602:              c &= largest_char;
1.1       misho     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 */
1.1.1.2 ! misho     611:              c &= largest_char;
1.1       misho     612:              break;
                    613:            default:    /* backslashes before non-special chars just add the char */
1.1.1.2 ! misho     614:              c &= largest_char;
1.1       misho     615:              break;    /* the backslash is stripped */
                    616:            }
                    617:        }
                    618: 
1.1.1.2 ! misho     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;
1.1       misho     645:     }
                    646: 
                    647:   *len = l;
                    648:   array[l] = '\0';
                    649:   return (0);
                    650: }
                    651: 
                    652: static int
1.1.1.2 ! misho     653: _rl_isescape (int c)
1.1       misho     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
1.1.1.2 ! misho     669: _rl_escchar (int c)
1.1       misho     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 *
1.1.1.2 ! misho     685: rl_untranslate_keyseq (int seq)
1.1       misho     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 *
1.1.1.2 ! misho     735: _rl_untranslate_macro_value (char *seq, int use_escapes)
1.1       misho     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
1.1.1.2 ! misho     792:    is returned. The string match is case-insensitive. */
1.1       misho     793: rl_command_func_t *
1.1.1.2 ! misho     794: rl_named_function (const char *string)
1.1       misho     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). */
1.1.1.2 ! misho     811: static rl_command_func_t *
        !           812: _rl_function_of_keyseq_internal (const char *keyseq, size_t len, Keymap map, int *type)
1.1       misho     813: {
                    814:   register int i;
                    815: 
                    816:   if (map == 0)
                    817:     map = _rl_keymap;
                    818: 
1.1.1.2 ! misho     819:   for (i = 0; keyseq && i < len; i++)
1.1       misho     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. */
1.1.1.2 ! misho     845:          if (i + 1 == len)
1.1       misho     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. */
1.1.1.2 ! misho     858:       else if (map[ic].type != ISKMAP && i+1 < len)
1.1       misho     859:        return ((rl_command_func_t *)NULL);
1.1.1.2 ! misho     860:       else     /* map[ic].type != ISKMAP && i+1 == len */
1.1       misho     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: 
1.1.1.2 ! misho     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: 
1.1       misho     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 *
1.1.1.2 ! misho     895: _rl_read_file (char *filename, size_t *sizep)
1.1       misho     896: {
                    897:   struct stat finfo;
                    898:   size_t file_size;
                    899:   char *buffer;
                    900:   int i, file;
                    901: 
1.1.1.2 ! misho     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:     }
1.1       misho     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
1.1.1.2 ! misho     945: rl_re_read_init_file (int count, int ignore)
1.1       misho     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
1.1.1.2 ! misho     962: rl_read_init_file (const char *filename)
1.1       misho     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
1.1.1.2 ! misho     987: _rl_read_init_file (const char *filename, int include_level)
1.1       misho     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
1.1.1.2 ! misho    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
1.1       misho    1059: {
1.1.1.2 ! misho    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: ");
1.1       misho    1073:   if (currently_reading_init_file)
1.1.1.2 ! misho    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;        
1.1       misho    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
1.1.1.2 ! misho    1170: parser_if (char *args)
1.1       misho    1171: {
1.1.1.2 ! misho    1172:   int i, llen, boolvar, strvar;
        !          1173: 
        !          1174:   boolvar = strvar = -1;
1.1       misho    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: 
1.1.1.2 ! misho    1191:   llen = strlen (args);
        !          1192: 
1.1       misho    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 */
1.1.1.2 ! misho    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:     }
1.1       misho    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;
1.1.1.2 ! misho    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:     }
1.1       misho    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
1.1.1.2 ! misho    1374: parser_else (char *args)
1.1       misho    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
1.1.1.2 ! misho    1404: parser_endif (char *args)
1.1       misho    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
1.1.1.2 ! misho    1414: parser_include (char *args)
1.1       misho    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
1.1.1.2 ! misho    1454: handle_parser_directive (char *statement)
1.1       misho    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 */
1.1.1.2 ! misho    1484:   _rl_init_file_error ("%s: unknown parser directive", directive);
1.1       misho    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
1.1.1.2 ! misho    1491: _rl_skip_to_delim (char *string, int start, int delim)
1.1       misho    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
1.1.1.2 ! misho    1523: rl_parse_and_bind (char *string)
1.1       misho    1524: {
                   1525:   char *funname, *kname;
                   1526:   register int c, i;
1.1.1.2 ! misho    1527:   int key, equivalency, foundmod, foundsep;
1.1       misho    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:         {
1.1.1.2 ! misho    1557:           _rl_init_file_error ("%s: no closing `\"' in key binding", string);
1.1       misho    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: 
1.1.1.2 ! misho    1567:   if (i == 0)
        !          1568:     {
        !          1569:       _rl_init_file_error ("`%s': invalid key binding: missing key sequence", string);
        !          1570:       return 1;
        !          1571:     }
        !          1572: 
1.1       misho    1573:   equivalency = (c == ':' && string[i + 1] == '=');
                   1574: 
1.1.1.2 ! misho    1575:   foundsep = c != 0;
        !          1576: 
1.1       misho    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:        {
1.1.1.2 ! misho    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 */
1.1       misho    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
1.1.1.2 ! misho    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:            }
1.1       misho    1631:        }
1.1.1.2 ! misho    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: 
1.1       misho    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++;
1.1.1.2 ! misho    1662:       else
        !          1663:        {
        !          1664:          _rl_init_file_error ("`%s': missing closing quote for macro", funname);
        !          1665:          return 1;
        !          1666:        }
1.1       misho    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: 
1.1.1.2 ! misho    1682:   if (foundsep == 0)
        !          1683:     {
        !          1684:       _rl_init_file_error ("%s: no key sequence terminator", string);
        !          1685:       return 1;
        !          1686:     }
        !          1687: 
1.1       misho    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. */
1.1.1.2 ! misho    1744:   foundmod = 0;
1.1       misho    1745:   if (substring_member_of_array (string, _rl_possible_control_prefixes))
1.1.1.2 ! misho    1746:     {
        !          1747:       key = CTRL (_rl_to_upper (key));
        !          1748:       foundmod = 1;
        !          1749:     }
1.1       misho    1750: 
                   1751:   if (substring_member_of_array (string, _rl_possible_meta_prefixes))
1.1.1.2 ! misho    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:     }
1.1       misho    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));
1.1.1.2 ! misho    1788: 
1.1       misho    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)
1.1.1.2 ! misho    1807:   { "colored-completion-prefix",&_rl_colored_completion_prefix,        0 },
1.1       misho    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 },
1.1.1.2 ! misho    1815:   { "enable-bracketed-paste",  &_rl_enable_bracketed_paste,    V_SPECIAL },
1.1       misho    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
1.1.1.2 ! misho    1844: find_boolean_var (const char *name)
1.1       misho    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: 
1.1.1.2 ! misho    1854: static const char *
        !          1855: boolean_varname (int i)
        !          1856: {
        !          1857:   return ((i >= 0) ? boolean_varlist[i].name : (char *)NULL);
        !          1858: }  
        !          1859: 
1.1       misho    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
1.1.1.2 ! misho    1864: hack_special_boolean_var (int i)
1.1       misho    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 ();
1.1.1.2 ! misho    1881:   else if (_rl_stricmp (name, "enable-bracketed-paste") == 0)
        !          1882:     _rl_enable_active_region = _rl_enable_bracketed_paste;
1.1       misho    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 *));
1.1.1.2 ! misho    1905: static int sv_emacs_modestr PARAMS((const char *));
1.1       misho    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 *));
1.1.1.2 ! misho    1910: static int sv_viins_modestr PARAMS((const char *));
        !          1911: static int sv_vicmd_modestr PARAMS((const char *));
1.1       misho    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 },
1.1.1.2 ! misho    1924:   { "emacs-mode-string", V_STRING,     sv_emacs_modestr },  
1.1       misho    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 },
1.1.1.2 ! misho    1929:   { "vi-cmd-mode-string", V_STRING,    sv_vicmd_modestr }, 
        !          1930:   { "vi-ins-mode-string", V_STRING,    sv_viins_modestr }, 
1.1       misho    1931:   { (char *)NULL,      0, (_rl_sv_func_t *)0 }
                   1932: };
                   1933: 
                   1934: static int
1.1.1.2 ! misho    1935: find_string_var (const char *name)
1.1       misho    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: 
1.1.1.2 ! misho    1945: static const char *
        !          1946: string_varname (int i)
        !          1947: {
        !          1948:   return ((i >= 0) ? string_varlist[i].name : (char *)NULL);
        !          1949: }  
        !          1950: 
1.1       misho    1951: /* A boolean value that can appear in a `set variable' command is true if
1.1.1.2 ! misho    1952:    the value is null or empty, `on' (case-insensitive), or "1".  All other
1.1       misho    1953:    values result in 0 (false). */
                   1954: static int
1.1.1.2 ! misho    1955: bool_to_int (const char *value)
1.1       misho    1956: {
                   1957:   return (value == 0 || *value == '\0' ||
                   1958:                (_rl_stricmp (value, "on") == 0) ||
                   1959:                (value[0] == '1' && value[1] == '\0'));
                   1960: }
                   1961: 
                   1962: char *
1.1.1.2 ! misho    1963: rl_variable_value (const char *name)
1.1       misho    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. */
1.1.1.2 ! misho    1977:   return (char *)NULL;
1.1       misho    1978: }
                   1979: 
                   1980: int
1.1.1.2 ! misho    1981: rl_variable_bind (const char *name, const char *value)
1.1       misho    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: 
1.1.1.2 ! misho    1998:   /* For the time being, string names without a handler function are simply
        !          1999:      ignored. */
1.1       misho    2000:   if (i < 0 || string_varlist[i].set_func == 0)
1.1.1.2 ! misho    2001:     {
        !          2002:       if (i < 0)
        !          2003:        _rl_init_file_error ("%s: unknown variable name", name);
        !          2004:       return 0;
        !          2005:     }
1.1       misho    2006: 
                   2007:   v = (*string_varlist[i].set_func) (value);
1.1.1.2 ! misho    2008:   if (v != 0)
        !          2009:     _rl_init_file_error ("%s: could not set value to `%s'", name, value);
1.1       misho    2010:   return v;
                   2011: }
                   2012: 
                   2013: static int
1.1.1.2 ! misho    2014: sv_editmode (const char *value)
1.1       misho    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
1.1.1.2 ! misho    2034: sv_combegin (const char *value)
1.1       misho    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
1.1.1.2 ! misho    2046: sv_dispprefix (const char *value)
1.1       misho    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
1.1.1.2 ! misho    2061: sv_compquery (const char *value)
1.1       misho    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
1.1.1.2 ! misho    2076: sv_compwidth (const char *value)
1.1       misho    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
1.1.1.2 ! misho    2088: sv_histsize (const char *value)
1.1       misho    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
1.1.1.2 ! misho    2107: sv_keymap (const char *value)
1.1       misho    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
1.1.1.2 ! misho    2121: sv_seqtimeout (const char *value)
1.1       misho    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
1.1.1.2 ! misho    2137: sv_bell_style (const char *value)
1.1       misho    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
1.1.1.2 ! misho    2153: sv_isrchterm (const char *value)
1.1       misho    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:     {
1.1.1.2 ! misho    2172:       for (beg = end = 0; v[end] && whitespace (v[end]) == 0; end++)
1.1       misho    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: }
1.1.1.2 ! misho    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: 
1.1       misho    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
1.1.1.2 ! misho    2297: glean_key_from_name (char *name)
1.1       misho    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. */
1.1.1.2 ! misho    2309: struct name_and_keymap {
        !          2310:   char *name;
1.1       misho    2311:   Keymap map;
1.1.1.2 ! misho    2312: };
        !          2313: 
        !          2314: static struct name_and_keymap builtin_keymap_names[] = {
1.1       misho    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: 
1.1.1.2 ! misho    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)
1.1       misho    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)
1.1.1.2 ! misho    2340:       return (i);
        !          2341:   return -1;
1.1       misho    2342: }
                   2343: 
1.1.1.2 ! misho    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)
1.1       misho    2355: {
                   2356:   register int i;
1.1.1.2 ! misho    2357: 
1.1       misho    2358:   for (i = 0; keymap_names[i].name; i++)
                   2359:     if (map == keymap_names[i].map)
1.1.1.2 ! misho    2360:       return (i);
        !          2361:   return -1;
1.1       misho    2362: }
1.1.1.2 ! misho    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: 
1.1       misho    2423: void
1.1.1.2 ! misho    2424: rl_set_keymap (Keymap map)
1.1       misho    2425: {
                   2426:   if (map)
                   2427:     _rl_keymap = map;
                   2428: }
                   2429: 
                   2430: Keymap
1.1.1.2 ! misho    2431: rl_get_keymap (void)
1.1       misho    2432: {
                   2433:   return (_rl_keymap);
                   2434: }
                   2435: 
                   2436: void
1.1.1.2 ! misho    2437: rl_set_keymap_from_edit_mode (void)
1.1       misho    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 *
1.1.1.2 ! misho    2448: rl_get_keymap_name_from_edit_mode (void)
1.1       misho    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
1.1.1.2 ! misho    2473: rl_list_funmap_names (void)
1.1       misho    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 *
1.1.1.2 ! misho    2490: _rl_get_keyname (int key)
1.1       misho    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 **
1.1.1.2 ! misho    2565: rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map)
1.1       misho    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:                  {
1.1.1.2 ! misho    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';
1.1       misho    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 **
1.1.1.2 ! misho    2674: rl_invoking_keyseqs (rl_command_func_t *function)
1.1       misho    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
1.1.1.2 ! misho    2683: rl_function_dumper (int print_readably)
1.1       misho    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
1.1.1.2 ! misho    2754: rl_dump_functions (int count, int key)
1.1       misho    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
1.1.1.2 ! misho    2764: _rl_macro_dumper_internal (int print_readably, Keymap map, char *prefix)
1.1       misho    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
1.1.1.2 ! misho    2823: rl_macro_dumper (int print_readably)
1.1       misho    2824: {
                   2825:   _rl_macro_dumper_internal (print_readably, _rl_keymap, (char *)NULL);
                   2826: }
                   2827: 
                   2828: int
1.1.1.2 ! misho    2829: rl_dump_macros (int count, int key)
1.1       misho    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 *
1.1.1.2 ! misho    2839: _rl_get_string_variable_value (const char *name)
1.1       misho    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:     }
1.1.1.2 ! misho    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);
1.1       misho    2914:   else
                   2915:     return (0);
                   2916: }
                   2917: 
                   2918: void
1.1.1.2 ! misho    2919: rl_variable_dumper (int print_readably)
1.1       misho    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
1.1.1.2 ! misho    2950: rl_dump_variables (int count, int key)
1.1       misho    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
1.1.1.2 ! misho    2961: substring_member_of_array (const char *string, const char * const *array)
1.1       misho    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>