Fossil

Check-in [fac10931]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge recent trunk changes into the tkdiff-enhancements branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tkdiff-enhancements
Files: files | file ages | folders
SHA1:fac1093192103b10e6af3c0ad1bf6467c4bab687
User & Date: drh 2013-09-28 10:34:27
Context
2013-10-08
13:11
Add the undocumented --script FILENAME option to all diff operations that make use of the --tk option. The --script FILENAME option is used for testing and debugging only. check-in: cee30a34 user: drh tags: trunk
2013-09-28
10:34
Merge recent trunk changes into the tkdiff-enhancements branch. Closed-Leaf check-in: fac10931 user: drh tags: tkdiff-enhancements
2013-09-27
14:41
The various "diff --tk" commands now take an optional, undocumented option "--script FILENAME" that causes the Tk script to be written into FILENAME rather than to be run. One use for this is to get a copy of the diff script in a form were it can be easily edited and enhanced before being moved back into Fossil. check-in: 326a7364 user: drh tags: tkdiff-enhancements
08:52
Disable use of the unloadTcl function on 64-bit Windows, since the underlying MinGW issue does not manifest there. check-in: ba779faf user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/main.c.

    98     98   struct TclContext {
    99     99     int argc;              /* Number of original (expanded) arguments. */
   100    100     char **argv;           /* Full copy of the original (expanded) arguments. */
   101    101     void *library;         /* The Tcl library module handle. */
   102    102     void *xFindExecutable; /* See tcl_FindExecutableProc in th_tcl.c. */
   103    103     void *xCreateInterp;   /* See tcl_CreateInterpProc in th_tcl.c. */
   104    104     void *xDeleteInterp;   /* See tcl_DeleteInterpProc in th_tcl.c. */
          105  +  void *xFinalize;       /* See tcl_FinalizeProc in th_tcl.c. */
   105    106     Tcl_Interp *interp;    /* The on-demand created Tcl interpreter. */
          107  +  int useObjProc;        /* Non-zero if an objProc can be called directly. */
   106    108     char *setup;           /* The optional Tcl setup script. */
   107    109     void *xPreEval;        /* Optional, called before Tcl_Eval*(). */
   108    110     void *pPreContext;     /* Optional, provided to xPreEval(). */
   109    111     void *xPostEval;       /* Optional, called after Tcl_Eval*(). */
   110    112     void *pPostContext;    /* Optional, provided to xPostEval(). */
   111    113   };
   112    114   #endif
................................................................................
   342    344   }
   343    345   
   344    346   /*
   345    347   ** atexit() handler which frees up "some" of the resources
   346    348   ** used by fossil.
   347    349   */
   348    350   static void fossil_atexit(void) {
   349         -#if defined(_WIN32) && defined(USE_TCL_STUBS)
   350         -  /* If Tcl is compiled on win32 using the latest mingw,
   351         -   * fossil crashes when exiting while Tcl is still loaded.
   352         -   * That's a bug in mingw, see:
   353         -   * <http://comments.gmane.org/gmane.comp.gnu.mingw.user/41724>
   354         -   * but the workaround is not that bad at all: */
   355         -  if( g.tcl.library ){
   356         -    FreeLibrary(g.tcl.library);
   357         -  }
          351  +#if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \
          352  +    defined(USE_TCL_STUBS)
          353  +  /*
          354  +  ** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash
          355  +  ** when exiting while a stubs-enabled Tcl is still loaded.  This is due to
          356  +  ** a bug in MinGW, see:
          357  +  **
          358  +  **     http://comments.gmane.org/gmane.comp.gnu.mingw.user/41724
          359  +  **
          360  +  ** The workaround is to manually unload the loaded Tcl library prior to
          361  +  ** exiting the process.  This issue does not impact 64-bit Windows.
          362  +  */
          363  +  unloadTcl(g.interp, &g.tcl);
   358    364   #endif
   359    365   #ifdef FOSSIL_ENABLE_JSON
   360    366     cson_value_free(g.json.gc.v);
   361    367     memset(&g.json, 0, sizeof(g.json));
   362    368   #endif
   363    369     free(g.zErrMsg);
   364    370     if(g.db){
................................................................................
   533    539   /*
   534    540   ** This procedure runs first.
   535    541   */
   536    542   #if defined(_WIN32) && !defined(BROKEN_MINGW_CMDLINE)
   537    543   int _dowildcard = -1; /* This turns on command-line globbing in MinGW-w64 */
   538    544   int wmain(int argc, wchar_t **argv)
   539    545   #else
          546  +#if defined(_WIN32)
          547  +int _CRT_glob = 0x0001; /* See MinGW bug #2062 */
          548  +#endif
   540    549   int main(int argc, char **argv)
   541    550   #endif
   542    551   {
   543    552     const char *zCmdName = "unknown";
   544    553     int idx;
   545    554     int rc;
   546    555     sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
................................................................................
   821    830       fossil_print("Schema version %s\n", AUX_SCHEMA);
   822    831       fossil_print("zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion());
   823    832   #if defined(FOSSIL_ENABLE_SSL)
   824    833       fossil_print("SSL (%s)\n", OPENSSL_VERSION_TEXT);
   825    834   #endif
   826    835   #if defined(FOSSIL_ENABLE_TCL)
   827    836       Th_FossilInit(TH_INIT_DEFAULT | TH_INIT_FORCE_TCL);
   828         -    rc = Th_Eval(g.interp, 0, "tclEval {info patchlevel}", -1);
          837  +    rc = Th_Eval(g.interp, 0, "tclInvoke info patchlevel", -1);
   829    838       zRc = Th_ReturnCodeName(rc, 0);
   830    839       fossil_print("TCL (Tcl %s, loaded %s: %s)\n",
   831    840         TCL_PATCH_LEVEL, zRc, Th_GetResult(g.interp, 0)
   832    841       );
   833    842   #endif
          843  +#if defined(USE_TCL_STUBS)
          844  +    fossil_print("USE_TCL_STUBS\n");
          845  +#endif
   834    846   #if defined(FOSSIL_ENABLE_TCL_STUBS)
   835    847       fossil_print("TCL_STUBS\n");
   836    848   #endif
   837    849   #if defined(FOSSIL_ENABLE_TCL_PRIVATE_STUBS)
   838    850       fossil_print("TCL_PRIVATE_STUBS\n");
   839    851   #endif
   840    852   #if defined(FOSSIL_ENABLE_JSON)

Changes to src/makemake.tcl.

   405    405   #    This is useful when Tcl has been compiled statically with MinGW.
   406    406   #
   407    407   FOSSIL_TCL_SOURCE = 1
   408    408   
   409    409   #### Check if the workaround for the MinGW command line handling needs to
   410    410   #    be enabled by default.
   411    411   #
   412         -ifndef BROKEN_MINGW_CMDLINE
          412  +ifndef MINGW_IS_32BIT_ONLY
   413    413   ifeq (,$(findstring w64-mingw32,$(PREFIX)))
   414         -BROKEN_MINGW_CMDLINE = 1
          414  +MINGW_IS_32BIT_ONLY = 1
   415    415   endif
   416    416   endif
   417    417   
   418    418   #### The directories where the zlib include and library files are located.
   419    419   #
   420    420   ZINCDIR = $(SRCDIR)/../compat/zlib
   421    421   ZLIBDIR = $(SRCDIR)/../compat/zlib
................................................................................
   499    499   else
   500    500   TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR)
   501    501   RCC += -I$(TCLINCDIR)
   502    502   endif
   503    503   endif
   504    504   
   505    505   # With MinGW command line handling workaround
   506         -ifdef BROKEN_MINGW_CMDLINE
   507         -TCC += -DBROKEN_MINGW_CMDLINE=1
   508         -RCC += -DBROKEN_MINGW_CMDLINE=1
          506  +ifdef MINGW_IS_32BIT_ONLY
          507  +TCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
          508  +RCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
   509    509   endif
   510    510   
   511    511   # With HTTPS support
   512    512   ifdef FOSSIL_ENABLE_SSL
   513    513   TCC += -DFOSSIL_ENABLE_SSL=1
   514    514   RCC += -DFOSSIL_ENABLE_SSL=1
   515    515   endif
................................................................................
   540    540   
   541    541   #### We add the -static option here so that we can build a static
   542    542   #    executable that will run in a chroot jail.
   543    543   #
   544    544   LIB = -static
   545    545   
   546    546   # MinGW: If available, use the Unicode capable runtime startup code.
   547         -ifndef BROKEN_MINGW_CMDLINE
          547  +ifndef MINGW_IS_32BIT_ONLY
   548    548   LIB += -municode
   549    549   endif
   550    550   
   551    551   # OpenSSL: Add the necessary libraries required, if enabled.
   552    552   ifdef FOSSIL_ENABLE_SSL
   553    553   LIB += -lssl -lcrypto -lgdi32
   554    554   endif

Changes to src/style.c.

   173    173         @ gebi("a%d(i+1)").href="%s(aHref[i])";
   174    174       }
   175    175     }
   176    176     for(i=0; i<nFormAction; i++){
   177    177       @ gebi("form%d(i+1)").action="%s(aFormAction[i])";
   178    178     }
   179    179     @ }
   180         -  if( db_get_boolean("auto-hyperlink-mouseover",0) ){
          180  +  if( strglob("*Opera Mini/[1-9]*", P("HTTP_USER_AGENT")) ){
          181  +    /* Special case for Opera Mini, which executes JS server-side */
          182  +    @ var isOperaMini = Object.prototype.toString.call(window.operamini)
          183  +    @                   === "[object OperaMini]";
          184  +    @ if( isOperaMini ){
          185  +    @   setTimeout("setAllHrefs();",%d(nDelay));
          186  +    @ }
          187  +  }else if( db_get_boolean("auto-hyperlink-mouseover",0) ){
   181    188       /* Require mouse movement prior to activating hyperlinks */
   182    189       @ document.getElementsByTagName("body")[0].onmousemove=function(){
   183    190       @   setTimeout("setAllHrefs();",%d(nDelay));
   184    191       @   this.onmousemove = null;
   185    192       @ }
   186    193     }else{
   187    194       /* Active hyperlinks right away */

Changes to src/th.h.

   153    153   /*
   154    154   ** Interfaces to register the language extensions.
   155    155   */
   156    156   int th_register_language(Th_Interp *interp);            /* th_lang.c */
   157    157   int th_register_sqlite(Th_Interp *interp);              /* th_sqlite.c */
   158    158   int th_register_vfs(Th_Interp *interp);                 /* th_vfs.c */
   159    159   int th_register_testvfs(Th_Interp *interp);             /* th_testvfs.c */
          160  +
          161  +#ifdef FOSSIL_ENABLE_TCL
   160    162   int th_register_tcl(Th_Interp *interp, void *pContext); /* th_tcl.c */
          163  +int unloadTcl(Th_Interp *interp, void *pContext);       /* th_tcl.c */
          164  +#endif
   161    165   
   162    166   /*
   163    167   ** General purpose hash table from th_lang.c.
   164    168   */
   165    169   typedef struct Th_Hash      Th_Hash;
   166    170   typedef struct Th_HashEntry Th_HashEntry;
   167    171   struct Th_HashEntry {

Changes to src/th_main.c.

   296    296   ** TH command:     hasfeature STRING
   297    297   **
   298    298   ** Return true if the fossil binary has the given compile-time feature
   299    299   ** enabled. The set of features includes:
   300    300   **
   301    301   ** "ssl"             = FOSSIL_ENABLE_SSL
   302    302   ** "tcl"             = FOSSIL_ENABLE_TCL
          303  +** "useTclStubs"     = USE_TCL_STUBS
   303    304   ** "tclStubs"        = FOSSIL_ENABLE_TCL_STUBS
   304    305   ** "tclPrivateStubs" = FOSSIL_ENABLE_TCL_PRIVATE_STUBS
   305    306   ** "json"            = FOSSIL_ENABLE_JSON
   306    307   ** "markdown"        = FOSSIL_ENABLE_MARKDOWN
   307    308   **
   308    309   */
   309    310   static int hasfeatureCmd(
................................................................................
   327    328       rc = 1;
   328    329     }
   329    330   #endif
   330    331   #if defined(FOSSIL_ENABLE_TCL)
   331    332     else if( 0 == fossil_strnicmp( zArg, "tcl\0", 4 ) ){
   332    333       rc = 1;
   333    334     }
          335  +#endif
          336  +#if defined(USE_TCL_STUBS)
          337  +  else if( 0 == fossil_strnicmp( zArg, "useTclStubs\0", 12 ) ){
          338  +    rc = 1;
          339  +  }
   334    340   #endif
   335    341   #if defined(FOSSIL_ENABLE_TCL_STUBS)
   336    342     else if( 0 == fossil_strnicmp( zArg, "tclStubs\0", 9 ) ){
   337    343       rc = 1;
   338    344     }
   339    345   #endif
   340    346   #if defined(FOSSIL_ENABLE_TCL_PRIVATE_STUBS)

Changes to src/th_tcl.c.

    21     21   #include "config.h"
    22     22   
    23     23   #ifdef FOSSIL_ENABLE_TCL
    24     24   
    25     25   #include "th.h"
    26     26   #include "tcl.h"
    27     27   
    28         -/*
    29         -** Has the decision about whether or not to use Tcl_EvalObjv already been made
    30         -** via the Makefile?
    31         - */
    32         -#if !defined(USE_TCL_EVALOBJV)
    33         -/*
    34         -** Are we being compiled against Tcl 8.6b1 or b2?  This check is [mostly]
    35         -** wrong for at the following reason:
    36         -**
    37         -** 1. Technically, this check is completely useless when the stubs mechanism
    38         -**    is in use.  In that case, a runtime version check would be required and
    39         -**    that has not been implemented.
    40         -**
    41         -** However, if a particular user compiles and runs against Tcl 8.6b1 or b2,
    42         -** this will cause a fallback to using the "conservative" method of directly
    43         -** invoking a Tcl command.  In that case, potential crashes will be avoided if
    44         -** the user just so happened to compile or run against Tcl 8.6b1 or b2.
    45         - */
    46         -#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION == 6) && \
    47         -    (TCL_RELEASE_LEVEL == TCL_BETA_RELEASE) && (TCL_RELEASE_SERIAL < 3)
    48         -/*
    49         -** Workaround NRE-specific issue in Tcl_EvalObjCmd (SF bug #3399564) by using
    50         -** Tcl_EvalObjv instead of invoking the objProc directly.
    51         - */
    52         -#  define USE_TCL_EVALOBJV    (1)
    53         -#else
    54         -/*
    55         -** We should be able to safely use Tcl_GetCommandInfoFromToken, when the need
    56         -** arises, to invoke a specific Tcl command "directly" with some arguments.
    57         - */
    58         -#  define USE_TCL_EVALOBJV    (0)
    59         -#endif /* (TCL_MAJOR_VERSION > 8) ... */
    60         -#endif /* !defined(USE_TCL_EVALOBJV) */
    61         -
    62     28   /*
    63     29   ** These macros are designed to reduce the redundant code required to marshal
    64     30   ** arguments from TH1 to Tcl.
    65         - */
           31  +*/
    66     32   #define USE_ARGV_TO_OBJV() \
    67     33     int objc;                \
    68     34     Tcl_Obj **objv;          \
    69     35     int i;
    70     36   
    71     37   #define COPY_ARGV_TO_OBJV()                                         \
    72     38     objc = argc-1;                                                    \
................................................................................
    81     47       Tcl_DecrRefCount(objv[i-1]); \
    82     48     }                              \
    83     49     ckfree((char *)objv);
    84     50   
    85     51   /*
    86     52   ** Fetch the Tcl interpreter from the specified void pointer, cast to a Tcl
    87     53   ** context.
    88         - */
           54  +*/
    89     55   #define GET_CTX_TCL_INTERP(ctx) \
    90     56     ((struct TclContext *)(ctx))->interp
    91     57   
           58  +/*
           59  +** Fetch the (logically boolean) value from the specified void pointer that
           60  +** indicates whether or not we can/should use direct objProc calls.
           61  +*/
           62  +#define GET_CTX_TCL_USEOBJPROC(ctx) \
           63  +  ((struct TclContext *)(ctx))->useObjProc
           64  +
    92     65   /*
    93     66   ** Define the Tcl shared library name, some exported function names, and some
    94     67   ** cross-platform macros for use with the Tcl stubs mechanism, when enabled.
    95         - */
           68  +*/
    96     69   #if defined(USE_TCL_STUBS)
    97     70   #  if defined(_WIN32)
    98     71   #    define WIN32_LEAN_AND_MEAN
    99     72   #    include <windows.h>
   100     73   #    ifndef TCL_LIBRARY_NAME
   101     74   #      define TCL_LIBRARY_NAME "tcl86.dll\0"
   102     75   #    endif
................................................................................
   142    115   #  endif
   143    116   #  ifndef TCL_CREATEINTERP_NAME
   144    117   #    define TCL_CREATEINTERP_NAME "_Tcl_CreateInterp"
   145    118   #  endif
   146    119   #  ifndef TCL_DELETEINTERP_NAME
   147    120   #    define TCL_DELETEINTERP_NAME "_Tcl_DeleteInterp"
   148    121   #  endif
          122  +#  ifndef TCL_FINALIZE_NAME
          123  +#    define TCL_FINALIZE_NAME "_Tcl_Finalize"
          124  +#  endif
   149    125   #endif /* defined(USE_TCL_STUBS) */
   150    126   
   151    127   /*
   152    128   ** The function types for Tcl_FindExecutable and Tcl_CreateInterp are needed
   153    129   ** when the Tcl library is being loaded dynamically by a stubs-enabled
   154    130   ** application (i.e. the inverse of using a stubs-enabled package).  These are
   155    131   ** the only Tcl API functions that MUST be called prior to being able to call
   156    132   ** Tcl_InitStubs (i.e. because it requires a Tcl interpreter).  For complete
   157    133   ** cleanup if the Tcl stubs initialization fails somehow, the Tcl_DeleteInterp
   158         -** function type is also required.
   159         - */
          134  +** and Tcl_Finalize function types are also required.
          135  +*/
   160    136   typedef void (tcl_FindExecutableProc) (const char * argv0);
   161    137   typedef Tcl_Interp *(tcl_CreateInterpProc) (void);
   162    138   typedef void (tcl_DeleteInterpProc) (Tcl_Interp *interp);
          139  +typedef void (tcl_FinalizeProc) (void);
   163    140   
   164    141   /*
   165    142   ** The function types for the "hook" functions to be called before and after a
   166    143   ** TH1 command makes a call to evaluate a Tcl script.  If the "pre" function
   167    144   ** returns anything but TH_OK, then evaluation of the Tcl script is skipped and
   168    145   ** that value is used as the return code.  If the "post" function returns
   169    146   ** anything other than its rc argument, that will become the new return code
   170    147   ** for the command.
   171         - */
          148  +*/
   172    149   typedef int (tcl_NotifyProc) (
   173    150     void *pContext,    /* The context for this notification. */
   174    151     Th_Interp *interp, /* The TH1 interpreter being used. */
   175    152     void *ctx,         /* The original TH1 command context. */
   176    153     int argc,          /* Number of arguments for the TH1 command. */
   177    154     const char **argv, /* Array of arguments for the TH1 command. */
   178    155     int *argl,         /* Array of lengths for the TH1 command arguments. */
................................................................................
   179    156     int rc             /* Recommended notification return value. */
   180    157   );
   181    158   
   182    159   /*
   183    160   ** Are we using our own private implementation of the Tcl stubs mechanism?  If
   184    161   ** this is enabled, it prevents the user from having to link against the Tcl
   185    162   ** stubs library for the target platform, which may not be readily available.
   186         - */
          163  +*/
   187    164   #if defined(FOSSIL_ENABLE_TCL_PRIVATE_STUBS)
   188    165   /*
   189    166   ** HACK: Using some preprocessor magic and a private static variable, redirect
   190    167   **       the Tcl API calls [found within this file] to the function pointers
   191    168   **       that will be contained in our private Tcl stubs table.  This takes
   192    169   **       advantage of the fact that the Tcl headers always define the Tcl API
   193    170   **       functions in terms of the "tclStubsPtr" variable.
   194         - */
          171  +*/
   195    172   #define tclStubsPtr privateTclStubsPtr
   196    173   static const TclStubs *tclStubsPtr = NULL;
   197    174   
   198    175   /*
   199    176   ** Create a Tcl interpreter structure that mirrors just enough fields to get
   200    177   ** it up and running successfully with our private implementation of the Tcl
   201    178   ** stubs mechanism.
   202         - */
          179  +*/
   203    180   struct PrivateTclInterp {
   204    181     char *result;
   205    182     Tcl_FreeProc *freeProc;
   206    183     int errorLine;
   207    184     const struct TclStubs *stubTable;
   208    185   };
   209    186   
   210    187   /*
   211    188   ** Fossil can now be compiled without linking to the actual Tcl stubs library.
   212    189   ** In that case, this function will be used to perform those steps that would
   213    190   ** normally be performed within the Tcl stubs library.
   214         - */
          191  +*/
   215    192   static int initTclStubs(
   216    193     Th_Interp *interp,
   217    194     Tcl_Interp *tclInterp
   218    195   ){
   219    196     tclStubsPtr = ((struct PrivateTclInterp *)tclInterp)->stubTable;
   220    197     if( !tclStubsPtr || (tclStubsPtr->magic!=TCL_STUB_MAGIC) ){
   221    198       Th_ErrorMessage(interp,
................................................................................
   229    206           "could not initialize Tcl stubs: incompatible version",
   230    207           (const char *)"", 0);
   231    208       return TH_ERROR;
   232    209     }
   233    210     return TH_OK;
   234    211   }
   235    212   #endif /* defined(FOSSIL_ENABLE_TCL_PRIVATE_STUBS) */
          213  +
          214  +/*
          215  +** Is the loaded version of Tcl one where querying and/or calling the objProc
          216  +** for a command does not work for some reason?  The following special cases
          217  +** are currently handled by this function:
          218  +**
          219  +** 1. All versions of Tcl 8.4 have a bug that causes a crash when calling into
          220  +**    the Tcl_GetCommandFromObj function via stubs (i.e. the stubs table entry
          221  +**    is NULL).
          222  +**
          223  +** 2. Various beta builds of Tcl 8.6, namely 1 and 2, have an NRE-specific bug
          224  +**    in Tcl_EvalObjCmd (SF bug #3399564) that cause a panic when calling into
          225  +**    the objProc directly.
          226  +**
          227  +** For both of the above cases, the Tcl_EvalObjv function must be used instead
          228  +** of the more direct route of querying and calling the objProc directly.
          229  +*/
          230  +static int canUseObjProc(){
          231  +  int major = -1, minor = -1, patchLevel = -1, type = -1;
          232  +
          233  +  Tcl_GetVersion(&major, &minor, &patchLevel, &type);
          234  +  if( major<0 || minor<0 || patchLevel<0 || type<0 ){
          235  +    return 0; /* NOTE: Invalid version info, assume bad. */
          236  +  }
          237  +  if( major==8 && minor==4 ){
          238  +    return 0; /* NOTE: Disabled on Tcl 8.4, missing public API. */
          239  +  }
          240  +  if( major==8 && minor==6 && type==TCL_BETA_RELEASE && patchLevel<3 ){
          241  +    return 0; /* NOTE: Disabled on Tcl 8.6b1/b2, SF bug #3399564. */
          242  +  }
          243  +  return 1;   /* NOTE: For all other cases, assume good. */
          244  +}
   236    245   
   237    246   /*
   238    247   ** Creates and initializes a Tcl interpreter for use with the specified TH1
   239    248   ** interpreter.  Stores the created Tcl interpreter in the Tcl context supplied
   240    249   ** by the caller.  This must be declared here because quite a few functions in
   241    250   ** this file need to use it before it can be defined.
   242         - */
          251  +*/
   243    252   static int createTclInterp(Th_Interp *interp, void *pContext);
   244    253   
   245    254   /*
   246    255   ** Returns the Tcl interpreter result as a string with the associated length.
   247    256   ** If the Tcl interpreter or the Tcl result are NULL, the length will be 0.
   248    257   ** If the length pointer is NULL, the length will not be stored.
   249         - */
          258  +*/
   250    259   static char *getTclResult(
   251    260     Tcl_Interp *pInterp,
   252    261     int *pN
   253    262   ){
   254    263     Tcl_Obj *resultPtr;
   255    264   
   256    265     if( !pInterp ){ /* This should not happen. */
................................................................................
   272    281   struct TclContext {
   273    282     int argc;           /* Number of original arguments. */
   274    283     char **argv;        /* Full copy of the original arguments. */
   275    284     void *library;      /* The Tcl library module handle. */
   276    285     tcl_FindExecutableProc *xFindExecutable; /* Tcl_FindExecutable() pointer. */
   277    286     tcl_CreateInterpProc *xCreateInterp;     /* Tcl_CreateInterp() pointer. */
   278    287     tcl_DeleteInterpProc *xDeleteInterp;     /* Tcl_DeleteInterp() pointer. */
          288  +  tcl_FinalizeProc *xFinalize;             /* Tcl_Finalize() pointer. */
   279    289     Tcl_Interp *interp; /* The on-demand created Tcl interpreter. */
          290  +  int useObjProc;     /* Non-zero if an objProc can be called directly. */
   280    291     char *setup;        /* The optional Tcl setup script. */
   281    292     tcl_NotifyProc *xPreEval;  /* Optional, called before Tcl_Eval*(). */
   282    293     void *pPreContext;         /* Optional, provided to xPreEval(). */
   283    294     tcl_NotifyProc *xPostEval; /* Optional, called after Tcl_Eval*(). */
   284    295     void *pPostContext;        /* Optional, provided to xPostEval(). */
   285    296   };
   286    297   
................................................................................
   441    452     Th_Interp *interp,
   442    453     void *ctx,
   443    454     int argc,
   444    455     const char **argv,
   445    456     int *argl
   446    457   ){
   447    458     Tcl_Interp *tclInterp;
   448         -#if !defined(USE_TCL_EVALOBJV) || !USE_TCL_EVALOBJV
   449         -  Tcl_Command command;
   450         -  Tcl_CmdInfo cmdInfo;
   451         -#endif /* !defined(USE_TCL_EVALOBJV) || !USE_TCL_EVALOBJV */
   452    459     int rc = TH_OK;
   453    460     int nResult;
   454    461     const char *zResult;
   455         -#if !defined(USE_TCL_EVALOBJV) || !USE_TCL_EVALOBJV
   456         -  Tcl_Obj *objPtr;
   457         -#endif /* !defined(USE_TCL_EVALOBJV) || !USE_TCL_EVALOBJV */
   458    462     USE_ARGV_TO_OBJV();
   459    463   
   460    464     if( createTclInterp(interp, ctx)!=TH_OK ){
   461    465       return TH_ERROR;
   462    466     }
   463    467     if( argc<2 ){
   464    468       return Th_WrongNumArgs(interp, "tclInvoke command ?arg ...?");
................................................................................
   470    474     }
   471    475     rc = notifyPreOrPostEval(0, interp, ctx, argc, argv, argl, rc);
   472    476     if( rc!=TH_OK ){
   473    477       return rc;
   474    478     }
   475    479     Tcl_Preserve((ClientData)tclInterp);
   476    480   #if !defined(USE_TCL_EVALOBJV) || !USE_TCL_EVALOBJV
   477         -  objPtr = Tcl_NewStringObj(argv[1], argl[1]);
   478         -  Tcl_IncrRefCount(objPtr);
   479         -  command = Tcl_GetCommandFromObj(tclInterp, objPtr);
   480         -  if( !command || Tcl_GetCommandInfoFromToken(command, &cmdInfo)==0 ){
   481         -    Th_ErrorMessage(interp, "Tcl command not found:", argv[1], argl[1]);
   482         -    Tcl_DecrRefCount(objPtr);
   483         -    Tcl_Release((ClientData)tclInterp);
   484         -    return TH_ERROR;
   485         -  }
   486         -  if( !cmdInfo.objProc ){
   487         -    Th_ErrorMessage(interp, "cannot invoke Tcl command:", argv[1], argl[1]);
          481  +  if( GET_CTX_TCL_USEOBJPROC(ctx) ){
          482  +    Tcl_Command command;
          483  +    Tcl_CmdInfo cmdInfo;
          484  +    Tcl_Obj *objPtr = Tcl_NewStringObj(argv[1], argl[1]);
          485  +    Tcl_IncrRefCount(objPtr);
          486  +    command = Tcl_GetCommandFromObj(tclInterp, objPtr);
          487  +    if( !command || Tcl_GetCommandInfoFromToken(command, &cmdInfo)==0 ){
          488  +      Th_ErrorMessage(interp, "Tcl command not found:", argv[1], argl[1]);
          489  +      Tcl_DecrRefCount(objPtr);
          490  +      Tcl_Release((ClientData)tclInterp);
          491  +      return TH_ERROR;
          492  +    }
          493  +    if( !cmdInfo.objProc ){
          494  +      Th_ErrorMessage(interp, "cannot invoke Tcl command:", argv[1], argl[1]);
          495  +      Tcl_DecrRefCount(objPtr);
          496  +      Tcl_Release((ClientData)tclInterp);
          497  +      return TH_ERROR;
          498  +    }
   488    499       Tcl_DecrRefCount(objPtr);
   489         -    Tcl_Release((ClientData)tclInterp);
   490         -    return TH_ERROR;
   491         -  }
   492         -  Tcl_DecrRefCount(objPtr);
          500  +    COPY_ARGV_TO_OBJV();
          501  +    Tcl_ResetResult(tclInterp);
          502  +    rc = cmdInfo.objProc(cmdInfo.objClientData, tclInterp, objc, objv);
          503  +    FREE_ARGV_TO_OBJV();
          504  +  }else
   493    505   #endif /* !defined(USE_TCL_EVALOBJV) || !USE_TCL_EVALOBJV */
   494         -  COPY_ARGV_TO_OBJV();
   495         -#if defined(USE_TCL_EVALOBJV) && USE_TCL_EVALOBJV
   496         -  rc = Tcl_EvalObjv(tclInterp, objc, objv, 0);
   497         -#else
   498         -  Tcl_ResetResult(tclInterp);
   499         -  rc = cmdInfo.objProc(cmdInfo.objClientData, tclInterp, objc, objv);
   500         -#endif /* defined(USE_TCL_EVALOBJV) && USE_TCL_EVALOBJV */
   501         -  FREE_ARGV_TO_OBJV();
          506  +  {
          507  +    COPY_ARGV_TO_OBJV();
          508  +    rc = Tcl_EvalObjv(tclInterp, objc, objv, 0);
          509  +    FREE_ARGV_TO_OBJV();
          510  +  }
   502    511     zResult = getTclResult(tclInterp, &nResult);
   503    512     Th_SetResult(interp, zResult, nResult);
   504    513     Tcl_Release((ClientData)tclInterp);
   505    514     rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl, rc);
   506    515     return rc;
   507    516   }
   508    517   
................................................................................
   584    593     {"tclInvoke", tclInvoke_command, 0},
   585    594     {0, 0, 0}
   586    595   };
   587    596   
   588    597   /*
   589    598   ** Called if the Tcl interpreter is deleted.  Removes the Tcl integration
   590    599   ** commands from the TH1 interpreter.
   591         - */
          600  +*/
   592    601   static void Th1DeleteProc(
   593    602     ClientData clientData,
   594    603     Tcl_Interp *interp
   595    604   ){
   596    605     int i;
   597    606     Th_Interp *th1Interp = (Th_Interp *)clientData;
   598    607   
................................................................................
   605    614   
   606    615   /*
   607    616   ** When Tcl stubs support is enabled, attempts to dynamically load the Tcl
   608    617   ** shared library and fetch the function pointers necessary to create an
   609    618   ** interpreter and initialize the stubs mechanism; otherwise, simply setup
   610    619   ** the function pointers provided by the caller with the statically linked
   611    620   ** functions.
   612         - */
          621  +*/
   613    622   static int loadTcl(
   614    623     Th_Interp *interp,
   615    624     void **pLibrary,
   616    625     tcl_FindExecutableProc **pxFindExecutable,
   617    626     tcl_CreateInterpProc **pxCreateInterp,
   618         -  tcl_DeleteInterpProc **pxDeleteInterp
          627  +  tcl_DeleteInterpProc **pxDeleteInterp,
          628  +  tcl_FinalizeProc **pxFinalize
   619    629   ){
   620    630   #if defined(USE_TCL_STUBS)
   621    631     char fileName[] = TCL_LIBRARY_NAME;
   622    632   #endif /* defined(USE_TCL_STUBS) */
   623    633   
   624         -  if( !pLibrary || !pxFindExecutable || !pxCreateInterp || !pxDeleteInterp ){
          634  +  if( !pLibrary || !pxFindExecutable || !pxCreateInterp ||
          635  +      !pxDeleteInterp || !pxFinalize ){
   625    636       Th_ErrorMessage(interp,
   626    637           "invalid Tcl loader argument(s)", (const char *)"", 0);
   627    638       return TH_ERROR;
   628    639     }
   629    640   #if defined(USE_TCL_STUBS)
   630    641     do {
   631    642       void *library = dlopen(fileName, RTLD_NOW | RTLD_GLOBAL);
   632    643       if( library ){
   633    644         tcl_FindExecutableProc *xFindExecutable;
   634    645         tcl_CreateInterpProc *xCreateInterp;
   635    646         tcl_DeleteInterpProc *xDeleteInterp;
          647  +      tcl_FinalizeProc *xFinalize;
   636    648         const char *procName = TCL_FINDEXECUTABLE_NAME;
   637    649         xFindExecutable = (tcl_FindExecutableProc *)dlsym(library, procName + 1);
   638    650         if( !xFindExecutable ){
   639    651           xFindExecutable = (tcl_FindExecutableProc *)dlsym(library, procName);
   640    652         }
   641    653         if( !xFindExecutable ){
   642    654           Th_ErrorMessage(interp,
................................................................................
   661    673           xDeleteInterp = (tcl_DeleteInterpProc *)dlsym(library, procName);
   662    674         }
   663    675         if( !xDeleteInterp ){
   664    676           Th_ErrorMessage(interp,
   665    677               "could not locate Tcl_DeleteInterp", (const char *)"", 0);
   666    678           dlclose(library);
   667    679           return TH_ERROR;
          680  +      }
          681  +      procName = TCL_FINALIZE_NAME;
          682  +      xFinalize = (tcl_FinalizeProc *)dlsym(library, procName + 1);
          683  +      if( !xFinalize ){
          684  +        xFinalize = (tcl_FinalizeProc *)dlsym(library, procName);
          685  +      }
          686  +      if( !xFinalize ){
          687  +        Th_ErrorMessage(interp,
          688  +            "could not locate Tcl_Finalize", (const char *)"", 0);
          689  +        dlclose(library);
          690  +        return TH_ERROR;
   668    691         }
   669    692         *pLibrary = library;
   670    693         *pxFindExecutable = xFindExecutable;
   671    694         *pxCreateInterp = xCreateInterp;
   672    695         *pxDeleteInterp = xDeleteInterp;
          696  +      *pxFinalize = xFinalize;
   673    697         return TH_OK;
   674    698       }
   675    699     } while( --fileName[TCL_MINOR_OFFSET]>'3' ); /* Tcl 8.4+ */
   676    700     fileName[TCL_MINOR_OFFSET] = 'x';
   677    701     Th_ErrorMessage(interp,
   678    702         "could not load any supported Tcl 8.6, 8.5, or 8.4 shared library \"",
   679    703         fileName, -1);
   680    704     return TH_ERROR;
   681    705   #else
   682    706     *pLibrary = 0;
   683    707     *pxFindExecutable = Tcl_FindExecutable;
   684    708     *pxCreateInterp = Tcl_CreateInterp;
   685    709     *pxDeleteInterp = Tcl_DeleteInterp;
          710  +  *pxFinalize = Tcl_Finalize;
   686    711     return TH_OK;
   687    712   #endif /* defined(USE_TCL_STUBS) */
   688    713   }
   689    714   
   690    715   /*
   691    716   ** Sets the "argv0", "argc", and "argv" script variables in the Tcl interpreter
   692    717   ** based on the supplied command line arguments.
   693         - */
          718  +*/
   694    719   static int setTclArguments(
   695    720     Tcl_Interp *pInterp,
   696    721     int argc,
   697    722     char **argv
   698    723   ){
   699    724     Tcl_Obj *objPtr;
   700    725     Tcl_Obj *resultObjPtr;
................................................................................
   744    769     return rc;
   745    770   }
   746    771   
   747    772   /*
   748    773   ** Creates and initializes a Tcl interpreter for use with the specified TH1
   749    774   ** interpreter.  Stores the created Tcl interpreter in the Tcl context supplied
   750    775   ** by the caller.
   751         - */
          776  +*/
   752    777   static int createTclInterp(
   753    778     Th_Interp *interp,
   754    779     void *pContext
   755    780   ){
   756    781     struct TclContext *tclContext = (struct TclContext *)pContext;
   757    782     int argc;
   758    783     char **argv;
................................................................................
   765    790           "invalid Tcl context", (const char *)"", 0);
   766    791       return TH_ERROR;
   767    792     }
   768    793     if ( tclContext->interp ){
   769    794       return TH_OK;
   770    795     }
   771    796     if( loadTcl(interp, &tclContext->library, &tclContext->xFindExecutable,
   772         -      &tclContext->xCreateInterp, &tclContext->xDeleteInterp)!=TH_OK ){
          797  +              &tclContext->xCreateInterp, &tclContext->xDeleteInterp,
          798  +              &tclContext->xFinalize)!=TH_OK ){
   773    799       return TH_ERROR;
   774    800     }
   775    801     argc = tclContext->argc;
   776    802     argv = tclContext->argv;
   777    803     if( argc>0 && argv ){
   778    804       argv0 = argv[0];
   779    805     }
................................................................................
   819    845     if( setTclArguments(tclInterp, argc, argv)!=TCL_OK ){
   820    846       Th_ErrorMessage(interp,
   821    847           "Tcl error setting arguments:", Tcl_GetStringResult(tclInterp), -1);
   822    848       Tcl_DeleteInterp(tclInterp);
   823    849       tclContext->interp = tclInterp = 0;
   824    850       return TH_ERROR;
   825    851     }
          852  +  /*
          853  +  ** Determine if an objProc can be called directly for a Tcl command invoked
          854  +  ** via the tclInvoke TH1 command.
          855  +  */
          856  +  tclContext->useObjProc = canUseObjProc();
   826    857     /* Add the TH1 integration commands to Tcl. */
   827    858     Tcl_CallWhenDeleted(tclInterp, Th1DeleteProc, interp);
   828    859     Tcl_CreateObjCommand(tclInterp, "th1Eval", Th1EvalObjCmd, interp, NULL);
   829    860     Tcl_CreateObjCommand(tclInterp, "th1Expr", Th1ExprObjCmd, interp, NULL);
   830    861     /* If necessary, evaluate the custom Tcl setup script. */
   831    862     setup = tclContext->setup;
   832    863     if( setup && Tcl_Eval(tclInterp, setup)!=TCL_OK ){
................................................................................
   834    865           "Tcl setup script error:", Tcl_GetStringResult(tclInterp), -1);
   835    866       Tcl_DeleteInterp(tclInterp);
   836    867       tclContext->interp = tclInterp = 0;
   837    868       return TH_ERROR;
   838    869     }
   839    870     return TH_OK;
   840    871   }
          872  +
          873  +/*
          874  +** Finalizes and unloads the previously loaded Tcl library, if applicable.
          875  +*/
          876  +int unloadTcl(
          877  +  Th_Interp *interp,
          878  +  void *pContext
          879  +){
          880  +  struct TclContext *tclContext = (struct TclContext *)pContext;
          881  +  Tcl_Interp *tclInterp;
          882  +  tcl_FinalizeProc *xFinalize;
          883  +#if defined(USE_TCL_STUBS)
          884  +  void *library;
          885  +#endif /* defined(USE_TCL_STUBS) */
          886  +
          887  +  if ( !tclContext ){
          888  +    Th_ErrorMessage(interp,
          889  +        "invalid Tcl context", (const char *)"", 0);
          890  +    return TH_ERROR;
          891  +  }
          892  +  /*
          893  +  ** Grab the Tcl_Finalize function pointer prior to deleting the Tcl
          894  +  ** interpreter because the memory backing the Tcl stubs table will
          895  +  ** be going away.
          896  +  */
          897  +  xFinalize = tclContext->xFinalize;
          898  +  /*
          899  +  ** If the Tcl interpreter has been created, formally delete it now.
          900  +  */
          901  +  tclInterp = tclContext->interp;
          902  +  if ( tclInterp ){
          903  +    Tcl_DeleteInterp(tclInterp);
          904  +    tclContext->interp = tclInterp = 0;
          905  +  }
          906  +  /*
          907  +  ** If the Tcl library is not finalized prior to unloading it, a deadlock
          908  +  ** can occur in some circumstances (i.e. the [clock] thread is running).
          909  +  */
          910  +  if( xFinalize ) xFinalize();
          911  +#if defined(USE_TCL_STUBS)
          912  +  /*
          913  +  ** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash
          914  +  ** when exiting while a stubs-enabled Tcl is still loaded.  This is due to
          915  +  ** a bug in MinGW, see:
          916  +  **
          917  +  **     http://comments.gmane.org/gmane.comp.gnu.mingw.user/41724
          918  +  **
          919  +  ** The workaround is to manually unload the loaded Tcl library prior to
          920  +  ** exiting the process.
          921  +  */
          922  +  library = tclContext->library;
          923  +  if( library ){
          924  +    dlclose(library);
          925  +    tclContext->library = library = 0;
          926  +  }
          927  +#endif /* defined(USE_TCL_STUBS) */
          928  +  return TH_OK;
          929  +}
   841    930   
   842    931   /*
   843    932   ** Register the Tcl language commands with interpreter interp.
   844    933   ** Usually this is called soon after interpreter creation.
   845    934   */
   846    935   int th_register_tcl(
   847    936     Th_Interp *interp,

Changes to test/th1-tcl.test.

   112    112   
   113    113   fossil test-th-render --th-open-config \
   114    114       [file nativename [file join $dir th1-tcl8.txt]]
   115    115   
   116    116   test th1-tcl-8 {$RESULT eq {<hr><p class="thmainError">ERROR:\
   117    117   cannot invoke Tcl command: tailcall</p>} || $RESULT eq {<hr><p\
   118    118   class="thmainError">ERROR: tailcall can only be called from a proc or\
   119         -lambda</p>}}
          119  +lambda</p>} || $RESULT eq {<hr><p class="thmainError">ERROR: This test\
          120  +requires Tcl 8.6 or higher.</p>}}
   120    121   
   121    122   ###############################################################################
   122    123   
   123    124   fossil test-th-render --th-open-config \
   124    125       [file nativename [file join $dir th1-tcl9.txt]]
   125    126   
   126    127   test th1-tcl-9 {[string trim $RESULT] eq [list [file tail $fossilexe] 3 \
   127    128   [list test-th-render --th-open-config [file nativename [file join $dir \
   128    129   th1-tcl9.txt]]]]}

Changes to test/th1-tcl8.txt.

     5      5     # Fossil command.
     6      6     #
     7      7     proc doOut {msg} {puts $msg; puts \n}
     8      8   
     9      9     if {[tclInvoke set tcl_version] >= 8.6} {
    10     10       doOut [tclInvoke tailcall set x 1]
    11     11     } else {
    12         -    doOut "This test requires Tcl 8.6 or higher."
           12  +    error "This test requires Tcl 8.6 or higher."
    13     13     }
    14     14   </th1>

Changes to win/Makefile.mingw.

    66     66   #    This is useful when Tcl has been compiled statically with MinGW.
    67     67   #
    68     68   FOSSIL_TCL_SOURCE = 1
    69     69   
    70     70   #### Check if the workaround for the MinGW command line handling needs to
    71     71   #    be enabled by default.
    72     72   #
    73         -ifndef BROKEN_MINGW_CMDLINE
           73  +ifndef MINGW_IS_32BIT_ONLY
    74     74   ifeq (,$(findstring w64-mingw32,$(PREFIX)))
    75         -BROKEN_MINGW_CMDLINE = 1
           75  +MINGW_IS_32BIT_ONLY = 1
    76     76   endif
    77     77   endif
    78     78   
    79     79   #### The directories where the zlib include and library files are located.
    80     80   #
    81     81   ZINCDIR = $(SRCDIR)/../compat/zlib
    82     82   ZLIBDIR = $(SRCDIR)/../compat/zlib
................................................................................
   160    160   else
   161    161   TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR)
   162    162   RCC += -I$(TCLINCDIR)
   163    163   endif
   164    164   endif
   165    165   
   166    166   # With MinGW command line handling workaround
   167         -ifdef BROKEN_MINGW_CMDLINE
   168         -TCC += -DBROKEN_MINGW_CMDLINE=1
   169         -RCC += -DBROKEN_MINGW_CMDLINE=1
          167  +ifdef MINGW_IS_32BIT_ONLY
          168  +TCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
          169  +RCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
   170    170   endif
   171    171   
   172    172   # With HTTPS support
   173    173   ifdef FOSSIL_ENABLE_SSL
   174    174   TCC += -DFOSSIL_ENABLE_SSL=1
   175    175   RCC += -DFOSSIL_ENABLE_SSL=1
   176    176   endif
................................................................................
   201    201   
   202    202   #### We add the -static option here so that we can build a static
   203    203   #    executable that will run in a chroot jail.
   204    204   #
   205    205   LIB = -static
   206    206   
   207    207   # MinGW: If available, use the Unicode capable runtime startup code.
   208         -ifndef BROKEN_MINGW_CMDLINE
          208  +ifndef MINGW_IS_32BIT_ONLY
   209    209   LIB += -municode
   210    210   endif
   211    211   
   212    212   # OpenSSL: Add the necessary libraries required, if enabled.
   213    213   ifdef FOSSIL_ENABLE_SSL
   214    214   LIB += -lssl -lcrypto -lgdi32
   215    215   endif

Changes to win/Makefile.mingw.mistachkin.

    66     66   #    This is useful when Tcl has been compiled statically with MinGW.
    67     67   #
    68     68   FOSSIL_TCL_SOURCE = 1
    69     69   
    70     70   #### Check if the workaround for the MinGW command line handling needs to
    71     71   #    be enabled by default.
    72     72   #
    73         -ifndef BROKEN_MINGW_CMDLINE
           73  +ifndef MINGW_IS_32BIT_ONLY
    74     74   ifeq (,$(findstring w64-mingw32,$(PREFIX)))
    75         -BROKEN_MINGW_CMDLINE = 1
           75  +MINGW_IS_32BIT_ONLY = 1
    76     76   endif
    77     77   endif
    78     78   
    79     79   #### The directories where the zlib include and library files are located.
    80     80   #
    81     81   ZINCDIR = $(SRCDIR)/../compat/zlib
    82     82   ZLIBDIR = $(SRCDIR)/../compat/zlib
................................................................................
   160    160   else
   161    161   TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR)
   162    162   RCC += -I$(TCLINCDIR)
   163    163   endif
   164    164   endif
   165    165   
   166    166   # With MinGW command line handling workaround
   167         -ifdef BROKEN_MINGW_CMDLINE
   168         -TCC += -DBROKEN_MINGW_CMDLINE=1
   169         -RCC += -DBROKEN_MINGW_CMDLINE=1
          167  +ifdef MINGW_IS_32BIT_ONLY
          168  +TCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
          169  +RCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
   170    170   endif
   171    171   
   172    172   # With HTTPS support
   173    173   ifdef FOSSIL_ENABLE_SSL
   174    174   TCC += -DFOSSIL_ENABLE_SSL=1
   175    175   RCC += -DFOSSIL_ENABLE_SSL=1
   176    176   endif
................................................................................
   201    201   
   202    202   #### We add the -static option here so that we can build a static
   203    203   #    executable that will run in a chroot jail.
   204    204   #
   205    205   LIB = -static
   206    206   
   207    207   # MinGW: If available, use the Unicode capable runtime startup code.
   208         -ifndef BROKEN_MINGW_CMDLINE
          208  +ifndef MINGW_IS_32BIT_ONLY
   209    209   LIB += -municode
   210    210   endif
   211    211   
   212    212   # OpenSSL: Add the necessary libraries required, if enabled.
   213    213   ifdef FOSSIL_ENABLE_SSL
   214    214   LIB += -lssl -lcrypto -lgdi32
   215    215   endif

Changes to win/fossil.rc.

   101    101         VALUE "CommandLineIsUnicode", "Yes\0"
   102    102   #endif /* defined(BROKEN_MINGW_CMDLINE) */
   103    103   #if defined(FOSSIL_ENABLE_SSL)
   104    104         VALUE "SslEnabled", "Yes, " OPENSSL_VERSION_TEXT "\0"
   105    105   #endif /* defined(FOSSIL_ENABLE_SSL) */
   106    106   #if defined(FOSSIL_ENABLE_TCL)
   107    107         VALUE "TclEnabled", "Yes, Tcl " TCL_PATCH_LEVEL "\0"
          108  +#if defined(USE_TCL_STUBS)
          109  +      VALUE "UseTclStubsEnabled", "Yes\0"
          110  +#else
          111  +      VALUE "UseTclStubsEnabled", "No\0"
          112  +#endif /* defined(USE_TCL_STUBS) */
   108    113   #if defined(FOSSIL_ENABLE_TCL_STUBS)
   109    114         VALUE "TclStubsEnabled", "Yes\0"
   110    115   #else
   111    116         VALUE "TclStubsEnabled", "No\0"
   112    117   #endif /* defined(FOSSIL_ENABLE_TCL_STUBS) */
   113    118   #if defined(FOSSIL_ENABLE_TCL_PRIVATE_STUBS)
   114    119         VALUE "TclPrivateStubsEnabled", "Yes\0"