Imported from ../bash-2.05.tar.gz.
[platform/upstream/bash.git] / lib / readline / histexpand.c
index 0dc179a..1c8a1d9 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
 
 #include "history.h"
 #include "histlib.h"
 
+#include "rlshell.h"
+#include "xmalloc.h"
+
 #define HISTORY_WORD_DELIMITERS                " \t\n;&()|<>"
 #define HISTORY_QUOTE_CHARACTERS       "\"'`"
 
+typedef int _hist_search_func_t __P((const char *, int));
+
 static char error_pointer;
 
 static char *subst_lhs;
@@ -60,15 +65,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
@@ -93,9 +93,12 @@ char *history_no_expand_chars = " \t\n\r=";
    The default is 0. */
 int history_quotes_inhibit_expansion = 0;
 
+/* Used to split words by history_tokenize_internal. */
+char *history_word_delimiters = HISTORY_WORD_DELIMITERS;
+
 /* 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;
+rl_linebuf_func_t *history_inhibit_expansion_function;
 
 /* **************************************************************** */
 /*                                                                 */
@@ -124,7 +127,7 @@ static char *search_match;
    line = get_history_event ("!echo:p", &index, 0);  */
 char *
 get_history_event (string, caller_index, delimiting_quote)
-     char *string;
+     const char *string;
      int *caller_index;
      int delimiting_quote;
 {
@@ -132,7 +135,7 @@ get_history_event (string, caller_index, delimiting_quote)
   register char c;
   HIST_ENTRY *entry;
   int which, sign, local_index, substring_okay;
-  Function *search_func;
+  _hist_search_func_t *search_func;
   char *temp;
 
   /* The event can be specified in a number of ways.
@@ -342,7 +345,8 @@ hist_error(s, start, current, errtype)
       char *s;
       int start, current, errtype;
 {
-  char *temp, *emsg;
+  char *temp;
+  const char *emsg;
   int ll, elen;
 
   ll = current - start;
@@ -365,6 +369,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;
@@ -620,7 +628,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
        case '&':
        case 's':
          {
-           char *new_event, *t;
+           char *new_event;
            int delimiter, failed, si, l_temp;
 
            if (c == 's')
@@ -654,15 +662,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);
 
@@ -674,6 +673,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)
@@ -739,7 +747,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
       char *x;
 
       if (want_quotes == 'q')
-       x = single_quote (temp);
+       x = sh_single_quote (temp);
       else if (want_quotes == 'x')
        x = quote_breaks (temp);
       else
@@ -814,6 +822,9 @@ history_expand (hstring, output)
   /* Used when adding the string. */
   char *temp;
 
+  if (output == 0)
+    return 0;
+
   /* Setting the history expansion character to 0 inhibits all
      history expansion. */
   if (history_expansion_char == 0)
@@ -863,7 +874,7 @@ history_expand (hstring, output)
             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)))
+             (i == 0 || member (string[i - 1], history_word_delimiters)))
            {
              while (string[i])
                i++;
@@ -961,7 +972,7 @@ history_expand (hstring, output)
          }
 
        case -2:                /* history_comment_char */
-         if (i == 0 || member (string[i - 1], HISTORY_WORD_DELIMITERS))
+         if (i == 0 || member (string[i - 1], history_word_delimiters))
            {
              temp = xmalloc (l - i + 1);
              strcpy (temp, string + i);
@@ -1149,7 +1160,7 @@ get_history_word_specifier (spec, from, caller_index)
 char *
 history_arg_extract (first, last, string)
      int first, last;
-     char *string;
+     const char *string;
 {
   register int i, len;
   char *result;
@@ -1215,13 +1226,18 @@ history_arg_extract (first, last, string)
    *INDP. */
 static char **
 history_tokenize_internal (string, wind, indp)
-     char *string;
+     const char *string;
      int wind, *indp;
 {
   char **result;
   register int i, start, result_index, size;
   int len, delimiter;
 
+  /* If we're searching for a string that's not part of a word (e.g., " "),
+     make sure we set *INDP to a reasonable value. */
+  if (indp && wind != -1)
+    *indp = -1;
+
   /* Get a token, and stuff it into RESULT.  The tokens are split
      exactly where the shell would split them. */
   for (i = result_index = size = 0, result = (char **)NULL; string[i]; )
@@ -1296,7 +1312,7 @@ history_tokenize_internal (string, wind, indp)
              continue;
            }
 
-         if (!delimiter && (member (string[i], HISTORY_WORD_DELIMITERS)))
+         if (!delimiter && (member (string[i], history_word_delimiters)))
            break;
 
          if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))
@@ -1326,7 +1342,7 @@ history_tokenize_internal (string, wind, indp)
    parsed out of STRING. */
 char **
 history_tokenize (string)
-     char *string;
+     const char *string;
 {
   return (history_tokenize_internal (string, -1, (int *)NULL));
 }
@@ -1343,7 +1359,7 @@ history_find_word (line, ind)
   int i, wind;
 
   words = history_tokenize_internal (line, ind, &wind);
-  if (wind == -1)
+  if (wind == -1 || words == 0)
     return ((char *)NULL);
   s = words[wind];
   for (i = 0; i < wind; i++)