From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: "Herbert Euler" Newsgroups: gmane.emacs.devel Subject: Re: find-file-noselect needs save-match-data Date: Fri, 29 Jun 2007 23:07:38 +0800 Message-ID: References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; format=flowed X-Trace: sea.gmane.org 1183129680 14575 80.91.229.12 (29 Jun 2007 15:08:00 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Fri, 29 Jun 2007 15:08:00 +0000 (UTC) Cc: emacs-devel@gnu.org To: herberteuler@hotmail.com, dak@gnu.org, rms@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Fri Jun 29 17:07:57 2007 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1I4I4h-0006MY-BZ for ged-emacs-devel@m.gmane.org; Fri, 29 Jun 2007 17:07:56 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1I4I4g-0008Se-3N for ged-emacs-devel@m.gmane.org; Fri, 29 Jun 2007 11:07:54 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1I4I4c-0008Ry-38 for emacs-devel@gnu.org; Fri, 29 Jun 2007 11:07:50 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1I4I4b-0008RE-3F for emacs-devel@gnu.org; Fri, 29 Jun 2007 11:07:49 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1I4I4a-0008Qv-TY for emacs-devel@gnu.org; Fri, 29 Jun 2007 11:07:48 -0400 Original-Received: from bay0-omc3-s40.bay0.hotmail.com ([65.54.246.240]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1I4I4W-0007xr-D4; Fri, 29 Jun 2007 11:07:44 -0400 Original-Received: from hotmail.com ([65.55.154.104]) by bay0-omc3-s40.bay0.hotmail.com with Microsoft SMTPSVC(6.0.3790.2668); Fri, 29 Jun 2007 08:07:43 -0700 Original-Received: from mail pickup service by hotmail.com with Microsoft SMTPSVC; Fri, 29 Jun 2007 08:07:43 -0700 Original-Received: from 65.55.154.123 by by143fd.bay143.hotmail.msn.com with HTTP; Fri, 29 Jun 2007 15:07:38 GMT X-Originating-IP: [221.223.217.39] X-Originating-Email: [herberteuler@hotmail.com] X-Sender: herberteuler@hotmail.com In-Reply-To: X-OriginalArrivalTime: 29 Jun 2007 15:07:43.0225 (UTC) FILETIME=[3E3DDE90:01C7BA5F] X-detected-kernel: Windows 2000 SP4, XP SP1+ X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:74033 Archived-At: >>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; /* we lose - */ --- 1932,1938 ---- cursor += dirlen; /* to resume search */ else return ((direction > 0) ! ? regs->end[0] : regs->start[0]); } else cursor += stride_for_teases; /* 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 * subr.el (looking-at-p, string-match-p): New functions. 2007-06-30 Guanpeng Xu * 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/