* config/tc-alpha.c (O_samegp): New.
[external/binutils.git] / readline / search.c
index ea98c6f..112f807 100644 (file)
@@ -8,7 +8,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
    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
 
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
 #include <stdio.h>
 
-#if defined (__GNUC__)
-#  define alloca __builtin_alloca
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
 #else
-#  if defined (sparc) || defined (HAVE_ALLOCA_H)
-#    include <alloca.h>
-#  endif
+#  include "ansi_stdlib.h"
 #endif
 
+#include "rldefs.h"
 #include "readline.h"
 #include "history.h"
 
-extern char *xmalloc (), *xrealloc ();
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+#ifdef abs
+#  undef abs
+#endif
+#define abs(x)         (((x) >= 0) ? (x) : -(x))
 
-/* Variables imported from readline.c */
-extern int rl_point, rl_end, rl_line_buffer_len;
-extern Keymap _rl_keymap;
-extern char *rl_prompt;
-extern char *rl_line_buffer;
 extern HIST_ENTRY *saved_line_for_history;
 
+/* Functions imported from the rest of the library. */
+extern int _rl_free_history_entry __P((HIST_ENTRY *));
+
 static char *noninc_search_string = (char *) NULL;
-static int noninc_history_pos = 0;
+static int noninc_history_pos;
+
+static char *prev_line_found = (char *) NULL;
+
+static int rl_history_search_len;
+static int rl_history_search_pos;
+static char *history_search_string;
+static int history_string_size;
+
+/* Make the data from the history entry ENTRY be the contents of the
+   current line.  This doesn't do anything with rl_point; the caller
+   must set it. */
+static void
+make_history_line_current (entry)
+     HIST_ENTRY *entry;
+{
+  int line_len;
+
+  line_len = strlen (entry->line);
+  if (line_len >= rl_line_buffer_len)
+    rl_extend_line_buffer (line_len);
+  strcpy (rl_line_buffer, entry->line);
+
+  rl_undo_list = (UNDO_LIST *)entry->data;
+  rl_end = line_len;
+
+  if (saved_line_for_history)
+    _rl_free_history_entry (saved_line_for_history);
+  saved_line_for_history = (HIST_ENTRY *)NULL;
+}
 
 /* Search the history list for STRING starting at absolute history position
    POS.  If STRING begins with `^', the search must match STRING at the
@@ -84,7 +126,7 @@ noninc_dosearch (string, dir)
   int oldpos, pos;
   HIST_ENTRY *entry;
 
-  if (string == 0 || *string == 0 || noninc_history_pos < 0)
+  if (string == 0 || *string == '\0' || noninc_history_pos < 0)
     {
       ding ();
       return;
@@ -106,25 +148,15 @@ noninc_dosearch (string, dir)
   oldpos = where_history ();
   history_set_pos (noninc_history_pos);
   entry = current_history ();
+#if defined (VI_MODE)
+  if (rl_editing_mode != vi_mode)
+#endif
   history_set_pos (oldpos);
 
-  {
-    int line_len;
+  make_history_line_current (entry);
 
-    line_len = strlen (entry->line);
-    if (line_len >= rl_line_buffer_len)
-      rl_extend_line_buffer (line_len);
-    strcpy (rl_line_buffer, entry->line);
-  }
-
-  rl_undo_list = (UNDO_LIST *)entry->data;
-  rl_end = strlen (rl_line_buffer);
   rl_point = 0;
   rl_clear_message ();
-
-  if (saved_line_for_history)
-    free_history_entry (saved_line_for_history);
-  saved_line_for_history = (HIST_ENTRY *)NULL;
 }
 
 /* Search non-interactively through the history list.  DIR < 0 means to
@@ -137,7 +169,7 @@ noninc_search (dir, pchar)
      int dir;
      int pchar;
 {
-  int saved_point, c, pmtlen;
+  int saved_point, c;
   char *p;
 
   maybe_save_line ();
@@ -147,14 +179,11 @@ noninc_search (dir, pchar)
   rl_line_buffer[0] = 0;
   rl_end = rl_point = 0;
 
-  pmtlen = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
-  p = (char *)alloca (2 + pmtlen);
-  if (pmtlen)
-    strcpy (p, rl_prompt);
-  p[pmtlen] = pchar ? pchar : ':';
-  p[pmtlen + 1]  = '\0';
-
+  p = _rl_make_prompt_for_search (pchar ? pchar : ':');
   rl_message (p, 0, 0);
+  free (p);
+
+#define SEARCH_RETURN rl_restore_prompt (); return
 
   /* Read the search string. */
   while (c = rl_read_key ())
@@ -168,13 +197,17 @@ noninc_search (dir, pchar)
              maybe_unsave_line ();
              rl_clear_message ();
              rl_point = saved_point;
-             return;
+             SEARCH_RETURN;
            }
-         /* FALLTHROUGH */
+         rl_rubout (1, c);
+         break;
 
        case CTRL('W'):
+         rl_unix_word_rubout (1, c);
+         break;
+
        case CTRL('U'):
-         rl_dispatch (c, _rl_keymap);
+         rl_unix_line_discard (1, c);
          break;
 
        case RETURN:
@@ -189,13 +222,13 @@ noninc_search (dir, pchar)
          rl_clear_message ();
          rl_point = saved_point;
          ding ();
-         return;
+         SEARCH_RETURN;
 
        default:
          rl_insert (1, c);
          break;
        }
-      rl_redisplay ();
+      (*rl_redisplay_function) ();
     }
 
  dosearch:
@@ -207,45 +240,44 @@ noninc_search (dir, pchar)
       if (!noninc_search_string)
        {
          ding ();
-         return;
+         SEARCH_RETURN;
        }
     }
   else
     {
       /* We want to start the search from the current history position. */
       noninc_history_pos = where_history ();
-      if (noninc_search_string)
-       free (noninc_search_string);
+      FREE (noninc_search_string);
       noninc_search_string = savestring (rl_line_buffer);
     }
 
+  rl_restore_prompt ();
   noninc_dosearch (noninc_search_string, dir);
 }
 
 /* Search forward through the history list for a string.  If the vi-mode
    code calls this, KEY will be `?'. */
+int
 rl_noninc_forward_search (count, key)
      int count, key;
 {
-  if (key == '?')
-    noninc_search (1, '?');
-  else
-    noninc_search (1, 0);
+  noninc_search (1, (key == '?') ? '?' : 0);
+  return 0;
 }
 
 /* Reverse search the history list for a string.  If the vi-mode code
    calls this, KEY will be `/'. */
+int
 rl_noninc_reverse_search (count, key)
      int count, key;
 {
-  if (key == '/')
-    noninc_search (-1, '/');
-  else
-    noninc_search (-1, 0);
+  noninc_search (-1, (key == '/') ? '/' : 0);
+  return 0;
 }
 
 /* Search forward through the history list for the last string searched
    for.  If there is no saved search string, abort. */
+int
 rl_noninc_forward_search_again (count, key)
      int count, key;
 {
@@ -255,10 +287,12 @@ rl_noninc_forward_search_again (count, key)
       return (-1);
     }
   noninc_dosearch (noninc_search_string, 1);
+  return 0;
 }
 
 /* Reverse search in the history list for the last string searched
    for.  If there is no saved search string, abort. */
+int
 rl_noninc_reverse_search_again (count, key)
      int count, key;
 {
@@ -268,4 +302,122 @@ rl_noninc_reverse_search_again (count, key)
       return (-1);
     }
   noninc_dosearch (noninc_search_string, -1);
+  return 0;
+}
+
+static int
+rl_history_search_internal (count, dir)
+     int count, dir;
+{
+  HIST_ENTRY *temp;
+  int ret, oldpos;
+
+  maybe_save_line ();
+  temp = (HIST_ENTRY *)NULL;
+
+  /* Search COUNT times through the history for a line whose prefix
+     matches history_search_string.  When this loop finishes, TEMP,
+     if non-null, is the history line to copy into the line buffer. */
+  while (count)
+    {
+      ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
+      if (ret == -1)
+       break;
+
+      /* Get the history entry we found. */
+      rl_history_search_pos = ret;
+      oldpos = where_history ();
+      history_set_pos (rl_history_search_pos);
+      temp = current_history ();
+      history_set_pos (oldpos);
+
+      /* Don't find multiple instances of the same line. */
+      if (prev_line_found && STREQ (prev_line_found, temp->line))
+        continue;
+      prev_line_found = temp->line;
+      count--;
+    }
+
+  /* If we didn't find anything at all, return. */
+  if (temp == 0)
+    {
+      maybe_unsave_line ();
+      ding ();
+      /* If you don't want the saved history line (last match) to show up
+         in the line buffer after the search fails, change the #if 0 to
+         #if 1 */
+#if 0
+      if (rl_point > rl_history_search_len)
+        {
+          rl_point = rl_end = rl_history_search_len;
+          rl_line_buffer[rl_end] = '\0';
+        }
+#else
+      rl_point = rl_history_search_len;        /* maybe_unsave_line changes it */
+#endif
+      return 1;
+    }
+
+  /* Copy the line we found into the current line buffer. */
+  make_history_line_current (temp);
+
+  rl_point = rl_history_search_len;
+  return 0;
+}
+
+static void
+rl_history_search_reinit ()
+{
+  rl_history_search_pos = where_history ();
+  rl_history_search_len = rl_point;
+  prev_line_found = (char *)NULL;
+  if (rl_point)
+    {
+      if (rl_history_search_len >= history_string_size - 2)
+       {
+         history_string_size = rl_history_search_len + 2;
+         history_search_string = xrealloc (history_search_string, history_string_size);
+       }
+      history_search_string[0] = '^';
+      strncpy (history_search_string + 1, rl_line_buffer, rl_point);
+      history_search_string[rl_point + 1] = '\0';
+    }
+}
+
+/* Search forward in the history for the string of characters
+   from the start of the line to rl_point.  This is a non-incremental
+   search. */
+int
+rl_history_search_forward (count, ignore)
+     int count, ignore;
+{
+  if (count == 0)
+    return (0);
+
+  if (rl_last_func != rl_history_search_forward &&
+      rl_last_func != rl_history_search_backward)
+    rl_history_search_reinit ();
+
+  if (rl_history_search_len == 0)
+    return (rl_get_next_history (count, ignore));
+  return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
+}
+
+/* Search backward through the history for the string of characters
+   from the start of the line to rl_point.  This is a non-incremental
+   search. */
+int
+rl_history_search_backward (count, ignore)
+     int count, ignore;
+{
+  if (count == 0)
+    return (0);
+
+  if (rl_last_func != rl_history_search_forward &&
+      rl_last_func != rl_history_search_backward)
+    rl_history_search_reinit ();
+
+  if (rl_history_search_len == 0)
+    return (rl_get_previous_history (count, ignore));
+  return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
 }