comparison src/search.c @ 771:943eaba38521

[xemacs-hg @ 2002-03-13 08:51:24 by ben] The big ben-mule-21-5 check-in! Various files were added and deleted. See CHANGES-ben-mule. There are still some test suite failures. No crashes, though. Many of the failures have to do with problems in the test suite itself rather than in the actual code. I'll be addressing these in the next day or so -- none of the test suite failures are at all critical. Meanwhile I'll be trying to address the biggest issues -- i.e. build or run failures, which will almost certainly happen on various platforms. All comments should be sent to ben@xemacs.org -- use a Cc: if necessary when sending to mailing lists. There will be pre- and post- tags, something like pre-ben-mule-21-5-merge-in, and post-ben-mule-21-5-merge-in.
author ben
date Wed, 13 Mar 2002 08:54:06 +0000
parents a307f9a2021d
children e38acbeb1cae
comparison
equal deleted inserted replaced
770:336a418893b5 771:943eaba38521
1 /* String search routines for XEmacs. 1 /* String search routines for XEmacs.
2 Copyright (C) 1985, 1986, 1987, 1992-1995 Free Software Foundation, Inc. 2 Copyright (C) 1985, 1986, 1987, 1992-1995 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc. 3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 2001 Ben Wing.
4 5
5 This file is part of XEmacs. 6 This file is part of XEmacs.
6 7
7 XEmacs is free software; you can redistribute it and/or modify it 8 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the 9 under the terms of the GNU General Public License as published by the
121 static Charbpos search_buffer (struct buffer *buf, Lisp_Object str, 122 static Charbpos search_buffer (struct buffer *buf, Lisp_Object str,
122 Charbpos charbpos, Charbpos buflim, EMACS_INT n, int RE, 123 Charbpos charbpos, Charbpos buflim, EMACS_INT n, int RE,
123 Lisp_Object trt, Lisp_Object inverse_trt, 124 Lisp_Object trt, Lisp_Object inverse_trt,
124 int posix); 125 int posix);
125 126
127 struct regex_reentrancy
128 {
129 struct syntax_cache cache;
130 struct buffer *regex_emacs_buffer;
131 Lisp_Object regex_match_object;
132 };
133
134 typedef struct
135 {
136 Dynarr_declare (struct regex_reentrancy);
137 } regex_reentrancy_dynarr;
138
139 static regex_reentrancy_dynarr *the_regex_reentrancy_dynarr;
140
141 static Lisp_Object
142 restore_regex_reentrancy (Lisp_Object dummy)
143 {
144 struct regex_reentrancy rr = Dynarr_pop (the_regex_reentrancy_dynarr);
145 syntax_cache = rr.cache;
146 regex_emacs_buffer = rr.regex_emacs_buffer;
147 regex_match_object = rr.regex_match_object;
148 return Qnil;
149 }
150
151 static int
152 begin_regex_reentrancy (void)
153 {
154 /* #### there is still a potential problem with the regex cache --
155 the compiled regex could be overwritten. we'd need 20-fold
156 reentrancy, though. */
157 struct regex_reentrancy rr;
158 rr.cache = syntax_cache;
159 rr.regex_emacs_buffer = regex_emacs_buffer;
160 rr.regex_match_object = regex_match_object;
161 if (!the_regex_reentrancy_dynarr)
162 the_regex_reentrancy_dynarr = Dynarr_new2 (regex_reentrancy_dynarr,
163 struct regex_reentrancy);
164 Dynarr_add (the_regex_reentrancy_dynarr, rr);
165 return record_unwind_protect (restore_regex_reentrancy, Qnil);
166 }
167
126 static void 168 static void
127 matcher_overflow (void) 169 matcher_overflow (void)
128 { 170 {
129 stack_overflow ("Stack overflow in regexp matcher", Qunbound); 171 stack_overflow ("Stack overflow in regexp matcher", Qunbound);
130 } 172 }
270 for (i = 0; i < num_regs; i++) 312 for (i = 0; i < num_regs; i++)
271 { 313 {
272 if (search_regs.start[i] > 0) 314 if (search_regs.start[i] > 0)
273 { 315 {
274 search_regs.start[i] = 316 search_regs.start[i] =
275 bytecount_to_charcount (XSTRING_DATA (string), 317 XSTRING_INDEX_BYTE_TO_CHAR (string, search_regs.start[i]);
276 search_regs.start[i]);
277 } 318 }
278 if (search_regs.end[i] > 0) 319 if (search_regs.end[i] > 0)
279 { 320 {
280 search_regs.end[i] = 321 search_regs.end[i] =
281 bytecount_to_charcount (XSTRING_DATA (string), 322 XSTRING_INDEX_BYTE_TO_CHAR (string, search_regs.end[i]);
282 search_regs.end[i]);
283 } 323 }
284 } 324 }
285 } 325 }
286 326
287 327
292 Lisp_Object val; 332 Lisp_Object val;
293 Bytebpos p1, p2; 333 Bytebpos p1, p2;
294 Bytecount s1, s2; 334 Bytecount s1, s2;
295 REGISTER int i; 335 REGISTER int i;
296 struct re_pattern_buffer *bufp; 336 struct re_pattern_buffer *bufp;
337 int count = begin_regex_reentrancy ();
297 338
298 if (running_asynch_code) 339 if (running_asynch_code)
299 save_search_regs (); 340 save_search_regs ();
300 341
301 CHECK_STRING (string); 342 CHECK_STRING (string);
324 if (i == -2) 365 if (i == -2)
325 matcher_overflow (); 366 matcher_overflow ();
326 367
327 val = (0 <= i ? Qt : Qnil); 368 val = (0 <= i ? Qt : Qnil);
328 if (NILP (val)) 369 if (NILP (val))
329 return Qnil; 370 return unbind_to (count);
330 { 371 {
331 int num_regs = search_regs.num_regs; 372 int num_regs = search_regs.num_regs;
332 for (i = 0; i < num_regs; i++) 373 for (i = 0; i < num_regs; i++)
333 if (search_regs.start[i] >= 0) 374 if (search_regs.start[i] >= 0)
334 { 375 {
336 search_regs.end[i] += BI_BUF_BEGV (buf); 377 search_regs.end[i] += BI_BUF_BEGV (buf);
337 } 378 }
338 } 379 }
339 XSETBUFFER (last_thing_searched, buf); 380 XSETBUFFER (last_thing_searched, buf);
340 fixup_search_regs_for_buffer (buf); 381 fixup_search_regs_for_buffer (buf);
341 return val; 382 return unbind_to_1 (count, val);
342 } 383 }
343 384
344 DEFUN ("looking-at", Flooking_at, 1, 2, 0, /* 385 DEFUN ("looking-at", Flooking_at, 1, 2, 0, /*
345 Return t if text after point matches regular expression REGEXP. 386 Return t if text after point matches regular expression REGEXP.
346 This function modifies the match data that `match-beginning', 387 This function modifies the match data that `match-beginning',
374 { 415 {
375 /* This function has been Mule-ized, except for the trt table handling. */ 416 /* This function has been Mule-ized, except for the trt table handling. */
376 Bytecount val; 417 Bytecount val;
377 Charcount s; 418 Charcount s;
378 struct re_pattern_buffer *bufp; 419 struct re_pattern_buffer *bufp;
420 int count = begin_regex_reentrancy ();
379 421
380 if (running_asynch_code) 422 if (running_asynch_code)
381 save_search_regs (); 423 save_search_regs ();
382 424
383 CHECK_STRING (regexp); 425 CHECK_STRING (regexp);
402 (!NILP (buf->case_fold_search) 444 (!NILP (buf->case_fold_search)
403 ? XCASE_TABLE_DOWNCASE (buf->case_table) : Qnil), 445 ? XCASE_TABLE_DOWNCASE (buf->case_table) : Qnil),
404 0, ERROR_ME); 446 0, ERROR_ME);
405 QUIT; 447 QUIT;
406 { 448 {
407 Bytecount bis = charcount_to_bytecount (XSTRING_DATA (string), s); 449 Bytecount bis = XSTRING_INDEX_CHAR_TO_BYTE (string, s);
408 regex_match_object = string; 450 regex_match_object = string;
409 regex_emacs_buffer = buf; 451 regex_emacs_buffer = buf;
410 val = re_search (bufp, (char *) XSTRING_DATA (string), 452 val = re_search (bufp, (char *) XSTRING_DATA (string),
411 XSTRING_LENGTH (string), bis, 453 XSTRING_LENGTH (string), bis,
412 XSTRING_LENGTH (string) - bis, 454 XSTRING_LENGTH (string) - bis,
413 &search_regs); 455 &search_regs);
414 } 456 }
415 if (val == -2) 457 if (val == -2)
416 matcher_overflow (); 458 matcher_overflow ();
417 if (val < 0) return Qnil; 459 if (val < 0) return unbind_to (count);
418 last_thing_searched = Qt; 460 last_thing_searched = Qt;
419 fixup_search_regs_for_string (string); 461 fixup_search_regs_for_string (string);
420 return make_int (bytecount_to_charcount (XSTRING_DATA (string), val)); 462 return
463 unbind_to_1 (count,
464 make_int (XSTRING_INDEX_BYTE_TO_CHAR (string, val)));
421 } 465 }
422 466
423 DEFUN ("string-match", Fstring_match, 2, 4, 0, /* 467 DEFUN ("string-match", Fstring_match, 2, 4, 0, /*
424 Return index of start of first match for REGEXP in STRING, or nil. 468 Return index of start of first match for REGEXP in STRING, or nil.
425 If third arg START is non-nil, start search at that index in STRING. 469 If third arg START is non-nil, start search at that index in STRING.
465 { 509 {
466 /* This function has been Mule-ized, except for the trt table handling. */ 510 /* This function has been Mule-ized, except for the trt table handling. */
467 Bytecount val; 511 Bytecount val;
468 Intbyte *newnonreloc = (Intbyte *) nonreloc; 512 Intbyte *newnonreloc = (Intbyte *) nonreloc;
469 struct re_pattern_buffer *bufp; 513 struct re_pattern_buffer *bufp;
514 int count;
470 515
471 bufp = compile_pattern (regexp, 0, 516 bufp = compile_pattern (regexp, 0,
472 (case_fold_search 517 (case_fold_search
473 ? XCASE_TABLE_DOWNCASE (current_buffer->case_table) 518 ? XCASE_TABLE_DOWNCASE (Vstandard_case_table)
474 : Qnil), 519 : Qnil),
475 0, errb); 520 0, errb);
476 if (!bufp) 521 if (!bufp)
477 return -1; /* will only do this when errb != ERROR_ME */ 522 return -1; /* will only do this when errb != ERROR_ME */
478 if (!no_quit) 523 if (!no_quit)
480 else 525 else
481 no_quit_in_re_search = 1; 526 no_quit_in_re_search = 1;
482 527
483 fixup_internal_substring (nonreloc, reloc, offset, &length); 528 fixup_internal_substring (nonreloc, reloc, offset, &length);
484 529
530 /* Don't need to protect against GC inside of re_search() due to QUIT;
531 QUIT is GC-inhibited. */
485 if (!NILP (reloc)) 532 if (!NILP (reloc))
486 { 533 newnonreloc = XSTRING_DATA (reloc);
487 if (no_quit) 534
488 newnonreloc = XSTRING_DATA (reloc); 535 count = begin_regex_reentrancy ();
489 else
490 {
491 /* QUIT could relocate RELOC. Therefore we must alloca()
492 and copy. No way around this except some serious
493 rewriting of re_search(). */
494 newnonreloc = (Intbyte *) alloca (length);
495 memcpy (newnonreloc, XSTRING_DATA (reloc), length);
496 }
497 }
498
499 /* #### evil current-buffer dependency */ 536 /* #### evil current-buffer dependency */
500 regex_match_object = reloc; 537 regex_match_object = reloc;
501 regex_emacs_buffer = current_buffer; 538 regex_emacs_buffer = current_buffer;
502 val = re_search (bufp, (char *) newnonreloc + offset, length, 0, 539 val = re_search (bufp, (char *) newnonreloc + offset, length, 0,
503 length, 0); 540 length, 0);
504 541
505 no_quit_in_re_search = 0; 542 no_quit_in_re_search = 0;
543 unbind_to (count);
506 return val; 544 return val;
507 } 545 }
508 546
509 Bytecount 547 Bytecount
510 fast_lisp_string_match (Lisp_Object regex, Lisp_Object string) 548 fast_lisp_string_match (Lisp_Object regex, Lisp_Object string)
1139 Intbyte *base_pat = XSTRING_DATA (string); 1177 Intbyte *base_pat = XSTRING_DATA (string);
1140 REGISTER EMACS_INT i, j; 1178 REGISTER EMACS_INT i, j;
1141 Bytebpos p1, p2; 1179 Bytebpos p1, p2;
1142 Bytecount s1, s2; 1180 Bytecount s1, s2;
1143 Bytebpos pos, lim; 1181 Bytebpos pos, lim;
1182 int count;
1144 1183
1145 if (running_asynch_code) 1184 if (running_asynch_code)
1146 save_search_regs (); 1185 save_search_regs ();
1147 1186
1148 /* Null string is found at starting position. */ 1187 /* Null string is found at starting position. */
1159 pos = charbpos_to_bytebpos (buf, charbpos); 1198 pos = charbpos_to_bytebpos (buf, charbpos);
1160 lim = charbpos_to_bytebpos (buf, buflim); 1199 lim = charbpos_to_bytebpos (buf, buflim);
1161 if (RE && !trivial_regexp_p (string)) 1200 if (RE && !trivial_regexp_p (string))
1162 { 1201 {
1163 struct re_pattern_buffer *bufp; 1202 struct re_pattern_buffer *bufp;
1203 count = begin_regex_reentrancy ();
1164 1204
1165 bufp = compile_pattern (string, &search_regs, trt, posix, 1205 bufp = compile_pattern (string, &search_regs, trt, posix,
1166 ERROR_ME); 1206 ERROR_ME);
1167 1207
1168 /* Get pointers and sizes of the two strings 1208 /* Get pointers and sizes of the two strings
1206 /* And charbpos too. */ 1246 /* And charbpos too. */
1207 charbpos = search_regs.start[0]; 1247 charbpos = search_regs.start[0];
1208 } 1248 }
1209 else 1249 else
1210 { 1250 {
1251 unbind_to (count);
1211 return n; 1252 return n;
1212 } 1253 }
1213 n++; 1254 n++;
1214 } 1255 }
1215 while (n > 0) 1256 while (n > 0)
1243 /* And charbpos too. */ 1284 /* And charbpos too. */
1244 charbpos = search_regs.end[0]; 1285 charbpos = search_regs.end[0];
1245 } 1286 }
1246 else 1287 else
1247 { 1288 {
1289 unbind_to (count);
1248 return 0 - n; 1290 return 0 - n;
1249 } 1291 }
1250 n--; 1292 n--;
1251 } 1293 }
1294 unbind_to (count);
1252 return charbpos; 1295 return charbpos;
1253 } 1296 }
1254 else /* non-RE case */ 1297 else /* non-RE case */
1255 { 1298 {
1256 int charset_base = -1; 1299 int charset_base = -1;
1631 j = (unsigned char) ch; 1674 j = (unsigned char) ch;
1632 1675
1633 /* For all the characters that map into CH, 1676 /* For all the characters that map into CH,
1634 set up simple_translate to map the last byte 1677 set up simple_translate to map the last byte
1635 into STARTING_J. */ 1678 into STARTING_J. */
1636 simple_translate[j] = starting_j; 1679 simple_translate[j] = (Intbyte) starting_j;
1637 if (ch == starting_ch) 1680 if (ch == starting_ch)
1638 break; 1681 break;
1639 BM_tab[j] = dirlen - i; 1682 BM_tab[j] = dirlen - i;
1640 } 1683 }
1641 } 1684 }
2556 set_string_char (XSTRING (replacement), strpos, newchar); 2599 set_string_char (XSTRING (replacement), strpos, newchar);
2557 } 2600 }
2558 } 2601 }
2559 2602
2560 /* frees the Dynarrs if necessary. */ 2603 /* frees the Dynarrs if necessary. */
2561 unbind_to (speccount, Qnil); 2604 unbind_to (speccount);
2562 return concat3 (before, replacement, after); 2605 return concat3 (before, replacement, after);
2563 } 2606 }
2564 2607
2565 mc_count = begin_multiple_change (buf, search_regs.start[sub], 2608 mc_count = begin_multiple_change (buf, search_regs.start[sub],
2566 search_regs.end[sub]); 2609 search_regs.end[sub]);
2689 buffer_replace_char (buf, pos, newchar, 0, 0); 2732 buffer_replace_char (buf, pos, newchar, 0, 0);
2690 } 2733 }
2691 } 2734 }
2692 2735
2693 /* frees the Dynarrs if necessary. */ 2736 /* frees the Dynarrs if necessary. */
2694 unbind_to (speccount, Qnil); 2737 unbind_to (speccount);
2695 end_multiple_change (buf, mc_count); 2738 end_multiple_change (buf, mc_count);
2696 2739
2697 return Qnil; 2740 return Qnil;
2698 } 2741 }
2699 2742