]> granicus.if.org Git - vim/commitdiff
patch 7.4.1070 v7.4.1070
authorBram Moolenaar <Bram@vim.org>
Sat, 9 Jan 2016 18:41:11 +0000 (19:41 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 9 Jan 2016 18:41:11 +0000 (19:41 +0100)
Problem:    The Tcl interface can't be loaded dynamically on Unix.
Solution:   Make it possible to load it dynamically. (Ken Takata)

12 files changed:
runtime/doc/if_tcl.txt
runtime/doc/options.txt
runtime/doc/quickref.txt
runtime/optwin.vim
src/Makefile
src/auto/configure
src/config.h.in
src/configure.in
src/if_tcl.c
src/option.c
src/option.h
src/version.c

index bc9d3b8e20c1ffc3f1270fc6f73efc50c90165a4..4d02233f08dc1b2fb1b1fc1025faaadd6979f62e 100644 (file)
@@ -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:
index a17cf71c804c49b7a26d1927eee7d7bf1f4dd0ca..8cf2aa7bd49b66ca7eb997f1ab649d6c0d3e9519 100644 (file)
@@ -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"
index fb10cccda5bb7f48811839d03a0cc953927c33b6..8450cdd89cae93599e8aad15b71c1d3e692a2576 100644 (file)
@@ -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
index 7318483306ba959582cef081c84a0329c0f50e30..314e7f3e0007845047cd9dabfa1875e0789c1eb1 100644 (file)
@@ -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
 
index 5cf116d5a0247ed9e6efb1f2485ec7581f273a78..72f0eaaf297ce188e337fc9f566f7ea3eb9775ef 100644 (file)
@@ -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
index a0452795a5be909723e7e568f5c96ba07a028abc..e07d7ecf387683ac4b5b26f297fc02f34365def9 100755 (executable)
@@ -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
index e92cc5e9f126f943bd1511ea05562d1fd7cefaad..d4fd50a3711100009c69db23df098375369e2235 100644 (file)
 /* 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
 
index 17368c1ac9210521e2f8c4ab6949387b09b915fc..6048e8f9c001fdc1a838e2668b089b3e11be7c9c 100644 (file)
@@ -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
index 1f37e1277801028126a95aa342e8bcddda2bd1d9..995a5c72739f7bc0a28fb3293de3d53fec982b18 100644 (file)
@@ -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;
index 9e7f30327679060a938396065478f738af6d96c9..bc88d455474e5d783f589d52ac21b602ada1f4cb 100644 (file)
@@ -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},
index af5b988963abef9dae68c61390d55d16590fb16e..f178ea7f88abbfd3af77479d0a9be58281d239dc 100644 (file)
@@ -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
index e2013d1aaa6fdaef2875b5ed0f4cfc57d349b8fe..af26ae3706a9a81c56a7cc3730f330ca121c4bf1 100644 (file)
@@ -741,6 +741,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1070,
 /**/
     1069,
 /**/