(TAGS): Fix typo.
[bpt/emacs.git] / src / search.c
index 45119e6..fde9a8a 100644 (file)
@@ -22,7 +22,9 @@ Boston, MA 02111-1307, USA.  */
 #include <config.h>
 #include "lisp.h"
 #include "syntax.h"
+#include "category.h"
 #include "buffer.h"
+#include "charset.h"
 #include "region-cache.h"
 #include "commands.h"
 #include "blockinput.h"
@@ -105,15 +107,19 @@ matcher_overflow ()
    If it is 0, we should compile the pattern not to record any
    subexpression bounds.
    POSIX is nonzero if we want full backtracking (POSIX style)
-   for this pattern.  0 means backtrack only enough to get a valid match.  */
+   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.  */
 
 static void
-compile_pattern_1 (cp, pattern, translate, regp, posix)
+compile_pattern_1 (cp, pattern, translate, regp, posix, multibyte)
      struct regexp_cache *cp;
      Lisp_Object pattern;
      Lisp_Object *translate;
      struct re_registers *regp;
      int posix;
+     int multibyte;
 {
   CONST char *val;
   reg_syntax_t old;
@@ -121,6 +127,7 @@ compile_pattern_1 (cp, pattern, translate, regp, posix)
   cp->regexp = Qnil;
   cp->buf.translate = translate;
   cp->posix = posix;
+  cp->buf.multibyte = multibyte;
   BLOCK_INPUT;
   old = re_set_syntax (RE_SYNTAX_EMACS
                       | (posix ? 0 : RE_NO_POSIX_BACKTRACKING));
@@ -153,6 +160,9 @@ compile_pattern (pattern, regp, translate, posix)
      int posix;
 {
   struct regexp_cache *cp, **cpp;
+  /* Should we check it here, or add an argument `multibyte' to this
+     function?  */
+  int multibyte = !NILP (current_buffer->enable_multibyte_characters);
 
   for (cpp = &searchbuf_head; ; cpp = &cp->next)
     {
@@ -160,13 +170,14 @@ compile_pattern (pattern, regp, translate, posix)
       if (XSTRING (cp->regexp)->size == XSTRING (pattern)->size
          && !NILP (Fstring_equal (cp->regexp, pattern))
          && cp->buf.translate == translate
-         && cp->posix == posix)
+         && cp->posix == posix
+         && cp->buf.multibyte == multibyte)
        break;
 
       /* If we're at the end of the cache, compile into the last cell.  */
       if (cp->next == 0)
        {
-         compile_pattern_1 (cp, pattern, translate, regp, posix);
+         compile_pattern_1 (cp, pattern, translate, regp, posix, multibyte);
          break;
        }
     }
@@ -238,6 +249,8 @@ looking_at_1 (string, posix)
       s1 = ZV - BEGV;
       s2 = 0;
     }
+
+  re_match_object = Qnil;
   
   i = re_match_2 (bufp, (char *) p1, s1, (char *) p2, s2,
                  PT - BEGV, &search_regs,
@@ -314,6 +327,8 @@ string_match_1 (regexp, string, start, posix)
                           ? DOWNCASE_TABLE : 0),
                          posix);
   immediate_quit = 1;
+  re_match_object = string;
+  
   val = re_search (bufp, (char *) XSTRING (string)->data,
                   XSTRING (string)->size, s, XSTRING (string)->size - s,
                   &search_regs);
@@ -363,12 +378,37 @@ fast_string_match (regexp, string)
 
   bufp = compile_pattern (regexp, 0, 0, 0);
   immediate_quit = 1;
+  re_match_object = string;
+  
   val = re_search (bufp, (char *) XSTRING (string)->data,
                   XSTRING (string)->size, 0, XSTRING (string)->size,
                   0);
   immediate_quit = 0;
   return val;
 }
+
+/* Match REGEXP against STRING, searching all of STRING ignoring case,
+   and return the index of the match, or negative on failure.
+   This does not clobber the match data.  */
+
+extern Lisp_Object Vascii_downcase_table;
+
+int
+fast_string_match_ignore_case (regexp, string)
+     Lisp_Object regexp;
+     char *string;
+{
+  int val;
+  struct re_pattern_buffer *bufp;
+  int len = strlen (string);
+
+  bufp = compile_pattern (regexp, 0,
+                         XCHAR_TABLE (Vascii_downcase_table)->contents, 0);
+  immediate_quit = 1;
+  val = re_search (bufp, string, len, 0, len, 0);
+  immediate_quit = 0;
+  return val;
+}
 \f
 /* max and min.  */
 
@@ -502,8 +542,8 @@ scan_buffer (target, start, end, count, shortage, allow_quit)
 
         {
           /* The termination address of the dumb loop.  */ 
-          register unsigned char *ceiling_addr = &FETCH_CHAR (ceiling) + 1;
-          register unsigned char *cursor = &FETCH_CHAR (start);
+          register unsigned char *ceiling_addr = POS_ADDR (ceiling) + 1;
+          register unsigned char *cursor = POS_ADDR (start);
           unsigned char *base = cursor;
 
           while (cursor < ceiling_addr)
@@ -566,8 +606,8 @@ scan_buffer (target, start, end, count, shortage, allow_quit)
 
         {
           /* The termination address of the dumb loop.  */
-          register unsigned char *ceiling_addr = &FETCH_CHAR (ceiling);
-          register unsigned char *cursor = &FETCH_CHAR (start - 1);
+          register unsigned char *ceiling_addr = POS_ADDR (ceiling);
+          register unsigned char *cursor = POS_ADDR (start - 1);
           unsigned char *base = cursor;
 
           while (cursor >= ceiling_addr)
@@ -637,171 +677,6 @@ find_before_next_newline (from, to, cnt)
   return pos;
 }
 \f
-Lisp_Object skip_chars ();
-
-DEFUN ("skip-chars-forward", Fskip_chars_forward, Sskip_chars_forward, 1, 2, 0,
-  "Move point forward, stopping before a char not in STRING, or at pos LIM.\n\
-STRING is like the inside of a `[...]' in a regular expression\n\
-except that `]' is never special and `\\' quotes `^', `-' or `\\'.\n\
-Thus, with arg \"a-zA-Z\", this skips letters stopping before first nonletter.\n\
-With arg \"^a-zA-Z\", skips nonletters stopping before first letter.\n\
-Returns the distance traveled, either zero or positive.")
-  (string, lim)
-     Lisp_Object string, lim;
-{
-  return skip_chars (1, 0, string, lim);
-}
-
-DEFUN ("skip-chars-backward", Fskip_chars_backward, Sskip_chars_backward, 1, 2, 0,
-  "Move point backward, stopping after a char not in STRING, or at pos LIM.\n\
-See `skip-chars-forward' for details.\n\
-Returns the distance traveled, either zero or negative.")
-  (string, lim)
-     Lisp_Object string, lim;
-{
-  return skip_chars (0, 0, string, lim);
-}
-
-DEFUN ("skip-syntax-forward", Fskip_syntax_forward, Sskip_syntax_forward, 1, 2, 0,
-  "Move point forward across chars in specified syntax classes.\n\
-SYNTAX is a string of syntax code characters.\n\
-Stop before a char whose syntax is not in SYNTAX, or at position LIM.\n\
-If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\
-This function returns the distance traveled, either zero or positive.")
-  (syntax, lim)
-     Lisp_Object syntax, lim;
-{
-  return skip_chars (1, 1, syntax, lim);
-}
-
-DEFUN ("skip-syntax-backward", Fskip_syntax_backward, Sskip_syntax_backward, 1, 2, 0,
-  "Move point backward across chars in specified syntax classes.\n\
-SYNTAX is a string of syntax code characters.\n\
-Stop on reaching a char whose syntax is not in SYNTAX, or at position LIM.\n\
-If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\
-This function returns the distance traveled, either zero or negative.")
-  (syntax, lim)
-     Lisp_Object syntax, lim;
-{
-  return skip_chars (0, 1, syntax, lim);
-}
-
-Lisp_Object
-skip_chars (forwardp, syntaxp, string, lim)
-     int forwardp, syntaxp;
-     Lisp_Object string, lim;
-{
-  register unsigned char *p, *pend;
-  register unsigned char c;
-  unsigned char fastmap[0400];
-  int negate = 0;
-  register int i;
-
-  CHECK_STRING (string, 0);
-
-  if (NILP (lim))
-    XSETINT (lim, forwardp ? ZV : BEGV);
-  else
-    CHECK_NUMBER_COERCE_MARKER (lim, 1);
-
-  /* In any case, don't allow scan outside bounds of buffer.  */
-  /* jla turned this off, for no known reason.
-     bfox turned the ZV part on, and rms turned the
-     BEGV part back on.  */
-  if (XINT (lim) > ZV)
-    XSETFASTINT (lim, ZV);
-  if (XINT (lim) < BEGV)
-    XSETFASTINT (lim, BEGV);
-
-  p = XSTRING (string)->data;
-  pend = p + XSTRING (string)->size;
-  bzero (fastmap, sizeof fastmap);
-
-  if (p != pend && *p == '^')
-    {
-      negate = 1; p++;
-    }
-
-  /* Find the characters specified and set their elements of fastmap.
-     If syntaxp, each character counts as itself.
-     Otherwise, handle backslashes and ranges specially  */
-
-  while (p != pend)
-    {
-      c = *p++;
-      if (syntaxp)
-       fastmap[c] = 1;
-      else
-       {
-         if (c == '\\')
-           {
-             if (p == pend) break;
-             c = *p++;
-           }
-         if (p != pend && *p == '-')
-           {
-             p++;
-             if (p == pend) break;
-             while (c <= *p)
-               {
-                 fastmap[c] = 1;
-                 c++;
-               }
-             p++;
-           }
-         else
-           fastmap[c] = 1;
-       }
-    }
-
-  if (syntaxp && fastmap['-'] != 0)
-    fastmap[' '] = 1;
-
-  /* If ^ was the first character, complement the fastmap. */
-
-  if (negate)
-    for (i = 0; i < sizeof fastmap; i++)
-      fastmap[i] ^= 1;
-
-  {
-    int start_point = PT;
-
-    immediate_quit = 1;
-    if (syntaxp)
-      {
-
-       if (forwardp)
-         {
-           while (PT < XINT (lim)
-                  && fastmap[(unsigned char) syntax_code_spec[(int) SYNTAX (FETCH_CHAR (PT))]])
-             SET_PT (PT + 1);
-         }
-       else
-         {
-           while (PT > XINT (lim)
-                  && fastmap[(unsigned char) syntax_code_spec[(int) SYNTAX (FETCH_CHAR (PT - 1))]])
-             SET_PT (PT - 1);
-         }
-      }
-    else
-      {
-       if (forwardp)
-         {
-           while (PT < XINT (lim) && fastmap[FETCH_CHAR (PT)])
-             SET_PT (PT + 1);
-         }
-       else
-         {
-           while (PT > XINT (lim) && fastmap[FETCH_CHAR (PT - 1)])
-             SET_PT (PT - 1);
-         }
-      }
-    immediate_quit = 0;
-
-    return make_number (PT - start_point);
-  }
-}
-\f
 /* Subroutines of Lisp buffer search functions. */
 
 static Lisp_Object
@@ -892,6 +767,7 @@ trivial_regexp_p (regexp)
            case '|': case '(': case ')': case '`': case '\'': case 'b':
            case 'B': case '<': case '>': case 'w': case 'W': case 's':
            case 'S': case '=':
+           case 'c': case 'C': /* for categoryspec and notcategoryspec */
            case '1': case '2': case '3': case '4': case '5':
            case '6': case '7': case '8': case '9':
              return 0;
@@ -982,6 +858,8 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
          s1 = ZV - BEGV;
          s2 = 0;
        }
+      re_match_object = Qnil;
+  
       while (n < 0)
        {
          int val;
@@ -1167,8 +1045,8 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
                   : max (lim, max (limit, pos - 20000)));
          if ((limit - pos) * direction > 20)
            {
-             p_limit = &FETCH_CHAR (limit);
-             p2 = (cursor = &FETCH_CHAR (pos));
+             p_limit = POS_ADDR (limit);
+             p2 = (cursor = POS_ADDR (pos));
              /* In this loop, pos + cursor - p2 is the surrogate for pos */
              while (1)         /* use one cursor setting as long as i can */
                {
@@ -1258,7 +1136,7 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
                  /* (the reach is at most len + 21, and typically */
                  /* does not exceed len) */    
                  while ((limit - pos) * direction >= 0)
-                   pos += BM_tab[FETCH_CHAR(pos)];
+                   pos += BM_tab[FETCH_BYTE (pos)];
                  /* now run the same tests to distinguish going off the */
                  /* end, a match or a phony match. */
                  if ((pos - limit) * direction <= len)
@@ -1271,8 +1149,8 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
                    {
                      pos -= direction;
                      if (pat[i] != (trt != 0
-                                    ? trt[FETCH_CHAR(pos)]
-                                    : FETCH_CHAR (pos)))
+                                    ? trt[FETCH_BYTE (pos)]
+                                    : FETCH_BYTE (pos)))
                        break;
                    }
                  /* Above loop has moved POS part or all the way
@@ -1601,7 +1479,7 @@ since only regular expressions have distinguished subexpressions.")
       for (pos = search_regs.start[sub]; pos < last; pos++)
        {
          if (NILP (string))
-           c = FETCH_CHAR (pos);
+           c = FETCH_BYTE (pos);
          else
            c = XSTRING (string)->data[pos];
 
@@ -1658,7 +1536,8 @@ since only regular expressions have distinguished subexpressions.")
                           make_number (search_regs.start[sub]));
       after = Fsubstring (string, make_number (search_regs.end[sub]), Qnil);
 
-      /* Do case substitution into NEWTEXT if desired.  */
+      /* Substitute parts of the match into NEWTEXT
+        if desired.  */
       if (NILP (literal))
        {
          int lastpos = -1;
@@ -1693,6 +1572,8 @@ since only regular expressions have distinguished subexpressions.")
                    }
                  else if (c == '\\')
                    delbackslash = 1;
+                 else
+                   error ("Invalid use of `\\' in replacement text");
                }
              if (substart >= 0)
                {
@@ -1725,6 +1606,7 @@ since only regular expressions have distinguished subexpressions.")
          newtext = concat2 (accum, middle);
        }
 
+      /* Do case substitution in NEWTEXT if desired.  */
       if (case_action == all_caps)
        newtext = Fupcase (newtext);
       else if (case_action == cap_initial)
@@ -1766,8 +1648,10 @@ since only regular expressions have distinguished subexpressions.")
                       make_number (search_regs.start[c - '0'] + offset),
                       make_number (search_regs.end[c - '0'] + offset));
                }
-             else
+             else if (c == '\\')
                insert_char (c);
+             else
+               error ("Invalid use of `\\' in replacement text");
            }
          else
            insert_char (c);
@@ -2104,10 +1988,6 @@ syms_of_search ()
   defsubr (&Sposix_looking_at);
   defsubr (&Sstring_match);
   defsubr (&Sposix_string_match);
-  defsubr (&Sskip_chars_forward);
-  defsubr (&Sskip_chars_backward);
-  defsubr (&Sskip_syntax_forward);
-  defsubr (&Sskip_syntax_backward);
   defsubr (&Ssearch_forward);
   defsubr (&Ssearch_backward);
   defsubr (&Sword_search_forward);