[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: find-file-noselect needs save-match-data
From: |
Herbert Euler |
Subject: |
Re: find-file-noselect needs save-match-data |
Date: |
Fri, 29 Jun 2007 23:07:38 +0800 |
Just as a note aside: regular expressions like \(.\)\1 are possible,
so the match data _has_ to be stored somewhere, presumably. This
might impact the attractiveness of the "C variable" implementation.
Fortunately we can solve this with providing another re_registers
variable. I've almost finished it, but I got segmentation fault after
adding a DEFVAR_LISP in syms_of_search. The segfault is triggered
by GC. Any hint on how to solve it? Thanks.
The crash goes away after I re-checked out the source from CVS. Below
is the patches and the change-log entries I did for the two functions.
All patches are based on files in unicode 2 branch. Please check
them. If they are OK, I'll write document for them. Thanks.
Regards,
Guanpeng Xu
Index: lisp/subr.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/subr.el,v
retrieving revision 1.360.2.68
diff -c -F '^[_a-zA-Z0-9$]+ *(' -r1.360.2.68 subr.el
*** lisp/subr.el 16 Jun 2007 22:31:38 -0000 1.360.2.68
--- lisp/subr.el 29 Jun 2007 14:26:21 -0000
*************** t (mix it with ordinary output), or a fi
*** 2667,2672 ****
--- 2667,2684 ----
(looking-at (concat "\\(?:" regexp "\\)\\'")))))
(not (null pos))))
+ (defsubst looking-at-p (regexp)
+ "\
+ Same as `looking-at' except this function does not change the match data."
+ (let ((inhibit-changing-match-data t))
+ (looking-at regexp)))
+
+ (defsubst string-match-p (regexp string &optional start)
+ "\
+ Same as `string-match' except this function does not change the match
data."
+ (let ((inhibit-changing-match-data t))
+ (string-match regexp string start)))
+
(defun subregexp-context-p (regexp pos &optional start)
"Return non-nil if POS is in a normal subregexp context in REGEXP.
A subregexp context is one where a sub-regexp can appear.
Index: src/search.c
===================================================================
RCS file: /sources/emacs/emacs/src/search.c,v
retrieving revision 1.174.2.38
diff -c -F '^[_a-zA-Z0-9$]+ *(' -r1.174.2.38 search.c
*** src/search.c 11 Jun 2007 00:57:33 -0000 1.174.2.38
--- src/search.c 29 Jun 2007 14:26:27 -0000
***************
*** 60,73 ****
struct regexp_cache *searchbuf_head;
! /* Every call to re_match, etc., must pass &search_regs as the regs
! argument unless you can show it is unnecessary (i.e., if re_match
! is certainly going to be called again before region-around-match
! can be called).
Since the registers are now dynamically allocated, we need to make
sure not to refer to the Nth register before checking that it has
! been allocated by checking search_regs.num_regs.
The regex code keeps track of whether it has allocated the search
buffer using bits in the re_pattern_buffer. This means that whenever
--- 60,74 ----
struct regexp_cache *searchbuf_head;
! /* Every call to re_match, etc., must pass &search_regs_nochange or
! &search_regs as the regs argument unless you can show it is
! unnecessary (i.e., if re_match is certainly going to be called
! again before region-around-match can be called).
Since the registers are now dynamically allocated, we need to make
sure not to refer to the Nth register before checking that it has
! been allocated by checking search_regs_nochange.num_regs, or
! search_regs.num_regs.
The regex code keeps track of whether it has allocated the search
buffer using bits in the re_pattern_buffer. This means that whenever
***************
*** 76,82 ****
time you call a searching or matching function. Therefore, we need
to call re_set_registers after compiling a new pattern or after
setting the match registers, so that the regex functions will be
! able to free or re-allocate it properly. */
static struct re_registers search_regs;
/* The buffer in which the last search was performed, or
--- 77,90 ----
time you call a searching or matching function. Therefore, we need
to call re_set_registers after compiling a new pattern or after
setting the match registers, so that the regex functions will be
! able to free or re-allocate it properly.
!
! We now have two families of searching or matching functions.
! Functions in one family won't change the match data at Lisp level,
! while functions in the other family will change it. The variable
! search_regs_nochange is used for the former family, and the
! variable search_regs is used for the latter one. */
! static struct re_registers search_regs_nochange;
static struct re_registers search_regs;
/* The buffer in which the last search was performed, or
***************
*** 93,98 ****
--- 101,115 ----
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;
+
+ #define SEARCH_REGS_PTR (NILP (Vinhibit_changing_match_data) \
+ ? &search_regs \
+ : &search_regs_nochange)
+
static void set_search_regs ();
static void save_search_regs ();
static int simple_search ();
*************** looking_at_1 (string, posix)
*** 280,285 ****
--- 297,303 ----
int s1, s2;
register int i;
struct re_pattern_buffer *bufp;
+ struct re_registers *regs = SEARCH_REGS_PTR;
if (running_asynch_code)
save_search_regs ();
*************** looking_at_1 (string, posix)
*** 289,295 ****
= current_buffer->case_eqv_table;
CHECK_STRING (string);
! bufp = compile_pattern (string, &search_regs,
(!NILP (current_buffer->case_fold_search)
? current_buffer->case_canon_table : Qnil),
posix,
--- 307,313 ----
= current_buffer->case_eqv_table;
CHECK_STRING (string);
! bufp = compile_pattern (string, regs,
(!NILP (current_buffer->case_fold_search)
? current_buffer->case_canon_table : Qnil),
posix,
*************** looking_at_1 (string, posix)
*** 320,326 ****
re_match_object = Qnil;
i = re_match_2 (bufp, (char *) p1, s1, (char *) p2, s2,
! PT_BYTE - BEGV_BYTE, &search_regs,
ZV_BYTE - BEGV_BYTE);
immediate_quit = 0;
--- 338,344 ----
re_match_object = Qnil;
i = re_match_2 (bufp, (char *) p1, s1, (char *) p2, s2,
! PT_BYTE - BEGV_BYTE, regs,
ZV_BYTE - BEGV_BYTE);
immediate_quit = 0;
*************** looking_at_1 (string, posix)
*** 329,341 ****
val = (0 <= i ? Qt : Qnil);
if (i >= 0)
! 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);
return val;
--- 347,357 ----
val = (0 <= i ? Qt : Qnil);
if (i >= 0)
! for (i = 0; i < regs->num_regs; i++)
! if (regs->start[i] >= 0)
{
! regs->start[i] = BYTE_TO_CHAR (regs->start[i] + BEGV_BYTE);
! regs->end[i] = BYTE_TO_CHAR (regs->end[i] + BEGV_BYTE);
}
XSETBUFFER (last_thing_searched, current_buffer);
return val;
*************** string_match_1 (regexp, string, start, p
*** 373,378 ****
--- 389,395 ----
struct re_pattern_buffer *bufp;
int pos, pos_byte;
int i;
+ struct re_registers *regs = SEARCH_REGS_PTR;
if (running_asynch_code)
save_search_regs ();
*************** string_match_1 (regexp, string, start, p
*** 399,405 ****
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),
posix,
--- 416,422 ----
XCHAR_TABLE (current_buffer->case_canon_table)->extras[2]
= current_buffer->case_eqv_table;
! bufp = compile_pattern (regexp, regs,
(!NILP (current_buffer->case_fold_search)
? current_buffer->case_canon_table : Qnil),
posix,
*************** string_match_1 (regexp, string, start, p
*** 410,429 ****
val = re_search (bufp, (char *) SDATA (string),
SBYTES (string), pos_byte,
SBYTES (string) - pos_byte,
! &search_regs);
immediate_quit = 0;
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]);
}
return make_number (string_byte_to_char (string, val));
--- 427,444 ----
val = re_search (bufp, (char *) SDATA (string),
SBYTES (string), pos_byte,
SBYTES (string) - pos_byte,
! regs);
immediate_quit = 0;
last_thing_searched = Qt;
if (val == -2)
matcher_overflow ();
if (val < 0) return Qnil;
! for (i = 0; i < regs->num_regs; i++)
! if (regs->start[i] >= 0)
{
! regs->start[i] = string_byte_to_char (string, regs->start[i]);
! regs->end[i] = string_byte_to_char (string, regs->end[i]);
}
return make_number (string_byte_to_char (string, val));
*************** search_buffer (string, pos, pos_byte, li
*** 1059,1064 ****
--- 1074,1080 ----
int len = SCHARS (string);
int len_byte = SBYTES (string);
register int i;
+ struct re_registers *regs = SEARCH_REGS_PTR;
if (running_asynch_code)
save_search_regs ();
*************** search_buffer (string, pos, pos_byte, li
*** 1077,1083 ****
int s1, s2;
struct re_pattern_buffer *bufp;
! bufp = compile_pattern (string, &search_regs, trt, posix,
!NILP
(current_buffer->enable_multibyte_characters));
immediate_quit = 1; /* Quit immediately if user types ^G,
--- 1093,1099 ----
int s1, s2;
struct re_pattern_buffer *bufp;
! bufp = compile_pattern (string, regs, trt, posix,
!NILP
(current_buffer->enable_multibyte_characters));
immediate_quit = 1; /* Quit immediately if user types ^G,
*************** search_buffer (string, pos, pos_byte, li
*** 1110,1116 ****
int val;
val = re_search_2 (bufp, (char *) p1, s1, (char *) p2, s2,
pos_byte - BEGV_BYTE, lim_byte - pos_byte,
! &search_regs,
/* Don't allow match past current point */
pos_byte - BEGV_BYTE);
if (val == -2)
--- 1126,1132 ----
int val;
val = re_search_2 (bufp, (char *) p1, s1, (char *) p2, s2,
pos_byte - BEGV_BYTE, lim_byte - pos_byte,
! regs,
/* Don't allow match past current point */
pos_byte - BEGV_BYTE);
if (val == -2)
*************** search_buffer (string, pos, pos_byte, li
*** 1119,1136 ****
}
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];
}
else
{
--- 1135,1150 ----
}
if (val >= 0)
{
! pos_byte = regs->start[0] + BEGV_BYTE;
! for (i = 0; i < regs->num_regs; i++)
! if (regs->start[i] >= 0)
{
! regs->start[i] = BYTE_TO_CHAR (regs->start[i] + BEGV_BYTE);
! regs->end[i] = BYTE_TO_CHAR (regs->end[i] + BEGV_BYTE);
}
XSETBUFFER (last_thing_searched, current_buffer);
/* Set pos to the new position. */
! pos = regs->start[0];
}
else
{
*************** search_buffer (string, pos, pos_byte, li
*** 1144,1150 ****
int val;
val = re_search_2 (bufp, (char *) p1, s1, (char *) p2, s2,
pos_byte - BEGV_BYTE, lim_byte - pos_byte,
! &search_regs,
lim_byte - BEGV_BYTE);
if (val == -2)
{
--- 1158,1164 ----
int val;
val = re_search_2 (bufp, (char *) p1, s1, (char *) p2, s2,
pos_byte - BEGV_BYTE, lim_byte - pos_byte,
! regs,
lim_byte - BEGV_BYTE);
if (val == -2)
{
*************** search_buffer (string, pos, pos_byte, li
*** 1152,1168 ****
}
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];
}
else
{
--- 1166,1180 ----
}
if (val >= 0)
{
! pos_byte = regs->end[0] + BEGV_BYTE;
! for (i = 0; i < regs->num_regs; i++)
! if (regs->start[i] >= 0)
{
! regs->start[i] = BYTE_TO_CHAR (regs->start[i] + BEGV_BYTE);
! regs->end[i] = BYTE_TO_CHAR (regs->end[i] + BEGV_BYTE);
}
XSETBUFFER (last_thing_searched, current_buffer);
! pos = regs->end[0];
}
else
{
*************** boyer_moore (n, base_pat, len, len_byte,
*** 1616,1621 ****
--- 1628,1634 ----
register int i, j;
unsigned char *pat, *pat_end;
int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
+ struct re_registers *regs = SEARCH_REGS_PTR;
unsigned char simple_translate[0400];
/* These are set to the preceding bytes of a byte to be translated
*************** boyer_moore (n, base_pat, len, len_byte,
*** 1919,1925 ****
cursor += dirlen; /* to resume search */
else
return ((direction > 0)
! ? search_regs.end[0] : search_regs.start[0]);
}
else
cursor += stride_for_teases; /* <sigh> we lose - */
--- 1932,1938 ----
cursor += dirlen; /* to resume search */
else
return ((direction > 0)
! ? regs->end[0] : regs->start[0]);
}
else
cursor += stride_for_teases; /* <sigh> we lose - */
*************** boyer_moore (n, base_pat, len, len_byte,
*** 1995,2001 ****
pos_byte += dirlen; /* to resume search */
else
return ((direction > 0)
! ? search_regs.end[0] : search_regs.start[0]);
}
else
pos_byte += stride_for_teases;
--- 2008,2014 ----
pos_byte += dirlen; /* to resume search */
else
return ((direction > 0)
! ? regs->end[0] : regs->start[0]);
}
else
pos_byte += stride_for_teases;
*************** set_search_regs (beg_byte, nbytes)
*** 2017,2041 ****
int beg_byte, nbytes;
{
int i;
/* Make sure we have registers in which to store
the match position. */
! if (search_regs.num_regs == 0)
{
! search_regs.start = (regoff_t *) xmalloc (2 * sizeof (regoff_t));
! search_regs.end = (regoff_t *) xmalloc (2 * sizeof (regoff_t));
! search_regs.num_regs = 2;
}
/* Clear out the other registers. */
! for (i = 1; i < search_regs.num_regs; i++)
{
! search_regs.start[i] = -1;
! search_regs.end[i] = -1;
}
! search_regs.start[0] = BYTE_TO_CHAR (beg_byte);
! search_regs.end[0] = BYTE_TO_CHAR (beg_byte + nbytes);
XSETBUFFER (last_thing_searched, current_buffer);
}
--- 2030,2055 ----
int beg_byte, nbytes;
{
int i;
+ struct re_registers *regs = SEARCH_REGS_PTR;
/* Make sure we have registers in which to store
the match position. */
! if (regs->num_regs == 0)
{
! regs->start = (regoff_t *) xmalloc (2 * sizeof (regoff_t));
! regs->end = (regoff_t *) xmalloc (2 * sizeof (regoff_t));
! regs->num_regs = 2;
}
/* Clear out the other registers. */
! for (i = 1; i < regs->num_regs; i++)
{
! regs->start[i] = -1;
! regs->end[i] = -1;
}
! regs->start[0] = BYTE_TO_CHAR (beg_byte);
! regs->end[0] = BYTE_TO_CHAR (beg_byte + nbytes);
XSETBUFFER (last_thing_searched, current_buffer);
}
*************** DEFUN ("set-match-data", Fset_match_data
*** 2998,3004 ****
}
/* 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;
static struct re_registers saved_search_regs;
static Lisp_Object saved_last_thing_searched;
--- 3012,3022 ----
}
/* If non-zero the match data have been saved in saved_search_regs
! during the execution of a sentinel or filter. The value of
! saved_search_regs is copied from and recovered to search_regs
! rather than search_regs_nochange, since the value of
! search_regs_nochange is intended to not be used and to be
! discarded. */
static int search_regs_saved;
static struct re_registers saved_search_regs;
static Lisp_Object saved_last_thing_searched;
*************** syms_of_search ()
*** 3145,3150 ****
--- 3163,3175 ----
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 match data will not be changed during call to searching or
+ matching functions, such as `looking-at', `string-match',
`re-search-forward'
+ etc. */);
+ Vinhibit_changing_match_data = Qnil;
+
defsubr (&Slooking_at);
defsubr (&Sposix_looking_at);
defsubr (&Sstring_match);
2007-06-30 Guanpeng Xu <address@hidden>
* subr.el (looking-at-p, string-match-p): New functions.
2007-06-30 Guanpeng Xu <address@hidden>
* search.c (search_regs_nochange, Vinhibit_changing_match_data):
New variables.
(SEARCH_REGS_PTR): New macro.
(looking_at_1): Don't chang match data at Lisp level if
Vinhibit_changing_match_data is not nil.
(string_match_1, search_buffer, boyer_moore, set_search_regs):
Likewise.
(syms_of_search): Add entry of Vinhibit_changing_match_data and
set it to nil.
_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today it's FREE!
http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/
- Re: find-file-noselect needs save-match-data, (continued)
- Re: find-file-noselect needs save-match-data, Richard Stallman, 2007/06/17
- Re: find-file-noselect needs save-match-data, Stefan Monnier, 2007/06/17
- Re: find-file-noselect needs save-match-data, Richard Stallman, 2007/06/18
- Re: find-file-noselect needs save-match-data, Herbert Euler, 2007/06/20
- Re: find-file-noselect needs save-match-data, Juri Linkov, 2007/06/20
- Re: find-file-noselect needs save-match-data, Herbert Euler, 2007/06/20
- Re: find-file-noselect needs save-match-data, Richard Stallman, 2007/06/20
- Re: find-file-noselect needs save-match-data, Herbert Euler, 2007/06/20
- Re: find-file-noselect needs save-match-data, David Kastrup, 2007/06/21
- Re: find-file-noselect needs save-match-data, Herbert Euler, 2007/06/28
- Re: find-file-noselect needs save-match-data,
Herbert Euler <=
- Re: find-file-noselect needs save-match-data, Richard Stallman, 2007/06/21
- Re: find-file-noselect needs save-match-data, Richard Stallman, 2007/06/20
- Re: find-file-noselect needs save-match-data, Richard Stallman, 2007/06/13
Re: find-file-noselect needs save-match-data, Richard Stallman, 2007/06/05
Re: find-file-noselect needs save-match-data, Stefan Monnier, 2007/06/05
Re: find-file-noselect needs save-match-data, Stefan Monnier, 2007/06/14
Re: find-file-noselect needs save-match-data, Herbert Euler, 2007/06/05