# HG changeset patch # User Christian Brabandt # Date 1452365105 -3600 # Node ID c9fc24b7629385e94b7479146e610fc7c28d07a3 # Parent e1a5a830aebb973d924ac4a4806d29de574b73ba commit https://github.com/vim/vim/commit/8a5115cf18751022387af2085f374d38c60dde83 Author: Bram Moolenaar Date: Sat Jan 9 19:41:11 2016 +0100 patch 7.4.1070 Problem: The Tcl interface can't be loaded dynamically on Unix. Solution: Make it possible to load it dynamically. (Ken Takata) diff --git a/runtime/doc/if_tcl.txt b/runtime/doc/if_tcl.txt --- a/runtime/doc/if_tcl.txt +++ b/runtime/doc/if_tcl.txt @@ -515,12 +515,15 @@ startup file (usually "~/.vimrc" on Unix ============================================================================== 9. Dynamic loading *tcl-dynamic* -On MS-Windows the Tcl library can be loaded dynamically. The |:version| -output then includes |+tcl/dyn|. +On MS-Windows and Unix the Tcl library can be loaded dynamically. The +|:version| output then includes |+tcl/dyn|. -This means that Vim will search for the Tcl DLL file only when needed. When -you don't use the Tcl interface you don't need it, thus you can use Vim -without this DLL file. +This means that Vim will search for the Tcl DLL or shared library file only +when needed. When you don't use the Tcl interface you don't need it, thus you +can use Vim without this file. + + +MS-Windows ~ To use the Tcl interface the Tcl DLL must be in your search path. In a console window type "path" to see what directories are used. @@ -529,5 +532,12 @@ The name of the DLL must match the Tcl v Currently the name is "tcl86.dll". That is for Tcl 8.6. To know for sure edit "gvim.exe" and search for "tcl\d*.dll\c". + +Unix ~ + +The 'tcldll' option can be used to specify the Tcl shared library file instead +of DYNAMIC_TCL_DLL file what was specified at compile time. The version of +the shared library must match the Tcl version Vim was compiled with. + ============================================================================== vim:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -7437,6 +7437,17 @@ A jump table for the options with a shor Resetting this option is useful when using a ":tag" command in a mapping which should not change the tagstack. + *'tcldll'* +'tcldll' string (default depends on the build) + global + {not in Vi} + {only available when compiled with the |+tcl/dyn| + feature} + Specifies the name of the Tcl shared library. The default is + DYNAMIC_TCL_DLL, which was specified at compile time. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + *'term'* *E529* *E530* *E531* 'term' string (default is $TERM, if that fails: in the GUI: "builtin_gui" diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -909,6 +909,7 @@ Short explanation of each option: *opti 'tagrelative' 'tr' file names in tag file are relative 'tags' 'tag' list of file names used by the tag command 'tagstack' 'tgst' push tags onto the tag stack +'tcldll' name of the Tcl dynamic library 'term' name of the terminal 'termbidi' 'tbidi' terminal takes care of bi-directionality 'termencoding' 'tenc' character encoding used by the terminal diff --git a/runtime/optwin.vim b/runtime/optwin.vim --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -1331,6 +1331,10 @@ if exists("&rubydll") call append("$", "rubydll\tname of the Ruby dynamic library") call OptionG("rubydll", &rubydll) endif +if exists("&tcldll") + call append("$", "tcldll\tname of the Tcl dynamic library") + call OptionG("tcldll", &tcldll) +endif set cpo&vim diff --git a/src/Makefile b/src/Makefile --- a/src/Makefile +++ b/src/Makefile @@ -445,7 +445,9 @@ CClink = $(CC) # TCL # Uncomment this when you want to include the Tcl interface. +# First one is for static linking, second one for dynamic loading. #CONF_OPT_TCL = --enable-tclinterp +#CONF_OPT_TCL = --enable-tclinterp=dynamic #CONF_OPT_TCL = --enable-tclinterp --with-tclsh=tclsh8.4 # CSCOPE @@ -1375,7 +1377,7 @@ SHELL = /bin/sh .SUFFIXES: .c .o .pro PRE_DEFS = -Iproto $(DEFS) $(GUI_DEFS) $(GUI_IPATH) $(CPPFLAGS) $(EXTRA_IPATHS) -POST_DEFS = $(X_CFLAGS) $(MZSCHEME_CFLAGS) $(TCL_CFLAGS) $(EXTRA_DEFS) +POST_DEFS = $(X_CFLAGS) $(MZSCHEME_CFLAGS) $(EXTRA_DEFS) ALL_CFLAGS = $(PRE_DEFS) $(CFLAGS) $(PROFILE_CFLAGS) $(SANITIZER_CFLAGS) $(LEAK_CFLAGS) $(POST_DEFS) @@ -1383,7 +1385,7 @@ ALL_CFLAGS = $(PRE_DEFS) $(CFLAGS) $(PRO # with "-E". OSDEF_CFLAGS = $(PRE_DEFS) $(POST_DEFS) -LINT_CFLAGS = -DLINT -I. $(PRE_DEFS) $(POST_DEFS) $(RUBY_CFLAGS) $(LUA_CFLAGS) $(PERL_CFLAGS) $(PYTHON_CFLAGS) $(PYTHON3_CFLAGS) -Dinline= -D__extension__= -Dalloca=alloca +LINT_CFLAGS = -DLINT -I. $(PRE_DEFS) $(POST_DEFS) $(RUBY_CFLAGS) $(LUA_CFLAGS) $(PERL_CFLAGS) $(PYTHON_CFLAGS) $(PYTHON3_CFLAGS) $(TCL_CFLAGS) -Dinline= -D__extension__= -Dalloca=alloca LINT_EXTRA = -DUSE_SNIFF -DHANGUL_INPUT -D"__attribute__(x)=" @@ -2756,7 +2758,7 @@ objects/if_sniff.o: if_sniff.c $(CCC) -o $@ if_sniff.c objects/if_tcl.o: if_tcl.c - $(CCC) -o $@ if_tcl.c + $(CCC) $(TCL_CFLAGS) -o $@ if_tcl.c objects/integration.o: integration.c $(CCC) -o $@ integration.c @@ -2801,7 +2803,7 @@ objects/ops.o: ops.c $(CCC) -o $@ ops.c objects/option.o: option.c - $(CCC) $(LUA_CFLAGS) $(PERL_CFLAGS) $(PYTHON_CFLAGS) $(PYTHON3_CFLAGS) $(RUBY_CFLAGS) -o $@ option.c + $(CCC) $(LUA_CFLAGS) $(PERL_CFLAGS) $(PYTHON_CFLAGS) $(PYTHON3_CFLAGS) $(RUBY_CFLAGS) $(TCL_CFLAGS) -o $@ option.c objects/os_beos.o: os_beos.c $(CCC) -o $@ os_beos.c diff --git a/src/auto/configure b/src/auto/configure --- a/src/auto/configure +++ b/src/auto/configure @@ -1468,7 +1468,7 @@ Optional Features: --enable-perlinterp=OPTS Include Perl interpreter. default=no OPTS=no/yes/dynamic --enable-pythoninterp=OPTS Include Python interpreter. default=no OPTS=no/yes/dynamic --enable-python3interp=OPTS Include Python3 interpreter. default=no OPTS=no/yes/dynamic - --enable-tclinterp Include Tcl interpreter. + --enable-tclinterp=OPTS Include Tcl interpreter. default=no OPTS=no/yes/dynamic --enable-rubyinterp=OPTS Include Ruby interpreter. default=no OPTS=no/yes/dynamic --enable-cscope Include cscope interface. --enable-workshop Include Sun Visual Workshop support. @@ -6616,7 +6616,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_tclinterp" >&5 $as_echo "$enable_tclinterp" >&6; } -if test "$enable_tclinterp" = "yes"; then +if test "$enable_tclinterp" = "yes" -o "$enable_tclinterp" = "dynamic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking --with-tclsh argument" >&5 $as_echo_n "checking --with-tclsh argument... " >&6; } @@ -6852,6 +6852,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tclver - OK" >&5 $as_echo "$tclver - OK" >&6; }; tclloc=`echo 'set l [info library];set i [string last lib $l];incr i -2;puts [string range $l 0 $i]' | $vi_cv_path_tcl -` + tcldll=`echo 'puts libtcl[info tclversion][info sharedlibextension]' | $vi_cv_path_tcl -` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for location of Tcl include" >&5 $as_echo_n "checking for location of Tcl include... " >&6; } @@ -6888,7 +6889,11 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $try/tclConfig.sh" >&5 $as_echo "$try/tclConfig.sh" >&6; } . "$try/tclConfig.sh" - TCL_LIBS=`eval echo "$TCL_LIB_SPEC $TCL_LIBS"` + if test "$enable_tclinterp" = "dynamic"; then + TCL_LIBS=`eval echo "$TCL_STUB_LIB_SPEC $TCL_LIBS"` + else + TCL_LIBS=`eval echo "$TCL_LIB_SPEC $TCL_LIBS"` + fi TCL_DEFS=`echo $TCL_DEFS | sed -e 's/\\\\ /\\\\X/g' | tr ' ' '\012' | sed -e '/^[^-]/d' -e '/^-[^D]/d' -e '/-D[^_]/d' -e 's/-D_/ -D_/' | tr '\012' ' ' | sed -e 's/\\\\X/\\\\ /g'` break fi @@ -6937,6 +6942,13 @@ fi $as_echo "too old; need Tcl version 8.0 or later" >&6; } fi fi + if test "$enable_tclinterp" = "dynamic"; then + if test "X$TCL_SRC" != "X" -a "X$tcldll" != "X"; then + $as_echo "#define DYNAMIC_TCL 1" >>confdefs.h + + TCL_CFLAGS="-DDYNAMIC_TCL_DLL=\\\"$tcldll\\\" -DDYNAMIC_TCL_VER=\\\"$tclver\\\" $TCL_CFLAGS" + fi + fi if test "$fail_if_missing" = "yes" -a -z "$TCL_SRC"; then as_fn_error $? "could not configure Tcl" "$LINENO" 5 fi diff --git a/src/config.h.in b/src/config.h.in --- a/src/config.h.in +++ b/src/config.h.in @@ -360,6 +360,9 @@ /* Define if you want to include the Tcl interpreter. */ #undef FEAT_TCL +/* Define for linking via dlopen() or LoadLibrary() */ +#undef DYNAMIC_TCL + /* Define if you want to include the Sniff interface. */ #undef FEAT_SNIFF diff --git a/src/configure.in b/src/configure.in --- a/src/configure.in +++ b/src/configure.in @@ -1622,11 +1622,11 @@ fi AC_MSG_CHECKING(--enable-tclinterp argument) AC_ARG_ENABLE(tclinterp, - [ --enable-tclinterp Include Tcl interpreter.], , + [ --enable-tclinterp[=OPTS] Include Tcl interpreter. [default=no] [OPTS=no/yes/dynamic]], , [enable_tclinterp="no"]) AC_MSG_RESULT($enable_tclinterp) -if test "$enable_tclinterp" = "yes"; then +if test "$enable_tclinterp" = "yes" -o "$enable_tclinterp" = "dynamic"; then dnl on FreeBSD tclsh is a silly script, look for tclsh8.[5420] AC_MSG_CHECKING(--with-tclsh argument) @@ -1660,6 +1660,7 @@ if test "$enable_tclinterp" = "yes"; the tclver=`echo 'puts [[info tclversion]]' | $vi_cv_path_tcl -` AC_MSG_RESULT($tclver - OK); tclloc=`echo 'set l [[info library]];set i [[string last lib $l]];incr i -2;puts [[string range $l 0 $i]]' | $vi_cv_path_tcl -` + tcldll=`echo 'puts libtcl[[info tclversion]][[info sharedlibextension]]' | $vi_cv_path_tcl -` AC_MSG_CHECKING(for location of Tcl include) if test "x$MACOSX" != "xyes"; then @@ -1694,7 +1695,11 @@ if test "$enable_tclinterp" = "yes"; the AC_MSG_RESULT($try/tclConfig.sh) . "$try/tclConfig.sh" dnl use eval, because tcl 8.2 includes ${TCL_DBGX} - TCL_LIBS=`eval echo "$TCL_LIB_SPEC $TCL_LIBS"` + if test "$enable_tclinterp" = "dynamic"; then + TCL_LIBS=`eval echo "$TCL_STUB_LIB_SPEC $TCL_LIBS"` + else + TCL_LIBS=`eval echo "$TCL_LIB_SPEC $TCL_LIBS"` + fi dnl Use $TCL_DEFS for -D_THREAD_SAFE et al. But only use the dnl "-D_ABC" items. Watch out for -DFOO=long\ long. TCL_DEFS=`echo $TCL_DEFS | sed -e 's/\\\\ /\\\\X/g' | tr ' ' '\012' | sed -e '/^[[^-]]/d' -e '/^-[[^D]]/d' -e '/-D[[^_]]/d' -e 's/-D_/ -D_/' | tr '\012' ' ' | sed -e 's/\\\\X/\\\\ /g'` @@ -1739,6 +1744,12 @@ if test "$enable_tclinterp" = "yes"; the AC_MSG_RESULT(too old; need Tcl version 8.0 or later) fi fi + if test "$enable_tclinterp" = "dynamic"; then + if test "X$TCL_SRC" != "X" -a "X$tcldll" != "X"; then + AC_DEFINE(DYNAMIC_TCL) + TCL_CFLAGS="-DDYNAMIC_TCL_DLL=\\\"$tcldll\\\" -DDYNAMIC_TCL_VER=\\\"$tclver\\\" $TCL_CFLAGS" + fi + fi if test "$fail_if_missing" = "yes" -a -z "$TCL_SRC"; then AC_MSG_ERROR([could not configure Tcl]) fi diff --git a/src/if_tcl.c b/src/if_tcl.c --- a/src/if_tcl.c +++ b/src/if_tcl.c @@ -160,6 +160,20 @@ static struct ref refsdeleted; /* dummy typedef int HANDLE; # endif +# ifndef WIN3264 +# include +# define HANDLE void* +# define TCL_PROC void* +# define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL) +# define symbol_from_dll dlsym +# define close_dll dlclose +# else +# define TCL_PROC FARPROC +# define load_dll vimLoadLib +# define symbol_from_dll GetProcAddress +# define close_dll FreeLibrary +# endif + /* * Declare HANDLE for tcl.dll and function pointers. */ @@ -170,7 +184,6 @@ void (*dll_Tcl_FindExecutable)(const voi /* * Table of name to function pointer of tcl. */ -#define TCL_PROC FARPROC static struct { char* name; TCL_PROC* ptr; @@ -197,7 +210,7 @@ tcl_runtime_link_init(char *libname, int if (hTclLib) return OK; - if (!(hTclLib = vimLoadLib(libname))) + if (!(hTclLib = load_dll(libname))) { if (verbose) EMSG2(_(e_loadlib), libname); @@ -205,10 +218,10 @@ tcl_runtime_link_init(char *libname, int } for (i = 0; tcl_funcname_table[i].ptr; ++i) { - if (!(*tcl_funcname_table[i].ptr = GetProcAddress(hTclLib, + if (!(*tcl_funcname_table[i].ptr = symbol_from_dll(hTclLib, tcl_funcname_table[i].name))) { - FreeLibrary(hTclLib); + close_dll(hTclLib); hTclLib = NULL; if (verbose) EMSG2(_(e_loadfunc), tcl_funcname_table[i].name); @@ -246,13 +259,13 @@ tcl_enabled(verbose) int verbose; { if (!stubs_initialized && find_executable_arg != NULL - && tcl_runtime_link_init(DYNAMIC_TCL_DLL, verbose) == OK) + && tcl_runtime_link_init((char *)p_tcldll, verbose) == OK) { Tcl_Interp *interp; dll_Tcl_FindExecutable(find_executable_arg); - if (interp = dll_Tcl_CreateInterp()) + if ((interp = dll_Tcl_CreateInterp()) != NULL) { if (Tcl_InitStubs(interp, DYNAMIC_TCL_VER, 0)) { @@ -272,7 +285,7 @@ tcl_end() #ifdef DYNAMIC_TCL if (hTclLib) { - FreeLibrary(hTclLib); + close_dll(hTclLib); hTclLib = NULL; } #endif @@ -2039,6 +2052,10 @@ tcldelallrefs(ref) int err; char *result; + /* TODO: this code currently crashes Vim on exit */ + if (exiting) + return; + while (ref != NULL) { next = ref->next; diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -2609,6 +2609,12 @@ static struct vimoption {"tagstack", "tgst", P_BOOL|P_VI_DEF, (char_u *)&p_tgst, PV_NONE, {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, +#if defined(DYNAMIC_TCL) + {"tcldll", NULL, P_STRING|P_VI_DEF|P_SECURE, + (char_u *)&p_tcldll, PV_NONE, + {(char_u *)DYNAMIC_TCL_DLL, (char_u *)0L} + SCRIPTID_INIT}, +#endif {"term", NULL, P_STRING|P_EXPAND|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RALL, (char_u *)&T_NAME, PV_NONE, {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, diff --git a/src/option.h b/src/option.h --- a/src/option.h +++ b/src/option.h @@ -832,6 +832,9 @@ EXTERN long p_tl; /* 'taglength' */ EXTERN int p_tr; /* 'tagrelative' */ EXTERN char_u *p_tags; /* 'tags' */ EXTERN int p_tgst; /* 'tagstack' */ +#if defined(DYNAMIC_TCL) +EXTERN char_u *p_tcldll; /* 'tcldll' */ +#endif #ifdef FEAT_ARABIC EXTERN int p_tbidi; /* 'termbidi' */ #endif diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1070, +/**/ 1069, /**/ 1068,