summaryrefslogtreecommitdiff
path: root/histexpand.c
diff options
context:
space:
mode:
authorChet Ramey <chet.ramey@case.edu>2019-01-07 09:30:21 -0500
committerChet Ramey <chet.ramey@case.edu>2019-01-07 09:30:21 -0500
commit8e6ccd0373d77b86ed37a9a7d232ccfea3d6670c (patch)
tree58bce2928cd55511defa0029ba70b884053c3fdb /histexpand.c
parent57ea39840aebbb34571df1586acc66783b3368d0 (diff)
downloadreadline-8e6ccd0373d77b86ed37a9a7d232ccfea3d6670c.tar.gz
readline-8.0 distribution sources and documentationreadline-8.0
Diffstat (limited to 'histexpand.c')
-rw-r--r--histexpand.c165
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;