os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclInterp.c
First public contribution.
4 * This file implements the "interp" command which allows creation
5 * and manipulation of Tcl interpreters from within Tcl scripts.
7 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
8 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * RCS: @(#) $Id: tclInterp.c,v 1.20.2.3 2006/11/28 22:20:02 andreas_kupries Exp $
21 * Counter for how many aliases were created (global)
24 static int aliasCounter = 0;
25 TCL_DECLARE_MUTEX(cntMutex)
30 * Stores information about an alias. Is stored in the slave interpreter
31 * and used by the source command to find the target command in the master
32 * when the source command is invoked.
35 typedef struct Alias {
36 Tcl_Obj *namePtr; /* Name of alias command in slave interp. */
37 Tcl_Interp *targetInterp; /* Interp in which target command will be
39 Tcl_Command slaveCmd; /* Source command in slave interpreter,
40 * bound to command that invokes the target
41 * command in the target interpreter. */
42 Tcl_HashEntry *aliasEntryPtr;
43 /* Entry for the alias hash table in slave.
44 * This is used by alias deletion to remove
45 * the alias from the slave interpreter
47 Tcl_HashEntry *targetEntryPtr;
48 /* Entry for target command in master.
49 * This is used in the master interpreter to
50 * map back from the target command to aliases
51 * redirecting to it. Random access to this
52 * hash table is never required - we are using
53 * a hash table only for convenience. */
54 int objc; /* Count of Tcl_Obj in the prefix of the
55 * target command to be invoked in the
56 * target interpreter. Additional arguments
57 * specified when calling the alias in the
58 * slave interp will be appended to the prefix
59 * before the command is invoked. */
60 Tcl_Obj *objPtr; /* The first actual prefix object - the target
61 * command name; this has to be at the end of the
62 * structure, which will be extended to accomodate
63 * the remaining objects in the prefix. */
70 * Used by the "interp" command to record and find information about slave
71 * interpreters. Maps from a command name in the master to information about
72 * a slave interpreter, e.g. what aliases are defined in it.
75 typedef struct Slave {
76 Tcl_Interp *masterInterp; /* Master interpreter for this slave. */
77 Tcl_HashEntry *slaveEntryPtr;
78 /* Hash entry in masters slave table for
79 * this slave interpreter. Used to find
80 * this record, and used when deleting the
81 * slave interpreter to delete it from the
83 Tcl_Interp *slaveInterp; /* The slave interpreter. */
84 Tcl_Command interpCmd; /* Interpreter object command. */
85 Tcl_HashTable aliasTable; /* Table which maps from names of commands
86 * in slave interpreter to struct Alias
93 * Maps from master interpreter commands back to the source commands in slave
94 * interpreters. This is needed because aliases can be created between sibling
95 * interpreters and must be deleted when the target interpreter is deleted. In
96 * case they would not be deleted the source interpreter would be left with a
97 * "dangling pointer". One such record is stored in the Master record of the
98 * master interpreter (in the targetTable hashtable, see below) with the
99 * master for each alias which directs to a command in the master. These
100 * records are used to remove the source command for an from a slave if/when
101 * the master is deleted.
104 typedef struct Target {
105 Tcl_Command slaveCmd; /* Command for alias in slave interp. */
106 Tcl_Interp *slaveInterp; /* Slave Interpreter. */
112 * This record is used for two purposes: First, slaveTable (a hashtable)
113 * maps from names of commands to slave interpreters. This hashtable is
114 * used to store information about slave interpreters of this interpreter,
115 * to map over all slaves, etc. The second purpose is to store information
116 * about all aliases in slaves (or siblings) which direct to target commands
117 * in this interpreter (using the targetTable hashtable).
119 * NB: the flags field in the interp structure, used with SAFE_INTERP
120 * mask denotes whether the interpreter is safe or not. Safe
121 * interpreters have restricted functionality, can only create safe slave
122 * interpreters and can only load safe extensions.
125 typedef struct Master {
126 Tcl_HashTable slaveTable; /* Hash table for slave interpreters.
127 * Maps from command names to Slave records. */
128 Tcl_HashTable targetTable; /* Hash table for Target Records. Contains
129 * all Target records which denote aliases
130 * from slaves or sibling interpreters that
131 * direct to commands in this interpreter. This
132 * table is used to remove dangling pointers
133 * from the slave (or sibling) interpreters
134 * when this interpreter is deleted. */
138 * The following structure keeps track of all the Master and Slave information
139 * on a per-interp basis.
142 typedef struct InterpInfo {
143 Master master; /* Keeps track of all interps for which this
144 * interp is the Master. */
145 Slave slave; /* Information necessary for this interp to
146 * function as a slave. */
150 * Prototypes for local static procedures:
153 static int AliasCreate _ANSI_ARGS_((Tcl_Interp *interp,
154 Tcl_Interp *slaveInterp, Tcl_Interp *masterInterp,
155 Tcl_Obj *namePtr, Tcl_Obj *targetPtr, int objc,
156 Tcl_Obj *CONST objv[]));
157 static int AliasDelete _ANSI_ARGS_((Tcl_Interp *interp,
158 Tcl_Interp *slaveInterp, Tcl_Obj *namePtr));
159 static int AliasDescribe _ANSI_ARGS_((Tcl_Interp *interp,
160 Tcl_Interp *slaveInterp, Tcl_Obj *objPtr));
161 static int AliasList _ANSI_ARGS_((Tcl_Interp *interp,
162 Tcl_Interp *slaveInterp));
163 static int AliasObjCmd _ANSI_ARGS_((ClientData dummy,
164 Tcl_Interp *currentInterp, int objc,
165 Tcl_Obj *CONST objv[]));
166 static void AliasObjCmdDeleteProc _ANSI_ARGS_((
167 ClientData clientData));
169 static Tcl_Interp * GetInterp _ANSI_ARGS_((Tcl_Interp *interp,
171 static Tcl_Interp * GetInterp2 _ANSI_ARGS_((Tcl_Interp *interp, int objc,
172 Tcl_Obj *CONST objv[]));
173 static void InterpInfoDeleteProc _ANSI_ARGS_((
174 ClientData clientData, Tcl_Interp *interp));
175 static Tcl_Interp * SlaveCreate _ANSI_ARGS_((Tcl_Interp *interp,
176 Tcl_Obj *pathPtr, int safe));
177 static int SlaveEval _ANSI_ARGS_((Tcl_Interp *interp,
178 Tcl_Interp *slaveInterp, int objc,
179 Tcl_Obj *CONST objv[]));
180 static int SlaveExpose _ANSI_ARGS_((Tcl_Interp *interp,
181 Tcl_Interp *slaveInterp, int objc,
182 Tcl_Obj *CONST objv[]));
183 static int SlaveHide _ANSI_ARGS_((Tcl_Interp *interp,
184 Tcl_Interp *slaveInterp, int objc,
185 Tcl_Obj *CONST objv[]));
186 static int SlaveHidden _ANSI_ARGS_((Tcl_Interp *interp,
187 Tcl_Interp *slaveInterp));
188 static int SlaveInvokeHidden _ANSI_ARGS_((Tcl_Interp *interp,
189 Tcl_Interp *slaveInterp, int global, int objc,
190 Tcl_Obj *CONST objv[]));
191 static int SlaveMarkTrusted _ANSI_ARGS_((Tcl_Interp *interp,
192 Tcl_Interp *slaveInterp));
193 static int SlaveObjCmd _ANSI_ARGS_((ClientData dummy,
194 Tcl_Interp *interp, int objc,
195 Tcl_Obj *CONST objv[]));
196 static void SlaveObjCmdDeleteProc _ANSI_ARGS_((
197 ClientData clientData));
198 static int SlaveRecursionLimit _ANSI_ARGS_((Tcl_Interp *interp,
199 Tcl_Interp *slaveInterp, int objc,
200 Tcl_Obj *CONST objv[]));
204 *---------------------------------------------------------------------------
208 * Initializes the invoking interpreter for using the master, slave
209 * and safe interp facilities. This is called from inside
210 * Tcl_CreateInterp().
213 * Always returns TCL_OK for backwards compatibility.
216 * Adds the "interp" command to an interpreter and initializes the
217 * interpInfoPtr field of the invoking interpreter.
219 *---------------------------------------------------------------------------
223 TclInterpInit(interp)
224 Tcl_Interp *interp; /* Interpreter to initialize. */
226 InterpInfo *interpInfoPtr;
230 interpInfoPtr = (InterpInfo *) ckalloc(sizeof(InterpInfo));
231 ((Interp *) interp)->interpInfo = (ClientData) interpInfoPtr;
233 masterPtr = &interpInfoPtr->master;
234 Tcl_InitHashTable(&masterPtr->slaveTable, TCL_STRING_KEYS);
235 Tcl_InitHashTable(&masterPtr->targetTable, TCL_ONE_WORD_KEYS);
237 slavePtr = &interpInfoPtr->slave;
238 slavePtr->masterInterp = NULL;
239 slavePtr->slaveEntryPtr = NULL;
240 slavePtr->slaveInterp = interp;
241 slavePtr->interpCmd = NULL;
242 Tcl_InitHashTable(&slavePtr->aliasTable, TCL_STRING_KEYS);
244 Tcl_CreateObjCommand(interp, "interp", Tcl_InterpObjCmd, NULL, NULL);
246 Tcl_CallWhenDeleted(interp, InterpInfoDeleteProc, NULL);
251 *---------------------------------------------------------------------------
253 * InterpInfoDeleteProc --
255 * Invoked when an interpreter is being deleted. It releases all
256 * storage used by the master/slave/safe interpreter facilities.
262 * Cleans up storage. Sets the interpInfoPtr field of the interp
265 *---------------------------------------------------------------------------
269 InterpInfoDeleteProc(clientData, interp)
270 ClientData clientData; /* Ignored. */
271 Tcl_Interp *interp; /* Interp being deleted. All commands for
272 * slave interps should already be deleted. */
274 InterpInfo *interpInfoPtr;
277 Tcl_HashSearch hSearch;
281 interpInfoPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
284 * There shouldn't be any commands left.
287 masterPtr = &interpInfoPtr->master;
288 if (masterPtr->slaveTable.numEntries != 0) {
289 panic("InterpInfoDeleteProc: still exist commands");
291 Tcl_DeleteHashTable(&masterPtr->slaveTable);
294 * Tell any interps that have aliases to this interp that they should
295 * delete those aliases. If the other interp was already dead, it
296 * would have removed the target record already.
299 hPtr = Tcl_FirstHashEntry(&masterPtr->targetTable, &hSearch);
300 while (hPtr != NULL) {
301 targetPtr = (Target *) Tcl_GetHashValue(hPtr);
302 Tcl_DeleteCommandFromToken(targetPtr->slaveInterp,
303 targetPtr->slaveCmd);
304 hPtr = Tcl_NextHashEntry(&hSearch);
306 Tcl_DeleteHashTable(&masterPtr->targetTable);
308 slavePtr = &interpInfoPtr->slave;
309 if (slavePtr->interpCmd != NULL) {
311 * Tcl_DeleteInterp() was called on this interpreter, rather
312 * "interp delete" or the equivalent deletion of the command in the
313 * master. First ensure that the cleanup callback doesn't try to
314 * delete the interp again.
317 slavePtr->slaveInterp = NULL;
318 Tcl_DeleteCommandFromToken(slavePtr->masterInterp,
319 slavePtr->interpCmd);
323 * There shouldn't be any aliases left.
326 if (slavePtr->aliasTable.numEntries != 0) {
327 panic("InterpInfoDeleteProc: still exist aliases");
329 Tcl_DeleteHashTable(&slavePtr->aliasTable);
331 ckfree((char *) interpInfoPtr);
335 *----------------------------------------------------------------------
337 * Tcl_InterpObjCmd --
339 * This procedure is invoked to process the "interp" Tcl command.
340 * See the user documentation for details on what it does.
343 * A standard Tcl result.
346 * See the user documentation.
348 *----------------------------------------------------------------------
352 Tcl_InterpObjCmd(clientData, interp, objc, objv)
353 ClientData clientData; /* Unused. */
354 Tcl_Interp *interp; /* Current interpreter. */
355 int objc; /* Number of arguments. */
356 Tcl_Obj *CONST objv[]; /* Argument objects. */
359 static CONST char *options[] = {
360 "alias", "aliases", "create", "delete",
361 "eval", "exists", "expose", "hide",
362 "hidden", "issafe", "invokehidden", "marktrusted",
363 "recursionlimit", "slaves", "share",
364 "target", "transfer",
368 OPT_ALIAS, OPT_ALIASES, OPT_CREATE, OPT_DELETE,
369 OPT_EVAL, OPT_EXISTS, OPT_EXPOSE, OPT_HIDE,
370 OPT_HIDDEN, OPT_ISSAFE, OPT_INVOKEHID, OPT_MARKTRUSTED,
371 OPT_RECLIMIT, OPT_SLAVES, OPT_SHARE,
372 OPT_TARGET, OPT_TRANSFER
377 Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?");
380 if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,
384 switch ((enum option) index) {
386 Tcl_Interp *slaveInterp, *masterInterp;
390 Tcl_WrongNumArgs(interp, 2, objv,
391 "slavePath slaveCmd ?masterPath masterCmd? ?args ..?");
394 slaveInterp = GetInterp(interp, objv[2]);
395 if (slaveInterp == (Tcl_Interp *) NULL) {
399 return AliasDescribe(interp, slaveInterp, objv[3]);
401 if ((objc == 5) && (Tcl_GetString(objv[4])[0] == '\0')) {
402 return AliasDelete(interp, slaveInterp, objv[3]);
405 masterInterp = GetInterp(interp, objv[4]);
406 if (masterInterp == (Tcl_Interp *) NULL) {
409 if (Tcl_GetString(objv[5])[0] == '\0') {
411 return AliasDelete(interp, slaveInterp, objv[3]);
414 return AliasCreate(interp, slaveInterp, masterInterp,
415 objv[3], objv[5], objc - 6, objv + 6);
421 Tcl_Interp *slaveInterp;
423 slaveInterp = GetInterp2(interp, objc, objv);
424 if (slaveInterp == NULL) {
427 return AliasList(interp, slaveInterp);
432 char buf[16 + TCL_INTEGER_SPACE];
433 static CONST char *options[] = {
440 safe = Tcl_IsSafe(interp);
443 * Weird historical rules: "-safe" is accepted at the end, too.
448 for (i = 2; i < objc; i++) {
449 if ((last == 0) && (Tcl_GetString(objv[i])[0] == '-')) {
450 if (Tcl_GetIndexFromObj(interp, objv[i], options, "option",
451 0, &index) != TCL_OK) {
454 if (index == OPT_SAFE) {
461 if (slavePtr != NULL) {
462 Tcl_WrongNumArgs(interp, 2, objv, "?-safe? ?--? ?path?");
470 if (slavePtr == NULL) {
472 * Create an anonymous interpreter -- we choose its name and
473 * the name of the command. We check that the command name
474 * that we use for the interpreter does not collide with an
475 * existing command in the master interpreter.
481 sprintf(buf, "interp%d", i);
482 if (Tcl_GetCommandInfo(interp, buf, &cmdInfo) == 0) {
486 slavePtr = Tcl_NewStringObj(buf, -1);
488 if (SlaveCreate(interp, slavePtr, safe) == NULL) {
489 if (buf[0] != '\0') {
490 Tcl_DecrRefCount(slavePtr);
494 Tcl_SetObjResult(interp, slavePtr);
500 Tcl_Interp *slaveInterp;
502 for (i = 2; i < objc; i++) {
503 slaveInterp = GetInterp(interp, objv[i]);
504 if (slaveInterp == NULL) {
506 } else if (slaveInterp == interp) {
507 Tcl_ResetResult(interp);
508 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
509 "cannot delete the current interpreter",
513 iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo;
514 Tcl_DeleteCommandFromToken(iiPtr->slave.masterInterp,
515 iiPtr->slave.interpCmd);
520 Tcl_Interp *slaveInterp;
523 Tcl_WrongNumArgs(interp, 2, objv, "path arg ?arg ...?");
526 slaveInterp = GetInterp(interp, objv[2]);
527 if (slaveInterp == NULL) {
530 return SlaveEval(interp, slaveInterp, objc - 3, objv + 3);
534 Tcl_Interp *slaveInterp;
537 slaveInterp = GetInterp2(interp, objc, objv);
538 if (slaveInterp == NULL) {
542 Tcl_ResetResult(interp);
545 Tcl_SetIntObj(Tcl_GetObjResult(interp), exists);
549 Tcl_Interp *slaveInterp;
551 if ((objc < 4) || (objc > 5)) {
552 Tcl_WrongNumArgs(interp, 2, objv,
553 "path hiddenCmdName ?cmdName?");
556 slaveInterp = GetInterp(interp, objv[2]);
557 if (slaveInterp == NULL) {
560 return SlaveExpose(interp, slaveInterp, objc - 3, objv + 3);
563 Tcl_Interp *slaveInterp; /* A slave. */
565 if ((objc < 4) || (objc > 5)) {
566 Tcl_WrongNumArgs(interp, 2, objv,
567 "path cmdName ?hiddenCmdName?");
570 slaveInterp = GetInterp(interp, objv[2]);
571 if (slaveInterp == (Tcl_Interp *) NULL) {
574 return SlaveHide(interp, slaveInterp, objc - 3, objv + 3);
577 Tcl_Interp *slaveInterp; /* A slave. */
579 slaveInterp = GetInterp2(interp, objc, objv);
580 if (slaveInterp == NULL) {
583 return SlaveHidden(interp, slaveInterp);
586 Tcl_Interp *slaveInterp;
588 slaveInterp = GetInterp2(interp, objc, objv);
589 if (slaveInterp == NULL) {
592 Tcl_SetIntObj(Tcl_GetObjResult(interp), Tcl_IsSafe(slaveInterp));
595 case OPT_INVOKEHID: {
596 int i, index, global;
597 Tcl_Interp *slaveInterp;
598 static CONST char *hiddenOptions[] = {
599 "-global", "--", NULL
606 for (i = 3; i < objc; i++) {
607 if (Tcl_GetString(objv[i])[0] != '-') {
610 if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions,
611 "option", 0, &index) != TCL_OK) {
614 if (index == OPT_GLOBAL) {
622 Tcl_WrongNumArgs(interp, 2, objv,
623 "path ?-global? ?--? cmd ?arg ..?");
626 slaveInterp = GetInterp(interp, objv[2]);
627 if (slaveInterp == (Tcl_Interp *) NULL) {
630 return SlaveInvokeHidden(interp, slaveInterp, global, objc - i,
633 case OPT_MARKTRUSTED: {
634 Tcl_Interp *slaveInterp;
637 Tcl_WrongNumArgs(interp, 2, objv, "path");
640 slaveInterp = GetInterp(interp, objv[2]);
641 if (slaveInterp == NULL) {
644 return SlaveMarkTrusted(interp, slaveInterp);
647 Tcl_Interp *slaveInterp;
649 if (objc != 3 && objc != 4) {
650 Tcl_WrongNumArgs(interp, 2, objv, "path ?newlimit?");
653 slaveInterp = GetInterp(interp, objv[2]);
654 if (slaveInterp == NULL) {
657 return SlaveRecursionLimit(interp, slaveInterp, objc - 3, objv + 3);
660 Tcl_Interp *slaveInterp;
664 Tcl_HashSearch hashSearch;
667 slaveInterp = GetInterp2(interp, objc, objv);
668 if (slaveInterp == NULL) {
671 iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo;
672 resultPtr = Tcl_GetObjResult(interp);
673 hPtr = Tcl_FirstHashEntry(&iiPtr->master.slaveTable, &hashSearch);
674 for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&hashSearch)) {
675 string = Tcl_GetHashKey(&iiPtr->master.slaveTable, hPtr);
676 Tcl_ListObjAppendElement(NULL, resultPtr,
677 Tcl_NewStringObj(string, -1));
682 Tcl_Interp *slaveInterp; /* A slave. */
683 Tcl_Interp *masterInterp; /* Its master. */
687 Tcl_WrongNumArgs(interp, 2, objv, "srcPath channelId destPath");
690 masterInterp = GetInterp(interp, objv[2]);
691 if (masterInterp == NULL) {
694 chan = Tcl_GetChannel(masterInterp, Tcl_GetString(objv[3]),
697 TclTransferResult(masterInterp, TCL_OK, interp);
700 slaveInterp = GetInterp(interp, objv[4]);
701 if (slaveInterp == NULL) {
704 Tcl_RegisterChannel(slaveInterp, chan);
708 Tcl_Interp *slaveInterp;
715 Tcl_WrongNumArgs(interp, 2, objv, "path alias");
719 slaveInterp = GetInterp(interp, objv[2]);
720 if (slaveInterp == NULL) {
724 aliasName = Tcl_GetString(objv[3]);
726 iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo;
727 hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName);
729 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
730 "alias \"", aliasName, "\" in path \"",
731 Tcl_GetString(objv[2]), "\" not found",
735 aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
736 if (Tcl_GetInterpPath(interp, aliasPtr->targetInterp) != TCL_OK) {
737 Tcl_ResetResult(interp);
738 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
739 "target interpreter for alias \"", aliasName,
740 "\" in path \"", Tcl_GetString(objv[2]),
741 "\" is not my descendant", (char *) NULL);
747 Tcl_Interp *slaveInterp; /* A slave. */
748 Tcl_Interp *masterInterp; /* Its master. */
752 Tcl_WrongNumArgs(interp, 2, objv,
753 "srcPath channelId destPath");
756 masterInterp = GetInterp(interp, objv[2]);
757 if (masterInterp == NULL) {
760 chan = Tcl_GetChannel(masterInterp, Tcl_GetString(objv[3]), NULL);
762 TclTransferResult(masterInterp, TCL_OK, interp);
765 slaveInterp = GetInterp(interp, objv[4]);
766 if (slaveInterp == NULL) {
769 Tcl_RegisterChannel(slaveInterp, chan);
770 if (Tcl_UnregisterChannel(masterInterp, chan) != TCL_OK) {
771 TclTransferResult(masterInterp, TCL_OK, interp);
781 *---------------------------------------------------------------------------
785 * Helper function for Tcl_InterpObjCmd() to convert the interp name
786 * potentially specified on the command line to an Tcl_Interp.
789 * The return value is the interp specified on the command line,
790 * or the interp argument itself if no interp was specified on the
791 * command line. If the interp could not be found or the wrong
792 * number of arguments was specified on the command line, the return
793 * value is NULL and an error message is left in the interp's result.
798 *---------------------------------------------------------------------------
802 GetInterp2(interp, objc, objv)
803 Tcl_Interp *interp; /* Default interp if no interp was specified
804 * on the command line. */
805 int objc; /* Number of arguments. */
806 Tcl_Obj *CONST objv[]; /* Argument objects. */
810 } else if (objc == 3) {
811 return GetInterp(interp, objv[2]);
813 Tcl_WrongNumArgs(interp, 2, objv, "?path?");
819 *----------------------------------------------------------------------
823 * Creates an alias between two interpreters.
826 * A standard Tcl result.
829 * Creates a new alias, manipulates the result field of slaveInterp.
831 *----------------------------------------------------------------------
835 Tcl_CreateAlias(slaveInterp, slaveCmd, targetInterp, targetCmd, argc, argv)
836 Tcl_Interp *slaveInterp; /* Interpreter for source command. */
837 CONST char *slaveCmd; /* Command to install in slave. */
838 Tcl_Interp *targetInterp; /* Interpreter for target command. */
839 CONST char *targetCmd; /* Name of target command. */
840 int argc; /* How many additional arguments? */
841 CONST char * CONST *argv; /* These are the additional args. */
843 Tcl_Obj *slaveObjPtr, *targetObjPtr;
848 objv = (Tcl_Obj **) ckalloc((unsigned) sizeof(Tcl_Obj *) * argc);
849 for (i = 0; i < argc; i++) {
850 objv[i] = Tcl_NewStringObj(argv[i], -1);
851 Tcl_IncrRefCount(objv[i]);
854 slaveObjPtr = Tcl_NewStringObj(slaveCmd, -1);
855 Tcl_IncrRefCount(slaveObjPtr);
857 targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
858 Tcl_IncrRefCount(targetObjPtr);
860 result = AliasCreate(slaveInterp, slaveInterp, targetInterp, slaveObjPtr,
861 targetObjPtr, argc, objv);
863 for (i = 0; i < argc; i++) {
864 Tcl_DecrRefCount(objv[i]);
866 ckfree((char *) objv);
867 Tcl_DecrRefCount(targetObjPtr);
868 Tcl_DecrRefCount(slaveObjPtr);
874 *----------------------------------------------------------------------
876 * Tcl_CreateAliasObj --
878 * Object version: Creates an alias between two interpreters.
881 * A standard Tcl result.
884 * Creates a new alias.
886 *----------------------------------------------------------------------
890 Tcl_CreateAliasObj(slaveInterp, slaveCmd, targetInterp, targetCmd, objc, objv)
891 Tcl_Interp *slaveInterp; /* Interpreter for source command. */
892 CONST char *slaveCmd; /* Command to install in slave. */
893 Tcl_Interp *targetInterp; /* Interpreter for target command. */
894 CONST char *targetCmd; /* Name of target command. */
895 int objc; /* How many additional arguments? */
896 Tcl_Obj *CONST objv[]; /* Argument vector. */
898 Tcl_Obj *slaveObjPtr, *targetObjPtr;
901 slaveObjPtr = Tcl_NewStringObj(slaveCmd, -1);
902 Tcl_IncrRefCount(slaveObjPtr);
904 targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
905 Tcl_IncrRefCount(targetObjPtr);
907 result = AliasCreate(slaveInterp, slaveInterp, targetInterp, slaveObjPtr,
908 targetObjPtr, objc, objv);
910 Tcl_DecrRefCount(slaveObjPtr);
911 Tcl_DecrRefCount(targetObjPtr);
916 *----------------------------------------------------------------------
920 * Gets information about an alias.
923 * A standard Tcl result.
928 *----------------------------------------------------------------------
932 Tcl_GetAlias(interp, aliasName, targetInterpPtr, targetNamePtr, argcPtr,
934 Tcl_Interp *interp; /* Interp to start search from. */
935 CONST char *aliasName; /* Name of alias to find. */
936 Tcl_Interp **targetInterpPtr; /* (Return) target interpreter. */
937 CONST char **targetNamePtr; /* (Return) name of target command. */
938 int *argcPtr; /* (Return) count of addnl args. */
939 CONST char ***argvPtr; /* (Return) additional arguments. */
947 iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
948 hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName);
950 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
951 "alias \"", aliasName, "\" not found", (char *) NULL);
954 aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
955 objc = aliasPtr->objc;
956 objv = &aliasPtr->objPtr;
958 if (targetInterpPtr != NULL) {
959 *targetInterpPtr = aliasPtr->targetInterp;
961 if (targetNamePtr != NULL) {
962 *targetNamePtr = Tcl_GetString(objv[0]);
964 if (argcPtr != NULL) {
967 if (argvPtr != NULL) {
968 *argvPtr = (CONST char **)
969 ckalloc((unsigned) sizeof(CONST char *) * (objc - 1));
970 for (i = 1; i < objc; i++) {
971 *argvPtr[i - 1] = Tcl_GetString(objv[i]);
978 *----------------------------------------------------------------------
982 * Object version: Gets information about an alias.
985 * A standard Tcl result.
990 *----------------------------------------------------------------------
994 Tcl_GetAliasObj(interp, aliasName, targetInterpPtr, targetNamePtr, objcPtr,
996 Tcl_Interp *interp; /* Interp to start search from. */
997 CONST char *aliasName; /* Name of alias to find. */
998 Tcl_Interp **targetInterpPtr; /* (Return) target interpreter. */
999 CONST char **targetNamePtr; /* (Return) name of target command. */
1000 int *objcPtr; /* (Return) count of addnl args. */
1001 Tcl_Obj ***objvPtr; /* (Return) additional args. */
1004 Tcl_HashEntry *hPtr;
1009 iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
1010 hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName);
1011 if (hPtr == (Tcl_HashEntry *) NULL) {
1012 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1013 "alias \"", aliasName, "\" not found", (char *) NULL);
1016 aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
1017 objc = aliasPtr->objc;
1018 objv = &aliasPtr->objPtr;
1020 if (targetInterpPtr != (Tcl_Interp **) NULL) {
1021 *targetInterpPtr = aliasPtr->targetInterp;
1023 if (targetNamePtr != (CONST char **) NULL) {
1024 *targetNamePtr = Tcl_GetString(objv[0]);
1026 if (objcPtr != (int *) NULL) {
1027 *objcPtr = objc - 1;
1029 if (objvPtr != (Tcl_Obj ***) NULL) {
1030 *objvPtr = objv + 1;
1036 *----------------------------------------------------------------------
1038 * TclPreventAliasLoop --
1040 * When defining an alias or renaming a command, prevent an alias
1041 * loop from being formed.
1044 * A standard Tcl object result.
1047 * If TCL_ERROR is returned, the function also stores an error message
1048 * in the interpreter's result object.
1051 * This function is public internal (instead of being static to
1052 * this file) because it is also used from TclRenameCommand.
1054 *----------------------------------------------------------------------
1058 TclPreventAliasLoop(interp, cmdInterp, cmd)
1059 Tcl_Interp *interp; /* Interp in which to report errors. */
1060 Tcl_Interp *cmdInterp; /* Interp in which the command is
1062 Tcl_Command cmd; /* Tcl command we are attempting
1065 Command *cmdPtr = (Command *) cmd;
1066 Alias *aliasPtr, *nextAliasPtr;
1067 Tcl_Command aliasCmd;
1068 Command *aliasCmdPtr;
1071 * If we are not creating or renaming an alias, then it is
1072 * always OK to create or rename the command.
1075 if (cmdPtr->objProc != AliasObjCmd) {
1080 * OK, we are dealing with an alias, so traverse the chain of aliases.
1081 * If we encounter the alias we are defining (or renaming to) any in
1082 * the chain then we have a loop.
1085 aliasPtr = (Alias *) cmdPtr->objClientData;
1086 nextAliasPtr = aliasPtr;
1088 Tcl_Obj *cmdNamePtr;
1091 * If the target of the next alias in the chain is the same as
1092 * the source alias, we have a loop.
1095 if (Tcl_InterpDeleted(nextAliasPtr->targetInterp)) {
1097 * The slave interpreter can be deleted while creating the alias.
1101 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1102 "cannot define or rename alias \"",
1103 Tcl_GetString(aliasPtr->namePtr),
1104 "\": interpreter deleted", (char *) NULL);
1107 cmdNamePtr = nextAliasPtr->objPtr;
1108 aliasCmd = Tcl_FindCommand(nextAliasPtr->targetInterp,
1109 Tcl_GetString(cmdNamePtr),
1110 Tcl_GetGlobalNamespace(nextAliasPtr->targetInterp),
1112 if (aliasCmd == (Tcl_Command) NULL) {
1115 aliasCmdPtr = (Command *) aliasCmd;
1116 if (aliasCmdPtr == cmdPtr) {
1117 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1118 "cannot define or rename alias \"",
1119 Tcl_GetString(aliasPtr->namePtr),
1120 "\": would create a loop", (char *) NULL);
1125 * Otherwise, follow the chain one step further. See if the target
1126 * command is an alias - if so, follow the loop to its target
1127 * command. Otherwise we do not have a loop.
1130 if (aliasCmdPtr->objProc != AliasObjCmd) {
1133 nextAliasPtr = (Alias *) aliasCmdPtr->objClientData;
1140 *----------------------------------------------------------------------
1144 * Helper function to do the work to actually create an alias.
1147 * A standard Tcl result.
1150 * An alias command is created and entered into the alias table
1151 * for the slave interpreter.
1153 *----------------------------------------------------------------------
1157 AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
1159 Tcl_Interp *interp; /* Interp for error reporting. */
1160 Tcl_Interp *slaveInterp; /* Interp where alias cmd will live or from
1161 * which alias will be deleted. */
1162 Tcl_Interp *masterInterp; /* Interp in which target command will be
1164 Tcl_Obj *namePtr; /* Name of alias cmd. */
1165 Tcl_Obj *targetNamePtr; /* Name of target cmd. */
1166 int objc; /* Additional arguments to store */
1167 Tcl_Obj *CONST objv[]; /* with alias. */
1170 Tcl_HashEntry *hPtr;
1177 aliasPtr = (Alias *) ckalloc((unsigned) (sizeof(Alias)
1178 + objc * sizeof(Tcl_Obj *)));
1179 aliasPtr->namePtr = namePtr;
1180 Tcl_IncrRefCount(aliasPtr->namePtr);
1181 aliasPtr->targetInterp = masterInterp;
1183 aliasPtr->objc = objc + 1;
1184 prefv = &aliasPtr->objPtr;
1186 *prefv = targetNamePtr;
1187 Tcl_IncrRefCount(targetNamePtr);
1188 for (i = 0; i < objc; i++) {
1189 *(++prefv) = objv[i];
1190 Tcl_IncrRefCount(objv[i]);
1193 Tcl_Preserve(slaveInterp);
1194 Tcl_Preserve(masterInterp);
1196 aliasPtr->slaveCmd = Tcl_CreateObjCommand(slaveInterp,
1197 Tcl_GetString(namePtr), AliasObjCmd, (ClientData) aliasPtr,
1198 AliasObjCmdDeleteProc);
1200 if (TclPreventAliasLoop(interp, slaveInterp,
1201 aliasPtr->slaveCmd) != TCL_OK) {
1203 * Found an alias loop! The last call to Tcl_CreateObjCommand made
1204 * the alias point to itself. Delete the command and its alias
1205 * record. Be careful to wipe out its client data first, so the
1206 * command doesn't try to delete itself.
1211 Tcl_DecrRefCount(aliasPtr->namePtr);
1212 Tcl_DecrRefCount(targetNamePtr);
1213 for (i = 0; i < objc; i++) {
1214 Tcl_DecrRefCount(objv[i]);
1217 cmdPtr = (Command *) aliasPtr->slaveCmd;
1218 cmdPtr->clientData = NULL;
1219 cmdPtr->deleteProc = NULL;
1220 cmdPtr->deleteData = NULL;
1221 Tcl_DeleteCommandFromToken(slaveInterp, aliasPtr->slaveCmd);
1223 ckfree((char *) aliasPtr);
1226 * The result was already set by TclPreventAliasLoop.
1229 Tcl_Release(slaveInterp);
1230 Tcl_Release(masterInterp);
1235 * Make an entry in the alias table. If it already exists delete
1236 * the alias command. Then retry.
1239 slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
1244 string = Tcl_GetString(namePtr);
1245 hPtr = Tcl_CreateHashEntry(&slavePtr->aliasTable, string, &new);
1250 oldAliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
1251 Tcl_DeleteCommandFromToken(slaveInterp, oldAliasPtr->slaveCmd);
1254 aliasPtr->aliasEntryPtr = hPtr;
1255 Tcl_SetHashValue(hPtr, (ClientData) aliasPtr);
1258 * Create the new command. We must do it after deleting any old command,
1259 * because the alias may be pointing at a renamed alias, as in:
1261 * interp alias {} foo {} bar # Create an alias "foo"
1262 * rename foo zop # Now rename the alias
1263 * interp alias {} foo {} zop # Now recreate "foo"...
1266 targetPtr = (Target *) ckalloc((unsigned) sizeof(Target));
1267 targetPtr->slaveCmd = aliasPtr->slaveCmd;
1268 targetPtr->slaveInterp = slaveInterp;
1270 Tcl_MutexLock(&cntMutex);
1271 masterPtr = &((InterpInfo *) ((Interp *) masterInterp)->interpInfo)->master;
1273 hPtr = Tcl_CreateHashEntry(&masterPtr->targetTable,
1274 (char *) aliasCounter, &new);
1277 Tcl_MutexUnlock(&cntMutex);
1279 Tcl_SetHashValue(hPtr, (ClientData) targetPtr);
1280 aliasPtr->targetEntryPtr = hPtr;
1282 Tcl_SetObjResult(interp, namePtr);
1284 Tcl_Release(slaveInterp);
1285 Tcl_Release(masterInterp);
1290 *----------------------------------------------------------------------
1294 * Deletes the given alias from the slave interpreter given.
1297 * A standard Tcl result.
1300 * Deletes the alias from the slave interpreter.
1302 *----------------------------------------------------------------------
1306 AliasDelete(interp, slaveInterp, namePtr)
1307 Tcl_Interp *interp; /* Interpreter for result & errors. */
1308 Tcl_Interp *slaveInterp; /* Interpreter containing alias. */
1309 Tcl_Obj *namePtr; /* Name of alias to delete. */
1313 Tcl_HashEntry *hPtr;
1316 * If the alias has been renamed in the slave, the master can still use
1317 * the original name (with which it was created) to find the alias to
1321 slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
1322 hPtr = Tcl_FindHashEntry(&slavePtr->aliasTable, Tcl_GetString(namePtr));
1324 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "alias \"",
1325 Tcl_GetString(namePtr), "\" not found", NULL);
1328 aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
1329 Tcl_DeleteCommandFromToken(slaveInterp, aliasPtr->slaveCmd);
1334 *----------------------------------------------------------------------
1338 * Sets the interpreter's result object to a Tcl list describing
1339 * the given alias in the given interpreter: its target command
1340 * and the additional arguments to prepend to any invocation
1344 * A standard Tcl result.
1349 *----------------------------------------------------------------------
1353 AliasDescribe(interp, slaveInterp, namePtr)
1354 Tcl_Interp *interp; /* Interpreter for result & errors. */
1355 Tcl_Interp *slaveInterp; /* Interpreter containing alias. */
1356 Tcl_Obj *namePtr; /* Name of alias to describe. */
1359 Tcl_HashEntry *hPtr;
1364 * If the alias has been renamed in the slave, the master can still use
1365 * the original name (with which it was created) to find the alias to
1369 slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
1370 hPtr = Tcl_FindHashEntry(&slavePtr->aliasTable, Tcl_GetString(namePtr));
1374 aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
1375 prefixPtr = Tcl_NewListObj(aliasPtr->objc, &aliasPtr->objPtr);
1376 Tcl_SetObjResult(interp, prefixPtr);
1381 *----------------------------------------------------------------------
1385 * Computes a list of aliases defined in a slave interpreter.
1388 * A standard Tcl result.
1393 *----------------------------------------------------------------------
1397 AliasList(interp, slaveInterp)
1398 Tcl_Interp *interp; /* Interp for data return. */
1399 Tcl_Interp *slaveInterp; /* Interp whose aliases to compute. */
1401 Tcl_HashEntry *entryPtr;
1402 Tcl_HashSearch hashSearch;
1407 slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
1408 resultPtr = Tcl_GetObjResult(interp);
1410 entryPtr = Tcl_FirstHashEntry(&slavePtr->aliasTable, &hashSearch);
1411 for ( ; entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&hashSearch)) {
1412 aliasPtr = (Alias *) Tcl_GetHashValue(entryPtr);
1413 Tcl_ListObjAppendElement(NULL, resultPtr, aliasPtr->namePtr);
1419 *----------------------------------------------------------------------
1423 * This is the procedure that services invocations of aliases in a
1424 * slave interpreter. One such command exists for each alias. When
1425 * invoked, this procedure redirects the invocation to the target
1426 * command in the master interpreter as designated by the Alias
1427 * record associated with this command.
1430 * A standard Tcl result.
1433 * Causes forwarding of the invocation; all possible side effects
1434 * may occur as a result of invoking the command to which the
1435 * invocation is forwarded.
1437 *----------------------------------------------------------------------
1441 AliasObjCmd(clientData, interp, objc, objv)
1442 ClientData clientData; /* Alias record. */
1443 Tcl_Interp *interp; /* Current interpreter. */
1444 int objc; /* Number of arguments. */
1445 Tcl_Obj *CONST objv[]; /* Argument vector. */
1447 #define ALIAS_CMDV_PREALLOC 10
1448 Tcl_Interp *targetInterp;
1450 int result, prefc, cmdc, i;
1451 Tcl_Obj **prefv, **cmdv;
1452 Tcl_Obj *cmdArr[ALIAS_CMDV_PREALLOC];
1453 aliasPtr = (Alias *) clientData;
1454 targetInterp = aliasPtr->targetInterp;
1457 * Append the arguments to the command prefix and invoke the command
1458 * in the target interp's global namespace.
1461 prefc = aliasPtr->objc;
1462 prefv = &aliasPtr->objPtr;
1463 cmdc = prefc + objc - 1;
1464 if (cmdc <= ALIAS_CMDV_PREALLOC) {
1467 cmdv = (Tcl_Obj **) ckalloc((unsigned) (cmdc * sizeof(Tcl_Obj *)));
1470 prefv = &aliasPtr->objPtr;
1471 memcpy((VOID *) cmdv, (VOID *) prefv,
1472 (size_t) (prefc * sizeof(Tcl_Obj *)));
1473 memcpy((VOID *) (cmdv+prefc), (VOID *) (objv+1),
1474 (size_t) ((objc-1) * sizeof(Tcl_Obj *)));
1476 Tcl_ResetResult(targetInterp);
1478 for (i=0; i<cmdc; i++) {
1479 Tcl_IncrRefCount(cmdv[i]);
1481 if (targetInterp != interp) {
1482 Tcl_Preserve((ClientData) targetInterp);
1483 result = Tcl_EvalObjv(targetInterp, cmdc, cmdv, TCL_EVAL_INVOKE);
1484 TclTransferResult(targetInterp, result, interp);
1485 Tcl_Release((ClientData) targetInterp);
1487 result = Tcl_EvalObjv(targetInterp, cmdc, cmdv, TCL_EVAL_INVOKE);
1489 for (i=0; i<cmdc; i++) {
1490 Tcl_DecrRefCount(cmdv[i]);
1493 if (cmdv != cmdArr) {
1494 ckfree((char *) cmdv);
1497 #undef ALIAS_CMDV_PREALLOC
1501 *----------------------------------------------------------------------
1503 * AliasObjCmdDeleteProc --
1505 * Is invoked when an alias command is deleted in a slave. Cleans up
1506 * all storage associated with this alias.
1512 * Deletes the alias record and its entry in the alias table for
1515 *----------------------------------------------------------------------
1519 AliasObjCmdDeleteProc(clientData)
1520 ClientData clientData; /* The alias record for this alias. */
1527 aliasPtr = (Alias *) clientData;
1529 Tcl_DecrRefCount(aliasPtr->namePtr);
1530 objv = &aliasPtr->objPtr;
1531 for (i = 0; i < aliasPtr->objc; i++) {
1532 Tcl_DecrRefCount(objv[i]);
1534 Tcl_DeleteHashEntry(aliasPtr->aliasEntryPtr);
1536 targetPtr = (Target *) Tcl_GetHashValue(aliasPtr->targetEntryPtr);
1537 ckfree((char *) targetPtr);
1538 Tcl_DeleteHashEntry(aliasPtr->targetEntryPtr);
1540 ckfree((char *) aliasPtr);
1544 *----------------------------------------------------------------------
1546 * Tcl_CreateSlave --
1548 * Creates a slave interpreter. The slavePath argument denotes the
1549 * name of the new slave relative to the current interpreter; the
1550 * slave is a direct descendant of the one-before-last component of
1551 * the path, e.g. it is a descendant of the current interpreter if
1552 * the slavePath argument contains only one component. Optionally makes
1553 * the slave interpreter safe.
1556 * Returns the interpreter structure created, or NULL if an error
1560 * Creates a new interpreter and a new interpreter object command in
1561 * the interpreter indicated by the slavePath argument.
1563 *----------------------------------------------------------------------
1566 EXPORT_C Tcl_Interp *
1567 Tcl_CreateSlave(interp, slavePath, isSafe)
1568 Tcl_Interp *interp; /* Interpreter to start search at. */
1569 CONST char *slavePath; /* Name of slave to create. */
1570 int isSafe; /* Should new slave be "safe" ? */
1573 Tcl_Interp *slaveInterp;
1575 pathPtr = Tcl_NewStringObj(slavePath, -1);
1576 slaveInterp = SlaveCreate(interp, pathPtr, isSafe);
1577 Tcl_DecrRefCount(pathPtr);
1583 *----------------------------------------------------------------------
1587 * Finds a slave interpreter by its path name.
1590 * Returns a Tcl_Interp * for the named interpreter or NULL if not
1596 *----------------------------------------------------------------------
1599 EXPORT_C Tcl_Interp *
1600 Tcl_GetSlave(interp, slavePath)
1601 Tcl_Interp *interp; /* Interpreter to start search from. */
1602 CONST char *slavePath; /* Path of slave to find. */
1605 Tcl_Interp *slaveInterp;
1607 pathPtr = Tcl_NewStringObj(slavePath, -1);
1608 slaveInterp = GetInterp(interp, pathPtr);
1609 Tcl_DecrRefCount(pathPtr);
1615 *----------------------------------------------------------------------
1619 * Finds the master interpreter of a slave interpreter.
1622 * Returns a Tcl_Interp * for the master interpreter or NULL if none.
1627 *----------------------------------------------------------------------
1630 EXPORT_C Tcl_Interp *
1631 Tcl_GetMaster(interp)
1632 Tcl_Interp *interp; /* Get the master of this interpreter. */
1634 Slave *slavePtr; /* Slave record of this interpreter. */
1636 if (interp == (Tcl_Interp *) NULL) {
1639 slavePtr = &((InterpInfo *) ((Interp *) interp)->interpInfo)->slave;
1640 return slavePtr->masterInterp;
1644 *----------------------------------------------------------------------
1646 * Tcl_GetInterpPath --
1648 * Sets the result of the asking interpreter to a proper Tcl list
1649 * containing the names of interpreters between the asking and
1650 * target interpreters. The target interpreter must be either the
1651 * same as the asking interpreter or one of its slaves (including
1655 * TCL_OK if the target interpreter is the same as, or a descendant
1656 * of, the asking interpreter; TCL_ERROR else. This way one can
1657 * distinguish between the case where the asking and target interps
1658 * are the same (an empty list is the result, and TCL_OK is returned)
1659 * and when the target is not a descendant of the asking interpreter
1660 * (in which case the Tcl result is an error message and the function
1661 * returns TCL_ERROR).
1666 *----------------------------------------------------------------------
1670 Tcl_GetInterpPath(askingInterp, targetInterp)
1671 Tcl_Interp *askingInterp; /* Interpreter to start search from. */
1672 Tcl_Interp *targetInterp; /* Interpreter to find. */
1676 if (targetInterp == askingInterp) {
1679 if (targetInterp == NULL) {
1682 iiPtr = (InterpInfo *) ((Interp *) targetInterp)->interpInfo;
1683 if (Tcl_GetInterpPath(askingInterp, iiPtr->slave.masterInterp) != TCL_OK) {
1686 Tcl_AppendElement(askingInterp,
1687 Tcl_GetHashKey(&iiPtr->master.slaveTable,
1688 iiPtr->slave.slaveEntryPtr));
1693 *----------------------------------------------------------------------
1697 * Helper function to find a slave interpreter given a pathname.
1700 * Returns the slave interpreter known by that name in the calling
1701 * interpreter, or NULL if no interpreter known by that name exists.
1704 * Assigns to the pointer variable passed in, if not NULL.
1706 *----------------------------------------------------------------------
1710 GetInterp(interp, pathPtr)
1711 Tcl_Interp *interp; /* Interp. to start search from. */
1712 Tcl_Obj *pathPtr; /* List object containing name of interp. to
1715 Tcl_HashEntry *hPtr; /* Search element. */
1716 Slave *slavePtr; /* Interim slave record. */
1719 Tcl_Interp *searchInterp; /* Interim storage for interp. to find. */
1720 InterpInfo *masterInfoPtr;
1722 if (Tcl_ListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
1726 searchInterp = interp;
1727 for (i = 0; i < objc; i++) {
1728 masterInfoPtr = (InterpInfo *) ((Interp *) searchInterp)->interpInfo;
1729 hPtr = Tcl_FindHashEntry(&masterInfoPtr->master.slaveTable,
1730 Tcl_GetString(objv[i]));
1732 searchInterp = NULL;
1735 slavePtr = (Slave *) Tcl_GetHashValue(hPtr);
1736 searchInterp = slavePtr->slaveInterp;
1737 if (searchInterp == NULL) {
1741 if (searchInterp == NULL) {
1742 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1743 "could not find interpreter \"",
1744 Tcl_GetString(pathPtr), "\"", (char *) NULL);
1746 return searchInterp;
1750 *----------------------------------------------------------------------
1754 * Helper function to do the actual work of creating a slave interp
1755 * and new object command. Also optionally makes the new slave
1756 * interpreter "safe".
1759 * Returns the new Tcl_Interp * if successful or NULL if not. If failed,
1760 * the result of the invoking interpreter contains an error message.
1763 * Creates a new slave interpreter and a new object command.
1765 *----------------------------------------------------------------------
1769 SlaveCreate(interp, pathPtr, safe)
1770 Tcl_Interp *interp; /* Interp. to start search from. */
1771 Tcl_Obj *pathPtr; /* Path (name) of slave to create. */
1772 int safe; /* Should we make it "safe"? */
1774 Tcl_Interp *masterInterp, *slaveInterp;
1776 InterpInfo *masterInfoPtr;
1777 Tcl_HashEntry *hPtr;
1782 if (Tcl_ListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
1786 masterInterp = interp;
1787 path = Tcl_GetString(pathPtr);
1791 objPtr = Tcl_NewListObj(objc - 1, objv);
1792 masterInterp = GetInterp(interp, objPtr);
1793 Tcl_DecrRefCount(objPtr);
1794 if (masterInterp == NULL) {
1797 path = Tcl_GetString(objv[objc - 1]);
1800 safe = Tcl_IsSafe(masterInterp);
1803 masterInfoPtr = (InterpInfo *) ((Interp *) masterInterp)->interpInfo;
1804 hPtr = Tcl_CreateHashEntry(&masterInfoPtr->master.slaveTable, path, &new);
1806 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1807 "interpreter named \"", path,
1808 "\" already exists, cannot create", (char *) NULL);
1812 slaveInterp = Tcl_CreateInterp();
1813 slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
1814 slavePtr->masterInterp = masterInterp;
1815 slavePtr->slaveEntryPtr = hPtr;
1816 slavePtr->slaveInterp = slaveInterp;
1817 slavePtr->interpCmd = Tcl_CreateObjCommand(masterInterp, path,
1818 SlaveObjCmd, (ClientData) slaveInterp, SlaveObjCmdDeleteProc);
1819 Tcl_InitHashTable(&slavePtr->aliasTable, TCL_STRING_KEYS);
1820 Tcl_SetHashValue(hPtr, (ClientData) slavePtr);
1821 Tcl_SetVar(slaveInterp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
1824 * Inherit the recursion limit.
1826 ((Interp *) slaveInterp)->maxNestingDepth =
1827 ((Interp *) masterInterp)->maxNestingDepth ;
1830 if (Tcl_MakeSafe(slaveInterp) == TCL_ERROR) {
1834 if (Tcl_Init(slaveInterp) == TCL_ERROR) {
1838 * This will create the "memory" command in slave interpreters
1839 * if we compiled with TCL_MEM_DEBUG, otherwise it does nothing.
1841 Tcl_InitMemory(slaveInterp);
1846 TclTransferResult(slaveInterp, TCL_ERROR, interp);
1847 Tcl_DeleteInterp(slaveInterp);
1853 *----------------------------------------------------------------------
1857 * Command to manipulate an interpreter, e.g. to send commands to it
1858 * to be evaluated. One such command exists for each slave interpreter.
1861 * A standard Tcl result.
1864 * See user documentation for details.
1866 *----------------------------------------------------------------------
1870 SlaveObjCmd(clientData, interp, objc, objv)
1871 ClientData clientData; /* Slave interpreter. */
1872 Tcl_Interp *interp; /* Current interpreter. */
1873 int objc; /* Number of arguments. */
1874 Tcl_Obj *CONST objv[]; /* Argument objects. */
1876 Tcl_Interp *slaveInterp;
1878 static CONST char *options[] = {
1879 "alias", "aliases", "eval", "expose",
1880 "hide", "hidden", "issafe", "invokehidden",
1881 "marktrusted", "recursionlimit", NULL
1884 OPT_ALIAS, OPT_ALIASES, OPT_EVAL, OPT_EXPOSE,
1885 OPT_HIDE, OPT_HIDDEN, OPT_ISSAFE, OPT_INVOKEHIDDEN,
1886 OPT_MARKTRUSTED, OPT_RECLIMIT
1889 slaveInterp = (Tcl_Interp *) clientData;
1890 if (slaveInterp == NULL) {
1891 panic("SlaveObjCmd: interpreter has been deleted");
1895 Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?");
1898 if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,
1899 &index) != TCL_OK) {
1903 switch ((enum options) index) {
1907 return AliasDescribe(interp, slaveInterp, objv[2]);
1909 if (Tcl_GetString(objv[3])[0] == '\0') {
1911 return AliasDelete(interp, slaveInterp, objv[2]);
1914 return AliasCreate(interp, slaveInterp, interp, objv[2],
1915 objv[3], objc - 4, objv + 4);
1918 Tcl_WrongNumArgs(interp, 2, objv,
1919 "aliasName ?targetName? ?args..?");
1924 Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
1927 return AliasList(interp, slaveInterp);
1931 Tcl_WrongNumArgs(interp, 2, objv, "arg ?arg ...?");
1934 return SlaveEval(interp, slaveInterp, objc - 2, objv + 2);
1937 if ((objc < 3) || (objc > 4)) {
1938 Tcl_WrongNumArgs(interp, 2, objv, "hiddenCmdName ?cmdName?");
1941 return SlaveExpose(interp, slaveInterp, objc - 2, objv + 2);
1944 if ((objc < 3) || (objc > 4)) {
1945 Tcl_WrongNumArgs(interp, 2, objv, "cmdName ?hiddenCmdName?");
1948 return SlaveHide(interp, slaveInterp, objc - 2, objv + 2);
1952 Tcl_WrongNumArgs(interp, 2, objv, NULL);
1955 return SlaveHidden(interp, slaveInterp);
1959 Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
1962 Tcl_SetIntObj(Tcl_GetObjResult(interp), Tcl_IsSafe(slaveInterp));
1965 case OPT_INVOKEHIDDEN: {
1966 int global, i, index;
1967 static CONST char *hiddenOptions[] = {
1968 "-global", "--", NULL
1971 OPT_GLOBAL, OPT_LAST
1974 for (i = 2; i < objc; i++) {
1975 if (Tcl_GetString(objv[i])[0] != '-') {
1978 if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions,
1979 "option", 0, &index) != TCL_OK) {
1982 if (index == OPT_GLOBAL) {
1990 Tcl_WrongNumArgs(interp, 2, objv,
1991 "?-global? ?--? cmd ?arg ..?");
1994 return SlaveInvokeHidden(interp, slaveInterp, global, objc - i,
1997 case OPT_MARKTRUSTED: {
1999 Tcl_WrongNumArgs(interp, 2, objv, NULL);
2002 return SlaveMarkTrusted(interp, slaveInterp);
2004 case OPT_RECLIMIT: {
2005 if (objc != 2 && objc != 3) {
2006 Tcl_WrongNumArgs(interp, 2, objv, "?newlimit?");
2009 return SlaveRecursionLimit(interp, slaveInterp, objc - 2, objv + 2);
2017 *----------------------------------------------------------------------
2019 * SlaveObjCmdDeleteProc --
2021 * Invoked when an object command for a slave interpreter is deleted;
2022 * cleans up all state associated with the slave interpreter and destroys
2023 * the slave interpreter.
2029 * Cleans up all state associated with the slave interpreter and
2030 * destroys the slave interpreter.
2032 *----------------------------------------------------------------------
2036 SlaveObjCmdDeleteProc(clientData)
2037 ClientData clientData; /* The SlaveRecord for the command. */
2039 Slave *slavePtr; /* Interim storage for Slave record. */
2040 Tcl_Interp *slaveInterp; /* And for a slave interp. */
2042 slaveInterp = (Tcl_Interp *) clientData;
2043 slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
2046 * Unlink the slave from its master interpreter.
2049 Tcl_DeleteHashEntry(slavePtr->slaveEntryPtr);
2052 * Set to NULL so that when the InterpInfo is cleaned up in the slave
2053 * it does not try to delete the command causing all sorts of grief.
2054 * See SlaveRecordDeleteProc().
2057 slavePtr->interpCmd = NULL;
2059 if (slavePtr->slaveInterp != NULL) {
2060 Tcl_DeleteInterp(slavePtr->slaveInterp);
2065 *----------------------------------------------------------------------
2069 * Helper function to evaluate a command in a slave interpreter.
2072 * A standard Tcl result.
2075 * Whatever the command does.
2077 *----------------------------------------------------------------------
2081 SlaveEval(interp, slaveInterp, objc, objv)
2082 Tcl_Interp *interp; /* Interp for error return. */
2083 Tcl_Interp *slaveInterp; /* The slave interpreter in which command
2084 * will be evaluated. */
2085 int objc; /* Number of arguments. */
2086 Tcl_Obj *CONST objv[]; /* Argument objects. */
2091 Tcl_Preserve((ClientData) slaveInterp);
2092 Tcl_AllowExceptions(slaveInterp);
2096 result = Tcl_EvalObjEx(slaveInterp, objv[0], 0);
2098 /* TIP #280 : Make invoker available to eval'd script */
2099 Interp* iPtr = (Interp*) interp;
2100 result = TclEvalObjEx(slaveInterp, objv[0], 0, iPtr->cmdFramePtr,0);
2103 objPtr = Tcl_ConcatObj(objc, objv);
2104 Tcl_IncrRefCount(objPtr);
2105 result = Tcl_EvalObjEx(slaveInterp, objPtr, 0);
2106 Tcl_DecrRefCount(objPtr);
2108 TclTransferResult(slaveInterp, result, interp);
2110 Tcl_Release((ClientData) slaveInterp);
2115 *----------------------------------------------------------------------
2119 * Helper function to expose a command in a slave interpreter.
2122 * A standard Tcl result.
2125 * After this call scripts in the slave will be able to invoke
2126 * the newly exposed command.
2128 *----------------------------------------------------------------------
2132 SlaveExpose(interp, slaveInterp, objc, objv)
2133 Tcl_Interp *interp; /* Interp for error return. */
2134 Tcl_Interp *slaveInterp; /* Interp in which command will be exposed. */
2135 int objc; /* Number of arguments. */
2136 Tcl_Obj *CONST objv[]; /* Argument strings. */
2140 if (Tcl_IsSafe(interp)) {
2141 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
2142 "permission denied: safe interpreter cannot expose commands",
2147 name = Tcl_GetString(objv[(objc == 1) ? 0 : 1]);
2148 if (Tcl_ExposeCommand(slaveInterp, Tcl_GetString(objv[0]),
2150 TclTransferResult(slaveInterp, TCL_ERROR, interp);
2157 *----------------------------------------------------------------------
2159 * SlaveRecursionLimit --
2161 * Helper function to set/query the Recursion limit of an interp
2164 * A standard Tcl result.
2167 * When (objc == 1), slaveInterp will be set to a new recursion
2170 *----------------------------------------------------------------------
2174 SlaveRecursionLimit(interp, slaveInterp, objc, objv)
2175 Tcl_Interp *interp; /* Interp for error return. */
2176 Tcl_Interp *slaveInterp; /* Interp in which limit is set/queried. */
2177 int objc; /* Set or Query. */
2178 Tcl_Obj *CONST objv[]; /* Argument strings. */
2184 if (Tcl_IsSafe(interp)) {
2185 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
2186 "permission denied: ",
2187 "safe interpreters cannot change recursion limit",
2191 if (Tcl_GetIntFromObj(interp, objv[0], &limit) == TCL_ERROR) {
2195 Tcl_SetObjResult(interp, Tcl_NewStringObj(
2196 "recursion limit must be > 0", -1));
2199 Tcl_SetRecursionLimit(slaveInterp, limit);
2200 iPtr = (Interp *) slaveInterp;
2201 if (interp == slaveInterp && iPtr->numLevels > limit) {
2202 Tcl_SetObjResult(interp, Tcl_NewStringObj(
2203 "falling back due to new recursion limit", -1));
2206 Tcl_SetObjResult(interp, objv[0]);
2209 limit = Tcl_SetRecursionLimit(slaveInterp, 0);
2210 Tcl_SetObjResult(interp, Tcl_NewIntObj(limit));
2216 *----------------------------------------------------------------------
2220 * Helper function to hide a command in a slave interpreter.
2223 * A standard Tcl result.
2226 * After this call scripts in the slave will no longer be able
2227 * to invoke the named command.
2229 *----------------------------------------------------------------------
2233 SlaveHide(interp, slaveInterp, objc, objv)
2234 Tcl_Interp *interp; /* Interp for error return. */
2235 Tcl_Interp *slaveInterp; /* Interp in which command will be exposed. */
2236 int objc; /* Number of arguments. */
2237 Tcl_Obj *CONST objv[]; /* Argument strings. */
2241 if (Tcl_IsSafe(interp)) {
2242 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
2243 "permission denied: safe interpreter cannot hide commands",
2248 name = Tcl_GetString(objv[(objc == 1) ? 0 : 1]);
2249 if (Tcl_HideCommand(slaveInterp, Tcl_GetString(objv[0]),
2251 TclTransferResult(slaveInterp, TCL_ERROR, interp);
2258 *----------------------------------------------------------------------
2262 * Helper function to compute list of hidden commands in a slave
2266 * A standard Tcl result.
2271 *----------------------------------------------------------------------
2275 SlaveHidden(interp, slaveInterp)
2276 Tcl_Interp *interp; /* Interp for data return. */
2277 Tcl_Interp *slaveInterp; /* Interp whose hidden commands to query. */
2279 Tcl_Obj *listObjPtr; /* Local object pointer. */
2280 Tcl_HashTable *hTblPtr; /* For local searches. */
2281 Tcl_HashEntry *hPtr; /* For local searches. */
2282 Tcl_HashSearch hSearch; /* For local searches. */
2284 listObjPtr = Tcl_GetObjResult(interp);
2285 hTblPtr = ((Interp *) slaveInterp)->hiddenCmdTablePtr;
2286 if (hTblPtr != (Tcl_HashTable *) NULL) {
2287 for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
2288 hPtr != (Tcl_HashEntry *) NULL;
2289 hPtr = Tcl_NextHashEntry(&hSearch)) {
2291 Tcl_ListObjAppendElement(NULL, listObjPtr,
2292 Tcl_NewStringObj(Tcl_GetHashKey(hTblPtr, hPtr), -1));
2299 *----------------------------------------------------------------------
2301 * SlaveInvokeHidden --
2303 * Helper function to invoke a hidden command in a slave interpreter.
2306 * A standard Tcl result.
2309 * Whatever the hidden command does.
2311 *----------------------------------------------------------------------
2315 SlaveInvokeHidden(interp, slaveInterp, global, objc, objv)
2316 Tcl_Interp *interp; /* Interp for error return. */
2317 Tcl_Interp *slaveInterp; /* The slave interpreter in which command
2318 * will be invoked. */
2319 int global; /* Non-zero to invoke in global namespace. */
2320 int objc; /* Number of arguments. */
2321 Tcl_Obj *CONST objv[]; /* Argument objects. */
2325 if (Tcl_IsSafe(interp)) {
2326 Tcl_SetStringObj(Tcl_GetObjResult(interp),
2327 "not allowed to invoke hidden commands from safe interpreter",
2332 Tcl_Preserve((ClientData) slaveInterp);
2333 Tcl_AllowExceptions(slaveInterp);
2336 result = TclObjInvokeGlobal(slaveInterp, objc, objv,
2339 result = TclObjInvoke(slaveInterp, objc, objv, TCL_INVOKE_HIDDEN);
2342 TclTransferResult(slaveInterp, result, interp);
2344 Tcl_Release((ClientData) slaveInterp);
2349 *----------------------------------------------------------------------
2351 * SlaveMarkTrusted --
2353 * Helper function to mark a slave interpreter as trusted (unsafe).
2356 * A standard Tcl result.
2359 * After this call the hard-wired security checks in the core no
2360 * longer prevent the slave from performing certain operations.
2362 *----------------------------------------------------------------------
2366 SlaveMarkTrusted(interp, slaveInterp)
2367 Tcl_Interp *interp; /* Interp for error return. */
2368 Tcl_Interp *slaveInterp; /* The slave interpreter which will be
2369 * marked trusted. */
2371 if (Tcl_IsSafe(interp)) {
2372 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
2373 "permission denied: safe interpreter cannot mark trusted",
2377 ((Interp *) slaveInterp)->flags &= ~SAFE_INTERP;
2382 *----------------------------------------------------------------------
2386 * Determines whether an interpreter is safe
2389 * 1 if it is safe, 0 if it is not.
2394 *----------------------------------------------------------------------
2399 Tcl_Interp *interp; /* Is this interpreter "safe" ? */
2403 if (interp == (Tcl_Interp *) NULL) {
2406 iPtr = (Interp *) interp;
2408 return ( (iPtr->flags) & SAFE_INTERP ) ? 1 : 0 ;
2412 *----------------------------------------------------------------------
2416 * Makes its argument interpreter contain only functionality that is
2417 * defined to be part of Safe Tcl. Unsafe commands are hidden, the
2418 * env array is unset, and the standard channels are removed.
2424 * Hides commands in its argument interpreter, and removes settings
2427 *----------------------------------------------------------------------
2431 Tcl_MakeSafe(interp)
2432 Tcl_Interp *interp; /* Interpreter to be made safe. */
2434 Tcl_Channel chan; /* Channel to remove from
2435 * safe interpreter. */
2436 Interp *iPtr = (Interp *) interp;
2438 TclHideUnsafeCommands(interp);
2440 iPtr->flags |= SAFE_INTERP;
2443 * Unsetting variables : (which should not have been set
2444 * in the first place, but...)
2448 * No env array in a safe slave.
2451 Tcl_UnsetVar(interp, "env", TCL_GLOBAL_ONLY);
2454 * Remove unsafe parts of tcl_platform
2457 Tcl_UnsetVar2(interp, "tcl_platform", "os", TCL_GLOBAL_ONLY);
2458 Tcl_UnsetVar2(interp, "tcl_platform", "osVersion", TCL_GLOBAL_ONLY);
2459 Tcl_UnsetVar2(interp, "tcl_platform", "machine", TCL_GLOBAL_ONLY);
2460 Tcl_UnsetVar2(interp, "tcl_platform", "user", TCL_GLOBAL_ONLY);
2463 * Unset path informations variables
2464 * (the only one remaining is [info nameofexecutable])
2467 Tcl_UnsetVar(interp, "tclDefaultLibrary", TCL_GLOBAL_ONLY);
2468 Tcl_UnsetVar(interp, "tcl_library", TCL_GLOBAL_ONLY);
2469 Tcl_UnsetVar(interp, "tcl_pkgPath", TCL_GLOBAL_ONLY);
2472 * Remove the standard channels from the interpreter; safe interpreters
2473 * do not ordinarily have access to stdin, stdout and stderr.
2475 * NOTE: These channels are not added to the interpreter by the
2476 * Tcl_CreateInterp call, but may be added later, by another I/O
2477 * operation. We want to ensure that the interpreter does not have
2478 * these channels even if it is being made safe after being used for
2482 chan = Tcl_GetStdChannel(TCL_STDIN);
2483 if (chan != (Tcl_Channel) NULL) {
2484 Tcl_UnregisterChannel(interp, chan);
2486 chan = Tcl_GetStdChannel(TCL_STDOUT);
2487 if (chan != (Tcl_Channel) NULL) {
2488 Tcl_UnregisterChannel(interp, chan);
2490 chan = Tcl_GetStdChannel(TCL_STDERR);
2491 if (chan != (Tcl_Channel) NULL) {
2492 Tcl_UnregisterChannel(interp, chan);