]> code.delx.au - gnu-emacs/blobdiff - src/search.c
(w32_createwindow): Remove code for handling -geometry command line option and
[gnu-emacs] / src / search.c
index d86a7cca7b2368939b7758a8f4c369a204e46834..7c3151b76b8475df0bd7c161be0542c9e767f35a 100644 (file)
@@ -1,6 +1,6 @@
 /* String search routines for GNU Emacs.
-   Copyright (C) 1985, 86,87,93,94,97,98, 1999, 2004
-             Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1993, 1994, 1997, 1998, 1999, 2002, 2003,
+                 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -16,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 
 #include <config.h>
@@ -42,6 +42,10 @@ struct regexp_cache
 {
   struct regexp_cache *next;
   Lisp_Object regexp, whitespace_regexp;
+  /* Syntax table for which the regexp applies.  We need this because
+     of character classes.  If this is t, then the compiled pattern is valid
+     for any syntax-table.  */
+  Lisp_Object syntax_table;
   struct re_pattern_buffer buf;
   char fastmap[0400];
   /* Nonzero means regexp was compiled to do full POSIX backtracking.  */
@@ -83,6 +87,9 @@ static Lisp_Object last_thing_searched;
 
 Lisp_Object Qinvalid_regexp;
 
+/* Error condition used for failing searches */
+Lisp_Object Qsearch_failed;
+
 Lisp_Object Vsearch_spaces_regexp;
 
 static void set_search_regs ();
@@ -90,6 +97,7 @@ static void save_search_regs ();
 static int simple_search ();
 static int boyer_moore ();
 static int search_buffer ();
+static void matcher_overflow () NO_RETURN;
 
 static void
 matcher_overflow ()
@@ -163,7 +171,11 @@ compile_pattern_1 (cp, pattern, translate, regp, posix, multibyte)
   cp->posix = posix;
   cp->buf.multibyte = multibyte;
   cp->whitespace_regexp = Vsearch_spaces_regexp;
-  BLOCK_INPUT;
+  /* rms: I think BLOCK_INPUT is not needed here any more,
+     because regex.c defines malloc to call xmalloc.
+     Using BLOCK_INPUT here means the debugger won't run if an error occurs.
+     So let's turn it off.  */
+  /*  BLOCK_INPUT;  */
   old = re_set_syntax (RE_SYNTAX_EMACS
                       | (posix ? 0 : RE_NO_POSIX_BACKTRACKING));
 
@@ -173,12 +185,16 @@ compile_pattern_1 (cp, pattern, translate, regp, posix, multibyte)
   val = (char *) re_compile_pattern ((char *)raw_pattern,
                                     raw_pattern_size, &cp->buf);
 
+  /* If the compiled pattern hard codes some of the contents of the
+     syntax-table, it can only be reused with *this* syntax table.  */
+  cp->syntax_table = cp->buf.used_syntax ? current_buffer->syntax_table : Qt;
+
   re_set_whitespace_regexp (NULL);
 
   re_set_syntax (old);
-  UNBLOCK_INPUT;
+  /* UNBLOCK_INPUT;  */
   if (val)
-    Fsignal (Qinvalid_regexp, Fcons (build_string (val), Qnil));
+    xsignal1 (Qinvalid_regexp, build_string (val));
 
   cp->regexp = Fcopy_sequence (pattern);
 }
@@ -200,6 +216,24 @@ shrink_regexp_cache ()
     }
 }
 
+/* Clear the regexp cache w.r.t. a particular syntax table,
+   because it was changed.
+   There is no danger of memory leak here because re_compile_pattern
+   automagically manages the memory in each re_pattern_buffer struct,
+   based on its `allocated' and `buffer' values.  */
+void
+clear_regexp_cache ()
+{
+  int i;
+
+  for (i = 0; i < REGEXP_CACHE_SIZE; ++i)
+    /* It's tempting to compare with the syntax-table we've actually changd,
+       but it's not sufficient because char-table inheritance mewans that
+       modifying one syntax-table can change others at the same time.  */
+    if (!EQ (searchbufs[i].syntax_table, Qt))
+      searchbufs[i].regexp = Qnil;
+}
+
 /* Compile a regexp if necessary, but first check to see if there's one in
    the cache.
    PATTERN is the pattern to compile.
@@ -236,6 +270,8 @@ compile_pattern (pattern, regp, translate, posix, multibyte)
          && EQ (cp->buf.translate, (! NILP (translate) ? translate : make_number (0)))
          && cp->posix == posix
          && cp->buf.multibyte == multibyte
+         && (EQ (cp->syntax_table, Qt)
+             || EQ (cp->syntax_table, current_buffer->syntax_table))
          && !NILP (Fequal (cp->whitespace_regexp, Vsearch_spaces_regexp)))
        break;
 
@@ -265,16 +301,6 @@ compile_pattern (pattern, regp, translate, posix, multibyte)
   return &cp->buf;
 }
 
-/* Error condition used for failing searches */
-Lisp_Object Qsearch_failed;
-
-Lisp_Object
-signal_failure (arg)
-     Lisp_Object arg;
-{
-  Fsignal (Qsearch_failed, Fcons (arg, Qnil));
-  return Qnil;
-}
 \f
 static Lisp_Object
 looking_at_1 (string, posix)
@@ -290,6 +316,10 @@ looking_at_1 (string, posix)
   if (running_asynch_code)
     save_search_regs ();
 
+  /* This is so set_image_of_range_1 in regex.c can find the EQV table.  */
+  XCHAR_TABLE (current_buffer->case_canon_table)->extras[2]
+    = current_buffer->case_eqv_table;
+
   CHECK_STRING (string);
   bufp = compile_pattern (string, &search_regs,
                          (!NILP (current_buffer->case_fold_search)
@@ -397,6 +427,10 @@ string_match_1 (regexp, string, start, posix)
       pos_byte = string_char_to_byte (string, pos);
     }
 
+  /* This is so set_image_of_range_1 in regex.c can find the EQV table.  */
+  XCHAR_TABLE (current_buffer->case_canon_table)->extras[2]
+    = current_buffer->case_eqv_table;
+
   bufp = compile_pattern (regexp, &search_regs,
                          (!NILP (current_buffer->case_fold_search)
                           ? current_buffer->case_canon_table : Qnil),
@@ -429,7 +463,7 @@ string_match_1 (regexp, string, start, posix)
 
 DEFUN ("string-match", Fstring_match, Sstring_match, 2, 3, 0,
        doc: /* Return index of start of first match for REGEXP in STRING, or nil.
-Case is ignored if `case-fold-search' is non-nil in the current buffer.
+Matching ignores case if `case-fold-search' is non-nil.
 If third arg START is non-nil, start search at that index in STRING.
 For index of first char beyond the match, do (match-end 0).
 `match-end' and `match-beginning' also give indices of substrings
@@ -936,6 +970,10 @@ search_command (string, bound, noerror, count, direction, RE, posix)
        lim_byte = CHAR_TO_BYTE (lim);
     }
 
+  /* This is so set_image_of_range_1 in regex.c can find the EQV table.  */
+  XCHAR_TABLE (current_buffer->case_canon_table)->extras[2]
+    = current_buffer->case_eqv_table;
+
   np = search_buffer (string, PT, PT_BYTE, lim, lim_byte, n, RE,
                      (!NILP (current_buffer->case_fold_search)
                       ? current_buffer->case_canon_table
@@ -947,7 +985,8 @@ search_command (string, bound, noerror, count, direction, RE, posix)
   if (np <= 0)
     {
       if (NILP (noerror))
-       return signal_failure (string);
+       xsignal1 (Qsearch_failed, string);
+
       if (!EQ (noerror, Qt))
        {
          if (lim < BEGV || lim > ZV)
@@ -1174,10 +1213,10 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n,
       int raw_pattern_size_byte;
       unsigned char *patbuf;
       int multibyte = !NILP (current_buffer->enable_multibyte_characters);
-      unsigned char *base_pat = SDATA (string);
-      /* Set to nozero if we find a non-ASCII char that need
-        translation.  */
-      int charset_base = 0;
+      unsigned char *base_pat;
+      /* Set to positive if we find a non-ASCII char that need
+        translation.  Otherwise set to zero later.  */
+      int charset_base = -1;
       int boyer_moore_ok = 1;
 
       /* MULTIBYTE says whether the text to be searched is multibyte.
@@ -1275,24 +1314,30 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n,
                         always handle their translation.  */
                      while (1)
                        {
-                         if (ASCII_BYTE_P (inverse))
+                         if (ASCII_BYTE_P (inverse))
                            {
-                             if (SINGLE_BYTE_CHAR_P (inverse))
-                               {
-                                 /* Boyer-moore search can't handle a
-                                    translation of an eight-bit
-                                    character.  */
-                                 boyer_moore_ok = 0;
-                                 break;
-                               }
-                             else if (charset_base == 0)
-                               charset_base = inverse & ~CHAR_FIELD3_MASK;
-                             else if ((inverse & ~CHAR_FIELD3_MASK)
-                                      != charset_base)
+                             if (charset_base > 0)
                                {
                                  boyer_moore_ok = 0;
                                  break;
                                }
+                             charset_base = 0;
+                           }
+                         else if (SINGLE_BYTE_CHAR_P (inverse))
+                           {
+                             /* Boyer-moore search can't handle a
+                                translation of an eight-bit
+                                character.  */
+                             boyer_moore_ok = 0;
+                             break;
+                           }
+                         else if (charset_base < 0)
+                           charset_base = inverse & ~CHAR_FIELD3_MASK;
+                         else if ((inverse & ~CHAR_FIELD3_MASK)
+                                  != charset_base)
+                           {
+                             boyer_moore_ok = 0;
+                             break;
                            }
                          if (c == inverse)
                            break;
@@ -1300,6 +1345,8 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n,
                        }
                    }
                }
+             if (charset_base < 0)
+               charset_base = 0;
 
              /* Store this character into the translated pattern.  */
              bcopy (str, pat, charlen);
@@ -1692,22 +1739,31 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
        i = infinity;
       if (! NILP (trt))
        {
-         /* If the byte currently looking at is a head of a character
-            to check case-equivalents, set CH to that character.  An
-            ASCII character and a non-ASCII character matching with
-            CHARSET_BASE are to be checked.  */
+         /* If the byte currently looking at is the last of a
+            character to check case-equivalents, set CH to that
+            character.  An ASCII character and a non-ASCII character
+            matching with CHARSET_BASE are to be checked.  */
          int ch = -1;
 
          if (ASCII_BYTE_P (*ptr) || ! multibyte)
            ch = *ptr;
-         else if (charset_base && CHAR_HEAD_P (*ptr))
+         else if (charset_base
+                  && ((pat_end - ptr) == 1 || CHAR_HEAD_P (ptr[1])))
            {
-             ch = STRING_CHAR (ptr, pat_end - ptr);
+             unsigned char *charstart = ptr - 1;
+
+             while (! (CHAR_HEAD_P (*charstart)))
+               charstart--;
+             ch = STRING_CHAR (charstart, ptr - charstart + 1);
              if (charset_base != (ch & ~CHAR_FIELD3_MASK))
                ch = -1;
            }
 
-         j = *ptr;
+         if (ch >= 0400)
+           j = ((unsigned char) ch) | 0200;
+         else
+           j = *ptr;
+
          if (i == infinity)
            stride_for_teases = BM_tab[j];
 
@@ -1717,16 +1773,12 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
          if (ch >= 0)
            {
              int starting_ch = ch;
-             int starting_j;
+             int starting_j = j;
 
-             if (ch > 0400)
-               starting_j = ((unsigned char) ch) | 0200;
-             else
-               starting_j = (unsigned char) ch;
              while (1)
                {
                  TRANSLATE (ch, inverse_trt, ch);
-                 if (ch > 0400)
+                 if (ch >= 0400)
                    j = ((unsigned char) ch) | 0200;
                  else
                    j = (unsigned char) ch;
@@ -2291,7 +2343,7 @@ since only regular expressions have distinguished subexpressions.  */)
                                /* but some C compilers blew it */
 
   if (search_regs.num_regs <= 0)
-    error ("replace-match called before any match found");
+    error ("`replace-match' called before any match found");
 
   if (NILP (subexp))
     sub = 0;
@@ -2363,7 +2415,7 @@ since only regular expressions have distinguished subexpressions.  */)
              else
                some_multiletter_word = 1;
            }
-         else if (!NOCASEP (c))
+         else if (UPPERCASEP (c))
            {
              some_uppercase = 1;
              if (SYNTAX (prevc) != Sword)
@@ -2734,7 +2786,7 @@ Zero means the entire text matched by the whole regexp or whole string.  */)
   return match_limit (subexp, 0);
 }
 
-DEFUN ("match-data", Fmatch_data, Smatch_data, 0, 2, 0,
+DEFUN ("match-data", Fmatch_data, Smatch_data, 0, 3, 0,
        doc: /* Return a list containing all info on what the last search matched.
 Element 2N is `(match-beginning N)'; element 2N + 1 is `(match-end N)'.
 All the elements are markers or nil (nil if the Nth pair didn't match)
@@ -2746,17 +2798,29 @@ integers \(rather than markers) to represent buffer positions.  In
 this case, and if the last match was in a buffer, the buffer will get
 stored as one additional element at the end of the list.
 
-If REUSE is a list, reuse it as part of the value.  If REUSE is long enough
-to hold all the values, and if INTEGERS is non-nil, no consing is done.
+If REUSE is a list, reuse it as part of the value.  If REUSE is long
+enough to hold all the values, and if INTEGERS is non-nil, no consing
+is done.
+
+If optional third arg RESEAT is non-nil, any previous markers on the
+REUSE list will be modified to point to nowhere.
 
 Return value is undefined if the last search failed.  */)
-     (integers, reuse)
-     Lisp_Object integers, reuse;
+  (integers, reuse, reseat)
+     Lisp_Object integers, reuse, reseat;
 {
   Lisp_Object tail, prev;
   Lisp_Object *data;
   int i, len;
 
+  if (!NILP (reseat))
+    for (tail = reuse; CONSP (tail); tail = XCDR (tail))
+      if (MARKERP (XCAR (tail)))
+       {
+         unchain_marker (XMARKER (XCAR (tail)));
+         XSETCAR (tail, Qnil);
+       }
+
   if (NILP (last_thing_searched))
     return Qnil;
 
@@ -2792,10 +2856,10 @@ Return value is undefined if the last search failed.  */)
            /* last_thing_searched must always be Qt, a buffer, or Qnil.  */
            abort ();
 
-         len = 2*(i+1);
+         len = 2 * i + 2;
        }
       else
-       data[2 * i] = data [2 * i + 1] = Qnil;
+       data[2 * i] = data[2 * i + 1] = Qnil;
     }
 
   if (BUFFERP (last_thing_searched) && !NILP (integers))
@@ -2828,12 +2892,19 @@ Return value is undefined if the last search failed.  */)
   return reuse;
 }
 
+/* Internal usage only:
+   If RESEAT is `evaporate', put the markers back on the free list
+   immediately.  No other references to the markers must exist in this case,
+   so it is used only internally on the unwind stack and save-match-data from
+   Lisp.  */
 
-DEFUN ("set-match-data", Fset_match_data, Sset_match_data, 1, 1, 0,
+DEFUN ("set-match-data", Fset_match_data, Sset_match_data, 1, 2, 0,
        doc: /* Set internal data on last search match from elements of LIST.
-LIST should have been created by calling `match-data' previously.  */)
-     (list)
-     register Lisp_Object list;
+LIST should have been created by calling `match-data' previously.
+
+If optional arg RESEAT is non-nil, make markers on LIST point nowhere.  */)
+    (list, reseat)
+     register Lisp_Object list, reseat;
 {
   register int i;
   register Lisp_Object marker;
@@ -2841,8 +2912,7 @@ LIST should have been created by calling `match-data' previously.  */)
   if (running_asynch_code)
     save_search_regs ();
 
-  if (!CONSP (list) && !NILP (list))
-    list = wrong_type_argument (Qconsp, list);
+  CHECK_LIST (list);
 
   /* Unless we find a marker with a buffer or an explicit buffer
      in LIST, assume that this match data came from a string.  */
@@ -2877,9 +2947,9 @@ LIST should have been created by calling `match-data' previously.  */)
        search_regs.num_regs = length;
       }
 
-    for (i = 0;; i++)
+    for (i = 0; CONSP (list); i++)
       {
-       marker = Fcar (list);
+       marker = XCAR (list);
        if (BUFFERP (marker))
          {
            last_thing_searched = marker;
@@ -2890,12 +2960,14 @@ LIST should have been created by calling `match-data' previously.  */)
        if (NILP (marker))
          {
            search_regs.start[i] = -1;
-           list = Fcdr (list);
+           list = XCDR (list);
          }
        else
          {
            int from;
+           Lisp_Object m;
 
+           m = marker;
            if (MARKERP (marker))
              {
                if (XMARKER (marker)->buffer == 0)
@@ -2906,17 +2978,38 @@ LIST should have been created by calling `match-data' previously.  */)
 
            CHECK_NUMBER_COERCE_MARKER (marker);
            from = XINT (marker);
-           list = Fcdr (list);
 
-           marker = Fcar (list);
+           if (!NILP (reseat) && MARKERP (m))
+             {
+               if (EQ (reseat, Qevaporate))
+                 free_marker (m);
+               else
+                 unchain_marker (XMARKER (m));
+               XSETCAR (list, Qnil);
+             }
+
+           if ((list = XCDR (list), !CONSP (list)))
+             break;
+
+           m = marker = XCAR (list);
+
            if (MARKERP (marker) && XMARKER (marker)->buffer == 0)
              XSETFASTINT (marker, 0);
 
            CHECK_NUMBER_COERCE_MARKER (marker);
            search_regs.start[i] = from;
            search_regs.end[i] = XINT (marker);
+
+           if (!NILP (reseat) && MARKERP (m))
+             {
+               if (EQ (reseat, Qevaporate))
+                 free_marker (m);
+               else
+                 unchain_marker (XMARKER (m));
+               XSETCAR (list, Qnil);
+             }
          }
-       list = Fcdr (list);
+       list = XCDR (list);
       }
 
     for (; i < search_regs.num_regs; i++)
@@ -2954,7 +3047,7 @@ save_search_regs ()
 
 /* Called upon exit from filters and sentinels. */
 void
-restore_match_data ()
+restore_search_regs ()
 {
   if (search_regs_saved)
     {
@@ -2972,6 +3065,22 @@ restore_match_data ()
     }
 }
 
+static Lisp_Object
+unwind_set_match_data (list)
+     Lisp_Object list;
+{
+  /* It is safe to free (evaporate) the markers immediately.  */
+  return Fset_match_data (list, Qevaporate);
+}
+
+/* Called to unwind protect the match data.  */
+void
+record_unwind_save_match_data ()
+{
+  record_unwind_protect (unwind_set_match_data,
+                        Fmatch_data (Qnil, Qnil, Qnil));
+}
+
 /* Quote a string to inactivate reg-expr chars */
 
 DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,
@@ -2995,7 +3104,7 @@ DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,
 
   for (; in != end; in++)
     {
-      if (*in == '[' || *in == ']'
+      if (*in == '['
          || *in == '*' || *in == '.' || *in == '\\'
          || *in == '?' || *in == '+'
          || *in == '^' || *in == '$')
@@ -3021,7 +3130,10 @@ syms_of_search ()
       searchbufs[i].buf.fastmap = searchbufs[i].fastmap;
       searchbufs[i].regexp = Qnil;
       searchbufs[i].whitespace_regexp = Qnil;
+      searchbufs[i].syntax_table = Qnil;
       staticpro (&searchbufs[i].regexp);
+      staticpro (&searchbufs[i].whitespace_regexp);
+      staticpro (&searchbufs[i].syntax_table);
       searchbufs[i].next = (i == REGEXP_CACHE_SIZE-1 ? 0 : &searchbufs[i+1]);
     }
   searchbuf_head = &searchbufs[0];