/* String search routines for GNU Emacs.
Copyright (C) 1985, 1986, 1987, 1993, 1994, 1997, 1998, 1999, 2002, 2003,
- 2004, 2005 Free Software Foundation, Inc.
+ 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Emacs.
{
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. */
Lisp_Object Qinvalid_regexp;
+/* Error condition used for failing searches */
+Lisp_Object Qsearch_failed;
+
Lisp_Object Vsearch_spaces_regexp;
static void set_search_regs ();
static int simple_search ();
static int boyer_moore ();
static int search_buffer ();
+static void matcher_overflow () NO_RETURN;
static void
matcher_overflow ()
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));
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);
}
}
}
+/* 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.
&& 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;
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)
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,
(!NILP (current_buffer->case_fold_search)
pos_byte = string_char_to_byte (string, pos);
}
+ /* 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, &search_regs,
(!NILP (current_buffer->case_fold_search)
? current_buffer->case_canon_table : Qnil),
DEFUN ("string-match", Fstring_match, Sstring_match, 2, 3, 0,
doc: /* Return index of start of first match for REGEXP in STRING, or nil.
-Matching ignores case `case-fold-search' is non-nil.
+Matching ignores case if `case-fold-search' is non-nil.
If third arg START is non-nil, start search at that index in STRING.
For index of first char beyond the match, do (match-end 0).
`match-end' and `match-beginning' also give indices of substrings
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
if (np <= 0)
{
if (NILP (noerror))
- return signal_failure (string);
+ xsignal1 (Qsearch_failed, string);
+
if (!EQ (noerror, Qt))
{
if (lim < BEGV || lim > ZV)
int raw_pattern_size_byte;
unsigned char *patbuf;
int multibyte = !NILP (current_buffer->enable_multibyte_characters);
- unsigned char *base_pat = SDATA (string);
+ unsigned char *base_pat;
/* Set to positive if we find a non-ASCII char that need
translation. Otherwise set to zero later. */
int charset_base = -1;
if (ASCII_BYTE_P (*ptr) || ! multibyte)
ch = *ptr;
else if (charset_base
- && (pat_end - ptr) == 1 || CHAR_HEAD_P (ptr[1]))
+ && ((pat_end - ptr) == 1 || CHAR_HEAD_P (ptr[1])))
{
unsigned char *charstart = ptr - 1;
ch = -1;
}
- if (ch > 0400)
+ if (ch >= 0400)
j = ((unsigned char) ch) | 0200;
else
j = *ptr;
while (1)
{
TRANSLATE (ch, inverse_trt, ch);
- if (ch > 0400)
+ if (ch >= 0400)
j = ((unsigned char) ch) | 0200;
else
j = (unsigned char) ch;
else
some_multiletter_word = 1;
}
- else if (!NOCASEP (c))
+ else if (UPPERCASEP (c))
{
some_uppercase = 1;
if (SYNTAX (prevc) != Sword)
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. */
for (; in != end; in++)
{
- if (*in == '[' || *in == ']'
+ if (*in == '['
|| *in == '*' || *in == '.' || *in == '\\'
|| *in == '?' || *in == '+'
|| *in == '^' || *in == '$')
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];