* config/tc-alpha.c (O_samegp): New.
[external/binutils.git] / readline / search.c
index 6c76e1a..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
@@ -19,7 +19,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
 
 #if defined (HAVE_CONFIG_H)
 #include "readline.h"
 #include "history.h"
 
+#include "rlprivate.h"
+#include "xmalloc.h"
+
 #ifdef abs
 #  undef abs
 #endif
 #define abs(x)         (((x) >= 0) ? (x) : -(x))
 
-extern char *xmalloc (), *xrealloc ();
-
-/* Variables imported from readline.c */
-extern int rl_point, rl_end, rl_line_buffer_len;
-extern int rl_editing_mode;
-extern char *rl_prompt;
-extern char *rl_line_buffer;
 extern HIST_ENTRY *saved_line_for_history;
-extern Function *rl_last_func;
 
 /* Functions imported from the rest of the library. */
-extern int _rl_free_history_entry ();
-extern char *_rl_make_prompt_for_search ();
-extern void rl_extend_line_buffer ();
+extern int _rl_free_history_entry __P((HIST_ENTRY *));
 
 static char *noninc_search_string = (char *) NULL;
 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
    beginning of a history line, otherwise a full substring match is performed
@@ -102,7 +123,7 @@ noninc_dosearch (string, dir)
      char *string;
      int dir;
 {
-  int oldpos, pos, line_len;
+  int oldpos, pos;
   HIST_ENTRY *entry;
 
   if (string == 0 || *string == '\0' || noninc_history_pos < 0)
@@ -132,19 +153,10 @@ noninc_dosearch (string, dir)
 #endif
   history_set_pos (oldpos);
 
-  line_len = strlen (entry->line);
-  if (line_len >= rl_line_buffer_len)
-    rl_extend_line_buffer (line_len);
-  strcpy (rl_line_buffer, entry->line);
+  make_history_line_current (entry);
 
-  rl_undo_list = (UNDO_LIST *)entry->data;
-  rl_end = strlen (rl_line_buffer);
   rl_point = 0;
   rl_clear_message ();
-
-  if (saved_line_for_history)
-    _rl_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
@@ -235,8 +247,7 @@ noninc_search (dir, pchar)
     {
       /* 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);
     }
 
@@ -295,59 +306,84 @@ rl_noninc_reverse_search_again (count, key)
 }
 
 static int
-rl_history_search_internal (count, direction)
-     int count, direction;
+rl_history_search_internal (count, dir)
+     int count, dir;
 {
-  HIST_ENTRY *temp, *old_temp;
-  int line_len;
+  HIST_ENTRY *temp;
+  int ret, oldpos;
 
   maybe_save_line ();
+  temp = (HIST_ENTRY *)NULL;
 
-  temp = old_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)
     {
-      temp = (direction < 0) ? previous_history () : next_history ();
-      if (temp == 0)
-        break;
-      /* On an empty prefix, make this the same as previous-history. */
-      if (rl_point == 0)
-       {
-         count--;
-         continue;
-       }
-      if (STREQN (rl_line_buffer, temp->line, rl_point))
-       {
-         /* Don't find multiple instances of the same line. */
-         if (prev_line_found && STREQ (prev_line_found, temp->line))
-           continue;
-          if (direction < 0)
-            old_temp = temp;
-          prev_line_found = temp->line;
-          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)
     {
-      if (direction < 0 && old_temp)
-       temp = old_temp;
-      else
-       {
-         maybe_unsave_line ();
-         ding ();
-         return 1;
-       }
+      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;
     }
 
-  line_len = strlen (temp->line);
-  if (line_len >= rl_line_buffer_len)
-    rl_extend_line_buffer (line_len);
-  strcpy (rl_line_buffer, temp->line);
-  rl_undo_list = (UNDO_LIST *)temp->data;
-  rl_end = line_len;
+  /* 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. */
@@ -357,8 +393,13 @@ rl_history_search_forward (count, ignore)
 {
   if (count == 0)
     return (0);
-  if (rl_last_func != rl_history_search_forward)
-    prev_line_found = (char *)NULL;
+
+  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));
 }
 
@@ -371,7 +412,12 @@ rl_history_search_backward (count, ignore)
 {
   if (count == 0)
     return (0);
-  if (rl_last_func != rl_history_search_backward)
-    prev_line_found = (char *)NULL;
+
+  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));
 }