Subject: Request Tcl 8.2b2 dynamic loading improvement for tclsh on Win32 - DN [1]
davygrvy@bigfoot.com - 09 Aug 1999 - comp.lang.tcl
Tcl 8.2b2 Request: Generated by Scriptics' bug entry form at
http://www.scriptics.com/support/bugForm.html
Responses to this post are encouraged.
------
Submitted by: David Gravereaux
OperatingSystem: Windows NT
OperatingSystemVersion: 4.0 sp5
Synopsis: dynamic loading improvement for tclsh on Win32
DesiredBehavior:
This patch gets tclsh using Stubs and adds a dynamic loading mechanism.
It only works on Win32 at the moment, but could be improved with
additional dlopen() function that Jan Nijtmans has.
The search routine (Stub_LoadTcl) will need some inspection to determine
if it's optimal. I like it though.
Patch:
Index: tcl.h
===================================================================
RCS file: /cvsroot/tcl/generic/tcl.h,v
retrieving revision 1.56
diff -c -r1.56 tcl.h
*** tcl.h 1999/08/02 17:45:36 1.56
--- tcl.h 1999/08/09 09:25:02
***************
*** 1579,1584 ****
--- 1579,1591 ----
EXTERN char * Tcl_InitStubs _ANSI_ARGS_((Tcl_Interp *interp,
char *version, int exact));
+ EXTERN char * Stub_LoadTcl _ANSI_ARGS_((char *minVer, int exact,
+ int dbgOnly));
+ EXTERN VOID Stub_PreInit _ANSI_ARGS_((char *ver, int exact, char *app));
+ EXTERN VOID * Stub_GetMain _ANSI_ARGS_(());
+ EXTERN VOID * Stub_GetCreateInterp _ANSI_ARGS_(());
+ EXTERN char * Stub_LoadTclError _ANSI_ARGS_(());
+
#ifndef USE_TCL_STUBS
Index: tclAppInit.c
===================================================================
RCS file: /cvsroot/tcl/win/tclAppInit.c,v
retrieving revision 1.5
diff -c -r1.5 tclAppInit.c
*** tclAppInit.c 1999/04/16 00:48:07 1.5
--- tclAppInit.c 1999/08/09 19:13:18
***************
*** 53,58 ****
--- 53,70 ----
int argc; /* Number of command-line arguments. */
char **argv; /* Values of command-line arguments. */
{
+ #ifdef USE_TCL_STUBS
+ void *(*tclMainProc) _ANSI_ARGS_((int argc, char **argv,
+ Tcl_AppInitProc *appInitProc));
+
+ #ifdef DEBUG
+ Stub_LoadTcl(TCL_VERSION, /*exact*/1, /*debug*/1);
+ #else
+ Stub_LoadTcl(TCL_VERSION, /*exact*/1, /*debug*/0);
+ #endif
+ tclMainProc = Stub_GetMain();
+ #endif
+
/*
* Set up the default locale to be standard "C" locale so parsing
* is performed correctly.
***************
*** 61,67 ****
--- 73,84 ----
setlocale(LC_ALL, "C");
setargv(&argc, &argv);
+
+ #ifdef USE_TCL_STUBS
+ tclMainProc(argc, argv, Tcl_AppInit);
+ #else
Tcl_Main(argc, argv, Tcl_AppInit);
+ #endif
return 0; /* Needed only to prevent compiler warning. */
}
***************
*** 89,98 ****
Tcl_AppInit(interp)
Tcl_Interp *interp; /* Interpreter for application. */
{
if (Tcl_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
-
#ifdef TCL_TEST
if (Tcltest_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
--- 106,117 ----
Tcl_AppInit(interp)
Tcl_Interp *interp; /* Interpreter for application. */
{
+ if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
+ return TCL_ERROR;
+ }
if (Tcl_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
#ifdef TCL_TEST
if (Tcltest_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
***************
*** 196,202 ****
--- 215,225 ----
}
}
}
+ #ifdef USE_TCL_STUBS
+ argSpace = (char *) malloc(
+ #else
argSpace = (char *) Tcl_Alloc(
+ #endif
(unsigned) (size * sizeof(char *) + strlen(cmdLine) + 1));
argv = (char **) argSpace;
argSpace += size * sizeof(char *);
Index: makefile.vc
===================================================================
RCS file: /cvsroot/tcl/win/makefile.vc,v
retrieving revision 1.42
diff -c -r1.42 makefile.vc
*** makefile.vc 1999/07/22 23:45:53 1.42
--- makefile.vc 1999/08/09 04:13:55
***************
*** 183,189 ****
$(TMPDIR)\tclScan.obj \
$(TMPDIR)\tclStringObj.obj \
$(TMPDIR)\tclStubInit.obj \
! $(TMPDIR)\tclStubLib.obj \
$(TMPDIR)\tclThread.obj \
$(TMPDIR)\tclTimer.obj \
$(TMPDIR)\tclUtf.obj \
--- 183,189 ----
$(TMPDIR)\tclScan.obj \
$(TMPDIR)\tclStringObj.obj \
$(TMPDIR)\tclStubInit.obj \
! # $(TMPDIR)\tclStubLib.obj \
$(TMPDIR)\tclThread.obj \
$(TMPDIR)\tclTimer.obj \
$(TMPDIR)\tclUtf.obj \
***************
*** 206,211 ****
--- 206,213 ----
$(TMPDIR)\tclWinTime.obj
TCLSTUBOBJS = $(TMPDIR)\tclStubLib.obj \
+ $(TMPDIR)\tclStubLoader.obj \
+ $(TMPDIR)\tclWinDlLoad.obj
cc32 = "$(TOOLS32)\bin\cl.exe"
link32 = "$(TOOLS32)\bin\link.exe"
***************
*** 356,365 ****
$(TCLOBJS)
<<
! $(TCLSH): $(TCLSHOBJS) $(TCLLIB) $(TMPDIR)\tclsh.res
set LIB="$(TOOLS32)\lib"
$(link32) $(ldebug) $(conlflags) $(TMPDIR)\tclsh.res -stack:2300000 \
! -out:$@ $(conlibsdll) $(TCLLIB) $(TCLSHOBJS)
$(TCLSHP): $(TCLSHOBJS) $(TCLPLUGINLIB) $(TMPDIR)\tclsh.res
set LIB=$(TOOLS32)\lib
--- 358,367 ----
$(TCLOBJS)
<<
! $(TCLSH): $(TCLSHOBJS) $(TCLSTUBLIB) $(TMPDIR)\tclsh.res
set LIB="$(TOOLS32)\lib"
$(link32) $(ldebug) $(conlflags) $(TMPDIR)\tclsh.res -stack:2300000 \
! -out:$@ $(conlibsdll) $(TCLSTUBLIB) $(TCLSHOBJS)
$(TCLSHP): $(TCLSHOBJS) $(TCLPLUGINLIB) $(TMPDIR)\tclsh.res
set LIB=$(TOOLS32)\lib
***************
*** 514,523 ****
$(TMPDIR)\tclWinTest.obj: $(WINDIR)\tclWinTest.c
$(cc32) $(TCL_CFLAGS) -Fo$@ $?
- $(TMPDIR)\tclAppInit.obj : $(WINDIR)\tclAppInit.c
- $(cc32) $(TCL_CFLAGS) -Fo$@ $?
-
# The following objects should be built using the stub interfaces
$(TMPDIR)\tclWinReg.obj : $(WINDIR)\tclWinReg.c
$(cc32) $(TCL_CFLAGS) -DUSE_TCL_STUBS -Fo$@ $?
--- 516,530 ----
$(TMPDIR)\tclWinTest.obj: $(WINDIR)\tclWinTest.c
$(cc32) $(TCL_CFLAGS) -Fo$@ $?
# The following objects should be built using the stub interfaces
+
+ !IF "$(NODEBUG)" == "1"
+ $(TMPDIR)\tclAppInit.obj : $(WINDIR)\tclAppInit.c
+ $(cc32) $(TCL_CFLAGS) -DUSE_TCL_STUBS -Fo$@ $?
+ !ELSE
+ $(TMPDIR)\tclAppInit.obj : $(WINDIR)\tclAppInit.c
+ $(cc32) $(TCL_CFLAGS) -DUSE_TCL_STUBS -DDEBUG -Fo$@ $?
+ !ENDIF
$(TMPDIR)\tclWinReg.obj : $(WINDIR)\tclWinReg.c
$(cc32) $(TCL_CFLAGS) -DUSE_TCL_STUBS -Fo$@ $?
Index: e:/tclcvs/tcl8.2b1/win/tclWinDlLoad.c
*** /dev/nul Mon Aug 09 04:31:33 1999
--- e:/tclcvs/tcl8.2b1/win/tclWinDlLoad.c Mon Aug 09 02:58:32 1999
***************
*** 0 ****
--- 1,146 ----
+ /*
+ * tclWinDlLoad.c --
+ *
+ * This procedure provides a version of dlopen() that
+ * works with the Windows "LoadLibrary" and "GetProcAddress"
+ * API for dynamic loading.
+ *
+ * These routines do not contain any dependancies for the
+ * Tcl library so they can be used specificly for loading one
+ * in a Stub'd application.
+ *
+ * They could also be integrated into TclpLoadFile, should it be desir
+ *
+ * code from a c.l.t post:
+ * Sub: [Request Tcl 8.1] Dynamical loading enhancement for extensions
+ * Date: 05/20/1999
+ * Author: Jan Nijtmans <jan.nijtmans@wxs.nl>
+ *
+ * RCS: @(#) $Id:$
+ *
+ */
+
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+ #undef WIN32_LEAN_AND_MEAN
+
+ #define _TCLDECLS /* lets make sure we don't touch ANY Tcl library fu
*/
+ #include "../compat/dlfcn.h"
+
+ #define WINERRMSGBUFSIZE 1024
+
+ char WinErrorMsg[WINERRMSGBUFSIZE];
+
+ /*
+ *--------------------------------------------------------------------
+ *
+ * dlopen --
+ *
+ * This function is an alternative for the functions
+ * TclWinLoadLibrary and TclWinGetTclInstance.
+ *
+ * Results:
+ * Returns the handle of the newly loaded library, or NULL on
+ * failure. If path is NULL, the global library instance handle
+ * is returned.
+ *
+ * Side effects:
+ * Loads the specified library into the process.
+ *
+ *--------------------------------------------------------------------
+ */
+
+ VOID *dlopen(path, mode)
+ const char *path;
+ int mode;
+ {
+ HMODULE mod;
+ mod = LoadLibrary(path);
+ if (mod <= (HMODULE) HINSTANCE_ERROR) return NULL;
+ return (VOID *) mod;
+ };
+
+
+ /*
+ *--------------------------------------------------------------------
+ *
+ * dlclose --
+ *
+ * This function is an alternative for the function
+ * FreeLibrary. It is responsible for removing library
+ * handles from the library list and remove the dll
+ * from memory.
+ *
+ * Results:
+ * -1 on error, 0 on success.
+ *
+ * Side effects:
+ * Unmaps and removes the specified library from the process.
+ *
+ *--------------------------------------------------------------------
+ */
+
+ int
+ dlclose(handle)
+ VOID *handle;
+ {
+ BOOL rtn;
+
+ rtn = FreeLibrary((HMODULE) handle);
+ if (rtn == TRUE) return 0;
+ return -1;
+ }
+
+ /*
+ *--------------------------------------------------------------------
+ *
+ * dlsym --
+ *
+ * This function is an alternative for the system function
+ * GetProcAddress. It returns the address of a
+ * symbol, give the handle returned by dlopen().
+ *
+ * Results:
+ * Returns the address of the symbol in the dll.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------
+ */
+
+ VOID *dlsym(handle, symbol)
+ VOID *handle;
+ CONST char *symbol;
+ {
+ return (VOID *) GetProcAddress((HMODULE) handle, symbol);
+ }
+
+ /*
+ *--------------------------------------------------------------------
+ *
+ * dlerror --
+ *
+ * This function returns a string describing the error which
+ * occurred in dlopen().
+ *
+ * Results:
+ * Returns an error message.
+ *
+ * Side effects:
+ * errno is not set.
+ *
+ *--------------------------------------------------------------------
+ */
+
+ char *
+ dlerror()
+ {
+ FormatMessage(
+ FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ WinErrorMsg, WINERRMSGBUFSIZE, NULL
+ );
+
+ return WinErrorMsg;
+ }
Index: e:/tclcvs/tcl8.2b1/generic/tclStubLoader.c
*** /dev/nul Mon Aug 09 04:31:33 1999
--- e:/tclcvs/tcl8.2b1/generic/tclStubLoader.c Mon Aug 09 19:09:36 1999
***************
*** 0 ****
--- 1,479 ----
+ /*
+ * tclStubLoader.c
+ *
+ * This file contains the routines for finding, dynamicaly loading
+ * and initializing the Stubs table in the Tcl library for a shell
+ * or any other Tcl application.
+ *
+ *
+ * Copyright (c) 1999 by David Gravereaux.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id:$
+ */
+
+ #define USE_TCL_STUBS
+ #include "tclPort.h"
+ #include "../compat/dlfcn.h"
+
+
+ #ifdef __WIN32__
+ char *prefix = "\\bin\\tcl";
+ #else
+ char *prefix = "/bin/libtcl"; /* fix me! */
+ #endif
+
+ char *shLibExt = TCL_SHLIB_EXT;
+ char *tclvers[] = { "8.4", "8.3", "8.2", "8.1", NULL };
+ VOID *stubTclLibHnd = NULL;
+ char *stubLoadErrorMsg;
+
+ typedef Tcl_Interp *(*LPFN_createInterpProc) ();
+
+ /*
+ * Prototypes for functions used only in this file.
+ */
+
+ static VOID stubBuildTrailing _ANSI_ARGS_((char *pos, char *ver, int dbgOnly));
+
+
+
+ /*
+ *-------------------------------------------------------------------------
+ *
+ * Stub_PreInit --
+ *
+ * Initializes the Stubs table and the lib paths. Use this for when
+ * you don't use Tcl_Main.
+ *
+ * Results:
+ * none
+ *
+ * Side effects:
+ * wastes an interp, but the Stubs table is all filled.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+ VOID
+ Stub_PreInit(ver, exact, app)
+ char *ver;
+ int exact;
+ char *app;
+ {
+ Tcl_Interp *interp;
+ LPFN_createInterpProc createInterpProc;
+
+ createInterpProc =
+ (LPFN_createInterpProc) dlsym(stubTclLibHnd, "Tcl_CreateInterp");
+
+ interp = createInterpProc();
+ Tcl_InitStubs(interp, ver, exact);
+ Tcl_FindExecutable(app);
+ Tcl_DeleteInterp(interp);
+ }
+
+ /*
+ *-------------------------------------------------------------------------
+ *
+ * Stub_GetMain --
+ *
+ * Just grabs the location of Tcl_Main.
+ *
+ * Results:
+ * pointer to the Tcl_Main function.
+ *
+ * Side effects:
+ * bypasses some type safety and just returns a VOID *.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+ VOID *
+ Stub_GetMain ()
+ {
+ return dlsym(stubTclLibHnd, "Tcl_Main");
+ }
+
+ /*
+ *-------------------------------------------------------------------------
+ *
+ * Stub_GetCreateInterp --
+ *
+ * Just grabs the location of Tcl_CreateInterp. Use this when you don't
+ * want to waste an interp with Stub_PreInit.
+ *
+ * Results:
+ * pointer to the Tcl_CreateInterp function.
+ *
+ * Side effects:
+ * bypasses some type safety and just returns a VOID *.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+ VOID *
+ Stub_GetCreateInterp ()
+ {
+ return dlsym(stubTclLibHnd, "Tcl_CreateInterp");
+ }
+
+ /*
+ *-------------------------------------------------------------------------
+ *
+ * Stub_LoadTcl --
+ *
+ * Searches the system and loads the proper Tcl library into memory.
+ *
+ * Checks: 1) TCL_LIBRARY_PATH first
+ * 2) Registry (windows only) search for
+ * HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl
+ * 3) current directory (or default path) search
+ *
+ * When exact is set to 0, a range of versions is tried, starting
+ * at the top of the tclvers array and working down.
+ *
+ * Results:
+ * The version actually loaded or NULL on error
+ *
+ * Side effects:
+ * Tcl is now in memory.
+ * BUG: running tclsh from the development environment will load
+ * the installed one rather than the Tcl library sitting next
+ * to it.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+ char *
+ Stub_LoadTcl (minVer, exact, dbgOnly)
+ char *minVer; /* minimum version acceptable */
+ int exact; /* only the specified version will do */
+ int dbgOnly; /* load the debug (symbol) library */
+ {
+ char *tclRootPath = NULL;
+ char stubTclLibFullPath[_MAX_PATH];
+ char *savedPos;
+ char *pos1, *pos2;
+ #ifdef __WIN32__
+ HKEY topTclKey;
+ HKEY subTclVer;
+ DWORD max_path = _MAX_PATH;
+ LONG result;
+ #endif
+
+ /*
+ * Try the environment variable first. This overrides everything.
+ */
+ tclRootPath = getenv("TCL_LIBRARY_PATH");
+ if (tclRootPath != NULL) {
+
+ pos1 = stubTclLibFullPath;
+ while (*tclRootPath != '\0') {
+ *pos1++ = *tclRootPath++;
+ }; /* ex. c:\program files\tcl */
+
+ /*
+ * Append the bin directory and prefix
+ */
+ pos2 = prefix;
+ while (*pos2 != '\0') {
+ *pos1++ = *pos2++;
+ }; /* ex. c:\program files\tcl\bin\tcl */
+ savedPos = pos1;
+
+ if (exact != 0) {
+
+ /*
+ * build the end of the filename from the parameter given
+ */
+ stubBuildTrailing(savedPos, minVer, dbgOnly);
+ /* ex. c:\program files\tcl\bin\tcl81d.dll */
+ /* Try it */
+ if ((stubTclLibHnd = dlopen(stubTclLibFullPath, RTLD_NOW)) != NULL)
+ return minVer;
+
+ } else {
+ int i = 0;
+
+ /*
+ * Try a range of filenames starting at the top and working down
+ */
+ for (i = 0; tclvers[i] != NULL && strcmp(tclvers[i],minVer) >= 0; i++) {
+
+ /*
+ * build the end of the filename
+ */
+ stubBuildTrailing(savedPos, tclvers[i], dbgOnly);
+ /* ex. c:\program files\tcl\bin\tcl84d.dll */
+ /* Try it */
+ if ((stubTclLibHnd = dlopen(stubTclLibFullPath, RTLD_NOW)) != NULL)
+ return tclvers[i];
+ };
+ }
+
+ /*
+ * A suitable Tcl library hasn't been found yet.
+ * Keep falling through.
+ */
+ }
+
+ #ifdef __WIN32__
+
+ /*
+ * Do a registry search
+ */
+ result = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE, "SOFTWARE\\Scriptics\\Tcl", 0,
+ KEY_ENUMERATE_SUB_KEYS, &topTclKey
+ );
+
+ if (result != ERROR_SUCCESS) {
+ goto Next;
+ };
+
+ if (exact != 0) {
+
+ /*
+ * Just try the requested only
+ */
+ result = RegOpenKeyEx(topTclKey, minVer, 0, KEY_READ, &subTclVer);
+
+ if (result != ERROR_SUCCESS) {
+ /* Subkey for exact version not found. */
+ goto Next;
+ };
+
+ /*
+ * Retrieve location and load it.
+ */
+ result = RegQueryValueEx(
+ subTclVer, "Root", NULL, NULL, stubTclLibFullPath, &max_path
+ );
+
+ if (result != ERROR_SUCCESS) {
+ stubLoadErrorMsg = "SubKey found in registry for exact match, but no Root value set.";
+ return NULL;
+ };
+
+ pos1 = stubTclLibFullPath;
+ while (*pos1 != '\0') { pos1++; }
+
+ /*
+ * Append the bin directory and prefix
+ */
+ pos2 = prefix;
+ while (*pos2 != '\0') {
+ *pos1++ = *pos2++;
+ };
+ savedPos = pos1;
+
+ /*
+ * build the end of the filename from the parameter given
+ */
+ stubBuildTrailing(savedPos, minVer, dbgOnly);
+
+ /* Try it */
+ if ((stubTclLibHnd = dlopen(stubTclLibFullPath, RTLD_NOW)) != NULL)
+ return minVer;
+
+ } else {
+ int i;
+
+ /*
+ * Try a range of filenames starting at the top and working down
+ */
+ for (i = 0; tclvers[i] != NULL && strcmp(tclvers[i],minVer) >= 0; i++) {
+
+ result = RegOpenKeyEx(topTclKey, tclvers[i], 0, KEY_READ, &subTclVer);
+
+ if (result != ERROR_SUCCESS) {
+ continue;
+ };
+
+ /* Try it. */
+ result = RegQueryValueEx(
+ subTclVer, "Root", NULL, NULL, stubTclLibFullPath, &max_path
+ );
+
+ if (result != ERROR_SUCCESS) {
+ /* Odd... SubKey is there, but no Root value. */
+ continue;
+ };
+
+ pos1 = stubTclLibFullPath;
+ while (*pos1 != '\0') { pos1++; }
+
+ /*
+ * Append the bin directory and prefix
+ */
+ pos2 = prefix;
+ while (*pos2 != '\0') {
+ *pos1++ = *pos2++;
+ };
+ savedPos = pos1;
+
+ /*
+ * Build the end of the filename
+ */
+ stubBuildTrailing(savedPos, tclvers[i], dbgOnly);
+
+ /* Try it */
+ if ((stubTclLibHnd = dlopen(stubTclLibFullPath, RTLD_NOW)) != NULL)
+ return tclvers[i];
+ };
+
+ /*
+ * A suitable Tcl library hasn't been found yet.
+ * Keep falling through.
+ */
+
+ };
+ Next:
+ #endif /* __WIN32__ */
+
+ /*
+ * Try current directory or default search path.
+ * Last chance. You better work.
+ */
+ pos1 = stubTclLibFullPath;
+
+ #ifdef __WIN32__
+ pos2 = "tcl";
+ #else
+ pos2 = "libtcl"; /* fix me! */
+ #endif
+
+ while (*pos2 != '\0') {
+ *pos1++ = *pos2++;
+ };
+ savedPos = pos1;
+
+
+ if (exact != 0) {
+ stubBuildTrailing(savedPos, minVer, dbgOnly);
+
+ /* Try it */
+ if ((stubTclLibHnd = dlopen(stubTclLibFullPath, RTLD_NOW)) != NULL)
+ return minVer;
+
+ } else {
+ int i;
+
+ /*
+ * Try a range of filenames starting at the top and working down
+ */
+ for (i = 0; tclvers[i] != NULL && strcmp(tclvers[i],minVer) >= 0; i++) {
+ /*
+ * Build the end of the filename
+ */
+ stubBuildTrailing(savedPos, tclvers[i], dbgOnly);
+
+ /* Try it */
+ if ((stubTclLibHnd = dlopen(stubTclLibFullPath, RTLD_NOW)) != NULL)
+ return tclvers[i];
+ };
+ }
+
+ stubLoadErrorMsg = "A proper Tcl library could not be located anywhere.";
+ return NULL;
+ }
+
+ /*
+ *-------------------------------------------------------------------------
+ *
+ * Stub_UnLoadTcl --
+ *
+ * Unloads the Tcl library into memory.
+ *
+ * Results:
+ * none.
+ *
+ * Side effects:
+ * The Stubs table is now invalid.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+ VOID
+ Stub_UnLoadTcl ()
+ {
+ if (stubTclLibHnd != NULL) dlclose(stubTclLibHnd);
+ };
+
+ /*
+ *-------------------------------------------------------------------------
+ *
+ * Stub_LoadTclError --
+ *
+ * Gets the associated error message for when Stub_LoadTcl returns NULL.
+ *
+ * Results:
+ * the message.
+ *
+ * Side effects:
+ * none.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+ char *
+ Stub_LoadTclError()
+ {
+ return stubLoadErrorMsg;
+ };
+
+ /*
+ *-------------------------------------------------------------------------
+ *
+ * stubBuildTrailing --
+ *
+ * Helper function for Stub_LoadTcl that finishes and terminates
+ * the path string.
+ *
+ * Results:
+ * none.
+ *
+ * Side effects:
+ * writes on the given memory location.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+ static VOID
+ stubBuildTrailing(pos, ver, dbgOnly)
+ char *pos;
+ char *ver;
+ int dbgOnly;
+ {
+ char *pos2;
+
+ #ifdef __WIN32__
+ /* append version w/o decimal */
+ pos2 = ver;
+ while (*pos2 != '\0') {
+ if (*pos2 != '.') *pos++ = *pos2++;
+ else pos2++;
+ };
+ #else /* fix me! */
+ /* append version w/ decimal */
+ pos2 = ver;
+ while (*pos2 != '\0') {
+ *pos++ = *pos2++;
+ };
+ #endif
+
+ /* if asked, add the debug suffix */
+ if (dbgOnly != 0) *pos++ = 'd';
+
+ /* append the extension */
+ pos2 = shLibExt;
+ while (*pos2 != '\0') {
+ *pos++ = *pos2++;
+ };
+
+ /* terminate it */
+ *pos = '\0';
+ };
PatchFiles:
generic/tcl.h, win/tclAppInit.c, win/makefile.vc
Comments:
This thing needs alpha testers. Give me some input :)
Last modified
1999-09-27
1999-09-27
(195.108.246.50)
Note: you are looking at
the snapshot of an old wiki
- much of this information
is likely to be very outdated
