XEmacs 21.4.15
[chise/xemacs-chise.git.1] / src / search.c
index 50d2a6b..7eebe5c 100644 (file)
@@ -108,6 +108,8 @@ Lisp_Object Vforward_word_regexp, Vbackward_word_regexp;
 Lisp_Object Vskip_chars_range_table;
 
 static void set_search_regs (struct buffer *buf, Bufpos beg, Charcount len);
+static void clear_unused_search_regs (struct re_registers *regp, int no_sub);
+/* #### according to comment in 21.5, unnecessary */
 static void save_search_regs (void);
 static Bufpos simple_search (struct buffer *buf, Bufbyte *base_pat,
                             Bytecount len, Bytind pos, Bytind lim,
@@ -772,6 +774,7 @@ find_before_next_newline (struct buffer *buf, Bufpos from, Bufpos to, int count)
   return pos;
 }
 \f
+/* This function synched with FSF 21.1 */
 static Lisp_Object
 skip_chars (struct buffer *buf, int forwardp, int syntaxp,
            Lisp_Object string, Lisp_Object lim)
@@ -842,6 +845,7 @@ skip_chars (struct buffer *buf, int forwardp, int syntaxp,
            {
              Emchar cend;
 
+             /* Skip over the dash.  */
              p++;
              if (p == pend) break;
              cend = charptr_emchar (p);
@@ -866,6 +870,7 @@ skip_chars (struct buffer *buf, int forwardp, int syntaxp,
        }
     }
 
+  /* #### Not in FSF 21.1 */
   if (syntaxp && fastmap['-'] != 0)
     fastmap[' '] = 1;
 
@@ -879,36 +884,48 @@ skip_chars (struct buffer *buf, int forwardp, int syntaxp,
 
   {
     Bufpos start_point = BUF_PT (buf);
+    Bufpos pos = start_point;
+    Bytind pos_byte = BI_BUF_PT (buf);
 
     if (syntaxp)
       {
-       SETUP_SYNTAX_CACHE_FOR_BUFFER (buf, BUF_PT (buf), forwardp ? 1 : -1);
+       SETUP_SYNTAX_CACHE_FOR_BUFFER (buf, pos, forwardp ? 1 : -1);
        /* All syntax designators are normal chars so nothing strange
           to worry about */
        if (forwardp)
          {
-           while (BUF_PT (buf) < limit
-                  && fastmap[(unsigned char)
-                              syntax_code_spec
-                             [(int) SYNTAX_FROM_CACHE (syntax_table,
-                                                       BUF_FETCH_CHAR
-                                                       (buf, BUF_PT (buf)))]])
-             {
-               BUF_SET_PT (buf, BUF_PT (buf) + 1);
-               UPDATE_SYNTAX_CACHE_FORWARD (BUF_PT (buf));
-             }
+           if (pos < limit)
+             while (fastmap[(unsigned char)
+                            syntax_code_spec
+                            [(int) SYNTAX_FROM_CACHE
+                             (syntax_table,
+                              BI_BUF_FETCH_CHAR (buf, pos_byte))]])
+               {
+                 pos++;
+                 INC_BYTIND (buf, pos_byte);
+                 if (pos >= limit)
+                   break;
+                 UPDATE_SYNTAX_CACHE_FORWARD (pos);
+               }
          }
        else
          {
-           while (BUF_PT (buf) > limit
-                  && fastmap[(unsigned char)
-                              syntax_code_spec
-                             [(int) SYNTAX_FROM_CACHE (syntax_table,
-                                                       BUF_FETCH_CHAR
-                                                       (buf, BUF_PT (buf) - 1))]])
+           while (pos > limit)
              {
-               BUF_SET_PT (buf, BUF_PT (buf) - 1);
-               UPDATE_SYNTAX_CACHE_BACKWARD (BUF_PT (buf) - 1);
+               Bufpos savepos = pos_byte;
+               pos--;
+               DEC_BYTIND (buf, pos_byte);
+               UPDATE_SYNTAX_CACHE_BACKWARD (pos);
+               if (!fastmap[(unsigned char)
+                            syntax_code_spec
+                            [(int) SYNTAX_FROM_CACHE
+                             (syntax_table,
+                              BI_BUF_FETCH_CHAR (buf, pos_byte))]])
+                 {
+                   pos++;
+                   pos_byte = savepos;
+                   break;
+                 }
              }
          }
       }
@@ -916,36 +933,47 @@ skip_chars (struct buffer *buf, int forwardp, int syntaxp,
       {
        if (forwardp)
          {
-           while (BUF_PT (buf) < limit)
+           while (pos < limit)
              {
-               Emchar ch = BUF_FETCH_CHAR (buf, BUF_PT (buf));
+               Emchar ch = BI_BUF_FETCH_CHAR (buf, pos_byte);
                if ((ch < 0400) ? fastmap[ch] :
                    (NILP (Fget_range_table (make_int (ch),
                                             Vskip_chars_range_table,
                                             Qnil))
                     == negate))
-                 BUF_SET_PT (buf, BUF_PT (buf) + 1);
+                 {
+                   pos++;
+                   INC_BYTIND (buf, pos_byte);
+                 }
                else
                  break;
              }
          }
        else
          {
-           while (BUF_PT (buf) > limit)
+           while (pos > limit)
              {
-               Emchar ch = BUF_FETCH_CHAR (buf, BUF_PT (buf) - 1);
+               Bufpos prev_pos_byte = pos_byte;
+               Emchar ch;
+
+               DEC_BYTIND (buf, prev_pos_byte);
+               ch = BI_BUF_FETCH_CHAR (buf, prev_pos_byte);
                if ((ch < 0400) ? fastmap[ch] :
-                   (NILP (Fget_range_table (make_int (ch),
-                                            Vskip_chars_range_table,
-                                            Qnil))
-                    == negate))
-                 BUF_SET_PT (buf, BUF_PT (buf) - 1);
-                else
-                  break;
+                     (NILP (Fget_range_table (make_int (ch),
+                                              Vskip_chars_range_table,
+                                              Qnil))
+                      == negate))
+                 {
+                   pos--;
+                   pos_byte = prev_pos_byte;
+                 }
+               else
+                 break;
              }
          }
       }
     QUIT;
+    BOTH_BUF_SET_PT (buf, pos, pos_byte);
     return make_int (BUF_PT (buf) - start_point);
   }
 }
@@ -1087,6 +1115,7 @@ trivial_regexp_p (Lisp_Object regexp)
     {
       switch (*s++)
        {
+       /* ']' doesn't appear here because it's only special after ] */
        case '.': case '*': case '+': case '?': case '[': case '^': case '$':
          return 0;
        case '\\':
@@ -1096,7 +1125,7 @@ trivial_regexp_p (Lisp_Object regexp)
            {
            case '|': case '(': case ')': case '`': case '\'': case 'b':
            case 'B': case '<': case '>': case 'w': case 'W': case 's':
-           case 'S': case '=':
+           case 'S': case '=': case '{': case '}':
 #ifdef MULE
            /* 97/2/25 jhod Added for category matches */
            case 'c': case 'C':
@@ -1146,10 +1175,11 @@ search_buffer (struct buffer *buf, Lisp_Object string, Bufpos bufpos,
   if (len == 0)
     {
       set_search_regs (buf, bufpos, 0);
+      clear_unused_search_regs (&search_regs, 0);
       return bufpos;
     }
 
-  /* Searching 0 times means don't move.  */
+  /* Searching 0 times means noop---don't move, don't touch registers.  */
   if (n == 0)
     return bufpos;
 
@@ -1196,6 +1226,8 @@ search_buffer (struct buffer *buf, Lisp_Object string, Bufpos bufpos,
                    search_regs.start[i] += j;
                    search_regs.end[i] += j;
                  }
+             /* re_match (called from re_search et al) does this for us */
+             /* clear_unused_search_regs (search_regs, bufp->no_sub);   */
              XSETBUFFER (last_thing_searched, buf);
              /* Set pos to the new position. */
              pos = search_regs.start[0];
@@ -1233,6 +1265,8 @@ search_buffer (struct buffer *buf, Lisp_Object string, Bufpos bufpos,
                    search_regs.start[i] += j;
                    search_regs.end[i] += j;
                  }
+             /* re_match (called from re_search et al) does this for us */
+             /* clear_unused_search_regs (search_regs, bufp->no_sub);   */
              XSETBUFFER (last_thing_searched, buf);
              /* Set pos to the new position. */
              pos = search_regs.end[0];
@@ -1433,6 +1467,7 @@ simple_search (struct buffer *buf, Bufbyte *base_pat, Bytecount len_byte,
          end = bytind_to_bufpos (buf, idx + buf_len);
        }
       set_search_regs (buf, beg, end - beg);
+      clear_unused_search_regs (&search_regs, 0);
 
       return retval;
     }
@@ -1794,6 +1829,7 @@ boyer_moore (struct buffer *buf, Bufbyte *base_pat, Bytecount len,
                    Bufpos bufend = bytind_to_bufpos (buf, bytstart + len);
 
                    set_search_regs (buf, bufstart, bufend - bufstart);
+                   clear_unused_search_regs (&search_regs, 0);
                  }
 
                  if ((n -= direction) != 0)
@@ -1883,6 +1919,7 @@ boyer_moore (struct buffer *buf, Bufbyte *base_pat, Bytecount len,
                    Bufpos bufend = bytind_to_bufpos (buf, bytstart + len);
 
                    set_search_regs (buf, bufstart, bufend - bufstart);
+                   clear_unused_search_regs (&search_regs, 0);
                  }
 
                  if ((n -= direction) != 0)
@@ -1902,8 +1939,8 @@ boyer_moore (struct buffer *buf, Bufbyte *base_pat, Bytecount len,
   return bytind_to_bufpos (buf, pos);
 }
 
-/* Record beginning BEG and end BEG + LEN
-   for a match just found in the current buffer.  */
+/* Record the whole-match data (beginning BEG and end BEG + LEN) and the
+   buffer for a match just found.  */
 
 static void
 set_search_regs (struct buffer *buf, Bufpos beg, Charcount len)
@@ -1923,6 +1960,24 @@ set_search_regs (struct buffer *buf, Bufpos beg, Charcount len)
   XSETBUFFER (last_thing_searched, buf);
 }
 
+/* Clear unused search registers so match data will be null.
+   REGP is a pointer to the register structure to clear, usually the global
+   search_regs.
+   NO_SUB is the number of subexpressions to allow for.  (Does not count
+   the whole match, ie, for a string search NO_SUB == 0.)
+   It is an error if NO_SUB > REGP.num_regs - 1. */
+
+static void
+clear_unused_search_regs (struct re_registers *regp, int no_sub)
+{
+  /* This function has been Mule-ized. */
+  int i;
+
+  assert (no_sub >= 0 && no_sub < regp->num_regs);
+  for (i = no_sub + 1; i < regp->num_regs; i++)
+    regp->start[i] = regp->end[i] = -1;
+}
+
 \f
 /* Given a string of words separated by word delimiters,
    compute a regexp that matches those exact words
@@ -2269,7 +2324,7 @@ match since only regular expressions have distinguished subexpressions.
   Lisp_Object buffer;
   int_dynarr *ul_action_dynarr = 0;
   int_dynarr *ul_pos_dynarr = 0;
-  int sub;
+  int sub = 0;
   int speccount;
 
   CHECK_STRING (replacement);
@@ -2290,9 +2345,7 @@ match since only regular expressions have distinguished subexpressions.
     }
   else
     {
-      if (NILP (strbuffer))
-       sub = 0;
-      else
+      if (!NILP (strbuffer))
        {
          CHECK_INT (strbuffer);
          sub = XINT (strbuffer);
@@ -2334,7 +2387,7 @@ match since only regular expressions have distinguished subexpressions.
     {
       /* Decide how to casify by examining the matched text. */
 
-      last = search_regs.end[0];
+      last = search_regs.end[sub];
       prevc = '\n';
       case_action = all_caps;
 
@@ -2345,7 +2398,7 @@ match since only regular expressions have distinguished subexpressions.
       some_nonuppercase_initial = 0;
       some_uppercase = 0;
 
-      for (pos = search_regs.start[0]; pos < last; pos++)
+      for (pos = search_regs.start[sub]; pos < last; pos++)
        {
          if (NILP (string))
            c = BUF_FETCH_CHAR (buf, pos);
@@ -2561,8 +2614,8 @@ match since only regular expressions have distinguished subexpressions.
       return concat3 (before, replacement, after);
     }
 
-  mc_count = begin_multiple_change (buf, search_regs.start[0],
-                                   search_regs.end[0]);
+  mc_count = begin_multiple_change (buf, search_regs.start[sub],
+                                   search_regs.end[sub]);
 
   /* begin_multiple_change() records an unwind-protect, so we need to
      record this value now. */
@@ -2572,7 +2625,7 @@ match since only regular expressions have distinguished subexpressions.
      delete the original text.  This means that markers at the
      beginning or end of the original will float to the corresponding
      position in the replacement.  */
-  BUF_SET_PT (buf, search_regs.start[0]);
+  BUF_SET_PT (buf, search_regs.start[sub]);
   if (!NILP (literal))
     Finsert (1, &replacement);
   else
@@ -2583,11 +2636,21 @@ match since only regular expressions have distinguished subexpressions.
       GCPRO1 (replacement);
       for (strpos = 0; strpos < stlen; strpos++)
        {
-         Charcount offset = BUF_PT (buf) - search_regs.start[0];
+         /* on the first iteration assert(offset==0),
+            exactly complementing BUF_SET_PT() above.
+            During the loop, it keeps track of the amount inserted.
+          */
+         Charcount offset = BUF_PT (buf) - search_regs.start[sub];
 
          c = string_char (XSTRING (replacement), strpos);
          if (c == '\\' && strpos < stlen - 1)
            {
+             /* XXX FIXME: replacing just a substring non-literally
+                using backslash refs to the match looks dangerous.  But
+                <15366.18513.698042.156573@ns.caldera.de> from Torsten Duwe
+                <duwe@caldera.de> claims Finsert_buffer_substring already
+                handles this correctly.
+             */
              c = string_char (XSTRING (replacement), ++strpos);
              if (c == '&')
                Finsert_buffer_substring
@@ -2630,9 +2693,9 @@ match since only regular expressions have distinguished subexpressions.
       UNGCPRO;
     }
 
-  inslen = BUF_PT (buf) - (search_regs.start[0]);
-  buffer_delete_range (buf, search_regs.start[0] + inslen, search_regs.end[0] +
-                      inslen, 0);
+  inslen = BUF_PT (buf) - (search_regs.start[sub]);
+  buffer_delete_range (buf, search_regs.start[sub] + inslen,
+                      search_regs.end[sub] +  inslen, 0);
 
   if (case_action == all_caps)
     Fupcase_region (make_int (BUF_PT (buf) - inslen),
@@ -2817,8 +2880,11 @@ LIST should have been created by calling `match-data' previously.
   int num_regs;
   int length;
 
+#if 0
+  /* #### according to 21.5 comment, unnecessary */
   if (running_asynch_code)
     save_search_regs ();
+#endif
 
   CONCHECK_LIST (list);
 
@@ -2881,6 +2947,7 @@ LIST should have been created by calling `match-data' previously.
   return Qnil;
 }
 
+/* #### according to 21.5 comment, unnecessary */
 /* If non-zero the match data have been saved in saved_search_regs
    during the execution of a sentinel or filter. */
 static int search_regs_saved;
@@ -2904,6 +2971,8 @@ save_search_regs (void)
     }
 }
 
+/* #### according to 21.5 comment, unnecessary
+   prototype in lisp.h, all calls in process.c */
 /* Called upon exit from filters and sentinels. */
 void
 restore_match_data (void)