Mercurial > hg > xemacs-beta
diff src/regex.c @ 1333:1b0339b048ce
[xemacs-hg @ 2003-03-02 09:38:37 by ben]
To: xemacs-patches@xemacs.org
PROBLEMS: Include nt/PROBLEMS and update. Add note about incremental
linking badness.
cmdloop.el, custom.el, dumped-lisp.el, files.el, keydefs.el, keymap.el, lisp-mode.el, make-docfile.el, replace.el, simple.el, subr.el, view-less.el, wid-edit.el: Lots of syncing with FSF 21.2.
Use if-fboundp in wid-edit.el.
New file newcomment.el from FSF.
internals/internals.texi: Fix typo.
(Build-Time Dependencies): New node.
PROBLEMS: Delete.
config.inc.samp, xemacs.mak: Eliminate HAVE_VC6, use SUPPORT_EDIT_AND_CONTINUE in its place.
No incremental linking unless SUPPORT_EDIT_AND_CONTINUE, since it
can cause nasty crashes in pdump. Put warnings about this in
config.inc.samp. Report the full compile flags used for src
and lib-src in the Installation output.
alloc.c, lisp.h, ralloc.c, regex.c: Use ALLOCA() in regex.c to avoid excessive stack allocation.
Also fix subtle problem with REL_ALLOC() -- any call to malloc()
(direct or indirect) may relocate rel-alloced data, causing
buffer text to shift. After any such call, regex must update
all its pointers to such data. Add a system, when
ERROR_CHECK_MALLOC, whereby regex.c indicates all the places
it is prepared to handle malloc()/realloc()/free(), and any
calls anywhere in XEmacs outside of this will trigger an abort.
alloc.c, dialog-msw.c, eval.c, event-stream.c, general-slots.h, insdel.c, lisp.h, menubar-msw.c, menubar-x.c: Change *run_hook*_trapping_problems to take a warning class, not
a string. Factor out code to issue warnings, add flag to
call_trapping_problems() to postpone warning issue, and make
*run_hook*_trapping_problems issue their own warnings tailored
to the hook, postponed in the case of safe_run_hook_trapping_problems()
so that the appropriate message can be issued about resetting to
nil only when not `quit'. Make record_unwind_protect_restoring_int()
non-static.
dumper.c: Issue notes about incremental linking problems under Windows.
fileio.c: Mule-ize encrypt/decrypt-string code.
text.h: Spacing changes.
author | ben |
---|---|
date | Sun, 02 Mar 2003 09:38:54 +0000 |
parents | b03923afd851 |
children | 01c57eb70ae9 |
line wrap: on
line diff
--- a/src/regex.c Sun Mar 02 02:18:12 2003 +0000 +++ b/src/regex.c Sun Mar 02 09:38:54 2003 +0000 @@ -5,7 +5,7 @@ Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 1995, 2001, 2002 Ben Wing. + Copyright (C) 1995, 2001, 2002, 2003 Ben Wing. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -126,6 +126,47 @@ return 0; } +#ifdef REL_ALLOC + +/* STRING1 is the value of STRING1 given to re_match_2(). LISPOBJ is + the Lisp object (if any) from which the string is taken. If LISPOBJ + is a buffer, return a relocation offset to be added to all pointers to + string data so that they will be accurate again, after an allocation or + reallocation that potentially relocated the buffer data. +*/ +static Bytecount +offset_post_relocation (Lisp_Object lispobj, char *string1) +{ + struct buffer *buf; + + if (!BUFFERP (lispobj)) + return 0; + return (BYTE_BUF_BYTE_ADDRESS (XBUFFER (lispobj), + BYTE_BUF_BEGV (XBUFFER (lispobj))) - + string1); +} + +#endif /* REL_ALLOC */ + +#ifdef ERROR_CHECK_MALLOC + +/* NOTE that this can run malloc() so you need to adjust afterwards. */ + +static int +bind_regex_malloc_disallowed (int value) +{ + /* Tricky, because the act of binding can run malloc(). */ + int old_regex_malloc_disallowed = regex_malloc_disallowed; + int depth; + regex_malloc_disallowed = 0; + depth = record_unwind_protect_restoring_int (®ex_malloc_disallowed, + old_regex_malloc_disallowed); + regex_malloc_disallowed = value; + return depth; +} + +#endif /* ERROR_CHECK_MALLOC */ + #else /* not emacs */ /* If we are not linking with Emacs proper, @@ -300,11 +341,61 @@ not functions -- `alloca'-allocated space disappears at the end of the function it is called in. */ +#ifndef emacs +#define ALLOCA alloca +#define xmalloc malloc +#define xrealloc realloc +#define xfree free +#endif + +#ifdef emacs +#define ALLOCA_GARBAGE_COLLECT() \ +do \ +{ \ + if (need_to_check_c_alloca) \ + xemacs_c_alloca (0); \ +} while (0) +#elif defined (C_ALLOCA) +#define ALLOCA_GARBAGE_COLLECT() alloca (0) +#else +#define ALLOCA_GARBAGE_COLLECT() +#endif + +#ifndef emacs +/* So we can use just it to conditionalize on */ +#undef ERROR_CHECK_MALLOC +#endif + +#ifdef ERROR_CHECK_MALLOC +/* When REL_ALLOC, malloc() is problematic because it could potentially + cause all rel-alloc()ed data -- including buffer text -- to be relocated. + We deal with this by checking for such relocation whenever we have + executed a statement that may call malloc() -- or alloca(), which may + end up calling malloc() in some circumstances -- and recomputing all + of our string pointers in re_match_2_internal() and re_search_2(). + However, if malloc() or alloca() happens and we don't know about it, + we could still be screwed. So we set up a system where we indicate all + places where we are prepared for malloc() or alloca(), and in any + other circumstances, calls to those functions (from anywhere inside of + XEmacs!) will abort(). We do this even when REL_ALLOC is not defined + so that we catch these problems sooner, since many developers and beta + testers will not be running with REL_ALLOC. */ +int regex_malloc_disallowed; +#define BEGIN_REGEX_MALLOC_OK() regex_malloc_disallowed = 0 +#define END_REGEX_MALLOC_OK() regex_malloc_disallowed = 1 +#define UNBIND_REGEX_MALLOC_CHECK() unbind_to (depth) +#else +#define BEGIN_REGEX_MALLOC_OK() +#define END_REGEX_MALLOC_OK() +#define UNBIND_REGEX_MALLOC_CHECK() +#endif + + #ifdef REGEX_MALLOC -#define REGEX_ALLOCATE malloc -#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) -#define REGEX_FREE free +#define REGEX_ALLOCATE xmalloc +#define REGEX_REALLOCATE(source, osize, nsize) xrealloc (source, nsize) +#define REGEX_FREE xfree #else /* not REGEX_MALLOC */ @@ -329,11 +420,11 @@ #endif /* not alloca */ -#define REGEX_ALLOCATE alloca +#define REGEX_ALLOCATE ALLOCA /* Assumes a `char *destination' variable. */ #define REGEX_REALLOCATE(source, osize, nsize) \ - (destination = (char *) alloca (nsize), \ + (destination = (char *) ALLOCA (nsize), \ memmove (destination, source, osize), \ destination) @@ -356,13 +447,13 @@ #ifdef REGEX_MALLOC -#define REGEX_ALLOCATE_STACK malloc -#define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) -#define REGEX_FREE_STACK free +#define REGEX_ALLOCATE_STACK xmalloc +#define REGEX_REALLOCATE_STACK(source, osize, nsize) xrealloc (source, nsize) +#define REGEX_FREE_STACK xfree #else /* not REGEX_MALLOC */ -#define REGEX_ALLOCATE_STACK alloca +#define REGEX_ALLOCATE_STACK ALLOCA #define REGEX_REALLOCATE_STACK(source, osize, nsize) \ REGEX_REALLOCATE (source, osize, nsize) @@ -380,8 +471,8 @@ (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) /* (Re)Allocate N items of type T using malloc, or fail. */ -#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) -#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) +#define TALLOC(n, t) ((t *) xmalloc ((n) * sizeof (t))) +#define RETALLOC(addr, n, t) ((addr) = (t *) xrealloc (addr, (n) * sizeof (t))) #define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) #define BYTEWIDTH 8 /* In bits. */ @@ -1115,6 +1206,26 @@ /* Avoiding alloca during matching, to placate r_alloc. */ +/* About these various flags: + + MATCH_MAY_ALLOCATE indicates that it's OK to do allocation in the + searching and matching functions. In this case, we use local variables + to hold the values allocated. If not, we use *global* variables, which + are pre-allocated. NOTE: XEmacs ***MUST*** run with MATCH_MAY_ALLOCATE, + because the regexp routines may get called reentrantly as a result of + QUIT processing (e.g. under Windows: re_match -> QUIT -> quit_p -> drain + events -> process WM_INITMENU -> call filter -> re_match; see stack + trace in signal.c), so we cannot have any global variables (unless we do + lots of trickiness including some unwind-protects, which isn't worth it + at this point). + + REL_ALLOC means that the relocating allocator is in use, for buffers + and such. REGEX_REL_ALLOC means that we use rel-alloc to manage the + fail stack, which may grow quite large. REGEX_MALLOC means we use + malloc() in place of alloca() to allocate the fail stack -- only + applicable if REGEX_REL_ALLOC is not defined. +*/ + /* Define MATCH_MAY_ALLOCATE unless we need to make sure that the searching and matching functions should not call alloca. On some systems, alloca is implemented in terms of malloc, and if we're @@ -1147,21 +1258,25 @@ matching routines; then we don't notice interrupts when they come in. So, Emacs blocks input around all regexp calls except the matching calls, which it leaves unprotected, in the faith that they - will not malloc.]] This previous paragraph is irrelevant. - - XEmacs: We *do not* do anything so stupid as process input from within a - signal handler. However, the regexp routines may get called reentrantly - as a result of QUIT processing (e.g. under Windows: re_match -> QUIT -> - quit_p -> drain events -> process WM_INITMENU -> call filter -> - re_match; see stack trace in signal.c), so we cannot have any global - variables (unless we do lots of trickiness including some - unwind-protects, which isn't worth it at this point). The first - paragraph appears utterly garbled to me -- shouldn't *ANY* use of - rel-alloc to different potentially cause buffer data to be relocated? I + will not malloc.]] This previous paragraph is irrelevant under XEmacs, + as we *do not* do anything so stupid as process input from within a + signal handler. + + However, the regexp routines may get called reentrantly as a result of + QUIT processing (e.g. under Windows: re_match -> QUIT -> quit_p -> drain + events -> process WM_INITMENU -> call filter -> re_match; see stack + trace in signal.c), so we cannot have any global variables (unless we do + lots of trickiness including some unwind-protects, which isn't worth it + at this point). Hence we MUST have MATCH_MAY_ALLOCATE defined. + + Also, the first paragraph does not make complete sense to me -- what + about the use of rel-alloc to handle the fail stacks? Shouldn't these + reallocations potentially cause buffer data to be relocated as well? I must be missing something, though -- perhaps the writer above is assuming that the failure stack(s) will always be allocated after the buffer data, and thus reallocating them with rel-alloc won't move buffer - data. --ben */ + data. (In fact, a cursory glance at the code in ralloc.c seems to + confirm this.) --ben */ /* Normally, this is fine. */ #define MATCH_MAY_ALLOCATE @@ -1178,14 +1293,12 @@ failure stack, but we would still use it for the register vectors; so REL_ALLOC should not affect this. */ -/* XEmacs change emacs -> REL_ALLOC */ -#if (defined (C_ALLOCA) || defined (REGEX_MALLOC)) && defined (REL_ALLOC) +/* XEmacs can handle REL_ALLOC and malloc() OK */ +#if !defined (emacs) && (defined (C_ALLOCA) || defined (REGEX_MALLOC)) && defined (REL_ALLOC) #undef MATCH_MAY_ALLOCATE #endif -/* #### need better check */ - -#if !defined (MATCH_MAY_ALLOCATE) && defined (emacs) && defined (HAVE_MS_WINDOWS) +#if !defined (MATCH_MAY_ALLOCATE) && defined (emacs) #error regex must be handle reentrancy; MATCH_MAY_ALLOCATE must be defined #endif @@ -1238,16 +1351,20 @@ Do `return -2' if the alloc fails. */ #ifdef MATCH_MAY_ALLOCATE -#define INIT_FAIL_STACK() \ - do { \ - fail_stack.stack = (fail_stack_elt_t *) \ - REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ - \ - if (fail_stack.stack == NULL) \ - return -2; \ - \ - fail_stack.size = INIT_FAILURE_ALLOC; \ - fail_stack.avail = 0; \ +#define INIT_FAIL_STACK() \ + do { \ + fail_stack.stack = (fail_stack_elt_t *) \ + REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * \ + sizeof (fail_stack_elt_t)); \ + \ + if (fail_stack.stack == NULL) \ + { \ + UNBIND_REGEX_MALLOC_CHECK (); \ + return -2; \ + } \ + \ + fail_stack.size = INIT_FAILURE_ALLOC; \ + fail_stack.avail = 0; \ } while (0) #define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack) @@ -1281,6 +1398,93 @@ : ((fail_stack).size <<= 1, \ 1))) +#if !defined (emacs) || !defined (REL_ALLOC) +#define RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS() +#else +/* Don't change NULL pointers */ +#define ADD_IF_NZ(val) if (val) val += rmdp_offset +#define RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS() \ +do \ +{ \ + Bytecount rmdp_offset = offset_post_relocation (lispobj, string1); \ + \ + if (rmdp_offset) \ + { \ + int i; \ + \ + ADD_IF_NZ (string1); \ + ADD_IF_NZ (string2); \ + ADD_IF_NZ (d); \ + ADD_IF_NZ (dend); \ + ADD_IF_NZ (end1); \ + ADD_IF_NZ (end2); \ + ADD_IF_NZ (end_match_1); \ + ADD_IF_NZ (end_match_2); \ + \ + if (bufp->re_ngroups) \ + { \ + for (i = 0; i < numregs; i++) \ + { \ + ADD_IF_NZ (regstart[i]); \ + ADD_IF_NZ (regend[i]); \ + ADD_IF_NZ (old_regstart[i]); \ + ADD_IF_NZ (old_regend[i]); \ + ADD_IF_NZ (best_regstart[i]); \ + ADD_IF_NZ (best_regend[i]); \ + ADD_IF_NZ (reg_dummy[i]); \ + } \ + } \ + \ + ADD_IF_NZ (match_end); \ + } \ +} while (0) +#endif /* !defined (emacs) || !defined (REL_ALLOC) */ + +#if !defined (emacs) || !defined (REL_ALLOC) +#define RE_SEARCH_RELOCATE_MOVEABLE_DATA_POINTERS() +#else +#define RE_SEARCH_RELOCATE_MOVEABLE_DATA_POINTERS() \ +do \ +{ \ + Bytecount rmdp_offset = offset_post_relocation (lispobj, str1); \ + \ + if (rmdp_offset) \ + { \ + int i; \ + \ + ADD_IF_NZ (str1); \ + ADD_IF_NZ (str2); \ + ADD_IF_NZ (string1); \ + ADD_IF_NZ (string2); \ + ADD_IF_NZ (d); \ + \ + \ + \ + ADD_IF_NZ (dend); \ + ADD_IF_NZ (end1); \ + ADD_IF_NZ (end2); \ + ADD_IF_NZ (end_match_1); \ + ADD_IF_NZ (end_match_2); \ + \ + if (bufp->re_ngroups) \ + { \ + for (i = 0; i < numregs; i++) \ + { \ + ADD_IF_NZ (regstart[i]); \ + ADD_IF_NZ (regend[i]); \ + ADD_IF_NZ (old_regstart[i]); \ + ADD_IF_NZ (old_regend[i]); \ + ADD_IF_NZ (best_regstart[i]); \ + ADD_IF_NZ (best_regend[i]); \ + ADD_IF_NZ (reg_dummy[i]); \ + } \ + } \ + \ + ADD_IF_NZ (match_end); \ + } \ +} while (0) + +#endif /* emacs */ /* Push pointer POINTER on FAIL_STACK. Return 1 if was able to do so and 0 if ran out of memory allocating @@ -1363,13 +1567,20 @@ /* Ensure we have enough space allocated for what we will push. */ \ while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ { \ + BEGIN_REGEX_MALLOC_OK (); \ if (!DOUBLE_FAIL_STACK (fail_stack)) \ - return failure_code; \ - \ + { \ + END_REGEX_MALLOC_OK (); \ + UNBIND_REGEX_MALLOC_CHECK (); \ + return failure_code; \ + } \ + END_REGEX_MALLOC_OK (); \ DEBUG_PRINT2 ("\n Doubled stack; size now: %ld\n", \ (long) (fail_stack).size); \ DEBUG_PRINT2 (" slots available: %ld\n", \ (long) REMAINING_AVAIL_SLOTS); \ + \ + RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS (); \ } \ \ /* Push the info, starting with the registers. */ \ @@ -1676,29 +1887,30 @@ reset the pointers that pointed into the old block to point to the correct places in the new one. If extending the buffer results in it being larger than MAX_BUF_SIZE, then flag memory exhausted. */ -#define EXTEND_BUFFER() \ - do { \ - re_char *old_buffer = bufp->buffer; \ - if (bufp->allocated == MAX_BUF_SIZE) \ - return REG_ESIZE; \ - bufp->allocated <<= 1; \ - if (bufp->allocated > MAX_BUF_SIZE) \ - bufp->allocated = MAX_BUF_SIZE; \ - bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\ - if (bufp->buffer == NULL) \ - return REG_ESPACE; \ - /* If the buffer moved, move all the pointers into it. */ \ - if (old_buffer != bufp->buffer) \ - { \ - buf_end = (buf_end - old_buffer) + bufp->buffer; \ - begalt = (begalt - old_buffer) + bufp->buffer; \ - if (fixup_alt_jump) \ - fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ - if (laststart) \ - laststart = (laststart - old_buffer) + bufp->buffer; \ - if (pending_exact) \ - pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ - } \ +#define EXTEND_BUFFER() \ + do { \ + re_char *old_buffer = bufp->buffer; \ + if (bufp->allocated == MAX_BUF_SIZE) \ + return REG_ESIZE; \ + bufp->allocated <<= 1; \ + if (bufp->allocated > MAX_BUF_SIZE) \ + bufp->allocated = MAX_BUF_SIZE; \ + bufp->buffer = \ + (unsigned char *) xrealloc (bufp->buffer, bufp->allocated); \ + if (bufp->buffer == NULL) \ + return REG_ESPACE; \ + /* If the buffer moved, move all the pointers into it. */ \ + if (old_buffer != bufp->buffer) \ + { \ + buf_end = (buf_end - old_buffer) + bufp->buffer; \ + begalt = (begalt - old_buffer) + bufp->buffer; \ + if (fixup_alt_jump) \ + fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer; \ + if (laststart) \ + laststart = (laststart - old_buffer) + bufp->buffer; \ + if (pending_exact) \ + pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ + } \ } while (0) @@ -1913,7 +2125,11 @@ /* Return, freeing storage we allocated. */ #define FREE_STACK_RETURN(value) \ - return (free (compile_stack.stack), value) +do \ +{ \ + xfree (compile_stack.stack); \ + return value; \ +} while (0) static reg_errcode_t regex_compile (re_char *pattern, int size, reg_syntax_t syntax, @@ -3216,7 +3432,7 @@ if (syntax & RE_NO_POSIX_BACKTRACKING) BUF_PUSH (succeed); - free (compile_stack.stack); + xfree (compile_stack.stack); /* We have succeeded; set the length of the buffer. */ bufp->used = buf_end - bufp->buffer; @@ -3243,7 +3459,6 @@ { fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS); -#ifdef emacs if (! fail_stack.stack) fail_stack.stack = (fail_stack_elt_t *) xmalloc (fail_stack.size @@ -3253,17 +3468,6 @@ = (fail_stack_elt_t *) xrealloc (fail_stack.stack, (fail_stack.size * sizeof (fail_stack_elt_t))); -#else /* not emacs */ - if (! fail_stack.stack) - fail_stack.stack - = (fail_stack_elt_t *) malloc (fail_stack.size - * sizeof (fail_stack_elt_t)); - else - fail_stack.stack - = (fail_stack_elt_t *) realloc (fail_stack.stack, - (fail_stack.size - * sizeof (fail_stack_elt_t))); -#endif /* emacs */ } regex_grow_registers (num_regs); @@ -3549,6 +3753,13 @@ /* We aren't doing a `succeed_n' to begin with. */ re_bool succeed_n_p = false; +#ifdef ERROR_CHECK_MALLOC + /* The pattern comes from string data, not buffer data. We don't access + any buffer data, so we don't have to worry about malloc() (but the + disallowed flag may have been set by a caller). */ + int depth = bind_regex_malloc_disallowed (0); +#endif + assert (fastmap != NULL && p != NULL); INIT_FAIL_STACK (); @@ -3838,6 +4049,7 @@ case categoryspec: case notcategoryspec: bufp->can_be_null = 1; + UNBIND_REGEX_MALLOC_CHECK (); return 0; /* end if category patch */ #endif /* MULE */ @@ -3915,6 +4127,7 @@ if (!PUSH_PATTERN_OP (p + j, fail_stack)) { RESET_FAIL_STACK (); + UNBIND_REGEX_MALLOC_CHECK (); return -2; } } @@ -3976,6 +4189,7 @@ done: RESET_FAIL_STACK (); + UNBIND_REGEX_MALLOC_CHECK (); return 0; } /* re_compile_fastmap */ @@ -4072,6 +4286,9 @@ re_char *d; #ifdef emacs Internal_Format fmt = buffer_or_other_internal_format (lispobj); +#ifdef ERROR_CHECK_MALLOC + int depth; +#endif #endif /* emacs */ #if 1 int forward_search_p; @@ -4120,10 +4337,23 @@ } #endif /* emacs */ +#ifdef ERROR_CHECK_MALLOC + /* Do this after the above return()s. */ + depth = bind_regex_malloc_disallowed (1); +#endif + /* Update the fastmap now if not correct already. */ + BEGIN_REGEX_MALLOC_OK (); if (fastmap && !bufp->fastmap_accurate) if (re_compile_fastmap (bufp RE_LISP_SHORT_CONTEXT_ARGS) == -2) - return -2; + { + END_REGEX_MALLOC_OK (); + UNBIND_REGEX_MALLOC_CHECK (); + return -2; + } + + END_REGEX_MALLOC_OK (); + RE_SEARCH_RELOCATE_MOVEABLE_DATA_POINTERS (); #ifdef REGEX_BEGLINE_CHECK { @@ -4142,9 +4372,12 @@ #endif #ifdef emacs + BEGIN_REGEX_MALLOC_OK (); scache = setup_syntax_cache (scache, lispobj, lispbuf, offset_to_charxpos (lispobj, startpos), 1); + END_REGEX_MALLOC_OK (); + RE_SEARCH_RELOCATE_MOVEABLE_DATA_POINTERS (); #endif /* Loop through the string, looking for a place to start matching. */ @@ -4274,7 +4507,7 @@ INC_IBYTEPTR_FMT (d, fmt); range -= (d - old_d); #if 1 - assert (!forward_search_p || range >= 0); + assert (!forward_search_p || range >= 0); #endif } } @@ -4292,7 +4525,7 @@ INC_IBYTEPTR_FMT (d, fmt); range -= (d - old_d); #if 1 - assert (!forward_search_p || range >= 0); + assert (!forward_search_p || range >= 0); #endif } } @@ -4338,27 +4571,44 @@ /* If can't match the null string, and that's all we have left, fail. */ if (range >= 0 && startpos == total_size && fastmap && !bufp->can_be_null) - return -1; + { + UNBIND_REGEX_MALLOC_CHECK (); + return -1; + } #ifdef emacs /* XEmacs added, w/removal of immediate_quit */ if (!no_quit_in_re_search) - QUIT; + { + BEGIN_REGEX_MALLOC_OK (); + QUIT; + END_REGEX_MALLOC_OK (); + RE_SEARCH_RELOCATE_MOVEABLE_DATA_POINTERS (); + } + #endif + BEGIN_REGEX_MALLOC_OK (); val = re_match_2_internal (bufp, string1, size1, string2, size2, startpos, regs, stop RE_LISP_CONTEXT_ARGS); #ifndef REGEX_MALLOC -#ifdef C_ALLOCA - alloca (0); + ALLOCA_GARBAGE_COLLECT (); #endif -#endif + END_REGEX_MALLOC_OK (); + RE_SEARCH_RELOCATE_MOVEABLE_DATA_POINTERS (); if (val >= 0) - return startpos; + { + UNBIND_REGEX_MALLOC_CHECK (); + return startpos; + } if (val == -2) - return -2; - + { + UNBIND_REGEX_MALLOC_CHECK (); + return -2; + } + + RE_SEARCH_RELOCATE_MOVEABLE_DATA_POINTERS (); advance: if (!range) break; @@ -4390,6 +4640,7 @@ startpos -= d_size; } } + UNBIND_REGEX_MALLOC_CHECK (); return -1; } /* re_search_2 */ @@ -4442,6 +4693,7 @@ #define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL #define FREE_VARIABLES() \ do { \ + UNBIND_REGEX_MALLOC_CHECK (); \ REGEX_FREE_STACK (fail_stack.stack); \ FREE_VAR (regstart); \ FREE_VAR (regend); \ @@ -4454,7 +4706,10 @@ FREE_VAR (reg_info_dummy); \ } while (0) #else /* not MATCH_MAY_ALLOCATE */ -#define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ +#define FREE_VARIABLES() \ + do { \ + UNBIND_REGEX_MALLOC_CHECK (); \ + } while (0) #endif /* MATCH_MAY_ALLOCATE */ /* These values must meet several constraints. They must not be valid @@ -4480,7 +4735,7 @@ int result = re_match_2_internal (bufp, NULL, 0, (re_char *) string, size, pos, regs, size RE_LISP_CONTEXT_ARGS); - alloca (0); + ALLOCA_GARBAGE_COLLECT (); return result; } #endif /* not emacs */ @@ -4517,7 +4772,7 @@ pos, regs, stop RE_LISP_CONTEXT_ARGS); - alloca (0); + ALLOCA_GARBAGE_COLLECT (); return result; } @@ -4659,11 +4914,16 @@ #ifdef emacs Internal_Format fmt = buffer_or_other_internal_format (lispobj); +#ifdef ERROR_CHECK_MALLOC + int depth = bind_regex_malloc_disallowed (1); +#endif #endif /* emacs */ DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); + BEGIN_REGEX_MALLOC_OK (); INIT_FAIL_STACK (); + END_REGEX_MALLOC_OK (); #ifdef MATCH_MAY_ALLOCATE /* Do not bother to initialize all the register variables if there are @@ -4673,6 +4933,7 @@ array indexing. We should fix this. */ if (bufp->re_ngroups) { + BEGIN_REGEX_MALLOC_OK (); regstart = REGEX_TALLOC (num_regs, re_char *); regend = REGEX_TALLOC (num_regs, re_char *); old_regstart = REGEX_TALLOC (num_regs, re_char *); @@ -4682,6 +4943,7 @@ reg_info = REGEX_TALLOC (num_regs, register_info_type); reg_dummy = REGEX_TALLOC (num_regs, re_char *); reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type); + END_REGEX_MALLOC_OK (); if (!(regstart && regend && old_regstart && old_regend && reg_info && best_regstart && best_regend && reg_dummy && reg_info_dummy)) @@ -4700,6 +4962,20 @@ } #endif /* MATCH_MAY_ALLOCATE */ +#if defined (emacs) && defined (REL_ALLOC) + { + /* If the allocations above (or the call to setup_syntax_cache() in + re_match_2) caused a rel-alloc relocation, then fix up the data + pointers */ + Bytecount offset = offset_post_relocation (lispobj, string1); + if (offset) + { + string1 += offset; + string2 += offset; + } + } +#endif /* defined (emacs) && defined (REL_ALLOC) */ + /* The starting position is bogus. */ if (pos < 0 || pos > size1 + size2) { @@ -4775,7 +5051,12 @@ DEBUG_PRINT2 ("\n0x%lx: ", (long) p); #ifdef emacs /* XEmacs added, w/removal of immediate_quit */ if (!no_quit_in_re_search) - QUIT; + { + BEGIN_REGEX_MALLOC_OK (); + QUIT; + END_REGEX_MALLOC_OK (); + RE_SEARCH_RELOCATE_MOVEABLE_DATA_POINTERS (); + } #endif if (p == pend) @@ -4857,8 +5138,11 @@ extra element beyond `num_regs' for the `-1' marker GNU code uses. */ regs->num_regs = MAX (RE_NREGS, num_nonshy_regs + 1); + BEGIN_REGEX_MALLOC_OK (); regs->start = TALLOC (regs->num_regs, regoff_t); regs->end = TALLOC (regs->num_regs, regoff_t); + END_REGEX_MALLOC_OK (); + RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS (); if (regs->start == NULL || regs->end == NULL) { FREE_VARIABLES (); @@ -4873,8 +5157,11 @@ if (regs->num_regs < num_nonshy_regs + 1) { regs->num_regs = num_nonshy_regs + 1; + BEGIN_REGEX_MALLOC_OK (); RETALLOC (regs->start, regs->num_regs, regoff_t); RETALLOC (regs->end, regs->num_regs, regoff_t); + END_REGEX_MALLOC_OK (); + RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS (); if (regs->start == NULL || regs->end == NULL) { FREE_VARIABLES (); @@ -5815,6 +6102,7 @@ #ifdef emacs pos_before = offset_to_charxpos (lispobj, PTR_TO_OFFSET (d)) - 1; + BEGIN_REGEX_MALLOC_OK (); UPDATE_SYNTAX_CACHE (scache, pos_before); #endif syn1 = SYNTAX_FROM_CACHE (scache, emch1); @@ -5824,6 +6112,8 @@ syn2 = SYNTAX_FROM_CACHE (scache, emch2); result = ((syn1 == Sword) != (syn2 == Sword)); + END_REGEX_MALLOC_OK (); + RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS (); } if (result == should_succeed) break; @@ -5848,21 +6138,30 @@ */ re_char *dtmp = POS_AFTER_GAP_UNSAFE (d); Ichar emch = itext_ichar_fmt (dtmp, fmt, lispobj); + int tempres; + BEGIN_REGEX_MALLOC_OK (); #ifdef emacs Charxpos charpos = offset_to_charxpos (lispobj, PTR_TO_OFFSET (d)); UPDATE_SYNTAX_CACHE (scache, charpos); #endif - if (SYNTAX_FROM_CACHE (scache, emch) != Sword) + tempres = (SYNTAX_FROM_CACHE (scache, emch) != Sword); + END_REGEX_MALLOC_OK (); + RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS (); + if (tempres) goto fail; if (AT_STRINGS_BEG (d)) break; dtmp = POS_BEFORE_GAP_UNSAFE (d); DEC_IBYTEPTR_FMT (dtmp, fmt); emch = itext_ichar_fmt (dtmp, fmt, lispobj); + BEGIN_REGEX_MALLOC_OK (); #ifdef emacs UPDATE_SYNTAX_CACHE_BACKWARD (scache, charpos - 1); #endif - if (SYNTAX_FROM_CACHE (scache, emch) != Sword) + tempres = (SYNTAX_FROM_CACHE (scache, emch) != Sword); + END_REGEX_MALLOC_OK (); + RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS (); + if (tempres) break; goto fail; } @@ -5882,23 +6181,35 @@ */ re_char *dtmp; Ichar emch; + int tempres; + BEGIN_REGEX_MALLOC_OK (); #ifdef emacs Charxpos charpos = offset_to_charxpos (lispobj, PTR_TO_OFFSET (d)); UPDATE_SYNTAX_CACHE (scache, charpos); #endif + END_REGEX_MALLOC_OK (); + RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS (); dtmp = POS_BEFORE_GAP_UNSAFE (d); DEC_IBYTEPTR_FMT (dtmp, fmt); emch = itext_ichar_fmt (dtmp, fmt, lispobj); - if (SYNTAX_FROM_CACHE (scache, emch) != Sword) + BEGIN_REGEX_MALLOC_OK (); + tempres = (SYNTAX_FROM_CACHE (scache, emch) != Sword); + END_REGEX_MALLOC_OK (); + RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS (); + if (tempres) goto fail; if (AT_STRINGS_END (d)) break; dtmp = POS_AFTER_GAP_UNSAFE (d); emch = itext_ichar_fmt (dtmp, fmt, lispobj); + BEGIN_REGEX_MALLOC_OK (); #ifdef emacs UPDATE_SYNTAX_CACHE_FORWARD (scache, charpos + 1); #endif - if (SYNTAX_FROM_CACHE (scache, emch) != Sword) + tempres = (SYNTAX_FROM_CACHE (scache, emch) != Sword); + END_REGEX_MALLOC_OK (); + RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS (); + if (tempres) break; goto fail; } @@ -5944,12 +6255,18 @@ Ichar emch; REGEX_PREFETCH (); + BEGIN_REGEX_MALLOC_OK (); UPDATE_SYNTAX_CACHE (scache, offset_to_charxpos (lispobj, PTR_TO_OFFSET (d))); + END_REGEX_MALLOC_OK (); + RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS (); emch = itext_ichar_fmt (d, fmt, lispobj); + BEGIN_REGEX_MALLOC_OK (); matches = (SYNTAX_FROM_CACHE (scache, emch) == (enum syntaxcode) mcnt); + END_REGEX_MALLOC_OK (); + RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS (); INC_IBYTEPTR_FMT (d, fmt); if (matches != should_succeed) goto fail; @@ -6074,7 +6391,7 @@ FREE_VARIABLES (); return -1; /* Failure to match. */ -} /* re_match_2 */ +} /* re_match_2_internal */ /* Subroutine definitions for re_match_2. */ @@ -6415,12 +6732,12 @@ if (!re_comp_buf.buffer) { - re_comp_buf.buffer = (unsigned char *) malloc (200); + re_comp_buf.buffer = (unsigned char *) xmalloc (200); if (re_comp_buf.buffer == NULL) return gettext (re_error_msgid[(int) REG_ESPACE]); re_comp_buf.allocated = 200; - re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); + re_comp_buf.fastmap = (char *) xmalloc (1 << BYTEWIDTH); if (re_comp_buf.fastmap == NULL) return gettext (re_error_msgid[(int) REG_ESPACE]); } @@ -6514,7 +6831,7 @@ { int i; - preg->translate = (char *) malloc (CHAR_SET_SIZE); + preg->translate = (char *) xmalloc (CHAR_SET_SIZE); if (preg->translate == NULL) return (int) REG_ESPACE; @@ -6613,8 +6930,8 @@ } /* If we needed the temporary register info, free the space now. */ - free (regs.start); - free (regs.end); + xfree (regs.start); + xfree (regs.end); } /* We want zero return to mean success, unlike `re_search'. */ @@ -6666,19 +6983,19 @@ regfree (regex_t *preg) { if (preg->buffer != NULL) - free (preg->buffer); + xfree (preg->buffer); preg->buffer = NULL; preg->allocated = 0; preg->used = 0; if (preg->fastmap != NULL) - free (preg->fastmap); + xfree (preg->fastmap); preg->fastmap = NULL; preg->fastmap_accurate = 0; if (preg->translate != NULL) - free (preg->translate); + xfree (preg->translate); preg->translate = NULL; }