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