OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tcl/] [generic/] [tclNamesp.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.