Import readline 8.0
[deliverable/binutils-gdb.git] / readline / histexpand.c
index b84a6b8ac4b21e3c139a3e5eb66276e8b9f753bf..adcf5dcb4e3cbfdfb29a2904452795e83acdd9ab 100644 (file)
@@ -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;
This page took 0.04046 seconds and 4 git commands to generate.