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