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