Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/tcl8.5.2/generic/tclNamesp.c @ 63

Last change on this file since 63 was 25, checked in by landauf, 17 years ago

added tcl to libs

File size: 204.7 KB
Line 
1/*
2 * tclNamesp.c --
3 *
4 *      Contains support for namespaces, which provide a separate context of
5 *      commands and global variables. The global :: namespace is the
6 *      traditional Tcl "global" scope. Other namespaces are created as
7 *      children of the global namespace. These other namespaces contain
8 *      special-purpose commands and variables for packages. Also includes the
9 *      TIP#112 ensemble machinery.
10 *
11 * Copyright (c) 1993-1997 Lucent Technologies.
12 * Copyright (c) 1997 Sun Microsystems, Inc.
13 * Copyright (c) 1998-1999 by Scriptics Corporation.
14 * Copyright (c) 2002-2005 Donal K. Fellows.
15 * Copyright (c) 2006 Neil Madden.
16 * Contributions from Don Porter, NIST, 2007. (not subject to US copyright)
17 *
18 * Originally implemented by
19 *   Michael J. McLennan
20 *   Bell Labs Innovations for Lucent Technologies
21 *   mmclennan@lucent.com
22 *
23 * See the file "license.terms" for information on usage and redistribution of
24 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
25 *
26 * RCS: @(#) $Id: tclNamesp.c,v 1.162 2008/03/02 18:46:39 msofer Exp $
27 */
28
29#include "tclInt.h"
30
31/*
32 * Thread-local storage used to avoid having a global lock on data that is not
33 * limited to a single interpreter.
34 */
35
36typedef struct ThreadSpecificData {
37    long numNsCreated;          /* Count of the number of namespaces created
38                                 * within the thread. This value is used as a
39                                 * unique id for each namespace. Cannot be
40                                 * per-interp because the nsId is used to
41                                 * distinguish objects which can be passed
42                                 * around between interps in the same thread,
43                                 * but does not need to be global because
44                                 * object internal reps are always per-thread
45                                 * anyway. */
46} ThreadSpecificData;
47
48static Tcl_ThreadDataKey dataKey;
49
50/*
51 * This structure contains a cached pointer to a namespace that is the result
52 * of resolving the namespace's name in some other namespace. It is the
53 * internal representation for a nsName object. It contains the pointer along
54 * with some information that is used to check the cached pointer's validity.
55 */
56
57typedef struct ResolvedNsName {
58    Namespace *nsPtr;          /* A cached pointer to the Namespace that the
59                                * name resolved to. */
60    Namespace *refNsPtr;       /* Points to the namespace context in which the
61                                * name was resolved. NULL if the name is fully
62                                * qualified and thus the resolution does not
63                                * depend on the context. */
64    int refCount;               /* Reference count: 1 for each nsName object
65                                 * that has a pointer to this ResolvedNsName
66                                 * structure as its internal rep. This
67                                 * structure can be freed when refCount
68                                 * becomes zero. */
69} ResolvedNsName;
70
71/*
72 * The client data for an ensemble command. This consists of the table of
73 * commands that are actually exported by the namespace, and an epoch counter
74 * that, combined with the exportLookupEpoch field of the namespace structure,
75 * defines whether the table contains valid data or will need to be recomputed
76 * next time the ensemble command is called.
77 */
78
79typedef struct EnsembleConfig {
80    Namespace *nsPtr;           /* The namspace backing this ensemble up. */
81    Tcl_Command token;          /* The token for the command that provides
82                                 * ensemble support for the namespace, or NULL
83                                 * if the command has been deleted (or never
84                                 * existed; the global namespace never has an
85                                 * ensemble command.) */
86    int epoch;                  /* The epoch at which this ensemble's table of
87                                 * exported commands is valid. */
88    char **subcommandArrayPtr;  /* Array of ensemble subcommand names. At all
89                                 * consistent points, this will have the same
90                                 * number of entries as there are entries in
91                                 * the subcommandTable hash. */
92    Tcl_HashTable subcommandTable;
93                                /* Hash table of ensemble subcommand names,
94                                 * which are its keys so this also provides
95                                 * the storage management for those subcommand
96                                 * names. The contents of the entry values are
97                                 * object version the prefix lists to use when
98                                 * substituting for the command/subcommand to
99                                 * build the ensemble implementation command.
100                                 * Has to be stored here as well as in
101                                 * subcommandDict because that field is NULL
102                                 * when we are deriving the ensemble from the
103                                 * namespace exports list. FUTURE WORK: use
104                                 * object hash table here. */
105    struct EnsembleConfig *next;/* The next ensemble in the linked list of
106                                 * ensembles associated with a namespace. If
107                                 * this field points to this ensemble, the
108                                 * structure has already been unlinked from
109                                 * all lists, and cannot be found by scanning
110                                 * the list from the namespace's ensemble
111                                 * field. */
112    int flags;                  /* ORed combo of TCL_ENSEMBLE_PREFIX, ENS_DEAD
113                                 * and ENSEMBLE_COMPILE. */
114
115    /* OBJECT FIELDS FOR ENSEMBLE CONFIGURATION */
116
117    Tcl_Obj *subcommandDict;    /* Dictionary providing mapping from
118                                 * subcommands to their implementing command
119                                 * prefixes, or NULL if we are to build the
120                                 * map automatically from the namespace
121                                 * exports. */
122    Tcl_Obj *subcmdList;        /* List of commands that this ensemble
123                                 * actually provides, and whose implementation
124                                 * will be built using the subcommandDict (if
125                                 * present and defined) and by simple mapping
126                                 * to the namespace otherwise. If NULL,
127                                 * indicates that we are using the (dynamic)
128                                 * list of currently exported commands. */
129    Tcl_Obj *unknownHandler;    /* Script prefix used to handle the case when
130                                 * no match is found (according to the rule
131                                 * defined by flag bit TCL_ENSEMBLE_PREFIX) or
132                                 * NULL to use the default error-generating
133                                 * behaviour. The script execution gets all
134                                 * the arguments to the ensemble command
135                                 * (including objv[0]) and will have the
136                                 * results passed directly back to the caller
137                                 * (including the error code) unless the code
138                                 * is TCL_CONTINUE in which case the
139                                 * subcommand will be reparsed by the ensemble
140                                 * core, presumably because the ensemble
141                                 * itself has been updated. */
142} EnsembleConfig;
143
144#define ENS_DEAD        0x1     /* Flag value to say that the ensemble is dead
145                                 * and on its way out. */
146
147/*
148 * Declarations for functions local to this file:
149 */
150
151static void             DeleteImportedCmd(ClientData clientData);
152static int              DoImport(Tcl_Interp *interp,
153                            Namespace *nsPtr, Tcl_HashEntry *hPtr,
154                            const char *cmdName, const char *pattern,
155                            Namespace *importNsPtr, int allowOverwrite);
156static void             DupNsNameInternalRep(Tcl_Obj *objPtr,Tcl_Obj *copyPtr);
157static char *           ErrorCodeRead(ClientData clientData,Tcl_Interp *interp,
158                            const char *name1, const char *name2, int flags);
159static char *           ErrorInfoRead(ClientData clientData,Tcl_Interp *interp,
160                            const char *name1, const char *name2, int flags);
161static char *           EstablishErrorCodeTraces(ClientData clientData,
162                            Tcl_Interp *interp, const char *name1,
163                            const char *name2, int flags);
164static char *           EstablishErrorInfoTraces(ClientData clientData,
165                            Tcl_Interp *interp, const char *name1,
166                            const char *name2, int flags);
167static void             FreeNsNameInternalRep(Tcl_Obj *objPtr);
168static int              GetNamespaceFromObj(Tcl_Interp *interp,
169                            Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr);
170static int              InvokeImportedCmd(ClientData clientData,
171                            Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
172static int              NamespaceChildrenCmd(ClientData dummy,
173                            Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
174static int              NamespaceCodeCmd(ClientData dummy, Tcl_Interp *interp,
175                            int objc, Tcl_Obj *const objv[]);
176static int              NamespaceCurrentCmd(ClientData dummy,
177                            Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
178static int              NamespaceDeleteCmd(ClientData dummy,Tcl_Interp *interp,
179                            int objc, Tcl_Obj *const objv[]);
180static int              NamespaceEnsembleCmd(ClientData dummy,
181                            Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
182static int              NamespaceEvalCmd(ClientData dummy, Tcl_Interp *interp,
183                            int objc, Tcl_Obj *const objv[]);
184static int              NamespaceExistsCmd(ClientData dummy,Tcl_Interp *interp,
185                            int objc, Tcl_Obj *const objv[]);
186static int              NamespaceExportCmd(ClientData dummy,Tcl_Interp *interp,
187                            int objc, Tcl_Obj *const objv[]);
188static int              NamespaceForgetCmd(ClientData dummy,Tcl_Interp *interp,
189                            int objc, Tcl_Obj *const objv[]);
190static void             NamespaceFree(Namespace *nsPtr);
191static int              NamespaceImportCmd(ClientData dummy,Tcl_Interp *interp,
192                            int objc, Tcl_Obj *const objv[]);
193static int              NamespaceInscopeCmd(ClientData dummy,
194                            Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
195static int              NamespaceOriginCmd(ClientData dummy,Tcl_Interp *interp,
196                            int objc, Tcl_Obj *const objv[]);
197static int              NamespaceParentCmd(ClientData dummy,Tcl_Interp *interp,
198                            int objc, Tcl_Obj *const objv[]);
199static int              NamespacePathCmd(ClientData dummy, Tcl_Interp *interp,
200                            int objc, Tcl_Obj *const objv[]);
201static int              NamespaceQualifiersCmd(ClientData dummy,
202                            Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
203static int              NamespaceTailCmd(ClientData dummy, Tcl_Interp *interp,
204                            int objc, Tcl_Obj *const objv[]);
205static int              NamespaceUpvarCmd(ClientData dummy, Tcl_Interp *interp,
206                            int objc, Tcl_Obj *const objv[]);
207static int              NamespaceUnknownCmd(ClientData dummy,
208                            Tcl_Interp *interp, int objc,
209                            Tcl_Obj *const objv[]);
210static int              NamespaceWhichCmd(ClientData dummy, Tcl_Interp *interp,
211                            int objc, Tcl_Obj *const objv[]);
212static int              SetNsNameFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
213static int              NsEnsembleImplementationCmd(ClientData clientData,
214                            Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
215static void             BuildEnsembleConfig(EnsembleConfig *ensemblePtr);
216static int              NsEnsembleStringOrder(const void *strPtr1,
217                            const void *strPtr2);
218static void             DeleteEnsembleConfig(ClientData clientData);
219static void             MakeCachedEnsembleCommand(Tcl_Obj *objPtr,
220                            EnsembleConfig *ensemblePtr,
221                            const char *subcmdName, Tcl_Obj *prefixObjPtr);
222static void             FreeEnsembleCmdRep(Tcl_Obj *objPtr);
223static void             DupEnsembleCmdRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
224static void             StringOfEnsembleCmdRep(Tcl_Obj *objPtr);
225static void             UnlinkNsPath(Namespace *nsPtr);
226
227/*
228 * This structure defines a Tcl object type that contains a namespace
229 * reference. It is used in commands that take the name of a namespace as an
230 * argument. The namespace reference is resolved, and the result in cached in
231 * the object.
232 */
233
234static Tcl_ObjType nsNameType = {
235    "nsName",                   /* the type's name */
236    FreeNsNameInternalRep,      /* freeIntRepProc */
237    DupNsNameInternalRep,       /* dupIntRepProc */
238    NULL,                       /* updateStringProc */
239    SetNsNameFromAny            /* setFromAnyProc */
240};
241
242/*
243 * This structure defines a Tcl object type that contains a reference to an
244 * ensemble subcommand (e.g. the "length" in [string length ab]). It is used
245 * to cache the mapping between the subcommand itself and the real command
246 * that implements it.
247 */
248
249Tcl_ObjType tclEnsembleCmdType = {
250    "ensembleCommand",          /* the type's name */
251    FreeEnsembleCmdRep,         /* freeIntRepProc */
252    DupEnsembleCmdRep,          /* dupIntRepProc */
253    StringOfEnsembleCmdRep,     /* updateStringProc */
254    NULL                        /* setFromAnyProc */
255};
256
257/*
258 *----------------------------------------------------------------------
259 *
260 * TclInitNamespaceSubsystem --
261 *
262 *      This function is called to initialize all the structures that are used
263 *      by namespaces on a per-process basis.
264 *
265 * Results:
266 *      None.
267 *
268 * Side effects:
269 *      None.
270 *
271 *----------------------------------------------------------------------
272 */
273
274void
275TclInitNamespaceSubsystem(void)
276{
277    /*
278     * Does nothing for now.
279     */
280}
281
282/*
283 *----------------------------------------------------------------------
284 *
285 * Tcl_GetCurrentNamespace --
286 *
287 *      Returns a pointer to an interpreter's currently active namespace.
288 *
289 * Results:
290 *      Returns a pointer to the interpreter's current namespace.
291 *
292 * Side effects:
293 *      None.
294 *
295 *----------------------------------------------------------------------
296 */
297
298Tcl_Namespace *
299Tcl_GetCurrentNamespace(
300    register Tcl_Interp *interp)/* Interpreter whose current namespace is
301                                 * being queried. */
302{
303    return TclGetCurrentNamespace(interp);
304}
305
306/*
307 *----------------------------------------------------------------------
308 *
309 * Tcl_GetGlobalNamespace --
310 *
311 *      Returns a pointer to an interpreter's global :: namespace.
312 *
313 * Results:
314 *      Returns a pointer to the specified interpreter's global namespace.
315 *
316 * Side effects:
317 *      None.
318 *
319 *----------------------------------------------------------------------
320 */
321
322Tcl_Namespace *
323Tcl_GetGlobalNamespace(
324    register Tcl_Interp *interp)/* Interpreter whose global namespace should
325                                 * be returned. */
326{
327    return TclGetGlobalNamespace(interp);
328}
329
330/*
331 *----------------------------------------------------------------------
332 *
333 * Tcl_PushCallFrame --
334 *
335 *      Pushes a new call frame onto the interpreter's Tcl call stack. Called
336 *      when executing a Tcl procedure or a "namespace eval" or "namespace
337 *      inscope" command.
338 *
339 * Results:
340 *      Returns TCL_OK if successful, or TCL_ERROR (along with an error
341 *      message in the interpreter's result object) if something goes wrong.
342 *
343 * Side effects:
344 *      Modifies the interpreter's Tcl call stack.
345 *
346 *----------------------------------------------------------------------
347 */
348
349int
350Tcl_PushCallFrame(
351    Tcl_Interp *interp,         /* Interpreter in which the new call frame is
352                                 * to be pushed. */
353    Tcl_CallFrame *callFramePtr,/* Points to a call frame structure to push.
354                                 * Storage for this has already been allocated
355                                 * by the caller; typically this is the
356                                 * address of a CallFrame structure allocated
357                                 * on the caller's C stack. The call frame
358                                 * will be initialized by this function. The
359                                 * caller can pop the frame later with
360                                 * Tcl_PopCallFrame, and it is responsible for
361                                 * freeing the frame's storage. */
362    Tcl_Namespace *namespacePtr,/* Points to the namespace in which the frame
363                                 * will execute. If NULL, the interpreter's
364                                 * current namespace will be used. */
365    int isProcCallFrame)        /* If nonzero, the frame represents a called
366                                 * Tcl procedure and may have local vars. Vars
367                                 * will ordinarily be looked up in the frame.
368                                 * If new variables are created, they will be
369                                 * created in the frame. If 0, the frame is
370                                 * for a "namespace eval" or "namespace
371                                 * inscope" command and var references are
372                                 * treated as references to namespace
373                                 * variables. */
374{
375    Interp *iPtr = (Interp *) interp;
376    register CallFrame *framePtr = (CallFrame *) callFramePtr;
377    register Namespace *nsPtr;
378
379    if (namespacePtr == NULL) {
380        nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
381    } else {
382        nsPtr = (Namespace *) namespacePtr;
383
384        /*
385         * TODO: Examine whether it would be better to guard based on NS_DYING
386         * or NS_KILLED. It appears that these are not tested because they can
387         * be set in a global interp that has been [namespace delete]d, but
388         * which never really completely goes away because of lingering global
389         * things like ::errorInfo and [::unknown] and hidden commands.
390         * Review of those designs might permit stricter checking here.
391         */
392
393        if (nsPtr->flags & NS_DEAD) {
394            Tcl_Panic("Trying to push call frame for dead namespace");
395            /*NOTREACHED*/
396        }
397    }
398
399    nsPtr->activationCount++;
400    framePtr->nsPtr = nsPtr;
401    framePtr->isProcCallFrame = isProcCallFrame;
402    framePtr->objc = 0;
403    framePtr->objv = NULL;
404    framePtr->callerPtr = iPtr->framePtr;
405    framePtr->callerVarPtr = iPtr->varFramePtr;
406    if (iPtr->varFramePtr != NULL) {
407        framePtr->level = (iPtr->varFramePtr->level + 1);
408    } else {
409        framePtr->level = 0;
410    }
411    framePtr->procPtr = NULL;           /* no called procedure */
412    framePtr->varTablePtr = NULL;       /* and no local variables */
413    framePtr->numCompiledLocals = 0;
414    framePtr->compiledLocals = NULL;
415    framePtr->clientData = NULL;
416    framePtr->localCachePtr = NULL;
417
418    /*
419     * Push the new call frame onto the interpreter's stack of procedure call
420     * frames making it the current frame.
421     */
422
423    iPtr->framePtr = framePtr;
424    iPtr->varFramePtr = framePtr;
425    return TCL_OK;
426}
427
428/*
429 *----------------------------------------------------------------------
430 *
431 * Tcl_PopCallFrame --
432 *
433 *      Removes a call frame from the Tcl call stack for the interpreter.
434 *      Called to remove a frame previously pushed by Tcl_PushCallFrame.
435 *
436 * Results:
437 *      None.
438 *
439 * Side effects:
440 *      Modifies the call stack of the interpreter. Resets various fields of
441 *      the popped call frame. If a namespace has been deleted and has no more
442 *      activations on the call stack, the namespace is destroyed.
443 *
444 *----------------------------------------------------------------------
445 */
446
447void
448Tcl_PopCallFrame(
449    Tcl_Interp *interp)         /* Interpreter with call frame to pop. */
450{
451    register Interp *iPtr = (Interp *) interp;
452    register CallFrame *framePtr = iPtr->framePtr;
453    Namespace *nsPtr;
454
455    /*
456     * It's important to remove the call frame from the interpreter's stack of
457     * call frames before deleting local variables, so that traces invoked by
458     * the variable deletion don't see the partially-deleted frame.
459     */
460
461    if (framePtr->callerPtr) {
462        iPtr->framePtr = framePtr->callerPtr;
463        iPtr->varFramePtr = framePtr->callerVarPtr;
464    } else {
465        /* Tcl_PopCallFrame: trying to pop rootCallFrame! */
466    }
467
468    if (framePtr->varTablePtr != NULL) {
469        TclDeleteVars(iPtr, framePtr->varTablePtr);
470        ckfree((char *) framePtr->varTablePtr);
471        framePtr->varTablePtr = NULL;
472    }
473    if (framePtr->numCompiledLocals > 0) {
474        TclDeleteCompiledLocalVars(iPtr, framePtr);
475        if (--framePtr->localCachePtr->refCount == 0) {
476            TclFreeLocalCache(interp, framePtr->localCachePtr);
477        }
478        framePtr->localCachePtr = NULL;
479    }
480
481    /*
482     * Decrement the namespace's count of active call frames. If the namespace
483     * is "dying" and there are no more active call frames, call
484     * Tcl_DeleteNamespace to destroy it.
485     */
486
487    nsPtr = framePtr->nsPtr;
488    nsPtr->activationCount--;
489    if ((nsPtr->flags & NS_DYING)
490            && (nsPtr->activationCount - (nsPtr == iPtr->globalNsPtr) == 0)) {
491        Tcl_DeleteNamespace((Tcl_Namespace *) nsPtr);
492    }
493    framePtr->nsPtr = NULL;
494}
495
496/*
497 *----------------------------------------------------------------------
498 *
499 * TclPushStackFrame --
500 *
501 *      Allocates a new call frame in the interpreter's execution stack, then
502 *      pushes it onto the interpreter's Tcl call stack. Called when executing
503 *      a Tcl procedure or a "namespace eval" or "namespace inscope" command.
504 *
505 * Results:
506 *      Returns TCL_OK if successful, or TCL_ERROR (along with an error
507 *      message in the interpreter's result object) if something goes wrong.
508 *
509 * Side effects:
510 *      Modifies the interpreter's Tcl call stack.
511 *
512 *----------------------------------------------------------------------
513 */
514
515int
516TclPushStackFrame(
517    Tcl_Interp *interp,         /* Interpreter in which the new call frame is
518                                 * to be pushed. */
519    Tcl_CallFrame **framePtrPtr,/* Place to store a pointer to the stack
520                                 * allocated call frame. */
521    Tcl_Namespace *namespacePtr,/* Points to the namespace in which the frame
522                                 * will execute. If NULL, the interpreter's
523                                 * current namespace will be used. */
524    int isProcCallFrame)        /* If nonzero, the frame represents a called
525                                 * Tcl procedure and may have local vars. Vars
526                                 * will ordinarily be looked up in the frame.
527                                 * If new variables are created, they will be
528                                 * created in the frame. If 0, the frame is
529                                 * for a "namespace eval" or "namespace
530                                 * inscope" command and var references are
531                                 * treated as references to namespace
532                                 * variables. */
533{
534    *framePtrPtr = (Tcl_CallFrame *) TclStackAlloc(interp, sizeof(CallFrame));
535    return Tcl_PushCallFrame(interp, *framePtrPtr, namespacePtr,
536            isProcCallFrame);
537}
538
539void
540TclPopStackFrame(
541    Tcl_Interp *interp)         /* Interpreter with call frame to pop. */
542{
543    CallFrame *freePtr = ((Interp *)interp)->framePtr;
544
545    Tcl_PopCallFrame(interp);
546    TclStackFree(interp, freePtr);
547}
548
549/*
550 *----------------------------------------------------------------------
551 *
552 * EstablishErrorCodeTraces --
553 *
554 *      Creates traces on the ::errorCode variable to keep its value
555 *      consistent with the expectations of legacy code.
556 *
557 * Results:
558 *      None.
559 *
560 * Side effects:
561 *      Read and unset traces are established on ::errorCode.
562 *
563 *----------------------------------------------------------------------
564 */
565
566static char *
567EstablishErrorCodeTraces(
568    ClientData clientData,
569    Tcl_Interp *interp,
570    const char *name1,
571    const char *name2,
572    int flags)
573{
574    Tcl_TraceVar(interp, "errorCode", TCL_GLOBAL_ONLY | TCL_TRACE_READS,
575            ErrorCodeRead, NULL);
576    Tcl_TraceVar(interp, "errorCode", TCL_GLOBAL_ONLY | TCL_TRACE_UNSETS,
577            EstablishErrorCodeTraces, NULL);
578    return NULL;
579}
580
581/*
582 *----------------------------------------------------------------------
583 *
584 * ErrorCodeRead --
585 *
586 *      Called when the ::errorCode variable is read. Copies the current value
587 *      of the interp's errorCode field into ::errorCode.
588 *
589 * Results:
590 *      None.
591 *
592 * Side effects:
593 *      None.
594 *
595 *----------------------------------------------------------------------
596 */
597
598static char *
599ErrorCodeRead(
600    ClientData clientData,
601    Tcl_Interp *interp,
602    const char *name1,
603    const char *name2,
604    int flags)
605{
606    Interp *iPtr = (Interp *)interp;
607
608    if (Tcl_InterpDeleted(interp) || !(iPtr->flags & ERR_LEGACY_COPY)) {
609        return NULL;
610    }
611    if (iPtr->errorCode) {
612        Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL,
613                iPtr->errorCode, TCL_GLOBAL_ONLY);
614        return NULL;
615    }
616    if (NULL == Tcl_ObjGetVar2(interp, iPtr->ecVar, NULL, TCL_GLOBAL_ONLY)) {
617        Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL,
618                Tcl_NewObj(), TCL_GLOBAL_ONLY);
619    }
620    return NULL;
621}
622
623/*
624 *----------------------------------------------------------------------
625 *
626 * EstablishErrorInfoTraces --
627 *
628 *      Creates traces on the ::errorInfo variable to keep its value
629 *      consistent with the expectations of legacy code.
630 *
631 * Results:
632 *      None.
633 *
634 * Side effects:
635 *      Read and unset traces are established on ::errorInfo.
636 *
637 *----------------------------------------------------------------------
638 */
639
640static char *
641EstablishErrorInfoTraces(
642    ClientData clientData,
643    Tcl_Interp *interp,
644    const char *name1,
645    const char *name2,
646    int flags)
647{
648    Tcl_TraceVar(interp, "errorInfo", TCL_GLOBAL_ONLY | TCL_TRACE_READS,
649            ErrorInfoRead, NULL);
650    Tcl_TraceVar(interp, "errorInfo", TCL_GLOBAL_ONLY | TCL_TRACE_UNSETS,
651            EstablishErrorInfoTraces, NULL);
652    return NULL;
653}
654
655/*
656 *----------------------------------------------------------------------
657 *
658 * ErrorInfoRead --
659 *
660 *      Called when the ::errorInfo variable is read. Copies the current value
661 *      of the interp's errorInfo field into ::errorInfo.
662 *
663 * Results:
664 *      None.
665 *
666 * Side effects:
667 *      None.
668 *
669 *----------------------------------------------------------------------
670 */
671
672static char *
673ErrorInfoRead(
674    ClientData clientData,
675    Tcl_Interp *interp,
676    const char *name1,
677    const char *name2,
678    int flags)
679{
680    Interp *iPtr = (Interp *) interp;
681
682    if (Tcl_InterpDeleted(interp) || !(iPtr->flags & ERR_LEGACY_COPY)) {
683        return NULL;
684    }
685    if (iPtr->errorInfo) {
686        Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL,
687                iPtr->errorInfo, TCL_GLOBAL_ONLY);
688        return NULL;
689    }
690    if (NULL == Tcl_ObjGetVar2(interp, iPtr->eiVar, NULL, TCL_GLOBAL_ONLY)) {
691        Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL,
692                Tcl_NewObj(), TCL_GLOBAL_ONLY);
693    }
694    return NULL;
695}
696
697/*
698 *----------------------------------------------------------------------
699 *
700 * Tcl_CreateNamespace --
701 *
702 *      Creates a new namespace with the given name. If there is no active
703 *      namespace (i.e., the interpreter is being initialized), the global ::
704 *      namespace is created and returned.
705 *
706 * Results:
707 *      Returns a pointer to the new namespace if successful. If the namespace
708 *      already exists or if another error occurs, this routine returns NULL,
709 *      along with an error message in the interpreter's result object.
710 *
711 * Side effects:
712 *      If the name contains "::" qualifiers and a parent namespace does not
713 *      already exist, it is automatically created.
714 *
715 *----------------------------------------------------------------------
716 */
717
718Tcl_Namespace *
719Tcl_CreateNamespace(
720    Tcl_Interp *interp,         /* Interpreter in which a new namespace is
721                                 * being created. Also used for error
722                                 * reporting. */
723    const char *name,           /* Name for the new namespace. May be a
724                                 * qualified name with names of ancestor
725                                 * namespaces separated by "::"s. */
726    ClientData clientData,      /* One-word value to store with namespace. */
727    Tcl_NamespaceDeleteProc *deleteProc)
728                                /* Function called to delete client data when
729                                 * the namespace is deleted. NULL if no
730                                 * function should be called. */
731{
732    Interp *iPtr = (Interp *) interp;
733    register Namespace *nsPtr, *ancestorPtr;
734    Namespace *parentPtr, *dummy1Ptr, *dummy2Ptr;
735    Namespace *globalNsPtr = iPtr->globalNsPtr;
736    const char *simpleName;
737    Tcl_HashEntry *entryPtr;
738    Tcl_DString buffer1, buffer2;
739    Tcl_DString *namePtr, *buffPtr;
740    int newEntry, nameLen;
741    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
742
743    /*
744     * If there is no active namespace, the interpreter is being initialized.
745     */
746
747    if ((globalNsPtr == NULL) && (iPtr->varFramePtr == NULL)) {
748        /*
749         * Treat this namespace as the global namespace, and avoid looking for
750         * a parent.
751         */
752
753        parentPtr = NULL;
754        simpleName = "";
755    } else if (*name == '\0') {
756        Tcl_ResetResult(interp);
757        Tcl_AppendResult(interp, "can't create namespace \"\": "
758                "only global namespace can have empty name", NULL);
759        return NULL;
760    } else {
761        /*
762         * Find the parent for the new namespace.
763         */
764
765        TclGetNamespaceForQualName(interp, name, NULL,
766                /*flags*/ (TCL_CREATE_NS_IF_UNKNOWN | TCL_LEAVE_ERR_MSG),
767                &parentPtr, &dummy1Ptr, &dummy2Ptr, &simpleName);
768
769        /*
770         * If the unqualified name at the end is empty, there were trailing
771         * "::"s after the namespace's name which we ignore. The new namespace
772         * was already (recursively) created and is pointed to by parentPtr.
773         */
774
775        if (*simpleName == '\0') {
776            return (Tcl_Namespace *) parentPtr;
777        }
778
779        /*
780         * Check for a bad namespace name and make sure that the name does not
781         * already exist in the parent namespace.
782         */
783
784        if (Tcl_FindHashEntry(&parentPtr->childTable, simpleName) != NULL) {
785            Tcl_AppendResult(interp, "can't create namespace \"", name,
786                    "\": already exists", NULL);
787            return NULL;
788        }
789    }
790
791    /*
792     * Create the new namespace and root it in its parent. Increment the count
793     * of namespaces created.
794     */
795
796    nsPtr = (Namespace *) ckalloc(sizeof(Namespace));
797    nsPtr->name = ckalloc((unsigned) (strlen(simpleName)+1));
798    strcpy(nsPtr->name, simpleName);
799    nsPtr->fullName = NULL;             /* Set below. */
800    nsPtr->clientData = clientData;
801    nsPtr->deleteProc = deleteProc;
802    nsPtr->parentPtr = parentPtr;
803    Tcl_InitHashTable(&nsPtr->childTable, TCL_STRING_KEYS);
804    nsPtr->nsId = ++(tsdPtr->numNsCreated);
805    nsPtr->interp = interp;
806    nsPtr->flags = 0;
807    nsPtr->activationCount = 0;
808    nsPtr->refCount = 0;
809    Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS);
810    TclInitVarHashTable(&nsPtr->varTable, nsPtr);
811    nsPtr->exportArrayPtr = NULL;
812    nsPtr->numExportPatterns = 0;
813    nsPtr->maxExportPatterns = 0;
814    nsPtr->cmdRefEpoch = 0;
815    nsPtr->resolverEpoch = 0;
816    nsPtr->cmdResProc = NULL;
817    nsPtr->varResProc = NULL;
818    nsPtr->compiledVarResProc = NULL;
819    nsPtr->exportLookupEpoch = 0;
820    nsPtr->ensembles = NULL;
821    nsPtr->unknownHandlerPtr = NULL;
822    nsPtr->commandPathLength = 0;
823    nsPtr->commandPathArray = NULL;
824    nsPtr->commandPathSourceList = NULL;
825
826    if (parentPtr != NULL) {
827        entryPtr = Tcl_CreateHashEntry(&parentPtr->childTable, simpleName,
828                &newEntry);
829        Tcl_SetHashValue(entryPtr, nsPtr);
830    } else {
831        /*
832         * In the global namespace create traces to maintain the ::errorInfo
833         * and ::errorCode variables.
834         */
835
836        iPtr->globalNsPtr = nsPtr;
837        EstablishErrorInfoTraces(NULL, interp, NULL, NULL, 0);
838        EstablishErrorCodeTraces(NULL, interp, NULL, NULL, 0);
839    }
840
841    /*
842     * Build the fully qualified name for this namespace.
843     */
844
845    Tcl_DStringInit(&buffer1);
846    Tcl_DStringInit(&buffer2);
847    namePtr = &buffer1;
848    buffPtr = &buffer2;
849    for (ancestorPtr = nsPtr; ancestorPtr != NULL;
850            ancestorPtr = ancestorPtr->parentPtr) {
851        if (ancestorPtr != globalNsPtr) {
852            register Tcl_DString *tempPtr = namePtr;
853
854            Tcl_DStringAppend(buffPtr, "::", 2);
855            Tcl_DStringAppend(buffPtr, ancestorPtr->name, -1);
856            Tcl_DStringAppend(buffPtr, Tcl_DStringValue(namePtr),
857                    Tcl_DStringLength(namePtr));
858
859            /*
860             * Clear the unwanted buffer or we end up appending to previous
861             * results, making the namespace fullNames of nested namespaces
862             * very wrong (and strange).
863             */
864
865            Tcl_DStringSetLength(namePtr, 0);
866
867            /*
868             * Now swap the buffer pointers so that we build in the other
869             * buffer. This is faster than repeated copying back and forth
870             * between buffers.
871             */
872
873            namePtr = buffPtr;
874            buffPtr = tempPtr;
875        }
876    }
877
878    name = Tcl_DStringValue(namePtr);
879    nameLen = Tcl_DStringLength(namePtr);
880    nsPtr->fullName = ckalloc((unsigned) (nameLen+1));
881    memcpy(nsPtr->fullName, name, (unsigned) nameLen + 1);
882
883    Tcl_DStringFree(&buffer1);
884    Tcl_DStringFree(&buffer2);
885
886    /*
887     * Return a pointer to the new namespace.
888     */
889
890    return (Tcl_Namespace *) nsPtr;
891}
892
893/*
894 *----------------------------------------------------------------------
895 *
896 * Tcl_DeleteNamespace --
897 *
898 *      Deletes a namespace and all of the commands, variables, and other
899 *      namespaces within it.
900 *
901 * Results:
902 *      None.
903 *
904 * Side effects:
905 *      When a namespace is deleted, it is automatically removed as a child of
906 *      its parent namespace. Also, all its commands, variables and child
907 *      namespaces are deleted.
908 *
909 *----------------------------------------------------------------------
910 */
911
912void
913Tcl_DeleteNamespace(
914    Tcl_Namespace *namespacePtr)/* Points to the namespace to delete. */
915{
916    register Namespace *nsPtr = (Namespace *) namespacePtr;
917    Interp *iPtr = (Interp *) nsPtr->interp;
918    Namespace *globalNsPtr = (Namespace *)
919            TclGetGlobalNamespace((Tcl_Interp *) iPtr);
920    Tcl_HashEntry *entryPtr;
921
922    /*
923     * If the namespace has associated ensemble commands, delete them first.
924     * This leaves the actual contents of the namespace alone (unless they are
925     * linked ensemble commands, of course). Note that this code is actually
926     * reentrant so command delete traces won't purturb things badly.
927     */
928
929    while (nsPtr->ensembles != NULL) {
930        EnsembleConfig *ensemblePtr = (EnsembleConfig *) nsPtr->ensembles;
931
932        /*
933         * Splice out and link to indicate that we've already been killed.
934         */
935
936        nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr->next;
937        ensemblePtr->next = ensemblePtr;
938        Tcl_DeleteCommandFromToken(nsPtr->interp, ensemblePtr->token);
939    }
940
941    /*
942     * If the namespace has a registered unknown handler (TIP 181), then free
943     * it here.
944     */
945
946    if (nsPtr->unknownHandlerPtr != NULL) {
947        Tcl_DecrRefCount(nsPtr->unknownHandlerPtr);
948        nsPtr->unknownHandlerPtr = NULL;
949    }
950
951    /*
952     * If the namespace is on the call frame stack, it is marked as "dying"
953     * (NS_DYING is OR'd into its flags): the namespace can't be looked up by
954     * name but its commands and variables are still usable by those active
955     * call frames. When all active call frames referring to the namespace
956     * have been popped from the Tcl stack, Tcl_PopCallFrame will call this
957     * function again to delete everything in the namespace. If no nsName
958     * objects refer to the namespace (i.e., if its refCount is zero), its
959     * commands and variables are deleted and the storage for its namespace
960     * structure is freed. Otherwise, if its refCount is nonzero, the
961     * namespace's commands and variables are deleted but the structure isn't
962     * freed. Instead, NS_DEAD is OR'd into the structure's flags to allow the
963     * namespace resolution code to recognize that the namespace is "deleted".
964     * The structure's storage is freed by FreeNsNameInternalRep when its
965     * refCount reaches 0.
966     */
967
968    if (nsPtr->activationCount - (nsPtr == globalNsPtr) > 0) {
969        nsPtr->flags |= NS_DYING;
970        if (nsPtr->parentPtr != NULL) {
971            entryPtr = Tcl_FindHashEntry(&nsPtr->parentPtr->childTable,
972                    nsPtr->name);
973            if (entryPtr != NULL) {
974                Tcl_DeleteHashEntry(entryPtr);
975            }
976        }
977        nsPtr->parentPtr = NULL;
978    } else if (!(nsPtr->flags & NS_KILLED)) {
979        /*
980         * Delete the namespace and everything in it. If this is the global
981         * namespace, then clear it but don't free its storage unless the
982         * interpreter is being torn down. Set the NS_KILLED flag to avoid
983         * recursive calls here - if the namespace is really in the process of
984         * being deleted, ignore any second call.
985         */
986
987        nsPtr->flags |= (NS_DYING|NS_KILLED);
988
989        TclTeardownNamespace(nsPtr);
990
991        if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) {
992            /*
993             * If this is the global namespace, then it may have residual
994             * "errorInfo" and "errorCode" variables for errors that occurred
995             * while it was being torn down. Try to clear the variable list
996             * one last time.
997             */
998
999            TclDeleteNamespaceVars(nsPtr);
1000
1001            Tcl_DeleteHashTable(&nsPtr->childTable);
1002            Tcl_DeleteHashTable(&nsPtr->cmdTable);
1003
1004            /*
1005             * If the reference count is 0, then discard the namespace.
1006             * Otherwise, mark it as "dead" so that it can't be used.
1007             */
1008
1009            if (nsPtr->refCount == 0) {
1010                NamespaceFree(nsPtr);
1011            } else {
1012                nsPtr->flags |= NS_DEAD;
1013            }
1014        } else {
1015            /*
1016             * Restore the ::errorInfo and ::errorCode traces.
1017             */
1018
1019            EstablishErrorInfoTraces(NULL, nsPtr->interp, NULL, NULL, 0);
1020            EstablishErrorCodeTraces(NULL, nsPtr->interp, NULL, NULL, 0);
1021
1022            /*
1023             * We didn't really kill it, so remove the KILLED marks, so it can
1024             * get killed later, avoiding mem leaks.
1025             */
1026
1027            nsPtr->flags &= ~(NS_DYING|NS_KILLED);
1028        }
1029    }
1030}
1031
1032/*
1033 *----------------------------------------------------------------------
1034 *
1035 * TclTeardownNamespace --
1036 *
1037 *      Used internally to dismantle and unlink a namespace when it is
1038 *      deleted. Divorces the namespace from its parent, and deletes all
1039 *      commands, variables, and child namespaces.
1040 *
1041 *      This is kept separate from Tcl_DeleteNamespace so that the global
1042 *      namespace can be handled specially.
1043 *
1044 * Results:
1045 *      None.
1046 *
1047 * Side effects:
1048 *      Removes this namespace from its parent's child namespace hashtable.
1049 *      Deletes all commands, variables and namespaces in this namespace.
1050 *
1051 *----------------------------------------------------------------------
1052 */
1053
1054void
1055TclTeardownNamespace(
1056    register Namespace *nsPtr)  /* Points to the namespace to be dismantled
1057                                 * and unlinked from its parent. */
1058{
1059    Interp *iPtr = (Interp *) nsPtr->interp;
1060    register Tcl_HashEntry *entryPtr;
1061    Tcl_HashSearch search;
1062    Tcl_Namespace *childNsPtr;
1063    Tcl_Command cmd;
1064    int i;
1065
1066    /*
1067     * Start by destroying the namespace's variable table, since variables
1068     * might trigger traces. Variable table should be cleared but not freed!
1069     * TclDeleteNamespaceVars frees it, so we reinitialize it afterwards.
1070     */
1071
1072    TclDeleteNamespaceVars(nsPtr);
1073    TclInitVarHashTable(&nsPtr->varTable, nsPtr);
1074
1075    /*
1076     * Delete all commands in this namespace. Be careful when traversing the
1077     * hash table: when each command is deleted, it removes itself from the
1078     * command table.
1079     *
1080     * Don't optimize to Tcl_NextHashEntry() because of traces.
1081     */
1082
1083    for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
1084            entryPtr != NULL;
1085            entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search)) {
1086        cmd = Tcl_GetHashValue(entryPtr);
1087        Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr, cmd);
1088    }
1089    Tcl_DeleteHashTable(&nsPtr->cmdTable);
1090    Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS);
1091
1092    /*
1093     * Remove the namespace from its parent's child hashtable.
1094     */
1095
1096    if (nsPtr->parentPtr != NULL) {
1097        entryPtr = Tcl_FindHashEntry(&nsPtr->parentPtr->childTable,
1098                nsPtr->name);
1099        if (entryPtr != NULL) {
1100            Tcl_DeleteHashEntry(entryPtr);
1101        }
1102    }
1103    nsPtr->parentPtr = NULL;
1104
1105    /*
1106     * Delete the namespace path if one is installed.
1107     */
1108
1109    if (nsPtr->commandPathLength != 0) {
1110        UnlinkNsPath(nsPtr);
1111        nsPtr->commandPathLength = 0;
1112    }
1113    if (nsPtr->commandPathSourceList != NULL) {
1114        NamespacePathEntry *nsPathPtr = nsPtr->commandPathSourceList;
1115        do {
1116            if (nsPathPtr->nsPtr != NULL && nsPathPtr->creatorNsPtr != NULL) {
1117                nsPathPtr->creatorNsPtr->cmdRefEpoch++;
1118            }
1119            nsPathPtr->nsPtr = NULL;
1120            nsPathPtr = nsPathPtr->nextPtr;
1121        } while (nsPathPtr != NULL);
1122        nsPtr->commandPathSourceList = NULL;
1123    }
1124
1125    /*
1126     * Delete all the child namespaces.
1127     *
1128     * BE CAREFUL: When each child is deleted, it will divorce itself from its
1129     * parent. You can't traverse a hash table properly if its elements are
1130     * being deleted. We use only the Tcl_FirstHashEntry function to be safe.
1131     *
1132     * Don't optimize to Tcl_NextHashEntry() because of traces.
1133     */
1134
1135    for (entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
1136            entryPtr != NULL;
1137            entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search)) {
1138        childNsPtr = Tcl_GetHashValue(entryPtr);
1139        Tcl_DeleteNamespace(childNsPtr);
1140    }
1141
1142    /*
1143     * Free the namespace's export pattern array.
1144     */
1145
1146    if (nsPtr->exportArrayPtr != NULL) {
1147        for (i = 0;  i < nsPtr->numExportPatterns;  i++) {
1148            ckfree(nsPtr->exportArrayPtr[i]);
1149        }
1150        ckfree((char *) nsPtr->exportArrayPtr);
1151        nsPtr->exportArrayPtr = NULL;
1152        nsPtr->numExportPatterns = 0;
1153        nsPtr->maxExportPatterns = 0;
1154    }
1155
1156    /*
1157     * Free any client data associated with the namespace.
1158     */
1159
1160    if (nsPtr->deleteProc != NULL) {
1161        (*nsPtr->deleteProc)(nsPtr->clientData);
1162    }
1163    nsPtr->deleteProc = NULL;
1164    nsPtr->clientData = NULL;
1165
1166    /*
1167     * Reset the namespace's id field to ensure that this namespace won't be
1168     * interpreted as valid by, e.g., the cache validation code for cached
1169     * command references in Tcl_GetCommandFromObj.
1170     */
1171
1172    nsPtr->nsId = 0;
1173}
1174
1175/*
1176 *----------------------------------------------------------------------
1177 *
1178 * NamespaceFree --
1179 *
1180 *      Called after a namespace has been deleted, when its reference count
1181 *      reaches 0. Frees the data structure representing the namespace.
1182 *
1183 * Results:
1184 *      None.
1185 *
1186 * Side effects:
1187 *      None.
1188 *
1189 *----------------------------------------------------------------------
1190 */
1191
1192static void
1193NamespaceFree(
1194    register Namespace *nsPtr)  /* Points to the namespace to free. */
1195{
1196    /*
1197     * Most of the namespace's contents are freed when the namespace is
1198     * deleted by Tcl_DeleteNamespace. All that remains is to free its names
1199     * (for error messages), and the structure itself.
1200     */
1201
1202    ckfree(nsPtr->name);
1203    ckfree(nsPtr->fullName);
1204
1205    ckfree((char *) nsPtr);
1206}
1207
1208/*
1209 *----------------------------------------------------------------------
1210 *
1211 * Tcl_Export --
1212 *
1213 *      Makes all the commands matching a pattern available to later be
1214 *      imported from the namespace specified by namespacePtr (or the current
1215 *      namespace if namespacePtr is NULL). The specified pattern is appended
1216 *      onto the namespace's export pattern list, which is optionally cleared
1217 *      beforehand.
1218 *
1219 * Results:
1220 *      Returns TCL_OK if successful, or TCL_ERROR (along with an error
1221 *      message in the interpreter's result) if something goes wrong.
1222 *
1223 * Side effects:
1224 *      Appends the export pattern onto the namespace's export list.
1225 *      Optionally reset the namespace's export pattern list.
1226 *
1227 *----------------------------------------------------------------------
1228 */
1229
1230int
1231Tcl_Export(
1232    Tcl_Interp *interp,         /* Current interpreter. */
1233    Tcl_Namespace *namespacePtr,/* Points to the namespace from which commands
1234                                 * are to be exported. NULL for the current
1235                                 * namespace. */
1236    const char *pattern,        /* String pattern indicating which commands to
1237                                 * export. This pattern may not include any
1238                                 * namespace qualifiers; only commands in the
1239                                 * specified namespace may be exported. */
1240    int resetListFirst)         /* If nonzero, resets the namespace's export
1241                                 * list before appending. */
1242{
1243#define INIT_EXPORT_PATTERNS 5
1244    Namespace *nsPtr, *exportNsPtr, *dummyPtr;
1245    Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
1246    const char *simplePattern;
1247    char *patternCpy;
1248    int neededElems, len, i;
1249
1250    /*
1251     * If the specified namespace is NULL, use the current namespace.
1252     */
1253
1254    if (namespacePtr == NULL) {
1255        nsPtr = (Namespace *) currNsPtr;
1256    } else {
1257        nsPtr = (Namespace *) namespacePtr;
1258    }
1259
1260    /*
1261     * If resetListFirst is true (nonzero), clear the namespace's export
1262     * pattern list.
1263     */
1264
1265    if (resetListFirst) {
1266        if (nsPtr->exportArrayPtr != NULL) {
1267            for (i = 0;  i < nsPtr->numExportPatterns;  i++) {
1268                ckfree(nsPtr->exportArrayPtr[i]);
1269            }
1270            ckfree((char *) nsPtr->exportArrayPtr);
1271            nsPtr->exportArrayPtr = NULL;
1272            TclInvalidateNsCmdLookup(nsPtr);
1273            nsPtr->numExportPatterns = 0;
1274            nsPtr->maxExportPatterns = 0;
1275        }
1276    }
1277
1278    /*
1279     * Check that the pattern doesn't have namespace qualifiers.
1280     */
1281
1282    TclGetNamespaceForQualName(interp, pattern, nsPtr,
1283            /*flags*/ (TCL_LEAVE_ERR_MSG | TCL_NAMESPACE_ONLY),
1284            &exportNsPtr, &dummyPtr, &dummyPtr, &simplePattern);
1285
1286    if ((exportNsPtr != nsPtr) || (strcmp(pattern, simplePattern) != 0)) {
1287        Tcl_AppendResult(interp, "invalid export pattern \"", pattern,
1288                "\": pattern can't specify a namespace", NULL);
1289        return TCL_ERROR;
1290    }
1291
1292    /*
1293     * Make sure that we don't already have the pattern in the array
1294     */
1295
1296    if (nsPtr->exportArrayPtr != NULL) {
1297        for (i = 0;  i < nsPtr->numExportPatterns;  i++) {
1298            if (strcmp(pattern, nsPtr->exportArrayPtr[i]) == 0) {
1299                /*
1300                 * The pattern already exists in the list.
1301                 */
1302
1303                return TCL_OK;
1304            }
1305        }
1306    }
1307
1308    /*
1309     * Make sure there is room in the namespace's pattern array for the new
1310     * pattern.
1311     */
1312
1313    neededElems = nsPtr->numExportPatterns + 1;
1314    if (neededElems > nsPtr->maxExportPatterns) {
1315        nsPtr->maxExportPatterns = nsPtr->maxExportPatterns ?
1316                2 * nsPtr->maxExportPatterns : INIT_EXPORT_PATTERNS;
1317        nsPtr->exportArrayPtr = (char **)
1318                ckrealloc((char *) nsPtr->exportArrayPtr,
1319                sizeof(char *) * nsPtr->maxExportPatterns);
1320    }
1321
1322    /*
1323     * Add the pattern to the namespace's array of export patterns.
1324     */
1325
1326    len = strlen(pattern);
1327    patternCpy = ckalloc((unsigned) (len + 1));
1328    memcpy(patternCpy, pattern, (unsigned) len + 1);
1329
1330    nsPtr->exportArrayPtr[nsPtr->numExportPatterns] = patternCpy;
1331    nsPtr->numExportPatterns++;
1332
1333    /*
1334     * The list of commands actually exported from the namespace might have
1335     * changed (probably will have!) However, we do not need to recompute this
1336     * just yet; next time we need the info will be soon enough.
1337     */
1338
1339    TclInvalidateNsCmdLookup(nsPtr);
1340
1341    return TCL_OK;
1342#undef INIT_EXPORT_PATTERNS
1343}
1344
1345/*
1346 *----------------------------------------------------------------------
1347 *
1348 * Tcl_AppendExportList --
1349 *
1350 *      Appends onto the argument object the list of export patterns for the
1351 *      specified namespace.
1352 *
1353 * Results:
1354 *      The return value is normally TCL_OK; in this case the object
1355 *      referenced by objPtr has each export pattern appended to it. If an
1356 *      error occurs, TCL_ERROR is returned and the interpreter's result holds
1357 *      an error message.
1358 *
1359 * Side effects:
1360 *      If necessary, the object referenced by objPtr is converted into a list
1361 *      object.
1362 *
1363 *----------------------------------------------------------------------
1364 */
1365
1366int
1367Tcl_AppendExportList(
1368    Tcl_Interp *interp,         /* Interpreter used for error reporting. */
1369    Tcl_Namespace *namespacePtr,/* Points to the namespace whose export
1370                                 * pattern list is appended onto objPtr. NULL
1371                                 * for the current namespace. */
1372    Tcl_Obj *objPtr)            /* Points to the Tcl object onto which the
1373                                 * export pattern list is appended. */
1374{
1375    Namespace *nsPtr;
1376    int i, result;
1377
1378    /*
1379     * If the specified namespace is NULL, use the current namespace.
1380     */
1381
1382    if (namespacePtr == NULL) {
1383        nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
1384    } else {
1385        nsPtr = (Namespace *) namespacePtr;
1386    }
1387
1388    /*
1389     * Append the export pattern list onto objPtr.
1390     */
1391
1392    for (i = 0;  i < nsPtr->numExportPatterns;  i++) {
1393        result = Tcl_ListObjAppendElement(interp, objPtr,
1394                Tcl_NewStringObj(nsPtr->exportArrayPtr[i], -1));
1395        if (result != TCL_OK) {
1396            return result;
1397        }
1398    }
1399    return TCL_OK;
1400}
1401
1402/*
1403 *----------------------------------------------------------------------
1404 *
1405 * Tcl_Import --
1406 *
1407 *      Imports all of the commands matching a pattern into the namespace
1408 *      specified by namespacePtr (or the current namespace if contextNsPtr is
1409 *      NULL). This is done by creating a new command (the "imported command")
1410 *      that points to the real command in its original namespace.
1411 *
1412 *      If matching commands are on the autoload path but haven't been loaded
1413 *      yet, this command forces them to be loaded, then creates the links to
1414 *      them.
1415 *
1416 * Results:
1417 *      Returns TCL_OK if successful, or TCL_ERROR (along with an error
1418 *      message in the interpreter's result) if something goes wrong.
1419 *
1420 * Side effects:
1421 *      Creates new commands in the importing namespace. These indirect calls
1422 *      back to the real command and are deleted if the real commands are
1423 *      deleted.
1424 *
1425 *----------------------------------------------------------------------
1426 */
1427
1428int
1429Tcl_Import(
1430    Tcl_Interp *interp,         /* Current interpreter. */
1431    Tcl_Namespace *namespacePtr,/* Points to the namespace into which the
1432                                 * commands are to be imported. NULL for the
1433                                 * current namespace. */
1434    const char *pattern,        /* String pattern indicating which commands to
1435                                 * import. This pattern should be qualified by
1436                                 * the name of the namespace from which to
1437                                 * import the command(s). */
1438    int allowOverwrite)         /* If nonzero, allow existing commands to be
1439                                 * overwritten by imported commands. If 0,
1440                                 * return an error if an imported cmd
1441                                 * conflicts with an existing one. */
1442{
1443    Namespace *nsPtr, *importNsPtr, *dummyPtr;
1444    const char *simplePattern;
1445    register Tcl_HashEntry *hPtr;
1446    Tcl_HashSearch search;
1447
1448    /*
1449     * If the specified namespace is NULL, use the current namespace.
1450     */
1451
1452    if (namespacePtr == NULL) {
1453        nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
1454    } else {
1455        nsPtr = (Namespace *) namespacePtr;
1456    }
1457
1458    /*
1459     * First, invoke the "auto_import" command with the pattern being
1460     * imported. This command is part of the Tcl library. It looks for
1461     * imported commands in autoloaded libraries and loads them in. That way,
1462     * they will be found when we try to create links below.
1463     *
1464     * Note that we don't just call Tcl_EvalObjv() directly because we do not
1465     * want absence of the command to be a failure case.
1466     */
1467
1468    if (Tcl_FindCommand(interp,"auto_import",NULL,TCL_GLOBAL_ONLY) != NULL) {
1469        Tcl_Obj *objv[2];
1470        int result;
1471
1472        TclNewLiteralStringObj(objv[0], "auto_import");
1473        objv[1] = Tcl_NewStringObj(pattern, -1);
1474
1475        Tcl_IncrRefCount(objv[0]);
1476        Tcl_IncrRefCount(objv[1]);
1477        result = Tcl_EvalObjv(interp, 2, objv, TCL_GLOBAL_ONLY);
1478        Tcl_DecrRefCount(objv[0]);
1479        Tcl_DecrRefCount(objv[1]);
1480
1481        if (result != TCL_OK) {
1482            return TCL_ERROR;
1483        }
1484        Tcl_ResetResult(interp);
1485    }
1486
1487    /*
1488     * From the pattern, find the namespace from which we are importing and
1489     * get the simple pattern (no namespace qualifiers or ::'s) at the end.
1490     */
1491
1492    if (strlen(pattern) == 0) {
1493        Tcl_SetObjResult(interp, Tcl_NewStringObj("empty import pattern", -1));
1494        return TCL_ERROR;
1495    }
1496    TclGetNamespaceForQualName(interp, pattern, nsPtr,
1497            /*flags*/ (TCL_LEAVE_ERR_MSG | TCL_NAMESPACE_ONLY),
1498            &importNsPtr, &dummyPtr, &dummyPtr, &simplePattern);
1499
1500    if (importNsPtr == NULL) {
1501        Tcl_AppendResult(interp, "unknown namespace in import pattern \"",
1502                pattern, "\"", NULL);
1503        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", pattern, NULL);
1504        return TCL_ERROR;
1505    }
1506    if (importNsPtr == nsPtr) {
1507        if (pattern == simplePattern) {
1508            Tcl_AppendResult(interp,
1509                    "no namespace specified in import pattern \"", pattern,
1510                    "\"", NULL);
1511        } else {
1512            Tcl_AppendResult(interp, "import pattern \"", pattern,
1513                    "\" tries to import from namespace \"",
1514                    importNsPtr->name, "\" into itself", NULL);
1515        }
1516        return TCL_ERROR;
1517    }
1518
1519    /*
1520     * Scan through the command table in the source namespace and look for
1521     * exported commands that match the string pattern. Create an "imported
1522     * command" in the current namespace for each imported command; these
1523     * commands redirect their invocations to the "real" command.
1524     */
1525
1526    if ((simplePattern != NULL) && TclMatchIsTrivial(simplePattern)) {
1527        hPtr = Tcl_FindHashEntry(&importNsPtr->cmdTable, simplePattern);
1528        if (hPtr == NULL) {
1529            return TCL_OK;
1530        }
1531        return DoImport(interp, nsPtr, hPtr, simplePattern, pattern,
1532                importNsPtr, allowOverwrite);
1533    }
1534    for (hPtr = Tcl_FirstHashEntry(&importNsPtr->cmdTable, &search);
1535            (hPtr != NULL); hPtr = Tcl_NextHashEntry(&search)) {
1536        char *cmdName = Tcl_GetHashKey(&importNsPtr->cmdTable, hPtr);
1537        if (Tcl_StringMatch(cmdName, simplePattern) &&
1538                DoImport(interp, nsPtr, hPtr, cmdName, pattern, importNsPtr,
1539                allowOverwrite) == TCL_ERROR) {
1540            return TCL_ERROR;
1541        }
1542    }
1543    return TCL_OK;
1544}
1545
1546/*
1547 *----------------------------------------------------------------------
1548 *
1549 * DoImport --
1550 *
1551 *      Import a particular command from one namespace into another. Helper
1552 *      for Tcl_Import().
1553 *
1554 * Results:
1555 *      Standard Tcl result code. If TCL_ERROR, appends an error message to
1556 *      the interpreter result.
1557 *
1558 * Side effects:
1559 *      A new command is created in the target namespace unless this is a
1560 *      reimport of exactly the same command as before.
1561 *
1562 *----------------------------------------------------------------------
1563 */
1564
1565static int
1566DoImport(
1567    Tcl_Interp *interp,
1568    Namespace *nsPtr,
1569    Tcl_HashEntry *hPtr,
1570    const char *cmdName,
1571    const char *pattern,
1572    Namespace *importNsPtr,
1573    int allowOverwrite)
1574{
1575    int i = 0, exported = 0;
1576    Tcl_HashEntry *found;
1577
1578    /*
1579     * The command cmdName in the source namespace matches the pattern. Check
1580     * whether it was exported. If it wasn't, we ignore it.
1581     */
1582
1583    while (!exported && (i < importNsPtr->numExportPatterns)) {
1584        exported |= Tcl_StringMatch(cmdName, importNsPtr->exportArrayPtr[i++]);
1585    }
1586    if (!exported) {
1587        return TCL_OK;
1588    }
1589
1590    /*
1591     * Unless there is a name clash, create an imported command in the current
1592     * namespace that refers to cmdPtr.
1593     */
1594
1595    found = Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName);
1596    if ((found == NULL) || allowOverwrite) {
1597        /*
1598         * Create the imported command and its client data. To create the new
1599         * command in the current namespace, generate a fully qualified name
1600         * for it.
1601         */
1602
1603        Tcl_DString ds;
1604        Tcl_Command importedCmd;
1605        ImportedCmdData *dataPtr;
1606        Command *cmdPtr;
1607        ImportRef *refPtr;
1608
1609        Tcl_DStringInit(&ds);
1610        Tcl_DStringAppend(&ds, nsPtr->fullName, -1);
1611        if (nsPtr != ((Interp *) interp)->globalNsPtr) {
1612            Tcl_DStringAppend(&ds, "::", 2);
1613        }
1614        Tcl_DStringAppend(&ds, cmdName, -1);
1615
1616        /*
1617         * Check whether creating the new imported command in the current
1618         * namespace would create a cycle of imported command references.
1619         */
1620
1621        cmdPtr = Tcl_GetHashValue(hPtr);
1622        if (found != NULL && cmdPtr->deleteProc == DeleteImportedCmd) {
1623            Command *overwrite = Tcl_GetHashValue(found);
1624            Command *link = cmdPtr;
1625
1626            while (link->deleteProc == DeleteImportedCmd) {
1627                ImportedCmdData *dataPtr = link->objClientData;
1628
1629                link = dataPtr->realCmdPtr;
1630                if (overwrite == link) {
1631                    Tcl_AppendResult(interp, "import pattern \"", pattern,
1632                            "\" would create a loop containing command \"",
1633                            Tcl_DStringValue(&ds), "\"", NULL);
1634                    Tcl_DStringFree(&ds);
1635                    return TCL_ERROR;
1636                }
1637            }
1638        }
1639
1640        dataPtr = (ImportedCmdData *) ckalloc(sizeof(ImportedCmdData));
1641        importedCmd = Tcl_CreateObjCommand(interp, Tcl_DStringValue(&ds),
1642                InvokeImportedCmd, dataPtr, DeleteImportedCmd);
1643        dataPtr->realCmdPtr = cmdPtr;
1644        dataPtr->selfPtr = (Command *) importedCmd;
1645        dataPtr->selfPtr->compileProc = cmdPtr->compileProc;
1646        Tcl_DStringFree(&ds);
1647
1648        /*
1649         * Create an ImportRef structure describing this new import command
1650         * and add it to the import ref list in the "real" command.
1651         */
1652
1653        refPtr = (ImportRef *) ckalloc(sizeof(ImportRef));
1654        refPtr->importedCmdPtr = (Command *) importedCmd;
1655        refPtr->nextPtr = cmdPtr->importRefPtr;
1656        cmdPtr->importRefPtr = refPtr;
1657    } else {
1658        Command *overwrite = Tcl_GetHashValue(found);
1659
1660        if (overwrite->deleteProc == DeleteImportedCmd) {
1661            ImportedCmdData *dataPtr = overwrite->objClientData;
1662
1663            if (dataPtr->realCmdPtr == Tcl_GetHashValue(hPtr)) {
1664                /*
1665                 * Repeated import of same command is acceptable.
1666                 */
1667
1668                return TCL_OK;
1669            }
1670        }
1671        Tcl_AppendResult(interp, "can't import command \"", cmdName,
1672                "\": already exists", NULL);
1673        return TCL_ERROR;
1674    }
1675    return TCL_OK;
1676}
1677
1678/*
1679 *----------------------------------------------------------------------
1680 *
1681 * Tcl_ForgetImport --
1682 *
1683 *      Deletes commands previously imported into the namespace indicated.
1684 *      The by namespacePtr, or the current namespace of interp, when
1685 *      namespacePtr is NULL. The pattern controls which imported commands are
1686 *      deleted. A simple pattern, one without namespace separators, matches
1687 *      the current command names of imported commands in the namespace.
1688 *      Matching imported commands are deleted. A qualified pattern is
1689 *      interpreted as deletion selection on the basis of where the command is
1690 *      imported from. The original command and "first link" command for each
1691 *      imported command are determined, and they are matched against the
1692 *      pattern. A match leads to deletion of the imported command.
1693 *
1694 * Results:
1695 *      Returns TCL_ERROR and records an error message in the interp result if
1696 *      a namespace qualified pattern refers to a namespace that does not
1697 *      exist. Otherwise, returns TCL_OK.
1698 *
1699 * Side effects:
1700 *      May delete commands.
1701 *
1702 *----------------------------------------------------------------------
1703 */
1704
1705int
1706Tcl_ForgetImport(
1707    Tcl_Interp *interp,         /* Current interpreter. */
1708    Tcl_Namespace *namespacePtr,/* Points to the namespace from which
1709                                 * previously imported commands should be
1710                                 * removed. NULL for current namespace. */
1711    const char *pattern)        /* String pattern indicating which imported
1712                                 * commands to remove. */
1713{
1714    Namespace *nsPtr, *sourceNsPtr, *dummyPtr;
1715    const char *simplePattern;
1716    char *cmdName;
1717    register Tcl_HashEntry *hPtr;
1718    Tcl_HashSearch search;
1719
1720    /*
1721     * If the specified namespace is NULL, use the current namespace.
1722     */
1723
1724    if (namespacePtr == NULL) {
1725        nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
1726    } else {
1727        nsPtr = (Namespace *) namespacePtr;
1728    }
1729
1730    /*
1731     * Parse the pattern into its namespace-qualification (if any) and the
1732     * simple pattern.
1733     */
1734
1735    TclGetNamespaceForQualName(interp, pattern, nsPtr,
1736            /*flags*/ (TCL_LEAVE_ERR_MSG | TCL_NAMESPACE_ONLY),
1737            &sourceNsPtr, &dummyPtr, &dummyPtr, &simplePattern);
1738
1739    if (sourceNsPtr == NULL) {
1740        Tcl_AppendResult(interp,
1741                "unknown namespace in namespace forget pattern \"",
1742                pattern, "\"", NULL);
1743        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", pattern, NULL);
1744        return TCL_ERROR;
1745    }
1746
1747    if (strcmp(pattern, simplePattern) == 0) {
1748        /*
1749         * The pattern is simple. Delete any imported commands that match it.
1750         */
1751
1752        if (TclMatchIsTrivial(simplePattern)) {
1753            Command *cmdPtr;
1754
1755            hPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern);
1756            if ((hPtr != NULL)
1757                    && (cmdPtr = Tcl_GetHashValue(hPtr))
1758                    && (cmdPtr->deleteProc == DeleteImportedCmd)) {
1759                Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
1760            }
1761            return TCL_OK;
1762        }
1763        for (hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
1764                (hPtr != NULL); hPtr = Tcl_NextHashEntry(&search)) {
1765            Command *cmdPtr = Tcl_GetHashValue(hPtr);
1766
1767            if (cmdPtr->deleteProc != DeleteImportedCmd) {
1768                continue;
1769            }
1770            cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, hPtr);
1771            if (Tcl_StringMatch(cmdName, simplePattern)) {
1772                Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
1773            }
1774        }
1775        return TCL_OK;
1776    }
1777
1778    /*
1779     * The pattern was namespace-qualified.
1780     */
1781
1782    for (hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); (hPtr != NULL);
1783            hPtr = Tcl_NextHashEntry(&search)) {
1784        Tcl_CmdInfo info;
1785        Tcl_Command token = Tcl_GetHashValue(hPtr);
1786        Tcl_Command origin = TclGetOriginalCommand(token);
1787
1788        if (Tcl_GetCommandInfoFromToken(origin, &info) == 0) {
1789            continue;                   /* Not an imported command. */
1790        }
1791        if (info.namespacePtr != (Tcl_Namespace *) sourceNsPtr) {
1792            /*
1793             * Original not in namespace we're matching. Check the first link
1794             * in the import chain.
1795             */
1796
1797            Command *cmdPtr = (Command *) token;
1798            ImportedCmdData *dataPtr = cmdPtr->objClientData;
1799            Tcl_Command firstToken = (Tcl_Command) dataPtr->realCmdPtr;
1800
1801            if (firstToken == origin) {
1802                continue;
1803            }
1804            Tcl_GetCommandInfoFromToken(firstToken, &info);
1805            if (info.namespacePtr != (Tcl_Namespace *) sourceNsPtr) {
1806                continue;
1807            }
1808            origin = firstToken;
1809        }
1810        if (Tcl_StringMatch(Tcl_GetCommandName(NULL, origin), simplePattern)) {
1811            Tcl_DeleteCommandFromToken(interp, token);
1812        }
1813    }
1814    return TCL_OK;
1815}
1816
1817/*
1818 *----------------------------------------------------------------------
1819 *
1820 * TclGetOriginalCommand --
1821 *
1822 *      An imported command is created in an namespace when a "real" command
1823 *      is imported from another namespace. If the specified command is an
1824 *      imported command, this function returns the original command it refers
1825 *      to.
1826 *
1827 * Results:
1828 *      If the command was imported into a sequence of namespaces a, b,...,n
1829 *      where each successive namespace just imports the command from the
1830 *      previous namespace, this function returns the Tcl_Command token in the
1831 *      first namespace, a. Otherwise, if the specified command is not an
1832 *      imported command, the function returns NULL.
1833 *
1834 * Side effects:
1835 *      None.
1836 *
1837 *----------------------------------------------------------------------
1838 */
1839
1840Tcl_Command
1841TclGetOriginalCommand(
1842    Tcl_Command command)        /* The imported command for which the original
1843                                 * command should be returned. */
1844{
1845    register Command *cmdPtr = (Command *) command;
1846    ImportedCmdData *dataPtr;
1847
1848    if (cmdPtr->deleteProc != DeleteImportedCmd) {
1849        return NULL;
1850    }
1851
1852    while (cmdPtr->deleteProc == DeleteImportedCmd) {
1853        dataPtr = cmdPtr->objClientData;
1854        cmdPtr = dataPtr->realCmdPtr;
1855    }
1856    return (Tcl_Command) cmdPtr;
1857}
1858
1859/*
1860 *----------------------------------------------------------------------
1861 *
1862 * InvokeImportedCmd --
1863 *
1864 *      Invoked by Tcl whenever the user calls an imported command that was
1865 *      created by Tcl_Import. Finds the "real" command (in another
1866 *      namespace), and passes control to it.
1867 *
1868 * Results:
1869 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
1870 *
1871 * Side effects:
1872 *      Returns a result in the interpreter's result object. If anything goes
1873 *      wrong, the result object is set to an error message.
1874 *
1875 *----------------------------------------------------------------------
1876 */
1877
1878static int
1879InvokeImportedCmd(
1880    ClientData clientData,      /* Points to the imported command's
1881                                 * ImportedCmdData structure. */
1882    Tcl_Interp *interp,         /* Current interpreter. */
1883    int objc,                   /* Number of arguments. */
1884    Tcl_Obj *const objv[])      /* The argument objects. */
1885{
1886    register ImportedCmdData *dataPtr = clientData;
1887    register Command *realCmdPtr = dataPtr->realCmdPtr;
1888
1889    return (*realCmdPtr->objProc)(realCmdPtr->objClientData, interp,
1890            objc, objv);
1891}
1892
1893/*
1894 *----------------------------------------------------------------------
1895 *
1896 * DeleteImportedCmd --
1897 *
1898 *      Invoked by Tcl whenever an imported command is deleted. The "real"
1899 *      command keeps a list of all the imported commands that refer to it, so
1900 *      those imported commands can be deleted when the real command is
1901 *      deleted. This function removes the imported command reference from the
1902 *      real command's list, and frees up the memory associated with the
1903 *      imported command.
1904 *
1905 * Results:
1906 *      None.
1907 *
1908 * Side effects:
1909 *      Removes the imported command from the real command's import list.
1910 *
1911 *----------------------------------------------------------------------
1912 */
1913
1914static void
1915DeleteImportedCmd(
1916    ClientData clientData)      /* Points to the imported command's
1917                                 * ImportedCmdData structure. */
1918{
1919    ImportedCmdData *dataPtr = clientData;
1920    Command *realCmdPtr = dataPtr->realCmdPtr;
1921    Command *selfPtr = dataPtr->selfPtr;
1922    register ImportRef *refPtr, *prevPtr;
1923
1924    prevPtr = NULL;
1925    for (refPtr = realCmdPtr->importRefPtr; refPtr != NULL;
1926            refPtr = refPtr->nextPtr) {
1927        if (refPtr->importedCmdPtr == selfPtr) {
1928            /*
1929             * Remove *refPtr from real command's list of imported commands
1930             * that refer to it.
1931             */
1932
1933            if (prevPtr == NULL) { /* refPtr is first in list. */
1934                realCmdPtr->importRefPtr = refPtr->nextPtr;
1935            } else {
1936                prevPtr->nextPtr = refPtr->nextPtr;
1937            }
1938            ckfree((char *) refPtr);
1939            ckfree((char *) dataPtr);
1940            return;
1941        }
1942        prevPtr = refPtr;
1943    }
1944
1945    Tcl_Panic("DeleteImportedCmd: did not find cmd in real cmd's list of import references");
1946}
1947
1948/*
1949 *----------------------------------------------------------------------
1950 *
1951 * TclGetNamespaceForQualName --
1952 *
1953 *      Given a qualified name specifying a command, variable, or namespace,
1954 *      and a namespace in which to resolve the name, this function returns a
1955 *      pointer to the namespace that contains the item. A qualified name
1956 *      consists of the "simple" name of an item qualified by the names of an
1957 *      arbitrary number of containing namespace separated by "::"s. If the
1958 *      qualified name starts with "::", it is interpreted absolutely from the
1959 *      global namespace. Otherwise, it is interpreted relative to the
1960 *      namespace specified by cxtNsPtr if it is non-NULL. If cxtNsPtr is
1961 *      NULL, the name is interpreted relative to the current namespace.
1962 *
1963 *      A relative name like "foo::bar::x" can be found starting in either the
1964 *      current namespace or in the global namespace. So each search usually
1965 *      follows two tracks, and two possible namespaces are returned. If the
1966 *      function sets either *nsPtrPtr or *altNsPtrPtr to NULL, then that path
1967 *      failed.
1968 *
1969 *      If "flags" contains TCL_GLOBAL_ONLY, the relative qualified name is
1970 *      sought only in the global :: namespace. The alternate search (also)
1971 *      starting from the global namespace is ignored and *altNsPtrPtr is set
1972 *      NULL.
1973 *
1974 *      If "flags" contains TCL_NAMESPACE_ONLY, the relative qualified name is
1975 *      sought only in the namespace specified by cxtNsPtr. The alternate
1976 *      search starting from the global namespace is ignored and *altNsPtrPtr
1977 *      is set NULL. If both TCL_GLOBAL_ONLY and TCL_NAMESPACE_ONLY are
1978 *      specified, TCL_GLOBAL_ONLY is ignored and the search starts from the
1979 *      namespace specified by cxtNsPtr.
1980 *
1981 *      If "flags" contains TCL_CREATE_NS_IF_UNKNOWN, all namespace components
1982 *      of the qualified name that cannot be found are automatically created
1983 *      within their specified parent. This makes sure that functions like
1984 *      Tcl_CreateCommand always succeed. There is no alternate search path,
1985 *      so *altNsPtrPtr is set NULL.
1986 *
1987 *      If "flags" contains TCL_FIND_ONLY_NS, the qualified name is treated as
1988 *      a reference to a namespace, and the entire qualified name is followed.
1989 *      If the name is relative, the namespace is looked up only in the
1990 *      current namespace. A pointer to the namespace is stored in *nsPtrPtr
1991 *      and NULL is stored in *simpleNamePtr. Otherwise, if TCL_FIND_ONLY_NS
1992 *      is not specified, only the leading components are treated as namespace
1993 *      names, and a pointer to the simple name of the final component is
1994 *      stored in *simpleNamePtr.
1995 *
1996 * Results:
1997 *      It sets *nsPtrPtr and *altNsPtrPtr to point to the two possible
1998 *      namespaces which represent the last (containing) namespace in the
1999 *      qualified name. If the function sets either *nsPtrPtr or *altNsPtrPtr
2000 *      to NULL, then the search along that path failed. The function also
2001 *      stores a pointer to the simple name of the final component in
2002 *      *simpleNamePtr. If the qualified name is "::" or was treated as a
2003 *      namespace reference (TCL_FIND_ONLY_NS), the function stores a pointer
2004 *      to the namespace in *nsPtrPtr, NULL in *altNsPtrPtr, and sets
2005 *      *simpleNamePtr to point to an empty string.
2006 *
2007 *      If there is an error, this function returns TCL_ERROR. If "flags"
2008 *      contains TCL_LEAVE_ERR_MSG, an error message is returned in the
2009 *      interpreter's result object. Otherwise, the interpreter's result
2010 *      object is left unchanged.
2011 *
2012 *      *actualCxtPtrPtr is set to the actual context namespace. It is set to
2013 *      the input context namespace pointer in cxtNsPtr. If cxtNsPtr is NULL,
2014 *      it is set to the current namespace context.
2015 *
2016 *      For backwards compatibility with the TclPro byte code loader, this
2017 *      function always returns TCL_OK.
2018 *
2019 * Side effects:
2020 *      If "flags" contains TCL_CREATE_NS_IF_UNKNOWN, new namespaces may be
2021 *      created.
2022 *
2023 *----------------------------------------------------------------------
2024 */
2025
2026int
2027TclGetNamespaceForQualName(
2028    Tcl_Interp *interp,         /* Interpreter in which to find the namespace
2029                                 * containing qualName. */
2030    const char *qualName,       /* A namespace-qualified name of an command,
2031                                 * variable, or namespace. */
2032    Namespace *cxtNsPtr,        /* The namespace in which to start the search
2033                                 * for qualName's namespace. If NULL start
2034                                 * from the current namespace. Ignored if
2035                                 * TCL_GLOBAL_ONLY is set. */
2036    int flags,                  /* Flags controlling the search: an OR'd
2037                                 * combination of TCL_GLOBAL_ONLY,
2038                                 * TCL_NAMESPACE_ONLY, TCL_FIND_ONLY_NS, and
2039                                 * TCL_CREATE_NS_IF_UNKNOWN. */
2040    Namespace **nsPtrPtr,       /* Address where function stores a pointer to
2041                                 * containing namespace if qualName is found
2042                                 * starting from *cxtNsPtr or, if
2043                                 * TCL_GLOBAL_ONLY is set, if qualName is
2044                                 * found in the global :: namespace. NULL is
2045                                 * stored otherwise. */
2046    Namespace **altNsPtrPtr,    /* Address where function stores a pointer to
2047                                 * containing namespace if qualName is found
2048                                 * starting from the global :: namespace.
2049                                 * NULL is stored if qualName isn't found
2050                                 * starting from :: or if the TCL_GLOBAL_ONLY,
2051                                 * TCL_NAMESPACE_ONLY, TCL_FIND_ONLY_NS,
2052                                 * TCL_CREATE_NS_IF_UNKNOWN flag is set. */
2053    Namespace **actualCxtPtrPtr,/* Address where function stores a pointer to
2054                                 * the actual namespace from which the search
2055                                 * started. This is either cxtNsPtr, the ::
2056                                 * namespace if TCL_GLOBAL_ONLY was specified,
2057                                 * or the current namespace if cxtNsPtr was
2058                                 * NULL. */
2059    const char **simpleNamePtr) /* Address where function stores the simple
2060                                 * name at end of the qualName, or NULL if
2061                                 * qualName is "::" or the flag
2062                                 * TCL_FIND_ONLY_NS was specified. */
2063{
2064    Interp *iPtr = (Interp *) interp;
2065    Namespace *nsPtr = cxtNsPtr;
2066    Namespace *altNsPtr;
2067    Namespace *globalNsPtr = iPtr->globalNsPtr;
2068    const char *start, *end;
2069    const char *nsName;
2070    Tcl_HashEntry *entryPtr;
2071    Tcl_DString buffer;
2072    int len;
2073
2074    /*
2075     * Determine the context namespace nsPtr in which to start the primary
2076     * search. If the qualName name starts with a "::" or TCL_GLOBAL_ONLY was
2077     * specified, search from the global namespace. Otherwise, use the
2078     * namespace given in cxtNsPtr, or if that is NULL, use the current
2079     * namespace context. Note that we always treat two or more adjacent ":"s
2080     * as a namespace separator.
2081     */
2082
2083    if (flags & TCL_GLOBAL_ONLY) {
2084        nsPtr = globalNsPtr;
2085    } else if (nsPtr == NULL) {
2086        nsPtr = iPtr->varFramePtr->nsPtr;
2087    }
2088
2089    start = qualName;                   /* Points to start of qualifying
2090                                         * namespace. */
2091    if ((*qualName == ':') && (*(qualName+1) == ':')) {
2092        start = qualName+2;             /* Skip over the initial :: */
2093        while (*start == ':') {
2094            start++;                    /* Skip over a subsequent : */
2095        }
2096        nsPtr = globalNsPtr;
2097        if (*start == '\0') {           /* qualName is just two or more
2098                                         * ":"s. */
2099            *nsPtrPtr = globalNsPtr;
2100            *altNsPtrPtr = NULL;
2101            *actualCxtPtrPtr = globalNsPtr;
2102            *simpleNamePtr = start;     /* Points to empty string. */
2103            return TCL_OK;
2104        }
2105    }
2106    *actualCxtPtrPtr = nsPtr;
2107
2108    /*
2109     * Start an alternate search path starting with the global namespace.
2110     * However, if the starting context is the global namespace, or if the
2111     * flag is set to search only the namespace *cxtNsPtr, ignore the
2112     * alternate search path.
2113     */
2114
2115    altNsPtr = globalNsPtr;
2116    if ((nsPtr == globalNsPtr)
2117            || (flags & (TCL_NAMESPACE_ONLY | TCL_FIND_ONLY_NS))) {
2118        altNsPtr = NULL;
2119    }
2120
2121    /*
2122     * Loop to resolve each namespace qualifier in qualName.
2123     */
2124
2125    Tcl_DStringInit(&buffer);
2126    end = start;
2127    while (*start != '\0') {
2128        /*
2129         * Find the next namespace qualifier (i.e., a name ending in "::") or
2130         * the end of the qualified name (i.e., a name ending in "\0"). Set
2131         * len to the number of characters, starting from start, in the name;
2132         * set end to point after the "::"s or at the "\0".
2133         */
2134
2135        len = 0;
2136        for (end = start;  *end != '\0';  end++) {
2137            if ((*end == ':') && (*(end+1) == ':')) {
2138                end += 2;               /* Skip over the initial :: */
2139                while (*end == ':') {
2140                    end++;              /* Skip over the subsequent : */
2141                }
2142                break;                  /* Exit for loop; end is after ::'s */
2143            }
2144            len++;
2145        }
2146
2147        if (*end=='\0' && !(end-start>=2 && *(end-1)==':' && *(end-2)==':')) {
2148            /*
2149             * qualName ended with a simple name at start. If TCL_FIND_ONLY_NS
2150             * was specified, look this up as a namespace. Otherwise, start is
2151             * the name of a cmd or var and we are done.
2152             */
2153
2154            if (flags & TCL_FIND_ONLY_NS) {
2155                nsName = start;
2156            } else {
2157                *nsPtrPtr = nsPtr;
2158                *altNsPtrPtr = altNsPtr;
2159                *simpleNamePtr = start;
2160                Tcl_DStringFree(&buffer);
2161                return TCL_OK;
2162            }
2163        } else {
2164            /*
2165             * start points to the beginning of a namespace qualifier ending
2166             * in "::". end points to the start of a name in that namespace
2167             * that might be empty. Copy the namespace qualifier to a buffer
2168             * so it can be null terminated. We can't modify the incoming
2169             * qualName since it may be a string constant.
2170             */
2171
2172            Tcl_DStringSetLength(&buffer, 0);
2173            Tcl_DStringAppend(&buffer, start, len);
2174            nsName = Tcl_DStringValue(&buffer);
2175        }
2176
2177        /*
2178         * Look up the namespace qualifier nsName in the current namespace
2179         * context. If it isn't found but TCL_CREATE_NS_IF_UNKNOWN is set,
2180         * create that qualifying namespace. This is needed for functions like
2181         * Tcl_CreateCommand that cannot fail.
2182         */
2183
2184        if (nsPtr != NULL) {
2185            entryPtr = Tcl_FindHashEntry(&nsPtr->childTable, nsName);
2186            if (entryPtr != NULL) {
2187                nsPtr = Tcl_GetHashValue(entryPtr);
2188            } else if (flags & TCL_CREATE_NS_IF_UNKNOWN) {
2189                Tcl_CallFrame *framePtr;
2190
2191                (void) TclPushStackFrame(interp, &framePtr,
2192                        (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 0);
2193
2194                nsPtr = (Namespace *) Tcl_CreateNamespace(interp, nsName,
2195                        NULL, NULL);
2196                TclPopStackFrame(interp);
2197
2198                if (nsPtr == NULL) {
2199                    Tcl_Panic("Could not create namespace '%s'", nsName);
2200                }
2201            } else {                    /* Namespace not found and was not
2202                                         * created. */
2203                nsPtr = NULL;
2204            }
2205        }
2206
2207        /*
2208         * Look up the namespace qualifier in the alternate search path too.
2209         */
2210
2211        if (altNsPtr != NULL) {
2212            entryPtr = Tcl_FindHashEntry(&altNsPtr->childTable, nsName);
2213            if (entryPtr != NULL) {
2214                altNsPtr = Tcl_GetHashValue(entryPtr);
2215            } else {
2216                altNsPtr = NULL;
2217            }
2218        }
2219
2220        /*
2221         * If both search paths have failed, return NULL results.
2222         */
2223
2224        if ((nsPtr == NULL) && (altNsPtr == NULL)) {
2225            *nsPtrPtr = NULL;
2226            *altNsPtrPtr = NULL;
2227            *simpleNamePtr = NULL;
2228            Tcl_DStringFree(&buffer);
2229            return TCL_OK;
2230        }
2231
2232        start = end;
2233    }
2234
2235    /*
2236     * We ignore trailing "::"s in a namespace name, but in a command or
2237     * variable name, trailing "::"s refer to the cmd or var named {}.
2238     */
2239
2240    if ((flags & TCL_FIND_ONLY_NS) || (end>start && *(end-1)!=':')) {
2241        *simpleNamePtr = NULL;          /* Found namespace name. */
2242    } else {
2243        *simpleNamePtr = end;           /* Found cmd/var: points to empty
2244                                         * string. */
2245    }
2246
2247    /*
2248     * As a special case, if we are looking for a namespace and qualName is ""
2249     * and the current active namespace (nsPtr) is not the global namespace,
2250     * return NULL (no namespace was found). This is because namespaces can
2251     * not have empty names except for the global namespace.
2252     */
2253
2254    if ((flags & TCL_FIND_ONLY_NS) && (*qualName == '\0')
2255            && (nsPtr != globalNsPtr)) {
2256        nsPtr = NULL;
2257    }
2258
2259    *nsPtrPtr = nsPtr;
2260    *altNsPtrPtr = altNsPtr;
2261    Tcl_DStringFree(&buffer);
2262    return TCL_OK;
2263}
2264
2265/*
2266 *----------------------------------------------------------------------
2267 *
2268 * Tcl_FindNamespace --
2269 *
2270 *      Searches for a namespace.
2271 *
2272 * Results:
2273 *      Returns a pointer to the namespace if it is found. Otherwise, returns
2274 *      NULL and leaves an error message in the interpreter's result object if
2275 *      "flags" contains TCL_LEAVE_ERR_MSG.
2276 *
2277 * Side effects:
2278 *      None.
2279 *
2280 *----------------------------------------------------------------------
2281 */
2282
2283Tcl_Namespace *
2284Tcl_FindNamespace(
2285    Tcl_Interp *interp,         /* The interpreter in which to find the
2286                                 * namespace. */
2287    const char *name,           /* Namespace name. If it starts with "::",
2288                                 * will be looked up in global namespace.
2289                                 * Else, looked up first in contextNsPtr
2290                                 * (current namespace if contextNsPtr is
2291                                 * NULL), then in global namespace. */
2292    Tcl_Namespace *contextNsPtr,/* Ignored if TCL_GLOBAL_ONLY flag is set or
2293                                 * if the name starts with "::". Otherwise,
2294                                 * points to namespace in which to resolve
2295                                 * name; if NULL, look up name in the current
2296                                 * namespace. */
2297    register int flags)         /* Flags controlling namespace lookup: an OR'd
2298                                 * combination of TCL_GLOBAL_ONLY and
2299                                 * TCL_LEAVE_ERR_MSG flags. */
2300{
2301    Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr;
2302    const char *dummy;
2303
2304    /*
2305     * Find the namespace(s) that contain the specified namespace name. Add
2306     * the TCL_FIND_ONLY_NS flag to resolve the name all the way down to its
2307     * last component, a namespace.
2308     */
2309
2310    TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
2311            flags|TCL_FIND_ONLY_NS, &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
2312
2313    if (nsPtr != NULL) {
2314        return (Tcl_Namespace *) nsPtr;
2315    } else if (flags & TCL_LEAVE_ERR_MSG) {
2316        Tcl_ResetResult(interp);
2317        Tcl_AppendResult(interp, "unknown namespace \"", name, "\"", NULL);
2318        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, NULL);
2319    }
2320    return NULL;
2321}
2322
2323/*
2324 *----------------------------------------------------------------------
2325 *
2326 * Tcl_FindCommand --
2327 *
2328 *      Searches for a command.
2329 *
2330 * Results:
2331 *      Returns a token for the command if it is found. Otherwise, if it can't
2332 *      be found or there is an error, returns NULL and leaves an error
2333 *      message in the interpreter's result object if "flags" contains
2334 *      TCL_LEAVE_ERR_MSG.
2335 *
2336 * Side effects:
2337 *      None.
2338 *
2339 *----------------------------------------------------------------------
2340 */
2341
2342Tcl_Command
2343Tcl_FindCommand(
2344    Tcl_Interp *interp,         /* The interpreter in which to find the
2345                                 * command and to report errors. */
2346    const char *name,           /* Command's name. If it starts with "::",
2347                                 * will be looked up in global namespace.
2348                                 * Else, looked up first in contextNsPtr
2349                                 * (current namespace if contextNsPtr is
2350                                 * NULL), then in global namespace. */
2351    Tcl_Namespace *contextNsPtr,/* Ignored if TCL_GLOBAL_ONLY flag set.
2352                                 * Otherwise, points to namespace in which to
2353                                 * resolve name. If NULL, look up name in the
2354                                 * current namespace. */
2355    int flags)                  /* An OR'd combination of flags:
2356                                 * TCL_GLOBAL_ONLY (look up name only in
2357                                 * global namespace), TCL_NAMESPACE_ONLY (look
2358                                 * up only in contextNsPtr, or the current
2359                                 * namespace if contextNsPtr is NULL), and
2360                                 * TCL_LEAVE_ERR_MSG. If both TCL_GLOBAL_ONLY
2361                                 * and TCL_NAMESPACE_ONLY are given,
2362                                 * TCL_GLOBAL_ONLY is ignored. */
2363{
2364    Interp *iPtr = (Interp *) interp;
2365    Namespace *cxtNsPtr;
2366    register Tcl_HashEntry *entryPtr;
2367    register Command *cmdPtr;
2368    const char *simpleName;
2369    int result;
2370
2371    /*
2372     * If this namespace has a command resolver, then give it first crack at
2373     * the command resolution. If the interpreter has any command resolvers,
2374     * consult them next. The command resolver functions may return a
2375     * Tcl_Command value, they may signal to continue onward, or they may
2376     * signal an error.
2377     */
2378
2379    if ((flags & TCL_GLOBAL_ONLY) || !strncmp(name, "::", 2)) {
2380        cxtNsPtr = (Namespace *) TclGetGlobalNamespace(interp);
2381    } else if (contextNsPtr != NULL) {
2382        cxtNsPtr = (Namespace *) contextNsPtr;
2383    } else {
2384        cxtNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
2385    }
2386
2387    if (cxtNsPtr->cmdResProc != NULL || iPtr->resolverPtr != NULL) {
2388        ResolverScheme *resPtr = iPtr->resolverPtr;
2389        Tcl_Command cmd;
2390
2391        if (cxtNsPtr->cmdResProc) {
2392            result = (*cxtNsPtr->cmdResProc)(interp, name,
2393                    (Tcl_Namespace *) cxtNsPtr, flags, &cmd);
2394        } else {
2395            result = TCL_CONTINUE;
2396        }
2397
2398        while (result == TCL_CONTINUE && resPtr) {
2399            if (resPtr->cmdResProc) {
2400                result = (*resPtr->cmdResProc)(interp, name,
2401                        (Tcl_Namespace *) cxtNsPtr, flags, &cmd);
2402            }
2403            resPtr = resPtr->nextPtr;
2404        }
2405
2406        if (result == TCL_OK) {
2407            return cmd;
2408        } else if (result != TCL_CONTINUE) {
2409            return NULL;
2410        }
2411    }
2412
2413    /*
2414     * Find the namespace(s) that contain the command.
2415     */
2416
2417    cmdPtr = NULL;
2418    if (cxtNsPtr->commandPathLength!=0 && strncmp(name, "::", 2)) {
2419        int i;
2420        Namespace *pathNsPtr, *realNsPtr, *dummyNsPtr;
2421
2422        (void) TclGetNamespaceForQualName(interp, name, cxtNsPtr,
2423                TCL_NAMESPACE_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
2424                &simpleName);
2425        if ((realNsPtr != NULL) && (simpleName != NULL)) {
2426            if ((cxtNsPtr == realNsPtr)
2427                    || !(realNsPtr->flags & NS_DYING)) {
2428                entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
2429                if (entryPtr != NULL) {
2430                    cmdPtr = Tcl_GetHashValue(entryPtr);
2431                }
2432            }
2433        }
2434
2435        /*
2436         * Next, check along the path.
2437         */
2438
2439        for (i=0 ; i<cxtNsPtr->commandPathLength && cmdPtr==NULL ; i++) {
2440            pathNsPtr = cxtNsPtr->commandPathArray[i].nsPtr;
2441            if (pathNsPtr == NULL) {
2442                continue;
2443            }
2444            (void) TclGetNamespaceForQualName(interp, name, pathNsPtr,
2445                    TCL_NAMESPACE_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
2446                    &simpleName);
2447            if ((realNsPtr != NULL) && (simpleName != NULL)
2448                    && !(realNsPtr->flags & NS_DYING)) {
2449                entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
2450                if (entryPtr != NULL) {
2451                    cmdPtr = Tcl_GetHashValue(entryPtr);
2452                }
2453            }
2454        }
2455
2456        /*
2457         * If we've still not found the command, look in the global namespace
2458         * as a last resort.
2459         */
2460
2461        if (cmdPtr == NULL) {
2462            (void) TclGetNamespaceForQualName(interp, name, NULL,
2463                    TCL_GLOBAL_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
2464                    &simpleName);
2465            if ((realNsPtr != NULL) && (simpleName != NULL)
2466                    && !(realNsPtr->flags & NS_DYING)) {
2467                entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
2468                if (entryPtr != NULL) {
2469                    cmdPtr = Tcl_GetHashValue(entryPtr);
2470                }
2471            }
2472        }
2473    } else {
2474        Namespace *nsPtr[2];
2475        register int search;
2476
2477        TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
2478                flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName);
2479
2480        /*
2481         * Look for the command in the command table of its namespace. Be sure
2482         * to check both possible search paths: from the specified namespace
2483         * context and from the global namespace.
2484         */
2485
2486        for (search = 0;  (search < 2) && (cmdPtr == NULL);  search++) {
2487            if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
2488                entryPtr = Tcl_FindHashEntry(&nsPtr[search]->cmdTable,
2489                        simpleName);
2490                if (entryPtr != NULL) {
2491                    cmdPtr = Tcl_GetHashValue(entryPtr);
2492                }
2493            }
2494        }
2495    }
2496
2497    if (cmdPtr != NULL) {
2498        return (Tcl_Command) cmdPtr;
2499    }
2500
2501    if (flags & TCL_LEAVE_ERR_MSG) {
2502        Tcl_ResetResult(interp);
2503        Tcl_AppendResult(interp, "unknown command \"", name, "\"", NULL);
2504        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", name, NULL);
2505    }
2506    return NULL;
2507}
2508
2509/*
2510 *----------------------------------------------------------------------
2511 *
2512 * TclResetShadowedCmdRefs --
2513 *
2514 *      Called when a command is added to a namespace to check for existing
2515 *      command references that the new command may invalidate. Consider the
2516 *      following cases that could happen when you add a command "foo" to a
2517 *      namespace "b":
2518 *         1. It could shadow a command named "foo" at the global scope. If
2519 *            it does, all command references in the namespace "b" are
2520 *            suspect.
2521 *         2. Suppose the namespace "b" resides in a namespace "a". Then to
2522 *            "a" the new command "b::foo" could shadow another command
2523 *            "b::foo" in the global namespace. If so, then all command
2524 *            references in "a" * are suspect.
2525 *      The same checks are applied to all parent namespaces, until we reach
2526 *      the global :: namespace.
2527 *
2528 * Results:
2529 *      None.
2530 *
2531 * Side effects:
2532 *      If the new command shadows an existing command, the cmdRefEpoch
2533 *      counter is incremented in each namespace that sees the shadow. This
2534 *      invalidates all command references that were previously cached in that
2535 *      namespace. The next time the commands are used, they are resolved from
2536 *      scratch.
2537 *
2538 *----------------------------------------------------------------------
2539 */
2540
2541void
2542TclResetShadowedCmdRefs(
2543    Tcl_Interp *interp,         /* Interpreter containing the new command. */
2544    Command *newCmdPtr)         /* Points to the new command. */
2545{
2546    char *cmdName;
2547    Tcl_HashEntry *hPtr;
2548    register Namespace *nsPtr;
2549    Namespace *trailNsPtr, *shadowNsPtr;
2550    Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace(interp);
2551    int found, i;
2552    int trailFront = -1;
2553    int trailSize = 5;          /* Formerly NUM_TRAIL_ELEMS. */
2554    Namespace **trailPtr = (Namespace **)
2555            TclStackAlloc(interp, trailSize * sizeof(Namespace *));
2556
2557    /*
2558     * Start at the namespace containing the new command, and work up through
2559     * the list of parents. Stop just before the global namespace, since the
2560     * global namespace can't "shadow" its own entries.
2561     *
2562     * The namespace "trail" list we build consists of the names of each
2563     * namespace that encloses the new command, in order from outermost to
2564     * innermost: for example, "a" then "b". Each iteration of this loop
2565     * eventually extends the trail upwards by one namespace, nsPtr. We use
2566     * this trail list to see if nsPtr (e.g. "a" in 2. above) could have
2567     * now-invalid cached command references. This will happen if nsPtr
2568     * (e.g. "a") contains a sequence of child namespaces (e.g. "b") such that
2569     * there is a identically-named sequence of child namespaces starting from
2570     * :: (e.g. "::b") whose tail namespace contains a command also named
2571     * cmdName.
2572     */
2573
2574    cmdName = Tcl_GetHashKey(newCmdPtr->hPtr->tablePtr, newCmdPtr->hPtr);
2575    for (nsPtr=newCmdPtr->nsPtr ; (nsPtr!=NULL) && (nsPtr!=globalNsPtr) ;
2576            nsPtr=nsPtr->parentPtr) {
2577        /*
2578         * Find the maximal sequence of child namespaces contained in nsPtr
2579         * such that there is a identically-named sequence of child namespaces
2580         * starting from ::. shadowNsPtr will be the tail of this sequence, or
2581         * the deepest namespace under :: that might contain a command now
2582         * shadowed by cmdName. We check below if shadowNsPtr actually
2583         * contains a command cmdName.
2584         */
2585
2586        found = 1;
2587        shadowNsPtr = globalNsPtr;
2588
2589        for (i = trailFront;  i >= 0;  i--) {
2590            trailNsPtr = trailPtr[i];
2591            hPtr = Tcl_FindHashEntry(&shadowNsPtr->childTable,
2592                    trailNsPtr->name);
2593            if (hPtr != NULL) {
2594                shadowNsPtr = Tcl_GetHashValue(hPtr);
2595            } else {
2596                found = 0;
2597                break;
2598            }
2599        }
2600
2601        /*
2602         * If shadowNsPtr contains a command named cmdName, we invalidate all
2603         * of the command refs cached in nsPtr. As a boundary case,
2604         * shadowNsPtr is initially :: and we check for case 1. above.
2605         */
2606
2607        if (found) {
2608            hPtr = Tcl_FindHashEntry(&shadowNsPtr->cmdTable, cmdName);
2609            if (hPtr != NULL) {
2610                nsPtr->cmdRefEpoch++;
2611                TclInvalidateNsPath(nsPtr);
2612
2613                /*
2614                 * If the shadowed command was compiled to bytecodes, we
2615                 * invalidate all the bytecodes in nsPtr, to force a new
2616                 * compilation. We use the resolverEpoch to signal the need
2617                 * for a fresh compilation of every bytecode.
2618                 */
2619
2620                if (((Command *)Tcl_GetHashValue(hPtr))->compileProc != NULL) {
2621                    nsPtr->resolverEpoch++;
2622                }
2623            }
2624        }
2625
2626        /*
2627         * Insert nsPtr at the front of the trail list: i.e., at the end of
2628         * the trailPtr array.
2629         */
2630
2631        trailFront++;
2632        if (trailFront == trailSize) {
2633            int newSize = 2 * trailSize;
2634            trailPtr = (Namespace **) TclStackRealloc(interp,
2635                    trailPtr, newSize * sizeof(Namespace *));
2636            trailSize = newSize;
2637        }
2638        trailPtr[trailFront] = nsPtr;
2639    }
2640    TclStackFree(interp, trailPtr);
2641}
2642
2643/*
2644 *----------------------------------------------------------------------
2645 *
2646 * TclGetNamespaceFromObj, GetNamespaceFromObj --
2647 *
2648 *      Gets the namespace specified by the name in a Tcl_Obj.
2649 *
2650 * Results:
2651 *      Returns TCL_OK if the namespace was resolved successfully, and stores
2652 *      a pointer to the namespace in the location specified by nsPtrPtr. If
2653 *      the namespace can't be found, or anything else goes wrong, this
2654 *      function returns TCL_ERROR and writes an error message to interp,
2655 *      if non-NULL.
2656 *
2657 * Side effects:
2658 *      May update the internal representation for the object, caching the
2659 *      namespace reference. The next time this function is called, the
2660 *      namespace value can be found quickly.
2661 *
2662 *----------------------------------------------------------------------
2663 */
2664
2665int
2666TclGetNamespaceFromObj(
2667    Tcl_Interp *interp,         /* The current interpreter. */
2668    Tcl_Obj *objPtr,            /* The object to be resolved as the name of a
2669                                 * namespace. */
2670    Tcl_Namespace **nsPtrPtr)   /* Result namespace pointer goes here. */
2671{
2672    if (GetNamespaceFromObj(interp, objPtr, nsPtrPtr) == TCL_ERROR) {
2673        const char *name = TclGetString(objPtr);
2674
2675        if ((name[0] == ':') && (name[1] == ':')) {
2676            Tcl_SetObjResult(interp, Tcl_ObjPrintf(
2677                    "namespace \"%s\" not found", name));
2678        } else {
2679            /*
2680             * Get the current namespace name.
2681             */
2682
2683            NamespaceCurrentCmd(NULL, interp, 2, NULL);
2684            Tcl_SetObjResult(interp, Tcl_ObjPrintf(
2685                    "namespace \"%s\" not found in \"%s\"", name,
2686                    Tcl_GetStringResult(interp)));
2687        }
2688        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, NULL);
2689        return TCL_ERROR;
2690    }
2691    return TCL_OK;
2692}
2693
2694static int
2695GetNamespaceFromObj(
2696    Tcl_Interp *interp,         /* The current interpreter. */
2697    Tcl_Obj *objPtr,            /* The object to be resolved as the name of a
2698                                 * namespace. */
2699    Tcl_Namespace **nsPtrPtr)   /* Result namespace pointer goes here. */
2700{
2701    ResolvedNsName *resNamePtr;
2702    Namespace *nsPtr, *refNsPtr;
2703
2704    if (objPtr->typePtr == &nsNameType) {
2705        /*
2706         * Check that the ResolvedNsName is still valid; avoid letting the ref
2707         * cross interps.
2708         */
2709
2710        resNamePtr = (ResolvedNsName *) objPtr->internalRep.twoPtrValue.ptr1;
2711        nsPtr = resNamePtr->nsPtr;
2712        refNsPtr = resNamePtr->refNsPtr;
2713        if (!(nsPtr->flags & NS_DYING) && (interp == nsPtr->interp) &&
2714                (!refNsPtr || ((interp == refNsPtr->interp) &&
2715                 (refNsPtr== (Namespace *) Tcl_GetCurrentNamespace(interp))))) {
2716            *nsPtrPtr = (Tcl_Namespace *) nsPtr;
2717            return TCL_OK;
2718        }
2719    }
2720    if (SetNsNameFromAny(interp, objPtr) == TCL_OK) {
2721        resNamePtr = (ResolvedNsName *) objPtr->internalRep.twoPtrValue.ptr1;
2722        *nsPtrPtr = (Tcl_Namespace *) resNamePtr->nsPtr;
2723        return TCL_OK;
2724    }
2725    return TCL_ERROR;
2726}
2727
2728/*
2729 *----------------------------------------------------------------------
2730 *
2731 * Tcl_NamespaceObjCmd --
2732 *
2733 *      Invoked to implement the "namespace" command that creates, deletes, or
2734 *      manipulates Tcl namespaces. Handles the following syntax:
2735 *
2736 *          namespace children ?name? ?pattern?
2737 *          namespace code arg
2738 *          namespace current
2739 *          namespace delete ?name name...?
2740 *          namespace ensemble subcommand ?arg...?
2741 *          namespace eval name arg ?arg...?
2742 *          namespace exists name
2743 *          namespace export ?-clear? ?pattern pattern...?
2744 *          namespace forget ?pattern pattern...?
2745 *          namespace import ?-force? ?pattern pattern...?
2746 *          namespace inscope name arg ?arg...?
2747 *          namespace origin name
2748 *          namespace parent ?name?
2749 *          namespace qualifiers string
2750 *          namespace tail string
2751 *          namespace which ?-command? ?-variable? name
2752 *
2753 * Results:
2754 *      Returns TCL_OK if the command is successful. Returns TCL_ERROR if
2755 *      anything goes wrong.
2756 *
2757 * Side effects:
2758 *      Based on the subcommand name (e.g., "import"), this function
2759 *      dispatches to a corresponding function NamespaceXXXCmd defined
2760 *      statically in this file. This function's side effects depend on
2761 *      whatever that subcommand function does. If there is an error, this
2762 *      function returns an error message in the interpreter's result object.
2763 *      Otherwise it may return a result in the interpreter's result object.
2764 *
2765 *----------------------------------------------------------------------
2766 */
2767
2768int
2769Tcl_NamespaceObjCmd(
2770    ClientData clientData,      /* Arbitrary value passed to cmd. */
2771    Tcl_Interp *interp,         /* Current interpreter. */
2772    int objc,                   /* Number of arguments. */
2773    Tcl_Obj *const objv[])      /* Argument objects. */
2774{
2775    static const char *subCmds[] = {
2776        "children", "code", "current", "delete", "ensemble",
2777        "eval", "exists", "export", "forget", "import",
2778        "inscope", "origin", "parent", "path", "qualifiers",
2779        "tail", "unknown", "upvar", "which", NULL
2780    };
2781    enum NSSubCmdIdx {
2782        NSChildrenIdx, NSCodeIdx, NSCurrentIdx, NSDeleteIdx, NSEnsembleIdx,
2783        NSEvalIdx, NSExistsIdx, NSExportIdx, NSForgetIdx, NSImportIdx,
2784        NSInscopeIdx, NSOriginIdx, NSParentIdx, NSPathIdx, NSQualifiersIdx,
2785        NSTailIdx, NSUnknownIdx, NSUpvarIdx, NSWhichIdx
2786    };
2787    int index, result;
2788
2789    if (objc < 2) {
2790        Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg ...?");
2791        return TCL_ERROR;
2792    }
2793
2794    /*
2795     * Return an index reflecting the particular subcommand.
2796     */
2797
2798    result = Tcl_GetIndexFromObj((Tcl_Interp *) interp, objv[1], subCmds,
2799            "option", /*flags*/ 0, (int *) &index);
2800    if (result != TCL_OK) {
2801        return result;
2802    }
2803
2804    switch (index) {
2805    case NSChildrenIdx:
2806        result = NamespaceChildrenCmd(clientData, interp, objc, objv);
2807        break;
2808    case NSCodeIdx:
2809        result = NamespaceCodeCmd(clientData, interp, objc, objv);
2810        break;
2811    case NSCurrentIdx:
2812        result = NamespaceCurrentCmd(clientData, interp, objc, objv);
2813        break;
2814    case NSDeleteIdx:
2815        result = NamespaceDeleteCmd(clientData, interp, objc, objv);
2816        break;
2817    case NSEnsembleIdx:
2818        result = NamespaceEnsembleCmd(clientData, interp, objc, objv);
2819        break;
2820    case NSEvalIdx:
2821        result = NamespaceEvalCmd(clientData, interp, objc, objv);
2822        break;
2823    case NSExistsIdx:
2824        result = NamespaceExistsCmd(clientData, interp, objc, objv);
2825        break;
2826    case NSExportIdx:
2827        result = NamespaceExportCmd(clientData, interp, objc, objv);
2828        break;
2829    case NSForgetIdx:
2830        result = NamespaceForgetCmd(clientData, interp, objc, objv);
2831        break;
2832    case NSImportIdx:
2833        result = NamespaceImportCmd(clientData, interp, objc, objv);
2834        break;
2835    case NSInscopeIdx:
2836        result = NamespaceInscopeCmd(clientData, interp, objc, objv);
2837        break;
2838    case NSOriginIdx:
2839        result = NamespaceOriginCmd(clientData, interp, objc, objv);
2840        break;
2841    case NSParentIdx:
2842        result = NamespaceParentCmd(clientData, interp, objc, objv);
2843        break;
2844    case NSPathIdx:
2845        result = NamespacePathCmd(clientData, interp, objc, objv);
2846        break;
2847    case NSQualifiersIdx:
2848        result = NamespaceQualifiersCmd(clientData, interp, objc, objv);
2849        break;
2850    case NSTailIdx:
2851        result = NamespaceTailCmd(clientData, interp, objc, objv);
2852        break;
2853    case NSUpvarIdx:
2854        result = NamespaceUpvarCmd(clientData, interp, objc, objv);
2855        break;
2856    case NSUnknownIdx:
2857        result = NamespaceUnknownCmd(clientData, interp, objc, objv);
2858        break;
2859    case NSWhichIdx:
2860        result = NamespaceWhichCmd(clientData, interp, objc, objv);
2861        break;
2862    }
2863    return result;
2864}
2865
2866/*
2867 *----------------------------------------------------------------------
2868 *
2869 * NamespaceChildrenCmd --
2870 *
2871 *      Invoked to implement the "namespace children" command that returns a
2872 *      list containing the fully-qualified names of the child namespaces of a
2873 *      given namespace. Handles the following syntax:
2874 *
2875 *          namespace children ?name? ?pattern?
2876 *
2877 * Results:
2878 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
2879 *
2880 * Side effects:
2881 *      Returns a result in the interpreter's result object. If anything goes
2882 *      wrong, the result is an error message.
2883 *
2884 *----------------------------------------------------------------------
2885 */
2886
2887static int
2888NamespaceChildrenCmd(
2889    ClientData dummy,           /* Not used. */
2890    Tcl_Interp *interp,         /* Current interpreter. */
2891    int objc,                   /* Number of arguments. */
2892    Tcl_Obj *const objv[])      /* Argument objects. */
2893{
2894    Tcl_Namespace *namespacePtr;
2895    Namespace *nsPtr, *childNsPtr;
2896    Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace(interp);
2897    char *pattern = NULL;
2898    Tcl_DString buffer;
2899    register Tcl_HashEntry *entryPtr;
2900    Tcl_HashSearch search;
2901    Tcl_Obj *listPtr, *elemPtr;
2902
2903    /*
2904     * Get a pointer to the specified namespace, or the current namespace.
2905     */
2906
2907    if (objc == 2) {
2908        nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
2909    } else if ((objc == 3) || (objc == 4)) {
2910        if (TclGetNamespaceFromObj(interp, objv[2], &namespacePtr) != TCL_OK) {
2911            return TCL_ERROR;
2912        }
2913        nsPtr = (Namespace *) namespacePtr;
2914    } else {
2915        Tcl_WrongNumArgs(interp, 2, objv, "?name? ?pattern?");
2916        return TCL_ERROR;
2917    }
2918
2919    /*
2920     * Get the glob-style pattern, if any, used to narrow the search.
2921     */
2922
2923    Tcl_DStringInit(&buffer);
2924    if (objc == 4) {
2925        char *name = TclGetString(objv[3]);
2926
2927        if ((*name == ':') && (*(name+1) == ':')) {
2928            pattern = name;
2929        } else {
2930            Tcl_DStringAppend(&buffer, nsPtr->fullName, -1);
2931            if (nsPtr != globalNsPtr) {
2932                Tcl_DStringAppend(&buffer, "::", 2);
2933            }
2934            Tcl_DStringAppend(&buffer, name, -1);
2935            pattern = Tcl_DStringValue(&buffer);
2936        }
2937    }
2938
2939    /*
2940     * Create a list containing the full names of all child namespaces whose
2941     * names match the specified pattern, if any.
2942     */
2943
2944    listPtr = Tcl_NewListObj(0, NULL);
2945    if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
2946        unsigned int length = strlen(nsPtr->fullName);
2947
2948        if (strncmp(pattern, nsPtr->fullName, length) != 0) {
2949            goto searchDone;
2950        }
2951        if (Tcl_FindHashEntry(&nsPtr->childTable, pattern+length) != NULL) {
2952            Tcl_ListObjAppendElement(interp, listPtr,
2953                    Tcl_NewStringObj(pattern, -1));
2954        }
2955        goto searchDone;
2956    }
2957    entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
2958    while (entryPtr != NULL) {
2959        childNsPtr = Tcl_GetHashValue(entryPtr);
2960        if ((pattern == NULL)
2961                || Tcl_StringMatch(childNsPtr->fullName, pattern)) {
2962            elemPtr = Tcl_NewStringObj(childNsPtr->fullName, -1);
2963            Tcl_ListObjAppendElement(interp, listPtr, elemPtr);
2964        }
2965        entryPtr = Tcl_NextHashEntry(&search);
2966    }
2967
2968  searchDone:
2969    Tcl_SetObjResult(interp, listPtr);
2970    Tcl_DStringFree(&buffer);
2971    return TCL_OK;
2972}
2973
2974/*
2975 *----------------------------------------------------------------------
2976 *
2977 * NamespaceCodeCmd --
2978 *
2979 *      Invoked to implement the "namespace code" command to capture the
2980 *      namespace context of a command. Handles the following syntax:
2981 *
2982 *          namespace code arg
2983 *
2984 *      Here "arg" can be a list. "namespace code arg" produces a result
2985 *      equivalent to that produced by the command
2986 *
2987 *          list ::namespace inscope [namespace current] $arg
2988 *
2989 *      However, if "arg" is itself a scoped value starting with "::namespace
2990 *      inscope", then the result is just "arg".
2991 *
2992 * Results:
2993 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
2994 *
2995 * Side effects:
2996 *      If anything goes wrong, this function returns an error message as the
2997 *      result in the interpreter's result object.
2998 *
2999 *----------------------------------------------------------------------
3000 */
3001
3002static int
3003NamespaceCodeCmd(
3004    ClientData dummy,           /* Not used. */
3005    Tcl_Interp *interp,         /* Current interpreter. */
3006    int objc,                   /* Number of arguments. */
3007    Tcl_Obj *const objv[])      /* Argument objects. */
3008{
3009    Namespace *currNsPtr;
3010    Tcl_Obj *listPtr, *objPtr;
3011    register char *arg, *p;
3012    int length;
3013
3014    if (objc != 3) {
3015        Tcl_WrongNumArgs(interp, 2, objv, "arg");
3016        return TCL_ERROR;
3017    }
3018
3019    /*
3020     * If "arg" is already a scoped value, then return it directly.
3021     */
3022
3023    arg = TclGetStringFromObj(objv[2], &length);
3024    while (*arg == ':') {
3025        arg++;
3026        length--;
3027    }
3028    if (*arg=='n' && length>17 && strncmp(arg, "namespace", 9)==0) {
3029        for (p=arg+9 ; isspace(UCHAR(*p)) ; p++) {
3030            /* empty body: skip over whitespace */
3031        }
3032        if (*p=='i' && (p+7 <= arg+length) && strncmp(p, "inscope", 7)==0) {
3033            Tcl_SetObjResult(interp, objv[2]);
3034            return TCL_OK;
3035        }
3036    }
3037
3038    /*
3039     * Otherwise, construct a scoped command by building a list with
3040     * "namespace inscope", the full name of the current namespace, and the
3041     * argument "arg". By constructing a list, we ensure that scoped commands
3042     * are interpreted properly when they are executed later, by the
3043     * "namespace inscope" command.
3044     */
3045
3046    TclNewObj(listPtr);
3047    TclNewLiteralStringObj(objPtr, "::namespace");
3048    Tcl_ListObjAppendElement(interp, listPtr, objPtr);
3049    TclNewLiteralStringObj(objPtr, "inscope");
3050    Tcl_ListObjAppendElement(interp, listPtr, objPtr);
3051
3052    currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
3053    if (currNsPtr == (Namespace *) TclGetGlobalNamespace(interp)) {
3054        TclNewLiteralStringObj(objPtr, "::");
3055    } else {
3056        objPtr = Tcl_NewStringObj(currNsPtr->fullName, -1);
3057    }
3058    Tcl_ListObjAppendElement(interp, listPtr, objPtr);
3059
3060    Tcl_ListObjAppendElement(interp, listPtr, objv[2]);
3061
3062    Tcl_SetObjResult(interp, listPtr);
3063    return TCL_OK;
3064}
3065
3066/*
3067 *----------------------------------------------------------------------
3068 *
3069 * NamespaceCurrentCmd --
3070 *
3071 *      Invoked to implement the "namespace current" command which returns the
3072 *      fully-qualified name of the current namespace. Handles the following
3073 *      syntax:
3074 *
3075 *          namespace current
3076 *
3077 * Results:
3078 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
3079 *
3080 * Side effects:
3081 *      Returns a result in the interpreter's result object. If anything goes
3082 *      wrong, the result is an error message.
3083 *
3084 *----------------------------------------------------------------------
3085 */
3086
3087static int
3088NamespaceCurrentCmd(
3089    ClientData dummy,           /* Not used. */
3090    Tcl_Interp *interp,         /* Current interpreter. */
3091    int objc,                   /* Number of arguments. */
3092    Tcl_Obj *const objv[])      /* Argument objects. */
3093{
3094    register Namespace *currNsPtr;
3095
3096    if (objc != 2) {
3097        Tcl_WrongNumArgs(interp, 2, objv, NULL);
3098        return TCL_ERROR;
3099    }
3100
3101    /*
3102     * The "real" name of the global namespace ("::") is the null string, but
3103     * we return "::" for it as a convenience to programmers. Note that "" and
3104     * "::" are treated as synonyms by the namespace code so that it is still
3105     * easy to do things like:
3106     *
3107     *    namespace [namespace current]::bar { ... }
3108     */
3109
3110    currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
3111    if (currNsPtr == (Namespace *) TclGetGlobalNamespace(interp)) {
3112        Tcl_SetObjResult(interp, Tcl_NewStringObj("::", 2));
3113    } else {
3114        Tcl_SetObjResult(interp, Tcl_NewStringObj(currNsPtr->fullName, -1));
3115    }
3116    return TCL_OK;
3117}
3118
3119/*
3120 *----------------------------------------------------------------------
3121 *
3122 * NamespaceDeleteCmd --
3123 *
3124 *      Invoked to implement the "namespace delete" command to delete
3125 *      namespace(s). Handles the following syntax:
3126 *
3127 *          namespace delete ?name name...?
3128 *
3129 *      Each name identifies a namespace. It may include a sequence of
3130 *      namespace qualifiers separated by "::"s. If a namespace is found, it
3131 *      is deleted: all variables and procedures contained in that namespace
3132 *      are deleted. If that namespace is being used on the call stack, it is
3133 *      kept alive (but logically deleted) until it is removed from the call
3134 *      stack: that is, it can no longer be referenced by name but any
3135 *      currently executing procedure that refers to it is allowed to do so
3136 *      until the procedure returns. If the namespace can't be found, this
3137 *      function returns an error. If no namespaces are specified, this
3138 *      command does nothing.
3139 *
3140 * Results:
3141 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
3142 *
3143 * Side effects:
3144 *      Deletes the specified namespaces. If anything goes wrong, this
3145 *      function returns an error message in the interpreter's result object.
3146 *
3147 *----------------------------------------------------------------------
3148 */
3149
3150static int
3151NamespaceDeleteCmd(
3152    ClientData dummy,           /* Not used. */
3153    Tcl_Interp *interp,         /* Current interpreter. */
3154    int objc,                   /* Number of arguments. */
3155    Tcl_Obj *const objv[])      /* Argument objects. */
3156{
3157    Tcl_Namespace *namespacePtr;
3158    char *name;
3159    register int i;
3160
3161    if (objc < 2) {
3162        Tcl_WrongNumArgs(interp, 2, objv, "?name name...?");
3163        return TCL_ERROR;
3164    }
3165
3166    /*
3167     * Destroying one namespace may cause another to be destroyed. Break this
3168     * into two passes: first check to make sure that all namespaces on the
3169     * command line are valid, and report any errors.
3170     */
3171
3172    for (i = 2;  i < objc;  i++) {
3173        name = TclGetString(objv[i]);
3174        namespacePtr = Tcl_FindNamespace(interp, name, NULL, /*flags*/ 0);
3175        if ((namespacePtr == NULL)
3176                || (((Namespace *)namespacePtr)->flags & NS_KILLED)) {
3177            Tcl_AppendResult(interp, "unknown namespace \"",
3178                    TclGetString(objv[i]),
3179                    "\" in namespace delete command", NULL);
3180            Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE",
3181                    TclGetString(objv[i]), NULL);
3182            return TCL_ERROR;
3183        }
3184    }
3185
3186    /*
3187     * Okay, now delete each namespace.
3188     */
3189
3190    for (i = 2;  i < objc;  i++) {
3191        name = TclGetString(objv[i]);
3192        namespacePtr = Tcl_FindNamespace(interp, name, NULL, /* flags */ 0);
3193        if (namespacePtr) {
3194            Tcl_DeleteNamespace(namespacePtr);
3195        }
3196    }
3197    return TCL_OK;
3198}
3199
3200/*
3201 *----------------------------------------------------------------------
3202 *
3203 * NamespaceEvalCmd --
3204 *
3205 *      Invoked to implement the "namespace eval" command. Executes commands
3206 *      in a namespace. If the namespace does not already exist, it is
3207 *      created. Handles the following syntax:
3208 *
3209 *          namespace eval name arg ?arg...?
3210 *
3211 *      If more than one arg argument is specified, the command that is
3212 *      executed is the result of concatenating the arguments together with a
3213 *      space between each argument.
3214 *
3215 * Results:
3216 *      Returns TCL_OK if the namespace is found and the commands are executed
3217 *      successfully. Returns TCL_ERROR if anything goes wrong.
3218 *
3219 * Side effects:
3220 *      Returns the result of the command in the interpreter's result object.
3221 *      If anything goes wrong, this function returns an error message as the
3222 *      result.
3223 *
3224 *----------------------------------------------------------------------
3225 */
3226
3227static int
3228NamespaceEvalCmd(
3229    ClientData dummy,           /* Not used. */
3230    Tcl_Interp *interp,         /* Current interpreter. */
3231    int objc,                   /* Number of arguments. */
3232    Tcl_Obj *const objv[])      /* Argument objects. */
3233{
3234    Tcl_Namespace *namespacePtr;
3235    CallFrame *framePtr, **framePtrPtr;
3236    Tcl_Obj *objPtr;
3237    int result;
3238
3239    if (objc < 4) {
3240        Tcl_WrongNumArgs(interp, 2, objv, "name arg ?arg...?");
3241        return TCL_ERROR;
3242    }
3243
3244    /*
3245     * Try to resolve the namespace reference, caching the result in the
3246     * namespace object along the way.
3247     */
3248
3249    result = GetNamespaceFromObj(interp, objv[2], &namespacePtr);
3250
3251    /*
3252     * If the namespace wasn't found, try to create it.
3253     */
3254
3255    if (result == TCL_ERROR) {
3256        char *name = TclGetString(objv[2]);
3257
3258        namespacePtr = Tcl_CreateNamespace(interp, name, NULL, NULL);
3259        if (namespacePtr == NULL) {
3260            return TCL_ERROR;
3261        }
3262    }
3263
3264    /*
3265     * Make the specified namespace the current namespace and evaluate the
3266     * command(s).
3267     */
3268
3269    /* This is needed to satisfy GCC 3.3's strict aliasing rules */
3270    framePtrPtr = &framePtr;
3271    result = TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
3272            namespacePtr, /*isProcCallFrame*/ 0);
3273    if (result != TCL_OK) {
3274        return TCL_ERROR;
3275    }
3276
3277    framePtr->objc = objc;
3278    framePtr->objv = objv;
3279
3280    if (objc == 4) {
3281        /*
3282         * TIP #280: Make invoker available to eval'd script.
3283         */
3284
3285        Interp *iPtr = (Interp *) interp;
3286
3287        result = TclEvalObjEx(interp, objv[3], 0, iPtr->cmdFramePtr, 3);
3288    } else {
3289        /*
3290         * More than one argument: concatenate them together with spaces
3291         * between, then evaluate the result. Tcl_EvalObjEx will delete the
3292         * object when it decrements its refcount after eval'ing it.
3293         */
3294
3295        objPtr = Tcl_ConcatObj(objc-3, objv+3);
3296
3297        /*
3298         * TIP #280: Make invoking context available to eval'd script.
3299         */
3300
3301        result = TclEvalObjEx(interp, objPtr, TCL_EVAL_DIRECT, NULL, 0);
3302    }
3303
3304    if (result == TCL_ERROR) {
3305        int length = strlen(namespacePtr->fullName);
3306        int limit = 200;
3307        int overflow = (length > limit);
3308
3309        Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
3310                "\n    (in namespace eval \"%.*s%s\" script line %d)",
3311                (overflow ? limit : length), namespacePtr->fullName,
3312                (overflow ? "..." : ""), interp->errorLine));
3313    }
3314
3315    /*
3316     * Restore the previous "current" namespace.
3317     */
3318
3319    TclPopStackFrame(interp);
3320    return result;
3321}
3322
3323/*
3324 *----------------------------------------------------------------------
3325 *
3326 * NamespaceExistsCmd --
3327 *
3328 *      Invoked to implement the "namespace exists" command that returns true
3329 *      if the given namespace currently exists, and false otherwise. Handles
3330 *      the following syntax:
3331 *
3332 *          namespace exists name
3333 *
3334 * Results:
3335 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
3336 *
3337 * Side effects:
3338 *      Returns a result in the interpreter's result object. If anything goes
3339 *      wrong, the result is an error message.
3340 *
3341 *----------------------------------------------------------------------
3342 */
3343
3344static int
3345NamespaceExistsCmd(
3346    ClientData dummy,           /* Not used. */
3347    Tcl_Interp *interp,         /* Current interpreter. */
3348    int objc,                   /* Number of arguments. */
3349    Tcl_Obj *const objv[])      /* Argument objects. */
3350{
3351    Tcl_Namespace *namespacePtr;
3352
3353    if (objc != 3) {
3354        Tcl_WrongNumArgs(interp, 2, objv, "name");
3355        return TCL_ERROR;
3356    }
3357
3358    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
3359            GetNamespaceFromObj(interp, objv[2], &namespacePtr) == TCL_OK));
3360    return TCL_OK;
3361}
3362
3363/*
3364 *----------------------------------------------------------------------
3365 *
3366 * NamespaceExportCmd --
3367 *
3368 *      Invoked to implement the "namespace export" command that specifies
3369 *      which commands are exported from a namespace. The exported commands
3370 *      are those that can be imported into another namespace using "namespace
3371 *      import". Both commands defined in a namespace and commands the
3372 *      namespace has imported can be exported by a namespace. This command
3373 *      has the following syntax:
3374 *
3375 *          namespace export ?-clear? ?pattern pattern...?
3376 *
3377 *      Each pattern may contain "string match"-style pattern matching special
3378 *      characters, but the pattern may not include any namespace qualifiers:
3379 *      that is, the pattern must specify commands in the current (exporting)
3380 *      namespace. The specified patterns are appended onto the namespace's
3381 *      list of export patterns.
3382 *
3383 *      To reset the namespace's export pattern list, specify the "-clear"
3384 *      flag.
3385 *
3386 *      If there are no export patterns and the "-clear" flag isn't given,
3387 *      this command returns the namespace's current export list.
3388 *
3389 * Results:
3390 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
3391 *
3392 * Side effects:
3393 *      Returns a result in the interpreter's result object. If anything goes
3394 *      wrong, the result is an error message.
3395 *
3396 *----------------------------------------------------------------------
3397 */
3398
3399static int
3400NamespaceExportCmd(
3401    ClientData dummy,           /* Not used. */
3402    Tcl_Interp *interp,         /* Current interpreter. */
3403    int objc,                   /* Number of arguments. */
3404    Tcl_Obj *const objv[])      /* Argument objects. */
3405{
3406    Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
3407    char *pattern, *string;
3408    int resetListFirst = 0;
3409    int firstArg, patternCt, i, result;
3410
3411    if (objc < 2) {
3412        Tcl_WrongNumArgs(interp, 2, objv, "?-clear? ?pattern pattern...?");
3413        return TCL_ERROR;
3414    }
3415
3416    /*
3417     * Process the optional "-clear" argument.
3418     */
3419
3420    firstArg = 2;
3421    if (firstArg < objc) {
3422        string = TclGetString(objv[firstArg]);
3423        if (strcmp(string, "-clear") == 0) {
3424            resetListFirst = 1;
3425            firstArg++;
3426        }
3427    }
3428
3429    /*
3430     * If no pattern arguments are given, and "-clear" isn't specified, return
3431     * the namespace's current export pattern list.
3432     */
3433
3434    patternCt = (objc - firstArg);
3435    if (patternCt == 0) {
3436        if (firstArg > 2) {
3437            return TCL_OK;
3438        } else {
3439            /*
3440             * Create list with export patterns.
3441             */
3442
3443            Tcl_Obj *listPtr = Tcl_NewListObj(0, NULL);
3444            result = Tcl_AppendExportList(interp, (Tcl_Namespace *) currNsPtr,
3445                    listPtr);
3446            if (result != TCL_OK) {
3447                return result;
3448            }
3449            Tcl_SetObjResult(interp, listPtr);
3450            return TCL_OK;
3451        }
3452    }
3453
3454    /*
3455     * Add each pattern to the namespace's export pattern list.
3456     */
3457
3458    for (i = firstArg;  i < objc;  i++) {
3459        pattern = TclGetString(objv[i]);
3460        result = Tcl_Export(interp, (Tcl_Namespace *) currNsPtr, pattern,
3461                ((i == firstArg)? resetListFirst : 0));
3462        if (result != TCL_OK) {
3463            return result;
3464        }
3465    }
3466    return TCL_OK;
3467}
3468
3469/*
3470 *----------------------------------------------------------------------
3471 *
3472 * NamespaceForgetCmd --
3473 *
3474 *      Invoked to implement the "namespace forget" command to remove imported
3475 *      commands from a namespace. Handles the following syntax:
3476 *
3477 *          namespace forget ?pattern pattern...?
3478 *
3479 *      Each pattern is a name like "foo::*" or "a::b::x*". That is, the
3480 *      pattern may include the special pattern matching characters recognized
3481 *      by the "string match" command, but only in the command name at the end
3482 *      of the qualified name; the special pattern characters may not appear
3483 *      in a namespace name. All of the commands that match that pattern are
3484 *      checked to see if they have an imported command in the current
3485 *      namespace that refers to the matched command. If there is an alias, it
3486 *      is removed.
3487 *
3488 * Results:
3489 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
3490 *
3491 * Side effects:
3492 *      Imported commands are removed from the current namespace. If anything
3493 *      goes wrong, this function returns an error message in the
3494 *      interpreter's result object.
3495 *
3496 *----------------------------------------------------------------------
3497 */
3498
3499static int
3500NamespaceForgetCmd(
3501    ClientData dummy,           /* Not used. */
3502    Tcl_Interp *interp,         /* Current interpreter. */
3503    int objc,                   /* Number of arguments. */
3504    Tcl_Obj *const objv[])      /* Argument objects. */
3505{
3506    char *pattern;
3507    register int i, result;
3508
3509    if (objc < 2) {
3510        Tcl_WrongNumArgs(interp, 2, objv, "?pattern pattern...?");
3511        return TCL_ERROR;
3512    }
3513
3514    for (i = 2;  i < objc;  i++) {
3515        pattern = TclGetString(objv[i]);
3516        result = Tcl_ForgetImport(interp, NULL, pattern);
3517        if (result != TCL_OK) {
3518            return result;
3519        }
3520    }
3521    return TCL_OK;
3522}
3523
3524/*
3525 *----------------------------------------------------------------------
3526 *
3527 * NamespaceImportCmd --
3528 *
3529 *      Invoked to implement the "namespace import" command that imports
3530 *      commands into a namespace. Handles the following syntax:
3531 *
3532 *          namespace import ?-force? ?pattern pattern...?
3533 *
3534 *      Each pattern is a namespace-qualified name like "foo::*", "a::b::x*",
3535 *      or "bar::p". That is, the pattern may include the special pattern
3536 *      matching characters recognized by the "string match" command, but only
3537 *      in the command name at the end of the qualified name; the special
3538 *      pattern characters may not appear in a namespace name. All of the
3539 *      commands that match the pattern and which are exported from their
3540 *      namespace are made accessible from the current namespace context. This
3541 *      is done by creating a new "imported command" in the current namespace
3542 *      that points to the real command in its original namespace; when the
3543 *      imported command is called, it invokes the real command.
3544 *
3545 *      If an imported command conflicts with an existing command, it is
3546 *      treated as an error. But if the "-force" option is included, then
3547 *      existing commands are overwritten by the imported commands.
3548 *
3549 *      If there are no pattern arguments and the "-force" flag isn't given,
3550 *      this command returns the list of commands currently imported in
3551 *      the current namespace.
3552 *
3553 * Results:
3554 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
3555 *
3556 * Side effects:
3557 *      Adds imported commands to the current namespace. If anything goes
3558 *      wrong, this function returns an error message in the interpreter's
3559 *      result object.
3560 *
3561 *----------------------------------------------------------------------
3562 */
3563
3564static int
3565NamespaceImportCmd(
3566    ClientData dummy,           /* Not used. */
3567    Tcl_Interp *interp,         /* Current interpreter. */
3568    int objc,                   /* Number of arguments. */
3569    Tcl_Obj *const objv[])      /* Argument objects. */
3570{
3571    int allowOverwrite = 0;
3572    char *string, *pattern;
3573    register int i, result;
3574    int firstArg;
3575
3576    if (objc < 2) {
3577        Tcl_WrongNumArgs(interp, 2, objv, "?-force? ?pattern pattern...?");
3578        return TCL_ERROR;
3579    }
3580
3581    /*
3582     * Skip over the optional "-force" as the first argument.
3583     */
3584
3585    firstArg = 2;
3586    if (firstArg < objc) {
3587        string = TclGetString(objv[firstArg]);
3588        if ((*string == '-') && (strcmp(string, "-force") == 0)) {
3589            allowOverwrite = 1;
3590            firstArg++;
3591        }
3592    } else {
3593        /*
3594         * When objc == 2, command is just [namespace import]. Introspection
3595         * form to return list of imported commands.
3596         */
3597
3598        Tcl_HashEntry *hPtr;
3599        Tcl_HashSearch search;
3600        Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
3601        Tcl_Obj *listPtr;
3602
3603        TclNewObj(listPtr);
3604        for (hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
3605                hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
3606            Command *cmdPtr = Tcl_GetHashValue(hPtr);
3607
3608            if (cmdPtr->deleteProc == DeleteImportedCmd) {
3609                Tcl_ListObjAppendElement(NULL, listPtr, Tcl_NewStringObj(
3610                        Tcl_GetHashKey(&nsPtr->cmdTable, hPtr) ,-1));
3611            }
3612        }
3613        Tcl_SetObjResult(interp, listPtr);
3614        return TCL_OK;
3615    }
3616
3617    /*
3618     * Handle the imports for each of the patterns.
3619     */
3620
3621    for (i = firstArg;  i < objc;  i++) {
3622        pattern = TclGetString(objv[i]);
3623        result = Tcl_Import(interp, NULL, pattern, allowOverwrite);
3624        if (result != TCL_OK) {
3625            return result;
3626        }
3627    }
3628    return TCL_OK;
3629}
3630
3631/*
3632 *----------------------------------------------------------------------
3633 *
3634 * NamespaceInscopeCmd --
3635 *
3636 *      Invoked to implement the "namespace inscope" command that executes a
3637 *      script in the context of a particular namespace. This command is not
3638 *      expected to be used directly by programmers; calls to it are generated
3639 *      implicitly when programs use "namespace code" commands to register
3640 *      callback scripts. Handles the following syntax:
3641 *
3642 *          namespace inscope name arg ?arg...?
3643 *
3644 *      The "namespace inscope" command is much like the "namespace eval"
3645 *      command except that it has lappend semantics and the namespace must
3646 *      already exist. It treats the first argument as a list, and appends any
3647 *      arguments after the first onto the end as proper list elements. For
3648 *      example,
3649 *
3650 *          namespace inscope ::foo {a b} c d e
3651 *
3652 *      is equivalent to
3653 *
3654 *          namespace eval ::foo [concat {a b} [list c d e]]
3655 *
3656 *      This lappend semantics is important because many callback scripts are
3657 *      actually prefixes.
3658 *
3659 * Results:
3660 *      Returns TCL_OK to indicate success, or TCL_ERROR to indicate failure.
3661 *
3662 * Side effects:
3663 *      Returns a result in the Tcl interpreter's result object.
3664 *
3665 *----------------------------------------------------------------------
3666 */
3667
3668static int
3669NamespaceInscopeCmd(
3670    ClientData dummy,           /* Not used. */
3671    Tcl_Interp *interp,         /* Current interpreter. */
3672    int objc,                   /* Number of arguments. */
3673    Tcl_Obj *const objv[])      /* Argument objects. */
3674{
3675    Tcl_Namespace *namespacePtr;
3676    CallFrame *framePtr, **framePtrPtr;
3677    int i, result;
3678
3679    if (objc < 4) {
3680        Tcl_WrongNumArgs(interp, 2, objv, "name arg ?arg...?");
3681        return TCL_ERROR;
3682    }
3683
3684    /*
3685     * Resolve the namespace reference.
3686     */
3687
3688    if (TclGetNamespaceFromObj(interp, objv[2], &namespacePtr) != TCL_OK) {
3689        return TCL_ERROR;
3690    }
3691
3692    /*
3693     * Make the specified namespace the current namespace.
3694     */
3695
3696    framePtrPtr = &framePtr;            /* This is needed to satisfy GCC's
3697                                         * strict aliasing rules. */
3698    result = TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
3699            namespacePtr, /*isProcCallFrame*/ 0);
3700    if (result != TCL_OK) {
3701        return result;
3702    }
3703
3704    framePtr->objc = objc;
3705    framePtr->objv = objv;
3706
3707    /*
3708     * Execute the command. If there is just one argument, just treat it as a
3709     * script and evaluate it. Otherwise, create a list from the arguments
3710     * after the first one, then concatenate the first argument and the list
3711     * of extra arguments to form the command to evaluate.
3712     */
3713
3714    if (objc == 4) {
3715        result = Tcl_EvalObjEx(interp, objv[3], 0);
3716    } else {
3717        Tcl_Obj *concatObjv[2];
3718        register Tcl_Obj *listPtr, *cmdObjPtr;
3719
3720        listPtr = Tcl_NewListObj(0, NULL);
3721        for (i = 4;  i < objc;  i++) {
3722            if (Tcl_ListObjAppendElement(interp, listPtr, objv[i]) != TCL_OK) {
3723                Tcl_DecrRefCount(listPtr);      /* Free unneeded obj. */
3724                return TCL_ERROR;
3725            }
3726        }
3727
3728        concatObjv[0] = objv[3];
3729        concatObjv[1] = listPtr;
3730        cmdObjPtr = Tcl_ConcatObj(2, concatObjv);
3731        result = Tcl_EvalObjEx(interp, cmdObjPtr, TCL_EVAL_DIRECT);
3732        Tcl_DecrRefCount(listPtr);    /* We're done with the list object. */
3733    }
3734
3735    if (result == TCL_ERROR) {
3736        int length = strlen(namespacePtr->fullName);
3737        int limit = 200;
3738        int overflow = (length > limit);
3739
3740        Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
3741                "\n    (in namespace inscope \"%.*s%s\" script line %d)",
3742                (overflow ? limit : length), namespacePtr->fullName,
3743                (overflow ? "..." : ""), interp->errorLine));
3744    }
3745
3746    /*
3747     * Restore the previous "current" namespace.
3748     */
3749
3750    TclPopStackFrame(interp);
3751    return result;
3752}
3753
3754/*
3755 *----------------------------------------------------------------------
3756 *
3757 * NamespaceOriginCmd --
3758 *
3759 *      Invoked to implement the "namespace origin" command to return the
3760 *      fully-qualified name of the "real" command to which the specified
3761 *      "imported command" refers. Handles the following syntax:
3762 *
3763 *          namespace origin name
3764 *
3765 * Results:
3766 *      An imported command is created in an namespace when that namespace
3767 *      imports a command from another namespace. If a command is imported
3768 *      into a sequence of namespaces a, b,...,n where each successive
3769 *      namespace just imports the command from the previous namespace, this
3770 *      command returns the fully-qualified name of the original command in
3771 *      the first namespace, a. If "name" does not refer to an alias, its
3772 *      fully-qualified name is returned. The returned name is stored in the
3773 *      interpreter's result object. This function returns TCL_OK if
3774 *      successful, and TCL_ERROR if anything goes wrong.
3775 *
3776 * Side effects:
3777 *      If anything goes wrong, this function returns an error message in the
3778 *      interpreter's result object.
3779 *
3780 *----------------------------------------------------------------------
3781 */
3782
3783static int
3784NamespaceOriginCmd(
3785    ClientData dummy,           /* Not used. */
3786    Tcl_Interp *interp,         /* Current interpreter. */
3787    int objc,                   /* Number of arguments. */
3788    Tcl_Obj *const objv[])      /* Argument objects. */
3789{
3790    Tcl_Command command, origCommand;
3791    Tcl_Obj *resultPtr;
3792
3793    if (objc != 3) {
3794        Tcl_WrongNumArgs(interp, 2, objv, "name");
3795        return TCL_ERROR;
3796    }
3797
3798    command = Tcl_GetCommandFromObj(interp, objv[2]);
3799    if (command == NULL) {
3800        Tcl_AppendResult(interp, "invalid command name \"",
3801                TclGetString(objv[2]), "\"", NULL);
3802        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND",
3803                TclGetString(objv[2]), NULL);
3804        return TCL_ERROR;
3805    }
3806    origCommand = TclGetOriginalCommand(command);
3807    TclNewObj(resultPtr);
3808    if (origCommand == NULL) {
3809        /*
3810         * The specified command isn't an imported command. Return the
3811         * command's name qualified by the full name of the namespace it was
3812         * defined in.
3813         */
3814
3815        Tcl_GetCommandFullName(interp, command, resultPtr);
3816    } else {
3817        Tcl_GetCommandFullName(interp, origCommand, resultPtr);
3818    }
3819    Tcl_SetObjResult(interp, resultPtr);
3820    return TCL_OK;
3821}
3822
3823/*
3824 *----------------------------------------------------------------------
3825 *
3826 * NamespaceParentCmd --
3827 *
3828 *      Invoked to implement the "namespace parent" command that returns the
3829 *      fully-qualified name of the parent namespace for a specified
3830 *      namespace. Handles the following syntax:
3831 *
3832 *          namespace parent ?name?
3833 *
3834 * Results:
3835 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
3836 *
3837 * Side effects:
3838 *      Returns a result in the interpreter's result object. If anything goes
3839 *      wrong, the result is an error message.
3840 *
3841 *----------------------------------------------------------------------
3842 */
3843
3844static int
3845NamespaceParentCmd(
3846    ClientData dummy,           /* Not used. */
3847    Tcl_Interp *interp,         /* Current interpreter. */
3848    int objc,                   /* Number of arguments. */
3849    Tcl_Obj *const objv[])      /* Argument objects. */
3850{
3851    Tcl_Namespace *nsPtr;
3852
3853    if (objc == 2) {
3854        nsPtr = TclGetCurrentNamespace(interp);
3855    } else if (objc == 3) {
3856        if (TclGetNamespaceFromObj(interp, objv[2], &nsPtr) != TCL_OK) {
3857            return TCL_ERROR;
3858        }
3859    } else {
3860        Tcl_WrongNumArgs(interp, 2, objv, "?name?");
3861        return TCL_ERROR;
3862    }
3863
3864    /*
3865     * Report the parent of the specified namespace.
3866     */
3867
3868    if (nsPtr->parentPtr != NULL) {
3869        Tcl_SetObjResult(interp, Tcl_NewStringObj(
3870                nsPtr->parentPtr->fullName, -1));
3871    }
3872    return TCL_OK;
3873}
3874
3875/*
3876 *----------------------------------------------------------------------
3877 *
3878 * NamespacePathCmd --
3879 *
3880 *      Invoked to implement the "namespace path" command that reads and
3881 *      writes the current namespace's command resolution path. Has one
3882 *      optional argument: if present, it is a list of named namespaces to set
3883 *      the path to, and if absent, the current path should be returned.
3884 *      Handles the following syntax:
3885 *
3886 *          namespace path ?nsList?
3887 *
3888 * Results:
3889 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong
3890 *      (most notably if the namespace list contains the name of something
3891 *      other than a namespace). In the successful-exit case, may set the
3892 *      interpreter result to the list of names of the namespaces on the
3893 *      current namespace's path.
3894 *
3895 * Side effects:
3896 *      May update the namespace path (triggering a recomputing of all command
3897 *      names that depend on the namespace for resolution).
3898 *
3899 *----------------------------------------------------------------------
3900 */
3901
3902static int
3903NamespacePathCmd(
3904    ClientData dummy,           /* Not used. */
3905    Tcl_Interp *interp,         /* Current interpreter. */
3906    int objc,                   /* Number of arguments. */
3907    Tcl_Obj *const objv[])      /* Argument objects. */
3908{
3909    Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
3910    int i, nsObjc, result = TCL_ERROR;
3911    Tcl_Obj **nsObjv;
3912    Tcl_Namespace **namespaceList = NULL;
3913
3914    if (objc > 3) {
3915        Tcl_WrongNumArgs(interp, 2, objv, "?pathList?");
3916        return TCL_ERROR;
3917    }
3918
3919    /*
3920     * If no path is given, return the current path.
3921     */
3922
3923    if (objc == 2) {
3924        /*
3925         * Not a very fast way to compute this, but easy to get right.
3926         */
3927
3928        for (i=0 ; i<nsPtr->commandPathLength ; i++) {
3929            if (nsPtr->commandPathArray[i].nsPtr != NULL) {
3930                Tcl_AppendElement(interp,
3931                        nsPtr->commandPathArray[i].nsPtr->fullName);
3932            }
3933        }
3934        return TCL_OK;
3935    }
3936
3937    /*
3938     * There is a path given, so parse it into an array of namespace pointers.
3939     */
3940
3941    if (TclListObjGetElements(interp, objv[2], &nsObjc, &nsObjv) != TCL_OK) {
3942        goto badNamespace;
3943    }
3944    if (nsObjc != 0) {
3945        namespaceList = (Tcl_Namespace **)
3946                TclStackAlloc(interp, sizeof(Tcl_Namespace *) * nsObjc);
3947
3948        for (i=0 ; i<nsObjc ; i++) {
3949            if (TclGetNamespaceFromObj(interp, nsObjv[i],
3950                    &namespaceList[i]) != TCL_OK) {
3951                goto badNamespace;
3952            }
3953        }
3954    }
3955
3956    /*
3957     * Now we have the list of valid namespaces, install it as the path.
3958     */
3959
3960    TclSetNsPath(nsPtr, nsObjc, namespaceList);
3961
3962    result = TCL_OK;
3963  badNamespace:
3964    if (namespaceList != NULL) {
3965        TclStackFree(interp, namespaceList);
3966    }
3967    return result;
3968}
3969
3970/*
3971 *----------------------------------------------------------------------
3972 *
3973 * TclSetNsPath --
3974 *
3975 *      Sets the namespace command name resolution path to the given list of
3976 *      namespaces. If the list is empty (of zero length) the path is set to
3977 *      empty and the default old-style behaviour of command name resolution
3978 *      is used.
3979 *
3980 * Results:
3981 *      nothing
3982 *
3983 * Side effects:
3984 *      Invalidates the command name resolution caches for any command
3985 *      resolved in the given namespace.
3986 *
3987 *----------------------------------------------------------------------
3988 */
3989
3990void
3991TclSetNsPath(
3992    Namespace *nsPtr,           /* Namespace whose path is to be set. */
3993    int pathLength,             /* Length of pathAry. */
3994    Tcl_Namespace *pathAry[])   /* Array of namespaces that are the path. */
3995{
3996    if (pathLength != 0) {
3997        NamespacePathEntry *tmpPathArray = (NamespacePathEntry *)
3998                ckalloc(sizeof(NamespacePathEntry) * pathLength);
3999        int i;
4000
4001        for (i=0 ; i<pathLength ; i++) {
4002            tmpPathArray[i].nsPtr = (Namespace *) pathAry[i];
4003            tmpPathArray[i].creatorNsPtr = nsPtr;
4004            tmpPathArray[i].prevPtr = NULL;
4005            tmpPathArray[i].nextPtr =
4006                    tmpPathArray[i].nsPtr->commandPathSourceList;
4007            if (tmpPathArray[i].nextPtr != NULL) {
4008                tmpPathArray[i].nextPtr->prevPtr = &tmpPathArray[i];
4009            }
4010            tmpPathArray[i].nsPtr->commandPathSourceList = &tmpPathArray[i];
4011        }
4012        if (nsPtr->commandPathLength != 0) {
4013            UnlinkNsPath(nsPtr);
4014        }
4015        nsPtr->commandPathArray = tmpPathArray;
4016    } else {
4017        if (nsPtr->commandPathLength != 0) {
4018            UnlinkNsPath(nsPtr);
4019        }
4020    }
4021
4022    nsPtr->commandPathLength = pathLength;
4023    nsPtr->cmdRefEpoch++;
4024    nsPtr->resolverEpoch++;
4025}
4026
4027/*
4028 *----------------------------------------------------------------------
4029 *
4030 * UnlinkNsPath --
4031 *
4032 *      Delete the given namespace's command name resolution path. Only call
4033 *      if the path is non-empty. Caller must reset the counter containing the
4034 *      path size.
4035 *
4036 * Results:
4037 *      nothing
4038 *
4039 * Side effects:
4040 *      Deletes the array of path entries and unlinks those path entries from
4041 *      the target namespace's list of interested namespaces.
4042 *
4043 *----------------------------------------------------------------------
4044 */
4045
4046static void
4047UnlinkNsPath(
4048    Namespace *nsPtr)
4049{
4050    int i;
4051    for (i=0 ; i<nsPtr->commandPathLength ; i++) {
4052        NamespacePathEntry *nsPathPtr = &nsPtr->commandPathArray[i];
4053        if (nsPathPtr->prevPtr != NULL) {
4054            nsPathPtr->prevPtr->nextPtr = nsPathPtr->nextPtr;
4055        }
4056        if (nsPathPtr->nextPtr != NULL) {
4057            nsPathPtr->nextPtr->prevPtr = nsPathPtr->prevPtr;
4058        }
4059        if (nsPathPtr->nsPtr != NULL) {
4060            if (nsPathPtr->nsPtr->commandPathSourceList == nsPathPtr) {
4061                nsPathPtr->nsPtr->commandPathSourceList = nsPathPtr->nextPtr;
4062            }
4063        }
4064    }
4065    ckfree((char *) nsPtr->commandPathArray);
4066}
4067
4068/*
4069 *----------------------------------------------------------------------
4070 *
4071 * TclInvalidateNsPath --
4072 *
4073 *      Invalidate the name resolution caches for all names looked up in
4074 *      namespaces whose name path includes the given namespace.
4075 *
4076 * Results:
4077 *      nothing
4078 *
4079 * Side effects:
4080 *      Increments the command reference epoch in each namespace whose path
4081 *      includes the given namespace. This causes any cached resolved names
4082 *      whose root cacheing context starts at that namespace to be recomputed
4083 *      the next time they are used.
4084 *
4085 *----------------------------------------------------------------------
4086 */
4087
4088void
4089TclInvalidateNsPath(
4090    Namespace *nsPtr)
4091{
4092    NamespacePathEntry *nsPathPtr = nsPtr->commandPathSourceList;
4093    while (nsPathPtr != NULL) {
4094        if (nsPathPtr->nsPtr != NULL) {
4095            nsPathPtr->creatorNsPtr->cmdRefEpoch++;
4096        }
4097        nsPathPtr = nsPathPtr->nextPtr;
4098    }
4099}
4100
4101/*
4102 *----------------------------------------------------------------------
4103 *
4104 * NamespaceQualifiersCmd --
4105 *
4106 *      Invoked to implement the "namespace qualifiers" command that returns
4107 *      any leading namespace qualifiers in a string. These qualifiers are
4108 *      namespace names separated by "::"s. For example, for "::foo::p" this
4109 *      command returns "::foo", and for "::" it returns "". This command is
4110 *      the complement of the "namespace tail" command. Note that this command
4111 *      does not check whether the "namespace" names are, in fact, the names
4112 *      of currently defined namespaces. Handles the following syntax:
4113 *
4114 *          namespace qualifiers string
4115 *
4116 * Results:
4117 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
4118 *
4119 * Side effects:
4120 *      Returns a result in the interpreter's result object. If anything goes
4121 *      wrong, the result is an error message.
4122 *
4123 *----------------------------------------------------------------------
4124 */
4125
4126static int
4127NamespaceQualifiersCmd(
4128    ClientData dummy,           /* Not used. */
4129    Tcl_Interp *interp,         /* Current interpreter. */
4130    int objc,                   /* Number of arguments. */
4131    Tcl_Obj *const objv[])      /* Argument objects. */
4132{
4133    register char *name, *p;
4134    int length;
4135
4136    if (objc != 3) {
4137        Tcl_WrongNumArgs(interp, 2, objv, "string");
4138        return TCL_ERROR;
4139    }
4140
4141    /*
4142     * Find the end of the string, then work backward and find the start of
4143     * the last "::" qualifier.
4144     */
4145
4146    name = TclGetString(objv[2]);
4147    for (p = name;  *p != '\0';  p++) {
4148        /* empty body */
4149    }
4150    while (--p >= name) {
4151        if ((*p == ':') && (p > name) && (*(p-1) == ':')) {
4152            p -= 2;                     /* Back up over the :: */
4153            while ((p >= name) && (*p == ':')) {
4154                p--;                    /* Back up over the preceeding : */
4155            }
4156            break;
4157        }
4158    }
4159
4160    if (p >= name) {
4161        length = p-name+1;
4162        Tcl_SetObjResult(interp, Tcl_NewStringObj(name, length));
4163    }
4164    return TCL_OK;
4165}
4166
4167/*
4168 *----------------------------------------------------------------------
4169 *
4170 * NamespaceUnknownCmd --
4171 *
4172 *      Invoked to implement the "namespace unknown" command (TIP 181) that
4173 *      sets or queries a per-namespace unknown command handler. This handler
4174 *      is called when command lookup fails (current and global ns). The
4175 *      default handler for the global namespace is ::unknown. The default
4176 *      handler for other namespaces is to call the global namespace unknown
4177 *      handler. Passing an empty list results in resetting the handler to its
4178 *      default.
4179 *
4180 *          namespace unknown ?handler?
4181 *
4182 * Results:
4183 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
4184 *
4185 * Side effects:
4186 *      If no handler is specified, returns a result in the interpreter's
4187 *      result object, otherwise it sets the unknown handler pointer in the
4188 *      current namespace to the script fragment provided. If anything goes
4189 *      wrong, the result is an error message.
4190 *
4191 *----------------------------------------------------------------------
4192 */
4193
4194static int
4195NamespaceUnknownCmd(
4196    ClientData dummy,           /* Not used. */
4197    Tcl_Interp *interp,         /* Current interpreter. */
4198    int objc,                   /* Number of arguments. */
4199    Tcl_Obj *const objv[])      /* Argument objects. */
4200{
4201    Tcl_Namespace *currNsPtr;
4202    Tcl_Obj *resultPtr;
4203    int rc;
4204
4205    if (objc > 3) {
4206        Tcl_WrongNumArgs(interp, 2, objv, "?script?");
4207        return TCL_ERROR;
4208    }
4209
4210    currNsPtr = TclGetCurrentNamespace(interp);
4211
4212    if (objc == 2) {
4213        /*
4214         * Introspection - return the current namespace handler.
4215         */
4216
4217        resultPtr = Tcl_GetNamespaceUnknownHandler(interp, currNsPtr);
4218        if (resultPtr == NULL) {
4219            TclNewObj(resultPtr);
4220        }
4221        Tcl_SetObjResult(interp, resultPtr);
4222    } else {
4223        rc = Tcl_SetNamespaceUnknownHandler(interp, currNsPtr, objv[2]);
4224        if (rc == TCL_OK) {
4225            Tcl_SetObjResult(interp, objv[2]);
4226        }
4227        return rc;
4228    }
4229    return TCL_OK;
4230}
4231
4232/*
4233 *----------------------------------------------------------------------
4234 *
4235 * Tcl_GetNamespaceUnknownHandler --
4236 *
4237 *      Returns the unknown command handler registered for the given
4238 *      namespace.
4239 *
4240 * Results:
4241 *      Returns the current unknown command handler, or NULL if none exists
4242 *      for the namespace.
4243 *
4244 * Side effects:
4245 *      None.
4246 *
4247 *----------------------------------------------------------------------
4248 */
4249
4250Tcl_Obj *
4251Tcl_GetNamespaceUnknownHandler(
4252    Tcl_Interp *interp,         /* The interpreter in which the namespace
4253                                 * exists. */
4254    Tcl_Namespace *nsPtr)       /* The namespace. */
4255{
4256    Namespace *currNsPtr = (Namespace *)nsPtr;
4257
4258    if (currNsPtr->unknownHandlerPtr == NULL &&
4259            currNsPtr == ((Interp *)interp)->globalNsPtr) {
4260        /*
4261         * Default handler for global namespace is "::unknown". For all other
4262         * namespaces, it is NULL (which falls back on the global unknown
4263         * handler).
4264         */
4265
4266        TclNewLiteralStringObj(currNsPtr->unknownHandlerPtr, "::unknown");
4267        Tcl_IncrRefCount(currNsPtr->unknownHandlerPtr);
4268    }
4269    return currNsPtr->unknownHandlerPtr;
4270}
4271
4272/*
4273 *----------------------------------------------------------------------
4274 *
4275 * Tcl_SetNamespaceUnknownHandler --
4276 *
4277 *      Sets the unknown command handler for the given namespace to the
4278 *      command prefix passed.
4279 *
4280 * Results:
4281 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
4282 *
4283 * Side effects:
4284 *      Sets the namespace unknown command handler. If the passed in handler
4285 *      is NULL or an empty list, then the handler is reset to its default. If
4286 *      an error occurs, then an error message is left in the interpreter
4287 *      result.
4288 *
4289 *----------------------------------------------------------------------
4290 */
4291
4292int
4293Tcl_SetNamespaceUnknownHandler(
4294    Tcl_Interp *interp,         /* Interpreter in which the namespace
4295                                 * exists. */
4296    Tcl_Namespace *nsPtr,       /* Namespace which is being updated. */
4297    Tcl_Obj *handlerPtr)        /* The new handler, or NULL to reset. */
4298{
4299    int lstlen;
4300    Namespace *currNsPtr = (Namespace *)nsPtr;
4301
4302    if (currNsPtr->unknownHandlerPtr != NULL) {
4303        /*
4304         * Remove old handler first.
4305         */
4306
4307        Tcl_DecrRefCount(currNsPtr->unknownHandlerPtr);
4308        currNsPtr->unknownHandlerPtr = NULL;
4309    }
4310
4311    /*
4312     * If NULL or an empty list is passed, then reset to the default
4313     * handler.
4314     */
4315
4316    if (handlerPtr == NULL) {
4317        currNsPtr->unknownHandlerPtr = NULL;
4318    } else if (TclListObjLength(interp, handlerPtr, &lstlen) != TCL_OK) {
4319        /*
4320         * Not a list.
4321         */
4322
4323        return TCL_ERROR;
4324    } else if (lstlen == 0) {
4325        /*
4326         * Empty list - reset to default.
4327         */
4328
4329        currNsPtr->unknownHandlerPtr = NULL;
4330    } else {
4331        /*
4332         * Increment ref count and store. The reference count is decremented
4333         * either in the code above, or when the namespace is deleted.
4334         */
4335
4336        Tcl_IncrRefCount(handlerPtr);
4337        currNsPtr->unknownHandlerPtr = handlerPtr;
4338    }
4339    return TCL_OK;
4340}
4341
4342/*
4343 *----------------------------------------------------------------------
4344 *
4345 * NamespaceTailCmd --
4346 *
4347 *      Invoked to implement the "namespace tail" command that returns the
4348 *      trailing name at the end of a string with "::" namespace qualifiers.
4349 *      These qualifiers are namespace names separated by "::"s. For example,
4350 *      for "::foo::p" this command returns "p", and for "::" it returns "".
4351 *      This command is the complement of the "namespace qualifiers" command.
4352 *      Note that this command does not check whether the "namespace" names
4353 *      are, in fact, the names of currently defined namespaces. Handles the
4354 *      following syntax:
4355 *
4356 *          namespace tail string
4357 *
4358 * Results:
4359 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
4360 *
4361 * Side effects:
4362 *      Returns a result in the interpreter's result object. If anything goes
4363 *      wrong, the result is an error message.
4364 *
4365 *----------------------------------------------------------------------
4366 */
4367
4368static int
4369NamespaceTailCmd(
4370    ClientData dummy,           /* Not used. */
4371    Tcl_Interp *interp,         /* Current interpreter. */
4372    int objc,                   /* Number of arguments. */
4373    Tcl_Obj *const objv[])      /* Argument objects. */
4374{
4375    register char *name, *p;
4376
4377    if (objc != 3) {
4378        Tcl_WrongNumArgs(interp, 2, objv, "string");
4379        return TCL_ERROR;
4380    }
4381
4382    /*
4383     * Find the end of the string, then work backward and find the last "::"
4384     * qualifier.
4385     */
4386
4387    name = TclGetString(objv[2]);
4388    for (p = name;  *p != '\0';  p++) {
4389        /* empty body */
4390    }
4391    while (--p > name) {
4392        if ((*p == ':') && (*(p-1) == ':')) {
4393            p++;                        /* Just after the last "::" */
4394            break;
4395        }
4396    }
4397
4398    if (p >= name) {
4399        Tcl_SetObjResult(interp, Tcl_NewStringObj(p, -1));
4400    }
4401    return TCL_OK;
4402}
4403
4404/*
4405 *----------------------------------------------------------------------
4406 *
4407 * NamespaceUpvarCmd --
4408 *
4409 *      Invoked to implement the "namespace upvar" command, that creates
4410 *      variables in the current scope linked to variables in another
4411 *      namespace. Handles the following syntax:
4412 *
4413 *          namespace upvar ns otherVar myVar ?otherVar myVar ...?
4414 *
4415 * Results:
4416 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
4417 *
4418 * Side effects:
4419 *      Creates new variables in the current scope, linked to the
4420 *      corresponding variables in the stipulated nmamespace. If anything goes
4421 *      wrong, the result is an error message.
4422 *
4423 *----------------------------------------------------------------------
4424 */
4425
4426static int
4427NamespaceUpvarCmd(
4428    ClientData dummy,           /* Not used. */
4429    Tcl_Interp *interp,         /* Current interpreter. */
4430    int objc,                   /* Number of arguments. */
4431    Tcl_Obj *const objv[])      /* Argument objects. */
4432{
4433    Interp *iPtr = (Interp *) interp;
4434    Tcl_Namespace *nsPtr, *savedNsPtr;
4435    Var *otherPtr, *arrayPtr;
4436    char *myName;
4437
4438    if (objc < 5 || !(objc & 1)) {
4439        Tcl_WrongNumArgs(interp, 2, objv,
4440                "ns otherVar myVar ?otherVar myVar ...?");
4441        return TCL_ERROR;
4442    }
4443
4444    if (TclGetNamespaceFromObj(interp, objv[2], &nsPtr) != TCL_OK) {
4445        return TCL_ERROR;
4446    }
4447
4448    objc -= 3;
4449    objv += 3;
4450
4451    for (; objc>0 ; objc-=2, objv+=2) {
4452        /*
4453         * Locate the other variable
4454         */
4455
4456        savedNsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
4457        iPtr->varFramePtr->nsPtr = (Namespace *) nsPtr;
4458        otherPtr = TclObjLookupVarEx(interp, objv[0], NULL,
4459                (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access",
4460                /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
4461        iPtr->varFramePtr->nsPtr = (Namespace *) savedNsPtr;
4462        if (otherPtr == NULL) {
4463            return TCL_ERROR;
4464        }
4465
4466        /*
4467         * Create the new variable and link it to otherPtr.
4468         */
4469
4470        myName = TclGetString(objv[1]);
4471        if (TclPtrMakeUpvar(interp, otherPtr, myName, 0, -1) != TCL_OK) {
4472            return TCL_ERROR;
4473        }
4474    }
4475
4476    return TCL_OK;
4477}
4478
4479/*
4480 *----------------------------------------------------------------------
4481 *
4482 * NamespaceWhichCmd --
4483 *
4484 *      Invoked to implement the "namespace which" command that returns the
4485 *      fully-qualified name of a command or variable. If the specified
4486 *      command or variable does not exist, it returns "". Handles the
4487 *      following syntax:
4488 *
4489 *          namespace which ?-command? ?-variable? name
4490 *
4491 * Results:
4492 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
4493 *
4494 * Side effects:
4495 *      Returns a result in the interpreter's result object. If anything goes
4496 *      wrong, the result is an error message.
4497 *
4498 *----------------------------------------------------------------------
4499 */
4500
4501static int
4502NamespaceWhichCmd(
4503    ClientData dummy,           /* Not used. */
4504    Tcl_Interp *interp,         /* Current interpreter. */
4505    int objc,                   /* Number of arguments. */
4506    Tcl_Obj *const objv[])      /* Argument objects. */
4507{
4508    static const char *opts[] = {
4509        "-command", "-variable", NULL
4510    };
4511    int lookupType = 0;
4512    Tcl_Obj *resultPtr;
4513
4514    if (objc < 3 || objc > 4) {
4515    badArgs:
4516        Tcl_WrongNumArgs(interp, 2, objv, "?-command? ?-variable? name");
4517        return TCL_ERROR;
4518    } else if (objc == 4) {
4519        /*
4520         * Look for a flag controlling the lookup.
4521         */
4522
4523        if (Tcl_GetIndexFromObj(interp, objv[2], opts, "option", 0,
4524                &lookupType) != TCL_OK) {
4525            /*
4526             * Preserve old style of error message!
4527             */
4528
4529            Tcl_ResetResult(interp);
4530            goto badArgs;
4531        }
4532    }
4533
4534    TclNewObj(resultPtr);
4535    switch (lookupType) {
4536    case 0: {                           /* -command */
4537        Tcl_Command cmd = Tcl_GetCommandFromObj(interp, objv[objc-1]);
4538
4539        if (cmd != NULL) {
4540            Tcl_GetCommandFullName(interp, cmd, resultPtr);
4541        }
4542        break;
4543    }
4544    case 1: {                           /* -variable */
4545        Tcl_Var var = Tcl_FindNamespaceVar(interp,
4546                TclGetString(objv[objc-1]), NULL, /*flags*/ 0);
4547
4548        if (var != NULL) {
4549            Tcl_GetVariableFullName(interp, var, resultPtr);
4550        }
4551        break;
4552    }
4553    }
4554    Tcl_SetObjResult(interp, resultPtr);
4555    return TCL_OK;
4556}
4557
4558/*
4559 *----------------------------------------------------------------------
4560 *
4561 * FreeNsNameInternalRep --
4562 *
4563 *      Frees the resources associated with a nsName object's internal
4564 *      representation.
4565 *
4566 * Results:
4567 *      None.
4568 *
4569 * Side effects:
4570 *      Decrements the ref count of any Namespace structure pointed to by the
4571 *      nsName's internal representation. If there are no more references to
4572 *      the namespace, it's structure will be freed.
4573 *
4574 *----------------------------------------------------------------------
4575 */
4576
4577static void
4578FreeNsNameInternalRep(
4579    register Tcl_Obj *objPtr)   /* nsName object with internal representation
4580                                 * to free. */
4581{
4582    register ResolvedNsName *resNamePtr = (ResolvedNsName *)
4583            objPtr->internalRep.twoPtrValue.ptr1;
4584    Namespace *nsPtr;
4585
4586    /*
4587     * Decrement the reference count of the namespace. If there are no more
4588     * references, free it up.
4589     */
4590
4591    resNamePtr->refCount--;
4592    if (resNamePtr->refCount == 0) {
4593
4594        /*
4595         * Decrement the reference count for the cached namespace. If the
4596         * namespace is dead, and there are no more references to it, free
4597         * it.
4598         */
4599
4600        nsPtr = resNamePtr->nsPtr;
4601        nsPtr->refCount--;
4602        if ((nsPtr->refCount == 0) && (nsPtr->flags & NS_DEAD)) {
4603            NamespaceFree(nsPtr);
4604        }
4605        ckfree((char *) resNamePtr);
4606    }
4607}
4608
4609/*
4610 *----------------------------------------------------------------------
4611 *
4612 * DupNsNameInternalRep --
4613 *
4614 *      Initializes the internal representation of a nsName object to a copy
4615 *      of the internal representation of another nsName object.
4616 *
4617 * Results:
4618 *      None.
4619 *
4620 * Side effects:
4621 *      copyPtr's internal rep is set to refer to the same namespace
4622 *      referenced by srcPtr's internal rep. Increments the ref count of the
4623 *      ResolvedNsName structure used to hold the namespace reference.
4624 *
4625 *----------------------------------------------------------------------
4626 */
4627
4628static void
4629DupNsNameInternalRep(
4630    Tcl_Obj *srcPtr,            /* Object with internal rep to copy. */
4631    register Tcl_Obj *copyPtr)  /* Object with internal rep to set. */
4632{
4633    register ResolvedNsName *resNamePtr = (ResolvedNsName *)
4634            srcPtr->internalRep.twoPtrValue.ptr1;
4635
4636    copyPtr->internalRep.twoPtrValue.ptr1 = resNamePtr;
4637    resNamePtr->refCount++;
4638    copyPtr->typePtr = &nsNameType;
4639}
4640
4641/*
4642 *----------------------------------------------------------------------
4643 *
4644 * SetNsNameFromAny --
4645 *
4646 *      Attempt to generate a nsName internal representation for a Tcl object.
4647 *
4648 * Results:
4649 *      Returns TCL_OK if the value could be converted to a proper namespace
4650 *      reference. Otherwise, it returns TCL_ERROR, along with an error
4651 *      message in the interpreter's result object.
4652 *
4653 * Side effects:
4654 *      If successful, the object is made a nsName object. Its internal rep is
4655 *      set to point to a ResolvedNsName, which contains a cached pointer to
4656 *      the Namespace. Reference counts are kept on both the ResolvedNsName
4657 *      and the Namespace, so we can keep track of their usage and free them
4658 *      when appropriate.
4659 *
4660 *----------------------------------------------------------------------
4661 */
4662
4663static int
4664SetNsNameFromAny(
4665    Tcl_Interp *interp,         /* Points to the namespace in which to resolve
4666                                 * name. Also used for error reporting if not
4667                                 * NULL. */
4668    register Tcl_Obj *objPtr)   /* The object to convert. */
4669{
4670    const char *dummy;
4671    Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr;
4672    register ResolvedNsName *resNamePtr;
4673    const char *name = TclGetString(objPtr);
4674
4675    TclGetNamespaceForQualName(interp, name, NULL, TCL_FIND_ONLY_NS,
4676             &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
4677
4678    /*
4679     * If we found a namespace, then create a new ResolvedNsName structure
4680     * that holds a reference to it.
4681     */
4682
4683    if ((nsPtr == NULL) || (nsPtr->flags & NS_DYING)) {
4684        /*
4685         * Our failed lookup proves any previously cached nsName intrep is no
4686         * longer valid. Get rid of it so we no longer waste memory storing
4687         * it, nor time determining its invalidity again and again.
4688         */
4689
4690        if (objPtr->typePtr == &nsNameType) {
4691            TclFreeIntRep(objPtr);
4692            objPtr->typePtr = NULL;
4693        }
4694        return TCL_ERROR;
4695    }
4696
4697    nsPtr->refCount++;
4698    resNamePtr = (ResolvedNsName *) ckalloc(sizeof(ResolvedNsName));
4699    resNamePtr->nsPtr = nsPtr;
4700    if ((name[0] == ':') && (name[1] == ':')) {
4701        resNamePtr->refNsPtr = NULL;
4702    } else {
4703        resNamePtr->refNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
4704    }
4705    resNamePtr->refCount = 1;
4706    TclFreeIntRep(objPtr);
4707    objPtr->internalRep.twoPtrValue.ptr1 = resNamePtr;
4708    objPtr->typePtr = &nsNameType;
4709    return TCL_OK;
4710}
4711
4712/*
4713 *----------------------------------------------------------------------
4714 *
4715 * NamespaceEnsembleCmd --
4716 *
4717 *      Invoked to implement the "namespace ensemble" command that creates and
4718 *      manipulates ensembles built on top of namespaces. Handles the
4719 *      following syntax:
4720 *
4721 *          namespace ensemble name ?dictionary?
4722 *
4723 * Results:
4724 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
4725 *
4726 * Side effects:
4727 *      Creates the ensemble for the namespace if one did not previously
4728 *      exist. Alternatively, alters the way that the ensemble's subcommand =>
4729 *      implementation prefix is configured.
4730 *
4731 *----------------------------------------------------------------------
4732 */
4733
4734static int
4735NamespaceEnsembleCmd(
4736    ClientData dummy,
4737    Tcl_Interp *interp,
4738    int objc,
4739    Tcl_Obj *const objv[])
4740{
4741    Namespace *nsPtr;
4742    Tcl_Command token;
4743    static const char *subcommands[] = {
4744        "configure", "create", "exists", NULL
4745    };
4746    enum EnsSubcmds {
4747        ENS_CONFIG, ENS_CREATE, ENS_EXISTS
4748    };
4749    static const char *createOptions[] = {
4750        "-command", "-map", "-prefixes", "-subcommands", "-unknown", NULL
4751    };
4752    enum EnsCreateOpts {
4753        CRT_CMD, CRT_MAP, CRT_PREFIX, CRT_SUBCMDS, CRT_UNKNOWN
4754    };
4755    static const char *configOptions[] = {
4756        "-map", "-namespace", "-prefixes", "-subcommands", "-unknown", NULL
4757    };
4758    enum EnsConfigOpts {
4759        CONF_MAP, CONF_NAMESPACE, CONF_PREFIX, CONF_SUBCMDS, CONF_UNKNOWN
4760    };
4761    int index;
4762
4763    nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
4764    if (nsPtr == NULL || nsPtr->flags & NS_DYING) {
4765        if (!Tcl_InterpDeleted(interp)) {
4766            Tcl_AppendResult(interp,
4767                    "tried to manipulate ensemble of deleted namespace", NULL);
4768        }
4769        return TCL_ERROR;
4770    }
4771
4772    if (objc < 3) {
4773        Tcl_WrongNumArgs(interp, 2, objv, "subcommand ?arg ...?");
4774        return TCL_ERROR;
4775    }
4776    if (Tcl_GetIndexFromObj(interp, objv[2], subcommands, "subcommand", 0,
4777            &index) != TCL_OK) {
4778        return TCL_ERROR;
4779    }
4780
4781    switch ((enum EnsSubcmds) index) {
4782    case ENS_CREATE: {
4783        char *name;
4784        Tcl_DictSearch search;
4785        Tcl_Obj *listObj;
4786        int done, len, allocatedMapFlag = 0;
4787        /*
4788         * Defaults
4789         */
4790        Tcl_Obj *subcmdObj = NULL;
4791        Tcl_Obj *mapObj = NULL;
4792        int permitPrefix = 1;
4793        Tcl_Obj *unknownObj = NULL;
4794
4795        objv += 3;
4796        objc -= 3;
4797
4798        /*
4799         * Work out what name to use for the command to create. If supplied,
4800         * it is either fully specified or relative to the current namespace.
4801         * If not supplied, it is exactly the name of the current namespace.
4802         */
4803
4804        name = nsPtr->fullName;
4805
4806        /*
4807         * Parse the option list, applying type checks as we go. Note that we
4808         * are not incrementing any reference counts in the objects at this
4809         * stage, so the presence of an option multiple times won't cause any
4810         * memory leaks.
4811         */
4812
4813        for (; objc>1 ; objc-=2,objv+=2 ) {
4814            if (Tcl_GetIndexFromObj(interp, objv[0], createOptions, "option",
4815                    0, &index) != TCL_OK) {
4816                if (allocatedMapFlag) {
4817                    Tcl_DecrRefCount(mapObj);
4818                }
4819                return TCL_ERROR;
4820            }
4821            switch ((enum EnsCreateOpts) index) {
4822            case CRT_CMD:
4823                name = TclGetString(objv[1]);
4824                continue;
4825            case CRT_SUBCMDS:
4826                if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
4827                    if (allocatedMapFlag) {
4828                        Tcl_DecrRefCount(mapObj);
4829                    }
4830                    return TCL_ERROR;
4831                }
4832                subcmdObj = (len > 0 ? objv[1] : NULL);
4833                continue;
4834            case CRT_MAP: {
4835                Tcl_Obj *patchedDict = NULL, *subcmdObj;
4836
4837                /*
4838                 * Verify that the map is sensible.
4839                 */
4840
4841                if (Tcl_DictObjFirst(interp, objv[1], &search,
4842                        &subcmdObj, &listObj, &done) != TCL_OK) {
4843                    if (allocatedMapFlag) {
4844                        Tcl_DecrRefCount(mapObj);
4845                    }
4846                    return TCL_ERROR;
4847                }
4848                if (done) {
4849                    mapObj = NULL;
4850                    continue;
4851                }
4852                do {
4853                    Tcl_Obj **listv;
4854                    char *cmd;
4855
4856                    if (TclListObjGetElements(interp, listObj, &len,
4857                            &listv) != TCL_OK) {
4858                        Tcl_DictObjDone(&search);
4859                        if (patchedDict) {
4860                            Tcl_DecrRefCount(patchedDict);
4861                        }
4862                        if (allocatedMapFlag) {
4863                            Tcl_DecrRefCount(mapObj);
4864                        }
4865                        return TCL_ERROR;
4866                    }
4867                    if (len < 1) {
4868                        Tcl_SetResult(interp,
4869                                "ensemble subcommand implementations "
4870                                "must be non-empty lists", TCL_STATIC);
4871                        Tcl_DictObjDone(&search);
4872                        if (patchedDict) {
4873                            Tcl_DecrRefCount(patchedDict);
4874                        }
4875                        if (allocatedMapFlag) {
4876                            Tcl_DecrRefCount(mapObj);
4877                        }
4878                        return TCL_ERROR;
4879                    }
4880                    cmd = TclGetString(listv[0]);
4881                    if (!(cmd[0] == ':' && cmd[1] == ':')) {
4882                        Tcl_Obj *newList = Tcl_NewListObj(len, listv);
4883                        Tcl_Obj *newCmd = Tcl_NewStringObj(nsPtr->fullName,-1);
4884
4885                        if (nsPtr->parentPtr) {
4886                            Tcl_AppendStringsToObj(newCmd, "::", NULL);
4887                        }
4888                        Tcl_AppendObjToObj(newCmd, listv[0]);
4889                        Tcl_ListObjReplace(NULL, newList, 0, 1, 1, &newCmd);
4890                        if (patchedDict == NULL) {
4891                            patchedDict = Tcl_DuplicateObj(objv[1]);
4892                        }
4893                        Tcl_DictObjPut(NULL, patchedDict, subcmdObj, newList);
4894                    }
4895                    Tcl_DictObjNext(&search, &subcmdObj, &listObj, &done);
4896                } while (!done);
4897
4898                if (allocatedMapFlag) {
4899                    Tcl_DecrRefCount(mapObj);
4900                }
4901                mapObj = (patchedDict ? patchedDict : objv[1]);
4902                if (patchedDict) {
4903                    allocatedMapFlag = 1;
4904                }
4905                continue;
4906            }
4907            case CRT_PREFIX:
4908                if (Tcl_GetBooleanFromObj(interp, objv[1],
4909                        &permitPrefix) != TCL_OK) {
4910                    if (allocatedMapFlag) {
4911                        Tcl_DecrRefCount(mapObj);
4912                    }
4913                    return TCL_ERROR;
4914                }
4915                continue;
4916            case CRT_UNKNOWN:
4917                if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
4918                    if (allocatedMapFlag) {
4919                        Tcl_DecrRefCount(mapObj);
4920                    }
4921                    return TCL_ERROR;
4922                }
4923                unknownObj = (len > 0 ? objv[1] : NULL);
4924                continue;
4925            }
4926        }
4927
4928        /*
4929         * Create the ensemble. Note that this might delete another ensemble
4930         * linked to the same namespace, so we must be careful. However, we
4931         * should be OK because we only link the namespace into the list once
4932         * we've created it (and after any deletions have occurred.)
4933         */
4934
4935        token = Tcl_CreateEnsemble(interp, name, NULL,
4936                (permitPrefix ? TCL_ENSEMBLE_PREFIX : 0));
4937        Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj);
4938        Tcl_SetEnsembleMappingDict(interp, token, mapObj);
4939        Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj);
4940
4941        /*
4942         * Tricky! Must ensure that the result is not shared (command delete
4943         * traces could have corrupted the pristine object that we started
4944         * with). [Snit test rename-1.5]
4945         */
4946
4947        Tcl_ResetResult(interp);
4948        Tcl_GetCommandFullName(interp, token, Tcl_GetObjResult(interp));
4949        return TCL_OK;
4950    }
4951
4952    case ENS_EXISTS:
4953        if (objc != 4) {
4954            Tcl_WrongNumArgs(interp, 3, objv, "cmdname");
4955            return TCL_ERROR;
4956        }
4957        Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
4958                Tcl_FindEnsemble(interp, objv[3], 0) != NULL));
4959        return TCL_OK;
4960
4961    case ENS_CONFIG:
4962        if (objc < 4 || (objc != 5 && objc & 1)) {
4963            Tcl_WrongNumArgs(interp, 3, objv, "cmdname ?opt? ?value? ...");
4964            return TCL_ERROR;
4965        }
4966        token = Tcl_FindEnsemble(interp, objv[3], TCL_LEAVE_ERR_MSG);
4967        if (token == NULL) {
4968            return TCL_ERROR;
4969        }
4970
4971        if (objc == 5) {
4972            Tcl_Obj *resultObj = NULL;          /* silence gcc 4 warning */
4973
4974            if (Tcl_GetIndexFromObj(interp, objv[4], configOptions, "option",
4975                    0, &index) != TCL_OK) {
4976                return TCL_ERROR;
4977            }
4978            switch ((enum EnsConfigOpts) index) {
4979            case CONF_SUBCMDS:
4980                Tcl_GetEnsembleSubcommandList(NULL, token, &resultObj);
4981                if (resultObj != NULL) {
4982                    Tcl_SetObjResult(interp, resultObj);
4983                }
4984                break;
4985            case CONF_MAP:
4986                Tcl_GetEnsembleMappingDict(NULL, token, &resultObj);
4987                if (resultObj != NULL) {
4988                    Tcl_SetObjResult(interp, resultObj);
4989                }
4990                break;
4991            case CONF_NAMESPACE: {
4992                Tcl_Namespace *namespacePtr = NULL; /* silence gcc 4 warning */
4993
4994                Tcl_GetEnsembleNamespace(NULL, token, &namespacePtr);
4995                Tcl_SetResult(interp, ((Namespace *)namespacePtr)->fullName,
4996                        TCL_VOLATILE);
4997                break;
4998            }
4999            case CONF_PREFIX: {
5000                int flags = 0;                  /* silence gcc 4 warning */
5001
5002                Tcl_GetEnsembleFlags(NULL, token, &flags);
5003                Tcl_SetObjResult(interp,
5004                        Tcl_NewBooleanObj(flags & TCL_ENSEMBLE_PREFIX));
5005                break;
5006            }
5007            case CONF_UNKNOWN:
5008                Tcl_GetEnsembleUnknownHandler(NULL, token, &resultObj);
5009                if (resultObj != NULL) {
5010                    Tcl_SetObjResult(interp, resultObj);
5011                }
5012                break;
5013            }
5014            return TCL_OK;
5015
5016        } else if (objc == 4) {
5017            /*
5018             * Produce list of all information.
5019             */
5020
5021            Tcl_Obj *resultObj, *tmpObj = NULL; /* silence gcc 4 warning */
5022            Tcl_Namespace *namespacePtr = NULL; /* silence gcc 4 warning */
5023            int flags = 0;                      /* silence gcc 4 warning */
5024
5025            TclNewObj(resultObj);
5026
5027            /* -map option */
5028            Tcl_ListObjAppendElement(NULL, resultObj,
5029                    Tcl_NewStringObj(configOptions[CONF_MAP], -1));
5030            Tcl_GetEnsembleMappingDict(NULL, token, &tmpObj);
5031            Tcl_ListObjAppendElement(NULL, resultObj,
5032                    (tmpObj != NULL) ? tmpObj : Tcl_NewObj());
5033
5034            /* -namespace option */
5035            Tcl_ListObjAppendElement(NULL, resultObj,
5036                    Tcl_NewStringObj(configOptions[CONF_NAMESPACE], -1));
5037            Tcl_GetEnsembleNamespace(NULL, token, &namespacePtr);
5038            Tcl_ListObjAppendElement(NULL, resultObj,
5039                    Tcl_NewStringObj(((Namespace *)namespacePtr)->fullName,
5040                    -1));
5041
5042            /* -prefix option */
5043            Tcl_ListObjAppendElement(NULL, resultObj,
5044                    Tcl_NewStringObj(configOptions[CONF_PREFIX], -1));
5045            Tcl_GetEnsembleFlags(NULL, token, &flags);
5046            Tcl_ListObjAppendElement(NULL, resultObj,
5047                    Tcl_NewBooleanObj(flags & TCL_ENSEMBLE_PREFIX));
5048
5049            /* -subcommands option */
5050            Tcl_ListObjAppendElement(NULL, resultObj,
5051                    Tcl_NewStringObj(configOptions[CONF_SUBCMDS], -1));
5052            Tcl_GetEnsembleSubcommandList(NULL, token, &tmpObj);
5053            Tcl_ListObjAppendElement(NULL, resultObj,
5054                    (tmpObj != NULL) ? tmpObj : Tcl_NewObj());
5055
5056            /* -unknown option */
5057            Tcl_ListObjAppendElement(NULL, resultObj,
5058                    Tcl_NewStringObj(configOptions[CONF_UNKNOWN], -1));
5059            Tcl_GetEnsembleUnknownHandler(NULL, token, &tmpObj);
5060            Tcl_ListObjAppendElement(NULL, resultObj,
5061                    (tmpObj != NULL) ? tmpObj : Tcl_NewObj());
5062
5063            Tcl_SetObjResult(interp, resultObj);
5064            return TCL_OK;
5065        } else {
5066            Tcl_DictSearch search;
5067            Tcl_Obj *listObj;
5068            int done, len, allocatedMapFlag = 0;
5069            Tcl_Obj *subcmdObj = NULL, *mapObj = NULL,
5070                    *unknownObj = NULL; /* Defaults, silence gcc 4 warnings */
5071            int permitPrefix, flags = 0;        /* silence gcc 4 warning */
5072
5073            Tcl_GetEnsembleSubcommandList(NULL, token, &subcmdObj);
5074            Tcl_GetEnsembleMappingDict(NULL, token, &mapObj);
5075            Tcl_GetEnsembleUnknownHandler(NULL, token, &unknownObj);
5076            Tcl_GetEnsembleFlags(NULL, token, &flags);
5077            permitPrefix = (flags & TCL_ENSEMBLE_PREFIX) != 0;
5078
5079            objv += 4;
5080            objc -= 4;
5081
5082            /*
5083             * Parse the option list, applying type checks as we go. Note that
5084             * we are not incrementing any reference counts in the objects at
5085             * this stage, so the presence of an option multiple times won't
5086             * cause any memory leaks.
5087             */
5088
5089            for (; objc>0 ; objc-=2,objv+=2 ) {
5090                if (Tcl_GetIndexFromObj(interp, objv[0], configOptions,
5091                        "option", 0, &index) != TCL_OK) {
5092                    if (allocatedMapFlag) {
5093                        Tcl_DecrRefCount(mapObj);
5094                    }
5095                    return TCL_ERROR;
5096                }
5097                switch ((enum EnsConfigOpts) index) {
5098                case CONF_SUBCMDS:
5099                    if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
5100                        if (allocatedMapFlag) {
5101                            Tcl_DecrRefCount(mapObj);
5102                        }
5103                        return TCL_ERROR;
5104                    }
5105                    subcmdObj = (len > 0 ? objv[1] : NULL);
5106                    continue;
5107                case CONF_MAP: {
5108                    Tcl_Obj *patchedDict = NULL, *subcmdObj;
5109
5110                    /*
5111                     * Verify that the map is sensible.
5112                     */
5113
5114                    if (Tcl_DictObjFirst(interp, objv[1], &search,
5115                            &subcmdObj, &listObj, &done) != TCL_OK) {
5116                        if (allocatedMapFlag) {
5117                            Tcl_DecrRefCount(mapObj);
5118                        }
5119                        return TCL_ERROR;
5120                    }
5121                    if (done) {
5122                        mapObj = NULL;
5123                        continue;
5124                    }
5125                    do {
5126                        Tcl_Obj **listv;
5127                        char *cmd;
5128
5129                        if (TclListObjGetElements(interp, listObj, &len,
5130                                &listv) != TCL_OK) {
5131                            Tcl_DictObjDone(&search);
5132                            if (patchedDict) {
5133                                Tcl_DecrRefCount(patchedDict);
5134                            }
5135                            if (allocatedMapFlag) {
5136                                Tcl_DecrRefCount(mapObj);
5137                            }
5138                            return TCL_ERROR;
5139                        }
5140                        if (len < 1) {
5141                            Tcl_SetResult(interp,
5142                                    "ensemble subcommand implementations "
5143                                    "must be non-empty lists", TCL_STATIC);
5144                            Tcl_DictObjDone(&search);
5145                            if (patchedDict) {
5146                                Tcl_DecrRefCount(patchedDict);
5147                            }
5148                            if (allocatedMapFlag) {
5149                                Tcl_DecrRefCount(mapObj);
5150                            }
5151                            return TCL_ERROR;
5152                        }
5153                        cmd = TclGetString(listv[0]);
5154                        if (!(cmd[0] == ':' && cmd[1] == ':')) {
5155                            Tcl_Obj *newList = Tcl_NewListObj(len, listv);
5156                            Tcl_Obj *newCmd =
5157                                    Tcl_NewStringObj(nsPtr->fullName, -1);
5158                            if (nsPtr->parentPtr) {
5159                                Tcl_AppendStringsToObj(newCmd, "::", NULL);
5160                            }
5161                            Tcl_AppendObjToObj(newCmd, listv[0]);
5162                            Tcl_ListObjReplace(NULL, newList, 0,1, 1,&newCmd);
5163                            if (patchedDict == NULL) {
5164                                patchedDict = Tcl_DuplicateObj(objv[1]);
5165                            }
5166                            Tcl_DictObjPut(NULL, patchedDict, subcmdObj,
5167                                    newList);
5168                        }
5169                        Tcl_DictObjNext(&search, &subcmdObj, &listObj, &done);
5170                    } while (!done);
5171                    if (allocatedMapFlag) {
5172                        Tcl_DecrRefCount(mapObj);
5173                    }
5174                    mapObj = (patchedDict ? patchedDict : objv[1]);
5175                    if (patchedDict) {
5176                        allocatedMapFlag = 1;
5177                    }
5178                    continue;
5179                }
5180                case CONF_NAMESPACE:
5181                    if (allocatedMapFlag) {
5182                        Tcl_DecrRefCount(mapObj);
5183                    }
5184                    Tcl_AppendResult(interp, "option -namespace is read-only",
5185                            NULL);
5186                    return TCL_ERROR;
5187                case CONF_PREFIX:
5188                    if (Tcl_GetBooleanFromObj(interp, objv[1],
5189                            &permitPrefix) != TCL_OK) {
5190                        if (allocatedMapFlag) {
5191                            Tcl_DecrRefCount(mapObj);
5192                        }
5193                        return TCL_ERROR;
5194                    }
5195                    continue;
5196                case CONF_UNKNOWN:
5197                    if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
5198                        if (allocatedMapFlag) {
5199                            Tcl_DecrRefCount(mapObj);
5200                        }
5201                        return TCL_ERROR;
5202                    }
5203                    unknownObj = (len > 0 ? objv[1] : NULL);
5204                    continue;
5205                }
5206            }
5207
5208            /*
5209             * Update the namespace now that we've finished the parsing stage.
5210             */
5211
5212            flags = (permitPrefix ? flags|TCL_ENSEMBLE_PREFIX
5213                    : flags&~TCL_ENSEMBLE_PREFIX);
5214            Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj);
5215            Tcl_SetEnsembleMappingDict(interp, token, mapObj);
5216            Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj);
5217            Tcl_SetEnsembleFlags(interp, token, flags);
5218            return TCL_OK;
5219        }
5220
5221    default:
5222        Tcl_Panic("unexpected ensemble command");
5223    }
5224    return TCL_OK;
5225}
5226
5227/*
5228 *----------------------------------------------------------------------
5229 *
5230 * Tcl_CreateEnsemble --
5231 *
5232 *      Create a simple ensemble attached to the given namespace.
5233 *
5234 * Results:
5235 *      The token for the command created.
5236 *
5237 * Side effects:
5238 *      The ensemble is created and marked for compilation.
5239 *
5240 *----------------------------------------------------------------------
5241 */
5242
5243Tcl_Command
5244Tcl_CreateEnsemble(
5245    Tcl_Interp *interp,
5246    const char *name,
5247    Tcl_Namespace *namespacePtr,
5248    int flags)
5249{
5250    Namespace *nsPtr = (Namespace *) namespacePtr;
5251    EnsembleConfig *ensemblePtr = (EnsembleConfig *)
5252            ckalloc(sizeof(EnsembleConfig));
5253    Tcl_Obj *nameObj = NULL;
5254
5255    if (nsPtr == NULL) {
5256        nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
5257    }
5258
5259    /*
5260     * Make the name of the ensemble into a fully qualified name. This might
5261     * allocate a temporary object.
5262     */
5263
5264    if (!(name[0] == ':' && name[1] == ':')) {
5265        nameObj = Tcl_NewStringObj(nsPtr->fullName, -1);
5266        if (nsPtr->parentPtr == NULL) {
5267            Tcl_AppendStringsToObj(nameObj, name, NULL);
5268        } else {
5269            Tcl_AppendStringsToObj(nameObj, "::", name, NULL);
5270        }
5271        Tcl_IncrRefCount(nameObj);
5272        name = TclGetString(nameObj);
5273    }
5274
5275    ensemblePtr->nsPtr = nsPtr;
5276    ensemblePtr->epoch = 0;
5277    Tcl_InitHashTable(&ensemblePtr->subcommandTable, TCL_STRING_KEYS);
5278    ensemblePtr->subcommandArrayPtr = NULL;
5279    ensemblePtr->subcmdList = NULL;
5280    ensemblePtr->subcommandDict = NULL;
5281    ensemblePtr->flags = flags;
5282    ensemblePtr->unknownHandler = NULL;
5283    ensemblePtr->token = Tcl_CreateObjCommand(interp, name,
5284            NsEnsembleImplementationCmd, ensemblePtr, DeleteEnsembleConfig);
5285    ensemblePtr->next = (EnsembleConfig *) nsPtr->ensembles;
5286    nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr;
5287
5288    /*
5289     * Trigger an eventual recomputation of the ensemble command set. Note
5290     * that this is slightly tricky, as it means that we are not actually
5291     * counting the number of namespace export actions, but it is the simplest
5292     * way to go!
5293     */
5294
5295    nsPtr->exportLookupEpoch++;
5296
5297    if (flags & ENSEMBLE_COMPILE) {
5298        ((Command *) ensemblePtr->token)->compileProc = TclCompileEnsemble;
5299    }
5300
5301    if (nameObj != NULL) {
5302        TclDecrRefCount(nameObj);
5303    }
5304    return ensemblePtr->token;
5305}
5306
5307/*
5308 *----------------------------------------------------------------------
5309 *
5310 * Tcl_SetEnsembleSubcommandList --
5311 *
5312 *      Set the subcommand list for a particular ensemble.
5313 *
5314 * Results:
5315 *      Tcl result code (error if command token does not indicate an ensemble
5316 *      or the subcommand list - if non-NULL - is not a list).
5317 *
5318 * Side effects:
5319 *      The ensemble is updated and marked for recompilation.
5320 *
5321 *----------------------------------------------------------------------
5322 */
5323
5324int
5325Tcl_SetEnsembleSubcommandList(
5326    Tcl_Interp *interp,
5327    Tcl_Command token,
5328    Tcl_Obj *subcmdList)
5329{
5330    Command *cmdPtr = (Command *) token;
5331    EnsembleConfig *ensemblePtr;
5332    Tcl_Obj *oldList;
5333
5334    if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
5335        Tcl_AppendResult(interp, "command is not an ensemble", NULL);
5336        return TCL_ERROR;
5337    }
5338    if (subcmdList != NULL) {
5339        int length;
5340
5341        if (TclListObjLength(interp, subcmdList, &length) != TCL_OK) {
5342            return TCL_ERROR;
5343        }
5344        if (length < 1) {
5345            subcmdList = NULL;
5346        }
5347    }
5348
5349    ensemblePtr = cmdPtr->objClientData;
5350    oldList = ensemblePtr->subcmdList;
5351    ensemblePtr->subcmdList = subcmdList;
5352    if (subcmdList != NULL) {
5353        Tcl_IncrRefCount(subcmdList);
5354    }
5355    if (oldList != NULL) {
5356        TclDecrRefCount(oldList);
5357    }
5358
5359    /*
5360     * Trigger an eventual recomputation of the ensemble command set. Note
5361     * that this is slightly tricky, as it means that we are not actually
5362     * counting the number of namespace export actions, but it is the simplest
5363     * way to go!
5364     */
5365
5366    ensemblePtr->nsPtr->exportLookupEpoch++;
5367
5368    /*
5369     * Special hack to make compiling of [info exists] work when the
5370     * dictionary is modified.
5371     */
5372
5373    if (cmdPtr->compileProc != NULL) {
5374        ((Interp *)interp)->compileEpoch++;
5375    }
5376
5377    return TCL_OK;
5378}
5379
5380/*
5381 *----------------------------------------------------------------------
5382 *
5383 * Tcl_SetEnsembleMappingDict --
5384 *
5385 *      Set the mapping dictionary for a particular ensemble.
5386 *
5387 * Results:
5388 *      Tcl result code (error if command token does not indicate an ensemble
5389 *      or the mapping - if non-NULL - is not a dict).
5390 *
5391 * Side effects:
5392 *      The ensemble is updated and marked for recompilation.
5393 *
5394 *----------------------------------------------------------------------
5395 */
5396
5397int
5398Tcl_SetEnsembleMappingDict(
5399    Tcl_Interp *interp,
5400    Tcl_Command token,
5401    Tcl_Obj *mapDict)
5402{
5403    Command *cmdPtr = (Command *) token;
5404    EnsembleConfig *ensemblePtr;
5405    Tcl_Obj *oldDict;
5406
5407    if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
5408        Tcl_AppendResult(interp, "command is not an ensemble", NULL);
5409        return TCL_ERROR;
5410    }
5411    if (mapDict != NULL) {
5412        int size, done;
5413        Tcl_DictSearch search;
5414        Tcl_Obj *valuePtr;
5415
5416        if (Tcl_DictObjSize(interp, mapDict, &size) != TCL_OK) {
5417            return TCL_ERROR;
5418        }
5419
5420        for (Tcl_DictObjFirst(NULL, mapDict, &search, NULL, &valuePtr, &done);
5421                !done; Tcl_DictObjNext(&search, NULL, &valuePtr, &done)) {
5422            Tcl_Obj *cmdPtr;
5423            const char *bytes;
5424
5425            if (Tcl_ListObjIndex(interp, valuePtr, 0, &cmdPtr) != TCL_OK) {
5426                Tcl_DictObjDone(&search);
5427                return TCL_ERROR;
5428            }
5429            bytes = TclGetString(cmdPtr);
5430            if (bytes[0] != ':' || bytes[1] != ':') {
5431                Tcl_AppendResult(interp,
5432                        "ensemble target is not a fully-qualified command",
5433                        NULL);
5434                Tcl_DictObjDone(&search);
5435                return TCL_ERROR;
5436            }
5437        }
5438
5439        if (size < 1) {
5440            mapDict = NULL;
5441        }
5442    }
5443
5444    ensemblePtr = cmdPtr->objClientData;
5445    oldDict = ensemblePtr->subcommandDict;
5446    ensemblePtr->subcommandDict = mapDict;
5447    if (mapDict != NULL) {
5448        Tcl_IncrRefCount(mapDict);
5449    }
5450    if (oldDict != NULL) {
5451        TclDecrRefCount(oldDict);
5452    }
5453
5454    /*
5455     * Trigger an eventual recomputation of the ensemble command set. Note
5456     * that this is slightly tricky, as it means that we are not actually
5457     * counting the number of namespace export actions, but it is the simplest
5458     * way to go!
5459     */
5460
5461    ensemblePtr->nsPtr->exportLookupEpoch++;
5462
5463    /*
5464     * Special hack to make compiling of [info exists] work when the
5465     * dictionary is modified.
5466     */
5467
5468    if (cmdPtr->compileProc != NULL) {
5469        ((Interp *)interp)->compileEpoch++;
5470    }
5471
5472    return TCL_OK;
5473}
5474
5475/*
5476 *----------------------------------------------------------------------
5477 *
5478 * Tcl_SetEnsembleUnknownHandler --
5479 *
5480 *      Set the unknown handler for a particular ensemble.
5481 *
5482 * Results:
5483 *      Tcl result code (error if command token does not indicate an ensemble
5484 *      or the unknown handler - if non-NULL - is not a list).
5485 *
5486 * Side effects:
5487 *      The ensemble is updated and marked for recompilation.
5488 *
5489 *----------------------------------------------------------------------
5490 */
5491
5492int
5493Tcl_SetEnsembleUnknownHandler(
5494    Tcl_Interp *interp,
5495    Tcl_Command token,
5496    Tcl_Obj *unknownList)
5497{
5498    Command *cmdPtr = (Command *) token;
5499    EnsembleConfig *ensemblePtr;
5500    Tcl_Obj *oldList;
5501
5502    if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
5503        Tcl_AppendResult(interp, "command is not an ensemble", NULL);
5504        return TCL_ERROR;
5505    }
5506    if (unknownList != NULL) {
5507        int length;
5508
5509        if (TclListObjLength(interp, unknownList, &length) != TCL_OK) {
5510            return TCL_ERROR;
5511        }
5512        if (length < 1) {
5513            unknownList = NULL;
5514        }
5515    }
5516
5517    ensemblePtr = cmdPtr->objClientData;
5518    oldList = ensemblePtr->unknownHandler;
5519    ensemblePtr->unknownHandler = unknownList;
5520    if (unknownList != NULL) {
5521        Tcl_IncrRefCount(unknownList);
5522    }
5523    if (oldList != NULL) {
5524        TclDecrRefCount(oldList);
5525    }
5526
5527    /*
5528     * Trigger an eventual recomputation of the ensemble command set. Note
5529     * that this is slightly tricky, as it means that we are not actually
5530     * counting the number of namespace export actions, but it is the simplest
5531     * way to go!
5532     */
5533
5534    ensemblePtr->nsPtr->exportLookupEpoch++;
5535
5536    return TCL_OK;
5537}
5538
5539/*
5540 *----------------------------------------------------------------------
5541 *
5542 * Tcl_SetEnsembleFlags --
5543 *
5544 *      Set the flags for a particular ensemble.
5545 *
5546 * Results:
5547 *      Tcl result code (error if command token does not indicate an
5548 *      ensemble).
5549 *
5550 * Side effects:
5551 *      The ensemble is updated and marked for recompilation.
5552 *
5553 *----------------------------------------------------------------------
5554 */
5555
5556int
5557Tcl_SetEnsembleFlags(
5558    Tcl_Interp *interp,
5559    Tcl_Command token,
5560    int flags)
5561{
5562    Command *cmdPtr = (Command *) token;
5563    EnsembleConfig *ensemblePtr;
5564    int wasCompiled;
5565
5566    if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
5567        Tcl_AppendResult(interp, "command is not an ensemble", NULL);
5568        return TCL_ERROR;
5569    }
5570
5571    ensemblePtr = cmdPtr->objClientData;
5572    wasCompiled = ensemblePtr->flags & ENSEMBLE_COMPILE;
5573
5574    /*
5575     * This API refuses to set the ENS_DEAD flag...
5576     */
5577
5578    ensemblePtr->flags &= ENS_DEAD;
5579    ensemblePtr->flags |= flags & ~ENS_DEAD;
5580
5581    /*
5582     * Trigger an eventual recomputation of the ensemble command set. Note
5583     * that this is slightly tricky, as it means that we are not actually
5584     * counting the number of namespace export actions, but it is the simplest
5585     * way to go!
5586     */
5587
5588    ensemblePtr->nsPtr->exportLookupEpoch++;
5589
5590    /*
5591     * If the ENSEMBLE_COMPILE flag status was changed, install or remove the
5592     * compiler function and bump the interpreter's compilation epoch so that
5593     * bytecode gets regenerated.
5594     */
5595
5596    if (flags & ENSEMBLE_COMPILE) {
5597        if (!wasCompiled) {
5598            ((Command*) ensemblePtr->token)->compileProc = TclCompileEnsemble;
5599            ((Interp *) interp)->compileEpoch++;
5600        }
5601    } else {
5602        if (wasCompiled) {
5603            ((Command*) ensemblePtr->token)->compileProc = NULL;
5604            ((Interp *) interp)->compileEpoch++;
5605        }
5606    }
5607
5608    return TCL_OK;
5609}
5610
5611/*
5612 *----------------------------------------------------------------------
5613 *
5614 * Tcl_GetEnsembleSubcommandList --
5615 *
5616 *      Get the list of subcommands associated with a particular ensemble.
5617 *
5618 * Results:
5619 *      Tcl result code (error if command token does not indicate an
5620 *      ensemble). The list of subcommands is returned by updating the
5621 *      variable pointed to by the last parameter (NULL if this is to be
5622 *      derived from the mapping dictionary or the associated namespace's
5623 *      exported commands).
5624 *
5625 * Side effects:
5626 *      None
5627 *
5628 *----------------------------------------------------------------------
5629 */
5630
5631int
5632Tcl_GetEnsembleSubcommandList(
5633    Tcl_Interp *interp,
5634    Tcl_Command token,
5635    Tcl_Obj **subcmdListPtr)
5636{
5637    Command *cmdPtr = (Command *) token;
5638    EnsembleConfig *ensemblePtr;
5639
5640    if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
5641        if (interp != NULL) {
5642            Tcl_AppendResult(interp, "command is not an ensemble", NULL);
5643        }
5644        return TCL_ERROR;
5645    }
5646
5647    ensemblePtr = cmdPtr->objClientData;
5648    *subcmdListPtr = ensemblePtr->subcmdList;
5649    return TCL_OK;
5650}
5651
5652/*
5653 *----------------------------------------------------------------------
5654 *
5655 * Tcl_GetEnsembleMappingDict --
5656 *
5657 *      Get the command mapping dictionary associated with a particular
5658 *      ensemble.
5659 *
5660 * Results:
5661 *      Tcl result code (error if command token does not indicate an
5662 *      ensemble). The mapping dict is returned by updating the variable
5663 *      pointed to by the last parameter (NULL if none is installed).
5664 *
5665 * Side effects:
5666 *      None
5667 *
5668 *----------------------------------------------------------------------
5669 */
5670
5671int
5672Tcl_GetEnsembleMappingDict(
5673    Tcl_Interp *interp,
5674    Tcl_Command token,
5675    Tcl_Obj **mapDictPtr)
5676{
5677    Command *cmdPtr = (Command *) token;
5678    EnsembleConfig *ensemblePtr;
5679
5680    if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
5681        if (interp != NULL) {
5682            Tcl_AppendResult(interp, "command is not an ensemble", NULL);
5683        }
5684        return TCL_ERROR;
5685    }
5686
5687    ensemblePtr = cmdPtr->objClientData;
5688    *mapDictPtr = ensemblePtr->subcommandDict;
5689    return TCL_OK;
5690}
5691
5692/*
5693 *----------------------------------------------------------------------
5694 *
5695 * Tcl_GetEnsembleUnknownHandler --
5696 *
5697 *      Get the unknown handler associated with a particular ensemble.
5698 *
5699 * Results:
5700 *      Tcl result code (error if command token does not indicate an
5701 *      ensemble). The unknown handler is returned by updating the variable
5702 *      pointed to by the last parameter (NULL if no handler is installed).
5703 *
5704 * Side effects:
5705 *      None
5706 *
5707 *----------------------------------------------------------------------
5708 */
5709
5710int
5711Tcl_GetEnsembleUnknownHandler(
5712    Tcl_Interp *interp,
5713    Tcl_Command token,
5714    Tcl_Obj **unknownListPtr)
5715{
5716    Command *cmdPtr = (Command *) token;
5717    EnsembleConfig *ensemblePtr;
5718
5719    if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
5720        if (interp != NULL) {
5721            Tcl_AppendResult(interp, "command is not an ensemble", NULL);
5722        }
5723        return TCL_ERROR;
5724    }
5725
5726    ensemblePtr = cmdPtr->objClientData;
5727    *unknownListPtr = ensemblePtr->unknownHandler;
5728    return TCL_OK;
5729}
5730
5731/*
5732 *----------------------------------------------------------------------
5733 *
5734 * Tcl_GetEnsembleFlags --
5735 *
5736 *      Get the flags for a particular ensemble.
5737 *
5738 * Results:
5739 *      Tcl result code (error if command token does not indicate an
5740 *      ensemble). The flags are returned by updating the variable pointed to
5741 *      by the last parameter.
5742 *
5743 * Side effects:
5744 *      None
5745 *
5746 *----------------------------------------------------------------------
5747 */
5748
5749int
5750Tcl_GetEnsembleFlags(
5751    Tcl_Interp *interp,
5752    Tcl_Command token,
5753    int *flagsPtr)
5754{
5755    Command *cmdPtr = (Command *) token;
5756    EnsembleConfig *ensemblePtr;
5757
5758    if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
5759        if (interp != NULL) {
5760            Tcl_AppendResult(interp, "command is not an ensemble", NULL);
5761        }
5762        return TCL_ERROR;
5763    }
5764
5765    ensemblePtr = cmdPtr->objClientData;
5766    *flagsPtr = ensemblePtr->flags;
5767    return TCL_OK;
5768}
5769
5770/*
5771 *----------------------------------------------------------------------
5772 *
5773 * Tcl_GetEnsembleNamespace --
5774 *
5775 *      Get the namespace associated with a particular ensemble.
5776 *
5777 * Results:
5778 *      Tcl result code (error if command token does not indicate an
5779 *      ensemble). Namespace is returned by updating the variable pointed to
5780 *      by the last parameter.
5781 *
5782 * Side effects:
5783 *      None
5784 *
5785 *----------------------------------------------------------------------
5786 */
5787
5788int
5789Tcl_GetEnsembleNamespace(
5790    Tcl_Interp *interp,
5791    Tcl_Command token,
5792    Tcl_Namespace **namespacePtrPtr)
5793{
5794    Command *cmdPtr = (Command *) token;
5795    EnsembleConfig *ensemblePtr;
5796
5797    if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
5798        if (interp != NULL) {
5799            Tcl_AppendResult(interp, "command is not an ensemble", NULL);
5800        }
5801        return TCL_ERROR;
5802    }
5803
5804    ensemblePtr = cmdPtr->objClientData;
5805    *namespacePtrPtr = (Tcl_Namespace *) ensemblePtr->nsPtr;
5806    return TCL_OK;
5807}
5808
5809/*
5810 *----------------------------------------------------------------------
5811 *
5812 * Tcl_FindEnsemble --
5813 *
5814 *      Given a command name, get the ensemble token for it, allowing for
5815 *      [namespace import]s. [Bug 1017022]
5816 *
5817 * Results:
5818 *      The token for the ensemble command with the given name, or NULL if the
5819 *      command either does not exist or is not an ensemble (when an error
5820 *      message will be written into the interp if thats non-NULL).
5821 *
5822 * Side effects:
5823 *      None
5824 *
5825 *----------------------------------------------------------------------
5826 */
5827
5828Tcl_Command
5829Tcl_FindEnsemble(
5830    Tcl_Interp *interp,         /* Where to do the lookup, and where to write
5831                                 * the errors if TCL_LEAVE_ERR_MSG is set in
5832                                 * the flags. */
5833    Tcl_Obj *cmdNameObj,        /* Name of command to look up. */
5834    int flags)                  /* Either 0 or TCL_LEAVE_ERR_MSG; other flags
5835                                 * are probably not useful. */
5836{
5837    Command *cmdPtr;
5838
5839    cmdPtr = (Command *)
5840            Tcl_FindCommand(interp, TclGetString(cmdNameObj), NULL, flags);
5841    if (cmdPtr == NULL) {
5842        return NULL;
5843    }
5844
5845    if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
5846        /*
5847         * Reuse existing infrastructure for following import link chains
5848         * rather than duplicating it.
5849         */
5850
5851        cmdPtr = (Command *) TclGetOriginalCommand((Tcl_Command) cmdPtr);
5852
5853        if (cmdPtr == NULL || cmdPtr->objProc != NsEnsembleImplementationCmd) {
5854            if (flags & TCL_LEAVE_ERR_MSG) {
5855                Tcl_AppendResult(interp, "\"", TclGetString(cmdNameObj),
5856                        "\" is not an ensemble command", NULL);
5857                Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENSEMBLE",
5858                        TclGetString(cmdNameObj), NULL);
5859            }
5860            return NULL;
5861        }
5862    }
5863
5864    return (Tcl_Command) cmdPtr;
5865}
5866
5867/*
5868 *----------------------------------------------------------------------
5869 *
5870 * Tcl_IsEnsemble --
5871 *
5872 *      Simple test for ensemble-hood that takes into account imported
5873 *      ensemble commands as well.
5874 *
5875 * Results:
5876 *      Boolean value
5877 *
5878 * Side effects:
5879 *      None
5880 *
5881 *----------------------------------------------------------------------
5882 */
5883
5884int
5885Tcl_IsEnsemble(
5886    Tcl_Command token)
5887{
5888    Command *cmdPtr = (Command *) token;
5889    if (cmdPtr->objProc == NsEnsembleImplementationCmd) {
5890        return 1;
5891    }
5892    cmdPtr = (Command *) TclGetOriginalCommand((Tcl_Command) cmdPtr);
5893    if (cmdPtr == NULL || cmdPtr->objProc != NsEnsembleImplementationCmd) {
5894        return 0;
5895    }
5896    return 1;
5897}
5898
5899/*
5900 *----------------------------------------------------------------------
5901 *
5902 * TclMakeEnsemble --
5903 *
5904 *      Create an ensemble from a table of implementation commands. The
5905 *      ensemble will be subject to (limited) compilation if any of the
5906 *      implementation commands are compilable.
5907 *
5908 * Results:
5909 *      Handle for the ensemble, or NULL if creation of it fails.
5910 *
5911 * Side effects:
5912 *      May advance bytecode compilation epoch.
5913 *
5914 *----------------------------------------------------------------------
5915 */
5916
5917Tcl_Command
5918TclMakeEnsemble(
5919    Tcl_Interp *interp,
5920    const char *name,
5921    const EnsembleImplMap map[])
5922{
5923    Tcl_Command ensemble;       /* The overall ensemble. */
5924    Tcl_Namespace *tclNsPtr;    /* Reference to the "::tcl" namespace. */
5925    Tcl_DString buf;
5926
5927    tclNsPtr = Tcl_FindNamespace(interp, "::tcl", NULL,
5928            TCL_CREATE_NS_IF_UNKNOWN);
5929    if (tclNsPtr == NULL) {
5930        Tcl_Panic("unable to find or create ::tcl namespace!");
5931    }
5932    Tcl_DStringInit(&buf);
5933    Tcl_DStringAppend(&buf, "::tcl::", -1);
5934    Tcl_DStringAppend(&buf, name, -1);
5935    tclNsPtr = Tcl_FindNamespace(interp, Tcl_DStringValue(&buf), NULL,
5936            TCL_CREATE_NS_IF_UNKNOWN);
5937    if (tclNsPtr == NULL) {
5938        Tcl_Panic("unable to find or create %s namespace!",
5939                Tcl_DStringValue(&buf));
5940    }
5941    ensemble = Tcl_CreateEnsemble(interp, Tcl_DStringValue(&buf)+5, tclNsPtr,
5942            TCL_ENSEMBLE_PREFIX);
5943    Tcl_DStringAppend(&buf, "::", -1);
5944    if (ensemble != NULL) {
5945        Tcl_Obj *mapDict;
5946        int i, compile = 0;
5947
5948        TclNewObj(mapDict);
5949        for (i=0 ; map[i].name != NULL ; i++) {
5950            Tcl_Obj *fromObj, *toObj;
5951            Command *cmdPtr;
5952
5953            fromObj = Tcl_NewStringObj(map[i].name, -1);
5954            TclNewStringObj(toObj, Tcl_DStringValue(&buf),
5955                    Tcl_DStringLength(&buf));
5956            Tcl_AppendToObj(toObj, map[i].name, -1);
5957            Tcl_DictObjPut(NULL, mapDict, fromObj, toObj);
5958            cmdPtr = (Command *) Tcl_CreateObjCommand(interp,
5959                    TclGetString(toObj), map[i].proc, NULL, NULL);
5960            cmdPtr->compileProc = map[i].compileProc;
5961            compile |= (map[i].compileProc != NULL);
5962        }
5963        Tcl_SetEnsembleMappingDict(interp, ensemble, mapDict);
5964        if (compile) {
5965            Tcl_SetEnsembleFlags(interp, ensemble,
5966                    TCL_ENSEMBLE_PREFIX | ENSEMBLE_COMPILE);
5967        }
5968    }
5969    Tcl_DStringFree(&buf);
5970
5971    return ensemble;
5972}
5973
5974/*
5975 *----------------------------------------------------------------------
5976 *
5977 * NsEnsembleImplementationCmd --
5978 *
5979 *      Implements an ensemble of commands (being those exported by a
5980 *      namespace other than the global namespace) as a command with the same
5981 *      (short) name as the namespace in the parent namespace.
5982 *
5983 * Results:
5984 *      A standard Tcl result code. Will be TCL_ERROR if the command is not an
5985 *      unambiguous prefix of any command exported by the ensemble's
5986 *      namespace.
5987 *
5988 * Side effects:
5989 *      Depends on the command within the namespace that gets executed. If the
5990 *      ensemble itself returns TCL_ERROR, a descriptive error message will be
5991 *      placed in the interpreter's result.
5992 *
5993 *----------------------------------------------------------------------
5994 */
5995
5996static int
5997NsEnsembleImplementationCmd(
5998    ClientData clientData,
5999    Tcl_Interp *interp,
6000    int objc,
6001    Tcl_Obj *const objv[])
6002{
6003    EnsembleConfig *ensemblePtr = clientData;
6004                                /* The ensemble itself. */
6005    Tcl_Obj **tempObjv;         /* Space used to construct the list of
6006                                 * arguments to pass to the command that
6007                                 * implements the ensemble subcommand. */
6008    int result;                 /* The result of the subcommand execution. */
6009    Tcl_Obj *prefixObj;         /* An object containing the prefix words of
6010                                 * the command that implements the
6011                                 * subcommand. */
6012    Tcl_HashEntry *hPtr;        /* Used for efficient lookup of fully
6013                                 * specified but not yet cached command
6014                                 * names. */
6015    Tcl_Obj **prefixObjv;       /* The list of objects to substitute in as the
6016                                 * target command prefix. */
6017    int prefixObjc;             /* Size of prefixObjv of course! */
6018    int reparseCount = 0;       /* Number of reparses. */
6019
6020    if (objc < 2) {
6021        Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?argument ...?");
6022        return TCL_ERROR;
6023    }
6024
6025  restartEnsembleParse:
6026    if (ensemblePtr->nsPtr->flags & NS_DYING) {
6027        /*
6028         * Don't know how we got here, but make things give up quickly.
6029         */
6030
6031        if (!Tcl_InterpDeleted(interp)) {
6032            Tcl_AppendResult(interp,
6033                    "ensemble activated for deleted namespace", NULL);
6034        }
6035        return TCL_ERROR;
6036    }
6037
6038    /*
6039     * Determine if the table of subcommands is right. If so, we can just look
6040     * up in there and go straight to dispatch.
6041     */
6042
6043    if (ensemblePtr->epoch == ensemblePtr->nsPtr->exportLookupEpoch) {
6044        /*
6045         * Table of subcommands is still valid; therefore there might be a
6046         * valid cache of discovered information which we can reuse. Do the
6047         * check here, and if we're still valid, we can jump straight to the
6048         * part where we do the invocation of the subcommand.
6049         */
6050
6051        if (objv[1]->typePtr == &tclEnsembleCmdType) {
6052            EnsembleCmdRep *ensembleCmd = objv[1]->internalRep.otherValuePtr;
6053
6054            if (ensembleCmd->nsPtr == ensemblePtr->nsPtr &&
6055                    ensembleCmd->epoch == ensemblePtr->epoch &&
6056                    ensembleCmd->token == ensemblePtr->token) {
6057                prefixObj = ensembleCmd->realPrefixObj;
6058                Tcl_IncrRefCount(prefixObj);
6059                goto runResultingSubcommand;
6060            }
6061        }
6062    } else {
6063        BuildEnsembleConfig(ensemblePtr);
6064        ensemblePtr->epoch = ensemblePtr->nsPtr->exportLookupEpoch;
6065    }
6066
6067    /*
6068     * Look in the hashtable for the subcommand name; this is the fastest way
6069     * of all.
6070     */
6071
6072    hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable,
6073            TclGetString(objv[1]));
6074    if (hPtr != NULL) {
6075        char *fullName = Tcl_GetHashKey(&ensemblePtr->subcommandTable, hPtr);
6076
6077        prefixObj = Tcl_GetHashValue(hPtr);
6078
6079        /*
6080         * Cache for later in the subcommand object.
6081         */
6082
6083        MakeCachedEnsembleCommand(objv[1], ensemblePtr, fullName, prefixObj);
6084    } else if (!(ensemblePtr->flags & TCL_ENSEMBLE_PREFIX)) {
6085        /*
6086         * Could not map, no prefixing, go to unknown/error handling.
6087         */
6088
6089        goto unknownOrAmbiguousSubcommand;
6090    } else {
6091        /*
6092         * If we've not already confirmed the command with the hash as part of
6093         * building our export table, we need to scan the sorted array for
6094         * matches.
6095         */
6096
6097        char *subcmdName;       /* Name of the subcommand, or unique prefix of
6098                                 * it (will be an error for a non-unique
6099                                 * prefix). */
6100        char *fullName = NULL;  /* Full name of the subcommand. */
6101        int stringLength, i;
6102        int tableLength = ensemblePtr->subcommandTable.numEntries;
6103
6104        subcmdName = TclGetString(objv[1]);
6105        stringLength = objv[1]->length;
6106        for (i=0 ; i<tableLength ; i++) {
6107            register int cmp = strncmp(subcmdName,
6108                    ensemblePtr->subcommandArrayPtr[i],
6109                    (unsigned) stringLength);
6110
6111            if (cmp == 0) {
6112                if (fullName != NULL) {
6113                    /*
6114                     * Since there's never the exact-match case to worry about
6115                     * (hash search filters this), getting here indicates that
6116                     * our subcommand is an ambiguous prefix of (at least) two
6117                     * exported subcommands, which is an error case.
6118                     */
6119
6120                    goto unknownOrAmbiguousSubcommand;
6121                }
6122                fullName = ensemblePtr->subcommandArrayPtr[i];
6123            } else if (cmp < 0) {
6124                /*
6125                 * Because we are searching a sorted table, we can now stop
6126                 * searching because we have gone past anything that could
6127                 * possibly match.
6128                 */
6129
6130                break;
6131            }
6132        }
6133        if (fullName == NULL) {
6134            /*
6135             * The subcommand is not a prefix of anything, so bail out!
6136             */
6137
6138            goto unknownOrAmbiguousSubcommand;
6139        }
6140        hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable, fullName);
6141        if (hPtr == NULL) {
6142            Tcl_Panic("full name %s not found in supposedly synchronized hash",
6143                    fullName);
6144        }
6145        prefixObj = Tcl_GetHashValue(hPtr);
6146
6147        /*
6148         * Cache for later in the subcommand object.
6149         */
6150
6151        MakeCachedEnsembleCommand(objv[1], ensemblePtr, fullName, prefixObj);
6152    }
6153
6154    Tcl_IncrRefCount(prefixObj);
6155  runResultingSubcommand:
6156
6157    /*
6158     * Do the real work of execution of the subcommand by building an array of
6159     * objects (note that this is potentially not the same length as the
6160     * number of arguments to this ensemble command), populating it and then
6161     * feeding it back through the main command-lookup engine. In theory, we
6162     * could look up the command in the namespace ourselves, as we already
6163     * have the namespace in which it is guaranteed to exist, but we don't do
6164     * that (the cacheing of the command object used should help with that.)
6165     */
6166
6167    {
6168        Interp *iPtr = (Interp *) interp;
6169        int isRootEnsemble;
6170        Tcl_Obj *copyObj;
6171
6172        /*
6173         * Get the prefix that we're rewriting to. To do this we need to
6174         * ensure that the internal representation of the list does not change
6175         * so that we can safely keep the internal representations of the
6176         * elements in the list.
6177         */
6178
6179        copyObj = TclListObjCopy(NULL, prefixObj);
6180        TclListObjGetElements(NULL, copyObj, &prefixObjc, &prefixObjv);
6181
6182        /*
6183         * Record what arguments the script sent in so that things like
6184         * Tcl_WrongNumArgs can give the correct error message.
6185         */
6186
6187        isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL);
6188        if (isRootEnsemble) {
6189            iPtr->ensembleRewrite.sourceObjs = objv;
6190            iPtr->ensembleRewrite.numRemovedObjs = 2;
6191            iPtr->ensembleRewrite.numInsertedObjs = prefixObjc;
6192        } else {
6193            int ni = iPtr->ensembleRewrite.numInsertedObjs;
6194
6195            if (ni < 2) {
6196                iPtr->ensembleRewrite.numRemovedObjs += 2 - ni;
6197                iPtr->ensembleRewrite.numInsertedObjs += prefixObjc-1;
6198            } else {
6199                iPtr->ensembleRewrite.numInsertedObjs += prefixObjc-2;
6200            }
6201        }
6202
6203        /*
6204         * Allocate a workspace and build the list of arguments to pass to the
6205         * target command in it.
6206         */
6207
6208        tempObjv = (Tcl_Obj **) TclStackAlloc(interp,
6209                (int) sizeof(Tcl_Obj *) * (objc - 2 + prefixObjc));
6210        memcpy(tempObjv, prefixObjv, sizeof(Tcl_Obj *) * prefixObjc);
6211        memcpy(tempObjv+prefixObjc, objv+2, sizeof(Tcl_Obj *) * (objc-2));
6212
6213        /*
6214         * Hand off to the target command.
6215         */
6216
6217        result = Tcl_EvalObjv(interp, objc-2+prefixObjc, tempObjv,
6218                TCL_EVAL_INVOKE);
6219
6220        /*
6221         * Clean up.
6222         */
6223
6224        TclStackFree(interp, tempObjv);
6225        Tcl_DecrRefCount(copyObj);
6226        if (isRootEnsemble) {
6227            iPtr->ensembleRewrite.sourceObjs = NULL;
6228            iPtr->ensembleRewrite.numRemovedObjs = 0;
6229            iPtr->ensembleRewrite.numInsertedObjs = 0;
6230        }
6231    }
6232    Tcl_DecrRefCount(prefixObj);
6233    return result;
6234
6235  unknownOrAmbiguousSubcommand:
6236    /*
6237     * Have not been able to match the subcommand asked for with a real
6238     * subcommand that we export. See whether a handler has been registered
6239     * for dealing with this situation. Will only call (at most) once for any
6240     * particular ensemble invocation.
6241     */
6242
6243    if (ensemblePtr->unknownHandler != NULL && reparseCount++ < 1) {
6244        int paramc, i;
6245        Tcl_Obj **paramv, *unknownCmd, *ensObj;
6246
6247        unknownCmd = Tcl_DuplicateObj(ensemblePtr->unknownHandler);
6248        TclNewObj(ensObj);
6249        Tcl_GetCommandFullName(interp, ensemblePtr->token, ensObj);
6250        Tcl_ListObjAppendElement(NULL, unknownCmd, ensObj);
6251        for (i=1 ; i<objc ; i++) {
6252            Tcl_ListObjAppendElement(NULL, unknownCmd, objv[i]);
6253        }
6254        TclListObjGetElements(NULL, unknownCmd, &paramc, &paramv);
6255        Tcl_Preserve(ensemblePtr);
6256        Tcl_IncrRefCount(unknownCmd);
6257        result = Tcl_EvalObjv(interp, paramc, paramv, 0);
6258        if (result == TCL_OK) {
6259            prefixObj = Tcl_GetObjResult(interp);
6260            Tcl_IncrRefCount(prefixObj);
6261            Tcl_DecrRefCount(unknownCmd);
6262            Tcl_Release(ensemblePtr);
6263            Tcl_ResetResult(interp);
6264            if (ensemblePtr->flags & ENS_DEAD) {
6265                Tcl_DecrRefCount(prefixObj);
6266                Tcl_SetResult(interp,
6267                        "unknown subcommand handler deleted its ensemble",
6268                        TCL_STATIC);
6269                return TCL_ERROR;
6270            }
6271
6272            /*
6273             * Namespace is still there. Check if the result is a valid list.
6274             * If it is, and it is non-empty, that list is what we are using
6275             * as our replacement.
6276             */
6277
6278            if (TclListObjLength(interp, prefixObj, &prefixObjc) != TCL_OK) {
6279                Tcl_DecrRefCount(prefixObj);
6280                Tcl_AddErrorInfo(interp, "\n    while parsing result of "
6281                        "ensemble unknown subcommand handler");
6282                return TCL_ERROR;
6283            }
6284            if (prefixObjc > 0) {
6285                goto runResultingSubcommand;
6286            }
6287
6288            /*
6289             * Namespace alive & empty result => reparse.
6290             */
6291
6292            Tcl_DecrRefCount(prefixObj);
6293            goto restartEnsembleParse;
6294        }
6295        if (!Tcl_InterpDeleted(interp)) {
6296            if (result != TCL_ERROR) {
6297                char buf[TCL_INTEGER_SPACE];
6298
6299                Tcl_ResetResult(interp);
6300                Tcl_SetResult(interp,
6301                        "unknown subcommand handler returned bad code: ",
6302                        TCL_STATIC);
6303                switch (result) {
6304                case TCL_RETURN:
6305                    Tcl_AppendResult(interp, "return", NULL);
6306                    break;
6307                case TCL_BREAK:
6308                    Tcl_AppendResult(interp, "break", NULL);
6309                    break;
6310                case TCL_CONTINUE:
6311                    Tcl_AppendResult(interp, "continue", NULL);
6312                    break;
6313                default:
6314                    sprintf(buf, "%d", result);
6315                    Tcl_AppendResult(interp, buf, NULL);
6316                }
6317                Tcl_AddErrorInfo(interp, "\n    result of "
6318                        "ensemble unknown subcommand handler: ");
6319                Tcl_AddErrorInfo(interp, TclGetString(unknownCmd));
6320            } else {
6321                Tcl_AddErrorInfo(interp,
6322                        "\n    (ensemble unknown subcommand handler)");
6323            }
6324        }
6325        Tcl_DecrRefCount(unknownCmd);
6326        Tcl_Release(ensemblePtr);
6327        return TCL_ERROR;
6328    }
6329
6330    /*
6331     * We cannot determine what subcommand to hand off to, so generate a
6332     * (standard) failure message. Note the one odd case compared with
6333     * standard ensemble-like command, which is where a namespace has no
6334     * exported commands at all...
6335     */
6336
6337    Tcl_ResetResult(interp);
6338    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENSEMBLE",
6339            TclGetString(objv[1]), NULL);
6340    if (ensemblePtr->subcommandTable.numEntries == 0) {
6341        Tcl_AppendResult(interp, "unknown subcommand \"",TclGetString(objv[1]),
6342                "\": namespace ", ensemblePtr->nsPtr->fullName,
6343                " does not export any commands", NULL);
6344        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "SUBCOMMAND",
6345                TclGetString(objv[1]), NULL);
6346        return TCL_ERROR;
6347    }
6348    Tcl_AppendResult(interp, "unknown ",
6349            (ensemblePtr->flags & TCL_ENSEMBLE_PREFIX ? "or ambiguous " : ""),
6350            "subcommand \"", TclGetString(objv[1]), "\": must be ", NULL);
6351    if (ensemblePtr->subcommandTable.numEntries == 1) {
6352        Tcl_AppendResult(interp, ensemblePtr->subcommandArrayPtr[0], NULL);
6353    } else {
6354        int i;
6355
6356        for (i=0 ; i<ensemblePtr->subcommandTable.numEntries-1 ; i++) {
6357            Tcl_AppendResult(interp,
6358                    ensemblePtr->subcommandArrayPtr[i], ", ", NULL);
6359        }
6360        Tcl_AppendResult(interp, "or ",
6361                ensemblePtr->subcommandArrayPtr[i], NULL);
6362    }
6363    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "SUBCOMMAND",
6364            TclGetString(objv[1]), NULL);
6365    return TCL_ERROR;
6366}
6367
6368/*
6369 *----------------------------------------------------------------------
6370 *
6371 * MakeCachedEnsembleCommand --
6372 *
6373 *      Cache what we've computed so far; it's not nice to repeatedly copy
6374 *      strings about. Note that to do this, we start by deleting any old
6375 *      representation that there was (though if it was an out of date
6376 *      ensemble rep, we can skip some of the deallocation process.)
6377 *
6378 * Results:
6379 *      None
6380 *
6381 * Side effects:
6382 *      Alters the internal representation of the first object parameter.
6383 *
6384 *----------------------------------------------------------------------
6385 */
6386
6387static void
6388MakeCachedEnsembleCommand(
6389    Tcl_Obj *objPtr,
6390    EnsembleConfig *ensemblePtr,
6391    const char *subcommandName,
6392    Tcl_Obj *prefixObjPtr)
6393{
6394    register EnsembleCmdRep *ensembleCmd;
6395    int length;
6396
6397    if (objPtr->typePtr == &tclEnsembleCmdType) {
6398        ensembleCmd = objPtr->internalRep.otherValuePtr;
6399        Tcl_DecrRefCount(ensembleCmd->realPrefixObj);
6400        ensembleCmd->nsPtr->refCount--;
6401        if ((ensembleCmd->nsPtr->refCount == 0)
6402                && (ensembleCmd->nsPtr->flags & NS_DEAD)) {
6403            NamespaceFree(ensembleCmd->nsPtr);
6404        }
6405        ckfree(ensembleCmd->fullSubcmdName);
6406    } else {
6407        /*
6408         * Kill the old internal rep, and replace it with a brand new one of
6409         * our own.
6410         */
6411
6412        TclFreeIntRep(objPtr);
6413        ensembleCmd = (EnsembleCmdRep *) ckalloc(sizeof(EnsembleCmdRep));
6414        objPtr->internalRep.otherValuePtr = ensembleCmd;
6415        objPtr->typePtr = &tclEnsembleCmdType;
6416    }
6417
6418    /*
6419     * Populate the internal rep.
6420     */
6421
6422    ensembleCmd->nsPtr = ensemblePtr->nsPtr;
6423    ensembleCmd->epoch = ensemblePtr->epoch;
6424    ensembleCmd->token = ensemblePtr->token;
6425    ensemblePtr->nsPtr->refCount++;
6426    ensembleCmd->realPrefixObj = prefixObjPtr;
6427    length = strlen(subcommandName)+1;
6428    ensembleCmd->fullSubcmdName = ckalloc((unsigned) length);
6429    memcpy(ensembleCmd->fullSubcmdName, subcommandName, (unsigned) length);
6430    Tcl_IncrRefCount(ensembleCmd->realPrefixObj);
6431}
6432
6433/*
6434 *----------------------------------------------------------------------
6435 *
6436 * DeleteEnsembleConfig --
6437 *
6438 *      Destroys the data structure used to represent an ensemble. This is
6439 *      called when the ensemble's command is deleted (which happens
6440 *      automatically if the ensemble's namespace is deleted.) Maintainers
6441 *      should note that ensembles should be deleted by deleting their
6442 *      commands.
6443 *
6444 * Results:
6445 *      None.
6446 *
6447 * Side effects:
6448 *      Memory is (eventually) deallocated.
6449 *
6450 *----------------------------------------------------------------------
6451 */
6452
6453static void
6454DeleteEnsembleConfig(
6455    ClientData clientData)
6456{
6457    EnsembleConfig *ensemblePtr = clientData;
6458    Namespace *nsPtr = ensemblePtr->nsPtr;
6459    Tcl_HashSearch search;
6460    Tcl_HashEntry *hEnt;
6461
6462    /*
6463     * Unlink from the ensemble chain if it has not been marked as having been
6464     * done already.
6465     */
6466
6467    if (ensemblePtr->next != ensemblePtr) {
6468        EnsembleConfig *ensPtr = (EnsembleConfig *) nsPtr->ensembles;
6469        if (ensPtr == ensemblePtr) {
6470            nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr->next;
6471        } else {
6472            while (ensPtr != NULL) {
6473                if (ensPtr->next == ensemblePtr) {
6474                    ensPtr->next = ensemblePtr->next;
6475                    break;
6476                }
6477                ensPtr = ensPtr->next;
6478            }
6479        }
6480    }
6481
6482    /*
6483     * Mark the namespace as dead so code that uses Tcl_Preserve() can tell
6484     * whether disaster happened anyway.
6485     */
6486
6487    ensemblePtr->flags |= ENS_DEAD;
6488
6489    /*
6490     * Kill the pointer-containing fields.
6491     */
6492
6493    if (ensemblePtr->subcommandTable.numEntries != 0) {
6494        ckfree((char *) ensemblePtr->subcommandArrayPtr);
6495    }
6496    hEnt = Tcl_FirstHashEntry(&ensemblePtr->subcommandTable, &search);
6497    while (hEnt != NULL) {
6498        Tcl_Obj *prefixObj = Tcl_GetHashValue(hEnt);
6499
6500        Tcl_DecrRefCount(prefixObj);
6501        hEnt = Tcl_NextHashEntry(&search);
6502    }
6503    Tcl_DeleteHashTable(&ensemblePtr->subcommandTable);
6504    if (ensemblePtr->subcmdList != NULL) {
6505        Tcl_DecrRefCount(ensemblePtr->subcmdList);
6506    }
6507    if (ensemblePtr->subcommandDict != NULL) {
6508        Tcl_DecrRefCount(ensemblePtr->subcommandDict);
6509    }
6510    if (ensemblePtr->unknownHandler != NULL) {
6511        Tcl_DecrRefCount(ensemblePtr->unknownHandler);
6512    }
6513
6514    /*
6515     * Arrange for the structure to be reclaimed. Note that this is complex
6516     * because we have to make sure that we can react sensibly when an
6517     * ensemble is deleted during the process of initialising the ensemble
6518     * (especially the unknown callback.)
6519     */
6520
6521    Tcl_EventuallyFree(ensemblePtr, TCL_DYNAMIC);
6522}
6523
6524/*
6525 *----------------------------------------------------------------------
6526 *
6527 * BuildEnsembleConfig --
6528 *
6529 *      Create the internal data structures that describe how an ensemble
6530 *      looks, being a hash mapping from the full command name to the Tcl list
6531 *      that describes the implementation prefix words, and a sorted array of
6532 *      all the full command names to allow for reasonably efficient
6533 *      unambiguous prefix handling.
6534 *
6535 * Results:
6536 *      None.
6537 *
6538 * Side effects:
6539 *      Reallocates and rebuilds the hash table and array stored at the
6540 *      ensemblePtr argument. For large ensembles or large namespaces, this is
6541 *      a potentially expensive operation.
6542 *
6543 *----------------------------------------------------------------------
6544 */
6545
6546static void
6547BuildEnsembleConfig(
6548    EnsembleConfig *ensemblePtr)
6549{
6550    Tcl_HashSearch search;      /* Used for scanning the set of commands in
6551                                 * the namespace that backs up this
6552                                 * ensemble. */
6553    int i, j, isNew;
6554    Tcl_HashTable *hash = &ensemblePtr->subcommandTable;
6555    Tcl_HashEntry *hPtr;
6556
6557    if (hash->numEntries != 0) {
6558        /*
6559         * Remove pre-existing table.
6560         */
6561
6562        Tcl_HashSearch search;
6563
6564        ckfree((char *) ensemblePtr->subcommandArrayPtr);
6565        hPtr = Tcl_FirstHashEntry(hash, &search);
6566        while (hPtr != NULL) {
6567            Tcl_Obj *prefixObj = Tcl_GetHashValue(hPtr);
6568            Tcl_DecrRefCount(prefixObj);
6569            hPtr = Tcl_NextHashEntry(&search);
6570        }
6571        Tcl_DeleteHashTable(hash);
6572        Tcl_InitHashTable(hash, TCL_STRING_KEYS);
6573    }
6574
6575    /*
6576     * See if we've got an export list. If so, we will only export exactly
6577     * those commands, which may be either implemented by the prefix in the
6578     * subcommandDict or mapped directly onto the namespace's commands.
6579     */
6580
6581    if (ensemblePtr->subcmdList != NULL) {
6582        Tcl_Obj **subcmdv, *target, *cmdObj, *cmdPrefixObj;
6583        int subcmdc;
6584
6585        TclListObjGetElements(NULL, ensemblePtr->subcmdList, &subcmdc,
6586                &subcmdv);
6587        for (i=0 ; i<subcmdc ; i++) {
6588            char *name = TclGetString(subcmdv[i]);
6589
6590            hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
6591
6592            /*
6593             * Skip non-unique cases.
6594             */
6595
6596            if (!isNew) {
6597                continue;
6598            }
6599
6600            /*
6601             * Look in our dictionary (if present) for the command.
6602             */
6603
6604            if (ensemblePtr->subcommandDict != NULL) {
6605                Tcl_DictObjGet(NULL, ensemblePtr->subcommandDict, subcmdv[i],
6606                        &target);
6607                if (target != NULL) {
6608                    Tcl_SetHashValue(hPtr, target);
6609                    Tcl_IncrRefCount(target);
6610                    continue;
6611                }
6612            }
6613
6614            /*
6615             * Not there, so map onto the namespace. Note in this case that we
6616             * do not guarantee that the command is actually there; that is
6617             * the programmer's responsibility (or [::unknown] of course).
6618             */
6619
6620            cmdObj = Tcl_NewStringObj(ensemblePtr->nsPtr->fullName, -1);
6621            if (ensemblePtr->nsPtr->parentPtr != NULL) {
6622                Tcl_AppendStringsToObj(cmdObj, "::", name, NULL);
6623            } else {
6624                Tcl_AppendStringsToObj(cmdObj, name, NULL);
6625            }
6626            cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
6627            Tcl_SetHashValue(hPtr, cmdPrefixObj);
6628            Tcl_IncrRefCount(cmdPrefixObj);
6629        }
6630    } else if (ensemblePtr->subcommandDict != NULL) {
6631        /*
6632         * No subcmd list, but we do have a mapping dictionary so we should
6633         * use the keys of that. Convert the dictionary's contents into the
6634         * form required for the ensemble's internal hashtable.
6635         */
6636
6637        Tcl_DictSearch dictSearch;
6638        Tcl_Obj *keyObj, *valueObj;
6639        int done;
6640
6641        Tcl_DictObjFirst(NULL, ensemblePtr->subcommandDict, &dictSearch,
6642                &keyObj, &valueObj, &done);
6643        while (!done) {
6644            char *name = TclGetString(keyObj);
6645
6646            hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
6647            Tcl_SetHashValue(hPtr, valueObj);
6648            Tcl_IncrRefCount(valueObj);
6649            Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
6650        }
6651    } else {
6652        /*
6653         * Discover what commands are actually exported by the namespace.
6654         * What we have is an array of patterns and a hash table whose keys
6655         * are the command names exported by the namespace (the contents do
6656         * not matter here.) We must find out what commands are actually
6657         * exported by filtering each command in the namespace against each of
6658         * the patterns in the export list. Note that we use an intermediate
6659         * hash table to make memory management easier, and because that makes
6660         * exact matching far easier too.
6661         *
6662         * Suggestion for future enhancement: compute the unique prefixes and
6663         * place them in the hash too, which should make for even faster
6664         * matching.
6665         */
6666
6667        hPtr = Tcl_FirstHashEntry(&ensemblePtr->nsPtr->cmdTable, &search);
6668        for (; hPtr!= NULL ; hPtr=Tcl_NextHashEntry(&search)) {
6669            char *nsCmdName =           /* Name of command in namespace. */
6670                    Tcl_GetHashKey(&ensemblePtr->nsPtr->cmdTable, hPtr);
6671
6672            for (i=0 ; i<ensemblePtr->nsPtr->numExportPatterns ; i++) {
6673                if (Tcl_StringMatch(nsCmdName,
6674                        ensemblePtr->nsPtr->exportArrayPtr[i])) {
6675                    hPtr = Tcl_CreateHashEntry(hash, nsCmdName, &isNew);
6676
6677                    /*
6678                     * Remember, hash entries have a full reference to the
6679                     * substituted part of the command (as a list) as their
6680                     * content!
6681                     */
6682
6683                    if (isNew) {
6684                        Tcl_Obj *cmdObj, *cmdPrefixObj;
6685
6686                        TclNewObj(cmdObj);
6687                        Tcl_AppendStringsToObj(cmdObj,
6688                                ensemblePtr->nsPtr->fullName,
6689                                (ensemblePtr->nsPtr->parentPtr ? "::" : ""),
6690                                nsCmdName, NULL);
6691                        cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
6692                        Tcl_SetHashValue(hPtr, cmdPrefixObj);
6693                        Tcl_IncrRefCount(cmdPrefixObj);
6694                    }
6695                    break;
6696                }
6697            }
6698        }
6699    }
6700
6701    if (hash->numEntries == 0) {
6702        ensemblePtr->subcommandArrayPtr = NULL;
6703        return;
6704    }
6705
6706    /*
6707     * Create a sorted array of all subcommands in the ensemble; hash tables
6708     * are all very well for a quick look for an exact match, but they can't
6709     * determine things like whether a string is a prefix of another (not
6710     * without lots of preparation anyway) and they're no good for when we're
6711     * generating the error message either.
6712     *
6713     * We do this by filling an array with the names (we use the hash keys
6714     * directly to save a copy, since any time we change the array we change
6715     * the hash too, and vice versa) and running quicksort over the array.
6716     */
6717
6718    ensemblePtr->subcommandArrayPtr = (char **)
6719            ckalloc(sizeof(char *) * hash->numEntries);
6720
6721    /*
6722     * Fill array from both ends as this makes us less likely to end up with
6723     * performance problems in qsort(), which is good. Note that doing this
6724     * makes this code much more opaque, but the naive alternatve:
6725     *
6726     * for (hPtr=Tcl_FirstHashEntry(hash,&search),i=0 ;
6727     *         hPtr!=NULL ; hPtr=Tcl_NextHashEntry(&search),i++) {
6728     *     ensemblePtr->subcommandArrayPtr[i] = Tcl_GetHashKey(hash, &hPtr);
6729     * }
6730     *
6731     * can produce long runs of precisely ordered table entries when the
6732     * commands in the namespace are declared in a sorted fashion (an ordering
6733     * some people like) and the hashing functions (or the command names
6734     * themselves) are fairly unfortunate. By filling from both ends, it
6735     * requires active malice (and probably a debugger) to get qsort() to have
6736     * awful runtime behaviour.
6737     */
6738
6739    i = 0;
6740    j = hash->numEntries;
6741    hPtr = Tcl_FirstHashEntry(hash, &search);
6742    while (hPtr != NULL) {
6743        ensemblePtr->subcommandArrayPtr[i++] = Tcl_GetHashKey(hash, hPtr);
6744        hPtr = Tcl_NextHashEntry(&search);
6745        if (hPtr == NULL) {
6746            break;
6747        }
6748        ensemblePtr->subcommandArrayPtr[--j] = Tcl_GetHashKey(hash, hPtr);
6749        hPtr = Tcl_NextHashEntry(&search);
6750    }
6751    if (hash->numEntries > 1) {
6752        qsort(ensemblePtr->subcommandArrayPtr, (unsigned)hash->numEntries,
6753                sizeof(char *), NsEnsembleStringOrder);
6754    }
6755}
6756
6757/*
6758 *----------------------------------------------------------------------
6759 *
6760 * NsEnsembleStringOrder --
6761 *
6762 *      Helper function to compare two pointers to two strings for use with
6763 *      qsort().
6764 *
6765 * Results:
6766 *      -1 if the first string is smaller, 1 if the second string is smaller,
6767 *      and 0 if they are equal.
6768 *
6769 * Side effects:
6770 *      None.
6771 *
6772 *----------------------------------------------------------------------
6773 */
6774
6775static int
6776NsEnsembleStringOrder(
6777    const void *strPtr1,
6778    const void *strPtr2)
6779{
6780    return strcmp(*(const char **)strPtr1, *(const char **)strPtr2);
6781}
6782
6783/*
6784 *----------------------------------------------------------------------
6785 *
6786 * FreeEnsembleCmdRep --
6787 *
6788 *      Destroys the internal representation of a Tcl_Obj that has been
6789 *      holding information about a command in an ensemble.
6790 *
6791 * Results:
6792 *      None.
6793 *
6794 * Side effects:
6795 *      Memory is deallocated. If this held the last reference to a
6796 *      namespace's main structure, that main structure will also be
6797 *      destroyed.
6798 *
6799 *----------------------------------------------------------------------
6800 */
6801
6802static void
6803FreeEnsembleCmdRep(
6804    Tcl_Obj *objPtr)
6805{
6806    EnsembleCmdRep *ensembleCmd = objPtr->internalRep.otherValuePtr;
6807
6808    Tcl_DecrRefCount(ensembleCmd->realPrefixObj);
6809    ckfree(ensembleCmd->fullSubcmdName);
6810    ensembleCmd->nsPtr->refCount--;
6811    if ((ensembleCmd->nsPtr->refCount == 0)
6812            && (ensembleCmd->nsPtr->flags & NS_DEAD)) {
6813        NamespaceFree(ensembleCmd->nsPtr);
6814    }
6815    ckfree((char *) ensembleCmd);
6816}
6817
6818/*
6819 *----------------------------------------------------------------------
6820 *
6821 * DupEnsembleCmdRep --
6822 *
6823 *      Makes one Tcl_Obj into a copy of another that is a subcommand of an
6824 *      ensemble.
6825 *
6826 * Results:
6827 *      None.
6828 *
6829 * Side effects:
6830 *      Memory is allocated, and the namespace that the ensemble is built on
6831 *      top of gains another reference.
6832 *
6833 *----------------------------------------------------------------------
6834 */
6835
6836static void
6837DupEnsembleCmdRep(
6838    Tcl_Obj *objPtr,
6839    Tcl_Obj *copyPtr)
6840{
6841    EnsembleCmdRep *ensembleCmd = objPtr->internalRep.otherValuePtr;
6842    EnsembleCmdRep *ensembleCopy = (EnsembleCmdRep *)
6843            ckalloc(sizeof(EnsembleCmdRep));
6844    int length = strlen(ensembleCmd->fullSubcmdName);
6845
6846    copyPtr->typePtr = &tclEnsembleCmdType;
6847    copyPtr->internalRep.otherValuePtr = ensembleCopy;
6848    ensembleCopy->nsPtr = ensembleCmd->nsPtr;
6849    ensembleCopy->epoch = ensembleCmd->epoch;
6850    ensembleCopy->token = ensembleCmd->token;
6851    ensembleCopy->nsPtr->refCount++;
6852    ensembleCopy->realPrefixObj = ensembleCmd->realPrefixObj;
6853    Tcl_IncrRefCount(ensembleCopy->realPrefixObj);
6854    ensembleCopy->fullSubcmdName = ckalloc((unsigned) length+1);
6855    memcpy(ensembleCopy->fullSubcmdName, ensembleCmd->fullSubcmdName,
6856            (unsigned) length+1);
6857}
6858
6859/*
6860 *----------------------------------------------------------------------
6861 *
6862 * StringOfEnsembleCmdRep --
6863 *
6864 *      Creates a string representation of a Tcl_Obj that holds a subcommand
6865 *      of an ensemble.
6866 *
6867 * Results:
6868 *      None.
6869 *
6870 * Side effects:
6871 *      The object gains a string (UTF-8) representation.
6872 *
6873 *----------------------------------------------------------------------
6874 */
6875
6876static void
6877StringOfEnsembleCmdRep(
6878    Tcl_Obj *objPtr)
6879{
6880    EnsembleCmdRep *ensembleCmd = objPtr->internalRep.otherValuePtr;
6881    int length = strlen(ensembleCmd->fullSubcmdName);
6882
6883    objPtr->length = length;
6884    objPtr->bytes = ckalloc((unsigned) length+1);
6885    memcpy(objPtr->bytes, ensembleCmd->fullSubcmdName, (unsigned) length+1);
6886}
6887
6888/*
6889 *----------------------------------------------------------------------
6890 *
6891 * Tcl_LogCommandInfo --
6892 *
6893 *      This function is invoked after an error occurs in an interpreter. It
6894 *      adds information to iPtr->errorInfo field to describe the command that
6895 *      was being executed when the error occurred.
6896 *
6897 * Results:
6898 *      None.
6899 *
6900 * Side effects:
6901 *      Information about the command is added to errorInfo and the line
6902 *      number stored internally in the interpreter is set.
6903 *
6904 *----------------------------------------------------------------------
6905 */
6906
6907void
6908Tcl_LogCommandInfo(
6909    Tcl_Interp *interp,         /* Interpreter in which to log information. */
6910    const char *script,         /* First character in script containing
6911                                 * command (must be <= command). */
6912    const char *command,        /* First character in command that generated
6913                                 * the error. */
6914    int length)                 /* Number of bytes in command (-1 means use
6915                                 * all bytes up to first null byte). */
6916{
6917    register const char *p;
6918    Interp *iPtr = (Interp *) interp;
6919    int overflow, limit = 150;
6920    Var *varPtr, *arrayPtr;
6921
6922    if (iPtr->flags & ERR_ALREADY_LOGGED) {
6923        /*
6924         * Someone else has already logged error information for this command;
6925         * we shouldn't add anything more.
6926         */
6927
6928        return;
6929    }
6930
6931    /*
6932     * Compute the line number where the error occurred.
6933     */
6934
6935    iPtr->errorLine = 1;
6936    for (p = script; p != command; p++) {
6937        if (*p == '\n') {
6938            iPtr->errorLine++;
6939        }
6940    }
6941
6942    overflow = (length > limit);
6943    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
6944            "\n    %s\n\"%.*s%s\"", ((iPtr->errorInfo == NULL)
6945            ? "while executing" : "invoked from within"),
6946            (overflow ? limit : length), command, (overflow ? "..." : "")));
6947
6948    varPtr = TclObjLookupVarEx(interp, iPtr->eiVar, NULL, TCL_GLOBAL_ONLY,
6949            NULL, 0, 0, &arrayPtr);
6950    if ((varPtr == NULL) || !TclIsVarTraced(varPtr)) {
6951        /*
6952         * Should not happen.
6953         */
6954
6955        return;
6956    } else {
6957        Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&iPtr->varTraces,
6958                (char *) varPtr);
6959        VarTrace *tracePtr = Tcl_GetHashValue(hPtr);
6960
6961        if (tracePtr->traceProc != EstablishErrorInfoTraces) {
6962            /*
6963             * The most recent trace set on ::errorInfo is not the one the
6964             * core itself puts on last. This means some other code is tracing
6965             * the variable, and the additional trace(s) might be write traces
6966             * that expect the timing of writes to ::errorInfo that existed
6967             * Tcl releases before 8.5. To satisfy that compatibility need, we
6968             * write the current -errorinfo value to the ::errorInfo variable.
6969             */
6970
6971            Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL, iPtr->errorInfo,
6972                    TCL_GLOBAL_ONLY);
6973        }
6974    }
6975}
6976
6977/*
6978 * Local Variables:
6979 * mode: c
6980 * c-basic-offset: 4
6981 * fill-column: 78
6982 * End:
6983 */
Note: See TracBrowser for help on using the repository browser.