1 To: vim_dev@googlegroups.com
4 From: Bram Moolenaar <Bram@moolenaar.net>
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
11 Problem: Tcl doesn't work on 64 bit MS-Windows.
12 Solution: Make it work. (Dave Bodenstab)
13 Files: src/Make_mvc.mak, src/if_tcl.c
16 *** ../vim-7.3.450/src/Make_mvc.mak 2012-02-12 01:55:50.000000000 +0100
17 --- src/Make_mvc.mak 2012-02-22 15:43:01.000000000 +0100
20 -DDYNAMIC_TCL_VER=\"$(TCL_VER_LONG)\"
21 TCL_OBJ = $(OUTDIR)\if_tcl.obj
22 TCL_INC = /I "$(TCL)\Include" /I "$(TCL)"
23 ! TCL_LIB = $(TCL)\lib\tclstub$(TCL_VER).lib
25 CFLAGS = $(CFLAGS) -DFEAT_TCL
26 TCL_OBJ = $(OUTDIR)\if_tcl.obj
28 -DDYNAMIC_TCL_VER=\"$(TCL_VER_LONG)\"
29 TCL_OBJ = $(OUTDIR)\if_tcl.obj
30 TCL_INC = /I "$(TCL)\Include" /I "$(TCL)"
31 ! TCL_LIB = "$(TCL)\lib\tclstub$(TCL_VER).lib"
33 CFLAGS = $(CFLAGS) -DFEAT_TCL
34 TCL_OBJ = $(OUTDIR)\if_tcl.obj
35 *** ../vim-7.3.450/src/if_tcl.c 2011-07-27 14:15:41.000000000 +0200
36 --- src/if_tcl.c 2012-02-22 15:47:00.000000000 +0100
42 int range_start, range_end;
44 char *curbuf, *curwin;
47 ! static tcl_info tclinfo = { NULL, 0, 0, 0, NULL, NULL };
49 #define VAR_RANGE1 "::vim::range(start)"
50 #define VAR_RANGE2 "::vim::range(begin)"
56 int range_start, range_end;
58 char *curbuf, *curwin;
61 ! static tcl_info tclinfo = { NULL, 0, 0, 0, 0, NULL, NULL };
63 #define VAR_RANGE1 "::vim::range(start)"
64 #define VAR_RANGE2 "::vim::range(begin)"
67 ****************************************************************************/
70 ! * Replace standard "exit" and "catch" commands.
72 ! * This is a design flaw in Tcl - the standard "exit" command just calls
73 ! * exit() and kills the application. It should return TCL_EXIT to the
74 ! * app, which then decides if it wants to terminate or not. In our case,
75 ! * we just delete the Tcl interpreter (and create a new one with the next
81 exitcmd(dummy, interp, objc, objv)
82 ClientData dummy UNUSED;
84 ****************************************************************************/
87 ! * Replace standard "exit" command.
89 ! * Delete the Tcl interpreter; a new one will be created with the next
90 ! * :tcl command). The exit code is saved (and retrieved in tclexit()).
91 ! * Since Tcl's exit is never expected to return and this replacement
92 ! * does, then (except for a trivial case) additional Tcl commands will
93 ! * be run. Since the interpreter is now marked as deleted, an error
94 ! * will be returned -- typically "attempt to call eval in deleted
95 ! * interpreter". Hopefully, at this point, checks for TCL_ERROR take
96 ! * place and control percolates back up to Vim -- but with this new error
97 ! * string in the interpreter's result value. Therefore it would be
98 ! * useless for this routine to return the exit code via Tcl_SetResult().
101 exitcmd(dummy, interp, objc, objv)
102 ClientData dummy UNUSED;
108 ! Tcl_SetObjResult(interp, Tcl_NewIntObj(value));
111 ! Tcl_WrongNumArgs(interp, 1, objv, "?returnCode?");
117 ! catchcmd(dummy, interp, objc, objv)
118 ! ClientData dummy UNUSED;
119 ! Tcl_Interp *interp;
121 ! Tcl_Obj *CONST objv[];
123 ! char *varname = NULL;
129 ! varname = Tcl_GetStringFromObj(objv[2], NULL);
132 ! Tcl_ResetResult(interp);
133 ! Tcl_AllowExceptions(interp);
134 ! result = Tcl_EvalObj(interp, objv[1]);
135 ! if (result == TCL_EXIT)
139 ! if (Tcl_SetVar(interp, varname, Tcl_GetStringResult(interp), 0) == NULL)
141 ! Tcl_SetResult(interp, "couldn't save command result in variable", TCL_STATIC);
145 ! Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
148 ! Tcl_WrongNumArgs(interp, 1, objv, "command ?varName?");
156 ! tclinfo.exitvalue = value;
158 ! Tcl_DeleteInterp(interp);
161 ! Tcl_WrongNumArgs(interp, 1, objv, "?returnCode?");
169 * "::vim::buffer list" - create a list of buffer commands.
170 * "::vim::buffer {N}" - create buffer command for buffer N.
171 + * "::vim::buffer exists {N}" - test if buffer N exists.
172 * "::vim::buffer new" - create a new buffer (not implemented)
177 static Tcl_ChannelType channel_type =
179 "vimmessage", /* typeName */
180 ! NULL, /* version */
181 channel_close, /* closeProc */
182 channel_input, /* inputProc */
183 channel_output, /* outputProc */
185 static Tcl_ChannelType channel_type =
187 "vimmessage", /* typeName */
188 ! TCL_CHANNEL_VERSION_2, /* version */
189 channel_close, /* closeProc */
190 channel_input, /* inputProc */
191 channel_output, /* outputProc */
195 NULL, /* flushProc */
196 NULL, /* handlerProc */
198 + /* The following should not be necessary since TCL_CHANNEL_VERSION_2 was
200 #ifdef TCL_CHANNEL_VERSION_3
201 NULL, /* wideSeekProc */
206 static Tcl_Channel ch1, ch2;
208 ! /* replace stdout and stderr */
209 ch1 = Tcl_CreateChannel(&channel_type, "vimout", VIMOUT, TCL_WRITABLE);
210 ch2 = Tcl_CreateChannel(&channel_type, "vimerr", VIMERR, TCL_WRITABLE);
211 Tcl_SetStdChannel(ch1, TCL_STDOUT);
214 static Tcl_Channel ch1, ch2;
216 ! /* Create replacement channels for stdout and stderr; this has to be
217 ! * done each time an interpreter is created since the channels are closed
218 ! * when the interpreter is deleted */
219 ch1 = Tcl_CreateChannel(&channel_type, "vimout", VIMOUT, TCL_WRITABLE);
220 ch2 = Tcl_CreateChannel(&channel_type, "vimerr", VIMERR, TCL_WRITABLE);
221 Tcl_SetStdChannel(ch1, TCL_STDOUT);
226 Tcl_SetChannelOption(interp, ch1, "-buffering", "line");
227 Tcl_SetChannelOption(interp, ch2, "-buffering", "line");
229 ! /* replace some standard Tcl commands */
230 Tcl_DeleteCommand(interp, "exit");
231 Tcl_CreateObjCommand(interp, "exit", exitcmd,
232 (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
233 - Tcl_DeleteCommand(interp, "catch");
234 - Tcl_CreateObjCommand(interp, "catch", catchcmd,
235 - (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
237 /* new commands, in ::vim namespace */
238 Tcl_CreateObjCommand(interp, "::vim::buffer", buffercmd,
242 Tcl_SetChannelOption(interp, ch1, "-buffering", "line");
244 + Tcl_SetChannelOption(interp, ch1, "-translation", "lf");
246 Tcl_SetChannelOption(interp, ch2, "-buffering", "line");
248 + Tcl_SetChannelOption(interp, ch2, "-translation", "lf");
251 ! /* replace standard Tcl exit command */
252 Tcl_DeleteCommand(interp, "exit");
253 Tcl_CreateObjCommand(interp, "exit", exitcmd,
254 (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
256 /* new commands, in ::vim namespace */
257 Tcl_CreateObjCommand(interp, "::vim::buffer", buffercmd,
261 tclinfo.range_end = row2tcl(eap->line2);
265 + tclinfo.exitvalue = 0;
274 ! if (error == TCL_EXIT)
280 ! robj = Tcl_GetObjResult(tclinfo.interp);
281 ! if (Tcl_GetIntFromObj(tclinfo.interp, robj, &retval) != TCL_OK)
283 ! EMSG(_("E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org"));
288 ! sprintf(buf, _("E572: exit code %d"), retval);
305 ! if (Tcl_InterpDeleted(tclinfo.interp) /* True if we intercepted Tcl's exit command */
306 ! #if (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 5) || TCL_MAJOR_VERSION > 8
307 ! || Tcl_LimitExceeded(tclinfo.interp) /* True if the interpreter cannot continue */
313 ! sprintf(buf, _("E572: exit code %d"), tclinfo.exitvalue);
315 ! if (tclinfo.exitvalue == 0)
327 Tcl_SetVar(tclinfo.interp, var_line, line, 0);
328 Tcl_AllowExceptions(tclinfo.interp);
329 err = Tcl_Eval(tclinfo.interp, script);
332 line = (char *)Tcl_GetVar(tclinfo.interp, var_line, 0);
335 Tcl_SetVar(tclinfo.interp, var_line, line, 0);
336 Tcl_AllowExceptions(tclinfo.interp);
337 err = Tcl_Eval(tclinfo.interp, script);
339 ! || Tcl_InterpDeleted(tclinfo.interp)
340 ! #if (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 5) || TCL_MAJOR_VERSION > 8
341 ! || Tcl_LimitExceeded(tclinfo.interp)
345 line = (char *)Tcl_GetVar(tclinfo.interp, var_line, 0);
347 *** ../vim-7.3.450/src/version.c 2012-02-22 15:34:05.000000000 +0100
348 --- src/version.c 2012-02-22 16:00:49.000000000 +0100
352 { /* Add new patch number below this line */
358 Where do you want to crash today?
360 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
361 /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
362 \\\ an exciting new programming language -- http://www.Zimbu.org ///
363 \\\ help me help AIDS victims -- http://ICCF-Holland.org ///