Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -823,11 +823,11 @@ #if defined(FOSSIL_ENABLE_SSL) fossil_print("SSL (%s)\n", OPENSSL_VERSION_TEXT); #endif #if defined(FOSSIL_ENABLE_TCL) Th_FossilInit(TH_INIT_DEFAULT | TH_INIT_FORCE_TCL); - rc = Th_Eval(g.interp, 0, "tclEval {info patchlevel}", -1); + rc = Th_Eval(g.interp, 0, "tclInvoke info patchlevel", -1); zRc = Th_ReturnCodeName(rc, 0); fossil_print("TCL (Tcl %s, loaded %s: %s)\n", TCL_PATCH_LEVEL, zRc, Th_GetResult(g.interp, 0) ); #endif Index: src/th_tcl.c ================================================================== --- src/th_tcl.c +++ src/th_tcl.c @@ -29,27 +29,28 @@ ** Has the decision about whether or not to use Tcl_EvalObjv already been made ** via the Makefile? */ #if !defined(USE_TCL_EVALOBJV) /* -** Are we being compiled against Tcl 8.6b1 or b2? This check is [mostly] +** Are we being compiled against Tcl 8.4, 8.6b1 or b2? This check is [mostly] ** wrong for at the following reason: ** ** 1. Technically, this check is completely useless when the stubs mechanism ** is in use. In that case, a runtime version check would be required and ** that has not been implemented. ** -** However, if a particular user compiles and runs against Tcl 8.6b1 or b2, +** However, if a particular user compiles and runs against Tcl 8.4, 8.6b1 or b2, ** this will cause a fallback to using the "conservative" method of directly ** invoking a Tcl command. In that case, potential crashes will be avoided if -** the user just so happened to compile or run against Tcl 8.6b1 or b2. +** the user just so happened to compile or run against Tcl 8.4, 8.6b1 or b2. */ -#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION == 6) && \ +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 5) || (TCL_MINOR_VERSION == 6) && \ (TCL_RELEASE_LEVEL == TCL_BETA_RELEASE) && (TCL_RELEASE_SERIAL < 3) /* ** Workaround NRE-specific issue in Tcl_EvalObjCmd (SF bug #3399564) by using -** Tcl_EvalObjv instead of invoking the objProc directly. +** Tcl_EvalObjv instead of invoking the objProc directly. In addition, Tcl 8.4 +** doesn't have the function Tcl_GetCommandFromObj (see TIP #139) */ # define USE_TCL_EVALOBJV (1) #else /* ** We should be able to safely use Tcl_GetCommandInfoFromToken, when the need @@ -443,20 +444,20 @@ int argc, const char **argv, int *argl ){ Tcl_Interp *tclInterp; -#if !defined(USE_TCL_EVALOBJV) || !USE_TCL_EVALOBJV +#if !USE_TCL_EVALOBJV Tcl_Command command; Tcl_CmdInfo cmdInfo; -#endif /* !defined(USE_TCL_EVALOBJV) || !USE_TCL_EVALOBJV */ +#endif /* !USE_TCL_EVALOBJV */ int rc = TH_OK; int nResult; const char *zResult; -#if !defined(USE_TCL_EVALOBJV) || !USE_TCL_EVALOBJV +#if !USE_TCL_EVALOBJV Tcl_Obj *objPtr; -#endif /* !defined(USE_TCL_EVALOBJV) || !USE_TCL_EVALOBJV */ +#endif /* !USE_TCL_EVALOBJV */ USE_ARGV_TO_OBJV(); if( createTclInterp(interp, ctx)!=TH_OK ){ return TH_ERROR; } @@ -471,11 +472,11 @@ rc = notifyPreOrPostEval(0, interp, ctx, argc, argv, argl, rc); if( rc!=TH_OK ){ return rc; } Tcl_Preserve((ClientData)tclInterp); -#if !defined(USE_TCL_EVALOBJV) || !USE_TCL_EVALOBJV +#if !USE_TCL_EVALOBJV objPtr = Tcl_NewStringObj(argv[1], argl[1]); Tcl_IncrRefCount(objPtr); command = Tcl_GetCommandFromObj(tclInterp, objPtr); if( !command || Tcl_GetCommandInfoFromToken(command, &cmdInfo)==0 ){ Th_ErrorMessage(interp, "Tcl command not found:", argv[1], argl[1]); @@ -488,18 +489,18 @@ Tcl_DecrRefCount(objPtr); Tcl_Release((ClientData)tclInterp); return TH_ERROR; } Tcl_DecrRefCount(objPtr); -#endif /* !defined(USE_TCL_EVALOBJV) || !USE_TCL_EVALOBJV */ +#endif /* !USE_TCL_EVALOBJV */ COPY_ARGV_TO_OBJV(); -#if defined(USE_TCL_EVALOBJV) && USE_TCL_EVALOBJV +#if USE_TCL_EVALOBJV rc = Tcl_EvalObjv(tclInterp, objc, objv, 0); #else Tcl_ResetResult(tclInterp); rc = cmdInfo.objProc(cmdInfo.objClientData, tclInterp, objc, objv); -#endif /* defined(USE_TCL_EVALOBJV) && USE_TCL_EVALOBJV */ +#endif /* USE_TCL_EVALOBJV */ FREE_ARGV_TO_OBJV(); zResult = getTclResult(tclInterp, &nResult); Th_SetResult(interp, zResult, nResult); Tcl_Release((ClientData)tclInterp); rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl, rc); @@ -670,14 +671,18 @@ *pxFindExecutable = xFindExecutable; *pxCreateInterp = xCreateInterp; *pxDeleteInterp = xDeleteInterp; return TH_OK; } - } while( --fileName[TCL_MINOR_OFFSET]>'3' ); /* Tcl 8.4+ */ + } while( --fileName[TCL_MINOR_OFFSET]>(USE_TCL_EVALOBJV?'4':'3') ); /* Tcl 8.5+ or 4*/ fileName[TCL_MINOR_OFFSET] = 'x'; Th_ErrorMessage(interp, +#if USE_TCL_EVALOBJV "could not load any supported Tcl 8.6, 8.5, or 8.4 shared library \"", +#else + "could not load any supported Tcl 8.6 or 8.5 shared library \"", +#endif fileName, -1); return TH_ERROR; #else *pLibrary = 0; *pxFindExecutable = Tcl_FindExecutable;