]> code.delx.au - gnu-emacs/blobdiff - src/search.c
(main) [MAC_OS8 || MAC_OSX && HAVE_CARBON]: Call syms_of_macselect.
[gnu-emacs] / src / search.c
index b73ed338791158f1cab665bafc7161862f8e966e..73ec3a78e58fedcb27d904852d3706db88b7fa03 100644 (file)
@@ -41,7 +41,7 @@ Boston, MA 02111-1307, USA.  */
 struct regexp_cache
 {
   struct regexp_cache *next;
-  Lisp_Object regexp;
+  Lisp_Object regexp, whitespace_regexp;
   struct re_pattern_buffer buf;
   char fastmap[0400];
   /* Nonzero means regexp was compiled to do full POSIX backtracking.  */
@@ -83,7 +83,7 @@ static Lisp_Object last_thing_searched;
 
 Lisp_Object Qinvalid_regexp;
 
-Lisp_Object Vsearch_whitespace_regexp;
+Lisp_Object Vsearch_spaces_regexp;
 
 static void set_search_regs ();
 static void save_search_regs ();
@@ -109,7 +109,9 @@ matcher_overflow ()
    for this pattern.  0 means backtrack only enough to get a valid match.
    MULTIBYTE is nonzero if we want to handle multibyte characters in
    PATTERN.  0 means all multibyte characters are recognized just as
-   sequences of binary data.  */
+   sequences of binary data.
+
+   The behavior also depends on Vsearch_spaces_regexp.  */
 
 static void
 compile_pattern_1 (cp, pattern, translate, regp, posix, multibyte)
@@ -160,12 +162,13 @@ compile_pattern_1 (cp, pattern, translate, regp, posix, multibyte)
   cp->buf.translate = (! NILP (translate) ? translate : make_number (0));
   cp->posix = posix;
   cp->buf.multibyte = multibyte;
+  cp->whitespace_regexp = Vsearch_spaces_regexp;
   BLOCK_INPUT;
   old = re_set_syntax (RE_SYNTAX_EMACS
                       | (posix ? 0 : RE_NO_POSIX_BACKTRACKING));
 
-  re_set_whitespace_regexp (NILP (Vsearch_whitespace_regexp) ? NULL
-                           : SDATA (Vsearch_whitespace_regexp));
+  re_set_whitespace_regexp (NILP (Vsearch_spaces_regexp) ? NULL
+                           : SDATA (Vsearch_spaces_regexp));
 
   val = (char *) re_compile_pattern ((char *)raw_pattern,
                                     raw_pattern_size, &cp->buf);
@@ -232,7 +235,8 @@ compile_pattern (pattern, regp, translate, posix, multibyte)
          && !NILP (Fstring_equal (cp->regexp, pattern))
          && EQ (cp->buf.translate, (! NILP (translate) ? translate : make_number (0)))
          && cp->posix == posix
-         && cp->buf.multibyte == multibyte)
+         && cp->buf.multibyte == multibyte
+         && !NILP (Fequal (cp->whitespace_regexp, Vsearch_spaces_regexp)))
        break;
 
       /* If we're at the end of the cache, compile into the nil cell
@@ -289,7 +293,7 @@ looking_at_1 (string, posix)
   CHECK_STRING (string);
   bufp = compile_pattern (string, &search_regs,
                          (!NILP (current_buffer->case_fold_search)
-                          ? DOWNCASE_TABLE : Qnil),
+                          ? current_buffer->case_canon_table : Qnil),
                          posix,
                          !NILP (current_buffer->enable_multibyte_characters));
 
@@ -395,7 +399,7 @@ string_match_1 (regexp, string, start, posix)
 
   bufp = compile_pattern (regexp, &search_regs,
                          (!NILP (current_buffer->case_fold_search)
-                          ? DOWNCASE_TABLE : Qnil),
+                          ? current_buffer->case_canon_table : Qnil),
                          posix,
                          STRING_MULTIBYTE (string));
   immediate_quit = 1;
@@ -495,7 +499,7 @@ fast_c_string_match_ignore_case (regexp, string)
   regexp = string_make_unibyte (regexp);
   re_match_object = Qt;
   bufp = compile_pattern (regexp, 0,
-                         Vascii_downcase_table, 0,
+                         Vascii_canon_table, 0,
                          0);
   immediate_quit = 1;
   val = re_search (bufp, string, len, 0, len, 0);
@@ -512,7 +516,7 @@ fast_string_match_ignore_case (regexp, string)
   int val;
   struct re_pattern_buffer *bufp;
 
-  bufp = compile_pattern (regexp, 0, Vascii_downcase_table,
+  bufp = compile_pattern (regexp, 0, Vascii_canon_table,
                          0, STRING_MULTIBYTE (string));
   immediate_quit = 1;
   re_match_object = string;
@@ -1060,7 +1064,7 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n,
       return pos;
     }
 
-  if (RE && !(trivial_regexp_p (string) && NILP (Vsearch_whitespace_regexp)))
+  if (RE && !(trivial_regexp_p (string) && NILP (Vsearch_spaces_regexp)))
     {
       unsigned char *p1, *p2;
       int s1, s2;
@@ -1171,7 +1175,9 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n,
       unsigned char *patbuf;
       int multibyte = !NILP (current_buffer->enable_multibyte_characters);
       unsigned char *base_pat = SDATA (string);
-      int charset_base = -1;
+      /* Set to nozero if we find a non-ASCII char that need
+        translation.  */
+      int charset_base = 0;
       int boyer_moore_ok = 1;
 
       /* MULTIBYTE says whether the text to be searched is multibyte.
@@ -1217,9 +1223,17 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n,
       base_pat = raw_pattern;
       if (multibyte)
        {
+         /* Fill patbuf by translated characters in STRING while
+            checking if we can use boyer-moore search.  If TRT is
+            non-nil, we can use boyer-moore search only if TRT can be
+            represented by the byte array of 256 elements.  For that,
+            all non-ASCII case-equivalents of all case-senstive
+            characters in STRING must belong to the same charset and
+            row.  */
+
          while (--len >= 0)
            {
-             unsigned char str[MAX_MULTIBYTE_LENGTH];
+             unsigned char str_base[MAX_MULTIBYTE_LENGTH], *str;
              int c, translated, inverse;
              int in_charlen, charlen;
 
@@ -1229,50 +1243,62 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n,
              if (RE && *base_pat == '\\')
                {
                  len--;
+                 raw_pattern_size--;
                  len_byte--;
                  base_pat++;
                }
 
              c = STRING_CHAR_AND_LENGTH (base_pat, len_byte, in_charlen);
 
-             /* Translate the character, if requested.  */
-             TRANSLATE (translated, trt, c);
-             /* If translation changed the byte-length, go back
-                to the original character.  */
-             charlen = CHAR_STRING (translated, str);
-             if (in_charlen != charlen)
+             if (NILP (trt))
                {
-                 translated = c;
-                 charlen = CHAR_STRING (c, str);
+                 str = base_pat;
+                 charlen = in_charlen;
                }
-
-             /* If we are searching for something strange,
-                an invalid multibyte code, don't use boyer-moore.  */
-             if (! ASCII_BYTE_P (translated)
-                 && (charlen == 1 /* 8bit code */
-                     || charlen != in_charlen /* invalid multibyte code */
-                     ))
-               boyer_moore_ok = 0;
-
-             TRANSLATE (inverse, inverse_trt, c);
-
-             /* Did this char actually get translated?
-                Would any other char get translated into it?  */
-             if (translated != c || inverse != c)
+             else
                {
-                 /* Keep track of which character set row
-                    contains the characters that need translation.  */
-                 int charset_base_code = c & ~CHAR_FIELD3_MASK;
-                 int inverse_charset_base = inverse & ~CHAR_FIELD3_MASK;
-
-                 if (charset_base_code != inverse_charset_base)
-                   boyer_moore_ok = 0;
-                 else if (charset_base == -1)
-                   charset_base = charset_base_code;
-                 else if (charset_base != charset_base_code)
-                   /* If two different rows appear, needing translation,
-                      then we cannot use boyer_moore search.  */
-                   boyer_moore_ok = 0;
+                 /* Translate the character.  */
+                 TRANSLATE (translated, trt, c);
+                 charlen = CHAR_STRING (translated, str_base);
+                 str = str_base;
+
+                 /* Check if C has any other case-equivalents.  */
+                 TRANSLATE (inverse, inverse_trt, c);
+                 /* If so, check if we can use boyer-moore.  */
+                 if (c != inverse && boyer_moore_ok)
+                   {
+                     /* Check if all equivalents belong to the same
+                        charset & row.  Note that the check of C
+                        itself is done by the last iteration.  Note
+                        also that we don't have to check ASCII
+                        characters because boyer-moore search can
+                        always handle their translation.  */
+                     while (1)
+                       {
+                         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)
+                               {
+                                 boyer_moore_ok = 0;
+                                 break;
+                               }
+                           }
+                         if (c == inverse)
+                           break;
+                         TRANSLATE (inverse, inverse_trt, inverse);
+                       }
+                   }
                }
 
              /* Store this character into the translated pattern.  */
@@ -1296,6 +1322,7 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n,
              if (RE && *base_pat == '\\')
                {
                  len--;
+                 raw_pattern_size--;
                  base_pat++;
                }
              c = *base_pat++;
@@ -1529,16 +1556,18 @@ simple_search (n, pat, len, len_byte, trt, pos, pos_byte, lim, lim_byte)
     return n;
 }
 \f
-/* Do Boyer-Moore search N times for the string PAT,
+/* Do Boyer-Moore search N times for the string BASE_PAT,
    whose length is LEN/LEN_BYTE,
    from buffer position POS/POS_BYTE until LIM/LIM_BYTE.
    DIRECTION says which direction we search in.
    TRT and INVERSE_TRT are translation tables.
+   Characters in PAT are already translated by TRT.
 
-   This kind of search works if all the characters in PAT that have
-   nontrivial translation are the same aside from the last byte.  This
-   makes it possible to translate just the last byte of a character,
-   and do so after just a simple test of the context.
+   This kind of search works if all the characters in BASE_PAT that
+   have nontrivial translation are the same aside from the last byte.
+   This makes it possible to translate just the last byte of a
+   character, and do so after just a simple test of the context.
+   CHARSET_BASE is nonzero iff there is such a non-ASCII character.
 
    If that criterion is not satisfied, do not call this function.  */
 
@@ -1565,8 +1594,13 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
   int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
 
   unsigned char simple_translate[0400];
-  int translate_prev_byte = 0;
-  int translate_anteprev_byte = 0;
+  /* These are set to the preceding bytes of a byte to be translated
+     if charset_base is nonzero.  As the maximum byte length of a
+     multibyte character is 4, we have to check at most three previous
+     bytes.  */
+  int translate_prev_byte1 = 0;
+  int translate_prev_byte2 = 0;
+  int translate_prev_byte3 = 0;
 
 #ifdef C_ALLOCA
   int BM_tab_space[0400];
@@ -1632,6 +1666,23 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
   for (i = 0; i < 0400; i++)
     simple_translate[i] = i;
 
+  if (charset_base)
+    {
+      /* Setup translate_prev_byte1/2/3 from CHARSET_BASE.  Only a
+        byte following them are the target of translation.  */
+      int sample_char = charset_base | 0x20;
+      unsigned char str[MAX_MULTIBYTE_LENGTH];
+      int len = CHAR_STRING (sample_char, str);
+
+      translate_prev_byte1 = str[len - 2];
+      if (len > 2)
+       {
+         translate_prev_byte2 = str[len - 3];
+         if (len > 3)
+           translate_prev_byte3 = str[len - 4];
+       }
+    }
+
   i = 0;
   while (i != infinity)
     {
@@ -1641,46 +1692,30 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
        i = infinity;
       if (! NILP (trt))
        {
-         int ch;
-         int untranslated;
-         int this_translated = 1;
-
-         if (multibyte
-             /* Is *PTR the last byte of a character?  */
-             && (pat_end - ptr == 1 || CHAR_HEAD_P (ptr[1])))
+         /* 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
+                  && (pat_end - ptr) == 1 || CHAR_HEAD_P (ptr[1]))
            {
-             unsigned char *charstart = ptr;
-             while (! CHAR_HEAD_P (*charstart))
+             unsigned char *charstart = ptr - 1;
+
+             while (! (CHAR_HEAD_P (*charstart)))
                charstart--;
-             untranslated = STRING_CHAR (charstart, ptr - charstart + 1);
-             if (charset_base == (untranslated & ~CHAR_FIELD3_MASK))
-               {
-                 TRANSLATE (ch, trt, untranslated);
-                 if (! CHAR_HEAD_P (*ptr))
-                   {
-                     translate_prev_byte = ptr[-1];
-                     if (! CHAR_HEAD_P (translate_prev_byte))
-                       translate_anteprev_byte = ptr[-2];
-                   }
-               }
-             else
-               {
-                 this_translated = 0;
-                 ch = *ptr;
-               }
-           }
-         else if (!multibyte)
-           TRANSLATE (ch, trt, *ptr);
-         else
-           {
-             ch = *ptr;
-             this_translated = 0;
+             ch = STRING_CHAR (charstart, ptr - charstart + 1);
+             if (charset_base != (ch & ~CHAR_FIELD3_MASK))
+               ch = -1;
            }
 
          if (ch > 0400)
            j = ((unsigned char) ch) | 0200;
          else
-           j = (unsigned char) ch;
+           j = *ptr;
 
          if (i == infinity)
            stride_for_teases = BM_tab[j];
@@ -1688,10 +1723,11 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
          BM_tab[j] = dirlen - i;
          /* A translation table is accompanied by its inverse -- see */
          /* comment following downcase_table for details */
-         if (this_translated)
+         if (ch >= 0)
            {
              int starting_ch = ch;
              int starting_j = j;
+
              while (1)
                {
                  TRANSLATE (ch, inverse_trt, ch);
@@ -1817,9 +1853,13 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
                          || ((cursor == tail_end_ptr
                               || CHAR_HEAD_P (cursor[1]))
                              && (CHAR_HEAD_P (cursor[0])
-                                 || (translate_prev_byte == cursor[-1]
-                                     && (CHAR_HEAD_P (translate_prev_byte)
-                                         || translate_anteprev_byte == cursor[-2])))))
+                                 /* Check if this is the last byte of
+                                    a translable character.  */
+                                 || (translate_prev_byte1 == cursor[-1]
+                                     && (CHAR_HEAD_P (translate_prev_byte1)
+                                         || (translate_prev_byte2 == cursor[-2]
+                                             && (CHAR_HEAD_P (translate_prev_byte2)
+                                                 || (translate_prev_byte3 == cursor[-3]))))))))
                        ch = simple_translate[*cursor];
                      else
                        ch = *cursor;
@@ -1897,9 +1937,13 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
                      || ((ptr == tail_end_ptr
                           || CHAR_HEAD_P (ptr[1]))
                          && (CHAR_HEAD_P (ptr[0])
-                             || (translate_prev_byte == ptr[-1]
-                                 && (CHAR_HEAD_P (translate_prev_byte)
-                                     || translate_anteprev_byte == ptr[-2])))))
+                             /* Check if this is the last byte of a
+                                translable character.  */
+                             || (translate_prev_byte1 == ptr[-1]
+                                 && (CHAR_HEAD_P (translate_prev_byte1)
+                                     || (translate_prev_byte2 == ptr[-2]
+                                         && (CHAR_HEAD_P (translate_prev_byte2)
+                                             || translate_prev_byte3 == ptr[-3])))))))
                    ch = simple_translate[*ptr];
                  else
                    ch = *ptr;
@@ -2856,7 +2900,7 @@ LIST should have been created by calling `match-data' previously.  */)
        else
          {
            int from;
-           
+
            if (MARKERP (marker))
              {
                if (XMARKER (marker)->buffer == 0)
@@ -2864,15 +2908,15 @@ LIST should have been created by calling `match-data' previously.  */)
                else
                  XSETBUFFER (last_thing_searched, XMARKER (marker)->buffer);
              }
-           
+
            CHECK_NUMBER_COERCE_MARKER (marker);
            from = XINT (marker);
            list = Fcdr (list);
-           
+
            marker = Fcar (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);
@@ -2981,6 +3025,7 @@ syms_of_search ()
       searchbufs[i].buf.buffer = (unsigned char *) xmalloc (100);
       searchbufs[i].buf.fastmap = searchbufs[i].fastmap;
       searchbufs[i].regexp = Qnil;
+      searchbufs[i].whitespace_regexp = Qnil;
       staticpro (&searchbufs[i].regexp);
       searchbufs[i].next = (i == REGEXP_CACHE_SIZE-1 ? 0 : &searchbufs[i+1]);
     }
@@ -3007,13 +3052,13 @@ syms_of_search ()
   saved_last_thing_searched = Qnil;
   staticpro (&saved_last_thing_searched);
 
-  DEFVAR_LISP ("search-whitespace-regexp", &Vsearch_whitespace_regexp,
-      /* doc: Regexp to substitute for bunches of spaces in regexp search.
+  DEFVAR_LISP ("search-spaces-regexp", &Vsearch_spaces_regexp,
+      doc: /* Regexp to substitute for bunches of spaces in regexp search.
 Some commands use this for user-specified regexps.
 Spaces that occur inside character classes or repetition operators
 or other such regexp constructs are not replaced with this.
 A value of nil (which is the normal value) means treat spaces literally.  */);
-  Vsearch_whitespace_regexp = Qnil;
+  Vsearch_spaces_regexp = Qnil;
 
   defsubr (&Slooking_at);
   defsubr (&Sposix_looking_at);