diff options
Diffstat (limited to 'generic/tclRegexp.c')
-rw-r--r-- | generic/tclRegexp.c | 341 |
1 files changed, 193 insertions, 148 deletions
diff --git a/generic/tclRegexp.c b/generic/tclRegexp.c index 98458a6..6348e4a 100644 --- a/generic/tclRegexp.c +++ b/generic/tclRegexp.c @@ -9,8 +9,6 @@ * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * RCS: @(#) $Id: tclRegexp.c,v 1.20 2005/07/21 14:38:51 dkf Exp $ */ #include "tclInt.h" @@ -55,8 +53,8 @@ * * *** NOTE: this code has been altered slightly for use in Tcl: *** * *** 1. Names have been changed, e.g. from re_comp to *** - * *** TclRegComp, to avoid clashes with other *** - * *** regexp implementations used by applications. *** + * *** TclRegComp, to avoid clashes with other *** + * *** regexp implementations used by applications. *** */ /* @@ -85,25 +83,24 @@ static Tcl_ThreadDataKey dataKey; * Declarations for functions used only in this file. */ -static TclRegexp * CompileRegexp _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *pattern, int length, int flags)); -static void DupRegexpInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, - Tcl_Obj *copyPtr)); -static void FinalizeRegexp _ANSI_ARGS_((ClientData clientData)); -static void FreeRegexp _ANSI_ARGS_((TclRegexp *regexpPtr)); -static void FreeRegexpInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr)); -static int RegExpExecUniChar _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_RegExp re, CONST Tcl_UniChar *uniString, - int numChars, int nmatches, int flags)); -static int SetRegexpFromAny _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr)); +static TclRegexp * CompileRegexp(Tcl_Interp *interp, const char *pattern, + int length, int flags); +static void DupRegexpInternalRep(Tcl_Obj *srcPtr, + Tcl_Obj *copyPtr); +static void FinalizeRegexp(ClientData clientData); +static void FreeRegexp(TclRegexp *regexpPtr); +static void FreeRegexpInternalRep(Tcl_Obj *objPtr); +static int RegExpExecUniChar(Tcl_Interp *interp, Tcl_RegExp re, + const Tcl_UniChar *uniString, int numChars, + int nmatches, int flags); +static int SetRegexpFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); /* * The regular expression Tcl object type. This serves as a cache of the * compiled form of the regular expression. */ -Tcl_ObjType tclRegexpType = { +const Tcl_ObjType tclRegexpType = { "regexp", /* name */ FreeRegexpInternalRep, /* freeIntRepProc */ DupRegexpInternalRep, /* dupIntRepProc */ @@ -134,10 +131,10 @@ Tcl_ObjType tclRegexpType = { */ Tcl_RegExp -Tcl_RegExpCompile(interp, pattern) - Tcl_Interp *interp; /* For use in error reporting and to access +Tcl_RegExpCompile( + Tcl_Interp *interp, /* For use in error reporting and to access * the interp regexp cache. */ - CONST char *pattern; /* String for which to produce compiled + const char *pattern) /* String for which to produce compiled * regular expression. */ { return (Tcl_RegExp) CompileRegexp(interp, pattern, (int) strlen(pattern), @@ -165,20 +162,20 @@ Tcl_RegExpCompile(interp, pattern) */ int -Tcl_RegExpExec(interp, re, text, start) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - Tcl_RegExp re; /* Compiled regular expression; must have been +Tcl_RegExpExec( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tcl_RegExp re, /* Compiled regular expression; must have been * returned by previous call to * Tcl_GetRegExpFromObj. */ - CONST char *text; /* Text against which to match re. */ - CONST char *start; /* If text is part of a larger string, this + const char *text, /* Text against which to match re. */ + const char *start) /* If text is part of a larger string, this * identifies beginning of larger string, so * that "^" won't match. */ { int flags, result, numChars; - TclRegexp *regexp = (TclRegexp *)re; + TclRegexp *regexp = (TclRegexp *) re; Tcl_DString ds; - CONST Tcl_UniChar *ustr; + const Tcl_UniChar *ustr; /* * If the starting point is offset from the beginning of the buffer, then @@ -232,19 +229,19 @@ Tcl_RegExpExec(interp, re, text, start) */ void -Tcl_RegExpRange(re, index, startPtr, endPtr) - Tcl_RegExp re; /* Compiled regular expression that has been +Tcl_RegExpRange( + Tcl_RegExp re, /* Compiled regular expression that has been * passed to Tcl_RegExpExec. */ - int index; /* 0 means give the range of the entire match, + int index, /* 0 means give the range of the entire match, * > 0 means give the range of a matching * subrange. */ - CONST char **startPtr; /* Store address of first character in + const char **startPtr, /* Store address of first character in * (sub-)range here. */ - CONST char **endPtr; /* Store address of character just after last + const char **endPtr) /* Store address of character just after last * in (sub-)range here. */ { TclRegexp *regexpPtr = (TclRegexp *) re; - CONST char *string; + const char *string; if ((size_t) index > regexpPtr->re.re_nsub) { *startPtr = *endPtr = NULL; @@ -252,7 +249,7 @@ Tcl_RegExpRange(re, index, startPtr, endPtr) *startPtr = *endPtr = NULL; } else { if (regexpPtr->objPtr) { - string = Tcl_GetString(regexpPtr->objPtr); + string = TclGetString(regexpPtr->objPtr); } else { string = regexpPtr->string; } @@ -282,17 +279,17 @@ Tcl_RegExpRange(re, index, startPtr, endPtr) */ static int -RegExpExecUniChar(interp, re, wString, numChars, nmatches, flags) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - Tcl_RegExp re; /* Compiled regular expression; returned by a +RegExpExecUniChar( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tcl_RegExp re, /* Compiled regular expression; returned by a * previous call to Tcl_GetRegExpFromObj */ - CONST Tcl_UniChar *wString; /* String against which to match re. */ - int numChars; /* Length of Tcl_UniChar string (must be + const Tcl_UniChar *wString, /* String against which to match re. */ + int numChars, /* Length of Tcl_UniChar string (must be * >=0). */ - int nmatches; /* How many subexpression matches (counting + int nmatches, /* How many subexpression matches (counting * the whole match as subexpression 0) are of * interest. -1 means "don't know". */ - int flags; /* Regular expression flags. */ + int flags) /* Regular expression flags. */ { int status; TclRegexp *regexpPtr = (TclRegexp *) re; @@ -344,16 +341,16 @@ RegExpExecUniChar(interp, re, wString, numChars, nmatches, flags) */ void -TclRegExpRangeUniChar(re, index, startPtr, endPtr) - Tcl_RegExp re; /* Compiled regular expression that has been +TclRegExpRangeUniChar( + Tcl_RegExp re, /* Compiled regular expression that has been * passed to Tcl_RegExpExec. */ - int index; /* 0 means give the range of the entire match, + int index, /* 0 means give the range of the entire match, * > 0 means give the range of a matching * subrange, -1 means the range of the * rm_extend field. */ - int *startPtr; /* Store address of first character in + int *startPtr, /* Store address of first character in * (sub-)range here. */ - int *endPtr; /* Store address of character just after last + int *endPtr) /* Store address of character just after last * in (sub-)range here. */ { TclRegexp *regexpPtr = (TclRegexp *) re; @@ -389,14 +386,13 @@ TclRegExpRangeUniChar(re, index, startPtr, endPtr) */ int -Tcl_RegExpMatch(interp, text, pattern) - Tcl_Interp *interp; /* Used for error reporting. May be NULL. */ - CONST char *text; /* Text to search for pattern matches. */ - CONST char *pattern; /* Regular expression to match against text. */ +Tcl_RegExpMatch( + Tcl_Interp *interp, /* Used for error reporting. May be NULL. */ + const char *text, /* Text to search for pattern matches. */ + const char *pattern) /* Regular expression to match against text. */ { - Tcl_RegExp re; + Tcl_RegExp re = Tcl_RegExpCompile(interp, pattern); - re = Tcl_RegExpCompile(interp, pattern); if (re == NULL) { return -1; } @@ -422,22 +418,44 @@ Tcl_RegExpMatch(interp, text, pattern) */ int -Tcl_RegExpExecObj(interp, re, textObj, offset, nmatches, flags) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - Tcl_RegExp re; /* Compiled regular expression; must have been +Tcl_RegExpExecObj( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tcl_RegExp re, /* Compiled regular expression; must have been * returned by previous call to * Tcl_GetRegExpFromObj. */ - Tcl_Obj *textObj; /* Text against which to match re. */ - int offset; /* Character index that marks where matching + Tcl_Obj *textObj, /* Text against which to match re. */ + int offset, /* Character index that marks where matching * should begin. */ - int nmatches; /* How many subexpression matches (counting + int nmatches, /* How many subexpression matches (counting * the whole match as subexpression 0) are of * interest. -1 means all of them. */ - int flags; /* Regular expression execution flags. */ + int flags) /* Regular expression execution flags. */ { TclRegexp *regexpPtr = (TclRegexp *) re; Tcl_UniChar *udata; int length; + int reflags = regexpPtr->flags; +#define TCL_REG_GLOBOK_FLAGS \ + (TCL_REG_ADVANCED | TCL_REG_NOSUB | TCL_REG_NOCASE) + + /* + * Take advantage of the equivalent glob pattern, if one exists. + * This is possible based only on the right mix of incoming flags (0) + * and regexp compile flags. + */ + if ((offset == 0) && (nmatches == 0) && (flags == 0) + && !(reflags & ~TCL_REG_GLOBOK_FLAGS) + && (regexpPtr->globObjPtr != NULL)) { + int nocase = (reflags & TCL_REG_NOCASE) ? TCL_MATCH_NOCASE : 0; + + /* + * Pass to TclStringMatchObj for obj-specific handling. + * XXX: Currently doesn't take advantage of exact-ness that + * XXX: TclReToGlob tells us about + */ + + return TclStringMatchObj(textObj, regexpPtr->globObjPtr, nocase); + } /* * Save the target object so we can extract strings from it later. @@ -476,10 +494,10 @@ Tcl_RegExpExecObj(interp, re, textObj, offset, nmatches, flags) */ int -Tcl_RegExpMatchObj(interp, textObj, patternObj) - Tcl_Interp *interp; /* Used for error reporting. May be NULL. */ - Tcl_Obj *textObj; /* Object containing the String to search. */ - Tcl_Obj *patternObj; /* Regular expression to match against +Tcl_RegExpMatchObj( + Tcl_Interp *interp, /* Used for error reporting. May be NULL. */ + Tcl_Obj *textObj, /* Object containing the String to search. */ + Tcl_Obj *patternObj) /* Regular expression to match against * string. */ { Tcl_RegExp re; @@ -510,9 +528,9 @@ Tcl_RegExpMatchObj(interp, textObj, patternObj) */ void -Tcl_RegExpGetInfo(regexp, infoPtr) - Tcl_RegExp regexp; /* Pattern from which to get subexpressions. */ - Tcl_RegExpInfo *infoPtr; /* Match information is stored here. */ +Tcl_RegExpGetInfo( + Tcl_RegExp regexp, /* Pattern from which to get subexpressions. */ + Tcl_RegExpInfo *infoPtr) /* Match information is stored here. */ { TclRegexp *regexpPtr = (TclRegexp *) regexp; @@ -542,28 +560,28 @@ Tcl_RegExpGetInfo(regexp, infoPtr) */ Tcl_RegExp -Tcl_GetRegExpFromObj(interp, objPtr, flags) - Tcl_Interp *interp; /* For use in error reporting, and to access +Tcl_GetRegExpFromObj( + Tcl_Interp *interp, /* For use in error reporting, and to access * the interp regexp cache. */ - Tcl_Obj *objPtr; /* Object whose string rep contains regular + Tcl_Obj *objPtr, /* Object whose string rep contains regular * expression pattern. Internal rep will be * changed to compiled form of this regular * expression. */ - int flags; /* Regular expression compilation flags. */ + int flags) /* Regular expression compilation flags. */ { int length; TclRegexp *regexpPtr; - char *pattern; + const char *pattern; /* * This is OK because we only actually interpret this value properly as a * TclRegexp* when the type is tclRegexpType. */ - regexpPtr = (TclRegexp *) objPtr->internalRep.otherValuePtr; + regexpPtr = objPtr->internalRep.twoPtrValue.ptr1; if ((objPtr->typePtr != &tclRegexpType) || (regexpPtr->flags != flags)) { - pattern = Tcl_GetStringFromObj(objPtr, &length); + pattern = TclGetStringFromObj(objPtr, &length); regexpPtr = CompileRegexp(interp, pattern, length, flags); if (regexpPtr == NULL) { @@ -583,7 +601,7 @@ Tcl_GetRegExpFromObj(interp, objPtr, flags) */ TclFreeIntRep(objPtr); - objPtr->internalRep.otherValuePtr = (VOID *) regexpPtr; + objPtr->internalRep.twoPtrValue.ptr1 = regexpPtr; objPtr->typePtr = &tclRegexpType; } return (Tcl_RegExp) regexpPtr; @@ -609,16 +627,16 @@ Tcl_GetRegExpFromObj(interp, objPtr, flags) */ int -TclRegAbout(interp, re) - Tcl_Interp *interp; /* For use in variable assignment. */ - Tcl_RegExp re; /* The compiled regular expression. */ +TclRegAbout( + Tcl_Interp *interp, /* For use in variable assignment. */ + Tcl_RegExp re) /* The compiled regular expression. */ { - TclRegexp *regexpPtr = (TclRegexp *)re; - char buf[TCL_INTEGER_SPACE]; - static struct infoname { + TclRegexp *regexpPtr = (TclRegexp *) re; + struct infoname { int bit; - char *text; - } infonames[] = { + const char *text; + }; + static const struct infoname infonames[] = { {REG_UBACKREF, "REG_UBACKREF"}, {REG_ULOOKAHEAD, "REG_ULOOKAHEAD"}, {REG_UBOUNDS, "REG_UBOUNDS"}, @@ -633,38 +651,42 @@ TclRegAbout(interp, re) {REG_UEMPTYMATCH, "REG_UEMPTYMATCH"}, {REG_UIMPOSSIBLE, "REG_UIMPOSSIBLE"}, {REG_USHORTEST, "REG_USHORTEST"}, - {0, ""} + {0, NULL} }; - struct infoname *inf; - int n; + const struct infoname *inf; + Tcl_Obj *infoObj, *resultObj; + + /* + * The reset here guarantees that the interpreter result is empty and + * unshared. This means that we can use Tcl_ListObjAppendElement on the + * result object quite safely. + */ Tcl_ResetResult(interp); - sprintf(buf, "%u", (unsigned)(regexpPtr->re.re_nsub)); - Tcl_AppendElement(interp, buf); + /* + * Assume that there will never be more than INT_MAX subexpressions. This + * is a pretty reasonable assumption; the RE engine doesn't scale _that_ + * well and Tcl has other limits that constrain things as well... + */ + + resultObj = Tcl_NewObj(); + Tcl_ListObjAppendElement(NULL, resultObj, + Tcl_NewIntObj((int) regexpPtr->re.re_nsub)); /* - * Must count bits before generating list, because we must know whether {} - * are needed before we start appending names. + * Now append a list of all the bit-flags set for the RE. */ - n = 0; - for (inf = infonames; inf->bit != 0; inf++) { - if (regexpPtr->re.re_info&inf->bit) { - n++; + TclNewObj(infoObj); + for (inf=infonames ; inf->bit != 0 ; inf++) { + if (regexpPtr->re.re_info & inf->bit) { + Tcl_ListObjAppendElement(NULL, infoObj, + Tcl_NewStringObj(inf->text, -1)); } } - if (n != 1) { - Tcl_AppendResult(interp, " {", NULL); - } - for (inf = infonames; inf->bit != 0; inf++) { - if (regexpPtr->re.re_info&inf->bit) { - Tcl_AppendElement(interp, inf->text); - } - } - if (n != 1) { - Tcl_AppendResult(interp, "}", NULL); - } + Tcl_ListObjAppendElement(NULL, resultObj, infoObj); + Tcl_SetObjResult(interp, resultObj); return 0; } @@ -686,23 +708,23 @@ TclRegAbout(interp, re) */ void -TclRegError(interp, msg, status) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - CONST char *msg; /* Message to prepend to error. */ - int status; /* Status code to report. */ +TclRegError( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + const char *msg, /* Message to prepend to error. */ + int status) /* Status code to report. */ { char buf[100]; /* ample in practice */ - char cbuf[100]; /* lots in practice */ + char cbuf[TCL_INTEGER_SPACE]; size_t n; - char *p; + const char *p; Tcl_ResetResult(interp); - n = TclReError(status, (regex_t *)NULL, buf, sizeof(buf)); + n = TclReError(status, NULL, buf, sizeof(buf)); p = (n > sizeof(buf)) ? "..." : ""; - Tcl_AppendResult(interp, msg, buf, p, NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s%s%s", msg, buf, p)); sprintf(cbuf, "%d", status); - (VOID) TclReError(REG_ITOA, (regex_t *)NULL, cbuf, sizeof(cbuf)); + (void) TclReError(REG_ITOA, NULL, cbuf, sizeof(cbuf)); Tcl_SetErrorCode(interp, "REGEXP", cbuf, buf, NULL); } @@ -724,10 +746,10 @@ TclRegError(interp, msg, status) */ static void -FreeRegexpInternalRep(objPtr) - Tcl_Obj *objPtr; /* Regexp object with internal rep to free. */ +FreeRegexpInternalRep( + Tcl_Obj *objPtr) /* Regexp object with internal rep to free. */ { - TclRegexp *regexpRepPtr = (TclRegexp *) objPtr->internalRep.otherValuePtr; + TclRegexp *regexpRepPtr = objPtr->internalRep.twoPtrValue.ptr1; /* * If this is the last reference to the regexp, free it. @@ -736,6 +758,7 @@ FreeRegexpInternalRep(objPtr) if (--(regexpRepPtr->refCount) <= 0) { FreeRegexp(regexpRepPtr); } + objPtr->typePtr = NULL; } /* @@ -756,14 +779,14 @@ FreeRegexpInternalRep(objPtr) */ static void -DupRegexpInternalRep(srcPtr, copyPtr) - Tcl_Obj *srcPtr; /* Object with internal rep to copy. */ - Tcl_Obj *copyPtr; /* Object with internal rep to set. */ +DupRegexpInternalRep( + Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ + Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { - TclRegexp *regexpPtr = (TclRegexp *) srcPtr->internalRep.otherValuePtr; + TclRegexp *regexpPtr = srcPtr->internalRep.twoPtrValue.ptr1; regexpPtr->refCount++; - copyPtr->internalRep.otherValuePtr = srcPtr->internalRep.otherValuePtr; + copyPtr->internalRep.twoPtrValue.ptr1 = srcPtr->internalRep.twoPtrValue.ptr1; copyPtr->typePtr = &tclRegexpType; } @@ -788,9 +811,9 @@ DupRegexpInternalRep(srcPtr, copyPtr) */ static int -SetRegexpFromAny(interp, objPtr) - Tcl_Interp *interp; /* Used for error reporting if not NULL. */ - Tcl_Obj *objPtr; /* The object to convert. */ +SetRegexpFromAny( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tcl_Obj *objPtr) /* The object to convert. */ { if (Tcl_GetRegExpFromObj(interp, objPtr, REG_ADVANCED) == NULL) { return TCL_ERROR; @@ -821,17 +844,16 @@ SetRegexpFromAny(interp, objPtr) */ static TclRegexp * -CompileRegexp(interp, string, length, flags) - Tcl_Interp *interp; /* Used for error reporting if not NULL. */ - CONST char *string; /* The regexp to compile (UTF-8). */ - int length; /* The length of the string in bytes. */ - int flags; /* Compilation flags. */ +CompileRegexp( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + const char *string, /* The regexp to compile (UTF-8). */ + int length, /* The length of the string in bytes. */ + int flags) /* Compilation flags. */ { TclRegexp *regexpPtr; - CONST Tcl_UniChar *uniString; - int numChars; + const Tcl_UniChar *uniString; + int numChars, status, i, exact; Tcl_DString stringBuf; - int status, i; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!tsdPtr->initialized) { @@ -883,7 +905,7 @@ CompileRegexp(interp, string, length, flags) * This is a new expression, so compile it and add it to the cache. */ - regexpPtr = (TclRegexp *) ckalloc(sizeof(TclRegexp)); + regexpPtr = ckalloc(sizeof(TclRegexp)); regexpPtr->objPtr = NULL; regexpPtr->string = NULL; regexpPtr->details.rm_extend.rm_so = -1; @@ -910,22 +932,34 @@ CompileRegexp(interp, string, length, flags) * Clean up and report errors in the interpreter, if possible. */ - ckfree((char *)regexpPtr); + ckfree(regexpPtr); if (interp) { TclRegError(interp, - "couldn't compile regular expression pattern: ", - status); + "couldn't compile regular expression pattern: ", status); } return NULL; } /* + * Convert RE to a glob pattern equivalent, if any, and cache it. If this + * is not possible, then globObjPtr will be NULL. This is used by + * Tcl_RegExpExecObj to optionally do a fast match (avoids RE engine). + */ + + if (TclReToGlob(NULL, string, length, &stringBuf, &exact) == TCL_OK) { + regexpPtr->globObjPtr = TclDStringToObj(&stringBuf); + Tcl_IncrRefCount(regexpPtr->globObjPtr); + } else { + regexpPtr->globObjPtr = NULL; + } + + /* * Allocate enough space for all of the subexpressions, plus one extra for * the entire pattern. */ - regexpPtr->matches = (regmatch_t *) ckalloc( - sizeof(regmatch_t) * (regexpPtr->re.re_nsub + 1)); + regexpPtr->matches = + ckalloc(sizeof(regmatch_t) * (regexpPtr->re.re_nsub + 1)); /* * Initialize the refcount to one initially, since it is in the cache. @@ -940,6 +974,7 @@ CompileRegexp(interp, string, length, flags) if (tsdPtr->patterns[NUM_REGEXPS-1] != NULL) { TclRegexp *oldRegexpPtr = tsdPtr->regexps[NUM_REGEXPS-1]; + if (--(oldRegexpPtr->refCount) <= 0) { FreeRegexp(oldRegexpPtr); } @@ -950,8 +985,8 @@ CompileRegexp(interp, string, length, flags) tsdPtr->patLengths[i+1] = tsdPtr->patLengths[i]; tsdPtr->regexps[i+1] = tsdPtr->regexps[i]; } - tsdPtr->patterns[0] = (char *) ckalloc((unsigned) (length+1)); - strcpy(tsdPtr->patterns[0], string); + tsdPtr->patterns[0] = ckalloc(length + 1); + memcpy(tsdPtr->patterns[0], string, (unsigned) length + 1); tsdPtr->patLengths[0] = length; tsdPtr->regexps[0] = regexpPtr; @@ -975,14 +1010,17 @@ CompileRegexp(interp, string, length, flags) */ static void -FreeRegexp(regexpPtr) - TclRegexp *regexpPtr; /* Compiled regular expression to free. */ +FreeRegexp( + TclRegexp *regexpPtr) /* Compiled regular expression to free. */ { TclReFree(®expPtr->re); + if (regexpPtr->globObjPtr) { + TclDecrRefCount(regexpPtr->globObjPtr); + } if (regexpPtr->matches) { - ckfree((char *) regexpPtr->matches); + ckfree(regexpPtr->matches); } - ckfree((char *) regexpPtr); + ckfree(regexpPtr); } /* @@ -990,8 +1028,7 @@ FreeRegexp(regexpPtr) * * FinalizeRegexp -- * - * Release the storage associated with the per-thread regexp - * cache. + * Release the storage associated with the per-thread regexp cache. * * Results: * None. @@ -1003,8 +1040,8 @@ FreeRegexp(regexpPtr) */ static void -FinalizeRegexp(clientData) - ClientData clientData; /* Not used. */ +FinalizeRegexp( + ClientData clientData) /* Not used. */ { int i; TclRegexp *regexpPtr; @@ -1016,7 +1053,15 @@ FinalizeRegexp(clientData) FreeRegexp(regexpPtr); } ckfree(tsdPtr->patterns[i]); + tsdPtr->patterns[i] = NULL; } + + /* + * We may find ourselves reinitialized if another finalization routine + * invokes regexps. + */ + + tsdPtr->initialized = 0; } /* |