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