Bash-4.3 distribution sources and documentation
[platform/upstream/bash.git] / lib / readline / histexpand.c
index 8fb3798..4899b9d 100644 (file)
@@ -1,6 +1,6 @@
 /* histexpand.c -- history expansion. */
 
-/* Copyright (C) 1989-2010 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2012 Free Software Foundation, Inc.
 
    This file contains the GNU History Library (History), a set of
    routines for managing the text of previously typed lines.
@@ -272,6 +272,8 @@ get_history_event (string, caller_index, delimiting_quote)
       if (local_index == 0 || substring_okay)
        {
          entry = current_history ();
+         if (entry == 0)
+           FAIL_SEARCH ();
          history_offset = history_length;
        
          /* If this was a substring search, then remember the
@@ -519,9 +521,9 @@ postproc_subst_rhs ()
    the returned string.  Returns the new index into string in
    *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
 static int
-history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
+history_expand_internal (string, start, qc, end_index_ptr, ret_string, current_line)
      char *string;
-     int start, *end_index_ptr;
+     int start, qc, *end_index_ptr;
      char **ret_string;
      char *current_line;       /* for !# */
 {
@@ -557,30 +559,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
       event = current_line;
     }
   else
-    {
-      int quoted_search_delimiter = 0;
-
-      /* If the character before this `!' is a double or single
-        quote, then this expansion takes place inside of the
-        quoted string.  If we have to search for some text ("!foo"),
-        allow the delimiter to end the search string. */
-#if defined (HANDLE_MULTIBYTE)
-      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-       {
-         int ch, l;
-         l = _rl_find_prev_mbchar (string, i, MB_FIND_ANY);
-         ch = string[l];
-         /* XXX - original patch had i - 1 ???  If i == 0 it would fail. */
-         if (i && (ch == '\'' || ch == '"'))
-           quoted_search_delimiter = ch;
-       }
-      else
-#endif /* HANDLE_MULTIBYTE */    
-       if (i && (string[i - 1] == '\'' || string[i - 1] == '"'))
-         quoted_search_delimiter = string[i - 1];
-
-      event = get_history_event (string, &i, quoted_search_delimiter);
-    }
+    event = get_history_event (string, &i, qc);
          
   if (event == 0)
     {
@@ -854,7 +833,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
        }
       i += 2;
     }
-  /* Done with modfiers. */
+  /* Done with modifiers. */
   /* Believe it or not, we have to back the pointer up by one. */
   --i;
 
@@ -928,7 +907,7 @@ history_expand (hstring, output)
      char **output;
 {
   register int j;
-  int i, r, l, passc, cc, modified, eindex, only_printing, dquote, flag;
+  int i, r, l, passc, cc, modified, eindex, only_printing, dquote, squote, flag;
   char *string;
 
   /* The output string, and its length. */
@@ -991,7 +970,7 @@ history_expand (hstring, output)
 
       /* `!' followed by one of the characters in history_no_expand_chars
         is NOT an expansion. */
-      for (i = dquote = 0; string[i]; i++)
+      for (i = dquote = squote = 0; string[i]; i++)
        {
 #if defined (HANDLE_MULTIBYTE)
          if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
@@ -1022,6 +1001,13 @@ history_expand (hstring, output)
            {
              if (cc == 0 || member (cc, history_no_expand_chars))
                continue;
+             /* DQUOTE won't be set unless history_quotes_inhibit_expansion
+                is set.  The idea here is to treat double-quoted strings the
+                same as the word outside double quotes; in effect making the
+                double quote part of history_no_expand_chars when DQUOTE is
+                set. */
+             else if (dquote && cc == '"')
+               continue;
              /* If the calling application has set
                 history_inhibit_expansion_function to a function that checks
                 for special cases that should not be history expanded,
@@ -1071,9 +1057,9 @@ history_expand (hstring, output)
     }
 
   /* Extract and perform the substitution. */
-  for (passc = dquote = i = j = 0; i < l; i++)
+  for (passc = dquote = squote = i = j = 0; i < l; i++)
     {
-      int tchar = string[i];
+      int qc, tchar = string[i];
 
       if (passc)
        {
@@ -1130,8 +1116,14 @@ history_expand (hstring, output)
        case '\'':
          {
            /* If history_quotes_inhibit_expansion is set, single quotes
-              inhibit history expansion. */
-           if (dquote == 0 && history_quotes_inhibit_expansion)
+              inhibit history expansion, otherwise they are treated like
+              double quotes. */
+           if (squote)
+             {
+               squote = 0;
+               ADD_CHAR (tchar);
+             }
+           else if (dquote == 0 && history_quotes_inhibit_expansion)
              {
                int quote, slen;
 
@@ -1146,6 +1138,11 @@ history_expand (hstring, output)
                ADD_STRING (temp);
                xfree (temp);
              }
+           else if (dquote == 0 && squote == 0 && history_quotes_inhibit_expansion == 0)
+             {
+               squote = 1;
+               ADD_CHAR (string[i]);
+             }
            else
              ADD_CHAR (string[i]);
            break;
@@ -1171,6 +1168,7 @@ history_expand (hstring, output)
             characters in history_no_expand_chars, then it is not a
             candidate for expansion of any kind. */
          if (cc == 0 || member (cc, history_no_expand_chars) ||
+                        (dquote && cc == '"') ||
                         (history_inhibit_expansion_function && (*history_inhibit_expansion_function) (string, i)))
            {
              ADD_CHAR (string[i]);
@@ -1196,8 +1194,8 @@ history_expand (hstring, output)
              break;
            }
 #endif
-
-         r = history_expand_internal (string, i, &eindex, &temp, result);
+         qc = squote ? '\'' : (dquote ? '"' : 0);
+         r = history_expand_internal (string, i, qc, &eindex, &temp, result);
          if (r < 0)
            {
              *output = temp;