changeset 412:cd6c9a160091

(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.
author Richard Stallman <rms@gnu.org>
date Sat, 29 Apr 1995 20:21:41 +0000
parents 19dca1d4d7f6
children 7ad568cbce0d
files regex.c
diffstat 1 files changed, 138 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/regex.c
+++ b/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 *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 @@
 
 #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 @@
    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 @@
 /* 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 @@
 
 /* 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 @@
    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 @@
 #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 @@
    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 @@
 #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 @@
    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 @@
     /* 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 @@
 static char reg_unset_dummy;
 #define REG_UNSET_VALUE (&reg_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 @@
     || 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 @@
 #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 @@
   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 @@
            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 @@
 	    /* 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 @@
           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 @@
   /* 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 @@
 
 /* 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 @@
     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 @@
   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 @@
           return -2;
         }
     }
-#if defined (REGEX_MALLOC)
   else
     {
       /* We must initialize all our variables to NULL, so that
@@ -3547,7 +3627,6 @@
         = 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 @@
                   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 @@
                       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 @@
                 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 @@
 
           DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
 
+          FREE_VARIABLES ();
           return mcnt;
         }