diff options
Diffstat (limited to 'generic/tclStubLib.c')
-rw-r--r-- | generic/tclStubLib.c | 96 |
1 files changed, 65 insertions, 31 deletions
diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c index cadb7b9..6c89562 100644 --- a/generic/tclStubLib.c +++ b/generic/tclStubLib.c @@ -60,57 +60,91 @@ Tcl_InitStubs( ClientData pkgData = NULL; const TclStubs *stubsPtr = iPtr->stubTable; + /* Compatibility with Tcl8. If "exact" has the value 0 or 1, then parameters + * tclversion and magic are not used, so fill in the right Tcl8 values. */ + if ((exact|1) == 1) { + tclversion = "8"; + magic = TCL_STUB_MAGIC; + exact |= (int)sizeof(int); + } /* * We can't optimize this check by caching tclStubsPtr because that * prevents apps from being able to load/unload Tcl dynamically multiple * times. [Bug 615304] */ - if (!stubsPtr || (stubsPtr->magic != TCL_STUB_MAGIC)) { - iPtr->legacyResult = "interpreter uses an incompatible stubs mechanism"; - iPtr->legacyFreeProc = 0; /* TCL_STATIC */ - return NULL; - } - - actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 0, &pkgData); - if (actualVersion == NULL) { + if (!stubsPtr || (stubsPtr->magic != magic)) { + /* This can only be executed in a Tcl < 8.1 interpreter, because + * the magic values are kept the same in later versions. */ + iPtr->objResultPtr = (Tcl_Obj *) + "interpreter uses an incompatible stubs mechanism"; + iPtr->emptyObjPtr = 0; /* TCL_STATIC */ return NULL; } - if (exact&1) { - const char *p = version; - int count = 0; - while (*p) { - count += !ISDIGIT(*p++); + if(iPtr->errorLine == TCL_STUB_MAGIC) { + actualVersion = (const char *)iPtr->objResultPtr; + tclStubsPtr = stubsPtr; + } else { + actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 0, &pkgData); + if (actualVersion == NULL) { + return NULL; } - if (count == 1) { - const char *q = actualVersion; + if (exact&1) { + const char *p = version; + int count = 0; + + while (*p) { + count += !ISDIGIT(*p++); + } + if (count == 1) { + const char *q = actualVersion; - p = version; - while (*p && (*p == *q)) { - p++; q++; + p = version; + while (*p && (*p == *q)) { + p++; q++; + } + if (*p || ISDIGIT(*q)) { + /* Construct error message */ + stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); + return NULL; + } + } else { + actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); + if (actualVersion == NULL) { + return NULL; + } } - if (*p || ISDIGIT(*q)) { - /* Construct error message */ - stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); + } + +#define MASK (4+8+16) /* possible values of sizeof(size_t) */ + + if (stubsPtr->reserved77) { + /* We are running Tcl 8. */ + if ((exact & MASK) != (int)sizeof(int)) { + char msg[32], *p = msg; + + /* Take "version", but strip off everything after '-' */ + while (*version && *version != '-') { + *p++ = *version++; + } + *p = '\0'; + stubsPtr->tcl_AppendResult(interp, "incompatible stub library: have ", + tclversion, ", need ", msg, NULL); return NULL; } + tclStubsPtr = (TclStubs *)pkgData; } else { - actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); - if (actualVersion == NULL) { + /* We are running Tcl 9. */ + if ((exact & MASK) != (int)sizeof(size_t)) { + stubsPtr->tcl_AppendResult(interp, "incompatible stub library: have ", + tclversion, ", need 9", NULL); return NULL; } + tclStubsPtr = stubsPtr; } } - if (stubsPtr->reserved77) { - /* We are running Tcl 8. Do some additional checks here. */ - tclStubsPtr = (TclStubs *)pkgData; - } else { - /* We are running Tcl 9. Do some additional checks here. */ - tclStubsPtr = stubsPtr; - } - if (tclStubsPtr->hooks) { tclPlatStubsPtr = tclStubsPtr->hooks->tclPlatStubs; tclIntStubsPtr = tclStubsPtr->hooks->tclIntStubs; |