mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
updated for version 7.3.451
Problem: Tcl doesn't work on 64 MS-Windows. Solution: Make it work. (Dave Bodenstab)
This commit is contained in:
@@ -616,7 +616,7 @@ CFLAGS = $(CFLAGS) -DFEAT_TCL -DDYNAMIC_TCL -DDYNAMIC_TCL_DLL=\"$(TCL_DLL)\" \
|
|||||||
-DDYNAMIC_TCL_VER=\"$(TCL_VER_LONG)\"
|
-DDYNAMIC_TCL_VER=\"$(TCL_VER_LONG)\"
|
||||||
TCL_OBJ = $(OUTDIR)\if_tcl.obj
|
TCL_OBJ = $(OUTDIR)\if_tcl.obj
|
||||||
TCL_INC = /I "$(TCL)\Include" /I "$(TCL)"
|
TCL_INC = /I "$(TCL)\Include" /I "$(TCL)"
|
||||||
TCL_LIB = $(TCL)\lib\tclstub$(TCL_VER).lib
|
TCL_LIB = "$(TCL)\lib\tclstub$(TCL_VER).lib"
|
||||||
!else
|
!else
|
||||||
CFLAGS = $(CFLAGS) -DFEAT_TCL
|
CFLAGS = $(CFLAGS) -DFEAT_TCL
|
||||||
TCL_OBJ = $(OUTDIR)\if_tcl.obj
|
TCL_OBJ = $(OUTDIR)\if_tcl.obj
|
||||||
|
123
src/if_tcl.c
123
src/if_tcl.c
@@ -79,12 +79,13 @@ TODO:
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Tcl_Interp *interp;
|
Tcl_Interp *interp;
|
||||||
|
int exitvalue;
|
||||||
int range_start, range_end;
|
int range_start, range_end;
|
||||||
int lbase;
|
int lbase;
|
||||||
char *curbuf, *curwin;
|
char *curbuf, *curwin;
|
||||||
} tcl_info;
|
} tcl_info;
|
||||||
|
|
||||||
static tcl_info tclinfo = { NULL, 0, 0, 0, NULL, NULL };
|
static tcl_info tclinfo = { NULL, 0, 0, 0, 0, NULL, NULL };
|
||||||
|
|
||||||
#define VAR_RANGE1 "::vim::range(start)"
|
#define VAR_RANGE1 "::vim::range(start)"
|
||||||
#define VAR_RANGE2 "::vim::range(begin)"
|
#define VAR_RANGE2 "::vim::range(begin)"
|
||||||
@@ -279,16 +280,19 @@ tcl_end()
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Replace standard "exit" and "catch" commands.
|
* Replace standard "exit" command.
|
||||||
*
|
*
|
||||||
* This is a design flaw in Tcl - the standard "exit" command just calls
|
* Delete the Tcl interpreter; a new one will be created with the next
|
||||||
* exit() and kills the application. It should return TCL_EXIT to the
|
* :tcl command). The exit code is saved (and retrieved in tclexit()).
|
||||||
* app, which then decides if it wants to terminate or not. In our case,
|
* Since Tcl's exit is never expected to return and this replacement
|
||||||
* we just delete the Tcl interpreter (and create a new one with the next
|
* does, then (except for a trivial case) additional Tcl commands will
|
||||||
* :tcl command).
|
* be run. Since the interpreter is now marked as deleted, an error
|
||||||
|
* will be returned -- typically "attempt to call eval in deleted
|
||||||
|
* interpreter". Hopefully, at this point, checks for TCL_ERROR take
|
||||||
|
* place and control percolates back up to Vim -- but with this new error
|
||||||
|
* string in the interpreter's result value. Therefore it would be
|
||||||
|
* useless for this routine to return the exit code via Tcl_SetResult().
|
||||||
*/
|
*/
|
||||||
#define TCL_EXIT 5
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
exitcmd(dummy, interp, objc, objv)
|
exitcmd(dummy, interp, objc, objv)
|
||||||
ClientData dummy UNUSED;
|
ClientData dummy UNUSED;
|
||||||
@@ -305,51 +309,16 @@ exitcmd(dummy, interp, objc, objv)
|
|||||||
break;
|
break;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case 1:
|
case 1:
|
||||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(value));
|
tclinfo.exitvalue = value;
|
||||||
return TCL_EXIT;
|
|
||||||
|
Tcl_DeleteInterp(interp);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Tcl_WrongNumArgs(interp, 1, objv, "?returnCode?");
|
Tcl_WrongNumArgs(interp, 1, objv, "?returnCode?");
|
||||||
}
|
}
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
catchcmd(dummy, interp, objc, objv)
|
|
||||||
ClientData dummy UNUSED;
|
|
||||||
Tcl_Interp *interp;
|
|
||||||
int objc;
|
|
||||||
Tcl_Obj *CONST objv[];
|
|
||||||
{
|
|
||||||
char *varname = NULL;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
switch (objc)
|
|
||||||
{
|
|
||||||
case 3:
|
|
||||||
varname = Tcl_GetStringFromObj(objv[2], NULL);
|
|
||||||
/* fallthrough */
|
|
||||||
case 2:
|
|
||||||
Tcl_ResetResult(interp);
|
|
||||||
Tcl_AllowExceptions(interp);
|
|
||||||
result = Tcl_EvalObj(interp, objv[1]);
|
|
||||||
if (result == TCL_EXIT)
|
|
||||||
return result;
|
|
||||||
if (varname)
|
|
||||||
{
|
|
||||||
if (Tcl_SetVar(interp, varname, Tcl_GetStringResult(interp), 0) == NULL)
|
|
||||||
{
|
|
||||||
Tcl_SetResult(interp, "couldn't save command result in variable", TCL_STATIC);
|
|
||||||
return TCL_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
|
|
||||||
return TCL_OK;
|
|
||||||
default:
|
|
||||||
Tcl_WrongNumArgs(interp, 1, objv, "command ?varName?");
|
|
||||||
}
|
|
||||||
return TCL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "::vim::beep" - what Vi[m] does best :-)
|
* "::vim::beep" - what Vi[m] does best :-)
|
||||||
*/
|
*/
|
||||||
@@ -372,6 +341,7 @@ beepcmd(dummy, interp, objc, objv)
|
|||||||
/*
|
/*
|
||||||
* "::vim::buffer list" - create a list of buffer commands.
|
* "::vim::buffer list" - create a list of buffer commands.
|
||||||
* "::vim::buffer {N}" - create buffer command for buffer N.
|
* "::vim::buffer {N}" - create buffer command for buffer N.
|
||||||
|
* "::vim::buffer exists {N}" - test if buffer N exists.
|
||||||
* "::vim::buffer new" - create a new buffer (not implemented)
|
* "::vim::buffer new" - create a new buffer (not implemented)
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@@ -1663,7 +1633,7 @@ channel_gethandle(instance, direction, handleptr)
|
|||||||
static Tcl_ChannelType channel_type =
|
static Tcl_ChannelType channel_type =
|
||||||
{
|
{
|
||||||
"vimmessage", /* typeName */
|
"vimmessage", /* typeName */
|
||||||
NULL, /* version */
|
TCL_CHANNEL_VERSION_2, /* version */
|
||||||
channel_close, /* closeProc */
|
channel_close, /* closeProc */
|
||||||
channel_input, /* inputProc */
|
channel_input, /* inputProc */
|
||||||
channel_output, /* outputProc */
|
channel_output, /* outputProc */
|
||||||
@@ -1678,6 +1648,8 @@ static Tcl_ChannelType channel_type =
|
|||||||
NULL, /* flushProc */
|
NULL, /* flushProc */
|
||||||
NULL, /* handlerProc */
|
NULL, /* handlerProc */
|
||||||
#endif
|
#endif
|
||||||
|
/* The following should not be necessary since TCL_CHANNEL_VERSION_2 was
|
||||||
|
* set above */
|
||||||
#ifdef TCL_CHANNEL_VERSION_3
|
#ifdef TCL_CHANNEL_VERSION_3
|
||||||
NULL, /* wideSeekProc */
|
NULL, /* wideSeekProc */
|
||||||
#endif
|
#endif
|
||||||
@@ -1741,7 +1713,9 @@ tclinit(eap)
|
|||||||
Tcl_Interp *interp;
|
Tcl_Interp *interp;
|
||||||
static Tcl_Channel ch1, ch2;
|
static Tcl_Channel ch1, ch2;
|
||||||
|
|
||||||
/* replace stdout and stderr */
|
/* Create replacement channels for stdout and stderr; this has to be
|
||||||
|
* done each time an interpreter is created since the channels are closed
|
||||||
|
* when the interpreter is deleted */
|
||||||
ch1 = Tcl_CreateChannel(&channel_type, "vimout", VIMOUT, TCL_WRITABLE);
|
ch1 = Tcl_CreateChannel(&channel_type, "vimout", VIMOUT, TCL_WRITABLE);
|
||||||
ch2 = Tcl_CreateChannel(&channel_type, "vimerr", VIMERR, TCL_WRITABLE);
|
ch2 = Tcl_CreateChannel(&channel_type, "vimerr", VIMERR, TCL_WRITABLE);
|
||||||
Tcl_SetStdChannel(ch1, TCL_STDOUT);
|
Tcl_SetStdChannel(ch1, TCL_STDOUT);
|
||||||
@@ -1761,15 +1735,18 @@ tclinit(eap)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Tcl_SetChannelOption(interp, ch1, "-buffering", "line");
|
Tcl_SetChannelOption(interp, ch1, "-buffering", "line");
|
||||||
|
#ifdef WIN3264
|
||||||
|
Tcl_SetChannelOption(interp, ch1, "-translation", "lf");
|
||||||
|
#endif
|
||||||
Tcl_SetChannelOption(interp, ch2, "-buffering", "line");
|
Tcl_SetChannelOption(interp, ch2, "-buffering", "line");
|
||||||
|
#ifdef WIN3264
|
||||||
|
Tcl_SetChannelOption(interp, ch2, "-translation", "lf");
|
||||||
|
#endif
|
||||||
|
|
||||||
/* replace some standard Tcl commands */
|
/* replace standard Tcl exit command */
|
||||||
Tcl_DeleteCommand(interp, "exit");
|
Tcl_DeleteCommand(interp, "exit");
|
||||||
Tcl_CreateObjCommand(interp, "exit", exitcmd,
|
Tcl_CreateObjCommand(interp, "exit", exitcmd,
|
||||||
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
||||||
Tcl_DeleteCommand(interp, "catch");
|
|
||||||
Tcl_CreateObjCommand(interp, "catch", catchcmd,
|
|
||||||
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
|
||||||
|
|
||||||
/* new commands, in ::vim namespace */
|
/* new commands, in ::vim namespace */
|
||||||
Tcl_CreateObjCommand(interp, "::vim::buffer", buffercmd,
|
Tcl_CreateObjCommand(interp, "::vim::buffer", buffercmd,
|
||||||
@@ -1821,6 +1798,8 @@ tclinit(eap)
|
|||||||
tclinfo.range_end = row2tcl(eap->line2);
|
tclinfo.range_end = row2tcl(eap->line2);
|
||||||
tclupdatevars();
|
tclupdatevars();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tclinfo.exitvalue = 0;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1884,30 +1863,23 @@ tclexit(error)
|
|||||||
{
|
{
|
||||||
int newerr = OK;
|
int newerr = OK;
|
||||||
|
|
||||||
if (error == TCL_EXIT)
|
if (Tcl_InterpDeleted(tclinfo.interp) /* True if we intercepted Tcl's exit command */
|
||||||
|
#if (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 5) || TCL_MAJOR_VERSION > 8
|
||||||
|
|| Tcl_LimitExceeded(tclinfo.interp) /* True if the interpreter cannot continue */
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
int retval;
|
|
||||||
char buf[50];
|
char buf[50];
|
||||||
Tcl_Obj *robj;
|
|
||||||
|
|
||||||
robj = Tcl_GetObjResult(tclinfo.interp);
|
sprintf(buf, _("E572: exit code %d"), tclinfo.exitvalue);
|
||||||
if (Tcl_GetIntFromObj(tclinfo.interp, robj, &retval) != TCL_OK)
|
tclerrmsg(buf);
|
||||||
|
if (tclinfo.exitvalue == 0)
|
||||||
{
|
{
|
||||||
EMSG(_("E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"));
|
did_emsg = 0;
|
||||||
newerr = FAIL;
|
newerr = OK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
newerr = FAIL;
|
||||||
sprintf(buf, _("E572: exit code %d"), retval);
|
|
||||||
tclerrmsg(buf);
|
|
||||||
if (retval == 0)
|
|
||||||
{
|
|
||||||
did_emsg = 0;
|
|
||||||
newerr = OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
newerr = FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tcldelthisinterp();
|
tcldelthisinterp();
|
||||||
}
|
}
|
||||||
@@ -2021,7 +1993,12 @@ ex_tcldo(eap)
|
|||||||
Tcl_SetVar(tclinfo.interp, var_line, line, 0);
|
Tcl_SetVar(tclinfo.interp, var_line, line, 0);
|
||||||
Tcl_AllowExceptions(tclinfo.interp);
|
Tcl_AllowExceptions(tclinfo.interp);
|
||||||
err = Tcl_Eval(tclinfo.interp, script);
|
err = Tcl_Eval(tclinfo.interp, script);
|
||||||
if (err != TCL_OK)
|
if (err != TCL_OK
|
||||||
|
|| Tcl_InterpDeleted(tclinfo.interp)
|
||||||
|
#if (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 5) || TCL_MAJOR_VERSION > 8
|
||||||
|
|| Tcl_LimitExceeded(tclinfo.interp)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
break;
|
break;
|
||||||
line = (char *)Tcl_GetVar(tclinfo.interp, var_line, 0);
|
line = (char *)Tcl_GetVar(tclinfo.interp, var_line, 0);
|
||||||
if (line)
|
if (line)
|
||||||
|
@@ -714,6 +714,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
451,
|
||||||
/**/
|
/**/
|
||||||
450,
|
450,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user