source: HiSusy/trunk/Delphes-3.0.0/external/tcl/tclNamesp.c @ 1

Last change on this file since 1 was 1, checked in by zerwas, 11 years ago

first import of structure, PYTHIA8 and DELPHES

File size: 122.0 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.
9 *
10 * Copyright (c) 1993-1997 Lucent Technologies.
11 * Copyright (c) 1997 Sun Microsystems, Inc.
12 * Copyright (c) 1998-1999 by Scriptics Corporation.
13 *
14 * Originally implemented by
15 *   Michael J. McLennan
16 *   Bell Labs Innovations for Lucent Technologies
17 *   mmclennan@lucent.com
18 *
19 * See the file "license.terms" for information on usage and redistribution
20 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
21 *
22 * RCS: @(#) $Id: tclNamesp.c,v 1.1 2008-06-04 13:58:08 demin Exp $
23 */
24
25#include "tclInt.h"
26
27/*
28 * Flag passed to TclGetNamespaceForQualName to indicate that it should
29 * search for a namespace rather than a command or variable inside a
30 * namespace. Note that this flag's value must not conflict with the values
31 * of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, or CREATE_NS_IF_UNKNOWN.
32 */
33
34#define FIND_ONLY_NS    0x1000
35
36/*
37 * Initial sise of stack allocated space for tail list - used when resetting
38 * shadowed command references in the functin: TclResetShadowedCmdRefs.
39 */
40
41#define NUM_TRAIL_ELEMS 5
42
43/*
44 * Count of the number of namespaces created. This value is used as a
45 * unique id for each namespace.
46 */
47
48static long numNsCreated = 0; 
49
50/*
51 * This structure contains a cached pointer to a namespace that is the
52 * result of resolving the namespace's name in some other namespace. It is
53 * the internal representation for a nsName object. It contains the
54 * pointer along with some information that is used to check the cached
55 * pointer's validity.
56 */
57
58typedef struct ResolvedNsName {
59    Namespace *nsPtr;           /* A cached namespace pointer. */
60    long nsId;                  /* nsPtr's unique namespace id. Used to
61                                 * verify that nsPtr is still valid
62                                 * (e.g., it's possible that the namespace
63                                 * was deleted and a new one created at
64                                 * the same address). */
65    Namespace *refNsPtr;        /* Points to the namespace containing the
66                                 * reference (not the namespace that
67                                 * contains the referenced namespace). */
68    int refCount;               /* Reference count: 1 for each nsName
69                                 * object that has a pointer to this
70                                 * ResolvedNsName structure as its internal
71                                 * rep. This structure can be freed when
72                                 * refCount becomes zero. */
73} ResolvedNsName;
74
75/*
76 * Declarations for procedures local to this file:
77 */
78
79static void             DeleteImportedCmd _ANSI_ARGS_((
80                            ClientData clientData));
81static void             DupNsNameInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr,
82                            Tcl_Obj *copyPtr));
83static void             FreeNsNameInternalRep _ANSI_ARGS_((
84                            Tcl_Obj *objPtr));
85static int              GetNamespaceFromObj _ANSI_ARGS_((
86                            Tcl_Interp *interp, Tcl_Obj *objPtr,
87                            Tcl_Namespace **nsPtrPtr));
88static int              InvokeImportedCmd _ANSI_ARGS_((
89                            ClientData clientData, Tcl_Interp *interp,
90                            int objc, Tcl_Obj *CONST objv[]));
91static int              NamespaceChildrenCmd _ANSI_ARGS_((
92                            ClientData dummy, Tcl_Interp *interp,
93                            int objc, Tcl_Obj *CONST objv[]));
94static int              NamespaceCodeCmd _ANSI_ARGS_((
95                            ClientData dummy, Tcl_Interp *interp,
96                            int objc, Tcl_Obj *CONST objv[]));
97static int              NamespaceCurrentCmd _ANSI_ARGS_((
98                            ClientData dummy, Tcl_Interp *interp,
99                            int objc, Tcl_Obj *CONST objv[]));
100static int              NamespaceDeleteCmd _ANSI_ARGS_((
101                            ClientData dummy, Tcl_Interp *interp,
102                            int objc, Tcl_Obj *CONST objv[]));
103static int              NamespaceEvalCmd _ANSI_ARGS_((
104                            ClientData dummy, Tcl_Interp *interp,
105                            int objc, Tcl_Obj *CONST objv[]));
106static int              NamespaceExportCmd _ANSI_ARGS_((
107                            ClientData dummy, Tcl_Interp *interp,
108                            int objc, Tcl_Obj *CONST objv[]));
109static int              NamespaceForgetCmd _ANSI_ARGS_((
110                            ClientData dummy, Tcl_Interp *interp,
111                            int objc, Tcl_Obj *CONST objv[]));
112static void             NamespaceFree _ANSI_ARGS_((Namespace *nsPtr));
113static int              NamespaceImportCmd _ANSI_ARGS_((
114                            ClientData dummy, Tcl_Interp *interp,
115                            int objc, Tcl_Obj *CONST objv[]));
116static int              NamespaceInscopeCmd _ANSI_ARGS_((
117                            ClientData dummy, Tcl_Interp *interp,
118                            int objc, Tcl_Obj *CONST objv[]));
119static int              NamespaceOriginCmd _ANSI_ARGS_((
120                            ClientData dummy, Tcl_Interp *interp,
121                            int objc, Tcl_Obj *CONST objv[]));
122static int              NamespaceParentCmd _ANSI_ARGS_((
123                            ClientData dummy, Tcl_Interp *interp,
124                            int objc, Tcl_Obj *CONST objv[]));
125static int              NamespaceQualifiersCmd _ANSI_ARGS_((
126                            ClientData dummy, Tcl_Interp *interp,
127                            int objc, Tcl_Obj *CONST objv[]));
128static int              NamespaceTailCmd _ANSI_ARGS_((
129                            ClientData dummy, Tcl_Interp *interp,
130                            int objc, Tcl_Obj *CONST objv[]));
131static int              NamespaceWhichCmd _ANSI_ARGS_((
132                            ClientData dummy, Tcl_Interp *interp,
133                            int objc, Tcl_Obj *CONST objv[]));
134static int              SetNsNameFromAny _ANSI_ARGS_((
135                            Tcl_Interp *interp, Tcl_Obj *objPtr));
136static void             UpdateStringOfNsName _ANSI_ARGS_((Tcl_Obj *objPtr));
137
138/*
139 * This structure defines a Tcl object type that contains a
140 * namespace reference.  It is used in commands that take the
141 * name of a namespace as an argument.  The namespace reference
142 * is resolved, and the result in cached in the object.
143 */
144
145Tcl_ObjType tclNsNameType = {
146    "nsName",                   /* the type's name */
147    FreeNsNameInternalRep,      /* freeIntRepProc */
148    DupNsNameInternalRep,       /* dupIntRepProc */
149    UpdateStringOfNsName,       /* updateStringProc */
150    SetNsNameFromAny            /* setFromAnyProc */
151};
152
153/*
154 * Boolean flag indicating whether or not the namespName object
155 * type has been registered with the Tcl compiler.
156 */
157
158static int nsInitialized = 0;
159
160/*
161 *----------------------------------------------------------------------
162 *
163 * TclInitNamespaces --
164 *
165 *      Called when any interpreter is created to make sure that
166 *      things are properly set up for namespaces.
167 *
168 * Results:
169 *      None.
170 *
171 * Side effects:
172 *      On the first call, the namespName object type is registered
173 *      with the Tcl compiler.
174 *
175 *----------------------------------------------------------------------
176 */
177
178void
179TclInitNamespaces()
180{
181    if (!nsInitialized) {
182        Tcl_RegisterObjType(&tclNsNameType);
183        nsInitialized = 1;
184    }
185}
186
187/*
188 *----------------------------------------------------------------------
189 *
190 * Tcl_GetCurrentNamespace --
191 *
192 *      Returns a pointer to an interpreter's currently active namespace.
193 *
194 * Results:
195 *      Returns a pointer to the interpreter's current namespace.
196 *
197 * Side effects:
198 *      None.
199 *
200 *----------------------------------------------------------------------
201 */
202
203Tcl_Namespace *
204Tcl_GetCurrentNamespace(interp)
205    register Tcl_Interp *interp; /* Interpreter whose current namespace is
206                                  * being queried. */
207{
208    register Interp *iPtr = (Interp *) interp;
209    register Namespace *nsPtr;
210
211    if (iPtr->varFramePtr != NULL) {
212        nsPtr = iPtr->varFramePtr->nsPtr;
213    } else {
214        nsPtr = iPtr->globalNsPtr;
215    }
216    return (Tcl_Namespace *) nsPtr;
217}
218
219/*
220 *----------------------------------------------------------------------
221 *
222 * Tcl_GetGlobalNamespace --
223 *
224 *      Returns a pointer to an interpreter's global :: namespace.
225 *
226 * Results:
227 *      Returns a pointer to the specified interpreter's global namespace.
228 *
229 * Side effects:
230 *      None.
231 *
232 *----------------------------------------------------------------------
233 */
234
235Tcl_Namespace *
236Tcl_GetGlobalNamespace(interp)
237    register Tcl_Interp *interp; /* Interpreter whose global namespace
238                                  * should be returned. */
239{
240    register Interp *iPtr = (Interp *) interp;
241   
242    return (Tcl_Namespace *) iPtr->globalNsPtr;
243}
244
245/*
246 *----------------------------------------------------------------------
247 *
248 * Tcl_PushCallFrame --
249 *
250 *      Pushes a new call frame onto the interpreter's Tcl call stack.
251 *      Called when executing a Tcl procedure or a "namespace eval" or
252 *      "namespace inscope" command.
253 *
254 * Results:
255 *      Returns TCL_OK if successful, or TCL_ERROR (along with an error
256 *      message in the interpreter's result object) if something goes wrong.
257 *
258 * Side effects:
259 *      Modifies the interpreter's Tcl call stack.
260 *
261 *----------------------------------------------------------------------
262 */
263
264int
265Tcl_PushCallFrame(interp, callFramePtr, namespacePtr, isProcCallFrame)
266    Tcl_Interp *interp;          /* Interpreter in which the new call frame
267                                  * is to be pushed. */
268    Tcl_CallFrame *callFramePtr; /* Points to a call frame structure to
269                                  * push. Storage for this have already been
270                                  * allocated by the caller; typically this
271                                  * is the address of a CallFrame structure
272                                  * allocated on the caller's C stack.  The
273                                  * call frame will be initialized by this
274                                  * procedure. The caller can pop the frame
275                                  * later with Tcl_PopCallFrame, and it is
276                                  * responsible for freeing the frame's
277                                  * storage. */
278    Tcl_Namespace *namespacePtr; /* Points to the namespace in which the
279                                  * frame will execute. If NULL, the
280                                  * interpreter's current namespace will
281                                  * be used. */
282    int isProcCallFrame;         /* If nonzero, the frame represents a
283                                  * called Tcl procedure and may have local
284                                  * vars. Vars will ordinarily be looked up
285                                  * in the frame. If new variables are
286                                  * created, they will be created in the
287                                  * frame. If 0, the frame is for a
288                                  * "namespace eval" or "namespace inscope"
289                                  * command and var references are treated
290                                  * as references to namespace variables. */
291{
292    Interp *iPtr = (Interp *) interp;
293    register CallFrame *framePtr = (CallFrame *) callFramePtr;
294    register Namespace *nsPtr;
295
296    if (namespacePtr == NULL) {
297        nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
298    } else {
299        nsPtr = (Namespace *) namespacePtr;
300        if (nsPtr->flags & NS_DEAD) {
301           panic("Trying to push call frame for dead namespace");
302            /*NOTREACHED*/
303        }
304    }
305
306    nsPtr->activationCount++;
307    framePtr->nsPtr = nsPtr;
308    framePtr->isProcCallFrame = isProcCallFrame;
309    framePtr->objc = 0;
310    framePtr->objv = NULL;
311    framePtr->callerPtr = iPtr->framePtr;
312    framePtr->callerVarPtr = iPtr->varFramePtr;
313    if (iPtr->varFramePtr != NULL) {
314        framePtr->level = (iPtr->varFramePtr->level + 1);
315    } else {
316        framePtr->level = 1;
317    }
318    framePtr->procPtr = NULL;      /* no called procedure */
319    framePtr->varTablePtr = NULL;  /* and no local variables */
320    framePtr->numCompiledLocals = 0;
321    framePtr->compiledLocals = NULL;
322
323    /*
324     * Push the new call frame onto the interpreter's stack of procedure
325     * call frames making it the current frame.
326     */
327
328    iPtr->framePtr = framePtr;
329    iPtr->varFramePtr = framePtr;
330    return TCL_OK;
331}
332
333/*
334 *----------------------------------------------------------------------
335 *
336 * Tcl_PopCallFrame --
337 *
338 *      Removes a call frame from the Tcl call stack for the interpreter.
339 *      Called to remove a frame previously pushed by Tcl_PushCallFrame.
340 *
341 * Results:
342 *      None.
343 *
344 * Side effects:
345 *      Modifies the call stack of the interpreter. Resets various fields of
346 *      the popped call frame. If a namespace has been deleted and
347 *      has no more activations on the call stack, the namespace is
348 *      destroyed.
349 *
350 *----------------------------------------------------------------------
351 */
352
353void
354Tcl_PopCallFrame(interp)
355    Tcl_Interp* interp;         /* Interpreter with call frame to pop. */
356{
357    register Interp *iPtr = (Interp *) interp;
358    register CallFrame *framePtr = iPtr->framePtr;
359    int saveErrFlag;
360    Namespace *nsPtr;
361
362    /*
363     * It's important to remove the call frame from the interpreter's stack
364     * of call frames before deleting local variables, so that traces
365     * invoked by the variable deletion don't see the partially-deleted
366     * frame.
367     */
368
369    iPtr->framePtr = framePtr->callerPtr;
370    iPtr->varFramePtr = framePtr->callerVarPtr;
371
372    /*
373     * Delete the local variables. As a hack, we save then restore the
374     * ERR_IN_PROGRESS flag in the interpreter. The problem is that there
375     * could be unset traces on the variables, which cause scripts to be
376     * evaluated. This will clear the ERR_IN_PROGRESS flag, losing stack
377     * trace information if the procedure was exiting with an error. The
378     * code below preserves the flag. Unfortunately, that isn't really
379     * enough: we really should preserve the errorInfo variable too
380     * (otherwise a nested error in the trace script will trash errorInfo).
381     * What's really needed is a general-purpose mechanism for saving and
382     * restoring interpreter state.
383     */
384
385    saveErrFlag = (iPtr->flags & ERR_IN_PROGRESS);
386
387    if (framePtr->varTablePtr != NULL) {
388        TclDeleteVars(iPtr, framePtr->varTablePtr);
389        ckfree((char *) framePtr->varTablePtr);
390        framePtr->varTablePtr = NULL;
391    }
392    if (framePtr->numCompiledLocals > 0) {
393        TclDeleteCompiledLocalVars(iPtr, framePtr);
394    }
395
396    iPtr->flags |= saveErrFlag;
397
398    /*
399     * Decrement the namespace's count of active call frames. If the
400     * namespace is "dying" and there are no more active call frames,
401     * call Tcl_DeleteNamespace to destroy it.
402     */
403
404    nsPtr = framePtr->nsPtr;
405    nsPtr->activationCount--;
406    if ((nsPtr->flags & NS_DYING)
407            && (nsPtr->activationCount == 0)) {
408        Tcl_DeleteNamespace((Tcl_Namespace *) nsPtr);
409    }
410    framePtr->nsPtr = NULL;
411}
412
413/*
414 *----------------------------------------------------------------------
415 *
416 * Tcl_CreateNamespace --
417 *
418 *      Creates a new namespace with the given name. If there is no
419 *      active namespace (i.e., the interpreter is being initialized),
420 *      the global :: namespace is created and returned.
421 *
422 * Results:
423 *      Returns a pointer to the new namespace if successful. If the
424 *      namespace already exists or if another error occurs, this routine
425 *      returns NULL, along with an error message in the interpreter's
426 *      result object.
427 *
428 * Side effects:
429 *      If the name contains "::" qualifiers and a parent namespace does
430 *      not already exist, it is automatically created.
431 *
432 *----------------------------------------------------------------------
433 */
434
435Tcl_Namespace *
436Tcl_CreateNamespace(interp, name, clientData, deleteProc)
437    Tcl_Interp *interp;             /* Interpreter in which a new namespace
438                                     * is being created. Also used for
439                                     * error reporting. */
440    char *name;                     /* Name for the new namespace. May be a
441                                     * qualified name with names of ancestor
442                                     * namespaces separated by "::"s. */
443    ClientData clientData;          /* One-word value to store with
444                                     * namespace. */
445    Tcl_NamespaceDeleteProc *deleteProc;
446                                    /* Procedure called to delete client
447                                     * data when the namespace is deleted.
448                                     * NULL if no procedure should be
449                                     * called. */
450{
451    Interp *iPtr = (Interp *) interp;
452    register Namespace *nsPtr, *ancestorPtr;
453    Namespace *parentPtr, *dummy1Ptr, *dummy2Ptr;
454    Namespace *globalNsPtr = iPtr->globalNsPtr;
455    char *simpleName;
456    Tcl_HashEntry *entryPtr;
457    Tcl_DString buffer1, buffer2;
458    int newEntry;
459
460    /*
461     * If there is no active namespace, the interpreter is being
462     * initialized.
463     */
464
465    if ((globalNsPtr == NULL) && (iPtr->varFramePtr == NULL)) {
466        /*
467         * Treat this namespace as the global namespace, and avoid
468         * looking for a parent.
469         */
470       
471        parentPtr = NULL;
472        simpleName = "";
473    } else if (*name == '\0') {
474        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
475                "can't create namespace \"\": only global namespace can have empty name", (char *) NULL);
476        return NULL;
477    } else {
478        /*
479         * Find the parent for the new namespace.
480         */
481
482       TclGetNamespaceForQualName(interp, name, (Namespace *) NULL,
483           /*flags*/ CREATE_NS_IF_UNKNOWN, &parentPtr, &dummy1Ptr,
484           &dummy2Ptr, &simpleName);
485
486        /*
487         * If the unqualified name at the end is empty, there were trailing
488         * "::"s after the namespace's name which we ignore. The new
489         * namespace was already (recursively) created and is pointed to
490         * by parentPtr.
491         */
492
493        if (*simpleName == '\0') {
494            return (Tcl_Namespace *) parentPtr;
495        }
496
497        /*
498         * Check for a bad namespace name and make sure that the name
499         * does not already exist in the parent namespace.
500         */
501
502        if (Tcl_FindHashEntry(&parentPtr->childTable, simpleName) != NULL) {
503            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
504                    "can't create namespace \"", name,
505                    "\": already exists", (char *) NULL);
506            return NULL;
507        }
508    }
509
510    /*
511     * Create the new namespace and root it in its parent. Increment the
512     * count of namespaces created.
513     */
514
515    numNsCreated++;
516
517    nsPtr = (Namespace *) ckalloc(sizeof(Namespace));
518    nsPtr->name            = (char *) ckalloc((unsigned) (strlen(simpleName)+1));
519    strcpy(nsPtr->name, simpleName);
520    nsPtr->fullName        = NULL;   /* set below */
521    nsPtr->clientData      = clientData;
522    nsPtr->deleteProc      = deleteProc;
523    nsPtr->parentPtr       = parentPtr;
524    Tcl_InitHashTable(&nsPtr->childTable, TCL_STRING_KEYS);
525    nsPtr->nsId            = numNsCreated;
526    nsPtr->interp          = interp;
527    nsPtr->flags           = 0;
528    nsPtr->activationCount = 0;
529    nsPtr->refCount        = 0;
530    Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS);
531    Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
532    nsPtr->exportArrayPtr  = NULL;
533    nsPtr->numExportPatterns = 0;
534    nsPtr->maxExportPatterns = 0;
535    nsPtr->cmdRefEpoch       = 0;
536    nsPtr->resolverEpoch     = 0;
537    nsPtr->cmdResProc        = NULL;
538    nsPtr->varResProc        = NULL;
539    nsPtr->compiledVarResProc = NULL;
540
541    if (parentPtr != NULL) {
542        entryPtr = Tcl_CreateHashEntry(&parentPtr->childTable, simpleName,
543                &newEntry);
544        Tcl_SetHashValue(entryPtr, (ClientData) nsPtr);
545    }
546
547    /*
548     * Build the fully qualified name for this namespace.
549     */
550
551    Tcl_DStringInit(&buffer1);
552    Tcl_DStringInit(&buffer2);
553    for (ancestorPtr = nsPtr;  ancestorPtr != NULL;
554            ancestorPtr = ancestorPtr->parentPtr) {
555        if (ancestorPtr != globalNsPtr) {
556            Tcl_DStringAppend(&buffer1, "::", 2);
557            Tcl_DStringAppend(&buffer1, ancestorPtr->name, -1);
558        }
559        Tcl_DStringAppend(&buffer1, Tcl_DStringValue(&buffer2), -1);
560
561        Tcl_DStringSetLength(&buffer2, 0);
562        Tcl_DStringAppend(&buffer2, Tcl_DStringValue(&buffer1), -1);
563        Tcl_DStringSetLength(&buffer1, 0);
564    }
565   
566    name = Tcl_DStringValue(&buffer2);
567    nsPtr->fullName = (char *) ckalloc((unsigned) (strlen(name)+1));
568    strcpy(nsPtr->fullName, name);
569
570    Tcl_DStringFree(&buffer1);
571    Tcl_DStringFree(&buffer2);
572
573    /*
574     * Return a pointer to the new namespace.
575     */
576
577    return (Tcl_Namespace *) nsPtr;
578}
579
580/*
581 *----------------------------------------------------------------------
582 *
583 * Tcl_DeleteNamespace --
584 *
585 *      Deletes a namespace and all of the commands, variables, and other
586 *      namespaces within it.
587 *
588 * Results:
589 *      None.
590 *
591 * Side effects:
592 *      When a namespace is deleted, it is automatically removed as a
593 *      child of its parent namespace. Also, all its commands, variables
594 *      and child namespaces are deleted.
595 *
596 *----------------------------------------------------------------------
597 */
598
599void
600Tcl_DeleteNamespace(namespacePtr)
601    Tcl_Namespace *namespacePtr;   /* Points to the namespace to delete. */
602{
603    register Namespace *nsPtr = (Namespace *) namespacePtr;
604    Interp *iPtr = (Interp *) nsPtr->interp;
605    Namespace *globalNsPtr =
606            (Namespace *) Tcl_GetGlobalNamespace((Tcl_Interp *) iPtr);
607    Tcl_HashEntry *entryPtr;
608
609    /*
610     * If the namespace is on the call frame stack, it is marked as "dying"
611     * (NS_DYING is OR'd into its flags): the namespace can't be looked up
612     * by name but its commands and variables are still usable by those
613     * active call frames. When all active call frames referring to the
614     * namespace have been popped from the Tcl stack, Tcl_PopCallFrame will
615     * call this procedure again to delete everything in the namespace.
616     * If no nsName objects refer to the namespace (i.e., if its refCount
617     * is zero), its commands and variables are deleted and the storage for
618     * its namespace structure is freed. Otherwise, if its refCount is
619     * nonzero, the namespace's commands and variables are deleted but the
620     * structure isn't freed. Instead, NS_DEAD is OR'd into the structure's
621     * flags to allow the namespace resolution code to recognize that the
622     * namespace is "deleted". The structure's storage is freed by
623     * FreeNsNameInternalRep when its refCount reaches 0.
624     */
625
626    if (nsPtr->activationCount > 0) {
627        nsPtr->flags |= NS_DYING;
628        if (nsPtr->parentPtr != NULL) {
629            entryPtr = Tcl_FindHashEntry(&nsPtr->parentPtr->childTable,
630                    nsPtr->name);
631            if (entryPtr != NULL) {
632                Tcl_DeleteHashEntry(entryPtr);
633            }
634        }
635        nsPtr->parentPtr = NULL;
636    } else {
637        /*
638         * Delete the namespace and everything in it. If this is the global
639         * namespace, then clear it but don't free its storage unless the
640         * interpreter is being torn down.
641         */
642
643        TclTeardownNamespace(nsPtr);
644
645        if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) {
646            /*
647             * If this is the global namespace, then it may have residual
648             * "errorInfo" and "errorCode" variables for errors that
649             * occurred while it was being torn down.  Try to clear the
650             * variable list one last time.
651             */
652
653            TclDeleteVars((Interp *) nsPtr->interp, &nsPtr->varTable);
654           
655            Tcl_DeleteHashTable(&nsPtr->childTable);
656            Tcl_DeleteHashTable(&nsPtr->cmdTable);
657
658            /*
659             * If the reference count is 0, then discard the namespace.
660             * Otherwise, mark it as "dead" so that it can't be used.
661             */
662
663            if (nsPtr->refCount == 0) {
664                NamespaceFree(nsPtr);
665            } else {
666                nsPtr->flags |= NS_DEAD;
667            }
668        }
669    }
670}
671
672/*
673 *----------------------------------------------------------------------
674 *
675 * TclTeardownNamespace --
676 *
677 *      Used internally to dismantle and unlink a namespace when it is
678 *      deleted. Divorces the namespace from its parent, and deletes all
679 *      commands, variables, and child namespaces.
680 *
681 *      This is kept separate from Tcl_DeleteNamespace so that the global
682 *      namespace can be handled specially. Global variables like
683 *      "errorInfo" and "errorCode" need to remain intact while other
684 *      namespaces and commands are torn down, in case any errors occur.
685 *
686 * Results:
687 *      None.
688 *
689 * Side effects:
690 *      Removes this namespace from its parent's child namespace hashtable.
691 *      Deletes all commands, variables and namespaces in this namespace.
692 *      If this is the global namespace, the "errorInfo" and "errorCode"
693 *      variables are left alone and deleted later.
694 *
695 *----------------------------------------------------------------------
696 */
697
698void
699TclTeardownNamespace(nsPtr)
700    register Namespace *nsPtr;  /* Points to the namespace to be dismantled
701                                 * and unlinked from its parent. */
702{
703    Interp *iPtr = (Interp *) nsPtr->interp;
704    register Tcl_HashEntry *entryPtr;
705    Tcl_HashSearch search;
706    Tcl_Namespace *childNsPtr;
707    Tcl_Command cmd;
708    Namespace *globalNsPtr =
709            (Namespace *) Tcl_GetGlobalNamespace((Tcl_Interp *) iPtr);
710    int i;
711
712    /*
713     * Start by destroying the namespace's variable table,
714     * since variables might trigger traces.
715     */
716
717    if (nsPtr == globalNsPtr) {
718        /*
719         * This is the global namespace, so be careful to preserve the
720         * "errorInfo" and "errorCode" variables. These might be needed
721         * later on if errors occur while deleting commands. We are careful
722         * to destroy and recreate the "errorInfo" and "errorCode"
723         * variables, in case they had any traces on them.
724         */
725   
726        char *str, *errorInfoStr, *errorCodeStr;
727
728        str = Tcl_GetVar((Tcl_Interp *) iPtr, "errorInfo", TCL_GLOBAL_ONLY);
729        if (str != NULL) {
730            errorInfoStr = ckalloc((unsigned) (strlen(str)+1));
731            strcpy(errorInfoStr, str);
732        } else {
733            errorInfoStr = NULL;
734        }
735
736        str = Tcl_GetVar((Tcl_Interp *) iPtr, "errorCode", TCL_GLOBAL_ONLY);
737        if (str != NULL) {
738            errorCodeStr = ckalloc((unsigned) (strlen(str)+1));
739            strcpy(errorCodeStr, str);
740        } else {
741            errorCodeStr = NULL;
742        }
743
744        TclDeleteVars(iPtr, &nsPtr->varTable);
745        Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
746
747        if (errorInfoStr != NULL) {
748            Tcl_SetVar((Tcl_Interp *) iPtr, "errorInfo", errorInfoStr,
749                TCL_GLOBAL_ONLY);
750            ckfree(errorInfoStr);
751        }
752        if (errorCodeStr != NULL) {
753            Tcl_SetVar((Tcl_Interp *) iPtr, "errorCode", errorCodeStr,
754                TCL_GLOBAL_ONLY);
755            ckfree(errorCodeStr);
756        }
757    } else {
758        /*
759         * Variable table should be cleared but not freed! TclDeleteVars
760         * frees it, so we reinitialize it afterwards.
761         */
762   
763        TclDeleteVars(iPtr, &nsPtr->varTable);
764        Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
765    }
766
767    /*
768     * Remove the namespace from its parent's child hashtable.
769     */
770
771    if (nsPtr->parentPtr != NULL) {
772        entryPtr = Tcl_FindHashEntry(&nsPtr->parentPtr->childTable,
773                nsPtr->name);
774        if (entryPtr != NULL) {
775            Tcl_DeleteHashEntry(entryPtr);
776        }
777    }
778    nsPtr->parentPtr = NULL;
779
780    /*
781     * Delete all the child namespaces.
782     *
783     * BE CAREFUL: When each child is deleted, it will divorce
784     *    itself from its parent. You can't traverse a hash table
785     *    properly if its elements are being deleted. We use only
786     *    the Tcl_FirstHashEntry function to be safe.
787     */
788
789    for (entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
790            entryPtr != NULL;
791            entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search)) {
792        childNsPtr = (Tcl_Namespace *) Tcl_GetHashValue(entryPtr);
793        Tcl_DeleteNamespace(childNsPtr);
794    }
795
796    /*
797     * Delete all commands in this namespace. Be careful when traversing the
798     * hash table: when each command is deleted, it removes itself from the
799     * command table.
800     */
801
802    for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
803            entryPtr != NULL;
804            entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search)) {
805        cmd = (Tcl_Command) Tcl_GetHashValue(entryPtr);
806        Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr, cmd);
807    }
808    Tcl_DeleteHashTable(&nsPtr->cmdTable);
809    Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS);
810
811    /*
812     * Free the namespace's export pattern array.
813     */
814
815    if (nsPtr->exportArrayPtr != NULL) {
816        for (i = 0;  i < nsPtr->numExportPatterns;  i++) {
817            ckfree(nsPtr->exportArrayPtr[i]);
818        }
819        ckfree((char *) nsPtr->exportArrayPtr);
820        nsPtr->exportArrayPtr = NULL;
821        nsPtr->numExportPatterns = 0;
822        nsPtr->maxExportPatterns = 0;
823    }
824
825    /*
826     * Free any client data associated with the namespace.
827     */
828
829    if (nsPtr->deleteProc != NULL) {
830        (*nsPtr->deleteProc)(nsPtr->clientData);
831    }
832    nsPtr->deleteProc = NULL;
833    nsPtr->clientData = NULL;
834
835    /*
836     * Reset the namespace's id field to ensure that this namespace won't
837     * be interpreted as valid by, e.g., the cache validation code for
838     * cached command references in Tcl_GetCommandFromObj.
839     */
840
841    nsPtr->nsId = 0;
842}
843
844/*
845 *----------------------------------------------------------------------
846 *
847 * NamespaceFree --
848 *
849 *      Called after a namespace has been deleted, when its
850 *      reference count reaches 0.  Frees the data structure
851 *      representing the namespace.
852 *
853 * Results:
854 *      None.
855 *
856 * Side effects:
857 *      None.
858 *
859 *----------------------------------------------------------------------
860 */
861
862static void
863NamespaceFree(nsPtr)
864    register Namespace *nsPtr;  /* Points to the namespace to free. */
865{
866    /*
867     * Most of the namespace's contents are freed when the namespace is
868     * deleted by Tcl_DeleteNamespace. All that remains is to free its names
869     * (for error messages), and the structure itself.
870     */
871
872    ckfree(nsPtr->name);
873    ckfree(nsPtr->fullName);
874
875    ckfree((char *) nsPtr);
876}
877
878
879/*
880 *----------------------------------------------------------------------
881 *
882 * Tcl_Export --
883 *
884 *      Makes all the commands matching a pattern available to later be
885 *      imported from the namespace specified by contextNsPtr (or the
886 *      current namespace if contextNsPtr is NULL). The specified pattern is
887 *      appended onto the namespace's export pattern list, which is
888 *      optionally cleared beforehand.
889 *
890 * Results:
891 *      Returns TCL_OK if successful, or TCL_ERROR (along with an error
892 *      message in the interpreter's result) if something goes wrong.
893 *
894 * Side effects:
895 *      Appends the export pattern onto the namespace's export list.
896 *      Optionally reset the namespace's export pattern list.
897 *
898 *----------------------------------------------------------------------
899 */
900
901int
902Tcl_Export(interp, namespacePtr, pattern, resetListFirst)
903    Tcl_Interp *interp;          /* Current interpreter. */
904    Tcl_Namespace *namespacePtr; /* Points to the namespace from which
905                                  * commands are to be exported. NULL for
906                                  * the current namespace. */
907    char *pattern;               /* String pattern indicating which commands
908                                  * to export. This pattern may not include
909                                  * any namespace qualifiers; only commands
910                                  * in the specified namespace may be
911                                  * exported. */
912    int resetListFirst;          /* If nonzero, resets the namespace's
913                                  * export list before appending
914                                  * be overwritten by imported commands.
915                                  * If 0, return an error if an imported
916                                  * cmd conflicts with an existing one. */
917{
918#define INIT_EXPORT_PATTERNS 5   
919    Namespace *nsPtr, *exportNsPtr, *dummyPtr;
920    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
921    char *simplePattern, *patternCpy;
922    int neededElems, len, i;
923
924    /*
925     * If the specified namespace is NULL, use the current namespace.
926     */
927
928    if (namespacePtr == NULL) {
929        nsPtr = (Namespace *) currNsPtr;
930    } else {
931        nsPtr = (Namespace *) namespacePtr;
932    }
933
934    /*
935     * If resetListFirst is true (nonzero), clear the namespace's export
936     * pattern list.
937     */
938
939    if (resetListFirst) {
940        if (nsPtr->exportArrayPtr != NULL) {
941            for (i = 0;  i < nsPtr->numExportPatterns;  i++) {
942                ckfree(nsPtr->exportArrayPtr[i]);
943            }
944            ckfree((char *) nsPtr->exportArrayPtr);
945            nsPtr->exportArrayPtr = NULL;
946            nsPtr->numExportPatterns = 0;
947            nsPtr->maxExportPatterns = 0;
948        }
949    }
950
951    /*
952     * Check that the pattern doesn't have namespace qualifiers.
953     */
954
955    TclGetNamespaceForQualName(interp, pattern, nsPtr,
956       /*flags*/ 0, &exportNsPtr, &dummyPtr, &dummyPtr, &simplePattern);
957
958    if ((exportNsPtr != nsPtr) || (strcmp(pattern, simplePattern) != 0)) {
959        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
960                "invalid export pattern \"", pattern,
961                "\": pattern can't specify a namespace",
962                (char *) NULL);
963        return TCL_ERROR;
964    }
965
966    /*
967     * Make sure there is room in the namespace's pattern array for the
968     * new pattern.
969     */
970
971    neededElems = nsPtr->numExportPatterns + 1;
972    if (nsPtr->exportArrayPtr == NULL) {
973        nsPtr->exportArrayPtr = (char **)
974                ckalloc((unsigned) (INIT_EXPORT_PATTERNS * sizeof(char *)));
975        nsPtr->numExportPatterns = 0;
976        nsPtr->maxExportPatterns = INIT_EXPORT_PATTERNS;
977    } else if (neededElems > nsPtr->maxExportPatterns) {
978        int numNewElems = 2 * nsPtr->maxExportPatterns;
979        size_t currBytes = nsPtr->numExportPatterns * sizeof(char *);
980        size_t newBytes  = numNewElems * sizeof(char *);
981        char **newPtr = (char **) ckalloc((unsigned) newBytes);
982
983        memcpy((VOID *) newPtr, (VOID *) nsPtr->exportArrayPtr,
984                currBytes);
985        ckfree((char *) nsPtr->exportArrayPtr);
986        nsPtr->exportArrayPtr = (char **) newPtr;
987        nsPtr->maxExportPatterns = numNewElems;
988    }
989
990    /*
991     * Add the pattern to the namespace's array of export patterns.
992     */
993
994    len = strlen(pattern);
995    patternCpy = (char *) ckalloc((unsigned) (len + 1));
996    strcpy(patternCpy, pattern);
997   
998    nsPtr->exportArrayPtr[nsPtr->numExportPatterns] = patternCpy;
999    nsPtr->numExportPatterns++;
1000    return TCL_OK;
1001#undef INIT_EXPORT_PATTERNS
1002}
1003
1004/*
1005 *----------------------------------------------------------------------
1006 *
1007 * Tcl_AppendExportList --
1008 *
1009 *      Appends onto the argument object the list of export patterns for the
1010 *      specified namespace.
1011 *
1012 * Results:
1013 *      The return value is normally TCL_OK; in this case the object
1014 *      referenced by objPtr has each export pattern appended to it. If an
1015 *      error occurs, TCL_ERROR is returned and the interpreter's result
1016 *      holds an error message.
1017 *
1018 * Side effects:
1019 *      If necessary, the object referenced by objPtr is converted into
1020 *      a list object.
1021 *
1022 *----------------------------------------------------------------------
1023 */
1024
1025int
1026Tcl_AppendExportList(interp, namespacePtr, objPtr)
1027    Tcl_Interp *interp;          /* Interpreter used for error reporting. */
1028    Tcl_Namespace *namespacePtr; /* Points to the namespace whose export
1029                                  * pattern list is appended onto objPtr.
1030                                  * NULL for the current namespace. */
1031    Tcl_Obj *objPtr;             /* Points to the Tcl object onto which the
1032                                  * export pattern list is appended. */
1033{
1034    Namespace *nsPtr;
1035    int i, result;
1036
1037    /*
1038     * If the specified namespace is NULL, use the current namespace.
1039     */
1040
1041    if (namespacePtr == NULL) {
1042        nsPtr = (Namespace *) (Namespace *) Tcl_GetCurrentNamespace(interp);
1043    } else {
1044        nsPtr = (Namespace *) namespacePtr;
1045    }
1046
1047    /*
1048     * Append the export pattern list onto objPtr.
1049     */
1050
1051    for (i = 0;  i < nsPtr->numExportPatterns;  i++) {
1052        result = Tcl_ListObjAppendElement(interp, objPtr,
1053                Tcl_NewStringObj(nsPtr->exportArrayPtr[i], -1));
1054        if (result != TCL_OK) {
1055            return result;
1056        }
1057    }
1058    return TCL_OK;
1059}
1060
1061/*
1062 *----------------------------------------------------------------------
1063 *
1064 * Tcl_Import --
1065 *
1066 *      Imports all of the commands matching a pattern into the namespace
1067 *      specified by contextNsPtr (or the current namespace if contextNsPtr
1068 *      is NULL). This is done by creating a new command (the "imported
1069 *      command") that points to the real command in its original namespace.
1070 *
1071 *      If matching commands are on the autoload path but haven't been
1072 *      loaded yet, this command forces them to be loaded, then creates
1073 *      the links to them.
1074 *
1075 * Results:
1076 *      Returns TCL_OK if successful, or TCL_ERROR (along with an error
1077 *      message in the interpreter's result) if something goes wrong.
1078 *
1079 * Side effects:
1080 *      Creates new commands in the importing namespace. These indirect
1081 *      calls back to the real command and are deleted if the real commands
1082 *      are deleted.
1083 *
1084 *----------------------------------------------------------------------
1085 */
1086
1087int
1088Tcl_Import(interp, namespacePtr, pattern, allowOverwrite)
1089    Tcl_Interp *interp;          /* Current interpreter. */
1090    Tcl_Namespace *namespacePtr; /* Points to the namespace into which the
1091                                  * commands are to be imported. NULL for
1092                                  * the current namespace. */
1093    char *pattern;               /* String pattern indicating which commands
1094                                  * to import. This pattern should be
1095                                  * qualified by the name of the namespace
1096                                  * from which to import the command(s). */
1097    int allowOverwrite;          /* If nonzero, allow existing commands to
1098                                  * be overwritten by imported commands.
1099                                  * If 0, return an error if an imported
1100                                  * cmd conflicts with an existing one. */
1101{
1102    Interp *iPtr = (Interp *) interp;
1103    Namespace *nsPtr, *importNsPtr, *dummyPtr;
1104    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
1105    char *simplePattern, *cmdName;
1106    register Tcl_HashEntry *hPtr;
1107    Tcl_HashSearch search;
1108    Command *cmdPtr;
1109    ImportRef *refPtr;
1110    Tcl_Command autoCmd, importedCmd;
1111    ImportedCmdData *dataPtr;
1112    int wasExported, i, result;
1113
1114    /*
1115     * If the specified namespace is NULL, use the current namespace.
1116     */
1117
1118    if (namespacePtr == NULL) {
1119        nsPtr = (Namespace *) currNsPtr;
1120    } else {
1121        nsPtr = (Namespace *) namespacePtr;
1122    }
1123 
1124    /*
1125     * First, invoke the "auto_import" command with the pattern
1126     * being imported.  This command is part of the Tcl library.
1127     * It looks for imported commands in autoloaded libraries and
1128     * loads them in.  That way, they will be found when we try
1129     * to create links below.
1130     */
1131   
1132    autoCmd = Tcl_FindCommand(interp, "auto_import",
1133            (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY);
1134 
1135    if (autoCmd != NULL) {
1136        Tcl_Obj *objv[2];
1137 
1138        objv[0] = Tcl_NewStringObj("auto_import", -1);
1139        Tcl_IncrRefCount(objv[0]);
1140        objv[1] = Tcl_NewStringObj(pattern, -1);
1141        Tcl_IncrRefCount(objv[1]);
1142 
1143        cmdPtr = (Command *) autoCmd;
1144        result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp,
1145                2, objv);
1146 
1147        Tcl_DecrRefCount(objv[0]);
1148        Tcl_DecrRefCount(objv[1]);
1149 
1150        if (result != TCL_OK) {
1151            return TCL_ERROR;
1152        }
1153        Tcl_ResetResult(interp);
1154    }
1155
1156    /*
1157     * From the pattern, find the namespace from which we are importing
1158     * and get the simple pattern (no namespace qualifiers or ::'s) at
1159     * the end.
1160     */
1161
1162    if (strlen(pattern) == 0) {
1163        Tcl_SetStringObj(Tcl_GetObjResult(interp),
1164                "empty import pattern", -1);
1165        return TCL_ERROR;
1166    }
1167    TclGetNamespaceForQualName(interp, pattern, nsPtr,
1168       /*flags*/ 0, &importNsPtr, &dummyPtr, &dummyPtr, &simplePattern);
1169
1170    if (importNsPtr == NULL) {
1171        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1172                "unknown namespace in import pattern \"",
1173                pattern, "\"", (char *) NULL);
1174        return TCL_ERROR;
1175    }
1176    if (importNsPtr == nsPtr) {
1177        if (pattern == simplePattern) {
1178            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1179                    "no namespace specified in import pattern \"", pattern,
1180                    "\"", (char *) NULL);
1181        } else {
1182            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1183                    "import pattern \"", pattern,
1184                    "\" tries to import from namespace \"",
1185                    importNsPtr->name, "\" into itself", (char *) NULL);
1186        }
1187        return TCL_ERROR;
1188    }
1189
1190    /*
1191     * Scan through the command table in the source namespace and look for
1192     * exported commands that match the string pattern. Create an "imported
1193     * command" in the current namespace for each imported command; these
1194     * commands redirect their invocations to the "real" command.
1195     */
1196
1197    for (hPtr = Tcl_FirstHashEntry(&importNsPtr->cmdTable, &search);
1198            (hPtr != NULL);
1199            hPtr = Tcl_NextHashEntry(&search)) {
1200        cmdName = Tcl_GetHashKey(&importNsPtr->cmdTable, hPtr);
1201        if (Tcl_StringMatch(cmdName, simplePattern)) {
1202            /*
1203             * The command cmdName in the source namespace matches the
1204             * pattern. Check whether it was exported. If it wasn't,
1205             * we ignore it.
1206             */
1207
1208            wasExported = 0;
1209            for (i = 0;  i < importNsPtr->numExportPatterns;  i++) {
1210                if (Tcl_StringMatch(cmdName,
1211                        importNsPtr->exportArrayPtr[i])) {
1212                    wasExported = 1;
1213                    break;
1214                }
1215            }
1216            if (!wasExported) {
1217                continue;
1218            }
1219
1220            /*
1221             * Unless there is a name clash, create an imported command
1222             * in the current namespace that refers to cmdPtr.
1223             */
1224           
1225            if ((Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName) == NULL)
1226                    || allowOverwrite) {
1227                /*
1228                 * Create the imported command and its client data.
1229                 * To create the new command in the current namespace,
1230                 * generate a fully qualified name for it.
1231                 */
1232
1233                Tcl_DString ds;
1234
1235                Tcl_DStringInit(&ds);
1236                Tcl_DStringAppend(&ds, nsPtr->fullName, -1);
1237                if (nsPtr != iPtr->globalNsPtr) {
1238                    Tcl_DStringAppend(&ds, "::", 2);
1239                }
1240                Tcl_DStringAppend(&ds, cmdName, -1);
1241               
1242                cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
1243                dataPtr = (ImportedCmdData *)
1244                        ckalloc(sizeof(ImportedCmdData));
1245                importedCmd = Tcl_CreateObjCommand(interp, 
1246                        Tcl_DStringValue(&ds), InvokeImportedCmd,
1247                        (ClientData) dataPtr, DeleteImportedCmd);
1248                dataPtr->realCmdPtr = cmdPtr;
1249                dataPtr->selfPtr = (Command *) importedCmd;
1250
1251                /*
1252                 * Create an ImportRef structure describing this new import
1253                 * command and add it to the import ref list in the "real"
1254                 * command.
1255                 */
1256
1257                refPtr = (ImportRef *) ckalloc(sizeof(ImportRef));
1258                refPtr->importedCmdPtr = (Command *) importedCmd;
1259                refPtr->nextPtr = cmdPtr->importRefPtr;
1260                cmdPtr->importRefPtr = refPtr;
1261            } else {
1262                Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1263                        "can't import command \"", cmdName,
1264                        "\": already exists", (char *) NULL);
1265                return TCL_ERROR;
1266            }
1267        }
1268    }
1269    return TCL_OK;
1270}
1271
1272/*
1273 *----------------------------------------------------------------------
1274 *
1275 * Tcl_ForgetImport --
1276 *
1277 *      Deletes previously imported commands. Given a pattern that may
1278 *      include the name of an exporting namespace, this procedure first
1279 *      finds all matching exported commands. It then looks in the namespace
1280 *      specified by namespacePtr for any corresponding previously imported
1281 *      commands, which it deletes. If namespacePtr is NULL, commands are
1282 *      deleted from the current namespace.
1283 *
1284 * Results:
1285 *      Returns TCL_OK if successful. If there is an error, returns
1286 *      TCL_ERROR and puts an error message in the interpreter's result
1287 *      object.
1288 *
1289 * Side effects:
1290 *      May delete commands.
1291 *
1292 *----------------------------------------------------------------------
1293 */
1294
1295int
1296Tcl_ForgetImport(interp, namespacePtr, pattern)
1297    Tcl_Interp *interp;          /* Current interpreter. */
1298    Tcl_Namespace *namespacePtr; /* Points to the namespace from which
1299                                  * previously imported commands should be
1300                                  * removed. NULL for current namespace. */
1301    char *pattern;               /* String pattern indicating which imported
1302                                  * commands to remove. This pattern should
1303                                  * be qualified by the name of the
1304                                  * namespace from which the command(s) were
1305                                  * imported. */
1306{
1307    Namespace *nsPtr, *importNsPtr, *dummyPtr, *actualCtxPtr;
1308    char *simplePattern, *cmdName;
1309    register Tcl_HashEntry *hPtr;
1310    Tcl_HashSearch search;
1311    Command *cmdPtr;
1312
1313    /*
1314     * If the specified namespace is NULL, use the current namespace.
1315     */
1316
1317    if (namespacePtr == NULL) {
1318        nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
1319    } else {
1320        nsPtr = (Namespace *) namespacePtr;
1321    }
1322
1323    /*
1324     * From the pattern, find the namespace from which we are importing
1325     * and get the simple pattern (no namespace qualifiers or ::'s) at
1326     * the end.
1327     */
1328
1329    TclGetNamespaceForQualName(interp, pattern, nsPtr,
1330       /*flags*/ 0, &importNsPtr, &dummyPtr, &actualCtxPtr, &simplePattern);
1331
1332    if (importNsPtr == NULL) {
1333        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1334                "unknown namespace in namespace forget pattern \"",
1335                pattern, "\"", (char *) NULL);
1336        return TCL_ERROR;
1337    }
1338
1339    /*
1340     * Scan through the command table in the source namespace and look for
1341     * exported commands that match the string pattern. If the current
1342     * namespace has an imported command that refers to one of those real
1343     * commands, delete it.
1344     */
1345
1346    for (hPtr = Tcl_FirstHashEntry(&importNsPtr->cmdTable, &search);
1347            (hPtr != NULL);
1348            hPtr = Tcl_NextHashEntry(&search)) {
1349        cmdName = Tcl_GetHashKey(&importNsPtr->cmdTable, hPtr);
1350        if (Tcl_StringMatch(cmdName, simplePattern)) {
1351            hPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName);
1352            if (hPtr != NULL) { /* cmd of same name in current namespace */
1353                cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
1354                if (cmdPtr->deleteProc == DeleteImportedCmd) { 
1355                    Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
1356                }
1357            }
1358        }
1359    }
1360    return TCL_OK;
1361}
1362
1363/*
1364 *----------------------------------------------------------------------
1365 *
1366 * TclGetOriginalCommand --
1367 *
1368 *      An imported command is created in an namespace when it imports a
1369 *      "real" command from another namespace. If the specified command is a
1370 *      imported command, this procedure returns the original command it
1371 *      refers to. 
1372 *
1373 * Results:
1374 *      If the command was imported into a sequence of namespaces a, b,...,n
1375 *      where each successive namespace just imports the command from the
1376 *      previous namespace, this procedure returns the Tcl_Command token in
1377 *      the first namespace, a. Otherwise, if the specified command is not
1378 *      an imported command, the procedure returns NULL.
1379 *
1380 * Side effects:
1381 *      None.
1382 *
1383 *----------------------------------------------------------------------
1384 */
1385
1386Tcl_Command
1387TclGetOriginalCommand(command)
1388    Tcl_Command command;        /* The command for which the original
1389                                 * command should be returned. */
1390{
1391    register Command *cmdPtr = (Command *) command;
1392    ImportedCmdData *dataPtr;
1393
1394    if (cmdPtr->deleteProc != DeleteImportedCmd) {
1395        return (Tcl_Command) NULL;
1396    }
1397   
1398    while (cmdPtr->deleteProc == DeleteImportedCmd) {
1399        dataPtr = (ImportedCmdData *) cmdPtr->objClientData;
1400        cmdPtr = dataPtr->realCmdPtr;
1401    }
1402    return (Tcl_Command) cmdPtr;
1403}
1404
1405/*
1406 *----------------------------------------------------------------------
1407 *
1408 * InvokeImportedCmd --
1409 *
1410 *      Invoked by Tcl whenever the user calls an imported command that
1411 *      was created by Tcl_Import. Finds the "real" command (in another
1412 *      namespace), and passes control to it.
1413 *
1414 * Results:
1415 *      Returns TCL_OK if successful, and  TCL_ERROR if anything goes wrong.
1416 *
1417 * Side effects:
1418 *      Returns a result in the interpreter's result object. If anything
1419 *      goes wrong, the result object is set to an error message.
1420 *
1421 *----------------------------------------------------------------------
1422 */
1423
1424static int
1425InvokeImportedCmd(clientData, interp, objc, objv)
1426    ClientData clientData;      /* Points to the imported command's
1427                                 * ImportedCmdData structure. */
1428    Tcl_Interp *interp;         /* Current interpreter. */
1429    int objc;                   /* Number of arguments. */
1430    Tcl_Obj *CONST objv[];      /* The argument objects. */
1431{
1432    register ImportedCmdData *dataPtr = (ImportedCmdData *) clientData;
1433    register Command *realCmdPtr = dataPtr->realCmdPtr;
1434
1435    return (*realCmdPtr->objProc)(realCmdPtr->objClientData, interp,
1436            objc, objv);
1437}
1438
1439/*
1440 *----------------------------------------------------------------------
1441 *
1442 * DeleteImportedCmd --
1443 *
1444 *      Invoked by Tcl whenever an imported command is deleted. The "real"
1445 *      command keeps a list of all the imported commands that refer to it,
1446 *      so those imported commands can be deleted when the real command is
1447 *      deleted. This procedure removes the imported command reference from
1448 *      the real command's list, and frees up the memory associated with
1449 *      the imported command.
1450 *
1451 * Results:
1452 *      None.
1453 *
1454 * Side effects:
1455 *      Removes the imported command from the real command's import list.
1456 *
1457 *----------------------------------------------------------------------
1458 */
1459
1460static void
1461DeleteImportedCmd(clientData)
1462    ClientData clientData;      /* Points to the imported command's
1463                                 * ImportedCmdData structure. */
1464{
1465    ImportedCmdData *dataPtr = (ImportedCmdData *) clientData;
1466    Command *realCmdPtr = dataPtr->realCmdPtr;
1467    Command *selfPtr = dataPtr->selfPtr;
1468    register ImportRef *refPtr, *prevPtr;
1469
1470    prevPtr = NULL;
1471    for (refPtr = realCmdPtr->importRefPtr;  refPtr != NULL;
1472            refPtr = refPtr->nextPtr) {
1473        if (refPtr->importedCmdPtr == selfPtr) {
1474            /*
1475             * Remove *refPtr from real command's list of imported commands
1476             * that refer to it.
1477             */
1478           
1479            if (prevPtr == NULL) { /* refPtr is first in list */
1480                realCmdPtr->importRefPtr = refPtr->nextPtr;
1481            } else {
1482                prevPtr->nextPtr = refPtr->nextPtr;
1483            }
1484            ckfree((char *) refPtr);
1485            ckfree((char *) dataPtr);
1486            return;
1487        }
1488        prevPtr = refPtr;
1489    }
1490       
1491    panic("DeleteImportedCmd: did not find cmd in real cmd's list of import references");
1492}
1493
1494/*
1495 *----------------------------------------------------------------------
1496 *
1497 * TclGetNamespaceForQualName --
1498 *
1499 *      Given a qualified name specifying a command, variable, or namespace,
1500 *      and a namespace in which to resolve the name, this procedure returns
1501 *      a pointer to the namespace that contains the item. A qualified name
1502 *      consists of the "simple" name of an item qualified by the names of
1503 *      an arbitrary number of containing namespace separated by "::"s. If
1504 *      the qualified name starts with "::", it is interpreted absolutely
1505 *      from the global namespace. Otherwise, it is interpreted relative to
1506 *      the namespace specified by cxtNsPtr if it is non-NULL. If cxtNsPtr
1507 *      is NULL, the name is interpreted relative to the current namespace.
1508 *
1509 *      A relative name like "foo::bar::x" can be found starting in either
1510 *      the current namespace or in the global namespace. So each search
1511 *      usually follows two tracks, and two possible namespaces are
1512 *      returned. If the procedure sets either *nsPtrPtr or *altNsPtrPtr to
1513 *      NULL, then that path failed.
1514 *
1515 *      If "flags" contains TCL_GLOBAL_ONLY, the relative qualified name is
1516 *      sought only in the global :: namespace. The alternate search
1517 *      (also) starting from the global namespace is ignored and
1518 *      *altNsPtrPtr is set NULL.
1519 *
1520 *      If "flags" contains TCL_NAMESPACE_ONLY, the relative qualified
1521 *      name is sought only in the namespace specified by cxtNsPtr. The
1522 *      alternate search starting from the global namespace is ignored and
1523 *      *altNsPtrPtr is set NULL. If both TCL_GLOBAL_ONLY and
1524 *      TCL_NAMESPACE_ONLY are specified, TCL_GLOBAL_ONLY is ignored and
1525 *      the search starts from the namespace specified by cxtNsPtr.
1526 *
1527 *      If "flags" contains CREATE_NS_IF_UNKNOWN, all namespace
1528 *      components of the qualified name that cannot be found are
1529 *      automatically created within their specified parent. This makes sure
1530 *      that functions like Tcl_CreateCommand always succeed. There is no
1531 *      alternate search path, so *altNsPtrPtr is set NULL.
1532 *
1533 *      If "flags" contains FIND_ONLY_NS, the qualified name is treated as a
1534 *      reference to a namespace, and the entire qualified name is
1535 *      followed. If the name is relative, the namespace is looked up only
1536 *      in the current namespace. A pointer to the namespace is stored in
1537 *      *nsPtrPtr and NULL is stored in *simpleNamePtr. Otherwise, if
1538 *      FIND_ONLY_NS is not specified, only the leading components are
1539 *      treated as namespace names, and a pointer to the simple name of the
1540 *      final component is stored in *simpleNamePtr.
1541 *
1542 * Results:
1543 *     It sets *nsPtrPtr and *altNsPtrPtr to point to the two possible
1544 *     namespaces which represent the last (containing) namespace in the
1545 *     qualified name. If the procedure sets either *nsPtrPtr or *altNsPtrPtr
1546 *     to NULL, then the search along that path failed.  The procedure also
1547 *     stores a pointer to the simple name of the final component in
1548 *     *simpleNamePtr. If the qualified name is "::" or was treated as a
1549 *     namespace reference (FIND_ONLY_NS), the procedure stores a pointer
1550 *     to the namespace in *nsPtrPtr, NULL in *altNsPtrPtr, and sets
1551 *      *simpleNamePtr to point to an empty string.
1552 *
1553 *      *actualCxtPtrPtr is set to the actual context namespace. It is
1554 *      set to the input context namespace pointer in cxtNsPtr. If cxtNsPtr
1555 *      is NULL, it is set to the current namespace context.
1556 *
1557 *      For backwards compatibility with the TclPro byte code loader,
1558 *      this function always returns TCL_OK.
1559 *
1560 * Side effects:
1561 *     If "flags" contains CREATE_NS_IF_UNKNOWN, new namespaces may be
1562 *     created.
1563 *
1564 *----------------------------------------------------------------------
1565 */
1566
1567int
1568TclGetNamespaceForQualName(interp, qualName, cxtNsPtr, flags,
1569        nsPtrPtr, altNsPtrPtr, actualCxtPtrPtr, simpleNamePtr)
1570    Tcl_Interp *interp;          /* Interpreter in which to find the
1571                                  * namespace containing qualName. */
1572    register char *qualName;     /* A namespace-qualified name of an
1573                                  * command, variable, or namespace. */
1574    Namespace *cxtNsPtr;         /* The namespace in which to start the
1575                                  * search for qualName's namespace. If NULL
1576                                  * start from the current namespace.
1577                                  * Ignored if TCL_GLOBAL_ONLY or
1578                                  * TCL_NAMESPACE_ONLY are set. */
1579    int flags;                   /* Flags controlling the search: an OR'd
1580                                  * combination of TCL_GLOBAL_ONLY,
1581                                  * TCL_NAMESPACE_ONLY,
1582                                  * CREATE_NS_IF_UNKNOWN, and
1583                                  * FIND_ONLY_NS. */
1584    Namespace **nsPtrPtr;        /* Address where procedure stores a pointer
1585                                  * to containing namespace if qualName is
1586                                  * found starting from *cxtNsPtr or, if
1587                                  * TCL_GLOBAL_ONLY is set, if qualName is
1588                                  * found in the global :: namespace. NULL
1589                                  * is stored otherwise. */
1590    Namespace **altNsPtrPtr;     /* Address where procedure stores a pointer
1591                                  * to containing namespace if qualName is
1592                                  * found starting from the global ::
1593                                  * namespace. NULL is stored if qualName
1594                                  * isn't found starting from :: or if the
1595                                  * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
1596                                  * CREATE_NS_IF_UNKNOWN, FIND_ONLY_NS flag
1597                                  * is set. */
1598    Namespace **actualCxtPtrPtr; /* Address where procedure stores a pointer
1599                                  * to the actual namespace from which the
1600                                  * search started. This is either cxtNsPtr,
1601                                  * the :: namespace if TCL_GLOBAL_ONLY was
1602                                  * specified, or the current namespace if
1603                                  * cxtNsPtr was NULL. */
1604    char **simpleNamePtr;        /* Address where procedure stores the
1605                                  * simple name at end of the qualName, or
1606                                  * NULL if qualName is "::" or the flag
1607                                  * FIND_ONLY_NS was specified. */
1608{
1609    Interp *iPtr = (Interp *) interp;
1610    Namespace *nsPtr = cxtNsPtr;
1611    Namespace *altNsPtr;
1612    Namespace *globalNsPtr = iPtr->globalNsPtr;
1613    register char *start, *end;
1614    char *nsName;
1615    Tcl_HashEntry *entryPtr;
1616    Tcl_DString buffer;
1617    int len;
1618
1619    /*
1620     * Determine the context namespace nsPtr in which to start the primary
1621     * search. If TCL_NAMESPACE_ONLY or FIND_ONLY_NS was specified, search
1622     * from the current namespace. If the qualName name starts with a "::"
1623     * or TCL_GLOBAL_ONLY was specified, search from the global
1624     * namespace. Otherwise, use the given namespace given in cxtNsPtr, or
1625     * if that is NULL, use the current namespace context. Note that we
1626     * always treat two or more adjacent ":"s as a namespace separator.
1627     */
1628
1629    if (flags & (TCL_NAMESPACE_ONLY | FIND_ONLY_NS)) {
1630        nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
1631    } else if (flags & TCL_GLOBAL_ONLY) {
1632        nsPtr = globalNsPtr;
1633    } else if (nsPtr == NULL) {
1634        if (iPtr->varFramePtr != NULL) {
1635            nsPtr = iPtr->varFramePtr->nsPtr;
1636        } else {
1637            nsPtr = iPtr->globalNsPtr;
1638        }
1639    }
1640
1641    start = qualName;           /* pts to start of qualifying namespace */
1642    if ((*qualName == ':') && (*(qualName+1) == ':')) {
1643        start = qualName+2;     /* skip over the initial :: */
1644        while (*start == ':') {
1645            start++;            /* skip over a subsequent : */
1646        }
1647        nsPtr = globalNsPtr;
1648        if (*start == '\0') {   /* qualName is just two or more ":"s */
1649            *nsPtrPtr        = globalNsPtr;
1650            *altNsPtrPtr     = NULL;
1651            *actualCxtPtrPtr = globalNsPtr;
1652            *simpleNamePtr   = start; /* points to empty string */
1653            return TCL_OK;
1654        }
1655    }
1656    *actualCxtPtrPtr = nsPtr;
1657
1658    /*
1659     * Start an alternate search path starting with the global namespace.
1660     * However, if the starting context is the global namespace, or if the
1661     * flag is set to search only the namespace *cxtNsPtr, ignore the
1662     * alternate search path.
1663     */
1664
1665    altNsPtr = globalNsPtr;
1666    if ((nsPtr == globalNsPtr)
1667            || (flags & (TCL_NAMESPACE_ONLY | FIND_ONLY_NS))) {
1668        altNsPtr = NULL;
1669    }
1670
1671    /*
1672     * Loop to resolve each namespace qualifier in qualName.
1673     */
1674
1675    Tcl_DStringInit(&buffer);
1676    end = start;
1677    while (*start != '\0') {
1678        /*
1679         * Find the next namespace qualifier (i.e., a name ending in "::")
1680         * or the end of the qualified name  (i.e., a name ending in "\0").
1681         * Set len to the number of characters, starting from start,
1682         * in the name; set end to point after the "::"s or at the "\0".
1683         */
1684
1685        len = 0;
1686        for (end = start;  *end != '\0';  end++) {
1687            if ((*end == ':') && (*(end+1) == ':')) {
1688                end += 2;       /* skip over the initial :: */
1689                while (*end == ':') {
1690                    end++;      /* skip over the subsequent : */
1691                }
1692                break;          /* exit for loop; end is after ::'s */
1693            }
1694            len++;
1695        }
1696
1697        if ((*end == '\0')
1698                && !((end-start >= 2) && (*(end-1) == ':') && (*(end-2) == ':'))) {
1699            /*
1700             * qualName ended with a simple name at start. If FIND_ONLY_NS
1701             * was specified, look this up as a namespace. Otherwise,
1702             * start is the name of a cmd or var and we are done.
1703             */
1704           
1705            if (flags & FIND_ONLY_NS) {
1706                nsName = start;
1707            } else {
1708                *nsPtrPtr      = nsPtr;
1709                *altNsPtrPtr   = altNsPtr;
1710                *simpleNamePtr = start;
1711                Tcl_DStringFree(&buffer);
1712               return TCL_OK;
1713            }
1714        } else {
1715            /*
1716             * start points to the beginning of a namespace qualifier ending
1717             * in "::". end points to the start of a name in that namespace
1718             * that might be empty. Copy the namespace qualifier to a
1719             * buffer so it can be null terminated. We can't modify the
1720             * incoming qualName since it may be a string constant.
1721             */
1722
1723            Tcl_DStringSetLength(&buffer, 0);
1724            Tcl_DStringAppend(&buffer, start, len);
1725            nsName = Tcl_DStringValue(&buffer);
1726        }
1727
1728        /*
1729         * Look up the namespace qualifier nsName in the current namespace
1730         * context. If it isn't found but CREATE_NS_IF_UNKNOWN is set,
1731         * create that qualifying namespace. This is needed for procedures
1732         * like Tcl_CreateCommand that cannot fail.
1733         */
1734
1735        if (nsPtr != NULL) {
1736            entryPtr = Tcl_FindHashEntry(&nsPtr->childTable, nsName);
1737            if (entryPtr != NULL) {
1738                nsPtr = (Namespace *) Tcl_GetHashValue(entryPtr);
1739            } else if (flags & CREATE_NS_IF_UNKNOWN) {
1740                Tcl_CallFrame frame;
1741               
1742               (void) Tcl_PushCallFrame(interp, &frame,
1743                        (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 0);
1744
1745                nsPtr = (Namespace *) Tcl_CreateNamespace(interp, nsName,
1746                        (ClientData) NULL, (Tcl_NamespaceDeleteProc *) NULL);
1747                Tcl_PopCallFrame(interp);
1748
1749                if (nsPtr == NULL) {
1750                   panic("Could not create namespace '%s'", nsName);
1751                }
1752            } else {            /* namespace not found and wasn't created */
1753                nsPtr = NULL;
1754            }
1755        }
1756
1757        /*
1758         * Look up the namespace qualifier in the alternate search path too.
1759         */
1760
1761        if (altNsPtr != NULL) {
1762            entryPtr = Tcl_FindHashEntry(&altNsPtr->childTable, nsName);
1763            if (entryPtr != NULL) {
1764                altNsPtr = (Namespace *) Tcl_GetHashValue(entryPtr);
1765            } else {
1766                altNsPtr = NULL;
1767            }
1768        }
1769
1770        /*
1771         * If both search paths have failed, return NULL results.
1772         */
1773
1774        if ((nsPtr == NULL) && (altNsPtr == NULL)) {
1775            *nsPtrPtr      = NULL;
1776            *altNsPtrPtr   = NULL;
1777            *simpleNamePtr = NULL;
1778            Tcl_DStringFree(&buffer);
1779            return TCL_OK;
1780        }
1781
1782        start = end;
1783    }
1784
1785    /*
1786     * We ignore trailing "::"s in a namespace name, but in a command or
1787     * variable name, trailing "::"s refer to the cmd or var named {}.
1788     */
1789
1790    if ((flags & FIND_ONLY_NS)
1791            || ((end > start ) && (*(end-1) != ':'))) {
1792        *simpleNamePtr = NULL; /* found namespace name */
1793    } else {
1794        *simpleNamePtr = end;  /* found cmd/var: points to empty string */
1795    }
1796
1797    /*
1798     * As a special case, if we are looking for a namespace and qualName
1799     * is "" and the current active namespace (nsPtr) is not the global
1800     * namespace, return NULL (no namespace was found). This is because
1801     * namespaces can not have empty names except for the global namespace.
1802     */
1803
1804    if ((flags & FIND_ONLY_NS) && (*qualName == '\0')
1805            && (nsPtr != globalNsPtr)) {
1806        nsPtr = NULL;
1807    }
1808
1809    *nsPtrPtr    = nsPtr;
1810    *altNsPtrPtr = altNsPtr;
1811    Tcl_DStringFree(&buffer);
1812    return TCL_OK;
1813}
1814
1815/*
1816 *----------------------------------------------------------------------
1817 *
1818 * Tcl_FindNamespace --
1819 *
1820 *      Searches for a namespace.
1821 *
1822 * Results:
1823 *      Returns a pointer to the namespace if it is found. Otherwise,
1824 *      returns NULL and leaves an error message in the interpreter's
1825 *      result object if "flags" contains TCL_LEAVE_ERR_MSG.
1826 *
1827 * Side effects:
1828 *      None.
1829 *
1830 *----------------------------------------------------------------------
1831 */
1832
1833Tcl_Namespace *
1834Tcl_FindNamespace(interp, name, contextNsPtr, flags)
1835    Tcl_Interp *interp;          /* The interpreter in which to find the
1836                                  * namespace. */
1837    char *name;                  /* Namespace name. If it starts with "::",
1838                                  * will be looked up in global namespace.
1839                                  * Else, looked up first in contextNsPtr
1840                                  * (current namespace if contextNsPtr is
1841                                  * NULL), then in global namespace. */
1842    Tcl_Namespace *contextNsPtr; /* Ignored if TCL_GLOBAL_ONLY flag is set
1843                                  * or if the name starts with "::".
1844                                  * Otherwise, points to namespace in which
1845                                  * to resolve name; if NULL, look up name
1846                                  * in the current namespace. */
1847    register int flags;          /* Flags controlling namespace lookup: an
1848                                  * OR'd combination of TCL_GLOBAL_ONLY and
1849                                  * TCL_LEAVE_ERR_MSG flags. */
1850{
1851    Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr;
1852    char *dummy;
1853
1854    /*
1855     * Find the namespace(s) that contain the specified namespace name.
1856     * Add the FIND_ONLY_NS flag to resolve the name all the way down
1857     * to its last component, a namespace.
1858     */
1859
1860    TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
1861       (flags | FIND_ONLY_NS), &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
1862
1863    if (nsPtr != NULL) {
1864       return (Tcl_Namespace *) nsPtr;
1865    } else if (flags & TCL_LEAVE_ERR_MSG) {
1866        Tcl_ResetResult(interp);
1867        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1868                "unknown namespace \"", name, "\"", (char *) NULL);
1869    }
1870    return NULL;
1871}
1872
1873/*
1874 *----------------------------------------------------------------------
1875 *
1876 * Tcl_FindCommand --
1877 *
1878 *      Searches for a command.
1879 *
1880 * Results:
1881 *      Returns a token for the command if it is found. Otherwise, if it
1882 *      can't be found or there is an error, returns NULL and leaves an
1883 *      error message in the interpreter's result object if "flags"
1884 *      contains TCL_LEAVE_ERR_MSG.
1885 *
1886 * Side effects:
1887 *      None.
1888 *
1889 *----------------------------------------------------------------------
1890 */
1891
1892Tcl_Command
1893Tcl_FindCommand(interp, name, contextNsPtr, flags)
1894    Tcl_Interp *interp;         /* The interpreter in which to find the
1895                                  * command and to report errors. */
1896    char *name;                  /* Command's name. If it starts with "::",
1897                                  * will be looked up in global namespace.
1898                                  * Else, looked up first in contextNsPtr
1899                                  * (current namespace if contextNsPtr is
1900                                  * NULL), then in global namespace. */
1901    Tcl_Namespace *contextNsPtr; /* Ignored if TCL_GLOBAL_ONLY flag set.
1902                                  * Otherwise, points to namespace in which
1903                                  * to resolve name. If NULL, look up name
1904                                  * in the current namespace. */
1905    int flags;                   /* An OR'd combination of flags:
1906                                  * TCL_GLOBAL_ONLY (look up name only in
1907                                  * global namespace), TCL_NAMESPACE_ONLY
1908                                  * (look up only in contextNsPtr, or the
1909                                  * current namespace if contextNsPtr is
1910                                  * NULL), and TCL_LEAVE_ERR_MSG. If both
1911                                  * TCL_GLOBAL_ONLY and TCL_NAMESPACE_ONLY
1912                                  * are given, TCL_GLOBAL_ONLY is
1913                                  * ignored. */
1914{
1915    Interp *iPtr = (Interp*)interp;
1916
1917    ResolverScheme *resPtr;
1918    Namespace *nsPtr[2], *cxtNsPtr;
1919    char *simpleName;
1920    register Tcl_HashEntry *entryPtr;
1921    register Command *cmdPtr;
1922    register int search;
1923    int result;
1924    Tcl_Command cmd;
1925
1926    /*
1927     * If this namespace has a command resolver, then give it first
1928     * crack at the command resolution.  If the interpreter has any
1929     * command resolvers, consult them next.  The command resolver
1930     * procedures may return a Tcl_Command value, they may signal
1931     * to continue onward, or they may signal an error.
1932     */
1933    if ((flags & TCL_GLOBAL_ONLY) != 0) {
1934        cxtNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
1935    }
1936    else if (contextNsPtr != NULL) {
1937        cxtNsPtr = (Namespace *) contextNsPtr;
1938    }
1939    else {
1940        cxtNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
1941    }
1942
1943    if (cxtNsPtr->cmdResProc != NULL || iPtr->resolverPtr != NULL) {
1944        resPtr = iPtr->resolverPtr;
1945
1946        if (cxtNsPtr->cmdResProc) {
1947            result = (*cxtNsPtr->cmdResProc)(interp, name,
1948                (Tcl_Namespace *) cxtNsPtr, flags, &cmd);
1949        } else {
1950            result = TCL_CONTINUE;
1951        }
1952
1953        while (result == TCL_CONTINUE && resPtr) {
1954            if (resPtr->cmdResProc) {
1955                result = (*resPtr->cmdResProc)(interp, name,
1956                    (Tcl_Namespace *) cxtNsPtr, flags, &cmd);
1957            }
1958            resPtr = resPtr->nextPtr;
1959        }
1960
1961        if (result == TCL_OK) {
1962            return cmd;
1963        }
1964        else if (result != TCL_CONTINUE) {
1965            return (Tcl_Command) NULL;
1966        }
1967    }
1968
1969    /*
1970     * Find the namespace(s) that contain the command.
1971     */
1972
1973    TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
1974       flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName);
1975
1976    /*
1977     * Look for the command in the command table of its namespace.
1978     * Be sure to check both possible search paths: from the specified
1979     * namespace context and from the global namespace.
1980     */
1981
1982    cmdPtr = NULL;
1983    for (search = 0;  (search < 2) && (cmdPtr == NULL);  search++) {
1984        if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
1985            entryPtr = Tcl_FindHashEntry(&nsPtr[search]->cmdTable,
1986                    simpleName);
1987            if (entryPtr != NULL) {
1988                cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
1989            }
1990        }
1991    }
1992    if (cmdPtr != NULL) {
1993        return (Tcl_Command) cmdPtr;
1994    } else if (flags & TCL_LEAVE_ERR_MSG) {
1995        Tcl_ResetResult(interp);
1996        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1997                "unknown command \"", name, "\"", (char *) NULL);
1998    }
1999
2000    return (Tcl_Command) NULL;
2001}
2002
2003/*
2004 *----------------------------------------------------------------------
2005 *
2006 * Tcl_FindNamespaceVar --
2007 *
2008 *      Searches for a namespace variable, a variable not local to a
2009 *      procedure. The variable can be either a scalar or an array, but
2010 *      may not be an element of an array.
2011 *
2012 * Results:
2013 *      Returns a token for the variable if it is found. Otherwise, if it
2014 *      can't be found or there is an error, returns NULL and leaves an
2015 *      error message in the interpreter's result object if "flags"
2016 *      contains TCL_LEAVE_ERR_MSG.
2017 *
2018 * Side effects:
2019 *      None.
2020 *
2021 *----------------------------------------------------------------------
2022 */
2023
2024Tcl_Var
2025Tcl_FindNamespaceVar(interp, name, contextNsPtr, flags)
2026    Tcl_Interp *interp;          /* The interpreter in which to find the
2027                                  * variable. */
2028    char *name;                  /* Variable's name. If it starts with "::",
2029                                  * will be looked up in global namespace.
2030                                  * Else, looked up first in contextNsPtr
2031                                  * (current namespace if contextNsPtr is
2032                                  * NULL), then in global namespace. */
2033    Tcl_Namespace *contextNsPtr; /* Ignored if TCL_GLOBAL_ONLY flag set.
2034                                  * Otherwise, points to namespace in which
2035                                  * to resolve name. If NULL, look up name
2036                                  * in the current namespace. */
2037    int flags;                   /* An OR'd combination of flags:
2038                                  * TCL_GLOBAL_ONLY (look up name only in
2039                                  * global namespace), TCL_NAMESPACE_ONLY
2040                                  * (look up only in contextNsPtr, or the
2041                                  * current namespace if contextNsPtr is
2042                                  * NULL), and TCL_LEAVE_ERR_MSG. If both
2043                                  * TCL_GLOBAL_ONLY and TCL_NAMESPACE_ONLY
2044                                  * are given, TCL_GLOBAL_ONLY is
2045                                  * ignored. */
2046{
2047    Interp *iPtr = (Interp*)interp;
2048    ResolverScheme *resPtr;
2049    Namespace *nsPtr[2], *cxtNsPtr;
2050    char *simpleName;
2051    Tcl_HashEntry *entryPtr;
2052    Var *varPtr;
2053    register int search;
2054    int result;
2055    Tcl_Var var;
2056
2057    /*
2058     * If this namespace has a variable resolver, then give it first
2059     * crack at the variable resolution.  It may return a Tcl_Var
2060     * value, it may signal to continue onward, or it may signal
2061     * an error.
2062     */
2063    if ((flags & TCL_GLOBAL_ONLY) != 0) {
2064        cxtNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
2065    }
2066    else if (contextNsPtr != NULL) {
2067        cxtNsPtr = (Namespace *) contextNsPtr;
2068    }
2069    else {
2070        cxtNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
2071    }
2072
2073    if (cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL) {
2074        resPtr = iPtr->resolverPtr;
2075
2076        if (cxtNsPtr->varResProc) {
2077            result = (*cxtNsPtr->varResProc)(interp, name,
2078                (Tcl_Namespace *) cxtNsPtr, flags, &var);
2079        } else {
2080            result = TCL_CONTINUE;
2081        }
2082
2083        while (result == TCL_CONTINUE && resPtr) {
2084            if (resPtr->varResProc) {
2085                result = (*resPtr->varResProc)(interp, name,
2086                    (Tcl_Namespace *) cxtNsPtr, flags, &var);
2087            }
2088            resPtr = resPtr->nextPtr;
2089        }
2090
2091        if (result == TCL_OK) {
2092            return var;
2093        }
2094        else if (result != TCL_CONTINUE) {
2095            return (Tcl_Var) NULL;
2096        }
2097    }
2098
2099    /*
2100     * Find the namespace(s) that contain the variable.
2101     */
2102
2103    TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
2104       flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName);
2105
2106    /*
2107     * Look for the variable in the variable table of its namespace.
2108     * Be sure to check both possible search paths: from the specified
2109     * namespace context and from the global namespace.
2110     */
2111
2112    varPtr = NULL;
2113    for (search = 0;  (search < 2) && (varPtr == NULL);  search++) {
2114        if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
2115            entryPtr = Tcl_FindHashEntry(&nsPtr[search]->varTable,
2116                    simpleName);
2117            if (entryPtr != NULL) {
2118                varPtr = (Var *) Tcl_GetHashValue(entryPtr);
2119            }
2120        }
2121    }
2122    if (varPtr != NULL) {
2123        return (Tcl_Var) varPtr;
2124    } else if (flags & TCL_LEAVE_ERR_MSG) {
2125        Tcl_ResetResult(interp);
2126        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
2127                "unknown variable \"", name, "\"", (char *) NULL);
2128    }
2129    return (Tcl_Var) NULL;
2130}
2131
2132/*
2133 *----------------------------------------------------------------------
2134 *
2135 * TclResetShadowedCmdRefs --
2136 *
2137 *      Called when a command is added to a namespace to check for existing
2138 *      command references that the new command may invalidate. Consider the
2139 *      following cases that could happen when you add a command "foo" to a
2140 *      namespace "b":
2141 *         1. It could shadow a command named "foo" at the global scope.
2142 *            If it does, all command references in the namespace "b" are
2143 *            suspect.
2144 *         2. Suppose the namespace "b" resides in a namespace "a".
2145 *            Then to "a" the new command "b::foo" could shadow another
2146 *            command "b::foo" in the global namespace. If so, then all
2147 *            command references in "a" are suspect.
2148 *      The same checks are applied to all parent namespaces, until we
2149 *      reach the global :: namespace.
2150 *
2151 * Results:
2152 *      None.
2153 *
2154 * Side effects:
2155 *      If the new command shadows an existing command, the cmdRefEpoch
2156 *      counter is incremented in each namespace that sees the shadow.
2157 *      This invalidates all command references that were previously cached
2158 *      in that namespace. The next time the commands are used, they are
2159 *      resolved from scratch.
2160 *
2161 *----------------------------------------------------------------------
2162 */
2163
2164void
2165TclResetShadowedCmdRefs(interp, newCmdPtr)
2166    Tcl_Interp *interp;        /* Interpreter containing the new command. */
2167    Command *newCmdPtr;        /* Points to the new command. */
2168{
2169    char *cmdName;
2170    Tcl_HashEntry *hPtr;
2171    register Namespace *nsPtr;
2172    Namespace *trailNsPtr, *shadowNsPtr;
2173    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
2174    int found, i;
2175
2176    /*
2177     * This procedure generates an array used to hold the trail list. This
2178     * starts out with stack-allocated space but uses dynamically-allocated
2179     * storage if needed.
2180     */
2181
2182    Namespace *(trailStorage[NUM_TRAIL_ELEMS]);
2183    Namespace **trailPtr = trailStorage;
2184    int trailFront = -1;
2185    int trailSize = NUM_TRAIL_ELEMS;
2186
2187    /*
2188     * Start at the namespace containing the new command, and work up
2189     * through the list of parents. Stop just before the global namespace,
2190     * since the global namespace can't "shadow" its own entries.
2191     *
2192     * The namespace "trail" list we build consists of the names of each
2193     * namespace that encloses the new command, in order from outermost to
2194     * innermost: for example, "a" then "b". Each iteration of this loop
2195     * eventually extends the trail upwards by one namespace, nsPtr. We use
2196     * this trail list to see if nsPtr (e.g. "a" in 2. above) could have
2197     * now-invalid cached command references. This will happen if nsPtr
2198     * (e.g. "a") contains a sequence of child namespaces (e.g. "b")
2199     * such that there is a identically-named sequence of child namespaces
2200     * starting from :: (e.g. "::b") whose tail namespace contains a command
2201     * also named cmdName.
2202     */
2203
2204    cmdName = Tcl_GetHashKey(newCmdPtr->hPtr->tablePtr, newCmdPtr->hPtr);
2205    for (nsPtr = newCmdPtr->nsPtr;
2206            (nsPtr != NULL) && (nsPtr != globalNsPtr);
2207            nsPtr = nsPtr->parentPtr) {
2208        /*
2209         * Find the maximal sequence of child namespaces contained in nsPtr
2210         * such that there is a identically-named sequence of child
2211         * namespaces starting from ::. shadowNsPtr will be the tail of this
2212         * sequence, or the deepest namespace under :: that might contain a
2213         * command now shadowed by cmdName. We check below if shadowNsPtr
2214         * actually contains a command cmdName.
2215         */
2216
2217        found = 1;
2218        shadowNsPtr = globalNsPtr;
2219
2220        for (i = trailFront;  i >= 0;  i--) {
2221            trailNsPtr = trailPtr[i];
2222            hPtr = Tcl_FindHashEntry(&shadowNsPtr->childTable,
2223                    trailNsPtr->name);
2224            if (hPtr != NULL) {
2225                shadowNsPtr = (Namespace *) Tcl_GetHashValue(hPtr);
2226            } else {
2227                found = 0;
2228                break;
2229            }
2230        }
2231
2232        /*
2233         * If shadowNsPtr contains a command named cmdName, we invalidate
2234         * all of the command refs cached in nsPtr. As a boundary case,
2235         * shadowNsPtr is initially :: and we check for case 1. above.
2236         */
2237
2238        if (found) {
2239            hPtr = Tcl_FindHashEntry(&shadowNsPtr->cmdTable, cmdName);
2240            if (hPtr != NULL) {
2241                nsPtr->cmdRefEpoch++;
2242            }
2243        }
2244
2245        /*
2246         * Insert nsPtr at the front of the trail list: i.e., at the end
2247         * of the trailPtr array.
2248         */
2249
2250        trailFront++;
2251        if (trailFront == trailSize) {
2252            size_t currBytes = trailSize * sizeof(Namespace *);
2253            int newSize = 2*trailSize;
2254            size_t newBytes = newSize * sizeof(Namespace *);
2255            Namespace **newPtr =
2256                    (Namespace **) ckalloc((unsigned) newBytes);
2257           
2258            memcpy((VOID *) newPtr, (VOID *) trailPtr, currBytes);
2259            if (trailPtr != trailStorage) {
2260                ckfree((char *) trailPtr);
2261            }
2262            trailPtr = newPtr;
2263            trailSize = newSize;
2264        }
2265        trailPtr[trailFront] = nsPtr;
2266    }
2267
2268    /*
2269     * Free any allocated storage.
2270     */
2271   
2272    if (trailPtr != trailStorage) {
2273        ckfree((char *) trailPtr);
2274    }
2275}
2276
2277/*
2278 *----------------------------------------------------------------------
2279 *
2280 * GetNamespaceFromObj --
2281 *
2282 *      Returns the namespace specified by the name in a Tcl_Obj.
2283 *
2284 * Results:
2285 *      Returns TCL_OK if the namespace was resolved successfully, and
2286 *      stores a pointer to the namespace in the location specified by
2287 *      nsPtrPtr. If the namespace can't be found, the procedure stores
2288 *      NULL in *nsPtrPtr and returns TCL_OK. If anything else goes wrong,
2289 *      this procedure returns TCL_ERROR.
2290 *
2291 * Side effects:
2292 *      May update the internal representation for the object, caching the
2293 *      namespace reference. The next time this procedure is called, the
2294 *      namespace value can be found quickly.
2295 *
2296 *      If anything goes wrong, an error message is left in the
2297 *      interpreter's result object.
2298 *
2299 *----------------------------------------------------------------------
2300 */
2301
2302static int
2303GetNamespaceFromObj(interp, objPtr, nsPtrPtr)
2304    Tcl_Interp *interp;         /* The current interpreter. */
2305    Tcl_Obj *objPtr;            /* The object to be resolved as the name
2306                                 * of a namespace. */
2307    Tcl_Namespace **nsPtrPtr;   /* Result namespace pointer goes here. */
2308{
2309    register ResolvedNsName *resNamePtr;
2310    register Namespace *nsPtr;
2311    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
2312    int result;
2313
2314    /*
2315     * Get the internal representation, converting to a namespace type if
2316     * needed. The internal representation is a ResolvedNsName that points
2317     * to the actual namespace.
2318     */
2319
2320    if (objPtr->typePtr != &tclNsNameType) {
2321        result = tclNsNameType.setFromAnyProc(interp, objPtr);
2322        if (result != TCL_OK) {
2323            return TCL_ERROR;
2324        }
2325    }
2326    resNamePtr = (ResolvedNsName *) objPtr->internalRep.otherValuePtr;
2327
2328    /*
2329     * Check the context namespace of the resolved symbol to make sure that
2330     * it is fresh. If not, then force another conversion to the namespace
2331     * type, to discard the old rep and create a new one. Note that we
2332     * verify that the namespace id of the cached namespace is the same as
2333     * the id when we cached it; this insures that the namespace wasn't
2334     * deleted and a new one created at the same address.
2335     */
2336
2337    nsPtr = NULL;
2338    if ((resNamePtr != NULL)
2339            && (resNamePtr->refNsPtr == currNsPtr)
2340            && (resNamePtr->nsId == resNamePtr->nsPtr->nsId)) {
2341        nsPtr = resNamePtr->nsPtr;
2342        if (nsPtr->flags & NS_DEAD) {
2343            nsPtr = NULL;
2344        }
2345    }
2346    if (nsPtr == NULL) {        /* try again */
2347        result = tclNsNameType.setFromAnyProc(interp, objPtr);
2348        if (result != TCL_OK) {
2349            return TCL_ERROR;
2350        }
2351        resNamePtr = (ResolvedNsName *) objPtr->internalRep.otherValuePtr;
2352        if (resNamePtr != NULL) {
2353            nsPtr = resNamePtr->nsPtr;
2354            if (nsPtr->flags & NS_DEAD) {
2355                nsPtr = NULL;
2356            }
2357        }
2358    }
2359    *nsPtrPtr = (Tcl_Namespace *) nsPtr;
2360    return TCL_OK;
2361}
2362
2363/*
2364 *----------------------------------------------------------------------
2365 *
2366 * Tcl_NamespaceObjCmd --
2367 *
2368 *      Invoked to implement the "namespace" command that creates, deletes,
2369 *      or manipulates Tcl namespaces. Handles the following syntax:
2370 *
2371 *          namespace children ?name? ?pattern?
2372 *          namespace code arg
2373 *          namespace current
2374 *          namespace delete ?name name...?
2375 *          namespace eval name arg ?arg...?
2376 *          namespace export ?-clear? ?pattern pattern...?
2377 *          namespace forget ?pattern pattern...?
2378 *          namespace import ?-force? ?pattern pattern...?
2379 *          namespace inscope name arg ?arg...?
2380 *          namespace origin name
2381 *          namespace parent ?name?
2382 *          namespace qualifiers string
2383 *          namespace tail string
2384 *          namespace which ?-command? ?-variable? name
2385 *
2386 * Results:
2387 *      Returns TCL_OK if the command is successful. Returns TCL_ERROR if
2388 *      anything goes wrong.
2389 *
2390 * Side effects:
2391 *      Based on the subcommand name (e.g., "import"), this procedure
2392 *      dispatches to a corresponding procedure NamespaceXXXCmd defined
2393 *      statically in this file. This procedure's side effects depend on
2394 *      whatever that subcommand procedure does. If there is an error, this
2395 *      procedure returns an error message in the interpreter's result
2396 *      object. Otherwise it may return a result in the interpreter's result
2397 *      object.
2398 *
2399 *----------------------------------------------------------------------
2400 */
2401
2402int
2403Tcl_NamespaceObjCmd(clientData, interp, objc, objv)
2404    ClientData clientData;              /* Arbitrary value passed to cmd. */
2405    Tcl_Interp *interp;                 /* Current interpreter. */
2406    register int objc;                  /* Number of arguments. */
2407    register Tcl_Obj *CONST objv[];     /* Argument objects. */
2408{
2409    static char *subCmds[] = {
2410            "children", "code", "current", "delete",
2411            "eval", "export", "forget", "import",
2412            "inscope", "origin", "parent", "qualifiers",
2413            "tail", "which", (char *) NULL};
2414    enum NSSubCmdIdx {
2415            NSChildrenIdx, NSCodeIdx, NSCurrentIdx, NSDeleteIdx,
2416            NSEvalIdx, NSExportIdx, NSForgetIdx, NSImportIdx,
2417            NSInscopeIdx, NSOriginIdx, NSParentIdx, NSQualifiersIdx,
2418            NSTailIdx, NSWhichIdx
2419    } index;
2420    int result;
2421
2422    if (objc < 2) {
2423        Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg ...?");
2424        return TCL_ERROR;
2425    }
2426
2427    /*
2428     * Return an index reflecting the particular subcommand.
2429     */
2430
2431    result = Tcl_GetIndexFromObj((Tcl_Interp *) interp, objv[1], subCmds,
2432            "option", /*flags*/ 0, (int *) &index);
2433    if (result != TCL_OK) {
2434        return result;
2435    }
2436   
2437    switch (index) {
2438        case NSChildrenIdx:
2439            result = NamespaceChildrenCmd(clientData, interp, objc, objv);
2440            break;
2441        case NSCodeIdx:
2442            result = NamespaceCodeCmd(clientData, interp, objc, objv);
2443            break;
2444        case NSCurrentIdx:
2445            result = NamespaceCurrentCmd(clientData, interp, objc, objv);
2446            break;
2447        case NSDeleteIdx:
2448            result = NamespaceDeleteCmd(clientData, interp, objc, objv);
2449            break;
2450        case NSEvalIdx:
2451            result = NamespaceEvalCmd(clientData, interp, objc, objv);
2452            break;
2453        case NSExportIdx:
2454            result = NamespaceExportCmd(clientData, interp, objc, objv);
2455            break;
2456        case NSForgetIdx:
2457            result = NamespaceForgetCmd(clientData, interp, objc, objv);
2458            break;
2459        case NSImportIdx:
2460            result = NamespaceImportCmd(clientData, interp, objc, objv);
2461            break;
2462        case NSInscopeIdx:
2463            result = NamespaceInscopeCmd(clientData, interp, objc, objv);
2464            break;
2465        case NSOriginIdx:
2466            result = NamespaceOriginCmd(clientData, interp, objc, objv);
2467            break;
2468        case NSParentIdx:
2469            result = NamespaceParentCmd(clientData, interp, objc, objv);
2470            break;
2471        case NSQualifiersIdx:
2472            result = NamespaceQualifiersCmd(clientData, interp, objc, objv);
2473            break;
2474        case NSTailIdx:
2475            result = NamespaceTailCmd(clientData, interp, objc, objv);
2476            break;
2477        case NSWhichIdx:
2478            result = NamespaceWhichCmd(clientData, interp, objc, objv);
2479            break;
2480    }
2481    return result;
2482}
2483
2484/*
2485 *----------------------------------------------------------------------
2486 *
2487 * NamespaceChildrenCmd --
2488 *
2489 *      Invoked to implement the "namespace children" command that returns a
2490 *      list containing the fully-qualified names of the child namespaces of
2491 *      a given namespace. Handles the following syntax:
2492 *
2493 *          namespace children ?name? ?pattern?
2494 *
2495 * Results:
2496 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
2497 *
2498 * Side effects:
2499 *      Returns a result in the interpreter's result object. If anything
2500 *      goes wrong, the result is an error message.
2501 *
2502 *----------------------------------------------------------------------
2503 */
2504
2505static int
2506NamespaceChildrenCmd(dummy, interp, objc, objv)
2507    ClientData dummy;           /* Not used. */
2508    Tcl_Interp *interp;         /* Current interpreter. */
2509    int objc;                   /* Number of arguments. */
2510    Tcl_Obj *CONST objv[];      /* Argument objects. */
2511{
2512    Tcl_Namespace *namespacePtr;
2513    Namespace *nsPtr, *childNsPtr;
2514    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
2515    char *pattern = NULL;
2516    Tcl_DString buffer;
2517    register Tcl_HashEntry *entryPtr;
2518    Tcl_HashSearch search;
2519    Tcl_Obj *listPtr, *elemPtr;
2520
2521    /*
2522     * Get a pointer to the specified namespace, or the current namespace.
2523     */
2524
2525    if (objc == 2) {
2526        nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
2527    } else if ((objc == 3) || (objc == 4)) {
2528        if (GetNamespaceFromObj(interp, objv[2], &namespacePtr) != TCL_OK) {
2529            return TCL_ERROR;
2530        }
2531        if (namespacePtr == NULL) {
2532            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
2533                    "unknown namespace \"",
2534                    Tcl_GetStringFromObj(objv[2], (int *) NULL),
2535                    "\" in namespace children command", (char *) NULL);
2536            return TCL_ERROR;
2537        }
2538        nsPtr = (Namespace *) namespacePtr;
2539    } else {
2540        Tcl_WrongNumArgs(interp, 2, objv, "?name? ?pattern?");
2541        return TCL_ERROR;
2542    }
2543
2544    /*
2545     * Get the glob-style pattern, if any, used to narrow the search.
2546     */
2547
2548    Tcl_DStringInit(&buffer);
2549    if (objc == 4) {
2550        char *name = Tcl_GetStringFromObj(objv[3], (int *) NULL);
2551       
2552        if ((*name == ':') && (*(name+1) == ':')) {
2553            pattern = name;
2554        } else {
2555            Tcl_DStringAppend(&buffer, nsPtr->fullName, -1);
2556            if (nsPtr != globalNsPtr) {
2557                Tcl_DStringAppend(&buffer, "::", 2);
2558            }
2559            Tcl_DStringAppend(&buffer, name, -1);
2560            pattern = Tcl_DStringValue(&buffer);
2561        }
2562    }
2563
2564    /*
2565     * Create a list containing the full names of all child namespaces
2566     * whose names match the specified pattern, if any.
2567     */
2568
2569    listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
2570    entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
2571    while (entryPtr != NULL) {
2572        childNsPtr = (Namespace *) Tcl_GetHashValue(entryPtr);
2573        if ((pattern == NULL)
2574                || Tcl_StringMatch(childNsPtr->fullName, pattern)) {
2575            elemPtr = Tcl_NewStringObj(childNsPtr->fullName, -1);
2576            Tcl_ListObjAppendElement(interp, listPtr, elemPtr);
2577        }
2578        entryPtr = Tcl_NextHashEntry(&search);
2579    }
2580
2581    Tcl_SetObjResult(interp, listPtr);
2582    Tcl_DStringFree(&buffer);
2583    return TCL_OK;
2584}
2585
2586/*
2587 *----------------------------------------------------------------------
2588 *
2589 * NamespaceCodeCmd --
2590 *
2591 *      Invoked to implement the "namespace code" command to capture the
2592 *      namespace context of a command. Handles the following syntax:
2593 *
2594 *          namespace code arg
2595 *
2596 *      Here "arg" can be a list. "namespace code arg" produces a result
2597 *      equivalent to that produced by the command
2598 *
2599 *          list namespace inscope [namespace current] $arg
2600 *
2601 *      However, if "arg" is itself a scoped value starting with
2602 *      "namespace inscope", then the result is just "arg".
2603 *
2604 * Results:
2605 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
2606 *
2607 * Side effects:
2608 *      If anything goes wrong, this procedure returns an error
2609 *      message as the result in the interpreter's result object.
2610 *
2611 *----------------------------------------------------------------------
2612 */
2613
2614static int
2615NamespaceCodeCmd(dummy, interp, objc, objv)
2616    ClientData dummy;           /* Not used. */
2617    Tcl_Interp *interp;         /* Current interpreter. */
2618    int objc;                   /* Number of arguments. */
2619    Tcl_Obj *CONST objv[];      /* Argument objects. */
2620{
2621    Namespace *currNsPtr;
2622    Tcl_Obj *listPtr, *objPtr;
2623    register char *arg, *p;
2624    int length;
2625
2626    if (objc != 3) {
2627        Tcl_WrongNumArgs(interp, 2, objv, "arg");
2628        return TCL_ERROR;
2629    }
2630
2631    /*
2632     * If "arg" is already a scoped value, then return it directly.
2633     */
2634
2635    arg = Tcl_GetStringFromObj(objv[2], &length);
2636    if ((*arg == 'n') && (length > 17)
2637            && (strncmp(arg, "namespace", 9) == 0)) {
2638        for (p = (arg + 9);  (*p == ' ');  p++) {
2639            /* empty body: skip over spaces */
2640        }
2641        if ((*p == 'i') && ((p + 7) <= (arg + length))
2642                && (strncmp(p, "inscope", 7) == 0)) {
2643            Tcl_SetObjResult(interp, objv[2]);
2644            return TCL_OK;
2645        }
2646    }
2647
2648    /*
2649     * Otherwise, construct a scoped command by building a list with
2650     * "namespace inscope", the full name of the current namespace, and
2651     * the argument "arg". By constructing a list, we ensure that scoped
2652     * commands are interpreted properly when they are executed later,
2653     * by the "namespace inscope" command.
2654     */
2655
2656    listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
2657    Tcl_ListObjAppendElement(interp, listPtr,
2658            Tcl_NewStringObj("namespace", -1));
2659    Tcl_ListObjAppendElement(interp, listPtr,
2660            Tcl_NewStringObj("inscope", -1));
2661
2662    currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
2663    if (currNsPtr == (Namespace *) Tcl_GetGlobalNamespace(interp)) {
2664        objPtr = Tcl_NewStringObj("::", -1);
2665    } else {
2666        objPtr = Tcl_NewStringObj(currNsPtr->fullName, -1);
2667    }
2668    Tcl_ListObjAppendElement(interp, listPtr, objPtr);
2669   
2670    Tcl_ListObjAppendElement(interp, listPtr, objv[2]);
2671
2672    Tcl_SetObjResult(interp, listPtr);
2673    return TCL_OK;
2674}
2675
2676/*
2677 *----------------------------------------------------------------------
2678 *
2679 * NamespaceCurrentCmd --
2680 *
2681 *      Invoked to implement the "namespace current" command which returns
2682 *      the fully-qualified name of the current namespace. Handles the
2683 *      following syntax:
2684 *
2685 *          namespace current
2686 *
2687 * Results:
2688 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
2689 *
2690 * Side effects:
2691 *      Returns a result in the interpreter's result object. If anything
2692 *      goes wrong, the result is an error message.
2693 *
2694 *----------------------------------------------------------------------
2695 */
2696
2697static int
2698NamespaceCurrentCmd(dummy, interp, objc, objv)
2699    ClientData dummy;           /* Not used. */
2700    Tcl_Interp *interp;         /* Current interpreter. */
2701    int objc;                   /* Number of arguments. */
2702    Tcl_Obj *CONST objv[];      /* Argument objects. */
2703{
2704    register Namespace *currNsPtr;
2705
2706    if (objc != 2) {
2707        Tcl_WrongNumArgs(interp, 2, objv, NULL);
2708        return TCL_ERROR;
2709    }
2710
2711    /*
2712     * The "real" name of the global namespace ("::") is the null string,
2713     * but we return "::" for it as a convenience to programmers. Note that
2714     * "" and "::" are treated as synonyms by the namespace code so that it
2715     * is still easy to do things like:
2716     *
2717     *    namespace [namespace current]::bar { ... }
2718     */
2719
2720    currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
2721    if (currNsPtr == (Namespace *) Tcl_GetGlobalNamespace(interp)) {
2722        Tcl_AppendToObj(Tcl_GetObjResult(interp), "::", -1);
2723    } else {
2724        Tcl_AppendToObj(Tcl_GetObjResult(interp), currNsPtr->fullName, -1);
2725    }
2726    return TCL_OK;
2727}
2728
2729/*
2730 *----------------------------------------------------------------------
2731 *
2732 * NamespaceDeleteCmd --
2733 *
2734 *      Invoked to implement the "namespace delete" command to delete
2735 *      namespace(s). Handles the following syntax:
2736 *
2737 *          namespace delete ?name name...?
2738 *
2739 *      Each name identifies a namespace. It may include a sequence of
2740 *      namespace qualifiers separated by "::"s. If a namespace is found, it
2741 *      is deleted: all variables and procedures contained in that namespace
2742 *      are deleted. If that namespace is being used on the call stack, it
2743 *      is kept alive (but logically deleted) until it is removed from the
2744 *      call stack: that is, it can no longer be referenced by name but any
2745 *      currently executing procedure that refers to it is allowed to do so
2746 *      until the procedure returns. If the namespace can't be found, this
2747 *      procedure returns an error. If no namespaces are specified, this
2748 *      command does nothing.
2749 *
2750 * Results:
2751 *      Returns TCL_OK if successful, and  TCL_ERROR if anything goes wrong.
2752 *
2753 * Side effects:
2754 *      Deletes the specified namespaces. If anything goes wrong, this
2755 *      procedure returns an error message in the interpreter's
2756 *      result object.
2757 *
2758 *----------------------------------------------------------------------
2759 */
2760
2761static int
2762NamespaceDeleteCmd(dummy, interp, objc, objv)
2763    ClientData dummy;           /* Not used. */
2764    Tcl_Interp *interp;         /* Current interpreter. */
2765    int objc;                   /* Number of arguments. */
2766    Tcl_Obj *CONST objv[];      /* Argument objects. */
2767{
2768    Tcl_Namespace *namespacePtr;
2769    char *name;
2770    register int i;
2771
2772    if (objc < 2) {
2773        Tcl_WrongNumArgs(interp, 2, objv, "?name name...?");
2774        return TCL_ERROR;
2775    }
2776
2777    /*
2778     * Destroying one namespace may cause another to be destroyed. Break
2779     * this into two passes: first check to make sure that all namespaces on
2780     * the command line are valid, and report any errors.
2781     */
2782
2783    for (i = 2;  i < objc;  i++) {
2784        name = Tcl_GetStringFromObj(objv[i], (int *) NULL);
2785        namespacePtr = Tcl_FindNamespace(interp, name,
2786                (Tcl_Namespace *) NULL, /*flags*/ 0);
2787        if (namespacePtr == NULL) {
2788            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
2789                    "unknown namespace \"",
2790                    Tcl_GetStringFromObj(objv[i], (int *) NULL),
2791                    "\" in namespace delete command", (char *) NULL);
2792            return TCL_ERROR;
2793        }
2794    }
2795
2796    /*
2797     * Okay, now delete each namespace.
2798     */
2799
2800    for (i = 2;  i < objc;  i++) {
2801        name = Tcl_GetStringFromObj(objv[i], (int *) NULL);
2802        namespacePtr = Tcl_FindNamespace(interp, name,
2803            (Tcl_Namespace *) NULL, /* flags */ 0);
2804        if (namespacePtr) {
2805            Tcl_DeleteNamespace(namespacePtr);
2806        }
2807    }
2808    return TCL_OK;
2809}
2810
2811/*
2812 *----------------------------------------------------------------------
2813 *
2814 * NamespaceEvalCmd --
2815 *
2816 *      Invoked to implement the "namespace eval" command. Executes
2817 *      commands in a namespace. If the namespace does not already exist,
2818 *      it is created. Handles the following syntax:
2819 *
2820 *          namespace eval name arg ?arg...?
2821 *
2822 *      If more than one arg argument is specified, the command that is
2823 *      executed is the result of concatenating the arguments together with
2824 *      a space between each argument.
2825 *
2826 * Results:
2827 *      Returns TCL_OK if the namespace is found and the commands are
2828 *      executed successfully. Returns TCL_ERROR if anything goes wrong.
2829 *
2830 * Side effects:
2831 *      Returns the result of the command in the interpreter's result
2832 *      object. If anything goes wrong, this procedure returns an error
2833 *      message as the result.
2834 *
2835 *----------------------------------------------------------------------
2836 */
2837
2838static int
2839NamespaceEvalCmd(dummy, interp, objc, objv)
2840    ClientData dummy;           /* Not used. */
2841    Tcl_Interp *interp;         /* Current interpreter. */
2842    int objc;                   /* Number of arguments. */
2843    Tcl_Obj *CONST objv[];      /* Argument objects. */
2844{
2845    Tcl_Namespace *namespacePtr;
2846    Tcl_CallFrame frame;
2847    Tcl_Obj *objPtr;
2848    char *name;
2849    int length, result;
2850
2851    if (objc < 4) {
2852        Tcl_WrongNumArgs(interp, 2, objv, "name arg ?arg...?");
2853        return TCL_ERROR;
2854    }
2855
2856    /*
2857     * Try to resolve the namespace reference, caching the result in the
2858     * namespace object along the way.
2859     */
2860
2861    result = GetNamespaceFromObj(interp, objv[2], &namespacePtr);
2862    if (result != TCL_OK) {
2863        return result;
2864    }
2865
2866    /*
2867     * If the namespace wasn't found, try to create it.
2868     */
2869   
2870    if (namespacePtr == NULL) {
2871        name = Tcl_GetStringFromObj(objv[2], &length);
2872        namespacePtr = Tcl_CreateNamespace(interp, name, (ClientData) NULL, 
2873                (Tcl_NamespaceDeleteProc *) NULL);
2874        if (namespacePtr == NULL) {
2875            return TCL_ERROR;
2876        }
2877    }
2878
2879    /*
2880     * Make the specified namespace the current namespace and evaluate
2881     * the command(s).
2882     */
2883
2884    result = Tcl_PushCallFrame(interp, &frame, namespacePtr,
2885            /*isProcCallFrame*/ 0);
2886    if (result != TCL_OK) {
2887        return TCL_ERROR;
2888    }
2889
2890    if (objc == 4) {
2891        result = Tcl_EvalObj(interp, objv[3]);
2892    } else {
2893        objPtr = Tcl_ConcatObj(objc-3, objv+3);
2894        result = Tcl_EvalObj(interp, objPtr);
2895        Tcl_DecrRefCount(objPtr);  /* we're done with the object */
2896    }
2897    if (result == TCL_ERROR) {
2898        char msg[256];
2899       
2900        sprintf(msg, "\n    (in namespace eval \"%.200s\" script line %d)",
2901            namespacePtr->fullName, interp->errorLine);
2902        Tcl_AddObjErrorInfo(interp, msg, -1);
2903    }
2904
2905    /*
2906     * Restore the previous "current" namespace.
2907     */
2908   
2909    Tcl_PopCallFrame(interp);
2910    return result;
2911}
2912
2913/*
2914 *----------------------------------------------------------------------
2915 *
2916 * NamespaceExportCmd --
2917 *
2918 *      Invoked to implement the "namespace export" command that specifies
2919 *      which commands are exported from a namespace. The exported commands
2920 *      are those that can be imported into another namespace using
2921 *      "namespace import". Both commands defined in a namespace and
2922 *      commands the namespace has imported can be exported by a
2923 *      namespace. This command has the following syntax:
2924 *
2925 *          namespace export ?-clear? ?pattern pattern...?
2926 *
2927 *      Each pattern may contain "string match"-style pattern matching
2928 *      special characters, but the pattern may not include any namespace
2929 *      qualifiers: that is, the pattern must specify commands in the
2930 *      current (exporting) namespace. The specified patterns are appended
2931 *      onto the namespace's list of export patterns.
2932 *
2933 *      To reset the namespace's export pattern list, specify the "-clear"
2934 *      flag.
2935 *
2936 *      If there are no export patterns and the "-clear" flag isn't given,
2937 *      this command returns the namespace's current export list.
2938 *
2939 * Results:
2940 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
2941 *
2942 * Side effects:
2943 *      Returns a result in the interpreter's result object. If anything
2944 *      goes wrong, the result is an error message.
2945 *
2946 *----------------------------------------------------------------------
2947 */
2948
2949static int
2950NamespaceExportCmd(dummy, interp, objc, objv)
2951    ClientData dummy;           /* Not used. */
2952    Tcl_Interp *interp;         /* Current interpreter. */
2953    int objc;                   /* Number of arguments. */
2954    Tcl_Obj *CONST objv[];      /* Argument objects. */
2955{
2956    Namespace *currNsPtr = (Namespace*) Tcl_GetCurrentNamespace(interp);
2957    char *pattern, *string;
2958    int resetListFirst = 0;
2959    int firstArg, patternCt, i, result;
2960
2961    if (objc < 2) {
2962        Tcl_WrongNumArgs(interp, 2, objv,
2963                "?-clear? ?pattern pattern...?");
2964        return TCL_ERROR;
2965    }
2966
2967    /*
2968     * Process the optional "-clear" argument.
2969     */
2970
2971    firstArg = 2;
2972    if (firstArg < objc) {
2973        string = Tcl_GetStringFromObj(objv[firstArg], (int *) NULL);
2974        if (strcmp(string, "-clear") == 0) {
2975            resetListFirst = 1;
2976            firstArg++;
2977        }
2978    }
2979
2980    /*
2981     * If no pattern arguments are given, and "-clear" isn't specified,
2982     * return the namespace's current export pattern list.
2983     */
2984
2985    patternCt = (objc - firstArg);
2986    if (patternCt == 0) {
2987        if (firstArg > 2) {
2988            return TCL_OK;
2989        } else {                /* create list with export patterns */
2990            Tcl_Obj *listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
2991            result = Tcl_AppendExportList(interp,
2992                    (Tcl_Namespace *) currNsPtr, listPtr);
2993            if (result != TCL_OK) {
2994                return result;
2995            }
2996            Tcl_SetObjResult(interp, listPtr);
2997            return TCL_OK;
2998        }
2999    }
3000
3001    /*
3002     * Add each pattern to the namespace's export pattern list.
3003     */
3004   
3005    for (i = firstArg;  i < objc;  i++) {
3006        pattern = Tcl_GetStringFromObj(objv[i], (int *) NULL);
3007        result = Tcl_Export(interp, (Tcl_Namespace *) currNsPtr, pattern,
3008                ((i == firstArg)? resetListFirst : 0));
3009        if (result != TCL_OK) {
3010            return result;
3011        }
3012    }
3013    return TCL_OK;
3014}
3015
3016/*
3017 *----------------------------------------------------------------------
3018 *
3019 * NamespaceForgetCmd --
3020 *
3021 *      Invoked to implement the "namespace forget" command to remove
3022 *      imported commands from a namespace. Handles the following syntax:
3023 *
3024 *          namespace forget ?pattern pattern...?
3025 *
3026 *      Each pattern is a name like "foo::*" or "a::b::x*". That is, the
3027 *      pattern may include the special pattern matching characters
3028 *      recognized by the "string match" command, but only in the command
3029 *      name at the end of the qualified name; the special pattern
3030 *      characters may not appear in a namespace name. All of the commands
3031 *      that match that pattern are checked to see if they have an imported
3032 *      command in the current namespace that refers to the matched
3033 *      command. If there is an alias, it is removed.
3034 *     
3035 * Results:
3036 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
3037 *
3038 * Side effects:
3039 *      Imported commands are removed from the current namespace. If
3040 *      anything goes wrong, this procedure returns an error message in the
3041 *      interpreter's result object.
3042 *
3043 *----------------------------------------------------------------------
3044 */
3045
3046static int
3047NamespaceForgetCmd(dummy, interp, objc, objv)
3048    ClientData dummy;           /* Not used. */
3049    Tcl_Interp *interp;         /* Current interpreter. */
3050    int objc;                   /* Number of arguments. */
3051    Tcl_Obj *CONST objv[];      /* Argument objects. */
3052{
3053    char *pattern;
3054    register int i, result;
3055
3056    if (objc < 2) {
3057        Tcl_WrongNumArgs(interp, 2, objv, "?pattern pattern...?");
3058        return TCL_ERROR;
3059    }
3060
3061    for (i = 2;  i < objc;  i++) {
3062        pattern = Tcl_GetStringFromObj(objv[i], (int *) NULL);
3063        result = Tcl_ForgetImport(interp, (Tcl_Namespace *) NULL, pattern);
3064        if (result != TCL_OK) {
3065            return result;
3066        }
3067    }
3068    return TCL_OK;
3069}
3070
3071/*
3072 *----------------------------------------------------------------------
3073 *
3074 * NamespaceImportCmd --
3075 *
3076 *      Invoked to implement the "namespace import" command that imports
3077 *      commands into a namespace. Handles the following syntax:
3078 *
3079 *          namespace import ?-force? ?pattern pattern...?
3080 *
3081 *      Each pattern is a namespace-qualified name like "foo::*",
3082 *      "a::b::x*", or "bar::p". That is, the pattern may include the
3083 *      special pattern matching characters recognized by the "string match"
3084 *      command, but only in the command name at the end of the qualified
3085 *      name; the special pattern characters may not appear in a namespace
3086 *      name. All of the commands that match the pattern and which are
3087 *      exported from their namespace are made accessible from the current
3088 *      namespace context. This is done by creating a new "imported command"
3089 *      in the current namespace that points to the real command in its
3090 *      original namespace; when the imported command is called, it invokes
3091 *      the real command.
3092 *
3093 *      If an imported command conflicts with an existing command, it is
3094 *      treated as an error. But if the "-force" option is included, then
3095 *      existing commands are overwritten by the imported commands.
3096 *     
3097 * Results:
3098 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
3099 *
3100 * Side effects:
3101 *      Adds imported commands to the current namespace. If anything goes
3102 *      wrong, this procedure returns an error message in the interpreter's
3103 *      result object.
3104 *
3105 *----------------------------------------------------------------------
3106 */
3107
3108static int
3109NamespaceImportCmd(dummy, interp, objc, objv)
3110    ClientData dummy;           /* Not used. */
3111    Tcl_Interp *interp;         /* Current interpreter. */
3112    int objc;                   /* Number of arguments. */
3113    Tcl_Obj *CONST objv[];      /* Argument objects. */
3114{
3115    int allowOverwrite = 0;
3116    char *string, *pattern;
3117    register int i, result;
3118    int firstArg;
3119
3120    if (objc < 2) {
3121        Tcl_WrongNumArgs(interp, 2, objv,
3122                "?-force? ?pattern pattern...?");
3123        return TCL_ERROR;
3124    }
3125
3126    /*
3127     * Skip over the optional "-force" as the first argument.
3128     */
3129
3130    firstArg = 2;
3131    if (firstArg < objc) {
3132        string = Tcl_GetStringFromObj(objv[firstArg], (int *) NULL);
3133        if ((*string == '-') && (strcmp(string, "-force") == 0)) {
3134            allowOverwrite = 1;
3135            firstArg++;
3136        }
3137    }
3138
3139    /*
3140     * Handle the imports for each of the patterns.
3141     */
3142
3143    for (i = firstArg;  i < objc;  i++) {
3144        pattern = Tcl_GetStringFromObj(objv[i], (int *) NULL);
3145        result = Tcl_Import(interp, (Tcl_Namespace *) NULL, pattern,
3146                allowOverwrite);
3147        if (result != TCL_OK) {
3148            return result;
3149        }
3150    }
3151    return TCL_OK;
3152}
3153
3154/*
3155 *----------------------------------------------------------------------
3156 *
3157 * NamespaceInscopeCmd --
3158 *
3159 *      Invoked to implement the "namespace inscope" command that executes a
3160 *      script in the context of a particular namespace. This command is not
3161 *      expected to be used directly by programmers; calls to it are
3162 *      generated implicitly when programs use "namespace code" commands
3163 *      to register callback scripts. Handles the following syntax:
3164 *
3165 *          namespace inscope name arg ?arg...?
3166 *
3167 *      The "namespace inscope" command is much like the "namespace eval"
3168 *      command except that it has lappend semantics and the namespace must
3169 *      already exist. It treats the first argument as a list, and appends
3170 *      any arguments after the first onto the end as proper list elements.
3171 *      For example,
3172 *
3173 *          namespace inscope ::foo a b c d
3174 *
3175 *      is equivalent to
3176 *
3177 *          namespace eval ::foo [concat a [list b c d]]
3178 *
3179 *      This lappend semantics is important because many callback scripts
3180 *      are actually prefixes.
3181 *
3182 * Results:
3183 *      Returns TCL_OK to indicate success, or TCL_ERROR to indicate
3184 *      failure.
3185 *
3186 * Side effects:
3187 *      Returns a result in the Tcl interpreter's result object.
3188 *
3189 *----------------------------------------------------------------------
3190 */
3191
3192static int
3193NamespaceInscopeCmd(dummy, interp, objc, objv)
3194    ClientData dummy;           /* Not used. */
3195    Tcl_Interp *interp;         /* Current interpreter. */
3196    int objc;                   /* Number of arguments. */
3197    Tcl_Obj *CONST objv[];      /* Argument objects. */
3198{
3199    Tcl_Namespace *namespacePtr;
3200    Tcl_CallFrame frame;
3201    int i, result;
3202
3203    if (objc < 4) {
3204        Tcl_WrongNumArgs(interp, 2, objv, "name arg ?arg...?");
3205        return TCL_ERROR;
3206    }
3207
3208    /*
3209     * Resolve the namespace reference.
3210     */
3211
3212    result = GetNamespaceFromObj(interp, objv[2], &namespacePtr);
3213    if (result != TCL_OK) {
3214        return result;
3215    }
3216    if (namespacePtr == NULL) {
3217        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
3218                "unknown namespace \"",
3219                Tcl_GetStringFromObj(objv[2], (int *) NULL),
3220                "\" in inscope namespace command", (char *) NULL);
3221        return TCL_ERROR;
3222    }
3223
3224    /*
3225     * Make the specified namespace the current namespace.
3226     */
3227
3228    result = Tcl_PushCallFrame(interp, &frame, namespacePtr,
3229            /*isProcCallFrame*/ 0);
3230    if (result != TCL_OK) {
3231        return result;
3232    }
3233
3234    /*
3235     * Execute the command. If there is just one argument, just treat it as
3236     * a script and evaluate it. Otherwise, create a list from the arguments
3237     * after the first one, then concatenate the first argument and the list
3238     * of extra arguments to form the command to evaluate.
3239     */
3240
3241    if (objc == 4) {
3242        result = Tcl_EvalObj(interp, objv[3]);
3243    } else {
3244        Tcl_Obj *concatObjv[2];
3245        register Tcl_Obj *listPtr, *cmdObjPtr;
3246       
3247        listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
3248        for (i = 4;  i < objc;  i++) {
3249            result = Tcl_ListObjAppendElement(interp, listPtr, objv[i]);
3250            if (result != TCL_OK) {
3251                Tcl_DecrRefCount(listPtr); /* free unneeded obj */
3252                return result;
3253            }
3254        }
3255
3256        concatObjv[0] = objv[3];
3257        concatObjv[1] = listPtr;
3258        cmdObjPtr = Tcl_ConcatObj(2, concatObjv);
3259        result = Tcl_EvalObj(interp, cmdObjPtr);
3260       
3261        Tcl_DecrRefCount(cmdObjPtr);  /* we're done with the cmd object */
3262        Tcl_DecrRefCount(listPtr);    /* we're done with the list object */
3263    }
3264    if (result == TCL_ERROR) {
3265        char msg[256];
3266       
3267        sprintf(msg,
3268            "\n    (in namespace inscope \"%.200s\" script line %d)",
3269            namespacePtr->fullName, interp->errorLine);
3270        Tcl_AddObjErrorInfo(interp, msg, -1);
3271    }
3272
3273    /*
3274     * Restore the previous "current" namespace.
3275     */
3276
3277    Tcl_PopCallFrame(interp);
3278    return result;
3279}
3280
3281/*
3282 *----------------------------------------------------------------------
3283 *
3284 * NamespaceOriginCmd --
3285 *
3286 *      Invoked to implement the "namespace origin" command to return the
3287 *      fully-qualified name of the "real" command to which the specified
3288 *      "imported command" refers. Handles the following syntax:
3289 *
3290 *          namespace origin name
3291 *
3292 * Results:
3293 *      An imported command is created in an namespace when that namespace
3294 *      imports a command from another namespace. If a command is imported
3295 *      into a sequence of namespaces a, b,...,n where each successive
3296 *      namespace just imports the command from the previous namespace, this
3297 *      command returns the fully-qualified name of the original command in
3298 *      the first namespace, a. If "name" does not refer to an alias, its
3299 *      fully-qualified name is returned. The returned name is stored in the
3300 *      interpreter's result object. This procedure returns TCL_OK if
3301 *      successful, and TCL_ERROR if anything goes wrong.
3302 *
3303 * Side effects:
3304 *      If anything goes wrong, this procedure returns an error message in
3305 *      the interpreter's result object.
3306 *
3307 *----------------------------------------------------------------------
3308 */
3309
3310static int
3311NamespaceOriginCmd(dummy, interp, objc, objv)
3312    ClientData dummy;           /* Not used. */
3313    Tcl_Interp *interp;         /* Current interpreter. */
3314    int objc;                   /* Number of arguments. */
3315    Tcl_Obj *CONST objv[];      /* Argument objects. */
3316{
3317    Tcl_Command command, origCommand;
3318
3319    if (objc != 3) {
3320        Tcl_WrongNumArgs(interp, 2, objv, "name");
3321        return TCL_ERROR;
3322    }
3323
3324    command = Tcl_GetCommandFromObj(interp, objv[2]);
3325    if (command == (Tcl_Command) NULL) {
3326        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
3327                "invalid command name \"",
3328                Tcl_GetStringFromObj(objv[2], (int *) NULL),
3329                "\"", (char *) NULL);
3330        return TCL_ERROR;
3331    }
3332    origCommand = TclGetOriginalCommand(command);
3333    if (origCommand == (Tcl_Command) NULL) {
3334        /*
3335         * The specified command isn't an imported command. Return the
3336         * command's name qualified by the full name of the namespace it
3337         * was defined in.
3338         */
3339       
3340        Tcl_GetCommandFullName(interp, command, Tcl_GetObjResult(interp));
3341    } else {
3342        Tcl_GetCommandFullName(interp, origCommand, Tcl_GetObjResult(interp));
3343    }
3344    return TCL_OK;
3345}
3346
3347/*
3348 *----------------------------------------------------------------------
3349 *
3350 * NamespaceParentCmd --
3351 *
3352 *      Invoked to implement the "namespace parent" command that returns the
3353 *      fully-qualified name of the parent namespace for a specified
3354 *      namespace. Handles the following syntax:
3355 *
3356 *          namespace parent ?name?
3357 *
3358 * Results:
3359 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
3360 *
3361 * Side effects:
3362 *      Returns a result in the interpreter's result object. If anything
3363 *      goes wrong, the result is an error message.
3364 *
3365 *----------------------------------------------------------------------
3366 */
3367
3368static int
3369NamespaceParentCmd(dummy, interp, objc, objv)
3370    ClientData dummy;           /* Not used. */
3371    Tcl_Interp *interp;         /* Current interpreter. */
3372    int objc;                   /* Number of arguments. */
3373    Tcl_Obj *CONST objv[];      /* Argument objects. */
3374{
3375    Tcl_Namespace *nsPtr;
3376    int result;
3377
3378    if (objc == 2) {
3379        nsPtr = Tcl_GetCurrentNamespace(interp);
3380    } else if (objc == 3) {
3381        result = GetNamespaceFromObj(interp, objv[2], &nsPtr);
3382        if (result != TCL_OK) {
3383            return result;
3384        }
3385        if (nsPtr == NULL) {
3386            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
3387                    "unknown namespace \"",
3388                    Tcl_GetStringFromObj(objv[2], (int *) NULL),
3389                    "\" in namespace parent command", (char *) NULL);
3390            return TCL_ERROR;
3391        }
3392    } else {
3393        Tcl_WrongNumArgs(interp, 2, objv, "?name?");
3394        return TCL_ERROR;
3395    }
3396
3397    /*
3398     * Report the parent of the specified namespace.
3399     */
3400
3401    if (nsPtr->parentPtr != NULL) {
3402        Tcl_SetStringObj(Tcl_GetObjResult(interp),
3403                nsPtr->parentPtr->fullName, -1);
3404    }
3405    return TCL_OK;
3406}
3407
3408/*
3409 *----------------------------------------------------------------------
3410 *
3411 * NamespaceQualifiersCmd --
3412 *
3413 *      Invoked to implement the "namespace qualifiers" command that returns
3414 *      any leading namespace qualifiers in a string. These qualifiers are
3415 *      namespace names separated by "::"s. For example, for "::foo::p" this
3416 *      command returns "::foo", and for "::" it returns "". This command
3417 *      is the complement of the "namespace tail" command. Note that this
3418 *      command does not check whether the "namespace" names are, in fact,
3419 *      the names of currently defined namespaces. Handles the following
3420 *      syntax:
3421 *
3422 *          namespace qualifiers string
3423 *
3424 * Results:
3425 *      Returns TCL_OK if successful, and  TCL_ERROR if anything goes wrong.
3426 *
3427 * Side effects:
3428 *      Returns a result in the interpreter's result object. If anything
3429 *      goes wrong, the result is an error message.
3430 *
3431 *----------------------------------------------------------------------
3432 */
3433
3434static int
3435NamespaceQualifiersCmd(dummy, interp, objc, objv)
3436    ClientData dummy;           /* Not used. */
3437    Tcl_Interp *interp;         /* Current interpreter. */
3438    int objc;                   /* Number of arguments. */
3439    Tcl_Obj *CONST objv[];      /* Argument objects. */
3440{
3441    register char *name, *p;
3442    int length;
3443
3444    if (objc != 3) {
3445        Tcl_WrongNumArgs(interp, 2, objv, "string");
3446        return TCL_ERROR;
3447    }
3448
3449    /*
3450     * Find the end of the string, then work backward and find
3451     * the start of the last "::" qualifier.
3452     */
3453
3454    name = Tcl_GetStringFromObj(objv[2], (int *) NULL);
3455    for (p = name;  *p != '\0';  p++) {
3456        /* empty body */
3457    }
3458    while (--p >= name) {
3459        if ((*p == ':') && (p > name) && (*(p-1) == ':')) {
3460            p -= 2;             /* back up over the :: */
3461            while ((p >= name) && (*p == ':')) {
3462                p--;            /* back up over the preceeding : */
3463            }
3464            break;
3465        }
3466    }
3467
3468    if (p >= name) {
3469        length = p-name+1;
3470        Tcl_AppendToObj(Tcl_GetObjResult(interp), name, length);
3471    }
3472    return TCL_OK;
3473}
3474
3475/*
3476 *----------------------------------------------------------------------
3477 *
3478 * NamespaceTailCmd --
3479 *
3480 *      Invoked to implement the "namespace tail" command that returns the
3481 *      trailing name at the end of a string with "::" namespace
3482 *      qualifiers. These qualifiers are namespace names separated by
3483 *      "::"s. For example, for "::foo::p" this command returns "p", and for
3484 *      "::" it returns "". This command is the complement of the "namespace
3485 *      qualifiers" command. Note that this command does not check whether
3486 *      the "namespace" names are, in fact, the names of currently defined
3487 *      namespaces. Handles the following syntax:
3488 *
3489 *          namespace tail string
3490 *
3491 * Results:
3492 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
3493 *
3494 * Side effects:
3495 *      Returns a result in the interpreter's result object. If anything
3496 *      goes wrong, the result is an error message.
3497 *
3498 *----------------------------------------------------------------------
3499 */
3500
3501static int
3502NamespaceTailCmd(dummy, interp, objc, objv)
3503    ClientData dummy;           /* Not used. */
3504    Tcl_Interp *interp;         /* Current interpreter. */
3505    int objc;                   /* Number of arguments. */
3506    Tcl_Obj *CONST objv[];      /* Argument objects. */
3507{
3508    register char *name, *p;
3509
3510    if (objc != 3) {
3511        Tcl_WrongNumArgs(interp, 2, objv, "string");
3512        return TCL_ERROR;
3513    }
3514
3515    /*
3516     * Find the end of the string, then work backward and find the
3517     * last "::" qualifier.
3518     */
3519
3520    name = Tcl_GetStringFromObj(objv[2], (int *) NULL);
3521    for (p = name;  *p != '\0';  p++) {
3522        /* empty body */
3523    }
3524    while (--p > name) {
3525        if ((*p == ':') && (*(p-1) == ':')) {
3526            p++;                /* just after the last "::" */
3527            break;
3528        }
3529    }
3530   
3531    if (p >= name) {
3532        Tcl_AppendToObj(Tcl_GetObjResult(interp), p, -1);
3533    }
3534    return TCL_OK;
3535}
3536
3537/*
3538 *----------------------------------------------------------------------
3539 *
3540 * NamespaceWhichCmd --
3541 *
3542 *      Invoked to implement the "namespace which" command that returns the
3543 *      fully-qualified name of a command or variable. If the specified
3544 *      command or variable does not exist, it returns "". Handles the
3545 *      following syntax:
3546 *
3547 *          namespace which ?-command? ?-variable? name
3548 *
3549 * Results:
3550 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
3551 *
3552 * Side effects:
3553 *      Returns a result in the interpreter's result object. If anything
3554 *      goes wrong, the result is an error message.
3555 *
3556 *----------------------------------------------------------------------
3557 */
3558
3559static int
3560NamespaceWhichCmd(dummy, interp, objc, objv)
3561    ClientData dummy;                   /* Not used. */
3562    Tcl_Interp *interp;                 /* Current interpreter. */
3563    int objc;                           /* Number of arguments. */
3564    Tcl_Obj *CONST objv[];              /* Argument objects. */
3565{
3566    register char *arg;
3567    Tcl_Command cmd;
3568    Tcl_Var variable;
3569    int argIndex, lookup;
3570
3571    if (objc < 3) {
3572        badArgs:
3573        Tcl_WrongNumArgs(interp, 2, objv,
3574                "?-command? ?-variable? name");
3575        return TCL_ERROR;
3576    }
3577
3578    /*
3579     * Look for a flag controlling the lookup.
3580     */
3581
3582    argIndex = 2;
3583    lookup = 0;                 /* assume command lookup by default */
3584    arg = Tcl_GetStringFromObj(objv[2], (int *) NULL);
3585    if (*arg == '-') {
3586        if (strncmp(arg, "-command", 8) == 0) {
3587            lookup = 0;
3588        } else if (strncmp(arg, "-variable", 9) == 0) {
3589            lookup = 1;
3590        } else {
3591            goto badArgs;
3592        }
3593        argIndex = 3;
3594    }
3595    if (objc != (argIndex + 1)) {
3596        goto badArgs;
3597    }
3598
3599    switch (lookup) {
3600    case 0:                     /* -command */
3601        cmd = Tcl_GetCommandFromObj(interp, objv[argIndex]);
3602        if (cmd == (Tcl_Command) NULL) {       
3603            return TCL_OK;      /* cmd not found, just return (no error) */
3604        }
3605        Tcl_GetCommandFullName(interp, cmd, Tcl_GetObjResult(interp));
3606        break;
3607
3608    case 1:                     /* -variable */
3609        arg = Tcl_GetStringFromObj(objv[argIndex], (int *) NULL);
3610        variable = Tcl_FindNamespaceVar(interp, arg, (Tcl_Namespace *) NULL,
3611                /*flags*/ 0);
3612        if (variable != (Tcl_Var) NULL) {
3613            Tcl_GetVariableFullName(interp, variable, Tcl_GetObjResult(interp));
3614        }
3615        break;
3616    }
3617    return TCL_OK;
3618}
3619
3620/*
3621 *----------------------------------------------------------------------
3622 *
3623 * FreeNsNameInternalRep --
3624 *
3625 *      Frees the resources associated with a nsName object's internal
3626 *      representation.
3627 *
3628 * Results:
3629 *      None.
3630 *
3631 * Side effects:
3632 *      Decrements the ref count of any Namespace structure pointed
3633 *      to by the nsName's internal representation. If there are no more
3634 *      references to the namespace, it's structure will be freed.
3635 *
3636 *----------------------------------------------------------------------
3637 */
3638
3639static void
3640FreeNsNameInternalRep(objPtr)
3641    register Tcl_Obj *objPtr;   /* nsName object with internal
3642                                 * representation to free */
3643{
3644    register ResolvedNsName *resNamePtr =
3645        (ResolvedNsName *) objPtr->internalRep.otherValuePtr;
3646    Namespace *nsPtr;
3647
3648    /*
3649     * Decrement the reference count of the namespace. If there are no
3650     * more references, free it up.
3651     */
3652
3653    if (resNamePtr != NULL) {
3654        resNamePtr->refCount--;
3655        if (resNamePtr->refCount == 0) {
3656
3657            /*
3658             * Decrement the reference count for the cached namespace.  If
3659             * the namespace is dead, and there are no more references to
3660             * it, free it.
3661             */
3662
3663            nsPtr = resNamePtr->nsPtr;
3664            nsPtr->refCount--;
3665            if ((nsPtr->refCount == 0) && (nsPtr->flags & NS_DEAD)) {
3666                NamespaceFree(nsPtr);
3667            }
3668            ckfree((char *) resNamePtr);
3669        }
3670    }
3671}
3672
3673/*
3674 *----------------------------------------------------------------------
3675 *
3676 * DupNsNameInternalRep --
3677 *
3678 *      Initializes the internal representation of a nsName object to a copy
3679 *      of the internal representation of another nsName object.
3680 *
3681 * Results:
3682 *      None.
3683 *
3684 * Side effects:
3685 *      copyPtr's internal rep is set to refer to the same namespace
3686 *      referenced by srcPtr's internal rep. Increments the ref count of
3687 *      the ResolvedNsName structure used to hold the namespace reference.
3688 *
3689 *----------------------------------------------------------------------
3690 */
3691
3692static void
3693DupNsNameInternalRep(srcPtr, copyPtr)
3694    Tcl_Obj *srcPtr;                /* Object with internal rep to copy. */
3695    register Tcl_Obj *copyPtr;      /* Object with internal rep to set. */
3696{
3697    register ResolvedNsName *resNamePtr =
3698        (ResolvedNsName *) srcPtr->internalRep.otherValuePtr;
3699
3700    copyPtr->internalRep.otherValuePtr = (VOID *) resNamePtr;
3701    if (resNamePtr != NULL) {
3702        resNamePtr->refCount++;
3703    }
3704    copyPtr->typePtr = &tclNsNameType;
3705}
3706
3707/*
3708 *----------------------------------------------------------------------
3709 *
3710 * SetNsNameFromAny --
3711 *
3712 *      Attempt to generate a nsName internal representation for a
3713 *      Tcl object.
3714 *
3715 * Results:
3716 *      Returns TCL_OK if the value could be converted to a proper
3717 *      namespace reference. Otherwise, it returns TCL_ERROR, along
3718 *      with an error message in the interpreter's result object.
3719 *
3720 * Side effects:
3721 *      If successful, the object is made a nsName object. Its internal rep
3722 *      is set to point to a ResolvedNsName, which contains a cached pointer
3723 *      to the Namespace. Reference counts are kept on both the
3724 *      ResolvedNsName and the Namespace, so we can keep track of their
3725 *      usage and free them when appropriate.
3726 *
3727 *----------------------------------------------------------------------
3728 */
3729
3730static int
3731SetNsNameFromAny(interp, objPtr)
3732    Tcl_Interp *interp;         /* Points to the namespace in which to
3733                                 * resolve name. Also used for error
3734                                 * reporting if not NULL. */
3735    register Tcl_Obj *objPtr;   /* The object to convert. */
3736{
3737    register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
3738    char *name, *dummy;
3739    Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr;
3740    register ResolvedNsName *resNamePtr;
3741
3742    /*
3743     * Get the string representation. Make it up-to-date if necessary.
3744     */
3745
3746    name = objPtr->bytes;
3747    if (name == NULL) {
3748        name = Tcl_GetStringFromObj(objPtr, (int *) NULL);
3749    }
3750
3751    /*
3752     * Look for the namespace "name" in the current namespace. If there is
3753     * an error parsing the (possibly qualified) name, return an error.
3754     * If the namespace isn't found, we convert the object to an nsName
3755     * object with a NULL ResolvedNsName* internal rep.
3756     */
3757
3758    TclGetNamespaceForQualName(interp, name, (Namespace *) NULL,
3759       /*flags*/ FIND_ONLY_NS, &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
3760
3761    /*
3762     * If we found a namespace, then create a new ResolvedNsName structure
3763     * that holds a reference to it.
3764     */
3765
3766    if (nsPtr != NULL) {
3767        Namespace *currNsPtr =
3768                (Namespace *) Tcl_GetCurrentNamespace(interp);
3769       
3770        nsPtr->refCount++;
3771        resNamePtr = (ResolvedNsName *) ckalloc(sizeof(ResolvedNsName));
3772        resNamePtr->nsPtr = nsPtr;
3773        resNamePtr->nsId = nsPtr->nsId;
3774        resNamePtr->refNsPtr = currNsPtr;
3775        resNamePtr->refCount = 1;
3776    } else {
3777        resNamePtr = NULL;
3778    }
3779
3780    /*
3781     * Free the old internalRep before setting the new one.
3782     * We do this as late as possible to allow the conversion code
3783     * (in particular, Tcl_GetStringFromObj) to use that old internalRep.
3784     */
3785
3786    if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
3787        oldTypePtr->freeIntRepProc(objPtr);
3788    }
3789
3790    objPtr->internalRep.otherValuePtr = (VOID *) resNamePtr;
3791    objPtr->typePtr = &tclNsNameType;
3792    return TCL_OK;
3793}
3794
3795/*
3796 *----------------------------------------------------------------------
3797 *
3798 * UpdateStringOfNsName --
3799 *
3800 *      Updates the string representation for a nsName object.
3801 *      Note: This procedure does not free an existing old string rep
3802 *      so storage will be lost if this has not already been done.
3803 *
3804 * Results:
3805 *      None.
3806 *
3807 * Side effects:
3808 *      The object's string is set to a copy of the fully qualified
3809 *      namespace name.
3810 *
3811 *----------------------------------------------------------------------
3812 */
3813
3814static void
3815UpdateStringOfNsName(objPtr)
3816    register Tcl_Obj *objPtr; /* nsName object with string rep to update. */
3817{
3818    ResolvedNsName *resNamePtr =
3819        (ResolvedNsName *) objPtr->internalRep.otherValuePtr;
3820    register Namespace *nsPtr;
3821    char *name = "";
3822    int length;
3823
3824    if ((resNamePtr != NULL)
3825            && (resNamePtr->nsId == resNamePtr->nsPtr->nsId)) {
3826        nsPtr = resNamePtr->nsPtr;
3827        if (nsPtr->flags & NS_DEAD) {
3828            nsPtr = NULL;
3829        }
3830        if (nsPtr != NULL) {
3831            name = nsPtr->fullName;
3832        }
3833    }
3834
3835    /*
3836     * The following sets the string rep to an empty string on the heap
3837     * if the internal rep is NULL.
3838     */
3839
3840    length = strlen(name);
3841    if (length == 0) {
3842        objPtr->bytes = tclEmptyStringRep;
3843    } else {
3844        objPtr->bytes = (char *) ckalloc((unsigned) (length + 1));
3845        memcpy((VOID *) objPtr->bytes, (VOID *) name, (unsigned) length);
3846        objPtr->bytes[length] = '\0';
3847    }
3848    objPtr->length = length;
3849}
Note: See TracBrowser for help on using the repository browser.