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,
#include "category.h"
#include "buffer.h"
#include "character.h"
+#include "charset.h"
#include "region-cache.h"
#include "commands.h"
#include "blockinput.h"
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 ();
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.
- MULTIBYTE is nonzero iff a target of match is a multibyte buffer or
- string.
The behavior also depends on Vsearch_spaces_regexp. */
static void
-compile_pattern_1 (cp, pattern, translate, regp, posix, multibyte)
+compile_pattern_1 (cp, pattern, translate, regp, posix)
struct regexp_cache *cp;
Lisp_Object pattern;
Lisp_Object translate;
struct re_registers *regp;
int posix;
- int multibyte;
{
char *val;
reg_syntax_t old;
cp->buf.translate = (! NILP (translate) ? translate : make_number (0));
cp->posix = posix;
cp->buf.multibyte = STRING_MULTIBYTE (pattern);
- cp->buf.target_multibyte = multibyte;
+ cp->buf.charset_unibyte = charset_unibyte;
cp->whitespace_regexp = Vsearch_spaces_regexp;
/* rms: I think BLOCK_INPUT is not needed here any more,
because regex.c defines malloc to call xmalloc.
&& !NILP (Fstring_equal (cp->regexp, pattern))
&& EQ (cp->buf.translate, (! NILP (translate) ? translate : make_number (0)))
&& cp->posix == posix
- && cp->buf.target_multibyte == multibyte
&& (EQ (cp->syntax_table, Qt)
|| EQ (cp->syntax_table, current_buffer->syntax_table))
- && !NILP (Fequal (cp->whitespace_regexp, Vsearch_spaces_regexp)))
+ && !NILP (Fequal (cp->whitespace_regexp, Vsearch_spaces_regexp))
+ && cp->buf.charset_unibyte == charset_unibyte)
break;
/* If we're at the end of the cache, compile into the nil cell
if (cp->next == 0)
{
compile_it:
- compile_pattern_1 (cp, pattern, translate, regp, posix, multibyte);
+ compile_pattern_1 (cp, pattern, translate, regp, posix);
break;
}
}
if (regp)
re_set_registers (&cp->buf, regp, regp->num_regs, regp->start, regp->end);
+ /* The compiled pattern can be used both for mulitbyte and unibyte
+ target. But, we have to tell which the pattern is used for. */
+ cp->buf.target_multibyte = multibyte;
+
return &cp->buf;
}
= 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,
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;
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)
{
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;
}
XCHAR_TABLE (current_buffer->case_canon_table)->extras[2]
= current_buffer->case_eqv_table;
- bufp = compile_pattern (regexp, &search_regs,
+ 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,
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));
}
} \
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)
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,
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)
}
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
{
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)
{
}
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
{
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.
- CHAR_BASE is nonzero iff there is such a non-ASCII character.
+ CHAR_BASE is nonzero if there is such a non-ASCII character.
If that criterion is not satisfied, do not call this function. */
int translate_prev_byte3 = 0;
int translate_prev_byte4 = 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 */
cursor += dirlen - i - direction; /* fix cursor */
if (i + direction == 0)
{
- int position;
+ int position, start, end;
cursor -= direction;
? 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 - */
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;
{
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)
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))
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.
if (!NILP (reseat) && MARKERP (m))
{
- if (EQ (reseat, Qevaporate))
- free_marker (m);
- else
- unchain_marker (XMARKER (m));
+ unchain_marker (XMARKER (m));
XSETCAR (list, Qnil);
}
if (!NILP (reseat) && MARKERP (m))
{
- if (EQ (reseat, Qevaporate))
- free_marker (m);
- else
- unchain_marker (XMARKER (m));
+ unchain_marker (XMARKER (m));
XSETCAR (list, Qnil);
}
}
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. */
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);