diff options
Diffstat (limited to 'generic/tclStubLib.c')
| -rw-r--r-- | generic/tclStubLib.c | 151 |
1 files changed, 82 insertions, 69 deletions
diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c index 4cffcac..31fc865 100644 --- a/generic/tclStubLib.c +++ b/generic/tclStubLib.c @@ -11,68 +11,24 @@ * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -/* - * We need to ensure that we use the stub macros so that this file contains no - * references to any of the stub functions. This will make it possible to - * build an extension that references Tcl_InitStubs but doesn't end up - * including the rest of the stub functions. - */ - -#define USE_TCL_STUBS - #include "tclInt.h" -MODULE_SCOPE const TclStubs *tclStubsPtr; -MODULE_SCOPE const TclPlatStubs *tclPlatStubsPtr; -MODULE_SCOPE const TclIntStubs *tclIntStubsPtr; -MODULE_SCOPE const TclIntPlatStubs *tclIntPlatStubsPtr; - -const TclStubs *tclStubsPtr = NULL; -const TclPlatStubs *tclPlatStubsPtr = NULL; -const TclIntStubs *tclIntStubsPtr = NULL; -const TclIntPlatStubs *tclIntPlatStubsPtr = NULL; +TclStubs *tclStubsPtr = NULL; +TclPlatStubs *tclPlatStubsPtr = NULL; +TclIntStubs *tclIntStubsPtr = NULL; +TclIntPlatStubs *tclIntPlatStubsPtr = NULL; +TclTomMathStubs* tclTomMathStubsPtr = NULL; -static const TclStubs * -HasStubSupport( - Tcl_Interp *interp, - int magic) -{ - Interp *iPtr = (Interp *) interp; - - if (!iPtr->stubTable) { - /* No stub table at all? Nothing we can do. */ - return NULL; - } - if (iPtr->stubTable->magic != magic) { - /* - * The iPtr->stubTable entry from Tcl_Interp and the - * Tcl_NewStringObj() and Tcl_SetObjResult() entries - * in the stub table cannot change in Tcl 9 compared - * to Tcl 8.x. Otherwise the lines below won't work. - * TODO: add a test case for that. - */ - iPtr->stubTable->tcl_SetObjResult(interp, - iPtr->stubTable->tcl_NewStringObj( - "This extension is compiled for Tcl 9.x", - TCL_STRLEN)); - return NULL; - } - return iPtr->stubTable; -} - /* - * Use our own isdigit to avoid linking to libc on windows + * Use our own ISDIGIT to avoid linking to libc on windows */ -static int isDigit(const int c) -{ - return (c >= '0' && c <= '9'); -} +#define ISDIGIT(c) (((unsigned)((c)-'0')) <= 9) /* *---------------------------------------------------------------------- * - * TclInitStubs -- + * Tcl_InitStubs -- * * Tries to initialise the stub table pointers and ensures that the * correct version of Tcl is loaded. @@ -86,16 +42,17 @@ static int isDigit(const int c) * *---------------------------------------------------------------------- */ - -MODULE_SCOPE const char * -TclInitStubs( +#undef Tcl_InitStubs +CONST char * +Tcl_InitStubs( Tcl_Interp *interp, - const char *version, - int exact, - int magic) + CONST char *version, + int exact) { - const char *actualVersion = NULL; + Interp *iPtr = (Interp *) interp; + CONST char *actualVersion = NULL; ClientData pkgData = NULL; + TclStubs *stubsPtr = iPtr->stubTable; /* * We can't optimize this check by caching tclStubsPtr because that @@ -103,42 +60,43 @@ TclInitStubs( * times. [Bug 615304] */ - tclStubsPtr = HasStubSupport(interp, magic); - if (!tclStubsPtr) { + if (!stubsPtr || (stubsPtr->magic != TCL_STUB_MAGIC)) { + iPtr->result = "interpreter uses an incompatible stubs mechanism"; + iPtr->freeProc = TCL_STATIC; return NULL; } - actualVersion = Tcl_PkgRequireEx(interp, "Tcl", version, 0, &pkgData); + actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 0, &pkgData); if (actualVersion == NULL) { return NULL; } if (exact) { - const char *p = version; + CONST char *p = version; int count = 0; while (*p) { - count += !isDigit(*p++); + count += !ISDIGIT(*p++); } if (count == 1) { - const char *q = actualVersion; + CONST char *q = actualVersion; p = version; while (*p && (*p == *q)) { p++; q++; } - if (*p) { + if (*p || ISDIGIT(*q)) { /* Construct error message */ - Tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); + stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); return NULL; } } else { - actualVersion = Tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); + actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); if (actualVersion == NULL) { return NULL; } } } - tclStubsPtr = (TclStubs *) pkgData; + tclStubsPtr = (TclStubs *)pkgData; if (tclStubsPtr->hooks) { tclPlatStubsPtr = tclStubsPtr->hooks->tclPlatStubs; @@ -154,6 +112,61 @@ TclInitStubs( } /* + *---------------------------------------------------------------------- + * + * TclTomMathInitStubs -- + * + * Initializes the Stubs table for Tcl's subset of libtommath + * + * Results: + * Returns a standard Tcl result. + * + * This procedure should not be called directly, but rather through + * the TclTomMath_InitStubs macro, to insure that the Stubs table + * matches the header files used in compilation. + * + *---------------------------------------------------------------------- + */ + +#undef TclTomMathInitializeStubs + +CONST char* +TclTomMathInitializeStubs( + Tcl_Interp* interp, /* Tcl interpreter */ + CONST char* version, /* Tcl version needed */ + int epoch, /* Stubs table epoch from the header files */ + int revision /* Stubs table revision number from the + * header files */ +) { + int exact = 0; + const char* packageName = "tcl::tommath"; + const char* errMsg = NULL; + ClientData pkgClientData = NULL; + const char* actualVersion = + tclStubsPtr->tcl_PkgRequireEx(interp, packageName, version, exact, &pkgClientData); + TclTomMathStubs* stubsPtr = (TclTomMathStubs*) pkgClientData; + if (actualVersion == NULL) { + return NULL; + } + if (pkgClientData == NULL) { + errMsg = "missing stub table pointer"; + } else if ((stubsPtr->tclBN_epoch)() != epoch) { + errMsg = "epoch number mismatch"; + } else if ((stubsPtr->tclBN_revision)() != revision) { + errMsg = "requires a later revision"; + } else { + tclTomMathStubsPtr = stubsPtr; + return actualVersion; + } + tclStubsPtr->tcl_ResetResult(interp); + tclStubsPtr->tcl_AppendResult(interp, "error loading ", packageName, + " (requested version ", version, + ", actual version ", actualVersion, + "): ", errMsg, NULL); + return NULL; +} + +/* * Local Variables: * mode: c * c-basic-offset: 4 |
