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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tcl/] [generic/] [tclProc.c] - Blame information for rev 578

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tclProc.c --
3
 *
4
 *      This file contains routines that implement Tcl procedures,
5
 *      including the "proc" and "uplevel" commands.
6
 *
7
 * Copyright (c) 1987-1993 The Regents of the University of California.
8
 * Copyright (c) 1994-1996 Sun Microsystems, Inc.
9
 *
10
 * See the file "license.terms" for information on usage and redistribution
11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
 *
13
 * RCS: @(#) $Id: tclProc.c,v 1.1.1.1 2002-01-16 10:25:29 markom Exp $
14
 */
15
 
16
#include "tclInt.h"
17
#include "tclCompile.h"
18
 
19
/*
20
 * Prototypes for static functions in this file
21
 */
22
 
23
static void     ProcBodyDup _ANSI_ARGS_((Tcl_Obj *srcPtr, Tcl_Obj *dupPtr));
24
static void     ProcBodyFree _ANSI_ARGS_((Tcl_Obj *objPtr));
25
static int      ProcBodySetFromAny _ANSI_ARGS_((Tcl_Interp *interp,
26
                Tcl_Obj *objPtr));
27
static void     ProcBodyUpdateString _ANSI_ARGS_((Tcl_Obj *objPtr));
28
 
29
/*
30
 * The ProcBodyObjType type
31
 */
32
 
33
Tcl_ObjType tclProcBodyType = {
34
    "procbody",                 /* name for this type */
35
    ProcBodyFree,               /* FreeInternalRep procedure */
36
    ProcBodyDup,                /* DupInternalRep procedure */
37
    ProcBodyUpdateString,       /* UpdateString procedure */
38
    ProcBodySetFromAny          /* SetFromAny procedure */
39
};
40
 
41
 
42
/*
43
 *----------------------------------------------------------------------
44
 *
45
 * Tcl_ProcObjCmd --
46
 *
47
 *      This object-based procedure is invoked to process the "proc" Tcl
48
 *      command. See the user documentation for details on what it does.
49
 *
50
 * Results:
51
 *      A standard Tcl object result value.
52
 *
53
 * Side effects:
54
 *      A new procedure gets created.
55
 *
56
 *----------------------------------------------------------------------
57
 */
58
 
59
        /* ARGSUSED */
60
int
61
Tcl_ProcObjCmd(dummy, interp, objc, objv)
62
    ClientData dummy;           /* Not used. */
63
    Tcl_Interp *interp;         /* Current interpreter. */
64
    int objc;                   /* Number of arguments. */
65
    Tcl_Obj *CONST objv[];      /* Argument objects. */
66
{
67
    register Interp *iPtr = (Interp *) interp;
68
    Proc *procPtr;
69
    char *fullName, *procName;
70
    Namespace *nsPtr, *altNsPtr, *cxtNsPtr;
71
    Tcl_Command cmd;
72
    Tcl_DString ds;
73
    int result;
74
 
75
    if (objc != 4) {
76
        Tcl_WrongNumArgs(interp, 1, objv, "name args body");
77
        return TCL_ERROR;
78
    }
79
 
80
    /*
81
     * Determine the namespace where the procedure should reside. Unless
82
     * the command name includes namespace qualifiers, this will be the
83
     * current namespace.
84
     */
85
 
86
    fullName = Tcl_GetStringFromObj(objv[1], (int *) NULL);
87
    result = TclGetNamespaceForQualName(interp, fullName,
88
            (Namespace *) NULL, TCL_LEAVE_ERR_MSG,
89
            &nsPtr, &altNsPtr, &cxtNsPtr, &procName);
90
    if (result != TCL_OK) {
91
        return result;
92
    }
93
    if (nsPtr == NULL) {
94
        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
95
                "can't create procedure \"", fullName,
96
                "\": unknown namespace", (char *) NULL);
97
        return TCL_ERROR;
98
    }
99
    if (procName == NULL) {
100
        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
101
                "can't create procedure \"", fullName,
102
                "\": bad procedure name", (char *) NULL);
103
        return TCL_ERROR;
104
    }
105
    if ((nsPtr != iPtr->globalNsPtr)
106
            && (procName != NULL) && (procName[0] == ':')) {
107
        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
108
                "can't create procedure \"", procName,
109
                "\" in non-global namespace with name starting with \":\"",
110
                (char *) NULL);
111
        return TCL_ERROR;
112
    }
113
 
114
    /*
115
     *  Create the data structure to represent the procedure.
116
     */
117
    if (TclCreateProc(interp, nsPtr, procName, objv[2], objv[3],
118
        &procPtr) != TCL_OK) {
119
        return TCL_ERROR;
120
    }
121
 
122
    /*
123
     * Now create a command for the procedure. This will initially be in
124
     * the current namespace unless the procedure's name included namespace
125
     * qualifiers. To create the new command in the right namespace, we
126
     * generate a fully qualified name for it.
127
     */
128
 
129
    Tcl_DStringInit(&ds);
130
    if (nsPtr != iPtr->globalNsPtr) {
131
        Tcl_DStringAppend(&ds, nsPtr->fullName, -1);
132
        Tcl_DStringAppend(&ds, "::", 2);
133
    }
134
    Tcl_DStringAppend(&ds, procName, -1);
135
 
136
    Tcl_CreateCommand(interp, Tcl_DStringValue(&ds), TclProcInterpProc,
137
            (ClientData) procPtr, TclProcDeleteProc);
138
    cmd = Tcl_CreateObjCommand(interp, Tcl_DStringValue(&ds),
139
            TclObjInterpProc, (ClientData) procPtr, TclProcDeleteProc);
140
 
141
    /*
142
     * Now initialize the new procedure's cmdPtr field. This will be used
143
     * later when the procedure is called to determine what namespace the
144
     * procedure will run in. This will be different than the current
145
     * namespace if the proc was renamed into a different namespace.
146
     */
147
 
148
    procPtr->cmdPtr = (Command *) cmd;
149
 
150
    return TCL_OK;
151
}
152
 
153
 
154
/*
155
 *----------------------------------------------------------------------
156
 *
157
 * TclCreateProc --
158
 *
159
 *      Creates the data associated with a Tcl procedure definition.
160
 *      This procedure knows how to handle two types of body objects:
161
 *      strings and procbody. Strings are the traditional (and common) value
162
 *      for bodies, procbody are values created by extensions that have
163
 *      loaded a previously compiled script.
164
 *
165
 * Results:
166
 *      Returns TCL_OK on success, along with a pointer to a Tcl
167
 *      procedure definition in procPtrPtr.  This definition should
168
 *      be freed by calling TclCleanupProc() when it is no longer
169
 *      needed.  Returns TCL_ERROR if anything goes wrong.
170
 *
171
 * Side effects:
172
 *      If anything goes wrong, this procedure returns an error
173
 *      message in the interpreter.
174
 *
175
 *----------------------------------------------------------------------
176
 */
177
int
178
TclCreateProc(interp, nsPtr, procName, argsPtr, bodyPtr, procPtrPtr)
179
    Tcl_Interp *interp;         /* interpreter containing proc */
180
    Namespace *nsPtr;           /* namespace containing this proc */
181
    char *procName;             /* unqualified name of this proc */
182
    Tcl_Obj *argsPtr;           /* description of arguments */
183
    Tcl_Obj *bodyPtr;           /* command body */
184
    Proc **procPtrPtr;          /* returns:  pointer to proc data */
185
{
186
    Interp *iPtr = (Interp*)interp;
187
    char **argArray = NULL;
188
 
189
    register Proc *procPtr;
190
    int i, length, result, numArgs;
191
    char *args, *bytes, *p;
192
    register CompiledLocal *localPtr;
193
    Tcl_Obj *defPtr;
194
    int precompiled = 0;
195
 
196
    if (bodyPtr->typePtr == &tclProcBodyType) {
197
        /*
198
         * Because the body is a TclProProcBody, the actual body is already
199
         * compiled, and it is not shared with anyone else, so it's OK not to
200
         * unshare it (as a matter of fact, it is bad to unshare it, because
201
         * there may be no source code).
202
         *
203
         * We don't create and initialize a Proc structure for the procedure;
204
         * rather, we use what is in the body object. Note that
205
         * we initialize its cmdPtr field below after we've created the command
206
         * for the procedure. We increment the ref count of the Proc struct
207
         * since the command (soon to be created) will be holding a reference
208
         * to it.
209
         */
210
 
211
        procPtr = (Proc *) bodyPtr->internalRep.otherValuePtr;
212
        procPtr->iPtr = iPtr;
213
        procPtr->refCount++;
214
        precompiled = 1;
215
    } else {
216
        /*
217
         * If the procedure's body object is shared because its string value is
218
         * identical to, e.g., the body of another procedure, we must create a
219
         * private copy for this procedure to use. Such sharing of procedure
220
         * bodies is rare but can cause problems. A procedure body is compiled
221
         * in a context that includes the number of compiler-allocated "slots"
222
         * for local variables. Each formal parameter is given a local variable
223
         * slot (the "procPtr->numCompiledLocals = numArgs" assignment
224
         * below). This means that the same code can not be shared by two
225
         * procedures that have a different number of arguments, even if their
226
         * bodies are identical. Note that we don't use Tcl_DuplicateObj since
227
         * we would not want any bytecode internal representation.
228
         */
229
 
230
        if (Tcl_IsShared(bodyPtr)) {
231
            bytes = Tcl_GetStringFromObj(bodyPtr, &length);
232
            bodyPtr = Tcl_NewStringObj(bytes, length);
233
        }
234
 
235
        /*
236
         * Create and initialize a Proc structure for the procedure. Note that
237
         * we initialize its cmdPtr field below after we've created the command
238
         * for the procedure. We increment the ref count of the procedure's
239
         * body object since there will be a reference to it in the Proc
240
         * structure.
241
         */
242
 
243
        Tcl_IncrRefCount(bodyPtr);
244
 
245
        procPtr = (Proc *) ckalloc(sizeof(Proc));
246
        procPtr->iPtr = iPtr;
247
        procPtr->refCount = 1;
248
        procPtr->bodyPtr = bodyPtr;
249
        procPtr->numArgs  = 0;   /* actual argument count is set below. */
250
        procPtr->numCompiledLocals = 0;
251
        procPtr->firstLocalPtr = NULL;
252
        procPtr->lastLocalPtr = NULL;
253
    }
254
 
255
    /*
256
     * Break up the argument list into argument specifiers, then process
257
     * each argument specifier.
258
     * If the body is precompiled, processing is limited to checking that
259
     * the the parsed argument is consistent with the one stored in the
260
     * Proc.
261
     * THIS FAILS IF THE ARG LIST OBJECT'S STRING REP CONTAINS NULLS.
262
     */
263
 
264
    args = Tcl_GetStringFromObj(argsPtr, &length);
265
    result = Tcl_SplitList(interp, args, &numArgs, &argArray);
266
    if (result != TCL_OK) {
267
        goto procError;
268
    }
269
 
270
    if (precompiled) {
271
        if (numArgs > procPtr->numArgs) {
272
            char buf[128];
273
            sprintf(buf, "\": arg list contains %d entries, precompiled header expects %d",
274
                    numArgs, procPtr->numArgs);
275
            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
276
                    "procedure \"", procName,
277
                    buf, (char *) NULL);
278
            goto procError;
279
        }
280
        localPtr = procPtr->firstLocalPtr;
281
    } else {
282
        procPtr->numArgs = numArgs;
283
        procPtr->numCompiledLocals = numArgs;
284
    }
285
    for (i = 0;  i < numArgs;  i++) {
286
        int fieldCount, nameLength, valueLength;
287
        char **fieldValues;
288
 
289
        /*
290
         * Now divide the specifier up into name and default.
291
         */
292
 
293
        result = Tcl_SplitList(interp, argArray[i], &fieldCount,
294
                &fieldValues);
295
        if (result != TCL_OK) {
296
            goto procError;
297
        }
298
        if (fieldCount > 2) {
299
            ckfree((char *) fieldValues);
300
            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
301
                    "too many fields in argument specifier \"",
302
                    argArray[i], "\"", (char *) NULL);
303
            goto procError;
304
        }
305
        if ((fieldCount == 0) || (*fieldValues[0] == 0)) {
306
            ckfree((char *) fieldValues);
307
            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
308
                    "procedure \"", procName,
309
                    "\" has argument with no name", (char *) NULL);
310
            goto procError;
311
        }
312
 
313
        nameLength = strlen(fieldValues[0]);
314
        if (fieldCount == 2) {
315
            valueLength = strlen(fieldValues[1]);
316
        } else {
317
            valueLength = 0;
318
        }
319
 
320
        /*
321
         * Check that the formal parameter name is a scalar.
322
         */
323
 
324
        p = fieldValues[0];
325
        while (*p != '\0') {
326
            if (*p == '(') {
327
                char *q = p;
328
                do {
329
                    q++;
330
                } while (*q != '\0');
331
                q--;
332
                if (*q == ')') { /* we have an array element */
333
                    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
334
                            "procedure \"", procName,
335
                            "\" has formal parameter \"", fieldValues[0],
336
                            "\" that is an array element",
337
                            (char *) NULL);
338
                    ckfree((char *) fieldValues);
339
                    goto procError;
340
                }
341
            }
342
            p++;
343
        }
344
 
345
        if (precompiled) {
346
            /*
347
             * compare the parsed argument with the stored one
348
             */
349
 
350
            if ((localPtr->nameLength != nameLength)
351
                    || (strcmp(localPtr->name, fieldValues[0]))
352
                    || (localPtr->frameIndex != i)
353
                    || (localPtr->flags != (VAR_SCALAR | VAR_ARGUMENT))
354
                    || ((localPtr->defValuePtr == NULL)
355
                            && (fieldCount == 2))
356
                    || ((localPtr->defValuePtr != NULL)
357
                            && (fieldCount != 2))) {
358
                char buf[128];
359
                sprintf(buf, "\": formal parameter %d is inconsistent with precompiled body",
360
                        i);
361
                Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
362
                        "procedure \"", procName,
363
                        buf, (char *) NULL);
364
                ckfree((char *) fieldValues);
365
                goto procError;
366
            }
367
 
368
            /*
369
             * compare the default value if any
370
             */
371
 
372
            if (localPtr->defValuePtr != NULL) {
373
                int tmpLength;
374
                char *tmpPtr = Tcl_GetStringFromObj(localPtr->defValuePtr,
375
                        &tmpLength);
376
                if ((valueLength != tmpLength)
377
                        || (strncmp(fieldValues[1], tmpPtr,
378
                                (size_t) tmpLength))) {
379
                    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
380
                            "procedure \"", procName,
381
                            "\": formal parameter \"",
382
                            fieldValues[0],
383
                            "\" has default value inconsistent with precompiled body",
384
                            (char *) NULL);
385
                    ckfree((char *) fieldValues);
386
                    goto procError;
387
                }
388
            }
389
 
390
            localPtr = localPtr->nextPtr;
391
        } else {
392
            /*
393
             * Allocate an entry in the runtime procedure frame's array of
394
             * local variables for the argument.
395
             */
396
 
397
            localPtr = (CompiledLocal *) ckalloc((unsigned)
398
                    (sizeof(CompiledLocal) - sizeof(localPtr->name)
399
                            + nameLength+1));
400
            if (procPtr->firstLocalPtr == NULL) {
401
                procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr;
402
            } else {
403
                procPtr->lastLocalPtr->nextPtr = localPtr;
404
                procPtr->lastLocalPtr = localPtr;
405
            }
406
            localPtr->nextPtr = NULL;
407
            localPtr->nameLength = nameLength;
408
            localPtr->frameIndex = i;
409
            localPtr->flags = VAR_SCALAR | VAR_ARGUMENT;
410
            localPtr->resolveInfo = NULL;
411
 
412
            if (fieldCount == 2) {
413
                localPtr->defValuePtr =
414
                    Tcl_NewStringObj(fieldValues[1], valueLength);
415
                Tcl_IncrRefCount(localPtr->defValuePtr);
416
            } else {
417
                localPtr->defValuePtr = NULL;
418
            }
419
            strcpy(localPtr->name, fieldValues[0]);
420
        }
421
 
422
        ckfree((char *) fieldValues);
423
    }
424
 
425
    /*
426
     * Now initialize the new procedure's cmdPtr field. This will be used
427
     * later when the procedure is called to determine what namespace the
428
     * procedure will run in. This will be different than the current
429
     * namespace if the proc was renamed into a different namespace.
430
     */
431
 
432
    *procPtrPtr = procPtr;
433
    ckfree((char *) argArray);
434
    return TCL_OK;
435
 
436
procError:
437
    if (precompiled) {
438
        procPtr->refCount--;
439
    } else {
440
        Tcl_DecrRefCount(bodyPtr);
441
        while (procPtr->firstLocalPtr != NULL) {
442
            localPtr = procPtr->firstLocalPtr;
443
            procPtr->firstLocalPtr = localPtr->nextPtr;
444
 
445
            defPtr = localPtr->defValuePtr;
446
            if (defPtr != NULL) {
447
                Tcl_DecrRefCount(defPtr);
448
            }
449
 
450
            ckfree((char *) localPtr);
451
        }
452
        ckfree((char *) procPtr);
453
    }
454
    if (argArray != NULL) {
455
        ckfree((char *) argArray);
456
    }
457
    return TCL_ERROR;
458
}
459
 
460
 
461
/*
462
 *----------------------------------------------------------------------
463
 *
464
 * TclGetFrame --
465
 *
466
 *      Given a description of a procedure frame, such as the first
467
 *      argument to an "uplevel" or "upvar" command, locate the
468
 *      call frame for the appropriate level of procedure.
469
 *
470
 * Results:
471
 *      The return value is -1 if an error occurred in finding the
472
 *      frame (in this case an error message is left in interp->result).
473
 *      1 is returned if string was either a number or a number preceded
474
 *      by "#" and it specified a valid frame.  0 is returned if string
475
 *      isn't one of the two things above (in this case, the lookup
476
 *      acts as if string were "1").  The variable pointed to by
477
 *      framePtrPtr is filled in with the address of the desired frame
478
 *      (unless an error occurs, in which case it isn't modified).
479
 *
480
 * Side effects:
481
 *      None.
482
 *
483
 *----------------------------------------------------------------------
484
 */
485
 
486
int
487
TclGetFrame(interp, string, framePtrPtr)
488
    Tcl_Interp *interp;         /* Interpreter in which to find frame. */
489
    char *string;               /* String describing frame. */
490
    CallFrame **framePtrPtr;    /* Store pointer to frame here (or NULL
491
                                 * if global frame indicated). */
492
{
493
    register Interp *iPtr = (Interp *) interp;
494
    int curLevel, level, result;
495
    CallFrame *framePtr;
496
 
497
    /*
498
     * Parse string to figure out which level number to go to.
499
     */
500
 
501
    result = 1;
502
    curLevel = (iPtr->varFramePtr == NULL) ? 0 : iPtr->varFramePtr->level;
503
    if (*string == '#') {
504
        if (Tcl_GetInt(interp, string+1, &level) != TCL_OK) {
505
            return -1;
506
        }
507
        if (level < 0) {
508
            levelError:
509
            Tcl_AppendResult(interp, "bad level \"", string, "\"",
510
                    (char *) NULL);
511
            return -1;
512
        }
513
    } else if (isdigit(UCHAR(*string))) {
514
        if (Tcl_GetInt(interp, string, &level) != TCL_OK) {
515
            return -1;
516
        }
517
        level = curLevel - level;
518
    } else {
519
        level = curLevel - 1;
520
        result = 0;
521
    }
522
 
523
    /*
524
     * Figure out which frame to use, and modify the interpreter so
525
     * its variables come from that frame.
526
     */
527
 
528
    if (level == 0) {
529
        framePtr = NULL;
530
    } else {
531
        for (framePtr = iPtr->varFramePtr; framePtr != NULL;
532
                framePtr = framePtr->callerVarPtr) {
533
            if (framePtr->level == level) {
534
                break;
535
            }
536
        }
537
        if (framePtr == NULL) {
538
            goto levelError;
539
        }
540
    }
541
    *framePtrPtr = framePtr;
542
    return result;
543
}
544
 
545
/*
546
 *----------------------------------------------------------------------
547
 *
548
 * Tcl_UplevelObjCmd --
549
 *
550
 *      This object procedure is invoked to process the "uplevel" Tcl
551
 *      command. See the user documentation for details on what it does.
552
 *
553
 * Results:
554
 *      A standard Tcl object result value.
555
 *
556
 * Side effects:
557
 *      See the user documentation.
558
 *
559
 *----------------------------------------------------------------------
560
 */
561
 
562
        /* ARGSUSED */
563
int
564
Tcl_UplevelObjCmd(dummy, interp, objc, objv)
565
    ClientData dummy;           /* Not used. */
566
    Tcl_Interp *interp;         /* Current interpreter. */
567
    int objc;                   /* Number of arguments. */
568
    Tcl_Obj *CONST objv[];      /* Argument objects. */
569
{
570
    register Interp *iPtr = (Interp *) interp;
571
    char *optLevel;
572
    int length, result;
573
    CallFrame *savedVarFramePtr, *framePtr;
574
 
575
    if (objc < 2) {
576
        uplevelSyntax:
577
        Tcl_WrongNumArgs(interp, 1, objv, "?level? command ?arg ...?");
578
        return TCL_ERROR;
579
    }
580
 
581
    /*
582
     * Find the level to use for executing the command.
583
     * THIS FAILS IF THE OBJECT RESULT'S STRING REP CONTAINS A NULL.
584
     */
585
 
586
    optLevel = Tcl_GetStringFromObj(objv[1], &length);
587
    result = TclGetFrame(interp, optLevel, &framePtr);
588
    if (result == -1) {
589
        return TCL_ERROR;
590
    }
591
    objc -= (result+1);
592
    if (objc == 0) {
593
        goto uplevelSyntax;
594
    }
595
    objv += (result+1);
596
 
597
    /*
598
     * Modify the interpreter state to execute in the given frame.
599
     */
600
 
601
    savedVarFramePtr = iPtr->varFramePtr;
602
    iPtr->varFramePtr = framePtr;
603
 
604
    /*
605
     * Execute the residual arguments as a command.
606
     */
607
 
608
    if (objc == 1) {
609
        result = Tcl_EvalObj(interp, objv[0]);
610
    } else {
611
        Tcl_Obj *cmdObjPtr = Tcl_ConcatObj(objc, objv);
612
        result = Tcl_EvalObj(interp, cmdObjPtr);
613
        Tcl_DecrRefCount(cmdObjPtr); /* done with object */
614
    }
615
    if (result == TCL_ERROR) {
616
        char msg[60];
617
        sprintf(msg, "\n    (\"uplevel\" body line %d)", interp->errorLine);
618
        Tcl_AddObjErrorInfo(interp, msg, -1);
619
    }
620
 
621
    /*
622
     * Restore the variable frame, and return.
623
     */
624
 
625
    iPtr->varFramePtr = savedVarFramePtr;
626
    return result;
627
}
628
 
629
/*
630
 *----------------------------------------------------------------------
631
 *
632
 * TclFindProc --
633
 *
634
 *      Given the name of a procedure, return a pointer to the
635
 *      record describing the procedure.
636
 *
637
 * Results:
638
 *      NULL is returned if the name doesn't correspond to any
639
 *      procedure.  Otherwise the return value is a pointer to
640
 *      the procedure's record.
641
 *
642
 * Side effects:
643
 *      None.
644
 *
645
 *----------------------------------------------------------------------
646
 */
647
 
648
Proc *
649
TclFindProc(iPtr, procName)
650
    Interp *iPtr;               /* Interpreter in which to look. */
651
    char *procName;             /* Name of desired procedure. */
652
{
653
    Tcl_Command cmd;
654
    Tcl_Command origCmd;
655
    Command *cmdPtr;
656
 
657
    cmd = Tcl_FindCommand((Tcl_Interp *) iPtr, procName,
658
            (Tcl_Namespace *) NULL, /*flags*/ 0);
659
    if (cmd == (Tcl_Command) NULL) {
660
        return NULL;
661
    }
662
    cmdPtr = (Command *) cmd;
663
 
664
    origCmd = TclGetOriginalCommand(cmd);
665
    if (origCmd != NULL) {
666
        cmdPtr = (Command *) origCmd;
667
    }
668
    if (cmdPtr->proc != TclProcInterpProc) {
669
        return NULL;
670
    }
671
    return (Proc *) cmdPtr->clientData;
672
}
673
 
674
/*
675
 *----------------------------------------------------------------------
676
 *
677
 * TclIsProc --
678
 *
679
 *      Tells whether a command is a Tcl procedure or not.
680
 *
681
 * Results:
682
 *      If the given command is actually a Tcl procedure, the
683
 *      return value is the address of the record describing
684
 *      the procedure.  Otherwise the return value is 0.
685
 *
686
 * Side effects:
687
 *      None.
688
 *
689
 *----------------------------------------------------------------------
690
 */
691
 
692
Proc *
693
TclIsProc(cmdPtr)
694
    Command *cmdPtr;            /* Command to test. */
695
{
696
    Tcl_Command origCmd;
697
 
698
    origCmd = TclGetOriginalCommand((Tcl_Command) cmdPtr);
699
    if (origCmd != NULL) {
700
        cmdPtr = (Command *) origCmd;
701
    }
702
    if (cmdPtr->proc == TclProcInterpProc) {
703
        return (Proc *) cmdPtr->clientData;
704
    }
705
    return (Proc *) 0;
706
}
707
 
708
/*
709
 *----------------------------------------------------------------------
710
 *
711
 * TclProcInterpProc --
712
 *
713
 *      When a Tcl procedure gets invoked with an argc/argv array of
714
 *      strings, this routine gets invoked to interpret the procedure.
715
 *
716
 * Results:
717
 *      A standard Tcl result value, usually TCL_OK.
718
 *
719
 * Side effects:
720
 *      Depends on the commands in the procedure.
721
 *
722
 *----------------------------------------------------------------------
723
 */
724
 
725
int
726
TclProcInterpProc(clientData, interp, argc, argv)
727
    ClientData clientData;      /* Record describing procedure to be
728
                                 * interpreted. */
729
    Tcl_Interp *interp;         /* Interpreter in which procedure was
730
                                 * invoked. */
731
    int argc;                   /* Count of number of arguments to this
732
                                 * procedure. */
733
    register char **argv;       /* Argument values. */
734
{
735
    register Tcl_Obj *objPtr;
736
    register int i;
737
    int result;
738
 
739
    /*
740
     * This procedure generates an objv array for object arguments that hold
741
     * the argv strings. It starts out with stack-allocated space but uses
742
     * dynamically-allocated storage if needed.
743
     */
744
 
745
#define NUM_ARGS 20
746
    Tcl_Obj *(objStorage[NUM_ARGS]);
747
    register Tcl_Obj **objv = objStorage;
748
 
749
    /*
750
     * Create the object argument array "objv". Make sure objv is large
751
     * enough to hold the objc arguments plus 1 extra for the zero
752
     * end-of-objv word.
753
     */
754
 
755
    if ((argc + 1) > NUM_ARGS) {
756
        objv = (Tcl_Obj **)
757
            ckalloc((unsigned)(argc + 1) * sizeof(Tcl_Obj *));
758
    }
759
 
760
    for (i = 0;  i < argc;  i++) {
761
        objv[i] = Tcl_NewStringObj(argv[i], -1);
762
        Tcl_IncrRefCount(objv[i]);
763
    }
764
    objv[argc] = 0;
765
 
766
    /*
767
     * Use TclObjInterpProc to actually interpret the procedure.
768
     */
769
 
770
    result = TclObjInterpProc(clientData, interp, argc, objv);
771
 
772
    /*
773
     * Move the interpreter's object result to the string result,
774
     * then reset the object result.
775
     * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
776
     */
777
 
778
    Tcl_SetResult(interp,
779
            TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
780
            TCL_VOLATILE);
781
 
782
    /*
783
     * Decrement the ref counts on the objv elements since we are done
784
     * with them.
785
     */
786
 
787
    for (i = 0;  i < argc;  i++) {
788
        objPtr = objv[i];
789
        TclDecrRefCount(objPtr);
790
    }
791
 
792
    /*
793
     * Free the objv array if malloc'ed storage was used.
794
     */
795
 
796
    if (objv != objStorage) {
797
        ckfree((char *) objv);
798
    }
799
    return result;
800
#undef NUM_ARGS
801
}
802
 
803
/*
804
 *----------------------------------------------------------------------
805
 *
806
 * TclObjInterpProc --
807
 *
808
 *      When a Tcl procedure gets invoked during bytecode evaluation, this
809
 *      object-based routine gets invoked to interpret the procedure.
810
 *
811
 * Results:
812
 *      A standard Tcl object result value.
813
 *
814
 * Side effects:
815
 *      Depends on the commands in the procedure.
816
 *
817
 *----------------------------------------------------------------------
818
 */
819
 
820
int
821
TclObjInterpProc(clientData, interp, objc, objv)
822
    ClientData clientData;      /* Record describing procedure to be
823
                                 * interpreted. */
824
    Tcl_Interp *interp;         /* Interpreter in which procedure was
825
                                 * invoked. */
826
    int objc;                   /* Count of number of arguments to this
827
                                 * procedure. */
828
    Tcl_Obj *CONST objv[];      /* Argument value objects. */
829
{
830
    Interp *iPtr = (Interp *) interp;
831
    Proc *procPtr = (Proc *) clientData;
832
    Namespace *nsPtr = procPtr->cmdPtr->nsPtr;
833
    CallFrame frame;
834
    register CallFrame *framePtr = &frame;
835
    register CompiledLocal *localPtr;
836
    char *procName, *bytes;
837
    int nameLen, localCt, numArgs, argCt, length, i, result;
838
    Var *varPtr;
839
 
840
    /*
841
     * This procedure generates an array "compiledLocals" that holds the
842
     * storage for local variables. It starts out with stack-allocated space
843
     * but uses dynamically-allocated storage if needed.
844
     */
845
 
846
#define NUM_LOCALS 20
847
    Var localStorage[NUM_LOCALS];
848
    Var *compiledLocals = localStorage;
849
 
850
    /*
851
     * Get the procedure's name.
852
     * THIS FAILS IF THE PROC NAME'S STRING REP HAS A NULL.
853
     */
854
 
855
    procName = Tcl_GetStringFromObj(objv[0], &nameLen);
856
 
857
    /*
858
     * If necessary, compile the procedure's body. The compiler will
859
     * allocate frame slots for the procedure's non-argument local
860
     * variables.  Note that compiling the body might increase
861
     * procPtr->numCompiledLocals if new local variables are found
862
     * while compiling.
863
     */
864
 
865
    result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr, nsPtr,
866
            "body of proc", procName);
867
 
868
    if (result != TCL_OK) {
869
        return result;
870
    }
871
 
872
    /*
873
     * Create the "compiledLocals" array. Make sure it is large enough to
874
     * hold all the procedure's compiled local variables, including its
875
     * formal parameters.
876
     */
877
 
878
    localCt = procPtr->numCompiledLocals;
879
    if (localCt > NUM_LOCALS) {
880
        compiledLocals = (Var *) ckalloc((unsigned) localCt * sizeof(Var));
881
    }
882
 
883
    /*
884
     * Set up and push a new call frame for the new procedure invocation.
885
     * This call frame will execute in the proc's namespace, which might
886
     * be different than the current namespace. The proc's namespace is
887
     * that of its command, which can change if the command is renamed
888
     * from one namespace to another.
889
     */
890
 
891
    result = Tcl_PushCallFrame(interp, (Tcl_CallFrame *) framePtr,
892
            (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 1);
893
 
894
    if (result != TCL_OK) {
895
        return result;
896
    }
897
 
898
    framePtr->objc = objc;
899
    framePtr->objv = objv;  /* ref counts for args are incremented below */
900
 
901
    /*
902
     * Initialize and resolve compiled variable references.
903
     */
904
 
905
    framePtr->procPtr = procPtr;
906
    framePtr->numCompiledLocals = localCt;
907
    framePtr->compiledLocals = compiledLocals;
908
 
909
    TclInitCompiledLocals(interp, framePtr, nsPtr);
910
 
911
    /*
912
     * Match and assign the call's actual parameters to the procedure's
913
     * formal arguments. The formal arguments are described by the first
914
     * numArgs entries in both the Proc structure's local variable list and
915
     * the call frame's local variable array.
916
     */
917
 
918
    numArgs = procPtr->numArgs;
919
    varPtr = framePtr->compiledLocals;
920
    localPtr = procPtr->firstLocalPtr;
921
    argCt = objc;
922
    for (i = 1, argCt -= 1;  i <= numArgs;  i++, argCt--) {
923
        if (!TclIsVarArgument(localPtr)) {
924
            panic("TclObjInterpProc: local variable %s is not argument but should be",
925
                  localPtr->name);
926
            return TCL_ERROR;
927
        }
928
        if (TclIsVarTemporary(localPtr)) {
929
            panic("TclObjInterpProc: local variable %d is temporary but should be an argument", i);
930
            return TCL_ERROR;
931
        }
932
 
933
        /*
934
         * Handle the special case of the last formal being "args".  When
935
         * it occurs, assign it a list consisting of all the remaining
936
         * actual arguments.
937
         */
938
 
939
        if ((i == numArgs) && ((localPtr->name[0] == 'a')
940
                && (strcmp(localPtr->name, "args") == 0))) {
941
            Tcl_Obj *listPtr = Tcl_NewListObj(argCt, &(objv[i]));
942
            varPtr->value.objPtr = listPtr;
943
            Tcl_IncrRefCount(listPtr); /* local var is a reference */
944
            varPtr->flags &= ~VAR_UNDEFINED;
945
            argCt = 0;
946
            break;              /* done processing args */
947
        } else if (argCt > 0) {
948
            Tcl_Obj *objPtr = objv[i];
949
            varPtr->value.objPtr = objPtr;
950
            varPtr->flags &= ~VAR_UNDEFINED;
951
            Tcl_IncrRefCount(objPtr);  /* since the local variable now has
952
                                        * another reference to object. */
953
        } else if (localPtr->defValuePtr != NULL) {
954
            Tcl_Obj *objPtr = localPtr->defValuePtr;
955
            varPtr->value.objPtr = objPtr;
956
            varPtr->flags &= ~VAR_UNDEFINED;
957
            Tcl_IncrRefCount(objPtr);  /* since the local variable now has
958
                                        * another reference to object. */
959
        } else {
960
            Tcl_ResetResult(interp);
961
            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
962
                    "no value given for parameter \"", localPtr->name,
963
                    "\" to \"", Tcl_GetStringFromObj(objv[0], (int *) NULL),
964
                    "\"", (char *) NULL);
965
            result = TCL_ERROR;
966
            goto procDone;
967
        }
968
        varPtr++;
969
        localPtr = localPtr->nextPtr;
970
    }
971
    if (argCt > 0) {
972
        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
973
                "called \"", Tcl_GetStringFromObj(objv[0], (int *) NULL),
974
                "\" with too many arguments", (char *) NULL);
975
        result = TCL_ERROR;
976
        goto procDone;
977
    }
978
 
979
    /*
980
     * Invoke the commands in the procedure's body.
981
     */
982
 
983
    if (tclTraceExec >= 1) {
984
        fprintf(stdout, "Calling proc ");
985
        for (i = 0;  i < objc;  i++) {
986
            bytes = Tcl_GetStringFromObj(objv[i], &length);
987
            TclPrintSource(stdout, bytes, TclMin(length, 15));
988
            fprintf(stdout, " ");
989
        }
990
        fprintf(stdout, "\n");
991
        fflush(stdout);
992
    }
993
 
994
    iPtr->returnCode = TCL_OK;
995
    procPtr->refCount++;
996
    result = Tcl_EvalObj(interp, procPtr->bodyPtr);
997
    procPtr->refCount--;
998
    if (procPtr->refCount <= 0) {
999
        TclProcCleanupProc(procPtr);
1000
    }
1001
 
1002
    if (result != TCL_OK) {
1003
        if (result == TCL_RETURN) {
1004
            result = TclUpdateReturnInfo(iPtr);
1005
        } else if (result == TCL_ERROR) {
1006
            char msg[100];
1007
            sprintf(msg, "\n    (procedure \"%.50s\" line %d)",
1008
                    procName, iPtr->errorLine);
1009
            Tcl_AddObjErrorInfo(interp, msg, -1);
1010
        } else if (result == TCL_BREAK) {
1011
            Tcl_ResetResult(interp);
1012
            Tcl_AppendToObj(Tcl_GetObjResult(interp),
1013
                    "invoked \"break\" outside of a loop", -1);
1014
            result = TCL_ERROR;
1015
        } else if (result == TCL_CONTINUE) {
1016
            Tcl_ResetResult(interp);
1017
            Tcl_AppendToObj(Tcl_GetObjResult(interp),
1018
                    "invoked \"continue\" outside of a loop", -1);
1019
            result = TCL_ERROR;
1020
        }
1021
    }
1022
 
1023
    procDone:
1024
 
1025
    /*
1026
     * Pop and free the call frame for this procedure invocation.
1027
     */
1028
 
1029
    Tcl_PopCallFrame(interp);
1030
 
1031
    /*
1032
     * Free the compiledLocals array if malloc'ed storage was used.
1033
     */
1034
 
1035
    if (compiledLocals != localStorage) {
1036
        ckfree((char *) compiledLocals);
1037
    }
1038
    return result;
1039
#undef NUM_LOCALS
1040
}
1041
 
1042
/*
1043
 *----------------------------------------------------------------------
1044
 *
1045
 * TclProcCompileProc --
1046
 *
1047
 *      Called just before a procedure is executed to compile the
1048
 *      body to byte codes.  If the type of the body is not
1049
 *      "byte code" or if the compile conditions have changed
1050
 *      (namespace context, epoch counters, etc.) then the body
1051
 *      is recompiled.  Otherwise, this procedure does nothing.
1052
 *
1053
 * Results:
1054
 *      None.
1055
 *
1056
 * Side effects:
1057
 *      May change the internal representation of the body object
1058
 *      to compiled code.
1059
 *
1060
 *----------------------------------------------------------------------
1061
 */
1062
 
1063
int
1064
TclProcCompileProc(interp, procPtr, bodyPtr, nsPtr, description, procName)
1065
    Tcl_Interp *interp;         /* Interpreter containing procedure. */
1066
    Proc *procPtr;              /* Data associated with procedure. */
1067
    Tcl_Obj *bodyPtr;           /* Body of proc. (Usually procPtr->bodyPtr,
1068
                                 * but could be any code fragment compiled
1069
                                 * in the context of this procedure.) */
1070
    Namespace *nsPtr;           /* Namespace containing procedure. */
1071
    CONST char *description;    /* string describing this body of code. */
1072
    CONST char *procName;       /* Name of this procedure. */
1073
{
1074
    Interp *iPtr = (Interp*)interp;
1075
    int result;
1076
    Tcl_CallFrame frame;
1077
    Proc *saveProcPtr;
1078
    ByteCode *codePtr = (ByteCode *) bodyPtr->internalRep.otherValuePtr;
1079
 
1080
    /*
1081
     * If necessary, compile the procedure's body. The compiler will
1082
     * allocate frame slots for the procedure's non-argument local
1083
     * variables. If the ByteCode already exists, make sure it hasn't been
1084
     * invalidated by someone redefining a core command (this might make the
1085
     * compiled code wrong). Also, if the code was compiled in/for a
1086
     * different interpreter, we recompile it. Note that compiling the body
1087
     * might increase procPtr->numCompiledLocals if new local variables are
1088
     * found while compiling.
1089
     *
1090
     * Precompiled procedure bodies, however, are immutable and therefore
1091
     * they are not recompiled, even if things have changed.
1092
     */
1093
 
1094
    if (bodyPtr->typePtr == &tclByteCodeType) {
1095
        if ((codePtr->iPtr != iPtr)
1096
                || (codePtr->compileEpoch != iPtr->compileEpoch)
1097
                || (codePtr->nsPtr != nsPtr)) {
1098
            if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
1099
                if (codePtr->iPtr != iPtr) {
1100
                    Tcl_AppendResult(interp,
1101
                            "a precompiled script jumped interps", NULL);
1102
                    return TCL_ERROR;
1103
                }
1104
                codePtr->compileEpoch = iPtr->compileEpoch;
1105
                codePtr->nsPtr = nsPtr;
1106
            } else {
1107
                tclByteCodeType.freeIntRepProc(bodyPtr);
1108
                bodyPtr->typePtr = (Tcl_ObjType *) NULL;
1109
            }
1110
        }
1111
    }
1112
    if (bodyPtr->typePtr != &tclByteCodeType) {
1113
        char buf[100];
1114
        int numChars;
1115
        char *ellipsis;
1116
 
1117
        if (tclTraceCompile >= 1) {
1118
            /*
1119
             * Display a line summarizing the top level command we
1120
             * are about to compile.
1121
             */
1122
 
1123
            numChars = strlen(procName);
1124
            ellipsis = "";
1125
            if (numChars > 50) {
1126
                numChars = 50;
1127
                ellipsis = "...";
1128
            }
1129
            fprintf(stdout, "Compiling %s \"%.*s%s\"\n",
1130
                    description, numChars, procName, ellipsis);
1131
        }
1132
 
1133
        /*
1134
         * Plug the current procPtr into the interpreter and coerce
1135
         * the code body to byte codes.  The interpreter needs to
1136
         * know which proc it's compiling so that it can access its
1137
         * list of compiled locals.
1138
         *
1139
         * TRICKY NOTE:  Be careful to push a call frame with the
1140
         *   proper namespace context, so that the byte codes are
1141
         *   compiled in the appropriate class context.
1142
         */
1143
 
1144
        saveProcPtr = iPtr->compiledProcPtr;
1145
        iPtr->compiledProcPtr = procPtr;
1146
 
1147
        result = Tcl_PushCallFrame(interp, &frame,
1148
                (Tcl_Namespace*)nsPtr, /* isProcCallFrame */ 0);
1149
 
1150
        if (result == TCL_OK) {
1151
            result = tclByteCodeType.setFromAnyProc(interp, bodyPtr);
1152
            Tcl_PopCallFrame(interp);
1153
        }
1154
 
1155
        iPtr->compiledProcPtr = saveProcPtr;
1156
 
1157
        if (result != TCL_OK) {
1158
            if (result == TCL_ERROR) {
1159
                numChars = strlen(procName);
1160
                ellipsis = "";
1161
                if (numChars > 50) {
1162
                    numChars = 50;
1163
                    ellipsis = "...";
1164
                }
1165
                sprintf(buf, "\n    (compiling %s \"%.*s%s\", line %d)",
1166
                        description, numChars, procName, ellipsis,
1167
                        interp->errorLine);
1168
                Tcl_AddObjErrorInfo(interp, buf, -1);
1169
            }
1170
            return result;
1171
        }
1172
    } else if (codePtr->nsEpoch != nsPtr->resolverEpoch) {
1173
        register CompiledLocal *localPtr;
1174
 
1175
        /*
1176
         * The resolver epoch has changed, but we only need to invalidate
1177
         * the resolver cache.
1178
         */
1179
 
1180
        for (localPtr = procPtr->firstLocalPtr;  localPtr != NULL;
1181
            localPtr = localPtr->nextPtr) {
1182
            localPtr->flags &= ~(VAR_RESOLVED);
1183
            if (localPtr->resolveInfo) {
1184
                if (localPtr->resolveInfo->deleteProc) {
1185
                    localPtr->resolveInfo->deleteProc(localPtr->resolveInfo);
1186
                } else {
1187
                    ckfree((char*)localPtr->resolveInfo);
1188
                }
1189
                localPtr->resolveInfo = NULL;
1190
            }
1191
        }
1192
    }
1193
    return TCL_OK;
1194
}
1195
 
1196
 
1197
/*
1198
 *----------------------------------------------------------------------
1199
 *
1200
 * TclProcDeleteProc --
1201
 *
1202
 *      This procedure is invoked just before a command procedure is
1203
 *      removed from an interpreter.  Its job is to release all the
1204
 *      resources allocated to the procedure.
1205
 *
1206
 * Results:
1207
 *      None.
1208
 *
1209
 * Side effects:
1210
 *      Memory gets freed, unless the procedure is actively being
1211
 *      executed.  In this case the cleanup is delayed until the
1212
 *      last call to the current procedure completes.
1213
 *
1214
 *----------------------------------------------------------------------
1215
 */
1216
 
1217
void
1218
TclProcDeleteProc(clientData)
1219
    ClientData clientData;              /* Procedure to be deleted. */
1220
{
1221
    Proc *procPtr = (Proc *) clientData;
1222
 
1223
    procPtr->refCount--;
1224
    if (procPtr->refCount <= 0) {
1225
        TclProcCleanupProc(procPtr);
1226
    }
1227
}
1228
 
1229
/*
1230
 *----------------------------------------------------------------------
1231
 *
1232
 * TclProcCleanupProc --
1233
 *
1234
 *      This procedure does all the real work of freeing up a Proc
1235
 *      structure.  It's called only when the structure's reference
1236
 *      count becomes zero.
1237
 *
1238
 * Results:
1239
 *      None.
1240
 *
1241
 * Side effects:
1242
 *      Memory gets freed.
1243
 *
1244
 *----------------------------------------------------------------------
1245
 */
1246
 
1247
void
1248
TclProcCleanupProc(procPtr)
1249
    register Proc *procPtr;             /* Procedure to be deleted. */
1250
{
1251
    register CompiledLocal *localPtr;
1252
    Tcl_Obj *bodyPtr = procPtr->bodyPtr;
1253
    Tcl_Obj *defPtr;
1254
    Tcl_ResolvedVarInfo *resVarInfo;
1255
 
1256
    if (bodyPtr != NULL) {
1257
        Tcl_DecrRefCount(bodyPtr);
1258
    }
1259
    for (localPtr = procPtr->firstLocalPtr;  localPtr != NULL;  ) {
1260
        CompiledLocal *nextPtr = localPtr->nextPtr;
1261
 
1262
        resVarInfo = localPtr->resolveInfo;
1263
        if (resVarInfo) {
1264
            if (resVarInfo->deleteProc) {
1265
                (*resVarInfo->deleteProc)(resVarInfo);
1266
            } else {
1267
                ckfree((char *) resVarInfo);
1268
            }
1269
        }
1270
 
1271
        if (localPtr->defValuePtr != NULL) {
1272
            defPtr = localPtr->defValuePtr;
1273
            Tcl_DecrRefCount(defPtr);
1274
        }
1275
        ckfree((char *) localPtr);
1276
        localPtr = nextPtr;
1277
    }
1278
    ckfree((char *) procPtr);
1279
}
1280
 
1281
/*
1282
 *----------------------------------------------------------------------
1283
 *
1284
 * TclUpdateReturnInfo --
1285
 *
1286
 *      This procedure is called when procedures return, and at other
1287
 *      points where the TCL_RETURN code is used.  It examines fields
1288
 *      such as iPtr->returnCode and iPtr->errorCode and modifies
1289
 *      the real return status accordingly.
1290
 *
1291
 * Results:
1292
 *      The return value is the true completion code to use for
1293
 *      the procedure, instead of TCL_RETURN.
1294
 *
1295
 * Side effects:
1296
 *      The errorInfo and errorCode variables may get modified.
1297
 *
1298
 *----------------------------------------------------------------------
1299
 */
1300
 
1301
int
1302
TclUpdateReturnInfo(iPtr)
1303
    Interp *iPtr;               /* Interpreter for which TCL_RETURN
1304
                                 * exception is being processed. */
1305
{
1306
    int code;
1307
 
1308
    code = iPtr->returnCode;
1309
    iPtr->returnCode = TCL_OK;
1310
    if (code == TCL_ERROR) {
1311
        Tcl_SetVar2((Tcl_Interp *) iPtr, "errorCode", (char *) NULL,
1312
                (iPtr->errorCode != NULL) ? iPtr->errorCode : "NONE",
1313
                TCL_GLOBAL_ONLY);
1314
        iPtr->flags |= ERROR_CODE_SET;
1315
        if (iPtr->errorInfo != NULL) {
1316
            Tcl_SetVar2((Tcl_Interp *) iPtr, "errorInfo", (char *) NULL,
1317
                    iPtr->errorInfo, TCL_GLOBAL_ONLY);
1318
            iPtr->flags |= ERR_IN_PROGRESS;
1319
        }
1320
    }
1321
    return code;
1322
}
1323
 
1324
/*
1325
 *----------------------------------------------------------------------
1326
 *
1327
 * TclGetInterpProc --
1328
 *
1329
 *  Returns a pointer to the TclProcInterpProc procedure; this is different
1330
 *  from the value obtained from the TclProcInterpProc reference on systems
1331
 *  like Windows where import and export versions of a procedure exported
1332
 *  by a DLL exist.
1333
 *
1334
 * Results:
1335
 *  Returns the internal address of the TclProcInterpProc procedure.
1336
 *
1337
 * Side effects:
1338
 *  None.
1339
 *
1340
 *----------------------------------------------------------------------
1341
 */
1342
 
1343
TclCmdProcType
1344
TclGetInterpProc()
1345
{
1346
    return TclProcInterpProc;
1347
}
1348
 
1349
/*
1350
 *----------------------------------------------------------------------
1351
 *
1352
 * TclGetObjInterpProc --
1353
 *
1354
 *  Returns a pointer to the TclObjInterpProc procedure; this is different
1355
 *  from the value obtained from the TclObjInterpProc reference on systems
1356
 *  like Windows where import and export versions of a procedure exported
1357
 *  by a DLL exist.
1358
 *
1359
 * Results:
1360
 *  Returns the internal address of the TclObjInterpProc procedure.
1361
 *
1362
 * Side effects:
1363
 *  None.
1364
 *
1365
 *----------------------------------------------------------------------
1366
 */
1367
 
1368
TclObjCmdProcType
1369
TclGetObjInterpProc()
1370
{
1371
    return TclObjInterpProc;
1372
}
1373
 
1374
/*
1375
 *----------------------------------------------------------------------
1376
 *
1377
 * TclNewProcBodyObj --
1378
 *
1379
 *  Creates a new object, of type "procbody", whose internal
1380
 *  representation is the given Proc struct.
1381
 *  The newly created object's reference count is 0.
1382
 *
1383
 * Results:
1384
 *  Returns a pointer to a newly allocated Tcl_Obj, 0 on error.
1385
 *
1386
 * Side effects:
1387
 *  The reference count in the ByteCode attached to the Proc is bumped up
1388
 *  by one, since the internal rep stores a pointer to it.
1389
 *
1390
 *----------------------------------------------------------------------
1391
 */
1392
 
1393
Tcl_Obj *
1394
TclNewProcBodyObj(procPtr)
1395
    Proc *procPtr;      /* the Proc struct to store as the internal
1396
                         * representation. */
1397
{
1398
    Tcl_Obj *objPtr;
1399
 
1400
    if (!procPtr) {
1401
        return (Tcl_Obj *) NULL;
1402
    }
1403
 
1404
    objPtr = Tcl_NewStringObj("", 0);
1405
 
1406
    if (objPtr) {
1407
        objPtr->typePtr = &tclProcBodyType;
1408
        objPtr->internalRep.otherValuePtr = (VOID *) procPtr;
1409
 
1410
        procPtr->refCount++;
1411
    }
1412
 
1413
    return objPtr;
1414
}
1415
 
1416
/*
1417
 *----------------------------------------------------------------------
1418
 *
1419
 * ProcBodyDup --
1420
 *
1421
 *  Tcl_ObjType's Dup function for the proc body object.
1422
 *  Bumps the reference count on the Proc stored in the internal
1423
 *  representation.
1424
 *
1425
 * Results:
1426
 *  None.
1427
 *
1428
 * Side effects:
1429
 *  Sets up the object in dupPtr to be a duplicate of the one in srcPtr.
1430
 *
1431
 *----------------------------------------------------------------------
1432
 */
1433
 
1434
static void ProcBodyDup(srcPtr, dupPtr)
1435
    Tcl_Obj *srcPtr;            /* object to copy */
1436
    Tcl_Obj *dupPtr;            /* target object for the duplication */
1437
{
1438
    Proc *procPtr = (Proc *) srcPtr->internalRep.otherValuePtr;
1439
 
1440
    dupPtr->typePtr = &tclProcBodyType;
1441
    dupPtr->internalRep.otherValuePtr = (VOID *) procPtr;
1442
    procPtr->refCount++;
1443
}
1444
 
1445
/*
1446
 *----------------------------------------------------------------------
1447
 *
1448
 * ProcBodyFree --
1449
 *
1450
 *  Tcl_ObjType's Free function for the proc body object.
1451
 *  The reference count on its Proc struct is decreased by 1; if the count
1452
 *  reaches 0, the proc is freed.
1453
 *
1454
 * Results:
1455
 *  None.
1456
 *
1457
 * Side effects:
1458
 *  If the reference count on the Proc struct reaches 0, the struct is freed.
1459
 *
1460
 *----------------------------------------------------------------------
1461
 */
1462
 
1463
static void
1464
ProcBodyFree(objPtr)
1465
    Tcl_Obj *objPtr;            /* the object to clean up */
1466
{
1467
    Proc *procPtr = (Proc *) objPtr->internalRep.otherValuePtr;
1468
    procPtr->refCount--;
1469
    if (procPtr->refCount <= 0) {
1470
        TclProcCleanupProc(procPtr);
1471
    }
1472
}
1473
 
1474
/*
1475
 *----------------------------------------------------------------------
1476
 *
1477
 * ProcBodySetFromAny --
1478
 *
1479
 *  Tcl_ObjType's SetFromAny function for the proc body object.
1480
 *  Calls panic.
1481
 *
1482
 * Results:
1483
 *  Theoretically returns a TCL result code.
1484
 *
1485
 * Side effects:
1486
 *  Calls panic, since we can't set the value of the object from a string
1487
 *  representation (or any other internal ones).
1488
 *
1489
 *----------------------------------------------------------------------
1490
 */
1491
 
1492
static int
1493
ProcBodySetFromAny(interp, objPtr)
1494
    Tcl_Interp *interp;                 /* current interpreter */
1495
    Tcl_Obj *objPtr;                    /* object pointer */
1496
{
1497
    panic("called ProcBodySetFromAny");
1498
 
1499
    /*
1500
     * this to keep compilers happy.
1501
     */
1502
 
1503
    return TCL_OK;
1504
}
1505
 
1506
/*
1507
 *----------------------------------------------------------------------
1508
 *
1509
 * ProcBodyUpdateString --
1510
 *
1511
 *  Tcl_ObjType's UpdateString function for the proc body object.
1512
 *  Calls panic.
1513
 *
1514
 * Results:
1515
 *  None.
1516
 *
1517
 * Side effects:
1518
 *  Calls panic, since we this type has no string representation.
1519
 *
1520
 *----------------------------------------------------------------------
1521
 */
1522
 
1523
static void
1524
ProcBodyUpdateString(objPtr)
1525
    Tcl_Obj *objPtr;            /* the object to update */
1526
{
1527
    panic("called ProcBodyUpdateString");
1528
}

powered by: WebSVN 2.1.0

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