]> code.delx.au - gnu-emacs/blobdiff - src/search.c
Merge from emacs--rel--22
[gnu-emacs] / src / search.c
index b92812597d5de581ba0b0d428321d13d69b0586a..7761448f0d9a2f189ce8f256425b29b70b3bf59a 100644 (file)
@@ -1,12 +1,13 @@
 /* String search routines for GNU Emacs.
-   Copyright (C) 1985, 1986, 1987, 1993, 1994, 1997, 1998, 1999, 2002, 2003,
-                 2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1993, 1994, 1997, 1998, 1999, 2001, 2002,
+                 2003, 2004, 2005, 2006, 2007, 2008
+                 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs 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 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -42,6 +43,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,13 +88,22 @@ 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;
 
+/* If non-nil, the match data will not be changed during call to
+   searching or matching functions.  This variable is for internal use
+   only.  */
+Lisp_Object Vinhibit_changing_match_data;
+
 static void set_search_regs ();
 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 +177,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 +191,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 +222,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 +276,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 +307,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,8 +322,14 @@ 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,
+  bufp = compile_pattern (string,
+                         (NILP (Vinhibit_changing_match_data)
+                          ? &search_regs : NULL),
                          (!NILP (current_buffer->case_fold_search)
                           ? current_buffer->case_canon_table : Qnil),
                          posix,
@@ -322,7 +360,9 @@ looking_at_1 (string, posix)
   re_match_object = Qnil;
 
   i = re_match_2 (bufp, (char *) p1, s1, (char *) p2, s2,
-                 PT_BYTE - BEGV_BYTE, &search_regs,
+                 PT_BYTE - BEGV_BYTE,
+                 (NILP (Vinhibit_changing_match_data)
+                  ? &search_regs : NULL),
                  ZV_BYTE - BEGV_BYTE);
   immediate_quit = 0;
 
@@ -330,7 +370,7 @@ looking_at_1 (string, posix)
     matcher_overflow ();
 
   val = (0 <= i ? Qt : Qnil);
-  if (i >= 0)
+  if (NILP (Vinhibit_changing_match_data) && i >= 0)
     for (i = 0; i < search_regs.num_regs; i++)
       if (search_regs.start[i] >= 0)
        {
@@ -339,7 +379,11 @@ looking_at_1 (string, posix)
          search_regs.end[i]
            = BYTE_TO_CHAR (search_regs.end[i] + BEGV_BYTE);
        }
-  XSETBUFFER (last_thing_searched, current_buffer);
+
+  /* Set last_thing_searched only when match data is changed.  */
+  if (NILP (Vinhibit_changing_match_data))
+    XSETBUFFER (last_thing_searched, current_buffer);
+
   return val;
 }
 
@@ -397,7 +441,13 @@ string_match_1 (regexp, string, start, posix)
       pos_byte = string_char_to_byte (string, pos);
     }
 
-  bufp = compile_pattern (regexp, &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;
+
+  bufp = compile_pattern (regexp,
+                         (NILP (Vinhibit_changing_match_data)
+                          ? &search_regs : NULL),
                          (!NILP (current_buffer->case_fold_search)
                           ? current_buffer->case_canon_table : Qnil),
                          posix,
@@ -408,21 +458,27 @@ string_match_1 (regexp, string, start, posix)
   val = re_search (bufp, (char *) SDATA (string),
                   SBYTES (string), pos_byte,
                   SBYTES (string) - pos_byte,
-                  &search_regs);
+                  (NILP (Vinhibit_changing_match_data)
+                   ? &search_regs : NULL));
   immediate_quit = 0;
-  last_thing_searched = Qt;
+
+  /* Set last_thing_searched only when match data is changed.  */
+  if (NILP (Vinhibit_changing_match_data))
+    last_thing_searched = Qt;
+
   if (val == -2)
     matcher_overflow ();
   if (val < 0) return Qnil;
 
-  for (i = 0; i < search_regs.num_regs; i++)
-    if (search_regs.start[i] >= 0)
-      {
-       search_regs.start[i]
-         = string_byte_to_char (string, search_regs.start[i]);
-       search_regs.end[i]
-         = string_byte_to_char (string, search_regs.end[i]);
-      }
+  if (NILP (Vinhibit_changing_match_data))
+    for (i = 0; i < search_regs.num_regs; i++)
+      if (search_regs.start[i] >= 0)
+       {
+         search_regs.start[i]
+           = string_byte_to_char (string, search_regs.start[i]);
+         search_regs.end[i]
+           = string_byte_to_char (string, search_regs.end[i]);
+       }
 
   return make_number (string_byte_to_char (string, val));
 }
@@ -936,6 +992,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 +1007,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)
@@ -1035,6 +1096,11 @@ do                                               \
   }                                            \
 while (0)
 
+/* Only used in search_buffer, to record the end position of the match
+   when searching regexps and SEARCH_REGS should not be changed
+   (i.e. Vinhibit_changing_match_data is non-nil).  */
+static struct re_registers search_regs_1;
+
 static int
 search_buffer (string, pos, pos_byte, lim, lim_byte, n,
               RE, trt, inverse_trt, posix)
@@ -1070,7 +1136,10 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n,
       int s1, s2;
       struct re_pattern_buffer *bufp;
 
-      bufp = compile_pattern (string, &search_regs, trt, posix,
+      bufp = compile_pattern (string,
+                             (NILP (Vinhibit_changing_match_data)
+                              ? &search_regs : &search_regs_1),
+                             trt, posix,
                              !NILP (current_buffer->enable_multibyte_characters));
 
       immediate_quit = 1;      /* Quit immediately if user types ^G,
@@ -1103,7 +1172,8 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n,
          int val;
          val = re_search_2 (bufp, (char *) p1, s1, (char *) p2, s2,
                             pos_byte - BEGV_BYTE, lim_byte - pos_byte,
-                            &search_regs,
+                            (NILP (Vinhibit_changing_match_data)
+                             ? &search_regs : &search_regs_1),
                             /* Don't allow match past current point */
                             pos_byte - BEGV_BYTE);
          if (val == -2)
@@ -1112,18 +1182,27 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n,
            }
          if (val >= 0)
            {
-             pos_byte = search_regs.start[0] + BEGV_BYTE;
-             for (i = 0; i < search_regs.num_regs; i++)
-               if (search_regs.start[i] >= 0)
-                 {
-                   search_regs.start[i]
-                     = BYTE_TO_CHAR (search_regs.start[i] + BEGV_BYTE);
-                   search_regs.end[i]
-                     = BYTE_TO_CHAR (search_regs.end[i] + BEGV_BYTE);
-                 }
-             XSETBUFFER (last_thing_searched, current_buffer);
-             /* Set pos to the new position. */
-             pos = search_regs.start[0];
+             if (NILP (Vinhibit_changing_match_data))
+               {
+                 pos_byte = search_regs.start[0] + BEGV_BYTE;
+                 for (i = 0; i < search_regs.num_regs; i++)
+                   if (search_regs.start[i] >= 0)
+                     {
+                       search_regs.start[i]
+                         = BYTE_TO_CHAR (search_regs.start[i] + BEGV_BYTE);
+                       search_regs.end[i]
+                         = BYTE_TO_CHAR (search_regs.end[i] + BEGV_BYTE);
+                     }
+                 XSETBUFFER (last_thing_searched, current_buffer);
+                 /* Set pos to the new position. */
+                 pos = search_regs.start[0];
+               }
+             else
+               {
+                 pos_byte = search_regs_1.start[0] + BEGV_BYTE;
+                 /* Set pos to the new position.  */
+                 pos = BYTE_TO_CHAR (search_regs_1.start[0] + BEGV_BYTE);
+               }
            }
          else
            {
@@ -1137,7 +1216,8 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n,
          int val;
          val = re_search_2 (bufp, (char *) p1, s1, (char *) p2, s2,
                             pos_byte - BEGV_BYTE, lim_byte - pos_byte,
-                            &search_regs,
+                            (NILP (Vinhibit_changing_match_data)
+                             ? &search_regs : &search_regs_1),
                             lim_byte - BEGV_BYTE);
          if (val == -2)
            {
@@ -1145,17 +1225,25 @@ search_buffer (string, pos, pos_byte, lim, lim_byte, n,
            }
          if (val >= 0)
            {
-             pos_byte = search_regs.end[0] + BEGV_BYTE;
-             for (i = 0; i < search_regs.num_regs; i++)
-               if (search_regs.start[i] >= 0)
-                 {
-                   search_regs.start[i]
-                     = BYTE_TO_CHAR (search_regs.start[i] + BEGV_BYTE);
-                   search_regs.end[i]
-                     = BYTE_TO_CHAR (search_regs.end[i] + BEGV_BYTE);
-                 }
-             XSETBUFFER (last_thing_searched, current_buffer);
-             pos = search_regs.end[0];
+             if (NILP (Vinhibit_changing_match_data))
+               {
+                 pos_byte = search_regs.end[0] + BEGV_BYTE;
+                 for (i = 0; i < search_regs.num_regs; i++)
+                   if (search_regs.start[i] >= 0)
+                     {
+                       search_regs.start[i]
+                         = BYTE_TO_CHAR (search_regs.start[i] + BEGV_BYTE);
+                       search_regs.end[i]
+                         = BYTE_TO_CHAR (search_regs.end[i] + BEGV_BYTE);
+                     }
+                 XSETBUFFER (last_thing_searched, current_buffer);
+                 pos = search_regs.end[0];
+               }
+             else
+               {
+                 pos_byte = search_regs_1.end[0] + BEGV_BYTE;
+                 pos = BYTE_TO_CHAR (search_regs_1.end[0] + BEGV_BYTE);
+               }
            }
          else
            {
@@ -1475,7 +1563,7 @@ simple_search (n, pat, len, len_byte, trt, pos, pos_byte, lim, lim_byte)
            int this_len_byte = len_byte;
            unsigned char *p = pat;
 
-           if (pos - len < lim)
+           if (this_pos < lim || this_pos_byte < lim_byte)
              goto stop;
 
            while (this_len > 0)
@@ -1575,7 +1663,7 @@ simple_search (n, pat, len, len_byte, trt, pos, pos_byte, lim, lim_byte)
    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.
+   CHARSET_BASE is nonzero if there is such a non-ASCII character.
 
    If that criterion is not satisfied, do not call this function.  */
 
@@ -1610,12 +1698,8 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
   int translate_prev_byte2 = 0;
   int translate_prev_byte3 = 0;
 
-#ifdef C_ALLOCA
-  int BM_tab_space[0400];
-  BM_tab = &BM_tab_space[0];
-#else
   BM_tab = (int *) alloca (0400 * sizeof (int));
-#endif
+
   /* The general approach is that we are going to maintain that we know */
   /* the first (closest to the present position, in whatever direction */
   /* we're searching) character that could possibly be the last */
@@ -1720,7 +1804,7 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
                ch = -1;
            }
 
-         if (ch > 0400)
+         if (ch >= 0400)
            j = ((unsigned char) ch) | 0200;
          else
            j = *ptr;
@@ -1739,7 +1823,7 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
              while (1)
                {
                  TRANSLATE (ch, inverse_trt, ch);
-                 if (ch > 0400)
+                 if (ch >= 0400)
                    j = ((unsigned char) ch) | 0200;
                  else
                    j = (unsigned char) ch;
@@ -1887,7 +1971,7 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
              cursor += dirlen - i - direction; /* fix cursor */
              if (i + direction == 0)
                {
-                 int position;
+                 int position, start, end;
 
                  cursor -= direction;
 
@@ -1895,11 +1979,24 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
                                                       ? 1 - len_byte : 0);
                  set_search_regs (position, len_byte);
 
+                 if (NILP (Vinhibit_changing_match_data))
+                   {
+                     start = search_regs.start[0];
+                     end = search_regs.end[0];
+                   }
+                 else
+                   /* If Vinhibit_changing_match_data is non-nil,
+                      search_regs will not be changed.  So let's
+                      compute start and end here.  */
+                   {
+                     start = BYTE_TO_CHAR (position);
+                     end = BYTE_TO_CHAR (position + len_byte);
+                   }
+
                  if ((n -= direction) != 0)
                    cursor += dirlen; /* to resume search */
                  else
-                   return ((direction > 0)
-                           ? search_regs.end[0] : search_regs.start[0]);
+                   return direction > 0 ? end : start;
                }
              else
                cursor += stride_for_teases; /* <sigh> we lose -  */
@@ -1964,18 +2061,30 @@ boyer_moore (n, base_pat, len, len_byte, trt, inverse_trt,
              pos_byte += dirlen - i- direction;
              if (i + direction == 0)
                {
-                 int position;
+                 int position, start, end;
                  pos_byte -= direction;
 
                  position = pos_byte + ((direction > 0) ? 1 - len_byte : 0);
-
                  set_search_regs (position, len_byte);
 
+                 if (NILP (Vinhibit_changing_match_data))
+                   {
+                     start = search_regs.start[0];
+                     end = search_regs.end[0];
+                   }
+                 else
+                   /* If Vinhibit_changing_match_data is non-nil,
+                      search_regs will not be changed.  So let's
+                      compute start and end here.  */
+                   {
+                     start = BYTE_TO_CHAR (position);
+                     end = BYTE_TO_CHAR (position + len_byte);
+                   }
+
                  if ((n -= direction) != 0)
                    pos_byte += dirlen; /* to resume search */
                  else
-                   return ((direction > 0)
-                           ? search_regs.end[0] : search_regs.start[0]);
+                   return direction > 0 ? end : start;
                }
              else
                pos_byte += stride_for_teases;
@@ -1998,6 +2107,9 @@ set_search_regs (beg_byte, nbytes)
 {
   int i;
 
+  if (!NILP (Vinhibit_changing_match_data))
+    return;
+
   /* Make sure we have registers in which to store
      the match position.  */
   if (search_regs.num_regs == 0)
@@ -2056,7 +2168,7 @@ wordify (string)
   if (SYNTAX (prev_c) == Sword)
     word_count++;
   if (!word_count)
-    return empty_string;
+    return empty_unibyte_string;
 
   adjust = - punct_count + 5 * (word_count - 1) + 4;
   if (STRING_MULTIBYTE (string))
@@ -2126,8 +2238,8 @@ DEFUN ("search-forward", Fsearch_forward, Ssearch_forward, 1, 4, "MSearch: ",
        doc: /* Search forward from point for STRING.
 Set point to the end of the occurrence found, and return point.
 An optional second argument bounds the search; it is a buffer position.
-The match found must not extend after that position.  nil is equivalent
-  to (point-max).
+The match found must not extend after that position.  A value of nil is
+  equivalent to (point-max).
 Optional third argument, if t, means if fail just return nil (no error).
   If not nil and not t, move to limit of search and return nil.
 Optional fourth argument is repeat count--search for successive occurrences.
@@ -2853,11 +2965,15 @@ 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.  */
+/* We used to have an internal use variant of `reseat' described as:
+
+      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.
+
+   But it was ill-conceived: those supposedly-internal markers get exposed via
+   the undo-list, so freeing them here is unsafe.  */
 
 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.
@@ -2873,8 +2989,7 @@ If optional arg RESEAT is non-nil, make markers on LIST point nowhere.  */)
   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.  */
@@ -2943,10 +3058,7 @@ If optional arg RESEAT is non-nil, make markers on LIST point nowhere.  */)
 
            if (!NILP (reseat) && MARKERP (m))
              {
-               if (EQ (reseat, Qevaporate))
-                 free_marker (m);
-               else
-                 unchain_marker (XMARKER (m));
+               unchain_marker (XMARKER (m));
                XSETCAR (list, Qnil);
              }
 
@@ -2964,10 +3076,7 @@ If optional arg RESEAT is non-nil, make markers on LIST point nowhere.  */)
 
            if (!NILP (reseat) && MARKERP (m))
              {
-               if (EQ (reseat, Qevaporate))
-                 free_marker (m);
-               else
-                 unchain_marker (XMARKER (m));
+               unchain_marker (XMARKER (m));
                XSETCAR (list, Qnil);
              }
          }
@@ -3031,8 +3140,8 @@ 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);
+  /* It is NOT ALWAYS safe to free (evaporate) the markers immediately.  */
+  return Fset_match_data (list, Qt);
 }
 
 /* Called to unwind protect the match data.  */
@@ -3092,8 +3201,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];
@@ -3127,6 +3238,14 @@ or other such regexp constructs are not replaced with this.
 A value of nil (which is the normal value) means treat spaces literally.  */);
   Vsearch_spaces_regexp = Qnil;
 
+  DEFVAR_LISP ("inhibit-changing-match-data", &Vinhibit_changing_match_data,
+      doc: /* Internal use only.
+If non-nil, the primitive searching and matching functions
+such as `looking-at', `string-match', `re-search-forward', etc.,
+do not set the match data.  The proper way to use this variable
+is to bind it with `let' around a small expression.  */);
+  Vinhibit_changing_match_data = Qnil;
+
   defsubr (&Slooking_at);
   defsubr (&Sposix_looking_at);
   defsubr (&Sstring_match);