summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--generic/regcomp.c12
-rw-r--r--generic/regcustom.h22
-rw-r--r--generic/regexec.c10
-rw-r--r--generic/regguts.h13
5 files changed, 61 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index b4bf470..34ae284 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,14 +1,22 @@
+2007-01-10 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/regcomp.c (compile, freev): Define a strategy for
+ * generic/regexec.c (exec): managing the internal vars
+ * generic/regguts.h (AllocVars, FreeVars): of the RE engine to reduce
+ * generic/regcustom.h (AllocVars, FreeVars): C stack usage. This will
+ make Tcl as a whole much less likely to run out of stack space...
+
2007-01-09 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * generic/tclCompCmds.c (TclCompileLindexCmd):
+ * generic/tclCompCmds.c (TclCompileLindexCmd):
* tests/lindex.test (lindex-9.2): Fix silly bug that ended up
sometimes compiling list arguments in the wrong order. [Bug 1631364]
2007-01-03 Kevin Kenny <kennykb@acm.org>
- * generic/tclDate.c: Regenerated to recover a lost fix from
- patthoyts. [Bug 1618523]
-
+ * generic/tclDate.c: Regenerated to recover a lost fix from patthoyts.
+ [Bug 1618523]
+
2006-12-26 Mo DeJong <mdejong@users.sourceforge.net>
* generic/tclIO.c (Tcl_GetsObj): Avoid checking for for the LF in a
diff --git a/generic/regcomp.c b/generic/regcomp.c
index 0d6f066..049ad69 100644
--- a/generic/regcomp.c
+++ b/generic/regcomp.c
@@ -287,8 +287,7 @@ compile(
size_t len,
int flags)
{
- struct vars var;
- struct vars *v = &var;
+ AllocVars(v);
struct guts *g;
int i;
size_t j;
@@ -300,12 +299,15 @@ compile(
*/
if (re == NULL || string == NULL) {
+ FreeVars(v);
return REG_INVARG;
}
if ((flags&REG_QUOTE) && (flags&(REG_ADVANCED|REG_EXPANDED|REG_NEWLINE))) {
+ FreeVars(v);
return REG_INVARG;
}
if (!(flags&REG_EXTENDED) && (flags&REG_ADVF)) {
+ FreeVars(v);
return REG_INVARG;
}
@@ -525,6 +527,8 @@ freev(
struct vars *v,
int err)
{
+ register int ret;
+
if (v->re != NULL) {
rfree(v->re);
}
@@ -554,7 +558,9 @@ freev(
}
ERR(err); /* nop if err==0 */
- return v->err;
+ ret = v->err;
+ FreeVars(v);
+ return ret;
}
/*
diff --git a/generic/regcustom.h b/generic/regcustom.h
index 6abd24c..6b6b38c 100644
--- a/generic/regcustom.h
+++ b/generic/regcustom.h
@@ -11,12 +11,12 @@
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
*
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
@@ -116,5 +116,21 @@ typedef int celt; /* type to hold chr, MCCE number, or NOCELT */
#define REG_DEBUG /* */
#endif
+/* method of allocating a local workspace */
+#if 1
+#define AllocVars(vPtr) \
+ static Tcl_ThreadDataKey varsKey; \
+ register struct vars *vPtr = (struct vars *) \
+ Tcl_GetThreadData(&varsKey, sizeof(struct vars))
+#else
+/* This strategy for allocating workspace is "more proper" in some sense, but
+ * quite a bit slower. Using TSD (as above) leads to code that is quite a bit
+ * faster in practice. */
+#define AllocVars(vPtr) \
+ register struct vars *vPtr = (struct vars *) MALLOC(sizeof(struct vars))
+#define FreeVars(vPtr) \
+ FREE(vPtr)
+#endif
+
/* and pick up the standard header */
#include "regex.h"
diff --git a/generic/regexec.c b/generic/regexec.c
index 6862ef9..d39685c 100644
--- a/generic/regexec.c
+++ b/generic/regexec.c
@@ -170,8 +170,7 @@ exec(
regmatch_t pmatch[],
int flags)
{
- struct vars var;
- register struct vars *v = &var;
+ AllocVars(v);
int st;
size_t n;
int backref;
@@ -185,9 +184,11 @@ exec(
*/
if (re == NULL || string == NULL || re->re_magic != REMAGIC) {
+ FreeVars(v);
return REG_INVARG;
}
if (re->re_csize != sizeof(chr)) {
+ FreeVars(v);
return REG_MIXED;
}
@@ -198,9 +199,11 @@ exec(
v->re = re;
v->g = (struct guts *)re->re_guts;
if ((v->g->cflags&REG_EXPECT) && details == NULL) {
+ FreeVars(v);
return REG_INVARG;
}
if (v->g->info&REG_UIMPOSSIBLE) {
+ FreeVars(v);
return REG_NOMATCH;
}
backref = (v->g->info&REG_UBACKREF) ? 1 : 0;
@@ -221,6 +224,7 @@ exec(
MALLOC((v->g->nsub + 1) * sizeof(regmatch_t));
}
if (v->pmatch == NULL) {
+ FreeVars(v);
return REG_ESPACE;
}
v->nmatch = v->g->nsub + 1;
@@ -247,6 +251,7 @@ exec(
if (v->pmatch != pmatch && v->pmatch != mat) {
FREE(v->pmatch);
}
+ FreeVars(v);
return REG_ESPACE;
}
} else {
@@ -284,6 +289,7 @@ exec(
if (v->mem != NULL && v->mem != mem) {
FREE(v->mem);
}
+ FreeVars(v);
return st;
}
diff --git a/generic/regguts.h b/generic/regguts.h
index 190d40b..991979e 100644
--- a/generic/regguts.h
+++ b/generic/regguts.h
@@ -399,6 +399,19 @@ struct guts {
struct subre *lacons; /* lookahead-constraint vector */
int nlacons; /* size of lacons */
};
+
+/*
+ * Magic for allocating a variable workspace.
+ */
+
+#ifndef AllocVars
+#define AllocVars(vPtr) \
+ struct vars var; \
+ register struct vars *vPtr = &var
+#endif
+#ifndef FreeVars
+#define FreeVars(vPtr) ((void) 0)
+#endif
/*
* Local Variables: