Import of readline 4.3.
[deliverable/binutils-gdb.git] / readline / histexpand.c
index 392e6d38d9ec771b77019df9272fa42c62d9f22f..6c81196161d86df3e707b59eb7453a72523aaf95 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 <unistd.h>
 #endif
 
-#if defined (HAVE_STRING_H)
-#  include <string.h>
-#else
-#  include <strings.h>
-#endif /* !HAVE_STRING_H */
+#include "rlmbutil.h"
 
 #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 PARAMS((const char *, int));
+
+extern int rl_byte_oriented;   /* declared in mbutil.c */
+
 static char error_pointer;
 
 static char *subst_lhs;
@@ -60,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 ();
+static char *get_history_word_specifier PARAMS((char *, char *, int *));
+static char *history_find_word PARAMS((char *, int));
 
-extern int history_offset;
-
-extern char *single_quote ();
-static char *quote_breaks ();
-
-extern char *xmalloc (), *xrealloc ();
+static char *quote_breaks PARAMS((char *));
 
 /* Variables exported by this file. */
 /* The character that represents the start of a history expansion
@@ -93,9 +91,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 +125,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 +133,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.
@@ -201,15 +202,33 @@ get_history_event (string, caller_index, delimiting_quote)
 
   /* Only a closing `?' or a newline delimit a substring search string. */
   for (local_index = i; c = string[i]; i++)
-    if ((!substring_okay && (whitespace (c) || c == ':' ||
-       (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
-       string[i] == delimiting_quote)) ||
-       string[i] == '\n' ||
-       (substring_okay && string[i] == '?'))
-      break;
+#if defined (HANDLE_MULTIBYTE)
+    if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+      {
+       int v;
+       mbstate_t ps;
+
+       memset (&ps, 0, sizeof (mbstate_t));
+       /* These produce warnings because we're passing a const string to a
+          function that takes a non-const string. */
+       _rl_adjust_point (string, i, &ps);
+       if ((v = _rl_get_char_len (string + i, &ps)) > 1)
+         {
+           i += v - 1;
+           continue;
+         }
+      }
+    else
+#endif /* HANDLE_MULTIBYTE */
+      if ((!substring_okay && (whitespace (c) || c == ':' ||
+         (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
+         string[i] == delimiting_quote)) ||
+         string[i] == '\n' ||
+         (substring_okay && string[i] == '?'))
+       break;
 
   which = i - local_index;
-  temp = xmalloc (1 + which);
+  temp = (char *)xmalloc (1 + which);
   if (which)
     strncpy (temp, string + local_index, which);
   temp[which] = '\0';
@@ -311,7 +330,7 @@ quote_breaks (s)
        len += 2;
     }
 
-  r = ret = xmalloc (len);
+  r = ret = (char *)xmalloc (len);
   *r++ = '\'';
   for (p = s; p && *p; )
     {
@@ -342,7 +361,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;
@@ -375,7 +395,7 @@ hist_error(s, start, current, errtype)
       break;
     }
 
-  temp = xmalloc (ll + elen + 3);
+  temp = (char *)xmalloc (ll + elen + 3);
   strncpy (temp, s + start, ll);
   temp[ll] = ':';
   temp[ll + 1] = ' ';
@@ -401,17 +421,37 @@ get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr)
      int *iptr, delimiter, is_rhs, *lenptr;
 {
   register int si, i, j, k;
-  char *s = (char *) NULL;
+  char *s;
+#if defined (HANDLE_MULTIBYTE)
+  mbstate_t ps;
+#endif
 
+  s = (char *)NULL;
   i = *iptr;
 
+#if defined (HANDLE_MULTIBYTE)
+  memset (&ps, 0, sizeof (mbstate_t));
+  _rl_adjust_point (str, i, &ps);
+#endif
+
   for (si = i; str[si] && str[si] != delimiter; si++)
-    if (str[si] == '\\' && str[si + 1] == delimiter)
-      si++;
+#if defined (HANDLE_MULTIBYTE)
+    if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+      {
+       int v;
+       if ((v = _rl_get_char_len (str + si, &ps)) > 1)
+         si += v - 1;
+       else if (str[si] == '\\' && str[si + 1] == delimiter)
+         si++;
+      }
+    else
+#endif /* HANDLE_MULTIBYTE */
+      if (str[si] == '\\' && str[si + 1] == delimiter)
+       si++;
 
   if (si > i || is_rhs)
     {
-      s = xmalloc (si - i + 1);
+      s = (char *)xmalloc (si - i + 1);
       for (j = 0, k = i; k < si; j++, k++)
        {
          /* Remove a backslash quoting the search string delimiter. */
@@ -438,13 +478,13 @@ postproc_subst_rhs ()
   char *new;
   int i, j, new_size;
 
-  new = xmalloc (new_size = subst_rhs_len + subst_lhs_len);
+  new = (char *)xmalloc (new_size = subst_rhs_len + subst_lhs_len);
   for (i = j = 0; i < subst_rhs_len; i++)
     {
       if (subst_rhs[i] == '&')
        {
          if (j + subst_lhs_len >= new_size)
-           new = xrealloc (new, (new_size = new_size * 2 + subst_lhs_len));
+           new = (char *)xrealloc (new, (new_size = new_size * 2 + subst_lhs_len));
          strcpy (new + j, subst_lhs);
          j += subst_lhs_len;
        }
@@ -454,7 +494,7 @@ postproc_subst_rhs ()
          if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&')
            i++;
          if (j >= new_size)
-           new = xrealloc (new, new_size *= 2);
+           new = (char *)xrealloc (new, new_size *= 2);
          new[j++] = subst_rhs[i];
        }
     }
@@ -480,8 +520,13 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
   int substitute_globally, want_quotes, print_only;
   char *event, *temp, *result, *tstr, *t, c, *word_spec;
   int result_len;
+#if defined (HANDLE_MULTIBYTE)
+  mbstate_t ps;
+
+  memset (&ps, 0, sizeof (mbstate_t));
+#endif
 
-  result = xmalloc (result_len = 128);
+  result = (char *)xmalloc (result_len = 128);
 
   i = start;
 
@@ -510,8 +555,21 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
         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 (i && (string[i - 1] == '\'' || string[i - 1] == '"'))
-       quoted_search_delimiter = string[i - 1];
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         int c, l;
+         l = _rl_find_prev_mbchar (string, i, MB_FIND_ANY);
+         c = string[l];
+         /* XXX - original patch had i - 1 ???  If i == 0 it would fail. */
+         if (i && (c == '\'' || c == '"'))
+           quoted_search_delimiter = c;
+       }
+      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);
     }
          
@@ -624,13 +682,26 @@ 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')
              {
                if (i + 2 < (int)strlen (string))
-                 delimiter = string[i + 2];
+                 {
+#if defined (HANDLE_MULTIBYTE)
+                   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+                     {
+                       _rl_adjust_point (string, i + 2, &ps);
+                       if (_rl_get_char_len (string + i + 2, &ps) > 1)
+                         delimiter = 0;
+                       else
+                         delimiter = string[i + 2];
+                     }
+                   else
+#endif /* HANDLE_MULTIBYTE */
+                     delimiter = string[i + 2];
+                 }
                else
                  break;        /* no search delimiter */
 
@@ -694,7 +765,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
              if (STREQN (temp+si, subst_lhs, subst_lhs_len))
                {
                  int len = subst_rhs_len - subst_lhs_len + l_temp;
-                 new_event = xmalloc (1 + len);
+                 new_event = (char *)xmalloc (1 + len);
                  strncpy (new_event, temp, si);
                  strncpy (new_event + si, subst_rhs, subst_rhs_len);
                  strncpy (new_event + si + subst_rhs_len,
@@ -743,7 +814,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
@@ -755,7 +826,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
 
   n = strlen (temp);
   if (n >= result_len)
-    result = xrealloc (result, n + 2);
+    result = (char *)xrealloc (result, n + 2);
   strcpy (result, temp);
   free (temp);
 
@@ -786,7 +857,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
              { \
                while (j >= result_len) \
                  result_len += 128; \
-               result = xrealloc (result, result_len); \
+               result = (char *)xrealloc (result, result_len); \
              } \
            strcpy (result + j - sl, s); \
          } \
@@ -796,7 +867,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
        do \
          { \
            if (j >= result_len - 1) \
-             result = xrealloc (result, result_len += 64); \
+             result = (char *)xrealloc (result, result_len += 64); \
            result[j++] = c; \
            result[j] = '\0'; \
          } \
@@ -815,9 +886,17 @@ history_expand (hstring, output)
   int result_len;
   char *result;
 
+#if defined (HANDLE_MULTIBYTE)
+  char mb[MB_LEN_MAX];
+  mbstate_t ps;
+#endif
+
   /* 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)
@@ -827,7 +906,7 @@ history_expand (hstring, output)
     }
     
   /* Prepare the buffer for printing error messages. */
-  result = xmalloc (result_len = 256);
+  result = (char *)xmalloc (result_len = 256);
   result[0] = '\0';
 
   only_printing = modified = 0;
@@ -844,7 +923,7 @@ history_expand (hstring, output)
      that is the substitution that we do. */
   if (hstring[0] == history_subst_char)
     {
-      string = xmalloc (l + 5);
+      string = (char *)xmalloc (l + 5);
 
       string[0] = string[1] = history_expansion_char;
       string[2] = ':';
@@ -854,6 +933,10 @@ history_expand (hstring, output)
     }
   else
     {
+#if defined (HANDLE_MULTIBYTE)
+      memset (&ps, 0, sizeof (mbstate_t));
+#endif
+
       string = hstring;
       /* If not quick substitution, still maybe have to do expansion. */
 
@@ -861,13 +944,26 @@ history_expand (hstring, output)
         is NOT an expansion. */
       for (i = 0; string[i]; i++)
        {
+#if defined (HANDLE_MULTIBYTE)
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           {
+             int v;
+             v = _rl_get_char_len (string + i, &ps);
+             if (v > 1)
+               {
+                 i += v - 1;
+                 continue;
+               }
+           }
+#endif /* HANDLE_MULTIBYTE */
+
          cc = string[i + 1];
-         /* The history_comment_char, if set, appearing that the beginning
+         /* The history_comment_char, if set, appearing at 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)))
+             (i == 0 || member (string[i - 1], history_word_delimiters)))
            {
              while (string[i])
                i++;
@@ -925,6 +1021,30 @@ history_expand (hstring, output)
          continue;
        }
 
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         int k, c;
+
+         c = tchar;
+         memset (mb, 0, sizeof (mb));
+         for (k = 0; k < MB_LEN_MAX; k++)
+           {
+             mb[k] = (char)c;
+             memset (&ps, 0, sizeof (mbstate_t));
+             if (_rl_get_char_len (mb, &ps) == -2)
+               c = string[++i];
+             else
+               break;
+           }
+         if (strlen (mb) > 1)
+           {
+             ADD_STRING (mb);
+             break;
+           }
+       }
+#endif /* HANDLE_MULTIBYTE */
+
       if (tchar == history_expansion_char)
        tchar = -3;
       else if (tchar == history_comment_char)
@@ -953,7 +1073,7 @@ history_expand (hstring, output)
                hist_string_extract_single_quoted (string, &i);
 
                slen = i - quote + 2;
-               temp = xmalloc (slen);
+               temp = (char *)xmalloc (slen);
                strncpy (temp, string + quote, slen);
                temp[slen - 1] = '\0';
                ADD_STRING (temp);
@@ -965,9 +1085,9 @@ 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);
+             temp = (char *)xmalloc (l - i + 1);
              strcpy (temp, string + i);
              ADD_STRING (temp);
              free (temp);
@@ -999,7 +1119,7 @@ history_expand (hstring, output)
            {
              if (result)
                {
-                 temp = xmalloc (1 + strlen (result));
+                 temp = (char *)xmalloc (1 + strlen (result));
                  strcpy (temp, result);
                  ADD_STRING (temp);
                  free (temp);
@@ -1133,7 +1253,14 @@ get_history_word_specifier (spec, from, caller_index)
          i++;
          last = '$';
        }
-      else if (!spec[i] || spec[i] == ':')  /* could be modifier separator */
+#if 0
+      else if (!spec[i] || spec[i] == ':')
+       /* check against `:' because there could be a modifier separator */
+#else
+      else
+       /* csh seems to allow anything to terminate the word spec here,
+          leaving it as an abbreviation. */
+#endif
        last = -1;              /* x- abbreviates x-$ omitting word `$' */
     }
 
@@ -1153,7 +1280,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;
@@ -1189,7 +1316,7 @@ history_arg_extract (first, last, string)
     {
       for (size = 0, i = first; i < last; i++)
        size += strlen (list[i]) + 1;
-      result = xmalloc (size + 1);
+      result = (char *)xmalloc (size + 1);
       result[0] = '\0';
 
       for (i = first, offset = 0; i < last; i++)
@@ -1219,13 +1346,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]; )
@@ -1300,7 +1432,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))
@@ -1317,7 +1449,7 @@ history_tokenize_internal (string, wind, indp)
       len = i - start;
       if (result_index + 2 >= size)
        result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));
-      result[result_index] = xmalloc (1 + len);
+      result[result_index] = (char *)xmalloc (1 + len);
       strncpy (result[result_index], string + start, len);
       result[result_index][len] = '\0';
       result[++result_index] = (char *)NULL;
@@ -1330,7 +1462,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));
 }
@@ -1347,7 +1479,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++)
This page took 0.033175 seconds and 4 git commands to generate.