diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-01-09 19:41:11 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-01-09 19:41:11 +0100 |
commit | 8a5115cf18751022387af2085f374d38c60dde83 (patch) | |
tree | 626c3e93cd3127931c85e631d50d6ced1b5f6380 | |
parent | 5f24542e5eda590acdbee89b120fa2e19ec7596e (diff) |
patch 7.4.1070v7.4.1070
Problem: The Tcl interface can't be loaded dynamically on Unix.
Solution: Make it possible to load it dynamically. (Ken Takata)
-rw-r--r-- | runtime/doc/if_tcl.txt | 20 | ||||
-rw-r--r-- | runtime/doc/options.txt | 11 | ||||
-rw-r--r-- | runtime/doc/quickref.txt | 1 | ||||
-rw-r--r-- | runtime/optwin.vim | 4 | ||||
-rw-r--r-- | src/Makefile | 10 | ||||
-rwxr-xr-x | src/auto/configure | 18 | ||||
-rw-r--r-- | src/config.h.in | 3 | ||||
-rw-r--r-- | src/configure.in | 17 | ||||
-rw-r--r-- | src/if_tcl.c | 31 | ||||
-rw-r--r-- | src/option.c | 6 | ||||
-rw-r--r-- | src/option.h | 3 | ||||
-rw-r--r-- | src/version.c | 2 |
12 files changed, 104 insertions, 22 deletions
diff --git a/runtime/doc/if_tcl.txt b/runtime/doc/if_tcl.txt index bc9d3b8e20..4d02233f08 100644 --- 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 version Vim was compiled with. 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 index a17cf71c80..8cf2aa7bd4 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -7437,6 +7437,17 @@ A jump table for the options with a short description can be found at |Q_op|. 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 index fb10cccda5..8450cdd89c 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -909,6 +909,7 @@ Short explanation of each option: *option-list* '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 index 7318483306..314e7f3e00 100644 --- 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 <SID>OptionG("rubydll", &rubydll) endif +if exists("&tcldll") + call append("$", "tcldll\tname of the Tcl dynamic library") + call <SID>OptionG("tcldll", &tcldll) +endif set cpo&vim diff --git a/src/Makefile b/src/Makefile index 5cf116d5a0..72f0eaaf29 100644 --- 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) $(PROFILE_CFLAGS) $(SANITIZER_CFLAGS) $(LEAK_ # 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 index a0452795a5..e07d7ecf38 100755 --- 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 @@ $as_echo_n "checking Tcl version... " >&6; } { $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 @@ $as_echo_n "checking for location of tclConfig.sh script... " >&6; } { $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 @@ $as_echo "<not found>" >&6; } $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 index e92cc5e9f1..d4fd50a371 100644 --- 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 index 17368c1ac9..6048e8f9c0 100644 --- 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"; then 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"; then 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"; then 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 index 1f37e12778..995a5c7273 100644 --- a/src/if_tcl.c +++ b/src/if_tcl.c @@ -160,6 +160,20 @@ static struct ref refsdeleted; /* dummy object for deleted ref list */ typedef int HANDLE; # endif +# ifndef WIN3264 +# include <dlfcn.h> +# 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 void *); /* * 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 verbose) 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 verbose) } 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 index 9e7f303276..bc88d45547 100644 --- 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 index af5b988963..f178ea7f88 100644 --- 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 index e2013d1aaa..af26ae3706 100644 --- 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, |