]> git.ipfire.org Git - thirdparty/bash.git/blobdiff - lib/readline/histexpand.c
Imported from ../bash-2.03.tar.gz.
[thirdparty/bash.git] / lib / readline / histexpand.c
index d916c7441d7d383a0d006a2e3bf74296227b7fb3..392e6d38d9ec771b77019df9272fa42c62d9f22f 100644 (file)
@@ -35,6 +35,9 @@
 #endif /* HAVE_STDLIB_H */
 
 #if defined (HAVE_UNISTD_H)
+#  ifndef _MINIX
+#    include <sys/types.h>
+#  endif
 #  include <unistd.h>
 #endif
 
@@ -47,6 +50,9 @@
 #include "history.h"
 #include "histlib.h"
 
+#define HISTORY_WORD_DELIMITERS                " \t\n;&()|<>"
+#define HISTORY_QUOTE_CHARACTERS       "\"'`"
+
 static char error_pointer;
 
 static char *subst_lhs;
@@ -59,11 +65,7 @@ static char *history_find_word ();
 
 extern int history_offset;
 
-#if defined (SHELL)
 extern char *single_quote ();
-#else
-static char *single_quote ();
-#endif /* !SHELL */
 static char *quote_breaks ();
 
 extern char *xmalloc (), *xrealloc ();
@@ -91,6 +93,10 @@ char *history_no_expand_chars = " \t\n\r=";
    The default is 0. */
 int history_quotes_inhibit_expansion = 0;
 
+/* If set, this points to a function that is called to verify that a
+   particular history expansion should be performed. */
+Function *history_inhibit_expansion_function;
+
 /* **************************************************************** */
 /*                                                                 */
 /*                     History Expansion                           */
@@ -289,38 +295,6 @@ hist_string_extract_single_quoted (string, sindex)
   *sindex = i;
 }
 
-#if !defined (SHELL)
-/* Does shell-like quoting using single quotes. */
-static char *
-single_quote (string)
-     char *string;
-{
-  register int c;
-  char *result, *r, *s;
-
-  result = (char *)xmalloc (3 + (3 * strlen (string)));
-  r = result;
-  *r++ = '\'';
-
-  for (s = string; s && (c = *s); s++)
-    {
-      *r++ = c;
-
-      if (c == '\'')
-       {
-         *r++ = '\\';  /* insert escaped single quote */
-         *r++ = '\'';
-         *r++ = '\'';  /* start new quoted string */
-       }
-    }
-
-  *r++ = '\'';
-  *r = '\0';
-
-  return (result);
-}
-#endif /* !SHELL */
-
 static char *
 quote_breaks (s)
      char *s;
@@ -391,6 +365,10 @@ hist_error(s, start, current, errtype)
       emsg = "unrecognized history modifier";
       elen = 29;
       break;
+    case NO_PREV_SUBST:
+      emsg = "no previous substitution";
+      elen = 24;
+      break;
     default:
       emsg = "unknown expansion error";
       elen = 23;
@@ -680,15 +658,6 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
                      }
                  }
 
-               /* If there is no lhs, the substitution can't succeed. */
-               if (subst_lhs_len == 0)
-                 {
-                   *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
-                   free (result);
-                   free (temp);
-                   return -1;
-                 }
-
                FREE (subst_rhs);
                subst_rhs = get_subst_pattern (string, &i, delimiter, 1, &subst_rhs_len);
 
@@ -700,6 +669,15 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
            else
              i += 2;
 
+           /* If there is no lhs, the substitution can't succeed. */
+           if (subst_lhs_len == 0)
+             {
+               *ret_string = hist_error (string, starting_index, i, NO_PREV_SUBST);
+               free (result);
+               free (temp);
+               return -1;
+             }
+
            l_temp = strlen (temp);
            /* Ignore impossible cases. */
            if (subst_lhs_len > l_temp)
@@ -855,8 +833,8 @@ history_expand (hstring, output)
   only_printing = modified = 0;
   l = strlen (hstring);
 
-  /* Grovel the string.  Only backslash can quote the history escape
-     character.  We also handle arg specifiers. */
+  /* Grovel the string.  Only backslash and single quotes can quote the
+     history escape character.  We also handle arg specifiers. */
 
   /* Before we grovel forever, see if the history_expansion_char appears
      anywhere within the text. */
@@ -884,26 +862,34 @@ history_expand (hstring, output)
       for (i = 0; string[i]; i++)
        {
          cc = string[i + 1];
-         if (string[i] == history_expansion_char)
+         /* The history_comment_char, if set, appearing that the beginning
+            of a word signifies that the rest of the line should not have
+            history expansion performed on it.
+            Skip the rest of the line and break out of the loop. */
+         if (history_comment_char && string[i] == history_comment_char &&
+             (i == 0 || member (string[i - 1], HISTORY_WORD_DELIMITERS)))
+           {
+             while (string[i])
+               i++;
+             break;
+           }
+         else if (string[i] == history_expansion_char)
            {
              if (!cc || member (cc, history_no_expand_chars))
                continue;
-#if defined (SHELL)
-             /* The shell uses ! as a pattern negation character
-                in globbing [...] expressions, so let those pass
-                without expansion. */
-             else if (i > 0 && (string[i - 1] == '[') &&
-                      member (']', string + i + 1))
+             /* If the calling application has set
+                history_inhibit_expansion_function to a function that checks
+                for special cases that should not be history expanded,
+                call the function and skip the expansion if it returns a
+                non-zero value. */
+             else if (history_inhibit_expansion_function &&
+                       (*history_inhibit_expansion_function) (string, i))
                continue;
-             /* The shell uses ! as the indirect expansion character, so
-                let those expansions pass as well. */
-             else if (i > 1 && string[i - 1] == '{' && string[i - 2] == '$' &&
-                      member ('}', string + i + 1))
-               continue;
-#endif /* SHELL */
              else
                break;
            }
+         /* XXX - at some point, might want to extend this to handle
+                  double quotes as well. */
          else if (history_quotes_inhibit_expansion && string[i] == '\'')
            {
              /* If this is bash, single quotes inhibit history expansion. */
@@ -941,6 +927,8 @@ history_expand (hstring, output)
 
       if (tchar == history_expansion_char)
        tchar = -3;
+      else if (tchar == history_comment_char)
+       tchar = -2;
 
       switch (tchar)
        {
@@ -976,6 +964,19 @@ history_expand (hstring, output)
            break;
          }
 
+       case -2:                /* history_comment_char */
+         if (i == 0 || member (string[i - 1], HISTORY_WORD_DELIMITERS))
+           {
+             temp = xmalloc (l - i + 1);
+             strcpy (temp, string + i);
+             ADD_STRING (temp);
+             free (temp);
+             i = l;
+           }
+         else
+           ADD_CHAR (string[i]);
+         break;
+
        case -3:                /* history_expansion_char */
          cc = string[i + 1];
 
@@ -1275,7 +1276,7 @@ history_tokenize_internal (string, wind, indp)
 
       /* Get word from string + i; */
 
-      if (member (string[i], "\"'`"))
+      if (member (string[i], HISTORY_QUOTE_CHARACTERS))
        delimiter = string[i++];
 
       for (; string[i]; i++)
@@ -1299,10 +1300,10 @@ history_tokenize_internal (string, wind, indp)
              continue;
            }
 
-         if (!delimiter && (member (string[i], " \t\n;&()|<>")))
+         if (!delimiter && (member (string[i], HISTORY_WORD_DELIMITERS)))
            break;
 
-         if (!delimiter && member (string[i], "\"'`"))
+         if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))
            delimiter = string[i];
        }