From e67d0029f0b234e56806c63244c1042f92747df0 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Mon, 9 Jan 2012 08:33:45 -0500 Subject: [PATCH] commit bash-20111123 snapshot --- CWRU/CWRU.chlog | 111 ++ CWRU/CWRU.chlog~ | 123 +- builtins/read.def | 53 +- ddd1 | 216 ++++ ddd1~ | 33 + doc/bash.1 | 15 +- doc/bashref.texi | 64 +- doc/bashref.texi~ | 59 +- doc/version.texi | 4 +- doc/version.texi~ | 4 +- lib/readline/complete.c | 75 +- lib/readline/complete.c~ | 83 +- lib/readline/doc/hsuser.texi | 2 +- lib/readline/rlprivate.h | 8 + lib/readline/rlprivate.h~ | 521 +++++++++ lib/readline/signals.c | 12 + lib/readline/signals.c~ | 20 +- lib/readline/util.c | 6 + lib/readline/util.c~ | 526 +++++++++ lib/readline/vi_keymap.c | 1 - lib/readline/vi_keymap.c~ | 876 ++++++++++++++ lib/readline/vi_mode.c | 93 +- lib/readline/vi_mode.c~ | 2142 ++++++++++++++++++++++++++++++++++ parse.y | 2 + parse.y~ | 14 +- patchlevel.h | 2 +- tests/RUN-ONE-TEST | 2 +- variables.c~ | 11 +- 28 files changed, 4966 insertions(+), 112 deletions(-) create mode 100644 ddd1 create mode 100644 ddd1~ create mode 100644 lib/readline/rlprivate.h~ create mode 100644 lib/readline/util.c~ create mode 100644 lib/readline/vi_keymap.c~ create mode 100644 lib/readline/vi_mode.c~ diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 1bb9c47d8..d169ddc5f 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -12628,3 +12628,114 @@ variables.c results in no file truncation - make it clear that numeric values less than 0 for HISTFILESIZE or HISTSIZE inhibit the usual functions + + 11/23 + ----- +parse.y + - save_input_line_state: add missing `return ls' at the end, since the + function is supposed to return its argument. Pointed out by + Andreas Schwab + +builtins/read.def + - skip over NUL bytes in input, as most modern shells seem to. Bug + report by Matthew Story + +lib/readline/vi_mode.c + - rl_vi_replace: set _rl_vi_last_key_before_insert to invoking key + + 11/25 + ----- +builtins/read.def + - read_builtin: if xrealloc returns same pointer as first argument, + don't bother with the remove_unwind_protect/add_unwind_protect pair + - read_builtin: set a flag (`reading') around calls to zread/zreadc + and readline() + - sigalrm: change to set flag (`sigalrm_seen') and only longjmp if + currently in read(2) (reading != 0) + - CHECK_ALRM: new macro, checks sigalrm_seen and longjmps if non-zero, + behavior of old SIGALRM catching function + - read_builtin: call CHECK_ALRM in appropriate places while reading + line of input. Fixes bug reported by Pierre Gaston + + +lib/readline/vi_mode.c + - rl_vi_replace: initialize characters before printing characters in + vi_replace_keymap to their default values in vi_insertion_keymap, + since we're supposed to be in insert mode replacing characters + - rl_vi_replace: call rl_vi_start_inserting to set last command to + `R' for undo + - rl_vi_replace: set _rl_vi_last_key_before_insert to `R' for future + use by _rl_vi_done_inserting + - vi_save_insert_buffer: new function, broke out code that copies text + into vi_insert_buffer from _rl_vi_save_insert + - _rl_vi_save_replace: new function, saves text modified by + rl_vi_replace (using current point and vi_replace_count to figure + it out) to vi_replace_buffer + - _rl_vi_save_insert: call vi_save_insert_buffer + - _rl_vi_done_inserting: if _rl_vi_last_key_before_insert == 'R', call + _rl_vi_save_replace to save text modified in replace mode (uses + vi_save_insert_buffer) + - _rl_vi_replace_insert: new function, replaces the number of chars + in vi_insert_buffer after rl_point with contents ov vi_insert_buffer + - rl_vi_redo: call _rl_vi_replace_insert if last command == 'R' and + there's something in vi_insert_buffer. Fixes bug with `.' not + redoing the most recent `R' command, reported by Geoff Clare + in readline area on savannah + + 11/26 + ----- +lib/readline/rlprivate.h + - RL_SIG_RECEIVED(): evaluate to non-zero if there is a pending signal + to be handled + - RL_SIGINT_RECEIVED(): evaluate to non-zero if there is a pending + SIGINT to be handled + +lib/readline/complete.c + - remove all mention of _rl_interrupt_immediately + - rl_completion_matches: check RL_SIG_RECEIVED after each call to + the entry function, call RL_CHECK_SIGNALS if true to handle the + signal + - rl_completion_matches: if RL_SIG_RECEIVED evaluates to true, free + and zero out the match_list this function allocated + - rl_completion_matches: if the completion entry function is + rl_filename_completion_function, free the contents of match_list, + because that function does not keep state and will not free the + entries; avoids possible memory leak pointed out by + Garrett Cooper + - gen_completion_matches: if RL_SIG_RECEIVED evalutes to true after + calling rl_attempted_completion_function, free the returned match + list and handle the signal with RL_CHECK_SIGNALS; avoids + possible memory leak pointed out by Garrett Cooper + + - gen_completion_matches: if RL_SIG_RECEIVED evaluates to true after + calling rl_completion_matches, free the returned match list and + handle the signal with RL_CHECK_SIGNALS + +lib/readline/util.c + - rl_settracefp: new utility function to set the tracing FILE * + +lib/readline/signals.c + - _rl_sigcleanup: pointer to a function that will be called with the + signal and a void * argument from _rl_handle_signal + - _rl_sigcleanarg: void * that the rest of the code can set to have + passed to the signal cleanup function + - _rl_handle_signal: if _rl_sigcleanup set, call as + (*_rl_sigcleanup) (sig, _rl_sigcleanarg) + +lib/readline/rlprivate.h + - extern declarations for _rl_sigcleanup and _rl_sigcleanarg + +lib/readline/complete.c + - _rl_complete_sigcleanup: signal cleanup function for completion code; + calls _rl_free_match_list on _rl_sigcleanarg if signal == SIGINT + - rl_complete_internal: before calling display_matches if what_to_do + == `?', set _rl_sigcleanup to _rl_complete_sigcleanup so the match + list gets freed on SIGINT; avoids possible memory leak pointed out + by Garrett Cooper + - rl_complete_internal: in default switch case, call _rl_free_match_list + before returning to avoid memory leak + +doc/bashref.texi + - start at a set of examples for the =~ regular expression matching + operator, touching on keeping the pattern in a shell variable and + quoting portions of the pattern to remove their special meaning diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index 6444aa46c..fcc9f043b 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -12620,5 +12620,126 @@ doc/{bash.1,bashref.texi},lib/readline/doc/hsuser.texi saved in the history list - make it clear that setting HISTFILESIZE=0 causes the history file to be truncated to zero size + +variables.c + - sv_histsize: change so setting HISTSIZE to a value less than 0 + causes the history to be `unstifled' + - sv_histsize: change so setting HISTFILESIZE to a value less than 0 + results in no file truncation - make it clear that numeric values less than 0 for HISTFILESIZE or - HISTSIZE are treated the same as 0 + HISTSIZE inhibit the usual functions + + 11/23 + ----- +parse.y + - save_input_line_state: add missing `return ls' at the end, since the + function is supposed to return its argument. Pointed out by + Andreas Schwab + +builtins/read.def + - skip over NUL bytes in input, as most modern shells seem to. Bug + report by Matthew Story + +lib/readline/vi_mode.c + - rl_vi_replace: set _rl_vi_last_key_before_insert to invoking key + + 11/25 + ----- +builtins/read.def + - read_builtin: if xrealloc returns same pointer as first argument, + don't bother with the remove_unwind_protect/add_unwind_protect pair + - read_builtin: set a flag (`reading') around calls to zread/zreadc + and readline() + - sigalrm: change to set flag (`sigalrm_seen') and only longjmp if + currently in read(2) (reading != 0) + - CHECK_ALRM: new macro, checks sigalrm_seen and longjmps if non-zero, + behavior of old SIGALRM catching function + - read_builtin: call CHECK_ALRM in appropriate places while reading + line of input. Fixes bug reported by Pierre Gaston + + +lib/readline/vi_mode.c + - rl_vi_replace: initialize characters before printing characters in + vi_replace_keymap to their default values in vi_insertion_keymap, + since we're supposed to be in insert mode replacing characters + - rl_vi_replace: call rl_vi_start_inserting to set last command to + `R' for undo + - rl_vi_replace: set _rl_vi_last_key_before_insert to `R' for future + use by _rl_vi_done_inserting + - vi_save_insert_buffer: new function, broke out code that copies text + into vi_insert_buffer from _rl_vi_save_insert + - _rl_vi_save_replace: new function, saves text modified by + rl_vi_replace (using current point and vi_replace_count to figure + it out) to vi_replace_buffer + - _rl_vi_save_insert: call vi_save_insert_buffer + - _rl_vi_done_inserting: if _rl_vi_last_key_before_insert == 'R', call + _rl_vi_save_replace to save text modified in replace mode (uses + vi_save_insert_buffer) + - _rl_vi_replace_insert: new function, replaces the number of chars + in vi_insert_buffer after rl_point with contents ov vi_insert_buffer + - rl_vi_redo: call _rl_vi_replace_insert if last command == 'R' and + there's something in vi_insert_buffer. Fixes bug with `.' not + redoing the most recent `R' command, reported by Geoff Clare + in readline area on savannah + + 11/26 + ----- +lib/readline/rlprivate.h + - RL_SIG_RECEIVED(): evaluate to non-zero if there is a pending signal + to be handled + - RL_SIGINT_RECEIVED(): evaluate to non-zero if there is a pending + SIGINT to be handled + +lib/readline/complete.c + - remove all mention of _rl_interrupt_immediately + - rl_completion_matches: check RL_SIG_RECEIVED after each call to + the entry function, call RL_CHECK_SIGNALS if true to handle the + signal + - rl_completion_matches: if RL_SIG_RECEIVED evaluates to true, free + and zero out the match_list this function allocated + - rl_completion_matches: if the completion entry function is + rl_filename_completion_function, free the contents of match_list, + because that function does not keep state and will not free the + entries; avoids possible memory leak pointed out by + Garrett Cooper + - gen_completion_matches: if RL_SIG_RECEIVED evalutes to true after + calling rl_attempted_completion_function, free the returned match + list and handle the signal with RL_CHECK_SIGNALS; avoids + possible memory leak pointed out by Garrett Cooper + + - gen_completion_matches: if RL_SIG_RECEIVED evaluates to true after + calling rl_completion_matches, free the returned match list and + handle the signal with RL_CHECK_SIGNALS + +lib/readline/util.c + - rl_settracefp: new utility function to set the tracing FILE * + +lib/readline/signals.c + - _rl_sigcleanup: pointer to a function that will be called with the + signal and a void * argument from _rl_handle_signal + - _rl_sigcleanarg: void * that the rest of the code can set to have + passed to the signal cleanup function + - _rl_handle_signal: if _rl_sigcleanup set, call as + (*_rl_sigcleanup) (sig, _rl_sigcleanarg) + +lib/readline/rlprivate.h + - extern declarations for _rl_sigcleanup and _rl_sigcleanarg + +lib/readline/complete.c + - _rl_complete_sigcleanup: signal cleanup function for completion code; + calls _rl_free_match_list on _rl_sigcleanarg if signal == SIGINT + - rl_complete_internal: before calling display_matches if what_to_do + == `?', set _rl_sigcleanup to _rl_complete_sigcleanup so the match + list gets freed on SIGINT; avoids possible memory leak pointed out + by Garrett Cooper + - rl_complete_internal: in default switch case, call _rl_free_match_list + before returning to avoid memory leak + +doc/bashref.texi + - start at a set of examples for the =~ regular expression matching + operator, touching on keeping the pattern in a shell variable and + quoting portions of the pattern to remove their special meaning + +variables.c + - sv_history_control: setting HISTCONTROL to the empty string or + unsetting it unsets the history_control variables diff --git a/builtins/read.def b/builtins/read.def index ba75be2ae..f9e23d7bb 100644 --- a/builtins/read.def +++ b/builtins/read.def @@ -1,7 +1,7 @@ This file is read.def, from which is created read.c. It implements the builtin "read" in Bash. -Copyright (C) 1987-2010 Free Software Foundation, Inc. +Copyright (C) 1987-2011 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -129,14 +129,26 @@ static sighandler sigalrm __P((int)); static void reset_alarm __P((void)); static procenv_t alrmbuf; +static int sigalrm_seen, reading; static SigHandler *old_alrm; static unsigned char delim; +/* In most cases, SIGALRM just sets a flag that we check periodically. This + avoids problems with the semi-tricky stuff we do with the xfree of + input_string at the top of the unwind-protect list (see below). */ +#define CHECK_ALRM \ + do { \ + if (sigalrm_seen) \ + longjmp (alrmbuf, 1); \ + } while (0) + static sighandler sigalrm (s) int s; { - longjmp (alrmbuf, 1); + sigalrm_seen = 1; + if (reading) /* do the longjmp if we get SIGALRM while in read() */ + longjmp (alrmbuf, 1); } static void @@ -201,6 +213,8 @@ read_builtin (list) USE_VAR(list); USE_VAR(ps2); + sigalrm_seen = reading = 0; + i = 0; /* Index into the string that we are reading. */ raw = edit = 0; /* Not reading raw input by default. */ silent = 0; @@ -384,9 +398,12 @@ read_builtin (list) code = setjmp (alrmbuf); if (code) { + sigalrm_seen = 0; /* Tricky. The top of the unwind-protect stack is the free of input_string. We want to run all the rest and use input_string, so we have to remove it from the stack. */ + orig_input_string = 0; + remove_unwind_protect (); run_unwind_frame ("read_builtin"); input_string[i] = '\0'; /* make sure it's terminated */ @@ -457,6 +474,7 @@ read_builtin (list) add_unwind_protect (xfree, input_string); interrupt_immediately++; + CHECK_ALRM; unbuffered_read = (nchars > 0) || (delim != '\n') || input_is_pipe; if (prompt && edit == 0) @@ -472,6 +490,8 @@ read_builtin (list) ps2 = 0; for (print_ps2 = eof = retval = 0;;) { + CHECK_ALRM; + #if defined (READLINE) if (edit) { @@ -482,7 +502,9 @@ read_builtin (list) } if (rlbuf == 0) { + reading = 1; rlbuf = edit_line (prompt ? prompt : "", itext); + reading = 0; rlind = 0; } if (rlbuf == 0) @@ -505,10 +527,12 @@ read_builtin (list) print_ps2 = 0; } + reading = 1; if (unbuffered_read) retval = zread (fd, &c, 1); else retval = zreadc (fd, &c); + reading = 0; if (retval <= 0) { @@ -517,15 +541,25 @@ read_builtin (list) break; } + CHECK_ALRM; + #if defined (READLINE) } #endif + CHECK_ALRM; if (i + 4 >= size) /* XXX was i + 2; use i + 4 for multibyte/read_mbchar */ { - input_string = (char *)xrealloc (input_string, size += 128); - remove_unwind_protect (); - add_unwind_protect (xfree, input_string); + char *t; + t = (char *)xrealloc (input_string, size += 128); + + /* Only need to change unwind-protect if input_string changes */ + if (t != input_string) + { + input_string = t; + remove_unwind_protect (); + add_unwind_protect (xfree, input_string); + } } /* If the next character is to be accepted verbatim, a backslash @@ -559,6 +593,9 @@ read_builtin (list) if ((unsigned char)c == delim) break; + if (c == '\0') + continue; /* skip NUL bytes in input */ + if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL)) { saw_escape++; @@ -567,6 +604,7 @@ read_builtin (list) add_char: input_string[i++] = c; + CHECK_ALRM; #if defined (HANDLE_MULTIBYTE) if (nchars > 0 && MB_CUR_MAX > 1) @@ -582,15 +620,14 @@ add_char: break; } input_string[i] = '\0'; + CHECK_ALRM; -#if 1 if (retval < 0) { builtin_error (_("read error: %d: %s"), fd, strerror (errno)); run_unwind_frame ("read_builtin"); return (EXECUTION_FAILURE); } -#endif if (tmsec > 0 || tmusec > 0) reset_alarm (); @@ -693,7 +730,7 @@ assign_vars: var = bind_variable ("REPLY", input_string, 0); VUNSETATTR (var, att_invisible); - free (input_string); + xfree (input_string); return (retval); } diff --git a/ddd1 b/ddd1 new file mode 100644 index 000000000..bddde9c19 --- /dev/null +++ b/ddd1 @@ -0,0 +1,216 @@ +*** ../bash-20111118/lib/readline/complete.c 2011-10-02 14:18:22.000000000 -0400 +--- lib/readline/complete.c 2011-11-26 16:01:20.000000000 -0500 +*************** +*** 31,36 **** +--- 31,38 ---- + # include + #endif + ++ #include ++ + #if defined (HAVE_UNISTD_H) + # include + #endif /* HAVE_UNISTD_H */ +*************** +*** 105,110 **** +--- 107,114 ---- + + static char *rl_quote_filename PARAMS((char *, int, char *)); + ++ static void _rl_complete_sigcleanup PARAMS((int, void *)); ++ + static void set_completion_defaults PARAMS((int)); + static int get_y_or_n PARAMS((int)); + static int _rl_internal_pager PARAMS((int)); +*************** +*** 459,464 **** +--- 463,477 ---- + rl_completion_quote_character = 0; + } + ++ static void ++ _rl_complete_sigcleanup (sig, ptr) ++ int sig; ++ void *ptr; ++ { ++ if (sig == SIGINT) /* XXX - for now */ ++ _rl_free_match_list ((char **)ptr); ++ } ++ + /* Set default values for readline word completion. These are the variables + that application completion functions can change or inspect. */ + static void +*************** +*** 1060,1073 **** + variable rl_attempted_completion_function. */ + if (rl_attempted_completion_function) + { +- #if 0 +- _rl_interrupt_immediately++; +- #endif + matches = (*rl_attempted_completion_function) (text, start, end); +! #if 0 +! if (_rl_interrupt_immediately > 0) +! _rl_interrupt_immediately--; +! #endif + + if (matches || rl_attempted_completion_over) + { +--- 1073,1085 ---- + variable rl_attempted_completion_function. */ + if (rl_attempted_completion_function) + { + matches = (*rl_attempted_completion_function) (text, start, end); +! if (RL_SIG_RECEIVED()) +! { +! _rl_free_match_list (matches); +! matches = 0; +! RL_CHECK_SIGNALS (); +! } + + if (matches || rl_attempted_completion_over) + { +*************** +*** 1078,1084 **** +--- 1090,1104 ---- + + /* XXX -- filename dequoting moved into rl_filename_completion_function */ + ++ /* rl_completion_matches will check for signals as well to avoid a long ++ delay while reading a directory. */ + matches = rl_completion_matches (text, our_func); ++ if (RL_SIG_RECEIVED()) ++ { ++ _rl_free_match_list (matches); ++ matches = 0; ++ RL_CHECK_SIGNALS (); ++ } + return matches; + } + +*************** +*** 1838,1847 **** + /* nontrivial_lcd is set if the common prefix adds something to the word + being completed. */ + nontrivial_lcd = matches && strcmp (text, matches[0]) != 0; +- #if 1 + if (what_to_do == '!' || what_to_do == '@') + tlen = strlen (text); +- #endif + xfree (text); + + if (matches == 0) +--- 1858,1865 ---- +*************** +*** 1875,1884 **** + case '!': + case '@': + /* Insert the first match with proper quoting. */ +- #if 0 +- if (*matches[0]) +- insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); +- #else + if (what_to_do == TAB) + { + if (*matches[0]) +--- 1893,1898 ---- +*************** +*** 1893,1899 **** + if (mlen >= tlen) + insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); + } +- #endif + + /* If there are more matches, ring the bell to indicate. + If we are in vi mode, Posix.2 says to not ring the bell. +--- 1907,1912 ---- +*************** +*** 1929,1935 **** +--- 1942,1955 ---- + break; + + case '?': ++ if (rl_completion_display_matches_hook == 0) ++ { ++ _rl_sigcleanup = _rl_complete_sigcleanup; ++ _rl_sigcleanarg = matches; ++ } + display_matches (matches); ++ _rl_sigcleanup = 0; ++ _rl_sigcleanarg = 0; + break; + + default: +*************** +*** 1937,1942 **** +--- 1957,1963 ---- + rl_ding (); + FREE (saved_line_buffer); + RL_UNSETSTATE(RL_STATE_COMPLETING); ++ _rl_free_match_list (matches); + _rl_reset_completion_state (); + return 1; + } +*************** +*** 1978,1983 **** +--- 1999,2006 ---- + const char *text; + rl_compentry_func_t *entry_function; + { ++ register int i; ++ + /* Number of slots in match_list. */ + int match_list_size; + +*************** +*** 1995,2005 **** + match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); + match_list[1] = (char *)NULL; + +- #if 0 +- _rl_interrupt_immediately++; +- #endif + while (string = (*entry_function) (text, matches)) + { + if (matches + 1 == match_list_size) + match_list = (char **)xrealloc + (match_list, ((match_list_size += 10) + 1) * sizeof (char *)); +--- 2018,2042 ---- + match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); + match_list[1] = (char *)NULL; + + while (string = (*entry_function) (text, matches)) + { ++ if (RL_SIG_RECEIVED ()) ++ { ++ /* Start at 1 because we don't set matches[0] in this function. ++ Only free the list members if we're building match list from ++ rl_filename_completion_function, since we know that doesn't ++ free the strings it returns. */ ++ if (entry_function == rl_filename_completion_function) ++ { ++ for (i = 1; match_list[i]; i++) ++ xfree (match_list[i]); ++ } ++ xfree (match_list); ++ match_list = 0; ++ match_list_size = 0; ++ RL_CHECK_SIGNALS (); ++ } ++ + if (matches + 1 == match_list_size) + match_list = (char **)xrealloc + (match_list, ((match_list_size += 10) + 1) * sizeof (char *)); +*************** +*** 2007,2016 **** + match_list[++matches] = string; + match_list[matches + 1] = (char *)NULL; + } +- #if 0 +- if (_rl_interrupt_immediately > 0) +- _rl_interrupt_immediately--; +- #endif + + /* If there were any matches, then look through them finding out the + lowest common denominator. That then becomes match_list[0]. */ +--- 2044,2049 ---- diff --git a/ddd1~ b/ddd1~ new file mode 100644 index 000000000..cf0b7cbb6 --- /dev/null +++ b/ddd1~ @@ -0,0 +1,33 @@ +*** /fs2/chet/scratch/bash-4.2-direxpand/bashline.c 2011-11-23 17:11:31.000000000 -0500 +--- bashline.c 2011-11-05 18:46:35.000000000 -0400 +*************** +*** 1292,1295 **** +--- 1339,1343 ---- + + rl_filename_quote_characters = default_filename_quote_characters; ++ set_directory_hook (); + + /* Determine if this could be a command word. It is if it appears at +*************** +*** 1605,1608 **** +--- 1672,1681 ---- + else + { ++ if (dircomplete_expand && path_dot_or_dotdot (filename_hint)) ++ { ++ dircomplete_expand = 0; ++ set_directory_hook (); ++ dircomplete_expand = 1; ++ } + mapping_over = 4; + goto inner; +*************** +*** 1805,1808 **** +--- 1878,1884 ---- + inner: + val = rl_filename_completion_function (filename_hint, istate); ++ if (mapping_over == 4 && dircomplete_expand) ++ set_directory_hook (); ++ + istate = 1; + diff --git a/doc/bash.1 b/doc/bash.1 index 135888176..5ad636832 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -48,7 +48,7 @@ bash \- GNU Bourne-Again SHell .SH SYNOPSIS .B bash [options] -[file] +[command_string | file] .SH COPYRIGHT .if n Bash is Copyright (C) 1989-2011 by the Free Software Foundation, Inc. .if t Bash is Copyright \(co 1989-2011 by the Free Software Foundation, Inc. @@ -75,13 +75,13 @@ interprets the following options when it is invoked: .PP .PD 0 .TP 10 -.BI \-c "\| string\^" +.B \-c If the .B \-c -option is present, then commands are read from -.IR string . +option is present, then commands are read from the first non-option argument +.IR command_string . If there are arguments after the -.IR string , +.IR command_string , they are assigned to the positional parameters, starting with .BR $0 . .TP @@ -1981,7 +1981,7 @@ to contain no more than that number of lines by removing the oldest entries. The history file is also truncated to this size after writing it when an interactive shell exits. If the value is 0, the history file is truncated to zero size. -Numeric values less than zero inhibit truncation. +Non-numeric values and numeric values less than zero inhibit truncation. The shell sets the default value to the value of \fBHISTSIZE\fP after reading any startup files. .TP @@ -6294,7 +6294,8 @@ to contain no more than lines. If .SM .B HISTFILESIZE -is not set, no truncation is performed. +is unset, or set to null, a non-numeric value, +or a numeric value less than zero, the history file is not truncated. .PP The builtin command .B fc diff --git a/doc/bashref.texi b/doc/bashref.texi index 0e8127b80..42a3d0055 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -1045,6 +1045,61 @@ matching the entire regular expression. The element of @code{BASH_REMATCH} with index @var{n} is the portion of the string matching the @var{n}th parenthesized subexpression. +For example, the following will match a line +(stored in the shell variable @var{line}) +if there is a sequence of characters in the value consisting of +any number, including zero, of +space characters, zero or one instances of @samp{a}, then a @samp{b}: +@example +[[ $line =~ [[:space:]]*(a)?b ]] +@end example + +@noindent +That means values like @samp{aab} and @samp{ aaaaaab} will match, as +will a line containing a @samp{b} anywhere in its value. + +Storing the regular expression in a shell variable is often a useful +way to avoid problems with quoting characters that are special to the +shell. +It is sometimes difficult to specify a regular expression literally +without using quotes, or to keep track of the quoting used by regular +expressions while paying attention to the shell's quote removal. +Using a shell variable to store the pattern decreases these problems. +For example, the following is equivalent to the above: +@example +pattern='[[:space:]]*(a)?b' +[[ $line =~ $pattern ]] +@end example + +@noindent +If you want to match a character that's special to the regular expression +grammar, it has to be quoted to remove its special meaning. +This means that in the pattern @samp{xxx.txt}, the @samp{.} matches any +character in the string (its usual regular expression meaning), but in the +pattern @samp{"xxx.txt"} it can only match a literal @samp{.}. +Shell programmers should take special care with backslashes, since backslashes +are used both by the shell and regular expressions to remove the special +meaning from the following character. +The following two sets of commands are @emph{not} equivalent: +@example +pattern='\.' + +[[ . =~ $pattern ]] +[[ . =~ \. ]] + +[[ . =~ "$pattern" ]] +[[ . =~ '\.' ]] +@end example + +@noindent +The first two matches will succeed, but the second two will not, because +in the second two the backslash will be part of the pattern to be matched. +In the first two examples, the backslash removes the special meaning from +@samp{.}, so the literal @samp{.} matches. +If the string in the first examples were anything other than @samp{.}, say +@samp{a}, the pattern would not match, because the quoted @samp{.} in the +pattern loses its special meaning of matching any single character. + Expressions may be combined using the following operators, listed in decreasing order of precedence: @@ -5313,7 +5368,7 @@ by removing the oldest entries. The history file is also truncated to this size after writing it when an interactive shell exits. If the value is 0, the history file is truncated to zero size. -Numeric values less than zero inhibit truncation. +Non-numeric values and numeric values less than zero inhibit truncation. The shell sets the default value to the value of @env{HISTSIZE} after reading any startup files. @@ -5706,9 +5761,10 @@ There are several single-character options that may be supplied at invocation which are not available with the @code{set} builtin. @table @code -@item -c @var{string} -Read and execute commands from @var{string} after processing the -options, then exit. Any remaining arguments are assigned to the +@item -c +Read and execute commands from the first non-option @var{argument} +after processing the options, then exit. +Any remaining arguments are assigned to the positional parameters, starting with @code{$0}. @item -i diff --git a/doc/bashref.texi~ b/doc/bashref.texi~ index 47c278981..f3094649e 100644 --- a/doc/bashref.texi~ +++ b/doc/bashref.texi~ @@ -1045,6 +1045,53 @@ matching the entire regular expression. The element of @code{BASH_REMATCH} with index @var{n} is the portion of the string matching the @var{n}th parenthesized subexpression. +For example, the following will match a line +(stored in the shell variable @var{line}) +if there is a sequence of characters in the value consisting of +any number, including zero, of +space characters, zero or one instances of @samp{a}, then a @samp{b}: +@example +[[ $line =~ [[:space:]]*(a)?b ]] +@end example + +@noindent +That means values like @samp{aab} and @samp{ aaaaaab} will match, as +will a line containing a @samp{b} anywhere in its value. + +Storing the regular expression in a shell variable is often a useful +way to avoid problems with quoting characters that are special to the +shell. For example, the following is equivalent to the above: +@example +pattern='[[:space:]]*(a)?b' +[[ $line =~ $pattern ]] +@end example + +@noindent +If you want to match a character that's special to the regular expression +grammar, it has to be quoted to remove its special meaning. +Shell programmers should take special care with backslashes, since backslashes +are used both by the shell and regular expressions to remove the special +meaning from the following character. +The following two sets of commands are @emph{not} equivalent: +@example +pattern='\.' + +[[ . =~ $pattern ]] +[[ . =~ \. ]] + +[[ . =~ "$pattern" ]] +[[ . =~ '\.' ]] +@end example + +@noindent +The first two matches will succeed, but the second two will not, because +in the second two the backslash will be part of the pattern to be matched. +In the first two examples, the backslash removes the special meaning from +@samp{.}, so the literal @samp{.} matches. +If the string in the first examples were anything other than @samp{.}, say +@samp{a}, the pattern would not match, because the quoted @samp{.} in the +pattern loses its special meaning of matching any single character. + Expressions may be combined using the following operators, listed in decreasing order of precedence: @@ -5313,7 +5360,7 @@ by removing the oldest entries. The history file is also truncated to this size after writing it when an interactive shell exits. If the value is 0, the history file is truncated to zero size. -Numeric values less than zero are treated as 0. +Non-numeric values and numeric values less than zero inhibit truncation. The shell sets the default value to the value of @env{HISTSIZE} after reading any startup files. @@ -5340,7 +5387,8 @@ provides the functionality of @code{ignoreboth}. @item HISTSIZE The maximum number of commands to remember on the history list. If the value is 0, commands are not saved in the history list. -Numeric values less than zero are treated as 0. +Numeric values less than zero result in every command being saved +on the history list (there is no limit). The shell sets the default value to 500 after reading any startup files. @item HISTTIMEFORMAT @@ -5705,9 +5753,10 @@ There are several single-character options that may be supplied at invocation which are not available with the @code{set} builtin. @table @code -@item -c @var{string} -Read and execute commands from @var{string} after processing the -options, then exit. Any remaining arguments are assigned to the +@item -c +Read and execute commands from the first non-option @var{argument} +after processing the options, then exit. +Any remaining arguments are assigned to the positional parameters, starting with @code{$0}. @item -i diff --git a/doc/version.texi b/doc/version.texi index 048bec516..f8d375799 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -2,9 +2,9 @@ Copyright (C) 1988-2011 Free Software Foundation, Inc. @end ignore -@set LASTCHANGE Sat Sat Nov 19 15:15:12 EST 2011 +@set LASTCHANGE Sat Nov 26 16:56:23 EST 2011 @set EDITION 4.2 @set VERSION 4.2 -@set UPDATED 19 November 2011 +@set UPDATED 26 November 2011 @set UPDATED-MONTH November 2011 diff --git a/doc/version.texi~ b/doc/version.texi~ index 1453458a6..048bec516 100644 --- a/doc/version.texi~ +++ b/doc/version.texi~ @@ -2,9 +2,9 @@ Copyright (C) 1988-2011 Free Software Foundation, Inc. @end ignore -@set LASTCHANGE Sat Nov 12 13:35:12 EST 2011 +@set LASTCHANGE Sat Sat Nov 19 15:15:12 EST 2011 @set EDITION 4.2 @set VERSION 4.2 -@set UPDATED 12 November 2011 +@set UPDATED 19 November 2011 @set UPDATED-MONTH November 2011 diff --git a/lib/readline/complete.c b/lib/readline/complete.c index 42a83d5c3..7ebb104e9 100644 --- a/lib/readline/complete.c +++ b/lib/readline/complete.c @@ -31,6 +31,8 @@ # include #endif +#include + #if defined (HAVE_UNISTD_H) # include #endif /* HAVE_UNISTD_H */ @@ -105,6 +107,8 @@ static int path_isdir PARAMS((const char *)); static char *rl_quote_filename PARAMS((char *, int, char *)); +static void _rl_complete_sigcleanup PARAMS((int, void *)); + static void set_completion_defaults PARAMS((int)); static int get_y_or_n PARAMS((int)); static int _rl_internal_pager PARAMS((int)); @@ -459,6 +463,15 @@ _rl_reset_completion_state () rl_completion_quote_character = 0; } +static void +_rl_complete_sigcleanup (sig, ptr) + int sig; + void *ptr; +{ + if (sig == SIGINT) /* XXX - for now */ + _rl_free_match_list ((char **)ptr); +} + /* Set default values for readline word completion. These are the variables that application completion functions can change or inspect. */ static void @@ -1060,14 +1073,13 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char) variable rl_attempted_completion_function. */ if (rl_attempted_completion_function) { -#if 0 - _rl_interrupt_immediately++; -#endif matches = (*rl_attempted_completion_function) (text, start, end); -#if 0 - if (_rl_interrupt_immediately > 0) - _rl_interrupt_immediately--; -#endif + if (RL_SIG_RECEIVED()) + { + _rl_free_match_list (matches); + matches = 0; + RL_CHECK_SIGNALS (); + } if (matches || rl_attempted_completion_over) { @@ -1078,7 +1090,15 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char) /* XXX -- filename dequoting moved into rl_filename_completion_function */ + /* rl_completion_matches will check for signals as well to avoid a long + delay while reading a directory. */ matches = rl_completion_matches (text, our_func); + if (RL_SIG_RECEIVED()) + { + _rl_free_match_list (matches); + matches = 0; + RL_CHECK_SIGNALS (); + } return matches; } @@ -1838,10 +1858,8 @@ rl_complete_internal (what_to_do) /* nontrivial_lcd is set if the common prefix adds something to the word being completed. */ nontrivial_lcd = matches && strcmp (text, matches[0]) != 0; -#if 1 if (what_to_do == '!' || what_to_do == '@') tlen = strlen (text); -#endif xfree (text); if (matches == 0) @@ -1875,10 +1893,6 @@ rl_complete_internal (what_to_do) case '!': case '@': /* Insert the first match with proper quoting. */ -#if 0 - if (*matches[0]) - insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); -#else if (what_to_do == TAB) { if (*matches[0]) @@ -1893,7 +1907,6 @@ rl_complete_internal (what_to_do) if (mlen >= tlen) insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); } -#endif /* If there are more matches, ring the bell to indicate. If we are in vi mode, Posix.2 says to not ring the bell. @@ -1929,7 +1942,14 @@ rl_complete_internal (what_to_do) break; case '?': + if (rl_completion_display_matches_hook == 0) + { + _rl_sigcleanup = _rl_complete_sigcleanup; + _rl_sigcleanarg = matches; + } display_matches (matches); + _rl_sigcleanup = 0; + _rl_sigcleanarg = 0; break; default: @@ -1937,6 +1957,7 @@ rl_complete_internal (what_to_do) rl_ding (); FREE (saved_line_buffer); RL_UNSETSTATE(RL_STATE_COMPLETING); + _rl_free_match_list (matches); _rl_reset_completion_state (); return 1; } @@ -1978,6 +1999,8 @@ rl_completion_matches (text, entry_function) const char *text; rl_compentry_func_t *entry_function; { + register int i; + /* Number of slots in match_list. */ int match_list_size; @@ -1995,11 +2018,25 @@ rl_completion_matches (text, entry_function) match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); match_list[1] = (char *)NULL; -#if 0 - _rl_interrupt_immediately++; -#endif while (string = (*entry_function) (text, matches)) { + if (RL_SIG_RECEIVED ()) + { + /* Start at 1 because we don't set matches[0] in this function. + Only free the list members if we're building match list from + rl_filename_completion_function, since we know that doesn't + free the strings it returns. */ + if (entry_function == rl_filename_completion_function) + { + for (i = 1; match_list[i]; i++) + xfree (match_list[i]); + } + xfree (match_list); + match_list = 0; + match_list_size = 0; + RL_CHECK_SIGNALS (); + } + if (matches + 1 == match_list_size) match_list = (char **)xrealloc (match_list, ((match_list_size += 10) + 1) * sizeof (char *)); @@ -2007,10 +2044,6 @@ rl_completion_matches (text, entry_function) match_list[++matches] = string; match_list[matches + 1] = (char *)NULL; } -#if 0 - if (_rl_interrupt_immediately > 0) - _rl_interrupt_immediately--; -#endif /* If there were any matches, then look through them finding out the lowest common denominator. That then becomes match_list[0]. */ diff --git a/lib/readline/complete.c~ b/lib/readline/complete.c~ index 250c69967..151eb80da 100644 --- a/lib/readline/complete.c~ +++ b/lib/readline/complete.c~ @@ -31,6 +31,8 @@ # include #endif +#include + #if defined (HAVE_UNISTD_H) # include #endif /* HAVE_UNISTD_H */ @@ -105,6 +107,8 @@ static int path_isdir PARAMS((const char *)); static char *rl_quote_filename PARAMS((char *, int, char *)); +static void _rl_complete_sigcleanup PARAMS((int, void *)); + static void set_completion_defaults PARAMS((int)); static int get_y_or_n PARAMS((int)); static int _rl_internal_pager PARAMS((int)); @@ -206,7 +210,7 @@ rl_icppfunc_t *rl_directory_completion_hook = (rl_icppfunc_t *)NULL; rl_icppfunc_t *rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL; -rl_icppfunc_t *rl_directory_stat_hook = (rl_icppfunc_t *)NULL; +rl_icppfunc_t *rl_filename_stat_hook = (rl_icppfunc_t *)NULL; /* If non-zero, this is the address of a function to call when reading directory entries from the filesystem for completion and comparing @@ -459,6 +463,15 @@ _rl_reset_completion_state () rl_completion_quote_character = 0; } +static void +_rl_complete_sigcleanup (sig, ptr) + int sig; + void *ptr; +{ + if (sig == SIGINT) /* XXX - for now */ + _rl_free_match_list ((char **)ptr); +} + /* Set default values for readline word completion. These are the variables that application completion functions can change or inspect. */ static void @@ -1060,14 +1073,13 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char) variable rl_attempted_completion_function. */ if (rl_attempted_completion_function) { -#if 0 - _rl_interrupt_immediately++; -#endif matches = (*rl_attempted_completion_function) (text, start, end); -#if 0 - if (_rl_interrupt_immediately > 0) - _rl_interrupt_immediately--; -#endif + if (RL_SIG_RECEIVED()) + { + _rl_free_match_list (matches); + matches = 0; + RL_CHECK_SIGNALS (); + } if (matches || rl_attempted_completion_over) { @@ -1078,7 +1090,15 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char) /* XXX -- filename dequoting moved into rl_filename_completion_function */ + /* rl_completion_matches will check for signals as well to avoid a long + delay while reading a directory. */ matches = rl_completion_matches (text, our_func); + if (RL_SIG_RECEIVED()) + { + _rl_free_match_list (matches); + matches = 0; + RL_CHECK_SIGNALS (); + } return matches; } @@ -1697,8 +1717,8 @@ append_to_match (text, delimiter, quote_char, nontrivial_match) if (rl_filename_completion_desired) { filename = tilde_expand (text); - if (rl_directory_stat_hook) - (*rl_directory_stat_hook) (&filename); + if (rl_filename_stat_hook) + (*rl_filename_stat_hook) (&filename); s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0) ? LSTAT (filename, &finfo) : stat (filename, &finfo); @@ -1838,10 +1858,8 @@ rl_complete_internal (what_to_do) /* nontrivial_lcd is set if the common prefix adds something to the word being completed. */ nontrivial_lcd = matches && strcmp (text, matches[0]) != 0; -#if 1 if (what_to_do == '!' || what_to_do == '@') tlen = strlen (text); -#endif xfree (text); if (matches == 0) @@ -1875,10 +1893,6 @@ rl_complete_internal (what_to_do) case '!': case '@': /* Insert the first match with proper quoting. */ -#if 0 - if (*matches[0]) - insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); -#else if (what_to_do == TAB) { if (*matches[0]) @@ -1893,7 +1907,6 @@ rl_complete_internal (what_to_do) if (mlen >= tlen) insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); } -#endif /* If there are more matches, ring the bell to indicate. If we are in vi mode, Posix.2 says to not ring the bell. @@ -1929,7 +1942,14 @@ rl_complete_internal (what_to_do) break; case '?': + if (rl_completion_display_matches_hook == 0) + { + _rl_sigcleanup = _rl_complete_sigcleanup; + _rl_sigcleanarg = matches; + } display_matches (matches); + _rl_sigcleanup = 0; + _rl_sigcleanarg = 0; break; default: @@ -1937,6 +1957,7 @@ rl_complete_internal (what_to_do) rl_ding (); FREE (saved_line_buffer); RL_UNSETSTATE(RL_STATE_COMPLETING); + _rl_free_match_list (matches); _rl_reset_completion_state (); return 1; } @@ -1961,6 +1982,8 @@ rl_complete_internal (what_to_do) /* */ /***************************************************************/ +extern void _rl_settracefp (FILE *); + /* Return an array of (char *) which is a list of completions for TEXT. If there are no completions, return a NULL pointer. The first entry in the returned array is the substitution for TEXT. @@ -1978,6 +2001,8 @@ rl_completion_matches (text, entry_function) const char *text; rl_compentry_func_t *entry_function; { + register int i; + /* Number of slots in match_list. */ int match_list_size; @@ -1995,11 +2020,25 @@ rl_completion_matches (text, entry_function) match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); match_list[1] = (char *)NULL; -#if 0 - _rl_interrupt_immediately++; -#endif while (string = (*entry_function) (text, matches)) { + if (RL_SIG_RECEIVED ()) + { + /* Start at 1 because we don't set matches[0] in this function. + Only free the list members if we're building match list from + rl_filename_completion_function, since we know that doesn't + free the strings it returns. */ + if (entry_function == rl_filename_completion_function) + { + for (i = 1; match_list[i]; i++) + xfree (match_list[i]); + } + xfree (match_list); + match_list = 0; + match_list_size = 0; + RL_CHECK_SIGNALS (); + } + if (matches + 1 == match_list_size) match_list = (char **)xrealloc (match_list, ((match_list_size += 10) + 1) * sizeof (char *)); @@ -2007,10 +2046,6 @@ rl_completion_matches (text, entry_function) match_list[++matches] = string; match_list[matches + 1] = (char *)NULL; } -#if 0 - if (_rl_interrupt_immediately > 0) - _rl_interrupt_immediately--; -#endif /* If there were any matches, then look through them finding out the lowest common denominator. That then becomes match_list[0]. */ diff --git a/lib/readline/doc/hsuser.texi b/lib/readline/doc/hsuser.texi index c5842bcaf..c962ad948 100644 --- a/lib/readline/doc/hsuser.texi +++ b/lib/readline/doc/hsuser.texi @@ -94,7 +94,7 @@ If @env{HISTFILE} is unset, or if the history file is unwritable, the history is not saved. After saving the history, the history file is truncated to contain no more than @env{$HISTFILESIZE} lines. -If @env{HISTFILESIZE} is not set, or set to null, a non-numeric value, or +If @env{HISTFILESIZE} is unset, or set to null, a non-numeric value, or a numeric value less than zero, the history file is not truncated. If the @env{HISTTIMEFORMAT} is set, the time stamp information diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h index 535696916..05f9c8a90 100644 --- a/lib/readline/rlprivate.h +++ b/lib/readline/rlprivate.h @@ -42,6 +42,9 @@ if (_rl_caught_signal) _rl_signal_handler (_rl_caught_signal); \ } while (0) +#define RL_SIG_RECEIVED() (_rl_caught_signal != 0) +#define RL_SIGINT_RECEIVED() (_rl_caught_signal == SIGINT) + /************************************************************************* * * * Global structs undocumented in texinfo manual and not in readline.h * @@ -158,6 +161,8 @@ typedef struct __rl_callback_generic_arg typedef int _rl_callback_func_t PARAMS((_rl_callback_generic_arg *)); +typedef void _rl_sigcleanup_func_t PARAMS((int, void *)); + /************************************************************************* * * * Global functions undocumented in texinfo manual and not in readline.h * @@ -476,6 +481,9 @@ extern _rl_search_cxt *_rl_nscxt; extern int _rl_interrupt_immediately; extern int volatile _rl_caught_signal; +extern _rl_sigcleanup_func_t *_rl_sigcleanup; +extern void *_rl_sigcleanarg; + extern int _rl_echoctl; extern int _rl_intr_char; diff --git a/lib/readline/rlprivate.h~ b/lib/readline/rlprivate.h~ new file mode 100644 index 000000000..c68e17611 --- /dev/null +++ b/lib/readline/rlprivate.h~ @@ -0,0 +1,521 @@ +/* rlprivate.h -- functions and variables global to the readline library, + but not intended for use by applications. */ + +/* Copyright (C) 1999-2011 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library (Readline), a library + for reading lines of text with interactive input and history editing. + + Readline is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Readline is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Readline. If not, see . +*/ + +#if !defined (_RL_PRIVATE_H_) +#define _RL_PRIVATE_H_ + +#include "rlconf.h" /* for VISIBLE_STATS */ +#include "rlstdc.h" +#include "posixjmp.h" /* defines procenv_t */ + +/************************************************************************* + * * + * Convenience definitions * + * * + *************************************************************************/ + +#define EMACS_MODE() (rl_editing_mode == emacs_mode) +#define VI_COMMAND_MODE() (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) +#define VI_INSERT_MODE() (rl_editing_mode == vi_mode && _rl_keymap == vi_insertion_keymap) + +#define RL_CHECK_SIGNALS() \ + do { \ + if (_rl_caught_signal) _rl_signal_handler (_rl_caught_signal); \ + } while (0) + +#define RL_SIG_RECEIVED() (_rl_caught_signal != 0) +#define RL_SIGINT_RECEIVED() (_rl_caught_signal == SIGINT) + +/************************************************************************* + * * + * Global structs undocumented in texinfo manual and not in readline.h * + * * + *************************************************************************/ +/* search types */ +#define RL_SEARCH_ISEARCH 0x01 /* incremental search */ +#define RL_SEARCH_NSEARCH 0x02 /* non-incremental search */ +#define RL_SEARCH_CSEARCH 0x04 /* intra-line char search */ + +/* search flags */ +#define SF_REVERSE 0x01 +#define SF_FOUND 0x02 +#define SF_FAILED 0x04 +#define SF_CHGKMAP 0x08 + +typedef struct __rl_search_context +{ + int type; + int sflags; + + char *search_string; + int search_string_index; + int search_string_size; + + char **lines; + char *allocated_line; + int hlen; + int hindex; + + int save_point; + int save_mark; + int save_line; + int last_found_line; + char *prev_line_found; + + UNDO_LIST *save_undo_list; + + Keymap keymap; /* used when dispatching commands in search string */ + Keymap okeymap; /* original keymap */ + + int history_pos; + int direction; + + int prevc; + int lastc; +#if defined (HANDLE_MULTIBYTE) + char mb[MB_LEN_MAX]; + char pmb[MB_LEN_MAX]; +#endif + + char *sline; + int sline_len; + int sline_index; + + char *search_terminators; +} _rl_search_cxt; + +/* Callback data for reading numeric arguments */ +#define NUM_SAWMINUS 0x01 +#define NUM_SAWDIGITS 0x02 +#define NUM_READONE 0x04 + +typedef int _rl_arg_cxt; + +/* A context for reading key sequences longer than a single character when + using the callback interface. */ +#define KSEQ_DISPATCHED 0x01 +#define KSEQ_SUBSEQ 0x02 +#define KSEQ_RECURSIVE 0x04 + +typedef struct __rl_keyseq_context +{ + int flags; + int subseq_arg; + int subseq_retval; /* XXX */ + Keymap dmap; + + Keymap oldmap; + int okey; + struct __rl_keyseq_context *ocxt; + int childval; +} _rl_keyseq_cxt; + +/* vi-mode commands that use result of motion command to define boundaries */ +#define VIM_DELETE 0x01 +#define VIM_CHANGE 0x02 +#define VIM_YANK 0x04 + +/* various states for vi-mode commands that use motion commands. reflects + RL_READLINE_STATE */ +#define VMSTATE_READ 0x01 +#define VMSTATE_NUMARG 0x02 + +typedef struct __rl_vimotion_context +{ + int op; + int state; + int flags; /* reserved */ + _rl_arg_cxt ncxt; + int numeric_arg; + int start, end; /* rl_point, rl_end */ + int key, motion; /* initial key, motion command */ +} _rl_vimotion_cxt; + +/* fill in more as needed */ +/* `Generic' callback data and functions */ +typedef struct __rl_callback_generic_arg +{ + int count; + int i1, i2; + /* add here as needed */ +} _rl_callback_generic_arg; + +typedef int _rl_callback_func_t PARAMS((_rl_callback_generic_arg *)); + +typedef void _rl_sigcleanup_func_t PARAMS((int, void *)); + +/************************************************************************* + * * + * Global functions undocumented in texinfo manual and not in readline.h * + * * + *************************************************************************/ + +/************************************************************************* + * * + * Global variables undocumented in texinfo manual and not in readline.h * + * * + *************************************************************************/ + +/* complete.c */ +extern int rl_complete_with_tilde_expansion; +#if defined (VISIBLE_STATS) +extern int rl_visible_stats; +#endif /* VISIBLE_STATS */ + +/* readline.c */ +extern int rl_line_buffer_len; +extern int rl_arg_sign; +extern int rl_visible_prompt_length; +extern int rl_key_sequence_length; +extern int rl_byte_oriented; + +/* display.c */ +extern int rl_display_fixed; + +/* parens.c */ +extern int rl_blink_matching_paren; + +/************************************************************************* + * * + * Global functions and variables unsed and undocumented * + * * + *************************************************************************/ + +/* kill.c */ +extern int rl_set_retained_kills PARAMS((int)); + +/* terminal.c */ +extern void _rl_set_screen_size PARAMS((int, int)); + +/* undo.c */ +extern int _rl_fix_last_undo_of_type PARAMS((int, int, int)); + +/* util.c */ +extern char *_rl_savestring PARAMS((const char *)); + +/************************************************************************* + * * + * Functions and variables private to the readline library * + * * + *************************************************************************/ + +/* NOTE: Functions and variables prefixed with `_rl_' are + pseudo-global: they are global so they can be shared + between files in the readline library, but are not intended + to be visible to readline callers. */ + +/************************************************************************* + * Undocumented private functions * + *************************************************************************/ + +#if defined(READLINE_CALLBACKS) + +/* readline.c */ +extern void readline_internal_setup PARAMS((void)); +extern char *readline_internal_teardown PARAMS((int)); +extern int readline_internal_char PARAMS((void)); + +extern _rl_keyseq_cxt *_rl_keyseq_cxt_alloc PARAMS((void)); +extern void _rl_keyseq_cxt_dispose PARAMS((_rl_keyseq_cxt *)); +extern void _rl_keyseq_chain_dispose PARAMS((void)); + +extern int _rl_dispatch_callback PARAMS((_rl_keyseq_cxt *)); + +/* callback.c */ +extern _rl_callback_generic_arg *_rl_callback_data_alloc PARAMS((int)); +extern void _rl_callback_data_dispose PARAMS((_rl_callback_generic_arg *)); + +#endif /* READLINE_CALLBACKS */ + +/* bind.c */ + +/* complete.c */ +extern void _rl_reset_completion_state PARAMS((void)); +extern char _rl_find_completion_word PARAMS((int *, int *)); +extern void _rl_free_match_list PARAMS((char **)); + +/* display.c */ +extern char *_rl_strip_prompt PARAMS((char *)); +extern void _rl_move_cursor_relative PARAMS((int, const char *)); +extern void _rl_move_vert PARAMS((int)); +extern void _rl_save_prompt PARAMS((void)); +extern void _rl_restore_prompt PARAMS((void)); +extern char *_rl_make_prompt_for_search PARAMS((int)); +extern void _rl_erase_at_end_of_line PARAMS((int)); +extern void _rl_clear_to_eol PARAMS((int)); +extern void _rl_clear_screen PARAMS((void)); +extern void _rl_update_final PARAMS((void)); +extern void _rl_redisplay_after_sigwinch PARAMS((void)); +extern void _rl_clean_up_for_exit PARAMS((void)); +extern void _rl_erase_entire_line PARAMS((void)); +extern int _rl_current_display_line PARAMS((void)); + +/* input.c */ +extern int _rl_any_typein PARAMS((void)); +extern int _rl_input_available PARAMS((void)); +extern int _rl_input_queued PARAMS((int)); +extern void _rl_insert_typein PARAMS((int)); +extern int _rl_unget_char PARAMS((int)); +extern int _rl_pushed_input_available PARAMS((void)); + +/* isearch.c */ +extern _rl_search_cxt *_rl_scxt_alloc PARAMS((int, int)); +extern void _rl_scxt_dispose PARAMS((_rl_search_cxt *, int)); + +extern int _rl_isearch_dispatch PARAMS((_rl_search_cxt *, int)); +extern int _rl_isearch_callback PARAMS((_rl_search_cxt *)); + +extern int _rl_search_getchar PARAMS((_rl_search_cxt *)); + +/* macro.c */ +extern void _rl_with_macro_input PARAMS((char *)); +extern int _rl_next_macro_key PARAMS((void)); +extern void _rl_push_executing_macro PARAMS((void)); +extern void _rl_pop_executing_macro PARAMS((void)); +extern void _rl_add_macro_char PARAMS((int)); +extern void _rl_kill_kbd_macro PARAMS((void)); + +/* misc.c */ +extern int _rl_arg_overflow PARAMS((void)); +extern void _rl_arg_init PARAMS((void)); +extern int _rl_arg_getchar PARAMS((void)); +extern int _rl_arg_callback PARAMS((_rl_arg_cxt)); +extern void _rl_reset_argument PARAMS((void)); + +extern void _rl_start_using_history PARAMS((void)); +extern int _rl_free_saved_history_line PARAMS((void)); +extern void _rl_set_insert_mode PARAMS((int, int)); + +extern void _rl_revert_all_lines PARAMS((void)); + +/* nls.c */ +extern int _rl_init_eightbit PARAMS((void)); + +/* parens.c */ +extern void _rl_enable_paren_matching PARAMS((int)); + +/* readline.c */ +extern void _rl_init_line_state PARAMS((void)); +extern void _rl_set_the_line PARAMS((void)); +extern int _rl_dispatch PARAMS((int, Keymap)); +extern int _rl_dispatch_subseq PARAMS((int, Keymap, int)); +extern void _rl_internal_char_cleanup PARAMS((void)); + +/* rltty.c */ +extern int _rl_disable_tty_signals PARAMS((void)); +extern int _rl_restore_tty_signals PARAMS((void)); + +/* search.c */ +extern int _rl_nsearch_callback PARAMS((_rl_search_cxt *)); + +/* signals.c */ +extern void _rl_signal_handler PARAMS((int)); + +extern void _rl_block_sigint PARAMS((void)); +extern void _rl_release_sigint PARAMS((void)); +extern void _rl_block_sigwinch PARAMS((void)); +extern void _rl_release_sigwinch PARAMS((void)); + +/* terminal.c */ +extern void _rl_get_screen_size PARAMS((int, int)); +extern void _rl_sigwinch_resize_terminal PARAMS((void)); +extern int _rl_init_terminal_io PARAMS((const char *)); +#ifdef _MINIX +extern void _rl_output_character_function PARAMS((int)); +#else +extern int _rl_output_character_function PARAMS((int)); +#endif +extern void _rl_output_some_chars PARAMS((const char *, int)); +extern int _rl_backspace PARAMS((int)); +extern void _rl_enable_meta_key PARAMS((void)); +extern void _rl_disable_meta_key PARAMS((void)); +extern void _rl_control_keypad PARAMS((int)); +extern void _rl_set_cursor PARAMS((int, int)); + +/* text.c */ +extern void _rl_fix_point PARAMS((int)); +extern int _rl_replace_text PARAMS((const char *, int, int)); +extern int _rl_forward_char_internal PARAMS((int)); +extern int _rl_insert_char PARAMS((int, int)); +extern int _rl_overwrite_char PARAMS((int, int)); +extern int _rl_overwrite_rubout PARAMS((int, int)); +extern int _rl_rubout_char PARAMS((int, int)); +#if defined (HANDLE_MULTIBYTE) +extern int _rl_char_search_internal PARAMS((int, int, char *, int)); +#else +extern int _rl_char_search_internal PARAMS((int, int, int)); +#endif +extern int _rl_set_mark_at_pos PARAMS((int)); + +/* undo.c */ +extern UNDO_LIST *_rl_copy_undo_entry PARAMS((UNDO_LIST *)); +extern UNDO_LIST *_rl_copy_undo_list PARAMS((UNDO_LIST *)); + +/* util.c */ +#if defined (USE_VARARGS) && defined (PREFER_STDARG) +extern void _rl_ttymsg (const char *, ...) __attribute__((__format__ (printf, 1, 2))); +extern void _rl_errmsg (const char *, ...) __attribute__((__format__ (printf, 1, 2))); +extern void _rl_trace (const char *, ...) __attribute__((__format__ (printf, 1, 2))); +#else +extern void _rl_ttymsg (); +extern void _rl_errmsg (); +extern void _rl_trace (); +#endif + +extern int _rl_tropen PARAMS((void)); + +extern int _rl_abort_internal PARAMS((void)); +extern int _rl_null_function PARAMS((int, int)); +extern char *_rl_strindex PARAMS((const char *, const char *)); +extern int _rl_qsort_string_compare PARAMS((char **, char **)); +extern int (_rl_uppercase_p) PARAMS((int)); +extern int (_rl_lowercase_p) PARAMS((int)); +extern int (_rl_pure_alphabetic) PARAMS((int)); +extern int (_rl_digit_p) PARAMS((int)); +extern int (_rl_to_lower) PARAMS((int)); +extern int (_rl_to_upper) PARAMS((int)); +extern int (_rl_digit_value) PARAMS((int)); + +/* vi_mode.c */ +extern void _rl_vi_initialize_line PARAMS((void)); +extern void _rl_vi_reset_last PARAMS((void)); +extern void _rl_vi_set_last PARAMS((int, int, int)); +extern int _rl_vi_textmod_command PARAMS((int)); +extern void _rl_vi_done_inserting PARAMS((void)); +extern int _rl_vi_domove_callback PARAMS((_rl_vimotion_cxt *)); + +/************************************************************************* + * Undocumented private variables * + *************************************************************************/ + +/* bind.c */ +extern const char * const _rl_possible_control_prefixes[]; +extern const char * const _rl_possible_meta_prefixes[]; + +/* callback.c */ +extern _rl_callback_func_t *_rl_callback_func; +extern _rl_callback_generic_arg *_rl_callback_data; + +/* complete.c */ +extern int _rl_complete_show_all; +extern int _rl_complete_show_unmodified; +extern int _rl_complete_mark_directories; +extern int _rl_complete_mark_symlink_dirs; +extern int _rl_completion_prefix_display_length; +extern int _rl_completion_columns; +extern int _rl_print_completions_horizontally; +extern int _rl_completion_case_fold; +extern int _rl_completion_case_map; +extern int _rl_match_hidden_files; +extern int _rl_page_completions; +extern int _rl_skip_completed_text; +extern int _rl_menu_complete_prefix_first; + +/* display.c */ +extern int _rl_vis_botlin; +extern int _rl_last_c_pos; +extern int _rl_suppress_redisplay; +extern int _rl_want_redisplay; + +/* isearch.c */ +extern char *_rl_isearch_terminators; + +extern _rl_search_cxt *_rl_iscxt; + +/* macro.c */ +extern char *_rl_executing_macro; + +/* misc.c */ +extern int _rl_history_preserve_point; +extern int _rl_history_saved_point; + +extern _rl_arg_cxt _rl_argcxt; + +/* nls.c */ +extern int _rl_utf8locale; + +/* readline.c */ +extern int _rl_echoing_p; +extern int _rl_horizontal_scroll_mode; +extern int _rl_mark_modified_lines; +extern int _rl_bell_preference; +extern int _rl_meta_flag; +extern int _rl_convert_meta_chars_to_ascii; +extern int _rl_output_meta_chars; +extern int _rl_bind_stty_chars; +extern int _rl_revert_all_at_newline; +extern int _rl_echo_control_chars; +extern char *_rl_comment_begin; +extern unsigned char _rl_parsing_conditionalized_out; +extern Keymap _rl_keymap; +extern FILE *_rl_in_stream; +extern FILE *_rl_out_stream; +extern int _rl_last_command_was_kill; +extern int _rl_eof_char; +extern procenv_t _rl_top_level; +extern _rl_keyseq_cxt *_rl_kscxt; + +/* search.c */ +extern _rl_search_cxt *_rl_nscxt; + +/* signals.c */ +extern int _rl_interrupt_immediately; +extern int volatile _rl_caught_signal; + +extern _rl_sigcleanup_func_t *_rl_sigcleanup; +extern void *rl_sigcleanarg; + +extern int _rl_echoctl; + +extern int _rl_intr_char; +extern int _rl_quit_char; +extern int _rl_susp_char; + +/* terminal.c */ +extern int _rl_enable_keypad; +extern int _rl_enable_meta; +extern char *_rl_term_clreol; +extern char *_rl_term_clrpag; +extern char *_rl_term_im; +extern char *_rl_term_ic; +extern char *_rl_term_ei; +extern char *_rl_term_DC; +extern char *_rl_term_up; +extern char *_rl_term_dc; +extern char *_rl_term_cr; +extern char *_rl_term_IC; +extern char *_rl_term_forward_char; +extern int _rl_screenheight; +extern int _rl_screenwidth; +extern int _rl_screenchars; +extern int _rl_terminal_can_insert; +extern int _rl_term_autowrap; + +/* undo.c */ +extern int _rl_doing_an_undo; +extern int _rl_undo_group_level; + +/* vi_mode.c */ +extern int _rl_vi_last_command; +extern _rl_vimotion_cxt *_rl_vimvcxt; + +#endif /* _RL_PRIVATE_H_ */ diff --git a/lib/readline/signals.c b/lib/readline/signals.c index 6b59b7281..29b75625f 100644 --- a/lib/readline/signals.c +++ b/lib/readline/signals.c @@ -126,6 +126,9 @@ static sighandler_cxt old_tstp, old_ttou, old_ttin; static sighandler_cxt old_winch; #endif +_rl_sigcleanup_func_t *_rl_sigcleanup; +void *_rl_sigcleanarg; + /* Readline signal handler functions. */ /* Called from RL_CHECK_SIGNALS() macro */ @@ -184,6 +187,15 @@ _rl_handle_signal (sig) rl_set_sighandler (sig, SIG_IGN, &dummy_cxt); #endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */ + /* If there's a sig cleanup function registered, call it and `deregister' + the cleanup function to avoid multiple calls */ + if (_rl_sigcleanup) + { + (*_rl_sigcleanup) (sig, _rl_sigcleanarg); + _rl_sigcleanup = 0; + _rl_sigcleanarg = 0; + } + switch (sig) { case SIGINT: diff --git a/lib/readline/signals.c~ b/lib/readline/signals.c~ index b34002fd1..29b75625f 100644 --- a/lib/readline/signals.c~ +++ b/lib/readline/signals.c~ @@ -126,6 +126,9 @@ static sighandler_cxt old_tstp, old_ttou, old_ttin; static sighandler_cxt old_winch; #endif +_rl_sigcleanup_func_t *_rl_sigcleanup; +void *_rl_sigcleanarg; + /* Readline signal handler functions. */ /* Called from RL_CHECK_SIGNALS() macro */ @@ -146,15 +149,7 @@ static RETSIGTYPE rl_signal_handler (sig) int sig; { -#if 0 -#if defined (SIGWINCH) - if (_rl_interrupt_immediately || (sig != SIGWINCH && RL_ISSTATE(RL_STATE_CALLBACK))) -#else - if (_rl_interrupt_immediately || RL_ISSTATE(RL_STATE_CALLBACK)) -#endif -#else if (_rl_interrupt_immediately) -#endif { _rl_interrupt_immediately = 0; _rl_handle_signal (sig); @@ -192,6 +187,15 @@ _rl_handle_signal (sig) rl_set_sighandler (sig, SIG_IGN, &dummy_cxt); #endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */ + /* If there's a sig cleanup function registered, call it and `deregister' + the cleanup function to avoid multiple calls */ + if (_rl_sigcleanup) + { + (*_rl_sigcleanup) (sig, _rl_sigcleanarg); + _rl_sigcleanup = 0; + _rl_sigcleanarg = 0; + } + switch (sig) { case SIGINT: diff --git a/lib/readline/util.c b/lib/readline/util.c index 6c68ad8d4..6bb68275d 100644 --- a/lib/readline/util.c +++ b/lib/readline/util.c @@ -523,4 +523,10 @@ _rl_trclose () return r; } +void +_rl_settracefp (fp) + FILE *fp; +{ + _rl_tracefp = fp; +} #endif diff --git a/lib/readline/util.c~ b/lib/readline/util.c~ new file mode 100644 index 000000000..6c68ad8d4 --- /dev/null +++ b/lib/readline/util.c~ @@ -0,0 +1,526 @@ +/* util.c -- readline utility functions */ + +/* Copyright (C) 1987-2010 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library (Readline), a library + for reading lines of text with interactive input and history editing. + + Readline is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Readline is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Readline. If not, see . +*/ + +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include +#include "posixjmp.h" + +#if defined (HAVE_UNISTD_H) +# include /* for _POSIX_VERSION */ +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" +#include "rlmbutil.h" + +#if defined (TIOCSTAT_IN_SYS_IOCTL) +# include +#endif /* TIOCSTAT_IN_SYS_IOCTL */ + +/* Some standard library routines. */ +#include "readline.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +/* **************************************************************** */ +/* */ +/* Utility Functions */ +/* */ +/* **************************************************************** */ + +/* Return 0 if C is not a member of the class of characters that belong + in words, or 1 if it is. */ + +int _rl_allow_pathname_alphabetic_chars = 0; +static const char * const pathname_alphabetic_chars = "/-_=~.#$"; + +int +rl_alphabetic (c) + int c; +{ + if (ALPHABETIC (c)) + return (1); + + return (_rl_allow_pathname_alphabetic_chars && + strchr (pathname_alphabetic_chars, c) != NULL); +} + +#if defined (HANDLE_MULTIBYTE) +int +_rl_walphabetic (wchar_t wc) +{ + int c; + + if (iswalnum (wc)) + return (1); + + c = wc & 0177; + return (_rl_allow_pathname_alphabetic_chars && + strchr (pathname_alphabetic_chars, c) != NULL); +} +#endif + +/* How to abort things. */ +int +_rl_abort_internal () +{ + rl_ding (); + rl_clear_message (); + _rl_reset_argument (); + rl_clear_pending_input (); + + RL_UNSETSTATE (RL_STATE_MACRODEF); + while (rl_executing_macro) + _rl_pop_executing_macro (); + + rl_last_func = (rl_command_func_t *)NULL; + longjmp (_rl_top_level, 1); + return (0); +} + +int +rl_abort (count, key) + int count, key; +{ + return (_rl_abort_internal ()); +} + +int +_rl_null_function (count, key) + int count, key; +{ + return 0; +} + +int +rl_tty_status (count, key) + int count, key; +{ +#if defined (TIOCSTAT) + ioctl (1, TIOCSTAT, (char *)0); + rl_refresh_line (count, key); +#else + rl_ding (); +#endif + return 0; +} + +/* Return a copy of the string between FROM and TO. + FROM is inclusive, TO is not. */ +char * +rl_copy_text (from, to) + int from, to; +{ + register int length; + char *copy; + + /* Fix it if the caller is confused. */ + if (from > to) + SWAP (from, to); + + length = to - from; + copy = (char *)xmalloc (1 + length); + strncpy (copy, rl_line_buffer + from, length); + copy[length] = '\0'; + return (copy); +} + +/* Increase the size of RL_LINE_BUFFER until it has enough space to hold + LEN characters. */ +void +rl_extend_line_buffer (len) + int len; +{ + while (len >= rl_line_buffer_len) + { + rl_line_buffer_len += DEFAULT_BUFFER_SIZE; + rl_line_buffer = (char *)xrealloc (rl_line_buffer, rl_line_buffer_len); + } + + _rl_set_the_line (); +} + + +/* A function for simple tilde expansion. */ +int +rl_tilde_expand (ignore, key) + int ignore, key; +{ + register int start, end; + char *homedir, *temp; + int len; + + end = rl_point; + start = end - 1; + + if (rl_point == rl_end && rl_line_buffer[rl_point] == '~') + { + homedir = tilde_expand ("~"); + _rl_replace_text (homedir, start, end); + xfree (homedir); + return (0); + } + else if (rl_line_buffer[start] != '~') + { + for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--) + ; + start++; + } + + end = start; + do + end++; + while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end); + + if (whitespace (rl_line_buffer[end]) || end >= rl_end) + end--; + + /* If the first character of the current word is a tilde, perform + tilde expansion and insert the result. If not a tilde, do + nothing. */ + if (rl_line_buffer[start] == '~') + { + len = end - start + 1; + temp = (char *)xmalloc (len + 1); + strncpy (temp, rl_line_buffer + start, len); + temp[len] = '\0'; + homedir = tilde_expand (temp); + xfree (temp); + + _rl_replace_text (homedir, start, end); + xfree (homedir); + } + + return (0); +} + +#if defined (USE_VARARGS) +void +#if defined (PREFER_STDARG) +_rl_ttymsg (const char *format, ...) +#else +_rl_ttymsg (va_alist) + va_dcl +#endif +{ + va_list args; +#if defined (PREFER_VARARGS) + char *format; +#endif + +#if defined (PREFER_STDARG) + va_start (args, format); +#else + va_start (args); + format = va_arg (args, char *); +#endif + + fprintf (stderr, "readline: "); + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + fflush (stderr); + + va_end (args); + + rl_forced_update_display (); +} + +void +#if defined (PREFER_STDARG) +_rl_errmsg (const char *format, ...) +#else +_rl_errmsg (va_alist) + va_dcl +#endif +{ + va_list args; +#if defined (PREFER_VARARGS) + char *format; +#endif + +#if defined (PREFER_STDARG) + va_start (args, format); +#else + va_start (args); + format = va_arg (args, char *); +#endif + + fprintf (stderr, "readline: "); + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + fflush (stderr); + + va_end (args); +} + +#else /* !USE_VARARGS */ +void +_rl_ttymsg (format, arg1, arg2) + char *format; +{ + fprintf (stderr, "readline: "); + fprintf (stderr, format, arg1, arg2); + fprintf (stderr, "\n"); + + rl_forced_update_display (); +} + +void +_rl_errmsg (format, arg1, arg2) + char *format; +{ + fprintf (stderr, "readline: "); + fprintf (stderr, format, arg1, arg2); + fprintf (stderr, "\n"); +} +#endif /* !USE_VARARGS */ + +/* **************************************************************** */ +/* */ +/* String Utility Functions */ +/* */ +/* **************************************************************** */ + +/* Determine if s2 occurs in s1. If so, return a pointer to the + match in s1. The compare is case insensitive. */ +char * +_rl_strindex (s1, s2) + register const char *s1, *s2; +{ + register int i, l, len; + + for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++) + if (_rl_strnicmp (s1 + i, s2, l) == 0) + return ((char *) (s1 + i)); + return ((char *)NULL); +} + +#ifndef HAVE_STRPBRK +/* Find the first occurrence in STRING1 of any character from STRING2. + Return a pointer to the character in STRING1. */ +char * +_rl_strpbrk (string1, string2) + const char *string1, *string2; +{ + register const char *scan; +#if defined (HANDLE_MULTIBYTE) + mbstate_t ps; + register int i, v; + + memset (&ps, 0, sizeof (mbstate_t)); +#endif + + for (; *string1; string1++) + { + for (scan = string2; *scan; scan++) + { + if (*string1 == *scan) + return ((char *)string1); + } +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + v = _rl_get_char_len (string1, &ps); + if (v > 1) + string1 += v - 1; /* -1 to account for auto-increment in loop */ + } +#endif + } + return ((char *)NULL); +} +#endif + +#if !defined (HAVE_STRCASECMP) +/* Compare at most COUNT characters from string1 to string2. Case + doesn't matter (strncasecmp). */ +int +_rl_strnicmp (string1, string2, count) + char *string1, *string2; + int count; +{ + register char *s1, *s2; + int d; + + if (count <= 0 || (string1 == string2)) + return 0; + + s1 = string1; + s2 = string2; + do + { + d = _rl_to_lower (*s1) - _rl_to_lower (*s2); /* XXX - cast to unsigned char? */ + if (d != 0) + return d; + if (*s1++ == '\0') + break; + s2++; + } + while (--count != 0) + + return (0); +} + +/* strcmp (), but caseless (strcasecmp). */ +int +_rl_stricmp (string1, string2) + char *string1, *string2; +{ + register char *s1, *s2; + int d; + + s1 = string1; + s2 = string2; + + if (s1 == s2) + return 0; + + while ((d = _rl_to_lower (*s1) - _rl_to_lower (*s2)) == 0) + { + if (*s1++ == '\0') + return 0; + s2++; + } + + return (d); +} +#endif /* !HAVE_STRCASECMP */ + +/* Stupid comparison routine for qsort () ing strings. */ +int +_rl_qsort_string_compare (s1, s2) + char **s1, **s2; +{ +#if defined (HAVE_STRCOLL) + return (strcoll (*s1, *s2)); +#else + int result; + + result = **s1 - **s2; + if (result == 0) + result = strcmp (*s1, *s2); + + return result; +#endif +} + +/* Function equivalents for the macros defined in chardefs.h. */ +#define FUNCTION_FOR_MACRO(f) int (f) (c) int c; { return f (c); } + +FUNCTION_FOR_MACRO (_rl_digit_p) +FUNCTION_FOR_MACRO (_rl_digit_value) +FUNCTION_FOR_MACRO (_rl_lowercase_p) +FUNCTION_FOR_MACRO (_rl_pure_alphabetic) +FUNCTION_FOR_MACRO (_rl_to_lower) +FUNCTION_FOR_MACRO (_rl_to_upper) +FUNCTION_FOR_MACRO (_rl_uppercase_p) + +/* A convenience function, to force memory deallocation to be performed + by readline. DLLs on Windows apparently require this. */ +void +rl_free (mem) + void *mem; +{ + if (mem) + free (mem); +} + +/* Backwards compatibility, now that savestring has been removed from + all `public' readline header files. */ +#undef _rl_savestring +char * +_rl_savestring (s) + const char *s; +{ + return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s))); +} + +#if defined (USE_VARARGS) +static FILE *_rl_tracefp; + +void +#if defined (PREFER_STDARG) +_rl_trace (const char *format, ...) +#else +_rl_trace (va_alist) + va_dcl +#endif +{ + va_list args; +#if defined (PREFER_VARARGS) + char *format; +#endif + +#if defined (PREFER_STDARG) + va_start (args, format); +#else + va_start (args); + format = va_arg (args, char *); +#endif + + if (_rl_tracefp == 0) + _rl_tropen (); + vfprintf (_rl_tracefp, format, args); + fprintf (_rl_tracefp, "\n"); + fflush (_rl_tracefp); + + va_end (args); +} + +int +_rl_tropen () +{ + char fnbuf[128]; + + if (_rl_tracefp) + fclose (_rl_tracefp); + sprintf (fnbuf, "/var/tmp/rltrace.%ld", getpid()); + unlink(fnbuf); + _rl_tracefp = fopen (fnbuf, "w+"); + return _rl_tracefp != 0; +} + +int +_rl_trclose () +{ + int r; + + r = fclose (_rl_tracefp); + _rl_tracefp = 0; + return r; +} + +#endif diff --git a/lib/readline/vi_keymap.c b/lib/readline/vi_keymap.c index ba5a27ba6..60c925d93 100644 --- a/lib/readline/vi_keymap.c +++ b/lib/readline/vi_keymap.c @@ -309,7 +309,6 @@ KEYMAP_ENTRY_ARRAY vi_movement_keymap = { #endif /* KEYMAP_SIZE > 128 */ }; - KEYMAP_ENTRY_ARRAY vi_insertion_keymap = { /* The regular control keys come first. */ { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */ diff --git a/lib/readline/vi_keymap.c~ b/lib/readline/vi_keymap.c~ new file mode 100644 index 000000000..ba5a27ba6 --- /dev/null +++ b/lib/readline/vi_keymap.c~ @@ -0,0 +1,876 @@ +/* vi_keymap.c -- the keymap for vi_mode in readline (). */ + +/* Copyright (C) 1987-2009 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library (Readline), a library + for reading lines of text with interactive input and history editing. + + Readline is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Readline is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Readline. If not, see . +*/ + +#if !defined (BUFSIZ) +#include +#endif /* !BUFSIZ */ + +#include "readline.h" + +#if 0 +extern KEYMAP_ENTRY_ARRAY vi_escape_keymap; +#endif + +/* The keymap arrays for handling vi mode. */ +KEYMAP_ENTRY_ARRAY vi_movement_keymap = { + /* The regular control keys come first. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */ + { ISFUNC, rl_vi_eof_maybe }, /* Control-d */ + { ISFUNC, rl_emacs_editing_mode }, /* Control-e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-f */ + { ISFUNC, rl_abort }, /* Control-g */ + { ISFUNC, rl_backward_char }, /* Control-h */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-i */ + { ISFUNC, rl_newline }, /* Control-j */ + { ISFUNC, rl_kill_line }, /* Control-k */ + { ISFUNC, rl_clear_screen }, /* Control-l */ + { ISFUNC, rl_newline }, /* Control-m */ + { ISFUNC, rl_get_next_history }, /* Control-n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */ + { ISFUNC, rl_get_previous_history }, /* Control-p */ + { ISFUNC, rl_quoted_insert }, /* Control-q */ + { ISFUNC, rl_reverse_search_history }, /* Control-r */ + { ISFUNC, rl_forward_search_history }, /* Control-s */ + { ISFUNC, rl_transpose_chars }, /* Control-t */ + { ISFUNC, rl_unix_line_discard }, /* Control-u */ + { ISFUNC, rl_quoted_insert }, /* Control-v */ + { ISFUNC, rl_unix_word_rubout }, /* Control-w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-x */ + { ISFUNC, rl_yank }, /* Control-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */ + + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-[ */ /* vi_escape_keymap */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */ + { ISFUNC, rl_vi_undo }, /* Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, rl_forward_char }, /* SPACE */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ! */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* " */ + { ISFUNC, rl_insert_comment }, /* # */ + { ISFUNC, rl_end_of_line }, /* $ */ + { ISFUNC, rl_vi_match }, /* % */ + { ISFUNC, rl_vi_tilde_expand }, /* & */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ' */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ( */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ) */ + { ISFUNC, rl_vi_complete }, /* * */ + { ISFUNC, rl_get_next_history}, /* + */ + { ISFUNC, rl_vi_char_search }, /* , */ + { ISFUNC, rl_get_previous_history }, /* - */ + { ISFUNC, rl_vi_redo }, /* . */ + { ISFUNC, rl_vi_search }, /* / */ + + /* Regular digits. */ + { ISFUNC, rl_beg_of_line }, /* 0 */ + { ISFUNC, rl_vi_arg_digit }, /* 1 */ + { ISFUNC, rl_vi_arg_digit }, /* 2 */ + { ISFUNC, rl_vi_arg_digit }, /* 3 */ + { ISFUNC, rl_vi_arg_digit }, /* 4 */ + { ISFUNC, rl_vi_arg_digit }, /* 5 */ + { ISFUNC, rl_vi_arg_digit }, /* 6 */ + { ISFUNC, rl_vi_arg_digit }, /* 7 */ + { ISFUNC, rl_vi_arg_digit }, /* 8 */ + { ISFUNC, rl_vi_arg_digit }, /* 9 */ + + /* A little more punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* : */ + { ISFUNC, rl_vi_char_search }, /* ; */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* < */ + { ISFUNC, rl_vi_complete }, /* = */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* > */ + { ISFUNC, rl_vi_search }, /* ? */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* @ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_vi_append_eol }, /* A */ + { ISFUNC, rl_vi_prev_word}, /* B */ + { ISFUNC, rl_vi_change_to }, /* C */ + { ISFUNC, rl_vi_delete_to }, /* D */ + { ISFUNC, rl_vi_end_word }, /* E */ + { ISFUNC, rl_vi_char_search }, /* F */ + { ISFUNC, rl_vi_fetch_history }, /* G */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* H */ + { ISFUNC, rl_vi_insert_beg }, /* I */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* J */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* K */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* L */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* M */ + { ISFUNC, rl_vi_search_again }, /* N */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* O */ + { ISFUNC, rl_vi_put }, /* P */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Q */ + { ISFUNC, rl_vi_replace }, /* R */ + { ISFUNC, rl_vi_subst }, /* S */ + { ISFUNC, rl_vi_char_search }, /* T */ + { ISFUNC, rl_revert_line }, /* U */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* V */ + { ISFUNC, rl_vi_next_word }, /* W */ + { ISFUNC, rl_vi_rubout }, /* X */ + { ISFUNC, rl_vi_yank_to }, /* Y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Z */ + + /* Some more punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* [ */ + { ISFUNC, rl_vi_complete }, /* \ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ] */ + { ISFUNC, rl_vi_first_print }, /* ^ */ + { ISFUNC, rl_vi_yank_arg }, /* _ */ + { ISFUNC, rl_vi_goto_mark }, /* ` */ + + /* Lowercase alphabet. */ + { ISFUNC, rl_vi_append_mode }, /* a */ + { ISFUNC, rl_vi_prev_word }, /* b */ + { ISFUNC, rl_vi_change_to }, /* c */ + { ISFUNC, rl_vi_delete_to }, /* d */ + { ISFUNC, rl_vi_end_word }, /* e */ + { ISFUNC, rl_vi_char_search }, /* f */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* g */ + { ISFUNC, rl_backward_char }, /* h */ + { ISFUNC, rl_vi_insert_mode }, /* i */ + { ISFUNC, rl_get_next_history }, /* j */ + { ISFUNC, rl_get_previous_history }, /* k */ + { ISFUNC, rl_forward_char }, /* l */ + { ISFUNC, rl_vi_set_mark }, /* m */ + { ISFUNC, rl_vi_search_again }, /* n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* o */ + { ISFUNC, rl_vi_put }, /* p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* q */ + { ISFUNC, rl_vi_change_char }, /* r */ + { ISFUNC, rl_vi_subst }, /* s */ + { ISFUNC, rl_vi_char_search }, /* t */ + { ISFUNC, rl_vi_undo }, /* u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* v */ + { ISFUNC, rl_vi_next_word }, /* w */ + { ISFUNC, rl_vi_delete }, /* x */ + { ISFUNC, rl_vi_yank_to }, /* y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* z */ + + /* Final punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* { */ + { ISFUNC, rl_vi_column }, /* | */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* } */ + { ISFUNC, rl_vi_change_case }, /* ~ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* RUBOUT */ + +#if KEYMAP_SIZE > 128 + /* Undefined keys. */ + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 } +#endif /* KEYMAP_SIZE > 128 */ +}; + + +KEYMAP_ENTRY_ARRAY vi_insertion_keymap = { + /* The regular control keys come first. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */ + { ISFUNC, rl_insert }, /* Control-a */ + { ISFUNC, rl_insert }, /* Control-b */ + { ISFUNC, rl_insert }, /* Control-c */ + { ISFUNC, rl_vi_eof_maybe }, /* Control-d */ + { ISFUNC, rl_insert }, /* Control-e */ + { ISFUNC, rl_insert }, /* Control-f */ + { ISFUNC, rl_insert }, /* Control-g */ + { ISFUNC, rl_rubout }, /* Control-h */ + { ISFUNC, rl_complete }, /* Control-i */ + { ISFUNC, rl_newline }, /* Control-j */ + { ISFUNC, rl_insert }, /* Control-k */ + { ISFUNC, rl_insert }, /* Control-l */ + { ISFUNC, rl_newline }, /* Control-m */ + { ISFUNC, rl_menu_complete}, /* Control-n */ + { ISFUNC, rl_insert }, /* Control-o */ + { ISFUNC, rl_backward_menu_complete }, /* Control-p */ + { ISFUNC, rl_insert }, /* Control-q */ + { ISFUNC, rl_reverse_search_history }, /* Control-r */ + { ISFUNC, rl_forward_search_history }, /* Control-s */ + { ISFUNC, rl_transpose_chars }, /* Control-t */ + { ISFUNC, rl_unix_line_discard }, /* Control-u */ + { ISFUNC, rl_quoted_insert }, /* Control-v */ + { ISFUNC, rl_unix_word_rubout }, /* Control-w */ + { ISFUNC, rl_insert }, /* Control-x */ + { ISFUNC, rl_yank }, /* Control-y */ + { ISFUNC, rl_insert }, /* Control-z */ + + { ISFUNC, rl_vi_movement_mode }, /* Control-[ */ + { ISFUNC, rl_insert }, /* Control-\ */ + { ISFUNC, rl_insert }, /* Control-] */ + { ISFUNC, rl_insert }, /* Control-^ */ + { ISFUNC, rl_vi_undo }, /* Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, rl_insert }, /* SPACE */ + { ISFUNC, rl_insert }, /* ! */ + { ISFUNC, rl_insert }, /* " */ + { ISFUNC, rl_insert }, /* # */ + { ISFUNC, rl_insert }, /* $ */ + { ISFUNC, rl_insert }, /* % */ + { ISFUNC, rl_insert }, /* & */ + { ISFUNC, rl_insert }, /* ' */ + { ISFUNC, rl_insert }, /* ( */ + { ISFUNC, rl_insert }, /* ) */ + { ISFUNC, rl_insert }, /* * */ + { ISFUNC, rl_insert }, /* + */ + { ISFUNC, rl_insert }, /* , */ + { ISFUNC, rl_insert }, /* - */ + { ISFUNC, rl_insert }, /* . */ + { ISFUNC, rl_insert }, /* / */ + + /* Regular digits. */ + { ISFUNC, rl_insert }, /* 0 */ + { ISFUNC, rl_insert }, /* 1 */ + { ISFUNC, rl_insert }, /* 2 */ + { ISFUNC, rl_insert }, /* 3 */ + { ISFUNC, rl_insert }, /* 4 */ + { ISFUNC, rl_insert }, /* 5 */ + { ISFUNC, rl_insert }, /* 6 */ + { ISFUNC, rl_insert }, /* 7 */ + { ISFUNC, rl_insert }, /* 8 */ + { ISFUNC, rl_insert }, /* 9 */ + + /* A little more punctuation. */ + { ISFUNC, rl_insert }, /* : */ + { ISFUNC, rl_insert }, /* ; */ + { ISFUNC, rl_insert }, /* < */ + { ISFUNC, rl_insert }, /* = */ + { ISFUNC, rl_insert }, /* > */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* @ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_insert }, /* A */ + { ISFUNC, rl_insert }, /* B */ + { ISFUNC, rl_insert }, /* C */ + { ISFUNC, rl_insert }, /* D */ + { ISFUNC, rl_insert }, /* E */ + { ISFUNC, rl_insert }, /* F */ + { ISFUNC, rl_insert }, /* G */ + { ISFUNC, rl_insert }, /* H */ + { ISFUNC, rl_insert }, /* I */ + { ISFUNC, rl_insert }, /* J */ + { ISFUNC, rl_insert }, /* K */ + { ISFUNC, rl_insert }, /* L */ + { ISFUNC, rl_insert }, /* M */ + { ISFUNC, rl_insert }, /* N */ + { ISFUNC, rl_insert }, /* O */ + { ISFUNC, rl_insert }, /* P */ + { ISFUNC, rl_insert }, /* Q */ + { ISFUNC, rl_insert }, /* R */ + { ISFUNC, rl_insert }, /* S */ + { ISFUNC, rl_insert }, /* T */ + { ISFUNC, rl_insert }, /* U */ + { ISFUNC, rl_insert }, /* V */ + { ISFUNC, rl_insert }, /* W */ + { ISFUNC, rl_insert }, /* X */ + { ISFUNC, rl_insert }, /* Y */ + { ISFUNC, rl_insert }, /* Z */ + + /* Some more punctuation. */ + { ISFUNC, rl_insert }, /* [ */ + { ISFUNC, rl_insert }, /* \ */ + { ISFUNC, rl_insert }, /* ] */ + { ISFUNC, rl_insert }, /* ^ */ + { ISFUNC, rl_insert }, /* _ */ + { ISFUNC, rl_insert }, /* ` */ + + /* Lowercase alphabet. */ + { ISFUNC, rl_insert }, /* a */ + { ISFUNC, rl_insert }, /* b */ + { ISFUNC, rl_insert }, /* c */ + { ISFUNC, rl_insert }, /* d */ + { ISFUNC, rl_insert }, /* e */ + { ISFUNC, rl_insert }, /* f */ + { ISFUNC, rl_insert }, /* g */ + { ISFUNC, rl_insert }, /* h */ + { ISFUNC, rl_insert }, /* i */ + { ISFUNC, rl_insert }, /* j */ + { ISFUNC, rl_insert }, /* k */ + { ISFUNC, rl_insert }, /* l */ + { ISFUNC, rl_insert }, /* m */ + { ISFUNC, rl_insert }, /* n */ + { ISFUNC, rl_insert }, /* o */ + { ISFUNC, rl_insert }, /* p */ + { ISFUNC, rl_insert }, /* q */ + { ISFUNC, rl_insert }, /* r */ + { ISFUNC, rl_insert }, /* s */ + { ISFUNC, rl_insert }, /* t */ + { ISFUNC, rl_insert }, /* u */ + { ISFUNC, rl_insert }, /* v */ + { ISFUNC, rl_insert }, /* w */ + { ISFUNC, rl_insert }, /* x */ + { ISFUNC, rl_insert }, /* y */ + { ISFUNC, rl_insert }, /* z */ + + /* Final punctuation. */ + { ISFUNC, rl_insert }, /* { */ + { ISFUNC, rl_insert }, /* | */ + { ISFUNC, rl_insert }, /* } */ + { ISFUNC, rl_insert }, /* ~ */ + { ISFUNC, rl_rubout }, /* RUBOUT */ + +#if KEYMAP_SIZE > 128 + /* Pure 8-bit characters (128 - 159). + These might be used in some + character sets. */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + + /* ISO Latin-1 characters (160 - 255) */ + { ISFUNC, rl_insert }, /* No-break space */ + { ISFUNC, rl_insert }, /* Inverted exclamation mark */ + { ISFUNC, rl_insert }, /* Cent sign */ + { ISFUNC, rl_insert }, /* Pound sign */ + { ISFUNC, rl_insert }, /* Currency sign */ + { ISFUNC, rl_insert }, /* Yen sign */ + { ISFUNC, rl_insert }, /* Broken bar */ + { ISFUNC, rl_insert }, /* Section sign */ + { ISFUNC, rl_insert }, /* Diaeresis */ + { ISFUNC, rl_insert }, /* Copyright sign */ + { ISFUNC, rl_insert }, /* Feminine ordinal indicator */ + { ISFUNC, rl_insert }, /* Left pointing double angle quotation mark */ + { ISFUNC, rl_insert }, /* Not sign */ + { ISFUNC, rl_insert }, /* Soft hyphen */ + { ISFUNC, rl_insert }, /* Registered sign */ + { ISFUNC, rl_insert }, /* Macron */ + { ISFUNC, rl_insert }, /* Degree sign */ + { ISFUNC, rl_insert }, /* Plus-minus sign */ + { ISFUNC, rl_insert }, /* Superscript two */ + { ISFUNC, rl_insert }, /* Superscript three */ + { ISFUNC, rl_insert }, /* Acute accent */ + { ISFUNC, rl_insert }, /* Micro sign */ + { ISFUNC, rl_insert }, /* Pilcrow sign */ + { ISFUNC, rl_insert }, /* Middle dot */ + { ISFUNC, rl_insert }, /* Cedilla */ + { ISFUNC, rl_insert }, /* Superscript one */ + { ISFUNC, rl_insert }, /* Masculine ordinal indicator */ + { ISFUNC, rl_insert }, /* Right pointing double angle quotation mark */ + { ISFUNC, rl_insert }, /* Vulgar fraction one quarter */ + { ISFUNC, rl_insert }, /* Vulgar fraction one half */ + { ISFUNC, rl_insert }, /* Vulgar fraction three quarters */ + { ISFUNC, rl_insert }, /* Inverted questionk mark */ + { ISFUNC, rl_insert }, /* Latin capital letter a with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter a with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter a with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter a with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter a with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter a with ring above */ + { ISFUNC, rl_insert }, /* Latin capital letter ae */ + { ISFUNC, rl_insert }, /* Latin capital letter c with cedilla */ + { ISFUNC, rl_insert }, /* Latin capital letter e with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter e with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter e with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter e with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter i with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter i with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter i with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter i with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter eth (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin capital letter n with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter o with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter o with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter o with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter o with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter o with diaeresis */ + { ISFUNC, rl_insert }, /* Multiplication sign */ + { ISFUNC, rl_insert }, /* Latin capital letter o with stroke */ + { ISFUNC, rl_insert }, /* Latin capital letter u with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter u with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter u with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter u with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter Y with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter thorn (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin small letter sharp s (German) */ + { ISFUNC, rl_insert }, /* Latin small letter a with grave */ + { ISFUNC, rl_insert }, /* Latin small letter a with acute */ + { ISFUNC, rl_insert }, /* Latin small letter a with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter a with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter a with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter a with ring above */ + { ISFUNC, rl_insert }, /* Latin small letter ae */ + { ISFUNC, rl_insert }, /* Latin small letter c with cedilla */ + { ISFUNC, rl_insert }, /* Latin small letter e with grave */ + { ISFUNC, rl_insert }, /* Latin small letter e with acute */ + { ISFUNC, rl_insert }, /* Latin small letter e with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter e with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter i with grave */ + { ISFUNC, rl_insert }, /* Latin small letter i with acute */ + { ISFUNC, rl_insert }, /* Latin small letter i with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter i with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter eth (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin small letter n with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter o with grave */ + { ISFUNC, rl_insert }, /* Latin small letter o with acute */ + { ISFUNC, rl_insert }, /* Latin small letter o with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter o with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter o with diaeresis */ + { ISFUNC, rl_insert }, /* Division sign */ + { ISFUNC, rl_insert }, /* Latin small letter o with stroke */ + { ISFUNC, rl_insert }, /* Latin small letter u with grave */ + { ISFUNC, rl_insert }, /* Latin small letter u with acute */ + { ISFUNC, rl_insert }, /* Latin small letter u with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter u with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter y with acute */ + { ISFUNC, rl_insert }, /* Latin small letter thorn (Icelandic) */ + { ISFUNC, rl_insert } /* Latin small letter y with diaeresis */ +#endif /* KEYMAP_SIZE > 128 */ +}; + +/* Unused for the time being. */ +#if 0 +KEYMAP_ENTRY_ARRAY vi_escape_keymap = { + /* The regular control keys come first. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-d */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-f */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-g */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-h */ + { ISFUNC, rl_tab_insert}, /* Control-i */ + { ISFUNC, rl_emacs_editing_mode}, /* Control-j */ + { ISFUNC, rl_kill_line }, /* Control-k */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-l */ + { ISFUNC, rl_emacs_editing_mode}, /* Control-m */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-q */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-s */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-t */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-x */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */ + + { ISFUNC, rl_vi_movement_mode }, /* Control-[ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */ + { ISFUNC, rl_vi_undo }, /* Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* SPACE */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ! */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* " */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* # */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* $ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* % */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* & */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ' */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ( */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ) */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* * */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* + */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* , */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* - */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* . */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* / */ + + /* Regular digits. */ + { ISFUNC, rl_vi_arg_digit }, /* 0 */ + { ISFUNC, rl_vi_arg_digit }, /* 1 */ + { ISFUNC, rl_vi_arg_digit }, /* 2 */ + { ISFUNC, rl_vi_arg_digit }, /* 3 */ + { ISFUNC, rl_vi_arg_digit }, /* 4 */ + { ISFUNC, rl_vi_arg_digit }, /* 5 */ + { ISFUNC, rl_vi_arg_digit }, /* 6 */ + { ISFUNC, rl_vi_arg_digit }, /* 7 */ + { ISFUNC, rl_vi_arg_digit }, /* 8 */ + { ISFUNC, rl_vi_arg_digit }, /* 9 */ + + /* A little more punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* : */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ; */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* < */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* = */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* > */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ? */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* @ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_do_lowercase_version }, /* A */ + { ISFUNC, rl_do_lowercase_version }, /* B */ + { ISFUNC, rl_do_lowercase_version }, /* C */ + { ISFUNC, rl_do_lowercase_version }, /* D */ + { ISFUNC, rl_do_lowercase_version }, /* E */ + { ISFUNC, rl_do_lowercase_version }, /* F */ + { ISFUNC, rl_do_lowercase_version }, /* G */ + { ISFUNC, rl_do_lowercase_version }, /* H */ + { ISFUNC, rl_do_lowercase_version }, /* I */ + { ISFUNC, rl_do_lowercase_version }, /* J */ + { ISFUNC, rl_do_lowercase_version }, /* K */ + { ISFUNC, rl_do_lowercase_version }, /* L */ + { ISFUNC, rl_do_lowercase_version }, /* M */ + { ISFUNC, rl_do_lowercase_version }, /* N */ + { ISFUNC, rl_do_lowercase_version }, /* O */ + { ISFUNC, rl_do_lowercase_version }, /* P */ + { ISFUNC, rl_do_lowercase_version }, /* Q */ + { ISFUNC, rl_do_lowercase_version }, /* R */ + { ISFUNC, rl_do_lowercase_version }, /* S */ + { ISFUNC, rl_do_lowercase_version }, /* T */ + { ISFUNC, rl_do_lowercase_version }, /* U */ + { ISFUNC, rl_do_lowercase_version }, /* V */ + { ISFUNC, rl_do_lowercase_version }, /* W */ + { ISFUNC, rl_do_lowercase_version }, /* X */ + { ISFUNC, rl_do_lowercase_version }, /* Y */ + { ISFUNC, rl_do_lowercase_version }, /* Z */ + + /* Some more punctuation. */ + { ISFUNC, rl_arrow_keys }, /* [ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* \ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ^ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* _ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ` */ + + /* Lowercase alphabet. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* c */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* d */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* f */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* g */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* h */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* i */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* j */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* k */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* l */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* m */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* n */ + { ISFUNC, rl_arrow_keys }, /* o */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* q */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* s */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* t */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* x */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* z */ + + /* Final punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* { */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* | */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* } */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ~ */ + { ISFUNC, rl_backward_kill_word }, /* RUBOUT */ + +#if KEYMAP_SIZE > 128 + /* Undefined keys. */ + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 } +#endif /* KEYMAP_SIZE > 128 */ +}; +#endif diff --git a/lib/readline/vi_mode.c b/lib/readline/vi_mode.c index a3c35786c..5e749521b 100644 --- a/lib/readline/vi_mode.c +++ b/lib/readline/vi_mode.c @@ -108,9 +108,13 @@ static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; /* Arrays for the saved marks. */ static int vi_mark_chars['z' - 'a' + 1]; +static void _rl_vi_replace_insert PARAMS((int)); +static void _rl_vi_save_replace PARAMS((void)); static void _rl_vi_stuff_insert PARAMS((int)); static void _rl_vi_save_insert PARAMS((UNDO_LIST *)); +static void vi_save_insert_buffer PARAMS ((int, int)); + static void _rl_vi_backup PARAMS((void)); static int _rl_vi_arg_dispatch PARAMS((int)); @@ -188,6 +192,22 @@ _rl_vi_textmod_command (c) return (member (c, vi_textmod)); } +static void +_rl_vi_replace_insert (count) + int count; +{ + int nchars; + + nchars = strlen (vi_insert_buffer); + + rl_begin_undo_group (); + while (count--) + /* nchars-1 to compensate for _rl_replace_text using `end+1' in call + to rl_delete_text */ + _rl_replace_text (vi_insert_buffer, rl_point, rl_point+nchars-1); + rl_end_undo_group (); +} + static void _rl_vi_stuff_insert (count) int count; @@ -207,7 +227,7 @@ rl_vi_redo (count, c) { int r; - if (!rl_explicit_arg) + if (rl_explicit_arg == 0) { rl_numeric_arg = _rl_vi_last_repeat; rl_arg_sign = _rl_vi_last_arg_sign; @@ -224,6 +244,13 @@ rl_vi_redo (count, c) if (rl_point > 0) _rl_vi_backup (); } + else if (_rl_vi_last_command == 'R' && vi_insert_buffer && *vi_insert_buffer) + { + _rl_vi_replace_insert (count); + /* And back up point over the last character inserted. */ + if (rl_point > 0) + _rl_vi_backup (); + } /* Ditto for redoing an insert with `I', but move to the beginning of the line like the `I' command does. */ else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer) @@ -690,6 +717,43 @@ rl_vi_insert_mode (count, key) return (0); } +static void +vi_save_insert_buffer (start, len) + int start, len; +{ + /* Same code as _rl_vi_save_insert below */ + if (len >= vi_insert_buffer_size) + { + vi_insert_buffer_size += (len + 32) - (len % 32); + vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size); + } + strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1); + vi_insert_buffer[len-1] = '\0'; +} + +static void +_rl_vi_save_replace () +{ + int len, start, end; + UNDO_LIST *up; + + up = rl_undo_list; + if (up == 0 || up->what != UNDO_END || vi_replace_count <= 0) + { + if (vi_insert_buffer_size >= 1) + vi_insert_buffer[0] = '\0'; + return; + } + /* Let's try it the quick and easy way for now. This should essentially + accommodate every UNDO_INSERT and save the inserted text to + vi_insert_buffer */ + end = rl_point; + start = end - vi_replace_count + 1; + len = vi_replace_count + 1; + + vi_save_insert_buffer (start, len); +} + static void _rl_vi_save_insert (up) UNDO_LIST *up; @@ -706,13 +770,8 @@ _rl_vi_save_insert (up) start = up->start; end = up->end; len = end - start + 1; - if (len >= vi_insert_buffer_size) - { - vi_insert_buffer_size += (len + 32) - (len % 32); - vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size); - } - strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1); - vi_insert_buffer[len-1] = '\0'; + + vi_save_insert_buffer (start, len); } void @@ -728,7 +787,10 @@ _rl_vi_done_inserting () on absolute indices into the line which may change (though they probably will not). */ _rl_vi_doing_insert = 0; - _rl_vi_save_insert (rl_undo_list->next); + if (_rl_vi_last_key_before_insert == 'R') + _rl_vi_save_replace (); /* Half the battle */ + else + _rl_vi_save_insert (rl_undo_list->next); vi_continued_command = 1; } else @@ -1911,14 +1973,20 @@ rl_vi_replace (count, key) vi_replace_count = 0; - if (!vi_replace_map) + if (vi_replace_map == 0) { vi_replace_map = rl_make_bare_keymap (); + for (i = 0; i < ' '; i++) + if (vi_insertion_keymap[i].type == ISFUNC) + vi_replace_map[i].function = vi_insertion_keymap[i].function; + for (i = ' '; i < KEYMAP_SIZE; i++) vi_replace_map[i].function = rl_vi_overstrike; vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete; + + /* Make sure these are what we want. */ vi_replace_map[ESC].function = rl_vi_movement_mode; vi_replace_map[RETURN].function = rl_newline; vi_replace_map[NEWLINE].function = rl_newline; @@ -1931,7 +1999,12 @@ rl_vi_replace (count, key) vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete; } + + rl_vi_start_inserting (key, 1, rl_arg_sign); + + _rl_vi_last_key_before_insert = key; _rl_keymap = vi_replace_map; + return (0); } diff --git a/lib/readline/vi_mode.c~ b/lib/readline/vi_mode.c~ new file mode 100644 index 000000000..bc65cb216 --- /dev/null +++ b/lib/readline/vi_mode.c~ @@ -0,0 +1,2142 @@ +/* vi_mode.c -- A vi emulation mode for Bash. + Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */ + +/* Copyright (C) 1987-2010 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library (Readline), a library + for reading lines of text with interactive input and history editing. + + Readline is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Readline is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Readline. If not, see . +*/ + +#define READLINE_LIBRARY + +/* **************************************************************** */ +/* */ +/* VI Emulation Mode */ +/* */ +/* **************************************************************** */ +#include "rlconf.h" + +#if defined (VI_MODE) + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include + +/* Some standard library routines. */ +#include "rldefs.h" +#include "rlmbutil.h" + +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +#ifndef member +#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) +#endif + +int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ + +_rl_vimotion_cxt *_rl_vimvcxt = 0; + +/* Non-zero means enter insertion mode. */ +static int _rl_vi_doing_insert; + +/* Command keys which do movement for xxx_to commands. */ +static const char * const vi_motion = " hl^$0ftFT;,%wbeWBE|`"; + +/* Keymap used for vi replace characters. Created dynamically since + rarely used. */ +static Keymap vi_replace_map; + +/* The number of characters inserted in the last replace operation. */ +static int vi_replace_count; + +/* If non-zero, we have text inserted after a c[motion] command that put + us implicitly into insert mode. Some people want this text to be + attached to the command so that it is `redoable' with `.'. */ +static int vi_continued_command; +static char *vi_insert_buffer; +static int vi_insert_buffer_size; + +static int _rl_vi_last_repeat = 1; +static int _rl_vi_last_arg_sign = 1; +static int _rl_vi_last_motion; +#if defined (HANDLE_MULTIBYTE) +static char _rl_vi_last_search_mbchar[MB_LEN_MAX]; +static int _rl_vi_last_search_mblen; +#else +static int _rl_vi_last_search_char; +#endif +static int _rl_vi_last_replacement; + +static int _rl_vi_last_key_before_insert; + +static int vi_redoing; + +/* Text modification commands. These are the `redoable' commands. */ +static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; + +/* Arrays for the saved marks. */ +static int vi_mark_chars['z' - 'a' + 1]; + +static void _rl_vi_replace_insert PARAMS((int)); +static void _rl_vi_save_replace PARAMS((void)); +static void _rl_vi_stuff_insert PARAMS((int)); +static void _rl_vi_save_insert PARAMS((UNDO_LIST *)); + +static void vi_save_insert_buffer PARAMS ((int, int)); + +static void _rl_vi_backup PARAMS((void)); + +static int _rl_vi_arg_dispatch PARAMS((int)); +static int rl_digit_loop1 PARAMS((void)); + +static int _rl_vi_set_mark PARAMS((void)); +static int _rl_vi_goto_mark PARAMS((void)); + +static void _rl_vi_append_forward PARAMS((int)); + +static int _rl_vi_callback_getchar PARAMS((char *, int)); + +#if defined (READLINE_CALLBACKS) +static int _rl_vi_callback_set_mark PARAMS((_rl_callback_generic_arg *)); +static int _rl_vi_callback_goto_mark PARAMS((_rl_callback_generic_arg *)); +static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *)); +static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *)); +#endif + +static int rl_domove_read_callback PARAMS((_rl_vimotion_cxt *)); +static int rl_domove_motion_callback PARAMS((_rl_vimotion_cxt *)); +static int rl_vi_domove_getchar PARAMS((_rl_vimotion_cxt *)); + +static int vi_change_dispatch PARAMS((_rl_vimotion_cxt *)); +static int vi_delete_dispatch PARAMS((_rl_vimotion_cxt *)); +static int vi_yank_dispatch PARAMS((_rl_vimotion_cxt *)); + +static int vidomove_dispatch PARAMS((_rl_vimotion_cxt *)); + +void +_rl_vi_initialize_line () +{ + register int i, n; + + n = sizeof (vi_mark_chars) / sizeof (vi_mark_chars[0]); + for (i = 0; i < n; i++) + vi_mark_chars[i] = -1; + + RL_UNSETSTATE(RL_STATE_VICMDONCE); +} + +void +_rl_vi_reset_last () +{ + _rl_vi_last_command = 'i'; + _rl_vi_last_repeat = 1; + _rl_vi_last_arg_sign = 1; + _rl_vi_last_motion = 0; +} + +void +_rl_vi_set_last (key, repeat, sign) + int key, repeat, sign; +{ + _rl_vi_last_command = key; + _rl_vi_last_repeat = repeat; + _rl_vi_last_arg_sign = sign; +} + +/* A convenience function that calls _rl_vi_set_last to save the last command + information and enters insertion mode. */ +void +rl_vi_start_inserting (key, repeat, sign) + int key, repeat, sign; +{ + _rl_vi_set_last (key, repeat, sign); + rl_vi_insertion_mode (1, key); +} + +/* Is the command C a VI mode text modification command? */ +int +_rl_vi_textmod_command (c) + int c; +{ + return (member (c, vi_textmod)); +} + +static void +_rl_vi_replace_insert (count) + int count; +{ + int nchars; + + nchars = strlen (vi_insert_buffer); + + rl_begin_undo_group (); + while (count--) + _rl_replace_text (vi_insert_buffer, rl_point, rl_point+nchars); + rl_end_undo_group (); +} + +static void +_rl_vi_stuff_insert (count) + int count; +{ + rl_begin_undo_group (); + while (count--) + rl_insert_text (vi_insert_buffer); + rl_end_undo_group (); +} + +/* Bound to `.'. Called from command mode, so we know that we have to + redo a text modification command. The default for _rl_vi_last_command + puts you back into insert mode. */ +int +rl_vi_redo (count, c) + int count, c; +{ + int r; + + if (rl_explicit_arg == 0) + { + rl_numeric_arg = _rl_vi_last_repeat; + rl_arg_sign = _rl_vi_last_arg_sign; + } + + r = 0; + vi_redoing = 1; + /* If we're redoing an insert with `i', stuff in the inserted text + and do not go into insertion mode. */ + if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer) + { + _rl_vi_stuff_insert (count); + /* And back up point over the last character inserted. */ + if (rl_point > 0) + _rl_vi_backup (); + } + else if (_rl_vi_last_command == 'R' && vi_insert_buffer && *vi_insert_buffer) + { + _rl_vi_replace_insert (count); + /* And back up point over the last character inserted. */ + if (rl_point > 0) + _rl_vi_backup (); + } + /* Ditto for redoing an insert with `I', but move to the beginning of the + line like the `I' command does. */ + else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer) + { + rl_beg_of_line (1, 'I'); + _rl_vi_stuff_insert (count); + if (rl_point > 0) + _rl_vi_backup (); + } + /* Ditto for redoing an insert with `a', but move forward a character first + like the `a' command does. */ + else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer) + { + _rl_vi_append_forward ('a'); + _rl_vi_stuff_insert (count); + if (rl_point > 0) + _rl_vi_backup (); + } + /* Ditto for redoing an insert with `A', but move to the end of the line + like the `A' command does. */ + else if (_rl_vi_last_command == 'A' && vi_insert_buffer && *vi_insert_buffer) + { + rl_end_of_line (1, 'A'); + _rl_vi_stuff_insert (count); + if (rl_point > 0) + _rl_vi_backup (); + } + else + r = _rl_dispatch (_rl_vi_last_command, _rl_keymap); + vi_redoing = 0; + + return (r); +} + +/* A placeholder for further expansion. */ +int +rl_vi_undo (count, key) + int count, key; +{ + return (rl_undo_command (count, key)); +} + +/* Yank the nth arg from the previous line into this line at point. */ +int +rl_vi_yank_arg (count, key) + int count, key; +{ + /* Readline thinks that the first word on a line is the 0th, while vi + thinks the first word on a line is the 1st. Compensate. */ + if (rl_explicit_arg) + rl_yank_nth_arg (count - 1, 0); + else + rl_yank_nth_arg ('$', 0); + + return (0); +} + +/* With an argument, move back that many history lines, else move to the + beginning of history. */ +int +rl_vi_fetch_history (count, c) + int count, c; +{ + int wanted; + + /* Giving an argument of n means we want the nth command in the history + file. The command number is interpreted the same way that the bash + `history' command does it -- that is, giving an argument count of 450 + to this command would get the command listed as number 450 in the + output of `history'. */ + if (rl_explicit_arg) + { + wanted = history_base + where_history () - count; + if (wanted <= 0) + rl_beginning_of_history (0, 0); + else + rl_get_previous_history (wanted, c); + } + else + rl_beginning_of_history (count, 0); + return (0); +} + +/* Search again for the last thing searched for. */ +int +rl_vi_search_again (count, key) + int count, key; +{ + switch (key) + { + case 'n': + rl_noninc_reverse_search_again (count, key); + break; + + case 'N': + rl_noninc_forward_search_again (count, key); + break; + } + return (0); +} + +/* Do a vi style search. */ +int +rl_vi_search (count, key) + int count, key; +{ + switch (key) + { + case '?': + _rl_free_saved_history_line (); + rl_noninc_forward_search (count, key); + break; + + case '/': + _rl_free_saved_history_line (); + rl_noninc_reverse_search (count, key); + break; + + default: + rl_ding (); + break; + } + return (0); +} + +/* Completion, from vi's point of view. */ +int +rl_vi_complete (ignore, key) + int ignore, key; +{ + if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) + { + if (!whitespace (rl_line_buffer[rl_point + 1])) + rl_vi_end_word (1, 'E'); + rl_point++; + } + + if (key == '*') + rl_complete_internal ('*'); /* Expansion and replacement. */ + else if (key == '=') + rl_complete_internal ('?'); /* List possible completions. */ + else if (key == '\\') + rl_complete_internal (TAB); /* Standard Readline completion. */ + else + rl_complete (0, key); + + if (key == '*' || key == '\\') + rl_vi_start_inserting (key, 1, rl_arg_sign); + + return (0); +} + +/* Tilde expansion for vi mode. */ +int +rl_vi_tilde_expand (ignore, key) + int ignore, key; +{ + rl_tilde_expand (0, key); + rl_vi_start_inserting (key, 1, rl_arg_sign); + return (0); +} + +/* Previous word in vi mode. */ +int +rl_vi_prev_word (count, key) + int count, key; +{ + if (count < 0) + return (rl_vi_next_word (-count, key)); + + if (rl_point == 0) + { + rl_ding (); + return (0); + } + + if (_rl_uppercase_p (key)) + rl_vi_bWord (count, key); + else + rl_vi_bword (count, key); + + return (0); +} + +/* Next word in vi mode. */ +int +rl_vi_next_word (count, key) + int count, key; +{ + if (count < 0) + return (rl_vi_prev_word (-count, key)); + + if (rl_point >= (rl_end - 1)) + { + rl_ding (); + return (0); + } + + if (_rl_uppercase_p (key)) + rl_vi_fWord (count, key); + else + rl_vi_fword (count, key); + return (0); +} + +/* Move to the end of the ?next? word. */ +int +rl_vi_end_word (count, key) + int count, key; +{ + if (count < 0) + { + rl_ding (); + return -1; + } + + if (_rl_uppercase_p (key)) + rl_vi_eWord (count, key); + else + rl_vi_eword (count, key); + return (0); +} + +/* Move forward a word the way that 'W' does. */ +int +rl_vi_fWord (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < (rl_end - 1)) + { + /* Skip until whitespace. */ + while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + + /* Now skip whitespace. */ + while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + return (0); +} + +int +rl_vi_bWord (count, ignore) + int count, ignore; +{ + while (count-- && rl_point > 0) + { + /* If we are at the start of a word, move back to whitespace so + we will go back to the start of the previous word. */ + if (!whitespace (rl_line_buffer[rl_point]) && + whitespace (rl_line_buffer[rl_point - 1])) + rl_point--; + + while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + if (rl_point > 0) + { + while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point])); + rl_point++; + } + } + return (0); +} + +int +rl_vi_eWord (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < (rl_end - 1)) + { + if (!whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Move to the next non-whitespace character (to the start of the + next word). */ + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + if (rl_point && rl_point < rl_end) + { + /* Skip whitespace. */ + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Skip until whitespace. */ + while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Move back to the last character of the word. */ + rl_point--; + } + } + return (0); +} + +int +rl_vi_fword (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < (rl_end - 1)) + { + /* Move to white space (really non-identifer). */ + if (_rl_isident (rl_line_buffer[rl_point])) + { + while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + else /* if (!whitespace (rl_line_buffer[rl_point])) */ + { + while (!_rl_isident (rl_line_buffer[rl_point]) && + !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + + /* Move past whitespace. */ + while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + return (0); +} + +int +rl_vi_bword (count, ignore) + int count, ignore; +{ + while (count-- && rl_point > 0) + { + int last_is_ident; + + /* If we are at the start of a word, move back to whitespace + so we will go back to the start of the previous word. */ + if (!whitespace (rl_line_buffer[rl_point]) && + whitespace (rl_line_buffer[rl_point - 1])) + rl_point--; + + /* If this character and the previous character are `opposite', move + back so we don't get messed up by the rl_point++ down there in + the while loop. Without this code, words like `l;' screw up the + function. */ + last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]); + if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) || + (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident)) + rl_point--; + + while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + if (rl_point > 0) + { + if (_rl_isident (rl_line_buffer[rl_point])) + while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point])); + else + while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) && + !whitespace (rl_line_buffer[rl_point])); + rl_point++; + } + } + return (0); +} + +int +rl_vi_eword (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < rl_end - 1) + { + if (!whitespace (rl_line_buffer[rl_point])) + rl_point++; + + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + if (rl_point < rl_end) + { + if (_rl_isident (rl_line_buffer[rl_point])) + while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point])); + else + while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point]) + && !whitespace (rl_line_buffer[rl_point])); + } + rl_point--; + } + return (0); +} + +int +rl_vi_insert_beg (count, key) + int count, key; +{ + rl_beg_of_line (1, key); + rl_vi_insert_mode (1, key); + return (0); +} + +static void +_rl_vi_append_forward (key) + int key; +{ + int point; + + if (rl_point < rl_end) + { + if (MB_CUR_MAX == 1 || rl_byte_oriented) + rl_point++; + else + { + point = rl_point; +#if 0 + rl_forward_char (1, key); +#else + rl_point = _rl_forward_char_internal (1); +#endif + if (point == rl_point) + rl_point = rl_end; + } + } +} + +int +rl_vi_append_mode (count, key) + int count, key; +{ + _rl_vi_append_forward (key); + rl_vi_start_inserting (key, 1, rl_arg_sign); + return (0); +} + +int +rl_vi_append_eol (count, key) + int count, key; +{ + rl_end_of_line (1, key); + rl_vi_append_mode (1, key); + return (0); +} + +/* What to do in the case of C-d. */ +int +rl_vi_eof_maybe (count, c) + int count, c; +{ + return (rl_newline (1, '\n')); +} + +/* Insertion mode stuff. */ + +/* Switching from one mode to the other really just involves + switching keymaps. */ +int +rl_vi_insertion_mode (count, key) + int count, key; +{ + _rl_keymap = vi_insertion_keymap; + _rl_vi_last_key_before_insert = key; + return (0); +} + +int +rl_vi_insert_mode (count, key) + int count, key; +{ + rl_vi_start_inserting (key, 1, rl_arg_sign); + return (0); +} + +static void +vi_save_insert_buffer (start, len) + int start, len; +{ + /* Same code as _rl_vi_save_insert below */ + if (len >= vi_insert_buffer_size) + { + vi_insert_buffer_size += (len + 32) - (len % 32); + vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size); + } + strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1); + vi_insert_buffer[len-1] = '\0'; +} + +static void +_rl_vi_save_replace () +{ + int len, start, end; + UNDO_LIST *up; + + up = rl_undo_list; + if (up == 0 || up->what != UNDO_END || vi_replace_count <= 0) + { + if (vi_insert_buffer_size >= 1) + vi_insert_buffer[0] = '\0'; + return; + } + /* Let's try it the quick and easy way for now. This should essentially + accommodate every UNDO_INSERT and save the inserted text to + vi_insert_buffer */ + end = rl_point; + start = end - vi_replace_count + 1; + len = vi_replace_count + 1; + + vi_save_insert_buffer (start, len); +} + +static void +_rl_vi_save_insert (up) + UNDO_LIST *up; +{ + int len, start, end; + + if (up == 0 || up->what != UNDO_INSERT) + { + if (vi_insert_buffer_size >= 1) + vi_insert_buffer[0] = '\0'; + return; + } + + start = up->start; + end = up->end; + len = end - start + 1; + + vi_save_insert_buffer (start, len); +} + +void +_rl_vi_done_inserting () +{ + if (_rl_vi_doing_insert) + { + /* The `C', `s', and `S' commands set this. */ + rl_end_undo_group (); + /* Now, the text between rl_undo_list->next->start and + rl_undo_list->next->end is what was inserted while in insert + mode. It gets copied to VI_INSERT_BUFFER because it depends + on absolute indices into the line which may change (though they + probably will not). */ + _rl_vi_doing_insert = 0; + if (_rl_vi_last_key_before_insert == 'R') + _rl_vi_save_replace (); /* Half the battle */ + else + _rl_vi_save_insert (rl_undo_list->next); + vi_continued_command = 1; + } + else + { + if (rl_undo_list && (_rl_vi_last_key_before_insert == 'i' || + _rl_vi_last_key_before_insert == 'a' || + _rl_vi_last_key_before_insert == 'I' || + _rl_vi_last_key_before_insert == 'A')) + _rl_vi_save_insert (rl_undo_list); + /* XXX - Other keys probably need to be checked. */ + else if (_rl_vi_last_key_before_insert == 'C') + rl_end_undo_group (); + while (_rl_undo_group_level > 0) + rl_end_undo_group (); + vi_continued_command = 0; + } +} + +int +rl_vi_movement_mode (count, key) + int count, key; +{ + if (rl_point > 0) + rl_backward_char (1, key); + + _rl_keymap = vi_movement_keymap; + _rl_vi_done_inserting (); + + /* This is how POSIX.2 says `U' should behave -- everything up until the + first time you go into command mode should not be undone. */ + if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0) + rl_free_undo_list (); + + RL_SETSTATE (RL_STATE_VICMDONCE); + return (0); +} + +int +rl_vi_arg_digit (count, c) + int count, c; +{ + if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg) + return (rl_beg_of_line (1, c)); + else + return (rl_digit_argument (count, c)); +} + +/* Change the case of the next COUNT characters. */ +#if defined (HANDLE_MULTIBYTE) +static int +_rl_vi_change_mbchar_case (count) + int count; +{ + wchar_t wc; + char mb[MB_LEN_MAX+1]; + int mlen, p; + size_t m; + mbstate_t ps; + + memset (&ps, 0, sizeof (mbstate_t)); + if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0) + count--; + while (count-- && rl_point < rl_end) + { + m = mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps); + if (MB_INVALIDCH (m)) + wc = (wchar_t)rl_line_buffer[rl_point]; + else if (MB_NULLWCH (m)) + wc = L'\0'; + if (iswupper (wc)) + wc = towlower (wc); + else if (iswlower (wc)) + wc = towupper (wc); + else + { + /* Just skip over chars neither upper nor lower case */ + rl_forward_char (1, 0); + continue; + } + + /* Vi is kind of strange here. */ + if (wc) + { + p = rl_point; + mlen = wcrtomb (mb, wc, &ps); + if (mlen >= 0) + mb[mlen] = '\0'; + rl_begin_undo_group (); + rl_vi_delete (1, 0); + if (rl_point < p) /* Did we retreat at EOL? */ + rl_point++; /* XXX - should we advance more than 1 for mbchar? */ + rl_insert_text (mb); + rl_end_undo_group (); + rl_vi_check (); + } + else + rl_forward_char (1, 0); + } + + return 0; +} +#endif + +int +rl_vi_change_case (count, ignore) + int count, ignore; +{ + int c, p; + + /* Don't try this on an empty line. */ + if (rl_point >= rl_end) + return (0); + + c = 0; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + return (_rl_vi_change_mbchar_case (count)); +#endif + + while (count-- && rl_point < rl_end) + { + if (_rl_uppercase_p (rl_line_buffer[rl_point])) + c = _rl_to_lower (rl_line_buffer[rl_point]); + else if (_rl_lowercase_p (rl_line_buffer[rl_point])) + c = _rl_to_upper (rl_line_buffer[rl_point]); + else + { + /* Just skip over characters neither upper nor lower case. */ + rl_forward_char (1, c); + continue; + } + + /* Vi is kind of strange here. */ + if (c) + { + p = rl_point; + rl_begin_undo_group (); + rl_vi_delete (1, c); + if (rl_point < p) /* Did we retreat at EOL? */ + rl_point++; + _rl_insert_char (1, c); + rl_end_undo_group (); + rl_vi_check (); + } + else + rl_forward_char (1, c); + } + return (0); +} + +int +rl_vi_put (count, key) + int count, key; +{ + if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end)) + rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); + + while (count--) + rl_yank (1, key); + + rl_backward_char (1, key); + return (0); +} + +static void +_rl_vi_backup () +{ + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else + rl_point--; +} + +int +rl_vi_check () +{ + if (rl_point && rl_point == rl_end) + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else + rl_point--; + } + return (0); +} + +int +rl_vi_column (count, key) + int count, key; +{ + if (count > rl_end) + rl_end_of_line (1, key); + else + rl_point = count - 1; + return (0); +} + +/* Process C as part of the current numeric argument. Return -1 if the + argument should be aborted, 0 if we should not read any more chars, and + 1 if we should continue to read chars. */ +static int +_rl_vi_arg_dispatch (c) + int c; +{ + int key; + + key = c; + if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) + { + rl_numeric_arg *= 4; + return 1; + } + + c = UNMETA (c); + + if (_rl_digit_p (c)) + { + if (rl_explicit_arg) + rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); + else + rl_numeric_arg = _rl_digit_value (c); + rl_explicit_arg = 1; + return 1; /* keep going */ + } + else + { + rl_clear_message (); + rl_stuff_char (key); + return 0; /* done */ + } +} + +/* A simplified loop for vi. Don't dispatch key at end. + Don't recognize minus sign? + Should this do rl_save_prompt/rl_restore_prompt? */ +static int +rl_digit_loop1 () +{ + int c, r; + + while (1) + { + if (_rl_arg_overflow ()) + return 1; + + c = _rl_arg_getchar (); + + r = _rl_vi_arg_dispatch (c); + if (r <= 0) + break; + } + + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return (0); +} + +static void +_rl_mvcxt_init (m, op, key) + _rl_vimotion_cxt *m; + int op, key; +{ + m->op = op; + m->state = m->flags = 0; + m->ncxt = 0; + m->numeric_arg = -1; + m->start = rl_point; + m->end = rl_end; + m->key = key; + m->motion = -1; +} + +static _rl_vimotion_cxt * +_rl_mvcxt_alloc (op, key) + int op, key; +{ + _rl_vimotion_cxt *m; + + m = xmalloc (sizeof (_rl_vimotion_cxt)); + _rl_mvcxt_init (m, op, key); + return m; +} + +static void +_rl_mvcxt_dispose (m) + _rl_vimotion_cxt *m; +{ + xfree (m); +} + +static int +rl_domove_motion_callback (m) + _rl_vimotion_cxt *m; +{ + int c, save, r; + int old_end; + + _rl_vi_last_motion = c = m->motion; + + /* Append a blank character temporarily so that the motion routines + work right at the end of the line. */ + old_end = rl_end; + rl_line_buffer[rl_end++] = ' '; + rl_line_buffer[rl_end] = '\0'; + + _rl_dispatch (c, _rl_keymap); + + /* Remove the blank that we added. */ + rl_end = old_end; + rl_line_buffer[rl_end] = '\0'; + if (rl_point > rl_end) + rl_point = rl_end; + + /* No change in position means the command failed. */ + if (rl_mark == rl_point) + return (-1); + + /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next + word. If we are not at the end of the line, and we are on a + non-whitespace character, move back one (presumably to whitespace). */ + if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark && + !whitespace (rl_line_buffer[rl_point])) + rl_point--; + + /* If cw or cW, back up to the end of a word, so the behaviour of ce + or cE is the actual result. Brute-force, no subtlety. */ + if (m->key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W')) + { + /* Don't move farther back than where we started. */ + while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + /* Posix.2 says that if cw or cW moves the cursor towards the end of + the line, the character under the cursor should be deleted. */ + if (rl_point == rl_mark) + rl_point++; + else + { + /* Move past the end of the word so that the kill doesn't + remove the last letter of the previous word. Only do this + if we are not at the end of the line. */ + if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point])) + rl_point++; + } + } + + if (rl_mark < rl_point) + SWAP (rl_point, rl_mark); + +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + (*rl_redisplay_function)(); /* make sure motion is displayed */ +#endif + + r = vidomove_dispatch (m); + + return (r); +} + +#define RL_VIMOVENUMARG() (RL_ISSTATE (RL_STATE_VIMOTION) && RL_ISSTATE (RL_STATE_NUMERICARG)) + +static int +rl_domove_read_callback (m) + _rl_vimotion_cxt *m; +{ + int c, save; + + c = m->motion; + + if (member (c, vi_motion)) + { +#if defined (READLINE_CALLBACKS) + /* If we just read a vi-mode motion command numeric argument, turn off + the `reading numeric arg' state */ + if (RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG()) + RL_UNSETSTATE (RL_STATE_NUMERICARG); +#endif + /* Should do everything, including turning off RL_STATE_VIMOTION */ + return (rl_domove_motion_callback (m)); + } + else if (m->key == c && (m->key == 'd' || m->key == 'y' || m->key == 'c')) + { + rl_mark = rl_end; + rl_beg_of_line (1, c); + _rl_vi_last_motion = c; + RL_UNSETSTATE (RL_STATE_VIMOTION); + return (vidomove_dispatch (m)); + } +#if defined (READLINE_CALLBACKS) + /* XXX - these need to handle rl_universal_argument bindings */ + /* Reading vi motion char continuing numeric argument */ + else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG()) + { + return (_rl_vi_arg_dispatch (c)); + } + /* Readine vi motion char starting numeric argument */ + else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_VIMOTION) && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)) + { + RL_SETSTATE (RL_STATE_NUMERICARG); + return (_rl_vi_arg_dispatch (c)); + } +#endif + else if (_rl_digit_p (c)) + { + /* This code path taken when not in callback mode */ + save = rl_numeric_arg; + rl_numeric_arg = _rl_digit_value (c); + rl_explicit_arg = 1; + RL_SETSTATE (RL_STATE_NUMERICARG); + rl_digit_loop1 (); + rl_numeric_arg *= save; + c = rl_vi_domove_getchar (m); + if (c < 0) + { + m->motion = 0; + return -1; + } + m->motion = c; + return (rl_domove_motion_callback (m)); + } + else + { + RL_UNSETSTATE (RL_STATE_VIMOTION); + RL_UNSETSTATE (RL_STATE_NUMERICARG); + return (1); + } +} + +static int +rl_vi_domove_getchar (m) + _rl_vimotion_cxt *m; +{ + int c; + + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + return c; +} + +#if defined (READLINE_CALLBACKS) +int +_rl_vi_domove_callback (m) + _rl_vimotion_cxt *m; +{ + int c, r; + + m->motion = c = rl_vi_domove_getchar (m); + /* XXX - what to do if this returns -1? Should we return 1 for eof to + callback code? */ + r = rl_domove_read_callback (m); + + return ((r == 0) ? r : 1); /* normalize return values */ +} +#endif + +/* This code path taken when not in callback mode. */ +int +rl_vi_domove (x, ignore) + int x, *ignore; +{ + int r; + _rl_vimotion_cxt *m; + + m = _rl_vimvcxt; + *ignore = m->motion = rl_vi_domove_getchar (m); + + if (m->motion < 0) + { + m->motion = 0; + return -1; + } + + return (rl_domove_read_callback (m)); +} + +static int +vi_delete_dispatch (m) + _rl_vimotion_cxt *m; +{ + /* These are the motion commands that do not require adjusting the + mark. */ + if (((strchr (" l|h^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) && + (rl_mark < rl_end)) + rl_mark++; + + rl_kill_text (rl_point, rl_mark); + return (0); +} + +int +rl_vi_delete_to (count, key) + int count, key; +{ + int c, r; + + _rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key); + _rl_vimvcxt->start = rl_point; + + rl_mark = rl_point; + if (_rl_uppercase_p (key)) + { + _rl_vimvcxt->motion = '$'; + r = rl_domove_motion_callback (_rl_vimvcxt); + } + else if (vi_redoing) + { + _rl_vimvcxt->motion = _rl_vi_last_motion; + r = rl_domove_motion_callback (_rl_vimvcxt); + } +#if defined (READLINE_CALLBACKS) + else if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + RL_SETSTATE (RL_STATE_VIMOTION); + return (0); + } +#endif + else + r = rl_vi_domove (key, &c); + + if (r < 0) + { + rl_ding (); + r = -1; + } + + _rl_mvcxt_dispose (_rl_vimvcxt); + _rl_vimvcxt = 0; + + return r; +} + +static int +vi_change_dispatch (m) + _rl_vimotion_cxt *m; +{ + /* These are the motion commands that do not require adjusting the + mark. c[wW] are handled by special-case code in rl_vi_domove(), + and already leave the mark at the correct location. */ + if (((strchr (" l|hwW^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) && + (rl_mark < rl_end)) + rl_mark++; + + /* The cursor never moves with c[wW]. */ + if ((_rl_to_upper (m->motion) == 'W') && rl_point < m->start) + rl_point = m->start; + + if (vi_redoing) + { + if (vi_insert_buffer && *vi_insert_buffer) + rl_begin_undo_group (); + rl_delete_text (rl_point, rl_mark); + if (vi_insert_buffer && *vi_insert_buffer) + { + rl_insert_text (vi_insert_buffer); + rl_end_undo_group (); + } + } + else + { + rl_begin_undo_group (); /* to make the `u' command work */ + rl_kill_text (rl_point, rl_mark); + /* `C' does not save the text inserted for undoing or redoing. */ + if (_rl_uppercase_p (m->key) == 0) + _rl_vi_doing_insert = 1; + /* XXX -- TODO -- use m->numericarg? */ + rl_vi_start_inserting (m->key, rl_numeric_arg, rl_arg_sign); + } + + return (0); +} + +int +rl_vi_change_to (count, key) + int count, key; +{ + int c, r; + + _rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key); + _rl_vimvcxt->start = rl_point; + + rl_mark = rl_point; + if (_rl_uppercase_p (key)) + { + _rl_vimvcxt->motion = '$'; + r = rl_domove_motion_callback (_rl_vimvcxt); + } + else if (vi_redoing) + { + _rl_vimvcxt->motion = _rl_vi_last_motion; + r = rl_domove_motion_callback (_rl_vimvcxt); + } +#if defined (READLINE_CALLBACKS) + else if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + RL_SETSTATE (RL_STATE_VIMOTION); + return (0); + } +#endif + else + r = rl_vi_domove (key, &c); + + if (r < 0) + { + rl_ding (); + r = -1; /* normalize return value */ + } + + _rl_mvcxt_dispose (_rl_vimvcxt); + _rl_vimvcxt = 0; + + return r; +} + +static int +vi_yank_dispatch (m) + _rl_vimotion_cxt *m; +{ + /* These are the motion commands that do not require adjusting the + mark. */ + if (((strchr (" l|h^0%bBFT`", m->motion) == 0) && (rl_point >= m->start)) && + (rl_mark < rl_end)) + rl_mark++; + + rl_begin_undo_group (); + rl_kill_text (rl_point, rl_mark); + rl_end_undo_group (); + rl_do_undo (); + rl_point = m->start; + + return (0); +} + +int +rl_vi_yank_to (count, key) + int count, key; +{ + int c, r; + + _rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key); + _rl_vimvcxt->start = rl_point; + + rl_mark = rl_point; + if (_rl_uppercase_p (key)) + { + _rl_vimvcxt->motion = '$'; + r = rl_domove_motion_callback (_rl_vimvcxt); + } +#if defined (READLINE_CALLBACKS) + else if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + RL_SETSTATE (RL_STATE_VIMOTION); + return (0); + } +#endif + else + r = rl_vi_domove (key, &c); + + if (r < 0) + { + rl_ding (); + r = -1; + } + + _rl_mvcxt_dispose (_rl_vimvcxt); + _rl_vimvcxt = 0; + + return r; +} + +static int +vidomove_dispatch (m) + _rl_vimotion_cxt *m; +{ + int r; + + switch (m->op) + { + case VIM_DELETE: + r = vi_delete_dispatch (m); + break; + case VIM_CHANGE: + r = vi_change_dispatch (m); + break; + case VIM_YANK: + r = vi_yank_dispatch (m); + break; + default: + _rl_errmsg ("vidomove_dispatch: unknown operator %d", m->op); + r = 1; + break; + } + + RL_UNSETSTATE (RL_STATE_VIMOTION); + return r; +} + +int +rl_vi_rubout (count, key) + int count, key; +{ + int opoint; + + if (count < 0) + return (rl_vi_delete (-count, key)); + + if (rl_point == 0) + { + rl_ding (); + return -1; + } + + opoint = rl_point; + if (count > 1 && MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_backward_char (count, key); + else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else + rl_point -= count; + + if (rl_point < 0) + rl_point = 0; + + rl_kill_text (rl_point, opoint); + + return (0); +} + +int +rl_vi_delete (count, key) + int count, key; +{ + int end; + + if (count < 0) + return (rl_vi_rubout (-count, key)); + + if (rl_end == 0) + { + rl_ding (); + return -1; + } + + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); + else + end = rl_point + count; + + if (end >= rl_end) + end = rl_end; + + rl_kill_text (rl_point, end); + + if (rl_point > 0 && rl_point == rl_end) + rl_backward_char (1, key); + + return (0); +} + +int +rl_vi_back_to_indent (count, key) + int count, key; +{ + rl_beg_of_line (1, key); + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + return (0); +} + +int +rl_vi_first_print (count, key) + int count, key; +{ + return (rl_vi_back_to_indent (1, key)); +} + +static int _rl_cs_dir, _rl_cs_orig_dir; + +#if defined (READLINE_CALLBACKS) +static int +_rl_vi_callback_char_search (data) + _rl_callback_generic_arg *data; +{ + int c; +#if defined (HANDLE_MULTIBYTE) + c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); +#else + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); +#endif + + if (c <= 0) + return -1; + +#if !defined (HANDLE_MULTIBYTE) + _rl_vi_last_search_char = c; +#endif + + _rl_callback_func = 0; + _rl_want_redisplay = 1; + +#if defined (HANDLE_MULTIBYTE) + return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen)); +#else + return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_char)); +#endif +} +#endif + +int +rl_vi_char_search (count, key) + int count, key; +{ + int c; +#if defined (HANDLE_MULTIBYTE) + static char *target; + static int tlen; +#else + static char target; +#endif + + if (key == ';' || key == ',') + { + if (_rl_cs_orig_dir == 0) + return -1; +#if defined (HANDLE_MULTIBYTE) + if (_rl_vi_last_search_mblen == 0) + return -1; +#else + if (_rl_vi_last_search_char == 0) + return -1; +#endif + _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir; + } + else + { + switch (key) + { + case 't': + _rl_cs_orig_dir = _rl_cs_dir = FTO; + break; + + case 'T': + _rl_cs_orig_dir = _rl_cs_dir = BTO; + break; + + case 'f': + _rl_cs_orig_dir = _rl_cs_dir = FFIND; + break; + + case 'F': + _rl_cs_orig_dir = _rl_cs_dir = BFIND; + break; + } + + if (vi_redoing) + { + /* set target and tlen below */ + } +#if defined (READLINE_CALLBACKS) + else if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = _rl_callback_data_alloc (count); + _rl_callback_data->i1 = _rl_cs_dir; + _rl_callback_func = _rl_vi_callback_char_search; + return (0); + } +#endif + else + { +#if defined (HANDLE_MULTIBYTE) + c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); + if (c <= 0) + return -1; + _rl_vi_last_search_mblen = c; +#else + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (c < 0) + return -1; + _rl_vi_last_search_char = c; +#endif + } + } + +#if defined (HANDLE_MULTIBYTE) + target = _rl_vi_last_search_mbchar; + tlen = _rl_vi_last_search_mblen; +#else + target = _rl_vi_last_search_char; +#endif + +#if defined (HANDLE_MULTIBYTE) + return (_rl_char_search_internal (count, _rl_cs_dir, target, tlen)); +#else + return (_rl_char_search_internal (count, _rl_cs_dir, target)); +#endif +} + +/* Match brackets */ +int +rl_vi_match (ignore, key) + int ignore, key; +{ + int count = 1, brack, pos, tmp, pre; + + pos = rl_point; + if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) + { + pre = rl_point; + rl_forward_char (1, key); + if (pre == rl_point) + break; + } + } + else + while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 && + rl_point < rl_end - 1) + rl_forward_char (1, key); + + if (brack <= 0) + { + rl_point = pos; + rl_ding (); + return -1; + } + } + + pos = rl_point; + + if (brack < 0) + { + while (count) + { + tmp = pos; + if (MB_CUR_MAX == 1 || rl_byte_oriented) + pos--; + else + { + pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY); + if (tmp == pos) + pos--; + } + if (pos >= 0) + { + int b = rl_vi_bracktype (rl_line_buffer[pos]); + if (b == -brack) + count--; + else if (b == brack) + count++; + } + else + { + rl_ding (); + return -1; + } + } + } + else + { /* brack > 0 */ + while (count) + { + if (MB_CUR_MAX == 1 || rl_byte_oriented) + pos++; + else + pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY); + + if (pos < rl_end) + { + int b = rl_vi_bracktype (rl_line_buffer[pos]); + if (b == -brack) + count--; + else if (b == brack) + count++; + } + else + { + rl_ding (); + return -1; + } + } + } + rl_point = pos; + return (0); +} + +int +rl_vi_bracktype (c) + int c; +{ + switch (c) + { + case '(': return 1; + case ')': return -1; + case '[': return 2; + case ']': return -2; + case '{': return 3; + case '}': return -3; + default: return 0; + } +} + +static int +_rl_vi_change_char (count, c, mb) + int count, c; + char *mb; +{ + int p; + + if (c == '\033' || c == CTRL ('C')) + return -1; + + rl_begin_undo_group (); + while (count-- && rl_point < rl_end) + { + p = rl_point; + rl_vi_delete (1, c); + if (rl_point < p) /* Did we retreat at EOL? */ + rl_point++; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_insert_text (mb); + else +#endif + _rl_insert_char (1, c); + } + + /* The cursor shall be left on the last character changed. */ + rl_backward_char (1, c); + + rl_end_undo_group (); + + return (0); +} + +static int +_rl_vi_callback_getchar (mb, mlen) + char *mb; + int mlen; +{ + int c; + + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (c < 0) + return -1; + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + c = _rl_read_mbstring (c, mb, mlen); +#endif + + return c; +} + +#if defined (READLINE_CALLBACKS) +static int +_rl_vi_callback_change_char (data) + _rl_callback_generic_arg *data; +{ + int c; + char mb[MB_LEN_MAX]; + + _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); + + if (c < 0) + return -1; + + _rl_callback_func = 0; + _rl_want_redisplay = 1; + + return (_rl_vi_change_char (data->count, c, mb)); +} +#endif + +int +rl_vi_change_char (count, key) + int count, key; +{ + int c; + char mb[MB_LEN_MAX]; + + if (vi_redoing) + { + c = _rl_vi_last_replacement; + mb[0] = c; + mb[1] = '\0'; + } +#if defined (READLINE_CALLBACKS) + else if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = _rl_callback_data_alloc (count); + _rl_callback_func = _rl_vi_callback_change_char; + return (0); + } +#endif + else + _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); + + if (c < 0) + return -1; + + return (_rl_vi_change_char (count, c, mb)); +} + +int +rl_vi_subst (count, key) + int count, key; +{ + /* If we are redoing, rl_vi_change_to will stuff the last motion char */ + if (vi_redoing == 0) + rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */ + + return (rl_vi_change_to (count, 'c')); +} + +int +rl_vi_overstrike (count, key) + int count, key; +{ + if (_rl_vi_doing_insert == 0) + { + _rl_vi_doing_insert = 1; + rl_begin_undo_group (); + } + + if (count > 0) + { + _rl_overwrite_char (count, key); + vi_replace_count += count; + } + + return (0); +} + +int +rl_vi_overstrike_delete (count, key) + int count, key; +{ + int i, s; + + for (i = 0; i < count; i++) + { + if (vi_replace_count == 0) + { + rl_ding (); + break; + } + s = rl_point; + + if (rl_do_undo ()) + vi_replace_count--; + + if (rl_point == s) + rl_backward_char (1, key); + } + + if (vi_replace_count == 0 && _rl_vi_doing_insert) + { + rl_end_undo_group (); + rl_do_undo (); + _rl_vi_doing_insert = 0; + } + return (0); +} + +int +rl_vi_replace (count, key) + int count, key; +{ + int i; + + vi_replace_count = 0; + + if (vi_replace_map == 0) + { + vi_replace_map = rl_make_bare_keymap (); + + for (i = 0; i < ' '; i++) + if (vi_insertion_keymap[i].type == ISFUNC) + vi_replace_map[i].function = vi_insertion_keymap[i].function; + + for (i = ' '; i < KEYMAP_SIZE; i++) + vi_replace_map[i].function = rl_vi_overstrike; + + vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete; + + /* Make sure these are what we want. */ + vi_replace_map[ESC].function = rl_vi_movement_mode; + vi_replace_map[RETURN].function = rl_newline; + vi_replace_map[NEWLINE].function = rl_newline; + + /* If the normal vi insertion keymap has ^H bound to erase, do the + same here. Probably should remove the assignment to RUBOUT up + there, but I don't think it will make a difference in real life. */ + if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC && + vi_insertion_keymap[CTRL ('H')].function == rl_rubout) + vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete; + + } + + rl_vi_start_inserting (key, 1, rl_arg_sign); + + _rl_vi_last_key_before_insert = key; + _rl_keymap = vi_replace_map; + + return (0); +} + +#if 0 +/* Try to complete the word we are standing on or the word that ends with + the previous character. A space matches everything. Word delimiters are + space and ;. */ +int +rl_vi_possible_completions() +{ + int save_pos = rl_point; + + if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';') + { + while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' && + rl_line_buffer[rl_point] != ';') + rl_point++; + } + else if (rl_line_buffer[rl_point - 1] == ';') + { + rl_ding (); + return (0); + } + + rl_possible_completions (); + rl_point = save_pos; + + return (0); +} +#endif + +/* Functions to save and restore marks. */ +static int +_rl_vi_set_mark () +{ + int ch; + + RL_SETSTATE(RL_STATE_MOREINPUT); + ch = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */ + { + rl_ding (); + return -1; + } + ch -= 'a'; + vi_mark_chars[ch] = rl_point; + return 0; +} + +#if defined (READLINE_CALLBACKS) +static int +_rl_vi_callback_set_mark (data) + _rl_callback_generic_arg *data; +{ + _rl_callback_func = 0; + _rl_want_redisplay = 1; + + return (_rl_vi_set_mark ()); +} +#endif + +int +rl_vi_set_mark (count, key) + int count, key; +{ +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = 0; + _rl_callback_func = _rl_vi_callback_set_mark; + return (0); + } +#endif + + return (_rl_vi_set_mark ()); +} + +static int +_rl_vi_goto_mark () +{ + int ch; + + RL_SETSTATE(RL_STATE_MOREINPUT); + ch = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (ch == '`') + { + rl_point = rl_mark; + return 0; + } + else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */ + { + rl_ding (); + return -1; + } + + ch -= 'a'; + if (vi_mark_chars[ch] == -1) + { + rl_ding (); + return -1; + } + rl_point = vi_mark_chars[ch]; + return 0; +} + +#if defined (READLINE_CALLBACKS) +static int +_rl_vi_callback_goto_mark (data) + _rl_callback_generic_arg *data; +{ + _rl_callback_func = 0; + _rl_want_redisplay = 1; + + return (_rl_vi_goto_mark ()); +} +#endif + +int +rl_vi_goto_mark (count, key) + int count, key; +{ +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = 0; + _rl_callback_func = _rl_vi_callback_goto_mark; + return (0); + } +#endif + + return (_rl_vi_goto_mark ()); +} +#endif /* VI_MODE */ diff --git a/parse.y b/parse.y index 16e72184c..4358a5f34 100644 --- a/parse.y +++ b/parse.y @@ -5989,6 +5989,8 @@ save_input_line_state (ls) /* force reallocation */ shell_input_line = 0; shell_input_line_size = shell_input_line_len = shell_input_line_index = 0; + + return ls; } void diff --git a/parse.y~ b/parse.y~ index afa51e37f..16e72184c 100644 --- a/parse.y~ +++ b/parse.y~ @@ -2532,26 +2532,14 @@ static int esacs_needed_count; void gather_here_documents () { - int r, save_lithist; + int r; r = 0; - save_lithist = -1; while (need_here_doc) { parser_state |= PST_HEREDOC; -#if defined (HISTORY) - if (remember_on_history) - { - save_lithist = literal_history; -/* literal_history = 1; */ - } -#endif make_here_document (redir_stack[r++], line_number); parser_state &= ~PST_HEREDOC; -#if defined (HISTORY) - if (remember_on_history && save_lithist >= 0) - literal_history = save_lithist; -#endif need_here_doc--; } } diff --git a/patchlevel.h b/patchlevel.h index ed9518404..d85641dcf 100644 --- a/patchlevel.h +++ b/patchlevel.h @@ -25,6 +25,6 @@ regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh looks for to find the patch level (for the sccs version string). */ -#define PATCHLEVEL 10 +#define PATCHLEVEL 20 #endif /* _PATCHLEVEL_H_ */ diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 72ec06a2c..3efcf32d6 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/bash/bash-current +BUILD_DIR=/usr/local/build/chet/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR diff --git a/variables.c~ b/variables.c~ index fca784456..2966545e5 100644 --- a/variables.c~ +++ b/variables.c~ @@ -4482,14 +4482,16 @@ sv_histsize (name) if (legal_number (temp, &num)) { hmax = num; - if (name[4] == 'S') + if (hmax < 0 && name[4] == 'S') + unstifle_history (); /* unstifle history if HISTSIZE < 0 */ + else if (name[4] == 'S') { stifle_history (hmax); hmax = where_history (); if (history_lines_this_session > hmax) history_lines_this_session = hmax; } - else + else if (hmax >= 0) /* truncate HISTFILE if HISTFILESIZE >= 0 */ { history_truncate_file (get_string_value ("HISTFILE"), hmax); if (hmax <= history_lines_in_file) @@ -4522,7 +4524,10 @@ sv_history_control (name) temp = get_string_value (name); if (temp == 0 || *temp == 0) - return; + { + history_control = 0; + return; + } tptr = 0; while (val = extract_colon_unit (temp, &tptr)) -- 2.39.2