Imported from ../bash-2.04.tar.gz.
[platform/upstream/bash.git] / lib / readline / histexpand.c
index de71d78..78da3e5 100644 (file)
@@ -7,7 +7,7 @@
 
    The Library is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 1, or (at your option)
+   the Free Software Foundation; either version 2, or (at your option)
    any later version.
 
    The Library is distributed in the hope that it will be useful, but
@@ -18,7 +18,7 @@
    The GNU General Public License is often shipped with GNU software, and
    is generally kept in a file called COPYING or LICENSE.  If you do not
    have a copy of the license, write to the Free Software Foundation,
-   675 Mass Ave, Cambridge, MA 02139, USA. */
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 
 #define READLINE_LIBRARY
 
@@ -35,6 +35,9 @@
 #endif /* HAVE_STDLIB_H */
 
 #if defined (HAVE_UNISTD_H)
+#  ifndef _MINIX
+#    include <sys/types.h>
+#  endif
 #  include <unistd.h>
 #endif
 
 #include "history.h"
 #include "histlib.h"
 
+#include "rlshell.h"
+#include "xmalloc.h"
+
+#define HISTORY_WORD_DELIMITERS                " \t\n;&()|<>"
+#define HISTORY_QUOTE_CHARACTERS       "\"'`"
+
 static char error_pointer;
 
 static char *subst_lhs;
@@ -54,15 +63,10 @@ static char *subst_rhs;
 static int subst_lhs_len;
 static int subst_rhs_len;
 
-static char *get_history_word_specifier ();
-static char *history_find_word ();
-
-extern int history_offset;
+static char *get_history_word_specifier __P((char *, char *, int *));
+static char *history_find_word __P((char *, int));
 
-extern char *single_quote ();
-static char *quote_breaks ();
-
-extern char *xmalloc (), *xrealloc ();
+static char *quote_breaks __P((char *));
 
 /* Variables exported by this file. */
 /* The character that represents the start of a history expansion
@@ -359,6 +363,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;
@@ -648,15 +656,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);
 
@@ -668,6 +667,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)
@@ -823,8 +831,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. */
@@ -852,7 +860,18 @@ 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;
@@ -867,6 +886,8 @@ history_expand (hstring, output)
              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. */
@@ -904,6 +925,8 @@ history_expand (hstring, output)
 
       if (tchar == history_expansion_char)
        tchar = -3;
+      else if (tchar == history_comment_char)
+       tchar = -2;
 
       switch (tchar)
        {
@@ -939,6 +962,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];
 
@@ -1238,7 +1274,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++)
@@ -1262,10 +1298,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];
        }