summaryrefslogtreecommitdiffstats
path: root/generic/tclStubLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclStubLib.c')
-rw-r--r--generic/tclStubLib.c96
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;