Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / nvi / tcl_api / tcl.c
blob1fc2f651e25df0c5a64e4e75034fe40655276b32
1 /* $NetBSD$ */
3 /*-
4 * Copyright (c) 1992, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 * Copyright (c) 1992, 1993, 1994, 1995
7 * Keith Bostic. All rights reserved.
8 * Copyright (c) 1995
9 * George V. Neville-Neil. All rights reserved.
11 * See the LICENSE file for redistribution information.
14 #include "config.h"
16 #ifndef lint
17 static const char sccsid[] = "Id: tcl.c,v 8.19 2001/08/24 12:17:27 skimo Exp (Berkeley) Date: 2001/08/24 12:17:27";
18 #endif /* not lint */
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/time.h>
24 #include <bitstring.h>
25 #include <errno.h>
26 #include <limits.h>
27 #include <signal.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <tcl.h>
32 #include <termios.h>
33 #include <unistd.h>
35 #include "../common/common.h"
36 #include "extern.h"
38 static int getint __P((Tcl_Interp *, char *, char *, int *));
39 static int getscreenid __P((Tcl_Interp *, SCR **, char *, char *));
40 static void msghandler __P((SCR *, mtype_t, char *, size_t));
42 extern GS *__global_list; /* XXX */
45 * INITMESSAGE --
46 * Macros to point messages at the Tcl message handler.
48 #define INITMESSAGE(sp) \
49 scr_msg = sp->wp->scr_msg; \
50 sp->wp->scr_msg = msghandler;
51 #define ENDMESSAGE(sp) \
52 sp->wp->scr_msg = scr_msg;
55 * tcl_fscreen --
56 * Return the screen id associated with file name.
58 * Tcl Command: viFindScreen
59 * Usage: viFindScreen file
61 static int
62 tcl_fscreen(clientData, interp, argc, argv)
63 ClientData clientData;
64 Tcl_Interp *interp;
65 int argc;
66 char **argv;
68 SCR *sp;
70 if (argc != 2) {
71 Tcl_SetResult(interp, "Usage: viFindScreen file", TCL_STATIC);
72 return (TCL_ERROR);
75 if (getscreenid(interp, &sp, NULL, argv[1]))
76 return (TCL_ERROR);
78 (void)sprintf(interp->result, "%d", sp->id);
79 return (TCL_OK);
83 * tcl_aline --
84 * -- Append the string text after the line in lineNumber.
86 * Tcl Command: viAppendLine
87 * Usage: viAppendLine screenId lineNumber text
89 static int
90 tcl_aline(clientData, interp, argc, argv)
91 ClientData clientData;
92 Tcl_Interp *interp;
93 int argc;
94 char **argv;
96 SCR *sp;
97 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
98 int lno, rval;
100 if (argc != 4) {
101 Tcl_SetResult(interp,
102 "Usage: viAppendLine screenId lineNumber text", TCL_STATIC);
103 return (TCL_ERROR);
106 if (getscreenid(interp, &sp, argv[1], NULL) ||
107 getint(interp, "line number", argv[2], &lno))
108 return (TCL_ERROR);
109 INITMESSAGE(sp);
110 rval = api_aline(sp, (db_recno_t)lno, argv[3], strlen(argv[3]));
111 ENDMESSAGE(sp);
113 return (rval ? TCL_ERROR : TCL_OK);
117 * tcl_dline --
118 * Delete lineNum.
120 * Tcl Command: viDelLine
121 * Usage: viDelLine screenId lineNum
123 static int
124 tcl_dline(clientData, interp, argc, argv)
125 ClientData clientData;
126 Tcl_Interp *interp;
127 int argc;
128 char **argv;
130 SCR *sp;
131 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
132 int lno, rval;
134 if (argc != 3) {
135 Tcl_SetResult(interp,
136 "Usage: viDelLine screenId lineNumber", TCL_STATIC);
137 return (TCL_ERROR);
140 if (getscreenid(interp, &sp, argv[1], NULL) ||
141 getint(interp, "line number", argv[2], &lno))
142 return (TCL_ERROR);
143 INITMESSAGE(sp);
144 rval = api_dline(sp, (db_recno_t)lno);
145 ENDMESSAGE(sp);
147 return (rval ? TCL_ERROR : TCL_OK);
151 * tcl_gline --
152 * Return lineNumber.
154 * Tcl Command: viGetLine
155 * Usage: viGetLine screenId lineNumber
157 static int
158 tcl_gline(clientData, interp, argc, argv)
159 ClientData clientData;
160 Tcl_Interp *interp;
161 int argc;
162 char **argv;
164 SCR *sp;
165 size_t len;
166 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
167 int lno, rval;
168 char *line, *p;
170 if (argc != 3) {
171 Tcl_SetResult(interp,
172 "Usage: viGetLine screenId lineNumber", TCL_STATIC);
173 return (TCL_ERROR);
175 if (getscreenid(interp, &sp, argv[1], NULL) ||
176 getint(interp, "line number", argv[2], &lno))
177 return (TCL_ERROR);
178 INITMESSAGE(sp);
179 rval = api_gline(sp, (db_recno_t)lno, &p, &len);
180 ENDMESSAGE(sp);
182 if (rval)
183 return (TCL_ERROR);
185 if ((line = malloc(len + 1)) == NULL)
186 exit(1); /* XXX */
187 memmove(line, p, len);
188 line[len] = '\0';
189 Tcl_SetResult(interp, line, TCL_DYNAMIC);
190 return (TCL_OK);
194 * tcl_iline --
195 * Insert the string text after the line in lineNumber.
197 * Tcl Command: viInsertLine
198 * Usage: viInsertLine screenId lineNumber text
200 static int
201 tcl_iline(clientData, interp, argc, argv)
202 ClientData clientData;
203 Tcl_Interp *interp;
204 int argc;
205 char **argv;
207 SCR *sp;
208 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
209 int lno, rval;
211 if (argc != 4) {
212 Tcl_SetResult(interp,
213 "Usage: viInsertLine screenId lineNumber text", TCL_STATIC);
214 return (TCL_ERROR);
217 if (getscreenid(interp, &sp, argv[1], NULL) ||
218 getint(interp, "line number", argv[2], &lno))
219 return (TCL_ERROR);
220 INITMESSAGE(sp);
221 rval = api_iline(sp, (db_recno_t)lno, argv[3], strlen(argv[3]));
222 ENDMESSAGE(sp);
224 return (rval ? TCL_ERROR : TCL_OK);
228 * tcl_lline --
229 * Return the last line in the screen.
231 * Tcl Command: viLastLine
232 * Usage: viLastLine screenId
234 static int
235 tcl_lline(clientData, interp, argc, argv)
236 ClientData clientData;
237 Tcl_Interp *interp;
238 int argc;
239 char **argv;
241 SCR *sp;
242 db_recno_t last;
243 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
244 int rval;
246 if (argc != 2) {
247 Tcl_SetResult(interp, "Usage: viLastLine screenId", TCL_STATIC);
248 return (TCL_ERROR);
251 if (getscreenid(interp, &sp, argv[1], NULL))
252 return (TCL_ERROR);
253 INITMESSAGE(sp);
254 rval = api_lline(sp, &last);
255 ENDMESSAGE(sp);
256 if (rval)
257 return (TCL_ERROR);
259 (void)sprintf(interp->result, "%lu", (unsigned long)last);
260 return (TCL_OK);
264 * tcl_sline --
265 * Set lineNumber to the text supplied.
267 * Tcl Command: viSetLine
268 * Usage: viSetLine screenId lineNumber text
270 static int
271 tcl_sline(clientData, interp, argc, argv)
272 ClientData clientData;
273 Tcl_Interp *interp;
274 int argc;
275 char **argv;
277 SCR *sp;
278 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
279 int lno, rval;
281 if (argc != 4) {
282 Tcl_SetResult(interp,
283 "Usage: viSetLine screenId lineNumber text", TCL_STATIC);
284 return (TCL_ERROR);
287 if (getscreenid(interp, &sp, argv[1], NULL) ||
288 getint(interp, "line number", argv[2], &lno))
289 return (TCL_ERROR);
290 INITMESSAGE(sp);
291 rval = api_sline(sp, (db_recno_t)lno, argv[3], strlen(argv[3]));
292 ENDMESSAGE(sp);
294 return (rval ? TCL_ERROR : TCL_OK);
298 * tcl_getmark --
299 * Return the mark's cursor position as a list with two elements.
300 * {line, column}.
302 * Tcl Command: viGetMark
303 * Usage: viGetMark screenId mark
305 static int
306 tcl_getmark(clientData, interp, argc, argv)
307 ClientData clientData;
308 Tcl_Interp *interp;
309 int argc;
310 char **argv;
312 MARK cursor;
313 SCR *sp;
314 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
315 int rval;
316 char buf[20];
318 if (argc != 3) {
319 Tcl_SetResult(interp,
320 "Usage: viGetMark screenId mark", TCL_STATIC);
321 return (TCL_ERROR);
324 if (getscreenid(interp, &sp, argv[1], NULL))
325 return (TCL_ERROR);
326 INITMESSAGE(sp);
327 rval = api_getmark(sp, (int)argv[2][0], &cursor);
328 ENDMESSAGE(sp);
330 if (rval)
331 return (TCL_ERROR);
333 (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.lno);
334 Tcl_AppendElement(interp, buf);
335 (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.cno);
336 Tcl_AppendElement(interp, buf);
337 return (TCL_OK);
341 * tcl_setmark --
342 * Set the mark to the line and column numbers supplied.
344 * Tcl Command: viSetMark
345 * Usage: viSetMark screenId mark line column
347 static int
348 tcl_setmark(clientData, interp, argc, argv)
349 ClientData clientData;
350 Tcl_Interp *interp;
351 int argc;
352 char **argv;
354 MARK cursor;
355 SCR *sp;
356 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
357 int i, rval;
359 if (argc != 5) {
360 Tcl_SetResult(interp,
361 "Usage: viSetMark screenId mark line column", TCL_STATIC);
362 return (TCL_ERROR);
365 if (getscreenid(interp, &sp, argv[1], NULL))
366 return (TCL_ERROR);
367 if (getint(interp, "line number", argv[3], &i))
368 return (TCL_ERROR);
369 cursor.lno = i;
370 if (getint(interp, "column number", argv[4], &i))
371 return (TCL_ERROR);
372 cursor.cno = i;
373 INITMESSAGE(sp);
374 rval = api_setmark(sp, (int)argv[2][0], &cursor);
375 ENDMESSAGE(sp);
377 return (rval ? TCL_ERROR : TCL_OK);
381 * tcl_getcursor --
382 * Return the current cursor position as a list with two elements.
383 * {line, column}.
385 * Tcl Command: viGetCursor
386 * Usage: viGetCursor screenId
388 static int
389 tcl_getcursor(clientData, interp, argc, argv)
390 ClientData clientData;
391 Tcl_Interp *interp;
392 int argc;
393 char **argv;
395 MARK cursor;
396 SCR *sp;
397 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
398 int rval;
399 char buf[20];
401 if (argc != 2) {
402 Tcl_SetResult(interp,
403 "Usage: viGetCursor screenId", TCL_STATIC);
404 return (TCL_ERROR);
407 if (getscreenid(interp, &sp, argv[1], NULL))
408 return (TCL_ERROR);
409 INITMESSAGE(sp);
410 rval = api_getcursor(sp, &cursor);
411 ENDMESSAGE(sp);
413 if (rval)
414 return (TCL_ERROR);
416 (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.lno);
417 Tcl_AppendElement(interp, buf);
418 (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.cno);
419 Tcl_AppendElement(interp, buf);
420 return (TCL_OK);
424 * tcl_setcursor --
425 * Set the cursor to the line and column numbers supplied.
427 * Tcl Command: viSetCursor
428 * Usage: viSetCursor screenId line column
430 static int
431 tcl_setcursor(clientData, interp, argc, argv)
432 ClientData clientData;
433 Tcl_Interp *interp;
434 int argc;
435 char **argv;
437 MARK cursor;
438 SCR *sp;
439 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
440 int i, rval;
442 if (argc != 4) {
443 Tcl_SetResult(interp,
444 "Usage: viSetCursor screenId line column", TCL_STATIC);
445 return (TCL_ERROR);
448 if (getscreenid(interp, &sp, argv[1], NULL))
449 return (TCL_ERROR);
450 if (getint(interp, "screen id", argv[2], &i))
451 return (TCL_ERROR);
452 cursor.lno = i;
453 if (getint(interp, "screen id", argv[3], &i))
454 return (TCL_ERROR);
455 cursor.cno = i;
456 INITMESSAGE(sp);
457 rval = api_setcursor(sp, &cursor);
458 ENDMESSAGE(sp);
460 return (rval ? TCL_ERROR : TCL_OK);
464 * tcl_msg --
465 * Set the message line to text.
467 * Tcl Command: viMsg
468 * Usage: viMsg screenId text
470 static int
471 tcl_msg(clientData, interp, argc, argv)
472 ClientData clientData;
473 Tcl_Interp *interp;
474 int argc;
475 char **argv;
477 SCR *sp;
479 if (argc != 3) {
480 Tcl_SetResult(interp, "Usage: viMsg screenId text", TCL_STATIC);
481 return (TCL_ERROR);
484 if (getscreenid(interp, &sp, argv[1], NULL))
485 return (TCL_ERROR);
486 api_imessage(sp, argv[2]);
488 return (TCL_OK);
492 * tcl_iscreen --
493 * Create a new screen. If a filename is specified then the screen
494 * is opened with that file.
496 * Tcl Command: viNewScreen
497 * Usage: viNewScreen screenId [file]
499 static int
500 tcl_iscreen(clientData, interp, argc, argv)
501 ClientData clientData;
502 Tcl_Interp *interp;
503 int argc;
504 char **argv;
506 SCR *sp, *nsp;
507 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
508 int rval;
510 if (argc != 2 && argc != 3) {
511 Tcl_SetResult(interp,
512 "Usage: viNewScreen screenId [file]", TCL_STATIC);
513 return (TCL_ERROR);
516 if (getscreenid(interp, &sp, argv[1], NULL))
517 return (TCL_ERROR);
518 INITMESSAGE(sp);
519 rval = api_edit(sp, argv[2], &nsp, 1);
520 ENDMESSAGE(sp);
522 if (rval)
523 return (TCL_ERROR);
525 (void)sprintf(interp->result, "%d", nsp->id);
526 return (TCL_OK);
530 * tcl_escreen --
531 * End a screen.
533 * Tcl Command: viEndScreen
534 * Usage: viEndScreen screenId
536 static int
537 tcl_escreen(clientData, interp, argc, argv)
538 ClientData clientData;
539 Tcl_Interp *interp;
540 int argc;
541 char **argv;
543 SCR *sp;
544 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
545 int rval;
547 if (argc != 2) {
548 Tcl_SetResult(interp,
549 "Usage: viEndScreen screenId", TCL_STATIC);
550 return (TCL_ERROR);
553 if (getscreenid(interp, &sp, argv[1], NULL))
554 return (TCL_ERROR);
555 INITMESSAGE(sp);
556 rval = api_escreen(sp);
557 ENDMESSAGE(sp);
559 return (rval ? TCL_ERROR : TCL_OK);
563 * tcl_swscreen --
564 * Change the current focus to screen.
566 * Tcl Command: viSwitchScreen
567 * Usage: viSwitchScreen screenId screenId
569 static int
570 tcl_swscreen(clientData, interp, argc, argv)
571 ClientData clientData;
572 Tcl_Interp *interp;
573 int argc;
574 char **argv;
576 SCR *sp, *new;
577 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
578 int rval;
580 if (argc != 3) {
581 Tcl_SetResult(interp,
582 "Usage: viSwitchScreen cur_screenId new_screenId",
583 TCL_STATIC);
584 return (TCL_ERROR);
587 if (getscreenid(interp, &sp, argv[1], NULL))
588 return (TCL_ERROR);
589 if (getscreenid(interp, &new, argv[2], NULL))
590 return (TCL_ERROR);
591 INITMESSAGE(sp);
592 rval = api_swscreen(sp, new);
593 ENDMESSAGE(sp);
595 return (rval ? TCL_ERROR : TCL_OK);
599 * tcl_map --
600 * Associate a key with a tcl procedure.
602 * Tcl Command: viMapKey
603 * Usage: viMapKey screenId key tclproc
605 static int
606 tcl_map(clientData, interp, argc, argv)
607 ClientData clientData;
608 Tcl_Interp *interp;
609 int argc;
610 char **argv;
612 SCR *sp;
613 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
614 int rval;
615 char command[256];
617 if (argc != 4) {
618 Tcl_SetResult(interp,
619 "Usage: viMapKey screenId key tclproc", TCL_STATIC);
620 return (TCL_ERROR);
623 if (getscreenid(interp, &sp, argv[1], NULL))
624 return (TCL_ERROR);
625 INITMESSAGE(sp);
626 (void)snprintf(command, sizeof(command), ":tcl %s\n", argv[3]);
627 rval = api_map(sp, argv[2], command, strlen(command));
628 ENDMESSAGE(sp);
630 return (rval ? TCL_ERROR : TCL_OK);
634 * tcl_unmap --
635 * Unmap a key.
637 * Tcl Command: viUnmapKey
638 * Usage: viUnmMapKey screenId key
640 static int
641 tcl_unmap(clientData, interp, argc, argv)
642 ClientData clientData;
643 Tcl_Interp *interp;
644 int argc;
645 char **argv;
647 SCR *sp;
648 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
649 int rval;
651 if (argc != 3) {
652 Tcl_SetResult(interp,
653 "Usage: viUnmapKey screenId key", TCL_STATIC);
654 return (TCL_ERROR);
657 if (getscreenid(interp, &sp, argv[1], NULL))
658 return (TCL_ERROR);
659 INITMESSAGE(sp);
660 rval = api_unmap(sp, argv[2]);
661 ENDMESSAGE(sp);
663 return (rval ? TCL_ERROR : TCL_OK);
667 * tcl_opts_set --
668 * Set an option.
670 * Tcl Command: viSetOpt
671 * Usage: viSetOpt screenId command
673 static int
674 tcl_opts_set(clientData, interp, argc, argv)
675 ClientData clientData;
676 Tcl_Interp *interp;
677 int argc;
678 char **argv;
680 SCR *sp;
681 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
682 int rval;
683 char *setting;
685 if (argc != 3) {
686 Tcl_SetResult(interp,
687 "Usage: viSetOpt screenId command", TCL_STATIC);
688 return (TCL_ERROR);
691 if (getscreenid(interp, &sp, argv[1], NULL))
692 return (TCL_ERROR);
693 INITMESSAGE(sp);
694 /*rval = api_opts_set(sp, argv[2]);*/
695 MALLOC(sp, setting, char *, strlen(argv[2])+6);
696 strcpy(setting, ":set ");
697 strcpy(setting+5, argv[2]);
698 rval=api_run_str(sp, setting);
699 free(setting);
700 ENDMESSAGE(sp);
702 return (rval ? TCL_ERROR : TCL_OK);
706 * tcl_opts_get --
707 Return the value of an option.
709 * Tcl Command: viGetOpt
710 * Usage: viGetOpt screenId option
712 static int
713 tcl_opts_get(clientData, interp, argc, argv)
714 ClientData clientData;
715 Tcl_Interp *interp;
716 int argc;
717 char **argv;
719 SCR *sp;
720 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t));
721 int rval;
722 char *value;
724 if (argc != 3) {
725 Tcl_SetResult(interp,
726 "Usage: viGetOpt screenId option", TCL_STATIC);
727 return (TCL_ERROR);
730 if (getscreenid(interp, &sp, argv[1], NULL))
731 return (TCL_ERROR);
732 INITMESSAGE(sp);
733 rval = api_opts_get(sp, argv[2], &value, NULL);
734 ENDMESSAGE(sp);
735 if (rval)
736 return (TCL_ERROR);
738 Tcl_SetResult(interp, value, TCL_DYNAMIC);
739 return (TCL_OK);
743 * tcl_init --
744 * Create the TCL commands used by nvi.
746 * PUBLIC: int tcl_init __P((GS *));
749 tcl_init(gp)
750 GS *gp;
752 gp->tcl_interp = Tcl_CreateInterp();
753 if (Tcl_Init(gp->tcl_interp) == TCL_ERROR)
754 return (1);
756 #define TCC(name, function) { \
757 Tcl_CreateCommand(gp->tcl_interp, name, function, \
758 (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); \
760 TCC("viAppendLine", tcl_aline);
761 TCC("viDelLine", tcl_dline);
762 TCC("viEndScreen", tcl_escreen);
763 TCC("viFindScreen", tcl_fscreen);
764 TCC("viGetCursor", tcl_getcursor);
765 TCC("viGetLine", tcl_gline);
766 TCC("viGetMark", tcl_getmark);
767 TCC("viGetOpt", tcl_opts_get);
768 TCC("viInsertLine", tcl_iline);
769 TCC("viLastLine", tcl_lline);
770 TCC("viMapKey", tcl_map);
771 TCC("viMsg", tcl_msg);
772 TCC("viNewScreen", tcl_iscreen);
773 TCC("viSetCursor", tcl_setcursor);
774 TCC("viSetLine", tcl_sline);
775 TCC("viSetMark", tcl_setmark);
776 TCC("viSetOpt", tcl_opts_set);
777 TCC("viSwitchScreen", tcl_swscreen);
778 TCC("viUnmapKey", tcl_unmap);
780 return (0);
784 * getscreenid --
785 * Get the specified screen pointer.
787 * XXX
788 * This is fatal. We can't post a message into vi that we're unable to find
789 * the screen without first finding the screen... So, this must be the first
790 * thing a Tcl routine does, and, if it fails, the last as well.
792 static int
793 getscreenid(interp, spp, id, name)
794 Tcl_Interp *interp;
795 SCR **spp;
796 char *id, *name;
798 int scr_no;
799 char buf[64];
801 if (id != NULL && getint(interp, "screen id", id, &scr_no))
802 return (1);
803 if ((*spp = api_fscreen(scr_no, name)) == NULL) {
804 (void)snprintf(buf, sizeof(buf),
805 "unknown screen id: %s", name == NULL ? id : name);
806 Tcl_SetResult(interp, buf, TCL_VOLATILE);
807 return (1);
809 return (0);
813 * getint --
814 * Get a Tcl integer.
816 * XXX
817 * This code assumes that both db_recno_t and size_t are larger than ints.
819 static int
820 getint(interp, msg, s, intp)
821 Tcl_Interp *interp;
822 char *msg, *s;
823 int *intp;
825 char buf[64];
827 if (Tcl_GetInt(interp, s, intp) == TCL_ERROR)
828 return (1);
829 if (*intp < 0) {
830 (void)snprintf(buf, sizeof(buf),
831 "illegal %s %s: may not be negative", msg, s);
832 Tcl_SetResult(interp, buf, TCL_VOLATILE);
833 return (1);
835 return (0);
839 * msghandler --
840 * Tcl message routine so that error messages are processed in
841 * Tcl, not in nvi.
843 static void
844 msghandler(sp, mtype, msg, len)
845 SCR *sp;
846 mtype_t mtype;
847 char *msg;
848 size_t len;
850 /* Replace the trailing <newline> with an EOS. */
851 msg[len - 1] = '\0';
853 Tcl_SetResult(sp->gp->tcl_interp, msg, TCL_VOLATILE);