mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-30 00:51:50 -08:00
(PUSH_FAILURE_INT, POP_FAILURE_INT): Use WIDE_INT.
(WIDE_INT): Defined (two alternate definitions). (C_ALLOCA): Undef it, if __GNUC__. (REGEX_ALLOCATE_STACK, REGEX_REALLOCATE_STACK) (REGEX_FREE_STACK): New macros. (INIT_FAIL_STACK, DOUBLE_FAIL_STACK, FREE_VARIABLES): Use them. (re_max_failures) [REL_ALLOC]: Alternative larger initial value. (re_compile_fastmap): Use REGEX_FREE_STACK. (re_match_2_internal): Always call FREE_VARIABLES before returning. Always init regstart, old_regstart, etc. whenever MATCH_MAY_ALLOCATE is defined. (FREE_VARIABLES) [REL_ALLOC]: Define non-trivially.
This commit is contained in:
parent
ae849784b4
commit
c823611d96
1 changed files with 138 additions and 53 deletions
191
src/regex.c
191
src/regex.c
|
|
@ -49,6 +49,8 @@
|
|||
#include "buffer.h"
|
||||
#include "syntax.h"
|
||||
|
||||
#define WIDE_INT EMACS_INT
|
||||
|
||||
#else /* not emacs */
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
|
|
@ -58,6 +60,10 @@ char *malloc ();
|
|||
char *realloc ();
|
||||
#endif
|
||||
|
||||
/* This isn't right--it needs to check for machines with 64-bit pointers
|
||||
and do something different. But I don't know what, and I don't
|
||||
need to deal with it right now. -- rms. */
|
||||
#define WIDE_INT int
|
||||
|
||||
/* We used to test for `BSTRING' here, but only GCC and Emacs define
|
||||
`BSTRING', as far as I know, and neither of them use this code. */
|
||||
|
|
@ -209,6 +215,7 @@ init_syntax_once ()
|
|||
|
||||
#define REGEX_ALLOCATE malloc
|
||||
#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
|
||||
#define REGEX_FREE free
|
||||
|
||||
#else /* not REGEX_MALLOC */
|
||||
|
||||
|
|
@ -238,8 +245,41 @@ char *alloca ();
|
|||
bcopy (source, destination, osize), \
|
||||
destination)
|
||||
|
||||
/* No need to do anything to free, after alloca. */
|
||||
#define REGEX_FREE(arg) (0)
|
||||
|
||||
#endif /* not REGEX_MALLOC */
|
||||
|
||||
/* Define how to allocate the failure stack. */
|
||||
|
||||
#ifdef REL_ALLOC
|
||||
#define REGEX_ALLOCATE_STACK(size) \
|
||||
r_alloc (&failure_stack_ptr, (size))
|
||||
#define REGEX_REALLOCATE_STACK(source, osize, nsize) \
|
||||
r_re_alloc (&failure_stack_ptr, (nsize))
|
||||
#define REGEX_FREE_STACK(ptr) \
|
||||
r_alloc_free (&failure_stack_ptr)
|
||||
|
||||
#else /* not REL_ALLOC */
|
||||
|
||||
#ifdef REGEX_MALLOC
|
||||
|
||||
#define REGEX_ALLOCATE_STACK malloc
|
||||
#define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
|
||||
#define REGEX_FREE_STACK free
|
||||
|
||||
#else /* not REGEX_MALLOC */
|
||||
|
||||
#define REGEX_ALLOCATE_STACK alloca
|
||||
|
||||
#define REGEX_REALLOCATE_STACK(source, osize, nsize) \
|
||||
REGEX_REALLOCATE (source, osize, nsize)
|
||||
/* No need to explicitly free anything. */
|
||||
#define REGEX_FREE_STACK(arg)
|
||||
|
||||
#endif /* not REGEX_MALLOC */
|
||||
#endif /* not REL_ALLOC */
|
||||
|
||||
|
||||
/* True if `size1' is non-NULL and PTR is pointing anywhere inside
|
||||
`string1' or just past its end. This works if PTR is NULL, which is
|
||||
|
|
@ -915,6 +955,12 @@ static const char *re_error_msgid[] =
|
|||
/* Normally, this is fine. */
|
||||
#define MATCH_MAY_ALLOCATE
|
||||
|
||||
/* When using GNU C, we are not REALLY using the C alloca, no matter
|
||||
what config.h may say. So don't take precautions for it. */
|
||||
#ifdef __GNUC__
|
||||
#undef C_ALLOCA
|
||||
#endif
|
||||
|
||||
/* The match routines may not allocate if (1) they would do it with malloc
|
||||
and (2) it's not safe for them to use malloc. */
|
||||
#if (defined (C_ALLOCA) || defined (REGEX_MALLOC)) && (defined (emacs) || defined (REL_ALLOC))
|
||||
|
|
@ -924,7 +970,7 @@ static const char *re_error_msgid[] =
|
|||
|
||||
/* Failure stack declarations and macros; both re_compile_fastmap and
|
||||
re_match_2 use a failure stack. These have to be macros because of
|
||||
REGEX_ALLOCATE. */
|
||||
REGEX_ALLOCATE_STACK. */
|
||||
|
||||
|
||||
/* Number of failure points for which to initially allocate space
|
||||
|
|
@ -938,7 +984,11 @@ static const char *re_error_msgid[] =
|
|||
exactly that if always used MAX_FAILURE_SPACE each time we failed.
|
||||
This is a variable only so users of regex can assign to it; we never
|
||||
change it ourselves. */
|
||||
#ifdef REL_ALLOC
|
||||
int re_max_failures = 20000000;
|
||||
#else
|
||||
int re_max_failures = 2000;
|
||||
#endif
|
||||
|
||||
typedef unsigned char *fail_stack_elt_t;
|
||||
|
||||
|
|
@ -961,7 +1011,7 @@ typedef struct
|
|||
#define INIT_FAIL_STACK() \
|
||||
do { \
|
||||
fail_stack.stack = (fail_stack_elt_t *) \
|
||||
REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \
|
||||
REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \
|
||||
\
|
||||
if (fail_stack.stack == NULL) \
|
||||
return -2; \
|
||||
|
|
@ -982,13 +1032,13 @@ typedef struct
|
|||
Return 1 if succeeds, and 0 if either ran out of memory
|
||||
allocating space for it or it was already too large.
|
||||
|
||||
REGEX_REALLOCATE requires `destination' be declared. */
|
||||
REGEX_REALLOCATE_STACK requires `destination' be declared. */
|
||||
|
||||
#define DOUBLE_FAIL_STACK(fail_stack) \
|
||||
((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \
|
||||
? 0 \
|
||||
: ((fail_stack).stack = (fail_stack_elt_t *) \
|
||||
REGEX_REALLOCATE ((fail_stack).stack, \
|
||||
REGEX_REALLOCATE_STACK ((fail_stack).stack, \
|
||||
(fail_stack).size * sizeof (fail_stack_elt_t), \
|
||||
((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \
|
||||
\
|
||||
|
|
@ -1005,9 +1055,9 @@ typedef struct
|
|||
#define PUSH_PATTERN_OP(pattern_op, fail_stack) \
|
||||
((FAIL_STACK_FULL () \
|
||||
&& !DOUBLE_FAIL_STACK (fail_stack)) \
|
||||
? 0 \
|
||||
: ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \
|
||||
1))
|
||||
? 0 \
|
||||
: ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \
|
||||
1))
|
||||
|
||||
/* Push a pointer value onto the failure stack.
|
||||
Assumes the variable `fail_stack'. Probably should only
|
||||
|
|
@ -1019,13 +1069,13 @@ typedef struct
|
|||
Assumes the variable `fail_stack'. Probably should only
|
||||
be called from within `PUSH_FAILURE_POINT'. */
|
||||
#define PUSH_FAILURE_INT(item) \
|
||||
fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) (EMACS_INT) (item)
|
||||
fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) (WIDE_INT) (item)
|
||||
|
||||
/* The complement operation. Assumes `fail_stack' is nonempty. */
|
||||
#define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail]
|
||||
|
||||
/* The complement operation. Assumes `fail_stack' is nonempty. */
|
||||
#define POP_FAILURE_INT() (EMACS_INT) fail_stack.stack[--fail_stack.avail]
|
||||
#define POP_FAILURE_INT() (WIDE_INT) fail_stack.stack[--fail_stack.avail]
|
||||
|
||||
/* Used to omit pushing failure point id's when we're not debugging. */
|
||||
#ifdef DEBUG
|
||||
|
|
@ -1065,7 +1115,7 @@ typedef struct
|
|||
/* Ensure we have enough space allocated for what we will push. */ \
|
||||
while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \
|
||||
{ \
|
||||
if (!DOUBLE_FAIL_STACK (fail_stack)) \
|
||||
if (!DOUBLE_FAIL_STACK (fail_stack)) \
|
||||
return failure_code; \
|
||||
\
|
||||
DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \
|
||||
|
|
@ -1271,23 +1321,6 @@ typedef union
|
|||
static char reg_unset_dummy;
|
||||
#define REG_UNSET_VALUE (®_unset_dummy)
|
||||
#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
|
||||
|
||||
|
||||
|
||||
/* How do we implement a missing MATCH_MAY_ALLOCATE?
|
||||
We make the fail stack a global thing, and then grow it to
|
||||
re_max_failures when we compile. */
|
||||
#ifndef MATCH_MAY_ALLOCATE
|
||||
static fail_stack_type fail_stack;
|
||||
|
||||
static const char ** regstart, ** regend;
|
||||
static const char ** old_regstart, ** old_regend;
|
||||
static const char **best_regstart, **best_regend;
|
||||
static register_info_type *reg_info;
|
||||
static const char **reg_dummy;
|
||||
static register_info_type *reg_info_dummy;
|
||||
#endif
|
||||
|
||||
|
||||
/* Subroutine declarations and macros for regex_compile. */
|
||||
|
||||
|
|
@ -1492,6 +1525,54 @@ typedef struct
|
|||
|| STREQ (string, "punct") || STREQ (string, "graph") \
|
||||
|| STREQ (string, "cntrl") || STREQ (string, "blank"))
|
||||
|
||||
#ifndef MATCH_MAY_ALLOCATE
|
||||
|
||||
/* If we cannot allocate large objects within re_match_2_internal,
|
||||
we make the fail stack and register vectors global.
|
||||
The fail stack, we grow to the maximum size when a regexp
|
||||
is compiled.
|
||||
The register vectors, we adjust in size each time we
|
||||
compile a regexp, according to the number of registers it needs. */
|
||||
|
||||
static fail_stack_type fail_stack;
|
||||
|
||||
/* Size with which the following vectors are currently allocated.
|
||||
That is so we can make them bigger as needed,
|
||||
but never make them smaller. */
|
||||
static int regs_allocated_size;
|
||||
|
||||
static const char ** regstart, ** regend;
|
||||
static const char ** old_regstart, ** old_regend;
|
||||
static const char **best_regstart, **best_regend;
|
||||
static register_info_type *reg_info;
|
||||
static const char **reg_dummy;
|
||||
static register_info_type *reg_info_dummy;
|
||||
|
||||
/* Make the register vectors big enough for NUM_REGS registers,
|
||||
but don't make them smaller. */
|
||||
|
||||
static
|
||||
regex_grow_registers (num_regs)
|
||||
int num_regs;
|
||||
{
|
||||
if (num_regs > regs_allocated_size)
|
||||
{
|
||||
RETALLOC_IF (regstart, num_regs, const char *);
|
||||
RETALLOC_IF (regend, num_regs, const char *);
|
||||
RETALLOC_IF (old_regstart, num_regs, const char *);
|
||||
RETALLOC_IF (old_regend, num_regs, const char *);
|
||||
RETALLOC_IF (best_regstart, num_regs, const char *);
|
||||
RETALLOC_IF (best_regend, num_regs, const char *);
|
||||
RETALLOC_IF (reg_info, num_regs, register_info_type);
|
||||
RETALLOC_IF (reg_dummy, num_regs, const char *);
|
||||
RETALLOC_IF (reg_info_dummy, num_regs, register_info_type);
|
||||
|
||||
regs_allocated_size = num_regs;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* not MATCH_MAY_ALLOCATE */
|
||||
|
||||
/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
|
||||
Returns one of error codes defined in `regex.h', or zero for success.
|
||||
|
||||
|
|
@ -2555,18 +2636,9 @@ regex_compile (pattern, size, syntax, bufp)
|
|||
#endif /* not emacs */
|
||||
}
|
||||
|
||||
/* Initialize some other variables the matcher uses. */
|
||||
RETALLOC_IF (regstart, num_regs, const char *);
|
||||
RETALLOC_IF (regend, num_regs, const char *);
|
||||
RETALLOC_IF (old_regstart, num_regs, const char *);
|
||||
RETALLOC_IF (old_regend, num_regs, const char *);
|
||||
RETALLOC_IF (best_regstart, num_regs, const char *);
|
||||
RETALLOC_IF (best_regend, num_regs, const char *);
|
||||
RETALLOC_IF (reg_info, num_regs, register_info_type);
|
||||
RETALLOC_IF (reg_dummy, num_regs, const char *);
|
||||
RETALLOC_IF (reg_info_dummy, num_regs, register_info_type);
|
||||
regex_grow_registers (num_regs);
|
||||
}
|
||||
#endif
|
||||
#endif /* not MATCH_MAY_ALLOCATE */
|
||||
|
||||
return REG_NOERROR;
|
||||
} /* regex_compile */
|
||||
|
|
@ -2791,6 +2863,10 @@ re_compile_fastmap (bufp)
|
|||
unsigned char *p = pattern;
|
||||
register unsigned char *pend = pattern + size;
|
||||
|
||||
/* This holds the pointer to the failure stack, when
|
||||
it is allocated relocatably. */
|
||||
fail_stack_elt_t *failure_stack_ptr;
|
||||
|
||||
/* Assume that each path through the pattern can be null until
|
||||
proven otherwise. We set this false at the bottom of switch
|
||||
statement, to which we get only if a particular path doesn't
|
||||
|
|
@ -2840,7 +2916,7 @@ re_compile_fastmap (bufp)
|
|||
that is all we do. */
|
||||
case duplicate:
|
||||
bufp->can_be_null = 1;
|
||||
return 0;
|
||||
goto done;
|
||||
|
||||
|
||||
/* Following are the cases which match a character. These end
|
||||
|
|
@ -2898,7 +2974,7 @@ re_compile_fastmap (bufp)
|
|||
/* Return if we have already set `can_be_null'; if we have,
|
||||
then the fastmap is irrelevant. Something's wrong here. */
|
||||
else if (bufp->can_be_null)
|
||||
return 0;
|
||||
goto done;
|
||||
|
||||
/* Otherwise, have to check alternative paths. */
|
||||
break;
|
||||
|
|
@ -2992,7 +3068,10 @@ re_compile_fastmap (bufp)
|
|||
if (p + j < pend)
|
||||
{
|
||||
if (!PUSH_PATTERN_OP (p + j, fail_stack))
|
||||
return -2;
|
||||
{
|
||||
REGEX_FREE_STACK (fail_stack.stack);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
else
|
||||
bufp->can_be_null = 1;
|
||||
|
|
@ -3049,6 +3128,9 @@ re_compile_fastmap (bufp)
|
|||
/* Set `can_be_null' for the last path (also the first path, if the
|
||||
pattern is empty). */
|
||||
bufp->can_be_null |= path_can_be_null;
|
||||
|
||||
done:
|
||||
REGEX_FREE_STACK (fail_stack.stack);
|
||||
return 0;
|
||||
} /* re_compile_fastmap */
|
||||
|
||||
|
|
@ -3303,11 +3385,10 @@ static boolean alt_match_null_string_p (),
|
|||
|
||||
/* Free everything we malloc. */
|
||||
#ifdef MATCH_MAY_ALLOCATE
|
||||
#ifdef REGEX_MALLOC
|
||||
#define FREE_VAR(var) if (var) free (var); var = NULL
|
||||
#define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
|
||||
#define FREE_VARIABLES() \
|
||||
do { \
|
||||
FREE_VAR (fail_stack.stack); \
|
||||
REGEX_FREE_STACK (fail_stack.stack); \
|
||||
FREE_VAR (regstart); \
|
||||
FREE_VAR (regend); \
|
||||
FREE_VAR (old_regstart); \
|
||||
|
|
@ -3318,10 +3399,6 @@ static boolean alt_match_null_string_p (),
|
|||
FREE_VAR (reg_dummy); \
|
||||
FREE_VAR (reg_info_dummy); \
|
||||
} while (0)
|
||||
#else /* not REGEX_MALLOC */
|
||||
/* This used to do alloca (0), but now we do that in the caller. */
|
||||
#define FREE_VARIABLES() /* Nothing */
|
||||
#endif /* not REGEX_MALLOC */
|
||||
#else
|
||||
#define FREE_VARIABLES() /* Do nothing! */
|
||||
#endif /* not MATCH_MAY_ALLOCATE */
|
||||
|
|
@ -3437,6 +3514,10 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
|
|||
unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
|
||||
#endif
|
||||
|
||||
/* This holds the pointer to the failure stack, when
|
||||
it is allocated relocatably. */
|
||||
fail_stack_elt_t *failure_stack_ptr;
|
||||
|
||||
/* We fill all the registers internally, independent of what we
|
||||
return, for use in backreferences. The number here includes
|
||||
an element for register zero. */
|
||||
|
|
@ -3538,7 +3619,6 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
|
|||
return -2;
|
||||
}
|
||||
}
|
||||
#if defined (REGEX_MALLOC)
|
||||
else
|
||||
{
|
||||
/* We must initialize all our variables to NULL, so that
|
||||
|
|
@ -3547,7 +3627,6 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
|
|||
= best_regend = reg_dummy = NULL;
|
||||
reg_info = reg_info_dummy = (register_info_type *) NULL;
|
||||
}
|
||||
#endif /* REGEX_MALLOC */
|
||||
#endif /* MATCH_MAY_ALLOCATE */
|
||||
|
||||
/* The starting position is bogus. */
|
||||
|
|
@ -3709,7 +3788,10 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
|
|||
regs->start = TALLOC (regs->num_regs, regoff_t);
|
||||
regs->end = TALLOC (regs->num_regs, regoff_t);
|
||||
if (regs->start == NULL || regs->end == NULL)
|
||||
return -2;
|
||||
{
|
||||
FREE_VARIABLES ();
|
||||
return -2;
|
||||
}
|
||||
bufp->regs_allocated = REGS_REALLOCATE;
|
||||
}
|
||||
else if (bufp->regs_allocated == REGS_REALLOCATE)
|
||||
|
|
@ -3722,7 +3804,10 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
|
|||
RETALLOC (regs->start, regs->num_regs, regoff_t);
|
||||
RETALLOC (regs->end, regs->num_regs, regoff_t);
|
||||
if (regs->start == NULL || regs->end == NULL)
|
||||
return -2;
|
||||
{
|
||||
FREE_VARIABLES ();
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -3767,7 +3852,6 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
|
|||
regs->start[mcnt] = regs->end[mcnt] = -1;
|
||||
} /* regs && !bufp->no_sub */
|
||||
|
||||
FREE_VARIABLES ();
|
||||
DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
|
||||
nfailure_points_pushed, nfailure_points_popped,
|
||||
nfailure_points_pushed - nfailure_points_popped);
|
||||
|
|
@ -3779,6 +3863,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
|
|||
|
||||
DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
|
||||
|
||||
FREE_VARIABLES ();
|
||||
return mcnt;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue