diff options
author | Chet Ramey <chet.ramey@case.edu> | 2019-01-07 09:30:21 -0500 |
---|---|---|
committer | Chet Ramey <chet.ramey@case.edu> | 2019-01-07 09:30:21 -0500 |
commit | 8e6ccd0373d77b86ed37a9a7d232ccfea3d6670c (patch) | |
tree | 58bce2928cd55511defa0029ba70b884053c3fdb /histexpand.c | |
parent | 57ea39840aebbb34571df1586acc66783b3368d0 (diff) | |
download | readline-8e6ccd0373d77b86ed37a9a7d232ccfea3d6670c.tar.gz |
readline-8.0 distribution sources and documentationreadline-8.0
Diffstat (limited to 'histexpand.c')
-rw-r--r-- | histexpand.c | 165 |
1 files changed, 80 insertions, 85 deletions
diff --git a/histexpand.c b/histexpand.c index b84a6b8..adcf5dc 100644 --- a/histexpand.c +++ b/histexpand.c @@ -1,6 +1,6 @@ /* histexpand.c -- history expansion. */ -/* Copyright (C) 1989-2015 Free Software Foundation, Inc. +/* Copyright (C) 1989-2018 Free Software Foundation, Inc. This file contains the GNU History Library (History), a set of routines for managing the text of previously typed lines. @@ -55,6 +55,8 @@ #define slashify_in_quotes "\\`\"$" +#define fielddelim(c) (whitespace(c) || (c) == '\n') + typedef int _hist_search_func_t PARAMS((const char *, int)); static char error_pointer; @@ -107,6 +109,8 @@ char *history_word_delimiters = HISTORY_WORD_DELIMITERS; particular history expansion should be performed. */ rl_linebuf_func_t *history_inhibit_expansion_function; +int history_quoting_state = 0; + /* **************************************************************** */ /* */ /* History Expansion */ @@ -132,10 +136,7 @@ static char *search_match; So you might call this function like: line = get_history_event ("!echo:p", &index, 0); */ char * -get_history_event (string, caller_index, delimiting_quote) - const char *string; - int *caller_index; - int delimiting_quote; +get_history_event (const char *string, int *caller_index, int delimiting_quote) { register int i; register char c; @@ -316,9 +317,7 @@ get_history_event (string, caller_index, delimiting_quote) to the closing single quote. FLAGS currently used to allow backslash to escape a single quote (e.g., for bash $'...'). */ static void -hist_string_extract_single_quoted (string, sindex, flags) - char *string; - int *sindex, flags; +hist_string_extract_single_quoted (char *string, int *sindex, int flags) { register int i; @@ -332,8 +331,7 @@ hist_string_extract_single_quoted (string, sindex, flags) } static char * -quote_breaks (s) - char *s; +quote_breaks (char *s) { register char *p, *r; char *ret; @@ -374,9 +372,7 @@ quote_breaks (s) } static char * -hist_error(s, start, current, errtype) - char *s; - int start, current, errtype; +hist_error(char *s, int start, int current, int errtype) { char *temp; const char *emsg; @@ -433,9 +429,7 @@ hist_error(s, start, current, errtype) subst_rhs is allowed to be set to the empty string. */ static char * -get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr) - char *str; - int *iptr, delimiter, is_rhs, *lenptr; +get_subst_pattern (char *str, int *iptr, int delimiter, int is_rhs, int *lenptr) { register int si, i, j, k; char *s; @@ -490,7 +484,7 @@ get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr) } static void -postproc_subst_rhs () +postproc_subst_rhs (void) { char *new; int i, j, new_size; @@ -526,12 +520,9 @@ postproc_subst_rhs () if the `p' modifier was supplied and the caller should just print the returned string. Returns the new index into string in *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */ +/* need current line for !# */ static int -history_expand_internal (string, start, qc, end_index_ptr, ret_string, current_line) - char *string; - int start, qc, *end_index_ptr; - char **ret_string; - char *current_line; /* for !# */ +history_expand_internal (char *string, int start, int qc, int *end_index_ptr, char **ret_string, char *current_line) { int i, n, starting_index; int substitute_globally, subst_bywords, want_quotes, print_only; @@ -780,7 +771,7 @@ history_expand_internal (string, start, qc, end_index_ptr, ret_string, current_l the last time. */ if (subst_bywords && si > we) { - for (; temp[si] && whitespace (temp[si]); si++) + for (; temp[si] && fielddelim (temp[si]); si++) ; ws = si; we = history_tokenize_word (temp, si); @@ -908,9 +899,7 @@ history_expand_internal (string, start, qc, end_index_ptr, ret_string, current_l while (0) int -history_expand (hstring, output) - char *hstring; - char **output; +history_expand (char *hstring, char **output) { register int j; int i, r, l, passc, cc, modified, eindex, only_printing, dquote, squote, flag; @@ -976,7 +965,22 @@ history_expand (hstring, output) /* `!' followed by one of the characters in history_no_expand_chars is NOT an expansion. */ - for (i = dquote = squote = 0; string[i]; i++) + dquote = history_quoting_state == '"'; + squote = history_quoting_state == '\''; + + /* If the calling application tells us we are already reading a + single-quoted string, consume the rest of the string right now + and then go on. */ + i = 0; + if (squote && history_quotes_inhibit_expansion) + { + hist_string_extract_single_quoted (string, &i, 0); + squote = 0; + if (string[i]) + i++; + } + + for ( ; string[i]; i++) { #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) @@ -1064,7 +1068,29 @@ history_expand (hstring, output) } /* Extract and perform the substitution. */ - for (passc = dquote = squote = i = j = 0; i < l; i++) + dquote = history_quoting_state == '"'; + squote = history_quoting_state == '\''; + + /* If the calling application tells us we are already reading a + single-quoted string, consume the rest of the string right now + and then go on. */ + i = j = 0; + if (squote && history_quotes_inhibit_expansion) + { + int c; + + hist_string_extract_single_quoted (string, &i, 0); + squote = 0; + for (c = 0; c < i; c++) + ADD_CHAR (string[c]); + if (string[i]) + { + ADD_CHAR (string[i]); + i++; + } + } + + for (passc = 0; i < l; i++) { int qc, tchar = string[i]; @@ -1249,9 +1275,7 @@ history_expand (hstring, output) CALLER_INDEX is the offset in SPEC to start looking; it is updated to point to just after the last character parsed. */ static char * -get_history_word_specifier (spec, from, caller_index) - char *spec, *from; - int *caller_index; +get_history_word_specifier (char *spec, char *from, int *caller_index) { register int i = *caller_index; int first, last; @@ -1357,9 +1381,7 @@ get_history_word_specifier (spec, from, caller_index) tokens, so that FIRST = -1 means the next to last token on the line). If LAST is `$' the last arg from STRING is used. */ char * -history_arg_extract (first, last, string) - int first, last; - const char *string; +history_arg_extract (int first, int last, const char *string) { register int i, len; char *result; @@ -1418,9 +1440,7 @@ history_arg_extract (first, last, string) } static int -history_tokenize_word (string, ind) - const char *string; - int ind; +history_tokenize_word (const char *string, int ind) { register int i, j; int delimiter, nestdelim, delimopen; @@ -1428,7 +1448,7 @@ history_tokenize_word (string, ind) i = ind; delimiter = nestdelim = 0; - if (member (string[i], "()\n")) + if (member (string[i], "()\n")) /* XXX - included \n, but why? been here forever */ { i++; return i; @@ -1450,11 +1470,11 @@ history_tokenize_word (string, ind) } } - if (member (string[i], "<>;&|$")) + if (member (string[i], "<>;&|")) { int peek = string[i + 1]; - if (peek == string[i] && peek != '$') + if (peek == string[i]) { if (peek == '<' && string[i + 2] == '-') i++; @@ -1477,9 +1497,8 @@ history_tokenize_word (string, ind) i += 2; return i; } - /* XXX - separated out for later -- bash-4.2 */ - else if ((peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */ - (peek == '(' && string[i] == '$')) /*)*/ + /* XXX - process substitution -- separated out for later -- bash-4.2 */ + else if (peek == '(' && (string[i] == '>' || string[i] == '<')) /*)*/ { i += 2; delimopen = '('; @@ -1487,34 +1506,9 @@ history_tokenize_word (string, ind) nestdelim = 1; goto get_word; } -#if 0 - else if (peek == '\'' && string[i] == '$') - { - i += 2; /* XXX */ - return i; - } -#endif - if (string[i] != '$') - { - i++; - return i; - } - } - - /* same code also used for $(...)/<(...)/>(...) above */ - if (member (string[i], "!@?+*")) - { - int peek = string[i + 1]; - - if (peek == '(') /*)*/ - { - /* Shell extended globbing patterns */ - i += 2; - delimopen = '('; - delimiter = ')'; /* XXX - not perfect */ - nestdelim = 1; - } + i++; + return i; } get_word: @@ -1559,6 +1553,16 @@ get_word: continue; } + /* Command and process substitution; shell extended globbing patterns */ + if (nestdelim == 0 && delimiter == 0 && member (string[i], "<>$!@?+*") && string[i+1] == '(') /*)*/ + { + i += 2; + delimopen = '('; + delimiter = ')'; + nestdelim = 1; + continue; + } + if (delimiter == 0 && (member (string[i], history_word_delimiters))) break; @@ -1570,9 +1574,7 @@ get_word: } static char * -history_substring (string, start, end) - const char *string; - int start, end; +history_substring (const char *string, int start, int end) { register int len; register char *result; @@ -1589,9 +1591,7 @@ history_substring (string, start, end) WIND. The position in the returned array of strings is returned in *INDP. */ static char ** -history_tokenize_internal (string, wind, indp) - const char *string; - int wind, *indp; +history_tokenize_internal (const char *string, int wind, int *indp) { char **result; register int i, start, result_index, size; @@ -1606,7 +1606,7 @@ history_tokenize_internal (string, wind, indp) for (i = result_index = size = 0, result = (char **)NULL; string[i]; ) { /* Skip leading whitespace. */ - for (; string[i] && whitespace (string[i]); i++) + for (; string[i] && fielddelim (string[i]); i++) ; if (string[i] == 0 || string[i] == history_comment_char) return (result); @@ -1644,17 +1644,14 @@ history_tokenize_internal (string, wind, indp) /* Return an array of tokens, much as the shell might. The tokens are parsed out of STRING. */ char ** -history_tokenize (string) - const char *string; +history_tokenize (const char *string) { return (history_tokenize_internal (string, -1, (int *)NULL)); } /* Free members of WORDS from START to an empty string */ static void -freewords (words, start) - char **words; - int start; +freewords (char **words, int start) { register int i; @@ -1666,9 +1663,7 @@ freewords (words, start) in the history line LINE. Used to save the word matched by the last history !?string? search. */ static char * -history_find_word (line, ind) - char *line; - int ind; +history_find_word (char *line, int ind) { char **words, *s; int i, wind; |