os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclExecute.c
Update contrib.
4 * This file contains procedures that execute byte-compiled Tcl
7 * Copyright (c) 1996-1997 Sun Microsystems, Inc.
8 * Copyright (c) 1998-2000 by Scriptics Corporation.
9 * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
10 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
12 * See the file "license.terms" for information on usage and redistribution
13 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 * RCS: @(#) $Id: tclExecute.c,v 1.94.2.21 2007/03/13 16:26:32 dgp Exp $
19 #include "tclCompile.h"
23 * The stuff below is a bit of a hack so that this file can be used
24 * in environments that include no UNIX, i.e. no errno. Just define
28 #ifndef TCL_GENERIC_ONLY
30 #else /* TCL_GENERIC_ONLY */
33 # else /* NO_FLOAT_H */
36 # endif /* !NO_VALUES_H */
37 # endif /* !NO_FLOAT_H */
39 #endif /* !TCL_GENERIC_ONLY */
48 * Need DBL_MAX for IS_INF() macro...
52 # define DBL_MAX MAXDOUBLE
53 # else /* !MAXDOUBLE */
55 * This value is from the Solaris headers, but doubles seem to be the
56 * same size everywhere. Long doubles aren't, but we don't use those.
58 # define DBL_MAX 1.79769313486231570e+308
59 # endif /* MAXDOUBLE */
63 * Boolean flag indicating whether the Tcl bytecode interpreter has been
67 static int execInitialized = 0;
68 TCL_DECLARE_MUTEX(execMutex)
70 #ifdef TCL_COMPILE_DEBUG
72 * Variable that controls whether execution tracing is enabled and, if so,
73 * what level of tracing is desired:
74 * 0: no execution tracing
75 * 1: trace invocations of Tcl procs only
76 * 2: trace invocations of all (not compiled away) commands
77 * 3: display each instruction executed
78 * This variable is linked to the Tcl variable "tcl_traceExec".
85 * Mapping from expression instruction opcodes to strings; used for error
86 * messages. Note that these entries must match the order and number of the
87 * expression opcodes (e.g., INST_LOR) in tclCompile.h.
90 static char *operatorStrings[] = {
91 "||", "&&", "|", "^", "&", "==", "!=", "<", ">", "<=", ">=", "<<", ">>",
92 "+", "-", "*", "/", "%", "+", "-", "~", "!",
93 "BUILTIN FUNCTION", "FUNCTION",
94 "", "", "", "", "", "", "", "", "eq", "ne",
98 * Mapping from Tcl result codes to strings; used for error and debugging
102 #ifdef TCL_COMPILE_DEBUG
103 static char *resultStrings[] = {
104 "TCL_OK", "TCL_ERROR", "TCL_RETURN", "TCL_BREAK", "TCL_CONTINUE"
109 * These are used by evalstats to monitor object usage in Tcl.
112 #ifdef TCL_COMPILE_STATS
113 long tclObjsAlloced = 0;
114 long tclObjsFreed = 0;
115 #define TCL_MAX_SHARED_OBJ_STATS 5
116 long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS] = { 0, 0, 0, 0, 0 };
117 #endif /* TCL_COMPILE_STATS */
120 * Macros for testing floating-point values for certain special cases. Test
121 * for not-a-number by comparing a value against itself; test for infinity
122 * by comparing against the largest floating-point value.
125 #define IS_NAN(v) ((v) != (v))
126 #define IS_INF(v) (((v) > DBL_MAX) || ((v) < -DBL_MAX))
129 * The new macro for ending an instruction; note that a
130 * reasonable C-optimiser will resolve all branches
131 * at compile time. (result) is always a constant; the macro
132 * NEXT_INST_F handles constant (nCleanup), NEXT_INST_V is
133 * resolved at runtime for variable (nCleanup).
136 * pcAdjustment: how much to increment pc
137 * nCleanup: how many objects to remove from the stack
138 * result: 0 indicates no object should be pushed on the
139 * stack; otherwise, push objResultPtr. If (result < 0),
140 * objResultPtr already has the correct reference count.
143 #define NEXT_INST_F(pcAdjustment, nCleanup, result) \
144 if (nCleanup == 0) {\
147 PUSH_OBJECT(objResultPtr);\
149 stackPtr[++stackTop] = objResultPtr;\
152 pc += (pcAdjustment);\
154 } else if (result != 0) {\
156 Tcl_IncrRefCount(objResultPtr);\
158 pc += (pcAdjustment);\
160 case 1: goto cleanup1_pushObjResultPtr;\
161 case 2: goto cleanup2_pushObjResultPtr;\
162 default: panic("ERROR: bad usage of macro NEXT_INST_F");\
165 pc += (pcAdjustment);\
167 case 1: goto cleanup1;\
168 case 2: goto cleanup2;\
169 default: panic("ERROR: bad usage of macro NEXT_INST_F");\
173 #define NEXT_INST_V(pcAdjustment, nCleanup, result) \
174 pc += (pcAdjustment);\
175 cleanup = (nCleanup);\
178 Tcl_IncrRefCount(objResultPtr);\
180 goto cleanupV_pushObjResultPtr;\
187 * Macros used to cache often-referenced Tcl evaluation stack information
188 * in local variables. Note that a DECACHE_STACK_INFO()-CACHE_STACK_INFO()
189 * pair must surround any call inside TclExecuteByteCode (and a few other
190 * procedures that use this scheme) that could result in a recursive call
191 * to TclExecuteByteCode.
194 #define CACHE_STACK_INFO() \
195 stackPtr = eePtr->stackPtr; \
196 stackTop = eePtr->stackTop
198 #define DECACHE_STACK_INFO() \
199 eePtr->stackTop = stackTop
203 * Macros used to access items on the Tcl evaluation stack. PUSH_OBJECT
204 * increments the object's ref count since it makes the stack have another
205 * reference pointing to the object. However, POP_OBJECT does not decrement
206 * the ref count. This is because the stack may hold the only reference to
207 * the object, so the object would be destroyed if its ref count were
208 * decremented before the caller had a chance to, e.g., store it in a
209 * variable. It is the caller's responsibility to decrement the ref count
210 * when it is finished with an object.
212 * WARNING! It is essential that objPtr only appear once in the PUSH_OBJECT
213 * macro. The actual parameter might be an expression with side effects,
214 * and this ensures that it will be executed only once.
217 #define PUSH_OBJECT(objPtr) \
218 Tcl_IncrRefCount(stackPtr[++stackTop] = (objPtr))
220 #define POP_OBJECT() \
221 (stackPtr[stackTop--])
224 * Macros used to trace instruction execution. The macros TRACE,
225 * TRACE_WITH_OBJ, and O2S are only used inside TclExecuteByteCode.
226 * O2S is only used in TRACE* calls to get a string from an object.
229 #ifdef TCL_COMPILE_DEBUG
231 if (traceInstructions) { \
232 fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, stackTop, \
233 (unsigned int)(pc - codePtr->codeStart), \
234 GetOpcodeName(pc)); \
237 # define TRACE_APPEND(a) \
238 if (traceInstructions) { \
241 # define TRACE_WITH_OBJ(a, objPtr) \
242 if (traceInstructions) { \
243 fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, stackTop, \
244 (unsigned int)(pc - codePtr->codeStart), \
245 GetOpcodeName(pc)); \
247 TclPrintObject(stdout, objPtr, 30); \
248 fprintf(stdout, "\n"); \
250 # define O2S(objPtr) \
251 (objPtr ? TclGetString(objPtr) : "")
252 #else /* !TCL_COMPILE_DEBUG */
254 # define TRACE_APPEND(a)
255 # define TRACE_WITH_OBJ(a, objPtr)
257 #endif /* TCL_COMPILE_DEBUG */
260 * Macro to read a string containing either a wide or an int and
261 * decide which it is while decoding it at the same time. This
262 * enforces the policy that integer constants between LONG_MIN and
263 * LONG_MAX (inclusive) are represented by normal longs, and integer
264 * constants outside that range are represented by wide ints.
266 * GET_WIDE_OR_INT is the same as REQUIRE_WIDE_OR_INT except it never
267 * generates an error message.
269 #define REQUIRE_WIDE_OR_INT(resultVar, objPtr, longVar, wideVar) \
270 (resultVar) = Tcl_GetWideIntFromObj(interp, (objPtr), &(wideVar)); \
271 if ((resultVar) == TCL_OK && (wideVar) >= Tcl_LongAsWide(LONG_MIN) \
272 && (wideVar) <= Tcl_LongAsWide(LONG_MAX)) { \
273 (objPtr)->typePtr = &tclIntType; \
274 (objPtr)->internalRep.longValue = (longVar) \
275 = Tcl_WideAsLong(wideVar); \
277 #define GET_WIDE_OR_INT(resultVar, objPtr, longVar, wideVar) \
278 (resultVar) = Tcl_GetWideIntFromObj((Tcl_Interp *) NULL, (objPtr), \
280 if ((resultVar) == TCL_OK && (wideVar) >= Tcl_LongAsWide(LONG_MIN) \
281 && (wideVar) <= Tcl_LongAsWide(LONG_MAX)) { \
282 (objPtr)->typePtr = &tclIntType; \
283 (objPtr)->internalRep.longValue = (longVar) \
284 = Tcl_WideAsLong(wideVar); \
287 * Combined with REQUIRE_WIDE_OR_INT, this gets a long value from
290 #define FORCE_LONG(objPtr, longVar, wideVar) \
291 if ((objPtr)->typePtr == &tclWideIntType) { \
292 (longVar) = Tcl_WideAsLong(wideVar); \
294 #define IS_INTEGER_TYPE(typePtr) \
295 ((typePtr) == &tclIntType || (typePtr) == &tclWideIntType)
296 #define IS_NUMERIC_TYPE(typePtr) \
297 (IS_INTEGER_TYPE(typePtr) || (typePtr) == &tclDoubleType)
299 #define W0 Tcl_LongAsWide(0)
301 * For tracing that uses wide values.
303 #define LLD "%" TCL_LL_MODIFIER "d"
305 #ifndef TCL_WIDE_INT_IS_LONG
307 * Extract a double value from a general numeric object.
309 #define GET_DOUBLE_VALUE(doubleVar, objPtr, typePtr) \
310 if ((typePtr) == &tclIntType) { \
311 (doubleVar) = (double) (objPtr)->internalRep.longValue; \
312 } else if ((typePtr) == &tclWideIntType) { \
313 (doubleVar) = Tcl_WideAsDouble((objPtr)->internalRep.wideValue);\
315 (doubleVar) = (objPtr)->internalRep.doubleValue; \
317 #else /* TCL_WIDE_INT_IS_LONG */
318 #define GET_DOUBLE_VALUE(doubleVar, objPtr, typePtr) \
319 if (((typePtr) == &tclIntType) || ((typePtr) == &tclWideIntType)) { \
320 (doubleVar) = (double) (objPtr)->internalRep.longValue; \
322 (doubleVar) = (objPtr)->internalRep.doubleValue; \
324 #endif /* TCL_WIDE_INT_IS_LONG */
327 * Declarations for local procedures to this file:
330 static int TclExecuteByteCode _ANSI_ARGS_((Tcl_Interp *interp,
332 static int ExprAbsFunc _ANSI_ARGS_((Tcl_Interp *interp,
333 ExecEnv *eePtr, ClientData clientData));
334 static int ExprBinaryFunc _ANSI_ARGS_((Tcl_Interp *interp,
335 ExecEnv *eePtr, ClientData clientData));
336 static int ExprCallMathFunc _ANSI_ARGS_((Tcl_Interp *interp,
337 ExecEnv *eePtr, int objc, Tcl_Obj **objv));
338 static int ExprDoubleFunc _ANSI_ARGS_((Tcl_Interp *interp,
339 ExecEnv *eePtr, ClientData clientData));
340 static int ExprIntFunc _ANSI_ARGS_((Tcl_Interp *interp,
341 ExecEnv *eePtr, ClientData clientData));
342 static int ExprRandFunc _ANSI_ARGS_((Tcl_Interp *interp,
343 ExecEnv *eePtr, ClientData clientData));
344 static int ExprRoundFunc _ANSI_ARGS_((Tcl_Interp *interp,
345 ExecEnv *eePtr, ClientData clientData));
346 static int ExprSrandFunc _ANSI_ARGS_((Tcl_Interp *interp,
347 ExecEnv *eePtr, ClientData clientData));
348 static int ExprUnaryFunc _ANSI_ARGS_((Tcl_Interp *interp,
349 ExecEnv *eePtr, ClientData clientData));
350 static int ExprWideFunc _ANSI_ARGS_((Tcl_Interp *interp,
351 ExecEnv *eePtr, ClientData clientData));
352 #ifdef TCL_COMPILE_STATS
353 static int EvalStatsCmd _ANSI_ARGS_((ClientData clientData,
354 Tcl_Interp *interp, int objc,
355 Tcl_Obj *CONST objv[]));
356 #endif /* TCL_COMPILE_STATS */
357 #ifdef TCL_COMPILE_DEBUG
358 static char * GetOpcodeName _ANSI_ARGS_((unsigned char *pc));
359 #endif /* TCL_COMPILE_DEBUG */
360 static ExceptionRange * GetExceptRangeForPc _ANSI_ARGS_((unsigned char *pc,
361 int catchOnly, ByteCode* codePtr));
362 static char * GetSrcInfoForPc _ANSI_ARGS_((unsigned char *pc,
363 ByteCode* codePtr, int *lengthPtr));
364 static void GrowEvaluationStack _ANSI_ARGS_((ExecEnv *eePtr));
365 static void IllegalExprOperandType _ANSI_ARGS_((
366 Tcl_Interp *interp, unsigned char *pc,
368 static void InitByteCodeExecution _ANSI_ARGS_((
369 Tcl_Interp *interp));
370 #ifdef TCL_COMPILE_DEBUG
371 static void PrintByteCodeInfo _ANSI_ARGS_((ByteCode *codePtr));
372 static char * StringForResultCode _ANSI_ARGS_((int result));
373 static void ValidatePcAndStackTop _ANSI_ARGS_((
374 ByteCode *codePtr, unsigned char *pc,
375 int stackTop, int stackLowerBound));
376 #endif /* TCL_COMPILE_DEBUG */
377 static int VerifyExprObjType _ANSI_ARGS_((Tcl_Interp *interp,
381 ========== Begin of math function wrappers =============
382 The math function wrappers bellow are need to avoid the "Import relocation does not refer to code segment" error
383 message reported from ELF2E32 tool.
386 static double Tcl_acos(double x)
391 static double Tcl_asin(double x)
396 static double Tcl_atan(double x)
401 static double Tcl_atan2(double x, double y)
406 static double Tcl_ceil(double num)
411 static double Tcl_cos(double x)
416 static double Tcl_cosh(double x)
421 static double Tcl_exp(double x)
426 static double Tcl_floor(double x)
431 static double Tcl_fmod(double numerator, double denominator)
433 return fmod(numerator, denominator);
436 static double Tcl_hypot(double x, double y)
441 static double Tcl_log(double x)
446 static double Tcl_log10(double x)
451 static double Tcl_pow(double base, double exponent)
453 return pow(base, exponent);
456 static double Tcl_sin(double x)
461 static double Tcl_sinh(double x)
466 static double Tcl_sqrt(double x)
471 static double Tcl_tan(double x)
476 static double Tcl_tanh(double x)
482 ========== End of math function wrappers ===============
486 * Table describing the built-in math functions. Entries in this table are
487 * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
491 BuiltinFunc tclBuiltinFuncTable[] = {
493 {"acos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_acos},
494 {"asin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_asin},
495 {"atan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_atan},
496 {"atan2", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) Tcl_atan2},
497 {"ceil", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_ceil},
498 {"cos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_cos},
499 {"cosh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_cosh},
500 {"exp", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_exp},
501 {"floor", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_floor},
502 {"fmod", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) Tcl_fmod},
503 {"hypot", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) Tcl_hypot},
504 {"log", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_log},
505 {"log10", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_log10},
506 {"pow", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) Tcl_pow},
507 {"sin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_sin},
508 {"sinh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_sinh},
509 {"sqrt", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_sqrt},
510 {"tan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_tan},
511 {"tanh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) Tcl_tanh},
513 {"abs", 1, {TCL_EITHER}, ExprAbsFunc, 0},
514 {"double", 1, {TCL_EITHER}, ExprDoubleFunc, 0},
515 {"int", 1, {TCL_EITHER}, ExprIntFunc, 0},
516 {"rand", 0, {TCL_EITHER}, ExprRandFunc, 0}, /* NOTE: rand takes no args. */
517 {"round", 1, {TCL_EITHER}, ExprRoundFunc, 0},
518 {"srand", 1, {TCL_INT}, ExprSrandFunc, 0},
519 {"wide", 1, {TCL_EITHER}, ExprWideFunc, 0},
524 *----------------------------------------------------------------------
526 * InitByteCodeExecution --
528 * This procedure is called once to initialize the Tcl bytecode
535 * This procedure initializes the array of instruction names. If
536 * compiling with the TCL_COMPILE_STATS flag, it initializes the
537 * array that counts the executions of each instruction and it
538 * creates the "evalstats" command. It also establishes the link
539 * between the Tcl "tcl_traceExec" and C "tclTraceExec" variables.
541 *----------------------------------------------------------------------
545 InitByteCodeExecution(interp)
546 Tcl_Interp *interp; /* Interpreter for which the Tcl variable
547 * "tcl_traceExec" is linked to control
548 * instruction tracing. */
550 #ifdef TCL_COMPILE_DEBUG
551 if (Tcl_LinkVar(interp, "tcl_traceExec", (char *) &tclTraceExec,
552 TCL_LINK_INT) != TCL_OK) {
553 panic("InitByteCodeExecution: can't create link for tcl_traceExec variable");
556 #ifdef TCL_COMPILE_STATS
557 Tcl_CreateObjCommand(interp, "evalstats", EvalStatsCmd,
558 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
559 #endif /* TCL_COMPILE_STATS */
563 *----------------------------------------------------------------------
565 * TclCreateExecEnv --
567 * This procedure creates a new execution environment for Tcl bytecode
568 * execution. An ExecEnv points to a Tcl evaluation stack. An ExecEnv
569 * is typically created once for each Tcl interpreter (Interp
570 * structure) and recursively passed to TclExecuteByteCode to execute
571 * ByteCode sequences for nested commands.
574 * A newly allocated ExecEnv is returned. This points to an empty
575 * evaluation stack of the standard initial size.
578 * The bytecode interpreter is also initialized here, as this
579 * procedure will be called before any call to TclExecuteByteCode.
581 *----------------------------------------------------------------------
584 #define TCL_STACK_INITIAL_SIZE 2000
587 TclCreateExecEnv(interp)
588 Tcl_Interp *interp; /* Interpreter for which the execution
589 * environment is being created. */
591 ExecEnv *eePtr = (ExecEnv *) ckalloc(sizeof(ExecEnv));
594 stackPtr = (Tcl_Obj **)
595 ckalloc((size_t) (TCL_STACK_INITIAL_SIZE * sizeof(Tcl_Obj *)));
598 * Use the bottom pointer to keep a reference count; the
599 * execution environment holds a reference.
603 eePtr->stackPtr = stackPtr;
604 stackPtr[-1] = (Tcl_Obj *) ((char *) 1);
606 eePtr->stackTop = -1;
607 eePtr->stackEnd = (TCL_STACK_INITIAL_SIZE - 2);
609 eePtr->errorInfo = Tcl_NewStringObj("::errorInfo", -1);
610 Tcl_IncrRefCount(eePtr->errorInfo);
612 eePtr->errorCode = Tcl_NewStringObj("::errorCode", -1);
613 Tcl_IncrRefCount(eePtr->errorCode);
615 Tcl_MutexLock(&execMutex);
616 if (!execInitialized) {
617 TclInitAuxDataTypeTable();
618 InitByteCodeExecution(interp);
621 Tcl_MutexUnlock(&execMutex);
625 #undef TCL_STACK_INITIAL_SIZE
628 *----------------------------------------------------------------------
630 * TclDeleteExecEnv --
632 * Frees the storage for an ExecEnv.
638 * Storage for an ExecEnv and its contained storage (e.g. the
639 * evaluation stack) is freed.
641 *----------------------------------------------------------------------
645 TclDeleteExecEnv(eePtr)
646 ExecEnv *eePtr; /* Execution environment to free. */
648 if (eePtr->stackPtr[-1] == (Tcl_Obj *) ((char *) 1)) {
649 ckfree((char *) (eePtr->stackPtr-1));
651 panic("ERROR: freeing an execEnv whose stack is still in use.\n");
653 TclDecrRefCount(eePtr->errorInfo);
654 TclDecrRefCount(eePtr->errorCode);
655 ckfree((char *) eePtr);
659 *----------------------------------------------------------------------
661 * TclFinalizeExecution --
663 * Finalizes the execution environment setup so that it can be
664 * later reinitialized.
670 * After this call, the next time TclCreateExecEnv will be called
671 * it will call InitByteCodeExecution.
673 *----------------------------------------------------------------------
677 TclFinalizeExecution()
679 Tcl_MutexLock(&execMutex);
681 Tcl_MutexUnlock(&execMutex);
682 TclFinalizeAuxDataTypeTable();
686 *----------------------------------------------------------------------
688 * GrowEvaluationStack --
690 * This procedure grows a Tcl evaluation stack stored in an ExecEnv.
696 * The size of the evaluation stack is doubled.
698 *----------------------------------------------------------------------
702 GrowEvaluationStack(eePtr)
703 register ExecEnv *eePtr; /* Points to the ExecEnv with an evaluation
704 * stack to enlarge. */
707 * The current Tcl stack elements are stored from eePtr->stackPtr[0]
708 * to eePtr->stackPtr[eePtr->stackEnd] (inclusive).
711 int currElems = (eePtr->stackEnd + 1);
712 int newElems = 2*currElems;
713 int currBytes = currElems * sizeof(Tcl_Obj *);
714 int newBytes = 2*currBytes;
715 Tcl_Obj **newStackPtr = (Tcl_Obj **) ckalloc((unsigned) newBytes);
716 Tcl_Obj **oldStackPtr = eePtr->stackPtr;
719 * We keep the stack reference count as a (char *), as that
720 * works nicely as a portable pointer-sized counter.
723 char *refCount = (char *) oldStackPtr[-1];
726 * Copy the existing stack items to the new stack space, free the old
727 * storage if appropriate, and record the refCount of the new stack
728 * held by the environment.
732 memcpy((VOID *) newStackPtr, (VOID *) oldStackPtr,
735 if (refCount == (char *) 1) {
736 ckfree((VOID *) (oldStackPtr-1));
739 * Remove the reference corresponding to the
740 * environment pointer.
743 oldStackPtr[-1] = (Tcl_Obj *) (refCount-1);
746 eePtr->stackPtr = newStackPtr;
747 eePtr->stackEnd = (newElems - 2); /* index of last usable item */
748 newStackPtr[-1] = (Tcl_Obj *) ((char *) 1);
752 *--------------------------------------------------------------
756 * Evaluate an expression in a Tcl_Obj.
759 * A standard Tcl object result. If the result is other than TCL_OK,
760 * then the interpreter's result contains an error message. If the
761 * result is TCL_OK, then a pointer to the expression's result value
762 * object is stored in resultPtrPtr. In that case, the object's ref
763 * count is incremented to reflect the reference returned to the
764 * caller; the caller is then responsible for the resulting object
765 * and must, for example, decrement the ref count when it is finished
769 * Any side effects caused by subcommands in the expression, if any.
770 * The interpreter result is not modified unless there is an error.
772 *--------------------------------------------------------------
776 Tcl_ExprObj(interp, objPtr, resultPtrPtr)
777 Tcl_Interp *interp; /* Context in which to evaluate the
779 register Tcl_Obj *objPtr; /* Points to Tcl object containing
780 * expression to evaluate. */
781 Tcl_Obj **resultPtrPtr; /* Where the Tcl_Obj* that is the expression
782 * result is stored if no errors occur. */
784 Interp *iPtr = (Interp *) interp;
785 CompileEnv compEnv; /* Compilation environment structure
786 * allocated in frame. */
787 LiteralTable *localTablePtr = &(compEnv.localLitTable);
788 register ByteCode *codePtr = NULL;
789 /* Tcl Internal type of bytecode.
790 * Initialized to avoid compiler warning. */
792 LiteralEntry *entryPtr;
795 int length, i, result;
798 * First handle some common expressions specially.
801 string = Tcl_GetStringFromObj(objPtr, &length);
803 if (*string == '0') {
804 *resultPtrPtr = Tcl_NewLongObj(0);
805 Tcl_IncrRefCount(*resultPtrPtr);
807 } else if (*string == '1') {
808 *resultPtrPtr = Tcl_NewLongObj(1);
809 Tcl_IncrRefCount(*resultPtrPtr);
812 } else if ((length == 2) && (*string == '!')) {
813 if (*(string+1) == '0') {
814 *resultPtrPtr = Tcl_NewLongObj(1);
815 Tcl_IncrRefCount(*resultPtrPtr);
817 } else if (*(string+1) == '1') {
818 *resultPtrPtr = Tcl_NewLongObj(0);
819 Tcl_IncrRefCount(*resultPtrPtr);
825 * Get the ByteCode from the object. If it exists, make sure it hasn't
826 * been invalidated by, e.g., someone redefining a command with a
827 * compile procedure (this might make the compiled code wrong). If
828 * necessary, convert the object to be a ByteCode object and compile it.
829 * Also, if the code was compiled in/for a different interpreter, we
832 * Precompiled expressions, however, are immutable and therefore
833 * they are not recompiled, even if the epoch has changed.
837 if (objPtr->typePtr == &tclByteCodeType) {
838 codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
839 if (((Interp *) *codePtr->interpHandle != iPtr)
840 || (codePtr->compileEpoch != iPtr->compileEpoch)) {
841 if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
842 if ((Interp *) *codePtr->interpHandle != iPtr) {
843 panic("Tcl_ExprObj: compiled expression jumped interps");
845 codePtr->compileEpoch = iPtr->compileEpoch;
847 (*tclByteCodeType.freeIntRepProc)(objPtr);
848 objPtr->typePtr = (Tcl_ObjType *) NULL;
852 if (objPtr->typePtr != &tclByteCodeType) {
854 TclInitCompileEnv(interp, &compEnv, string, length);
856 /* TIP #280 : No invoker (yet) - Expression compilation */
857 TclInitCompileEnv(interp, &compEnv, string, length, NULL, 0);
859 result = TclCompileExpr(interp, string, length, &compEnv);
862 * Free the compilation environment's literal table bucket array if
863 * it was dynamically allocated.
866 if (localTablePtr->buckets != localTablePtr->staticBuckets) {
867 ckfree((char *) localTablePtr->buckets);
870 if (result != TCL_OK) {
872 * Compilation errors. Free storage allocated for compilation.
875 #ifdef TCL_COMPILE_DEBUG
876 TclVerifyLocalLiteralTable(&compEnv);
877 #endif /*TCL_COMPILE_DEBUG*/
878 entryPtr = compEnv.literalArrayPtr;
879 for (i = 0; i < compEnv.literalArrayNext; i++) {
880 TclReleaseLiteral(interp, entryPtr->objPtr);
883 #ifdef TCL_COMPILE_DEBUG
884 TclVerifyGlobalLiteralTable(iPtr);
885 #endif /*TCL_COMPILE_DEBUG*/
887 auxDataPtr = compEnv.auxDataArrayPtr;
888 for (i = 0; i < compEnv.auxDataArrayNext; i++) {
889 if (auxDataPtr->type->freeProc != NULL) {
890 auxDataPtr->type->freeProc(auxDataPtr->clientData);
894 TclFreeCompileEnv(&compEnv);
899 * Successful compilation. If the expression yielded no
900 * instructions, push an zero object as the expression's result.
903 if (compEnv.codeNext == compEnv.codeStart) {
904 TclEmitPush(TclRegisterLiteral(&compEnv, "0", 1, /*onHeap*/ 0),
909 * Add a "done" instruction as the last instruction and change the
910 * object into a ByteCode object. Ownership of the literal objects
911 * and aux data items is given to the ByteCode object.
914 compEnv.numSrcBytes = iPtr->termOffset;
915 TclEmitOpcode(INST_DONE, &compEnv);
916 TclInitByteCodeObj(objPtr, &compEnv);
917 TclFreeCompileEnv(&compEnv);
918 codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
919 #ifdef TCL_COMPILE_DEBUG
920 if (tclTraceCompile == 2) {
921 TclPrintByteCodeObj(interp, objPtr);
923 #endif /* TCL_COMPILE_DEBUG */
927 * Execute the expression after first saving the interpreter's result.
930 saveObjPtr = Tcl_GetObjResult(interp);
931 Tcl_IncrRefCount(saveObjPtr);
932 Tcl_ResetResult(interp);
935 * Increment the code's ref count while it is being executed. If
936 * afterwards no references to it remain, free the code.
940 result = TclExecuteByteCode(interp, codePtr);
942 if (codePtr->refCount <= 0) {
943 TclCleanupByteCode(codePtr);
944 objPtr->typePtr = NULL;
945 objPtr->internalRep.otherValuePtr = NULL;
949 * If the expression evaluated successfully, store a pointer to its
950 * value object in resultPtrPtr then restore the old interpreter result.
951 * We increment the object's ref count to reflect the reference that we
952 * are returning to the caller. We also decrement the ref count of the
953 * interpreter's result object after calling Tcl_SetResult since we
954 * next store into that field directly.
957 if (result == TCL_OK) {
958 *resultPtrPtr = iPtr->objResultPtr;
959 Tcl_IncrRefCount(iPtr->objResultPtr);
961 Tcl_SetObjResult(interp, saveObjPtr);
963 TclDecrRefCount(saveObjPtr);
968 *----------------------------------------------------------------------
972 * This procedure evaluates the script contained in a Tcl_Obj by
973 * first compiling it and then passing it to TclExecuteByteCode.
976 * The return value is one of the return codes defined in tcl.h
977 * (such as TCL_OK), and interp->objResultPtr refers to a Tcl object
978 * that either contains the result of executing the code or an
982 * Almost certainly, depending on the ByteCode's instructions.
984 *----------------------------------------------------------------------
989 TclCompEvalObj(interp, objPtr)
991 TclCompEvalObj(interp, objPtr, invoker, word)
996 CONST CmdFrame* invoker; /* Frame of the command doing the eval */
997 int word; /* Index of the word which is in objPtr */
1000 register Interp *iPtr = (Interp *) interp;
1001 register ByteCode* codePtr; /* Tcl Internal type of bytecode. */
1002 int oldCount = iPtr->cmdCount; /* Used to tell whether any commands
1003 * at all were executed. */
1007 Namespace *namespacePtr;
1011 * Check that the interpreter is ready to execute scripts
1015 if (TclInterpReady(interp) == TCL_ERROR) {
1020 if (iPtr->varFramePtr != NULL) {
1021 namespacePtr = iPtr->varFramePtr->nsPtr;
1023 namespacePtr = iPtr->globalNsPtr;
1027 * If the object is not already of tclByteCodeType, compile it (and
1028 * reset the compilation flags in the interpreter; this should be
1029 * done after any compilation).
1030 * Otherwise, check that it is "fresh" enough.
1033 if (objPtr->typePtr != &tclByteCodeType) {
1035 iPtr->errorLine = 1;
1038 /* TIP #280. Remember the invoker for a moment in the interpreter
1039 * structures so that the byte code compiler can pick it up when
1040 * initializing the compilation environment, i.e. the extended
1041 * location information.
1044 iPtr->invokeCmdFramePtr = invoker;
1045 iPtr->invokeWord = word;
1047 result = tclByteCodeType.setFromAnyProc(interp, objPtr);
1049 iPtr->invokeCmdFramePtr = NULL;
1052 if (result != TCL_OK) {
1056 codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
1059 * Make sure the Bytecode hasn't been invalidated by, e.g., someone
1060 * redefining a command with a compile procedure (this might make the
1061 * compiled code wrong).
1062 * The object needs to be recompiled if it was compiled in/for a
1063 * different interpreter, or for a different namespace, or for the
1064 * same namespace but with different name resolution rules.
1065 * Precompiled objects, however, are immutable and therefore
1066 * they are not recompiled, even if the epoch has changed.
1068 * To be pedantically correct, we should also check that the
1069 * originating procPtr is the same as the current context procPtr
1070 * (assuming one exists at all - none for global level). This
1071 * code is #def'ed out because [info body] was changed to never
1072 * return a bytecode type object, which should obviate us from
1073 * the extra checks here.
1075 codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
1076 if (((Interp *) *codePtr->interpHandle != iPtr)
1077 || (codePtr->compileEpoch != iPtr->compileEpoch)
1078 #ifdef CHECK_PROC_ORIGINATION /* [Bug: 3412 Pedantic] */
1079 || (codePtr->procPtr != NULL && !(iPtr->varFramePtr &&
1080 iPtr->varFramePtr->procPtr == codePtr->procPtr))
1082 || (codePtr->nsPtr != namespacePtr)
1083 || (codePtr->nsEpoch != namespacePtr->resolverEpoch)) {
1084 if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
1085 if ((Interp *) *codePtr->interpHandle != iPtr) {
1086 panic("Tcl_EvalObj: compiled script jumped interps");
1088 codePtr->compileEpoch = iPtr->compileEpoch;
1091 * This byteCode is invalid: free it and recompile
1093 tclByteCodeType.freeIntRepProc(objPtr);
1100 * Execute the commands. If the code was compiled from an empty string,
1101 * don't bother executing the code.
1104 numSrcBytes = codePtr->numSrcBytes;
1105 if ((numSrcBytes > 0) || (codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
1107 * Increment the code's ref count while it is being executed. If
1108 * afterwards no references to it remain, free the code.
1111 codePtr->refCount++;
1112 result = TclExecuteByteCode(interp, codePtr);
1113 codePtr->refCount--;
1114 if (codePtr->refCount <= 0) {
1115 TclCleanupByteCode(codePtr);
1124 * If no commands at all were executed, check for asynchronous
1125 * handlers so that they at least get one change to execute.
1126 * This is needed to handle event loops written in Tcl with
1130 if ((oldCount == iPtr->cmdCount) && Tcl_AsyncReady()) {
1131 result = Tcl_AsyncInvoke(interp, result);
1135 * If an error occurred, record information about what was being
1136 * executed when the error occurred.
1139 if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
1140 script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
1141 Tcl_LogCommandInfo(interp, script, script, numSrcBytes);
1146 * Set the interpreter's termOffset member to the offset of the
1147 * character just after the last one executed. We approximate the offset
1148 * of the last character executed by using the number of characters
1152 iPtr->termOffset = numSrcBytes;
1153 iPtr->flags &= ~ERR_ALREADY_LOGGED;
1159 *----------------------------------------------------------------------
1161 * TclExecuteByteCode --
1163 * This procedure executes the instructions of a ByteCode structure.
1164 * It returns when a "done" instruction is executed or an error occurs.
1167 * The return value is one of the return codes defined in tcl.h
1168 * (such as TCL_OK), and interp->objResultPtr refers to a Tcl object
1169 * that either contains the result of executing the code or an
1173 * Almost certainly, depending on the ByteCode's instructions.
1175 *----------------------------------------------------------------------
1179 TclExecuteByteCode(interp, codePtr)
1180 Tcl_Interp *interp; /* Token for command interpreter. */
1181 ByteCode *codePtr; /* The bytecode sequence to interpret. */
1183 Interp *iPtr = (Interp *) interp;
1184 ExecEnv *eePtr = iPtr->execEnvPtr;
1185 /* Points to the execution environment. */
1186 register Tcl_Obj **stackPtr = eePtr->stackPtr;
1187 /* Cached evaluation stack base pointer. */
1188 register int stackTop = eePtr->stackTop;
1189 /* Cached top index of evaluation stack. */
1190 register unsigned char *pc = codePtr->codeStart;
1191 /* The current program counter. */
1192 int opnd; /* Current instruction's operand byte(s). */
1193 int pcAdjustment; /* Hold pc adjustment after instruction. */
1194 int initStackTop = stackTop;/* Stack top at start of execution. */
1195 ExceptionRange *rangePtr; /* Points to closest loop or catch exception
1196 * range enclosing the pc. Used by various
1197 * instructions and processCatch to
1198 * process break, continue, and errors. */
1199 int result = TCL_OK; /* Return code returned after execution. */
1201 Tcl_Obj *valuePtr, *value2Ptr, *objPtr;
1204 long i = 0; /* Init. avoids compiler warning. */
1206 register int cleanup;
1207 Tcl_Obj *objResultPtr;
1208 char *part1, *part2;
1209 Var *varPtr, *arrayPtr;
1210 CallFrame *varFramePtr = iPtr->varFramePtr;
1213 /* TIP #280 : Structures for tracking lines */
1217 #ifdef TCL_COMPILE_DEBUG
1218 int traceInstructions = (tclTraceExec == 3);
1219 char cmdNameBuf[21];
1223 * This procedure uses a stack to hold information about catch commands.
1224 * This information is the current operand stack top when starting to
1225 * execute the code for each catch command. It starts out with stack-
1226 * allocated space but uses dynamically-allocated storage if needed.
1229 #define STATIC_CATCH_STACK_SIZE 4
1230 int (catchStackStorage[STATIC_CATCH_STACK_SIZE]);
1231 int *catchStackPtr = catchStackStorage;
1235 /* TIP #280 : Initialize the frame. Do not push it yet. */
1237 bcFrame.type = ((codePtr->flags & TCL_BYTECODE_PRECOMPILED)
1238 ? TCL_LOCATION_PREBC
1240 bcFrame.level = (iPtr->cmdFramePtr == NULL ?
1242 iPtr->cmdFramePtr->level + 1);
1243 bcFrame.framePtr = iPtr->framePtr;
1244 bcFrame.nextPtr = iPtr->cmdFramePtr;
1246 bcFrame.line = NULL;
1248 bcFrame.data.tebc.codePtr = codePtr;
1249 bcFrame.data.tebc.pc = NULL;
1250 bcFrame.cmd.str.cmd = NULL;
1251 bcFrame.cmd.str.len = 0;
1254 #ifdef TCL_COMPILE_DEBUG
1255 if (tclTraceExec >= 2) {
1256 PrintByteCodeInfo(codePtr);
1257 fprintf(stdout, " Starting stack top=%d\n", eePtr->stackTop);
1260 opnd = 0; /* Init. avoids compiler warning. */
1263 #ifdef TCL_COMPILE_STATS
1264 iPtr->stats.numExecutions++;
1268 * Make sure the catch stack is large enough to hold the maximum number
1269 * of catch commands that could ever be executing at the same time. This
1270 * will be no more than the exception range array's depth.
1273 if (codePtr->maxExceptDepth > STATIC_CATCH_STACK_SIZE) {
1274 catchStackPtr = (int *)
1275 ckalloc(codePtr->maxExceptDepth * sizeof(int));
1279 * Make sure the stack has enough room to execute this ByteCode.
1282 while ((stackTop + codePtr->maxStackDepth) > eePtr->stackEnd) {
1283 GrowEvaluationStack(eePtr);
1284 stackPtr = eePtr->stackPtr;
1288 * Loop executing instructions until a "done" instruction, a
1289 * TCL_RETURN, or some error.
1296 * Targets for standard instruction endings; unrolled
1297 * for speed in the most frequent cases (instructions that
1298 * consume up to two stack elements).
1300 * This used to be a "for(;;)" loop, with each instruction doing
1304 cleanupV_pushObjResultPtr:
1307 stackPtr[++stackTop] = (objResultPtr);
1312 valuePtr = POP_OBJECT();
1313 TclDecrRefCount(valuePtr);
1316 cleanup2_pushObjResultPtr:
1317 valuePtr = POP_OBJECT();
1318 TclDecrRefCount(valuePtr);
1320 cleanup1_pushObjResultPtr:
1321 valuePtr = stackPtr[stackTop];
1322 TclDecrRefCount(valuePtr);
1324 stackPtr[stackTop] = objResultPtr;
1332 valuePtr = POP_OBJECT();
1333 TclDecrRefCount(valuePtr);
1337 valuePtr = POP_OBJECT();
1338 TclDecrRefCount(valuePtr);
1341 valuePtr = POP_OBJECT();
1342 TclDecrRefCount(valuePtr);
1345 * We really want to do nothing now, but this is needed
1346 * for some compilers (SunPro CC)
1353 #ifdef TCL_COMPILE_DEBUG
1354 ValidatePcAndStackTop(codePtr, pc, stackTop, initStackTop);
1355 if (traceInstructions) {
1356 fprintf(stdout, "%2d: %2d ", iPtr->numLevels, stackTop);
1357 TclPrintInstruction(codePtr, pc);
1360 #endif /* TCL_COMPILE_DEBUG */
1362 #ifdef TCL_COMPILE_STATS
1363 iPtr->stats.instructionCount[*pc]++;
1367 if (stackTop <= initStackTop) {
1369 goto abnormalReturn;
1373 * Set the interpreter's object result to point to the
1374 * topmost object from the stack, and check for a possible
1375 * [catch]. The stackTop's level and refCount will be handled
1376 * by "processCatch" or "abnormalReturn".
1379 valuePtr = stackPtr[stackTop];
1380 Tcl_SetObjResult(interp, valuePtr);
1381 #ifdef TCL_COMPILE_DEBUG
1382 TRACE_WITH_OBJ(("=> return code=%d, result=", result),
1383 iPtr->objResultPtr);
1384 if (traceInstructions) {
1385 fprintf(stdout, "\n");
1391 objResultPtr = codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)];
1392 TRACE_WITH_OBJ(("%u => ", TclGetInt1AtPtr(pc+1)), objResultPtr);
1393 NEXT_INST_F(2, 0, 1);
1396 objResultPtr = codePtr->objArrayPtr[TclGetUInt4AtPtr(pc+1)];
1397 TRACE_WITH_OBJ(("%u => ", TclGetUInt4AtPtr(pc+1)), objResultPtr);
1398 NEXT_INST_F(5, 0, 1);
1401 TRACE_WITH_OBJ(("=> discarding "), stackPtr[stackTop]);
1402 valuePtr = POP_OBJECT();
1403 TclDecrRefCount(valuePtr);
1404 NEXT_INST_F(1, 0, 0);
1407 objResultPtr = stackPtr[stackTop];
1408 TRACE_WITH_OBJ(("=> "), objResultPtr);
1409 NEXT_INST_F(1, 0, 1);
1412 opnd = TclGetUInt4AtPtr( pc+1 );
1413 objResultPtr = stackPtr[ stackTop - opnd ];
1414 TRACE_WITH_OBJ(("=> "), objResultPtr);
1415 NEXT_INST_F(5, 0, 1);
1418 opnd = TclGetUInt1AtPtr(pc+1);
1423 * Peephole optimisation for appending an empty string.
1424 * This enables replacing 'K $x [set x{}]' by '$x[set x{}]'
1425 * for fastest execution. Avoid doing the optimisation for wide
1426 * ints - a case where equal strings may refer to different values
1427 * (see [Bug 1251791]).
1430 if ((opnd == 2) && (stackPtr[stackTop-1]->typePtr != &tclWideIntType)) {
1431 Tcl_GetStringFromObj(stackPtr[stackTop], &length);
1433 /* Just drop the top item from the stack */
1434 NEXT_INST_F(2, 1, 0);
1439 * Concatenate strings (with no separators) from the top
1440 * opnd items on the stack starting with the deepest item.
1441 * First, determine how many characters are needed.
1444 for (i = (stackTop - (opnd-1)); i <= stackTop; i++) {
1445 bytes = Tcl_GetStringFromObj(stackPtr[i], &length);
1446 if (bytes != NULL) {
1452 * Initialize the new append string object by appending the
1453 * strings of the opnd stack objects. Also pop the objects.
1456 TclNewObj(objResultPtr);
1458 char *p = (char *) ckalloc((unsigned) (totalLen + 1));
1459 objResultPtr->bytes = p;
1460 objResultPtr->length = totalLen;
1461 for (i = (stackTop - (opnd-1)); i <= stackTop; i++) {
1462 valuePtr = stackPtr[i];
1463 bytes = Tcl_GetStringFromObj(valuePtr, &length);
1464 if (bytes != NULL) {
1465 memcpy((VOID *) p, (VOID *) bytes,
1473 TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
1474 NEXT_INST_V(2, opnd, 1);
1477 case INST_INVOKE_STK4:
1478 opnd = TclGetUInt4AtPtr(pc+1);
1482 case INST_INVOKE_STK1:
1483 opnd = TclGetUInt1AtPtr(pc+1);
1488 int objc = opnd; /* The number of arguments. */
1489 Tcl_Obj **objv; /* The array of argument objects. */
1492 * We keep the stack reference count as a (char *), as that
1493 * works nicely as a portable pointer-sized counter.
1496 char **preservedStackRefCountPtr;
1499 * Reference to memory block containing
1500 * objv array (must be kept live throughout
1501 * trace and command invokations.)
1504 objv = &(stackPtr[stackTop - (objc-1)]);
1506 #ifdef TCL_COMPILE_DEBUG
1507 if (tclTraceExec >= 2) {
1508 if (traceInstructions) {
1509 strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
1510 TRACE(("%u => call ", objc));
1512 fprintf(stdout, "%d: (%u) invoking ",
1514 (unsigned int)(pc - codePtr->codeStart));
1516 for (i = 0; i < objc; i++) {
1517 TclPrintObject(stdout, objv[i], 15);
1518 fprintf(stdout, " ");
1520 fprintf(stdout, "\n");
1523 #endif /*TCL_COMPILE_DEBUG*/
1526 * If trace procedures will be called, we need a
1527 * command string to pass to TclEvalObjvInternal; note
1528 * that a copy of the string will be made there to
1529 * include the ending \0.
1534 if (iPtr->tracePtr != NULL) {
1535 Trace *tracePtr, *nextTracePtr;
1537 for (tracePtr = iPtr->tracePtr; tracePtr != NULL;
1538 tracePtr = nextTracePtr) {
1539 nextTracePtr = tracePtr->nextPtr;
1540 if (tracePtr->level == 0 ||
1541 iPtr->numLevels <= tracePtr->level) {
1543 * Traces will be called: get command string
1546 bytes = GetSrcInfoForPc(pc, codePtr, &length);
1552 cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
1553 if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) {
1554 bytes = GetSrcInfoForPc(pc, codePtr, &length);
1559 * A reference to part of the stack vector itself
1560 * escapes our control: increase its refCount
1561 * to stop it from being deallocated by a recursive
1562 * call to ourselves. The extra variable is needed
1563 * because all others are liable to change due to the
1567 preservedStackRefCountPtr = (char **) (stackPtr-1);
1568 ++*preservedStackRefCountPtr;
1571 * Finally, let TclEvalObjvInternal handle the command.
1573 * TIP #280 : Record the last piece of info needed by
1574 * 'TclGetSrcInfoForPc', and push the frame.
1578 bcFrame.data.tebc.pc = pc;
1579 iPtr->cmdFramePtr = &bcFrame;
1581 DECACHE_STACK_INFO();
1582 Tcl_ResetResult(interp);
1583 result = TclEvalObjvInternal(interp, objc, objv, bytes, length, 0);
1586 iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
1590 * If the old stack is going to be released, it is
1591 * safe to do so now, since no references to objv are
1592 * going to be used from now on.
1595 --*preservedStackRefCountPtr;
1596 if (*preservedStackRefCountPtr == (char *) 0) {
1597 ckfree((VOID *) preservedStackRefCountPtr);
1600 if (result == TCL_OK) {
1602 * Push the call's object result and continue execution
1603 * with the next instruction.
1606 TRACE_WITH_OBJ(("%u => ... after \"%.20s\": TCL_OK, result=",
1607 objc, cmdNameBuf), Tcl_GetObjResult(interp));
1609 objResultPtr = Tcl_GetObjResult(interp);
1612 * Reset the interp's result to avoid possible duplications
1613 * of large objects [Bug 781585]. We do not call
1614 * Tcl_ResetResult() to avoid any side effects caused by
1615 * the resetting of errorInfo and errorCode [Bug 804681],
1616 * which are not needed here. We chose instead to manipulate
1617 * the interp's object result directly.
1619 * Note that the result object is now in objResultPtr, it
1620 * keeps the refCount it had in its role of iPtr->objResultPtr.
1623 Tcl_Obj *newObjResultPtr;
1624 TclNewObj(newObjResultPtr);
1625 Tcl_IncrRefCount(newObjResultPtr);
1626 iPtr->objResultPtr = newObjResultPtr;
1629 NEXT_INST_V(pcAdjustment, opnd, -1);
1632 goto processExceptionReturn;
1638 * Note to maintainers: it is important that INST_EVAL_STK
1639 * pop its argument from the stack before jumping to
1640 * checkForCatch! DO NOT OPTIMISE!
1643 objPtr = stackPtr[stackTop];
1644 DECACHE_STACK_INFO();
1646 result = TclCompEvalObj(interp, objPtr);
1648 /* TIP #280: The invoking context is left NULL for a dynamically
1649 * constructed command. We cannot match its lines to the outer
1653 result = TclCompEvalObj(interp, objPtr, NULL,0);
1656 if (result == TCL_OK) {
1658 * Normal return; push the eval's object result.
1661 objResultPtr = Tcl_GetObjResult(interp);
1662 TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)),
1663 Tcl_GetObjResult(interp));
1666 * Reset the interp's result to avoid possible duplications
1667 * of large objects [Bug 781585]. We do not call
1668 * Tcl_ResetResult() to avoid any side effects caused by
1669 * the resetting of errorInfo and errorCode [Bug 804681],
1670 * which are not needed here. We chose instead to manipulate
1671 * the interp's object result directly.
1673 * Note that the result object is now in objResultPtr, it
1674 * keeps the refCount it had in its role of iPtr->objResultPtr.
1677 Tcl_Obj *newObjResultPtr;
1678 TclNewObj(newObjResultPtr);
1679 Tcl_IncrRefCount(newObjResultPtr);
1680 iPtr->objResultPtr = newObjResultPtr;
1683 NEXT_INST_F(1, 1, -1);
1686 goto processExceptionReturn;
1690 objPtr = stackPtr[stackTop];
1691 DECACHE_STACK_INFO();
1692 Tcl_ResetResult(interp);
1693 result = Tcl_ExprObj(interp, objPtr, &valuePtr);
1695 if (result != TCL_OK) {
1696 TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ",
1697 O2S(objPtr)), Tcl_GetObjResult(interp));
1700 objResultPtr = valuePtr;
1701 TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)), valuePtr);
1702 NEXT_INST_F(1, 1, -1); /* already has right refct */
1705 * ---------------------------------------------------------
1706 * Start of INST_LOAD instructions.
1708 * WARNING: more 'goto' here than your doctor recommended!
1709 * The different instructions set the value of some variables
1710 * and then jump to somme common execution code.
1713 case INST_LOAD_SCALAR1:
1714 opnd = TclGetUInt1AtPtr(pc+1);
1715 varPtr = &(varFramePtr->compiledLocals[opnd]);
1716 part1 = varPtr->name;
1717 while (TclIsVarLink(varPtr)) {
1718 varPtr = varPtr->value.linkPtr;
1720 TRACE(("%u => ", opnd));
1721 if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)
1722 && (varPtr->tracePtr == NULL)) {
1724 * No errors, no traces: just get the value.
1726 objResultPtr = varPtr->value.objPtr;
1727 TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
1728 NEXT_INST_F(2, 0, 1);
1734 goto doCallPtrGetVar;
1736 case INST_LOAD_SCALAR4:
1737 opnd = TclGetUInt4AtPtr(pc+1);
1738 varPtr = &(varFramePtr->compiledLocals[opnd]);
1739 part1 = varPtr->name;
1740 while (TclIsVarLink(varPtr)) {
1741 varPtr = varPtr->value.linkPtr;
1743 TRACE(("%u => ", opnd));
1744 if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)
1745 && (varPtr->tracePtr == NULL)) {
1747 * No errors, no traces: just get the value.
1749 objResultPtr = varPtr->value.objPtr;
1750 TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
1751 NEXT_INST_F(5, 0, 1);
1757 goto doCallPtrGetVar;
1759 case INST_LOAD_ARRAY_STK:
1761 part2 = Tcl_GetString(stackPtr[stackTop]); /* element name */
1762 objPtr = stackPtr[stackTop-1]; /* array name */
1763 TRACE(("\"%.30s(%.30s)\" => ", O2S(objPtr), part2));
1767 case INST_LOAD_SCALAR_STK:
1770 objPtr = stackPtr[stackTop]; /* variable name */
1771 TRACE(("\"%.30s\" => ", O2S(objPtr)));
1774 part1 = TclGetString(objPtr);
1775 varPtr = TclObjLookupVar(interp, objPtr, part2,
1776 TCL_LEAVE_ERR_MSG, "read",
1778 /*createPart2*/ 1, &arrayPtr);
1779 if (varPtr == NULL) {
1780 TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
1784 if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)
1785 && (varPtr->tracePtr == NULL)
1786 && ((arrayPtr == NULL)
1787 || (arrayPtr->tracePtr == NULL))) {
1789 * No errors, no traces: just get the value.
1791 objResultPtr = varPtr->value.objPtr;
1792 TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
1793 NEXT_INST_V(1, cleanup, 1);
1796 goto doCallPtrGetVar;
1798 case INST_LOAD_ARRAY4:
1799 opnd = TclGetUInt4AtPtr(pc+1);
1803 case INST_LOAD_ARRAY1:
1804 opnd = TclGetUInt1AtPtr(pc+1);
1808 part2 = TclGetString(stackPtr[stackTop]);
1809 arrayPtr = &(varFramePtr->compiledLocals[opnd]);
1810 part1 = arrayPtr->name;
1811 while (TclIsVarLink(arrayPtr)) {
1812 arrayPtr = arrayPtr->value.linkPtr;
1814 TRACE(("%u \"%.30s\" => ", opnd, part2));
1815 varPtr = TclLookupArrayElement(interp, part1, part2,
1816 TCL_LEAVE_ERR_MSG, "read", 0, 1, arrayPtr);
1817 if (varPtr == NULL) {
1818 TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
1822 if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)
1823 && (varPtr->tracePtr == NULL)
1824 && ((arrayPtr == NULL)
1825 || (arrayPtr->tracePtr == NULL))) {
1827 * No errors, no traces: just get the value.
1829 objResultPtr = varPtr->value.objPtr;
1830 TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
1831 NEXT_INST_F(pcAdjustment, 1, 1);
1834 goto doCallPtrGetVar;
1838 * There are either errors or the variable is traced:
1839 * call TclPtrGetVar to process fully.
1842 DECACHE_STACK_INFO();
1843 objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1,
1844 part2, TCL_LEAVE_ERR_MSG);
1846 if (objResultPtr == NULL) {
1847 TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
1851 TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
1852 NEXT_INST_V(pcAdjustment, cleanup, 1);
1855 * End of INST_LOAD instructions.
1856 * ---------------------------------------------------------
1860 * ---------------------------------------------------------
1861 * Start of INST_STORE and related instructions.
1863 * WARNING: more 'goto' here than your doctor recommended!
1864 * The different instructions set the value of some variables
1865 * and then jump to somme common execution code.
1868 case INST_LAPPEND_STK:
1869 valuePtr = stackPtr[stackTop]; /* value to append */
1871 storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
1872 | TCL_LIST_ELEMENT | TCL_TRACE_READS);
1875 case INST_LAPPEND_ARRAY_STK:
1876 valuePtr = stackPtr[stackTop]; /* value to append */
1877 part2 = TclGetString(stackPtr[stackTop - 1]);
1878 storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
1879 | TCL_LIST_ELEMENT | TCL_TRACE_READS);
1882 case INST_APPEND_STK:
1883 valuePtr = stackPtr[stackTop]; /* value to append */
1885 storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
1888 case INST_APPEND_ARRAY_STK:
1889 valuePtr = stackPtr[stackTop]; /* value to append */
1890 part2 = TclGetString(stackPtr[stackTop - 1]);
1891 storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
1894 case INST_STORE_ARRAY_STK:
1895 valuePtr = stackPtr[stackTop];
1896 part2 = TclGetString(stackPtr[stackTop - 1]);
1897 storeFlags = TCL_LEAVE_ERR_MSG;
1900 case INST_STORE_STK:
1901 case INST_STORE_SCALAR_STK:
1902 valuePtr = stackPtr[stackTop];
1904 storeFlags = TCL_LEAVE_ERR_MSG;
1907 objPtr = stackPtr[stackTop - 1 - (part2 != NULL)]; /* variable name */
1908 part1 = TclGetString(objPtr);
1909 #ifdef TCL_COMPILE_DEBUG
1910 if (part2 == NULL) {
1911 TRACE(("\"%.30s\" <- \"%.30s\" =>",
1912 part1, O2S(valuePtr)));
1914 TRACE(("\"%.30s(%.30s)\" <- \"%.30s\" => ",
1915 part1, part2, O2S(valuePtr)));
1918 varPtr = TclObjLookupVar(interp, objPtr, part2,
1919 TCL_LEAVE_ERR_MSG, "set",
1921 /*createPart2*/ 1, &arrayPtr);
1922 if (varPtr == NULL) {
1923 TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
1927 cleanup = ((part2 == NULL)? 2 : 3);
1929 goto doCallPtrSetVar;
1931 case INST_LAPPEND_ARRAY4:
1932 opnd = TclGetUInt4AtPtr(pc+1);
1934 storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
1935 | TCL_LIST_ELEMENT | TCL_TRACE_READS);
1938 case INST_LAPPEND_ARRAY1:
1939 opnd = TclGetUInt1AtPtr(pc+1);
1941 storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
1942 | TCL_LIST_ELEMENT | TCL_TRACE_READS);
1945 case INST_APPEND_ARRAY4:
1946 opnd = TclGetUInt4AtPtr(pc+1);
1948 storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
1951 case INST_APPEND_ARRAY1:
1952 opnd = TclGetUInt1AtPtr(pc+1);
1954 storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
1957 case INST_STORE_ARRAY4:
1958 opnd = TclGetUInt4AtPtr(pc+1);
1960 storeFlags = TCL_LEAVE_ERR_MSG;
1963 case INST_STORE_ARRAY1:
1964 opnd = TclGetUInt1AtPtr(pc+1);
1966 storeFlags = TCL_LEAVE_ERR_MSG;
1969 valuePtr = stackPtr[stackTop];
1970 part2 = TclGetString(stackPtr[stackTop - 1]);
1971 arrayPtr = &(varFramePtr->compiledLocals[opnd]);
1972 part1 = arrayPtr->name;
1973 TRACE(("%u \"%.30s\" <- \"%.30s\" => ",
1974 opnd, part2, O2S(valuePtr)));
1975 while (TclIsVarLink(arrayPtr)) {
1976 arrayPtr = arrayPtr->value.linkPtr;
1978 varPtr = TclLookupArrayElement(interp, part1, part2,
1979 TCL_LEAVE_ERR_MSG, "set", 1, 1, arrayPtr);
1980 if (varPtr == NULL) {
1981 TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
1986 goto doCallPtrSetVar;
1988 case INST_LAPPEND_SCALAR4:
1989 opnd = TclGetUInt4AtPtr(pc+1);
1991 storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
1992 | TCL_LIST_ELEMENT | TCL_TRACE_READS);
1995 case INST_LAPPEND_SCALAR1:
1996 opnd = TclGetUInt1AtPtr(pc+1);
1998 storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
1999 | TCL_LIST_ELEMENT | TCL_TRACE_READS);
2002 case INST_APPEND_SCALAR4:
2003 opnd = TclGetUInt4AtPtr(pc+1);
2005 storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
2008 case INST_APPEND_SCALAR1:
2009 opnd = TclGetUInt1AtPtr(pc+1);
2011 storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
2014 case INST_STORE_SCALAR4:
2015 opnd = TclGetUInt4AtPtr(pc+1);
2017 storeFlags = TCL_LEAVE_ERR_MSG;
2020 case INST_STORE_SCALAR1:
2021 opnd = TclGetUInt1AtPtr(pc+1);
2023 storeFlags = TCL_LEAVE_ERR_MSG;
2026 valuePtr = stackPtr[stackTop];
2027 varPtr = &(varFramePtr->compiledLocals[opnd]);
2028 part1 = varPtr->name;
2029 TRACE(("%u <- \"%.30s\" => ", opnd, O2S(valuePtr)));
2030 while (TclIsVarLink(varPtr)) {
2031 varPtr = varPtr->value.linkPtr;
2038 if ((storeFlags == TCL_LEAVE_ERR_MSG)
2039 && !((varPtr->flags & VAR_IN_HASHTABLE)
2040 && (varPtr->hPtr == NULL))
2041 && (varPtr->tracePtr == NULL)
2042 && (TclIsVarScalar(varPtr)
2043 || TclIsVarUndefined(varPtr))
2044 && ((arrayPtr == NULL)
2045 || (arrayPtr->tracePtr == NULL))) {
2047 * No traces, no errors, plain 'set': we can safely inline.
2048 * The value *will* be set to what's requested, so that
2049 * the stack top remains pointing to the same Tcl_Obj.
2051 valuePtr = varPtr->value.objPtr;
2052 objResultPtr = stackPtr[stackTop];
2053 if (valuePtr != objResultPtr) {
2054 if (valuePtr != NULL) {
2055 TclDecrRefCount(valuePtr);
2057 TclSetVarScalar(varPtr);
2058 TclClearVarUndefined(varPtr);
2060 varPtr->value.objPtr = objResultPtr;
2061 Tcl_IncrRefCount(objResultPtr);
2063 #ifndef TCL_COMPILE_DEBUG
2064 if (*(pc+pcAdjustment) == INST_POP) {
2065 NEXT_INST_V((pcAdjustment+1), cleanup, 0);
2068 TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
2070 NEXT_INST_V(pcAdjustment, cleanup, 1);
2072 DECACHE_STACK_INFO();
2073 objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr,
2074 part1, part2, valuePtr, storeFlags);
2076 if (objResultPtr == NULL) {
2077 TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
2082 #ifndef TCL_COMPILE_DEBUG
2083 if (*(pc+pcAdjustment) == INST_POP) {
2084 NEXT_INST_V((pcAdjustment+1), cleanup, 0);
2087 TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
2088 NEXT_INST_V(pcAdjustment, cleanup, 1);
2092 * End of INST_STORE and related instructions.
2093 * ---------------------------------------------------------
2097 * ---------------------------------------------------------
2098 * Start of INST_INCR instructions.
2100 * WARNING: more 'goto' here than your doctor recommended!
2101 * The different instructions set the value of some variables
2102 * and then jump to somme common execution code.
2105 case INST_INCR_SCALAR1:
2106 case INST_INCR_ARRAY1:
2107 case INST_INCR_ARRAY_STK:
2108 case INST_INCR_SCALAR_STK:
2110 opnd = TclGetUInt1AtPtr(pc+1);
2111 valuePtr = stackPtr[stackTop];
2112 if (valuePtr->typePtr == &tclIntType) {
2113 i = valuePtr->internalRep.longValue;
2114 } else if (valuePtr->typePtr == &tclWideIntType) {
2115 TclGetLongFromWide(i,valuePtr);
2117 REQUIRE_WIDE_OR_INT(result, valuePtr, i, w);
2118 if (result != TCL_OK) {
2119 TRACE_WITH_OBJ(("%u (by %s) => ERROR converting increment amount to int: ",
2120 opnd, O2S(valuePtr)), Tcl_GetObjResult(interp));
2121 DECACHE_STACK_INFO();
2122 Tcl_AddErrorInfo(interp, "\n (reading increment)");
2126 FORCE_LONG(valuePtr, i, w);
2129 TclDecrRefCount(valuePtr);
2131 case INST_INCR_SCALAR1:
2134 case INST_INCR_ARRAY1:
2142 case INST_INCR_ARRAY_STK_IMM:
2143 case INST_INCR_SCALAR_STK_IMM:
2144 case INST_INCR_STK_IMM:
2145 i = TclGetInt1AtPtr(pc+1);
2149 if ((*pc == INST_INCR_ARRAY_STK_IMM)
2150 || (*pc == INST_INCR_ARRAY_STK)) {
2151 part2 = TclGetString(stackPtr[stackTop]);
2152 objPtr = stackPtr[stackTop - 1];
2153 TRACE(("\"%.30s(%.30s)\" (by %ld) => ",
2154 O2S(objPtr), part2, i));
2157 objPtr = stackPtr[stackTop];
2158 TRACE(("\"%.30s\" (by %ld) => ", O2S(objPtr), i));
2160 part1 = TclGetString(objPtr);
2162 varPtr = TclObjLookupVar(interp, objPtr, part2,
2163 TCL_LEAVE_ERR_MSG, "read", 0, 1, &arrayPtr);
2164 if (varPtr == NULL) {
2165 DECACHE_STACK_INFO();
2166 Tcl_AddObjErrorInfo(interp,
2167 "\n (reading value of variable to increment)", -1);
2169 TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
2173 cleanup = ((part2 == NULL)? 1 : 2);
2176 case INST_INCR_ARRAY1_IMM:
2177 opnd = TclGetUInt1AtPtr(pc+1);
2178 i = TclGetInt1AtPtr(pc+2);
2182 part2 = TclGetString(stackPtr[stackTop]);
2183 arrayPtr = &(varFramePtr->compiledLocals[opnd]);
2184 part1 = arrayPtr->name;
2185 while (TclIsVarLink(arrayPtr)) {
2186 arrayPtr = arrayPtr->value.linkPtr;
2188 TRACE(("%u \"%.30s\" (by %ld) => ",
2190 varPtr = TclLookupArrayElement(interp, part1, part2,
2191 TCL_LEAVE_ERR_MSG, "read", 0, 1, arrayPtr);
2192 if (varPtr == NULL) {
2193 TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
2200 case INST_INCR_SCALAR1_IMM:
2201 opnd = TclGetUInt1AtPtr(pc+1);
2202 i = TclGetInt1AtPtr(pc+2);
2206 varPtr = &(varFramePtr->compiledLocals[opnd]);
2207 part1 = varPtr->name;
2208 while (TclIsVarLink(varPtr)) {
2209 varPtr = varPtr->value.linkPtr;
2214 TRACE(("%u %ld => ", opnd, i));
2218 objPtr = varPtr->value.objPtr;
2219 if (TclIsVarScalar(varPtr)
2220 && !TclIsVarUndefined(varPtr)
2221 && (varPtr->tracePtr == NULL)
2222 && ((arrayPtr == NULL)
2223 || (arrayPtr->tracePtr == NULL))
2224 && (objPtr->typePtr == &tclIntType)) {
2226 * No errors, no traces, the variable already has an
2227 * integer value: inline processing.
2230 i += objPtr->internalRep.longValue;
2231 if (Tcl_IsShared(objPtr)) {
2232 objResultPtr = Tcl_NewLongObj(i);
2233 TclDecrRefCount(objPtr);
2234 Tcl_IncrRefCount(objResultPtr);
2235 varPtr->value.objPtr = objResultPtr;
2237 Tcl_SetLongObj(objPtr, i);
2238 objResultPtr = objPtr;
2240 TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
2242 DECACHE_STACK_INFO();
2243 objResultPtr = TclPtrIncrVar(interp, varPtr, arrayPtr, part1,
2244 part2, i, TCL_LEAVE_ERR_MSG);
2246 if (objResultPtr == NULL) {
2247 TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
2252 TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
2253 #ifndef TCL_COMPILE_DEBUG
2254 if (*(pc+pcAdjustment) == INST_POP) {
2255 NEXT_INST_V((pcAdjustment+1), cleanup, 0);
2258 NEXT_INST_V(pcAdjustment, cleanup, 1);
2261 * End of INST_INCR instructions.
2262 * ---------------------------------------------------------
2267 opnd = TclGetInt1AtPtr(pc+1);
2268 TRACE(("%d => new pc %u\n", opnd,
2269 (unsigned int)(pc + opnd - codePtr->codeStart)));
2270 NEXT_INST_F(opnd, 0, 0);
2273 opnd = TclGetInt4AtPtr(pc+1);
2274 TRACE(("%d => new pc %u\n", opnd,
2275 (unsigned int)(pc + opnd - codePtr->codeStart)));
2276 NEXT_INST_F(opnd, 0, 0);
2278 case INST_JUMP_FALSE4:
2279 opnd = 5; /* TRUE */
2280 pcAdjustment = TclGetInt4AtPtr(pc+1); /* FALSE */
2283 case INST_JUMP_TRUE4:
2284 opnd = TclGetInt4AtPtr(pc+1); /* TRUE */
2285 pcAdjustment = 5; /* FALSE */
2288 case INST_JUMP_FALSE1:
2289 opnd = 2; /* TRUE */
2290 pcAdjustment = TclGetInt1AtPtr(pc+1); /* FALSE */
2293 case INST_JUMP_TRUE1:
2294 opnd = TclGetInt1AtPtr(pc+1); /* TRUE */
2295 pcAdjustment = 2; /* FALSE */
2301 valuePtr = stackPtr[stackTop];
2302 if (valuePtr->typePtr == &tclIntType) {
2303 b = (valuePtr->internalRep.longValue != 0);
2304 } else if (valuePtr->typePtr == &tclDoubleType) {
2305 b = (valuePtr->internalRep.doubleValue != 0.0);
2306 } else if (valuePtr->typePtr == &tclWideIntType) {
2307 TclGetWide(w,valuePtr);
2310 result = Tcl_GetBooleanFromObj(interp, valuePtr, &b);
2311 if (result != TCL_OK) {
2312 TRACE_WITH_OBJ(("%d => ERROR: ", opnd), Tcl_GetObjResult(interp));
2316 #ifndef TCL_COMPILE_DEBUG
2317 NEXT_INST_F((b? opnd : pcAdjustment), 1, 0);
2320 if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE1)) {
2321 TRACE(("%d => %.20s true, new pc %u\n", opnd, O2S(valuePtr),
2322 (unsigned int)(pc+opnd - codePtr->codeStart)));
2324 TRACE(("%d => %.20s true\n", pcAdjustment, O2S(valuePtr)));
2326 NEXT_INST_F(opnd, 1, 0);
2328 if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE1)) {
2329 TRACE(("%d => %.20s false\n", opnd, O2S(valuePtr)));
2331 opnd = pcAdjustment;
2332 TRACE(("%d => %.20s false, new pc %u\n", opnd, O2S(valuePtr),
2333 (unsigned int)(pc + opnd - codePtr->codeStart)));
2335 NEXT_INST_F(pcAdjustment, 1, 0);
2344 * Operands must be boolean or numeric. No int->double
2345 * conversions are performed.
2351 Tcl_ObjType *t1Ptr, *t2Ptr;
2353 value2Ptr = stackPtr[stackTop];
2354 valuePtr = stackPtr[stackTop - 1];;
2355 t1Ptr = valuePtr->typePtr;
2356 t2Ptr = value2Ptr->typePtr;
2358 if ((t1Ptr == &tclIntType) || (t1Ptr == &tclBooleanType)) {
2359 i1 = (valuePtr->internalRep.longValue != 0);
2360 } else if (t1Ptr == &tclWideIntType) {
2361 TclGetWide(w,valuePtr);
2363 } else if (t1Ptr == &tclDoubleType) {
2364 i1 = (valuePtr->internalRep.doubleValue != 0.0);
2366 s = Tcl_GetStringFromObj(valuePtr, &length);
2367 if (TclLooksLikeInt(s, length)) {
2368 GET_WIDE_OR_INT(result, valuePtr, i, w);
2369 if (valuePtr->typePtr == &tclIntType) {
2375 result = Tcl_GetBooleanFromObj((Tcl_Interp *) NULL,
2379 if (result != TCL_OK) {
2380 TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr),
2381 (t1Ptr? t1Ptr->name : "null")));
2382 DECACHE_STACK_INFO();
2383 IllegalExprOperandType(interp, pc, valuePtr);
2389 if ((t2Ptr == &tclIntType) || (t2Ptr == &tclBooleanType)) {
2390 i2 = (value2Ptr->internalRep.longValue != 0);
2391 } else if (t2Ptr == &tclWideIntType) {
2392 TclGetWide(w,value2Ptr);
2394 } else if (t2Ptr == &tclDoubleType) {
2395 i2 = (value2Ptr->internalRep.doubleValue != 0.0);
2397 s = Tcl_GetStringFromObj(value2Ptr, &length);
2398 if (TclLooksLikeInt(s, length)) {
2399 GET_WIDE_OR_INT(result, value2Ptr, i, w);
2400 if (value2Ptr->typePtr == &tclIntType) {
2406 result = Tcl_GetBooleanFromObj((Tcl_Interp *) NULL, value2Ptr, &i2);
2408 if (result != TCL_OK) {
2409 TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(value2Ptr),
2410 (t2Ptr? t2Ptr->name : "null")));
2411 DECACHE_STACK_INFO();
2412 IllegalExprOperandType(interp, pc, value2Ptr);
2419 * Reuse the valuePtr object already on stack if possible.
2422 if (*pc == INST_LOR) {
2423 iResult = (i1 || i2);
2425 iResult = (i1 && i2);
2427 if (Tcl_IsShared(valuePtr)) {
2428 objResultPtr = Tcl_NewLongObj(iResult);
2429 TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
2430 NEXT_INST_F(1, 2, 1);
2431 } else { /* reuse the valuePtr object */
2432 TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
2433 Tcl_SetLongObj(valuePtr, iResult);
2434 NEXT_INST_F(1, 1, 0);
2439 * ---------------------------------------------------------
2440 * Start of INST_LIST and related instructions.
2445 * Pop the opnd (objc) top stack elements into a new list obj
2446 * and then decrement their ref counts.
2449 opnd = TclGetUInt4AtPtr(pc+1);
2450 objResultPtr = Tcl_NewListObj(opnd, &(stackPtr[stackTop - (opnd-1)]));
2451 TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
2452 NEXT_INST_V(5, opnd, 1);
2454 case INST_LIST_LENGTH:
2455 valuePtr = stackPtr[stackTop];
2457 result = Tcl_ListObjLength(interp, valuePtr, &length);
2458 if (result != TCL_OK) {
2459 TRACE_WITH_OBJ(("%.30s => ERROR: ", O2S(valuePtr)),
2460 Tcl_GetObjResult(interp));
2463 objResultPtr = Tcl_NewIntObj(length);
2464 TRACE(("%.20s => %d\n", O2S(valuePtr), length));
2465 NEXT_INST_F(1, 1, 1);
2467 case INST_LIST_INDEX:
2468 /*** lindex with objc == 3 ***/
2471 * Pop the two operands
2473 value2Ptr = stackPtr[stackTop];
2474 valuePtr = stackPtr[stackTop- 1];
2477 * Extract the desired list element
2479 objResultPtr = TclLindexList(interp, valuePtr, value2Ptr);
2480 if (objResultPtr == NULL) {
2481 TRACE_WITH_OBJ(("%.30s %.30s => ERROR: ", O2S(valuePtr), O2S(value2Ptr)),
2482 Tcl_GetObjResult(interp));
2488 * Stash the list element on the stack
2490 TRACE(("%.20s %.20s => %s\n",
2491 O2S(valuePtr), O2S(value2Ptr), O2S(objResultPtr)));
2492 NEXT_INST_F(1, 2, -1); /* already has the correct refCount */
2494 case INST_LIST_INDEX_MULTI:
2497 * 'lindex' with multiple index args:
2499 * Determine the count of index args.
2504 opnd = TclGetUInt4AtPtr(pc+1);
2508 * Do the 'lindex' operation.
2510 objResultPtr = TclLindexFlat(interp, stackPtr[stackTop - numIdx],
2511 numIdx, stackPtr + stackTop - numIdx + 1);
2516 if (objResultPtr == NULL) {
2517 TRACE_WITH_OBJ(("%d => ERROR: ", opnd), Tcl_GetObjResult(interp));
2525 TRACE(("%d => %s\n", opnd, O2S(objResultPtr)));
2526 NEXT_INST_V(5, opnd, -1);
2529 case INST_LSET_FLAT:
2532 * Lset with 3, 5, or more args. Get the number
2537 opnd = TclGetUInt4AtPtr( pc + 1 );
2541 * Get the old value of variable, and remove the stack ref.
2542 * This is safe because the variable still references the
2543 * object; the ref count will never go zero here.
2545 value2Ptr = POP_OBJECT();
2546 TclDecrRefCount(value2Ptr); /* This one should be done here */
2549 * Get the new element value.
2551 valuePtr = stackPtr[stackTop];
2554 * Compute the new variable value
2556 objResultPtr = TclLsetFlat(interp, value2Ptr, numIdx,
2557 stackPtr + stackTop - numIdx, valuePtr);
2563 if (objResultPtr == NULL) {
2564 TRACE_WITH_OBJ(("%d => ERROR: ", opnd), Tcl_GetObjResult(interp));
2572 TRACE(("%d => %s\n", opnd, O2S(objResultPtr)));
2573 NEXT_INST_V(5, (numIdx+1), -1);
2576 case INST_LSET_LIST:
2578 * 'lset' with 4 args.
2580 * Get the old value of variable, and remove the stack ref.
2581 * This is safe because the variable still references the
2582 * object; the ref count will never go zero here.
2584 objPtr = POP_OBJECT();
2585 TclDecrRefCount(objPtr); /* This one should be done here */
2588 * Get the new element value, and the index list
2590 valuePtr = stackPtr[stackTop];
2591 value2Ptr = stackPtr[stackTop - 1];
2594 * Compute the new variable value
2596 objResultPtr = TclLsetList(interp, objPtr, value2Ptr, valuePtr);
2601 if (objResultPtr == NULL) {
2602 TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ", O2S(value2Ptr)),
2603 Tcl_GetObjResult(interp));
2611 TRACE(("=> %s\n", O2S(objResultPtr)));
2612 NEXT_INST_F(1, 2, -1);
2615 * End of INST_LIST and related instructions.
2616 * ---------------------------------------------------------
2623 * String (in)equality check
2627 value2Ptr = stackPtr[stackTop];
2628 valuePtr = stackPtr[stackTop - 1];
2630 if (valuePtr == value2Ptr) {
2632 * On the off-chance that the objects are the same,
2633 * we don't really have to think hard about equality.
2635 iResult = (*pc == INST_STR_EQ);
2640 s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
2641 s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
2642 if (s1len == s2len) {
2644 * We only need to check (in)equality when
2645 * we have equal length strings.
2647 if (*pc == INST_STR_NEQ) {
2648 iResult = (strcmp(s1, s2) != 0);
2651 iResult = (strcmp(s1, s2) == 0);
2654 iResult = (*pc == INST_STR_NEQ);
2658 TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
2661 * Peep-hole optimisation: if you're about to jump, do jump
2666 #ifndef TCL_COMPILE_DEBUG
2668 case INST_JUMP_FALSE1:
2669 NEXT_INST_F((iResult? 2 : TclGetInt1AtPtr(pc+1)), 2, 0);
2670 case INST_JUMP_TRUE1:
2671 NEXT_INST_F((iResult? TclGetInt1AtPtr(pc+1) : 2), 2, 0);
2672 case INST_JUMP_FALSE4:
2673 NEXT_INST_F((iResult? 5 : TclGetInt4AtPtr(pc+1)), 2, 0);
2674 case INST_JUMP_TRUE4:
2675 NEXT_INST_F((iResult? TclGetInt4AtPtr(pc+1) : 5), 2, 0);
2678 objResultPtr = Tcl_NewIntObj(iResult);
2679 NEXT_INST_F(0, 2, 1);
2687 CONST char *s1, *s2;
2688 int s1len, s2len, iResult;
2690 value2Ptr = stackPtr[stackTop];
2691 valuePtr = stackPtr[stackTop - 1];
2694 * The comparison function should compare up to the
2695 * minimum byte length only.
2697 if (valuePtr == value2Ptr) {
2699 * In the pure equality case, set lengths too for
2700 * the checks below (or we could goto beyond it).
2702 iResult = s1len = s2len = 0;
2703 } else if ((valuePtr->typePtr == &tclByteArrayType)
2704 && (value2Ptr->typePtr == &tclByteArrayType)) {
2705 s1 = (char *) Tcl_GetByteArrayFromObj(valuePtr, &s1len);
2706 s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len);
2707 iResult = memcmp(s1, s2,
2708 (size_t) ((s1len < s2len) ? s1len : s2len));
2709 } else if (((valuePtr->typePtr == &tclStringType)
2710 && (value2Ptr->typePtr == &tclStringType))) {
2712 * Do a unicode-specific comparison if both of the args are of
2713 * String type. If the char length == byte length, we can do a
2714 * memcmp. In benchmark testing this proved the most efficient
2715 * check between the unicode and string comparison operations.
2718 s1len = Tcl_GetCharLength(valuePtr);
2719 s2len = Tcl_GetCharLength(value2Ptr);
2720 if ((s1len == valuePtr->length) && (s2len == value2Ptr->length)) {
2721 iResult = memcmp(valuePtr->bytes, value2Ptr->bytes,
2722 (unsigned) ((s1len < s2len) ? s1len : s2len));
2724 iResult = TclUniCharNcmp(Tcl_GetUnicode(valuePtr),
2725 Tcl_GetUnicode(value2Ptr),
2726 (unsigned) ((s1len < s2len) ? s1len : s2len));
2730 * We can't do a simple memcmp in order to handle the
2731 * special Tcl \xC0\x80 null encoding for utf-8.
2733 s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
2734 s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
2735 iResult = TclpUtfNcmp2(s1, s2,
2736 (size_t) ((s1len < s2len) ? s1len : s2len));
2740 * Make sure only -1,0,1 is returned
2743 iResult = s1len - s2len;
2747 } else if (iResult > 0) {
2751 objResultPtr = Tcl_NewIntObj(iResult);
2752 TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
2753 NEXT_INST_F(1, 2, 1);
2760 valuePtr = stackPtr[stackTop];
2762 if (valuePtr->typePtr == &tclByteArrayType) {
2763 (void) Tcl_GetByteArrayFromObj(valuePtr, &length1);
2765 length1 = Tcl_GetCharLength(valuePtr);
2767 objResultPtr = Tcl_NewIntObj(length1);
2768 TRACE(("%.20s => %d\n", O2S(valuePtr), length1));
2769 NEXT_INST_F(1, 1, 1);
2772 case INST_STR_INDEX:
2778 bytes = NULL; /* lint */
2780 value2Ptr = stackPtr[stackTop];
2781 valuePtr = stackPtr[stackTop - 1];
2784 * If we have a ByteArray object, avoid indexing in the
2785 * Utf string since the byte array contains one byte per
2786 * character. Otherwise, use the Unicode string rep to
2787 * get the index'th char.
2790 if (valuePtr->typePtr == &tclByteArrayType) {
2791 bytes = (char *)Tcl_GetByteArrayFromObj(valuePtr, &length);
2794 * Get Unicode char length to calulate what 'end' means.
2796 length = Tcl_GetCharLength(valuePtr);
2799 result = TclGetIntForIndex(interp, value2Ptr, length - 1, &index);
2800 if (result != TCL_OK) {
2804 if ((index >= 0) && (index < length)) {
2805 if (valuePtr->typePtr == &tclByteArrayType) {
2806 objResultPtr = Tcl_NewByteArrayObj((unsigned char *)
2807 (&bytes[index]), 1);
2808 } else if (valuePtr->bytes && length == valuePtr->length) {
2809 objResultPtr = Tcl_NewStringObj((CONST char *)
2810 (&valuePtr->bytes[index]), 1);
2812 char buf[TCL_UTF_MAX];
2815 ch = Tcl_GetUniChar(valuePtr, index);
2818 * Tcl_NewUnicodeObj((CONST Tcl_UniChar *)&ch, 1)
2819 * but creating the object as a string seems to be
2820 * faster in practical use.
2822 length = Tcl_UniCharToUtf(ch, buf);
2823 objResultPtr = Tcl_NewStringObj(buf, length);
2826 TclNewObj(objResultPtr);
2829 TRACE(("%.20s %.20s => %s\n", O2S(valuePtr), O2S(value2Ptr),
2830 O2S(objResultPtr)));
2831 NEXT_INST_F(1, 2, 1);
2834 case INST_STR_MATCH:
2838 nocase = TclGetInt1AtPtr(pc+1);
2839 valuePtr = stackPtr[stackTop]; /* String */
2840 value2Ptr = stackPtr[stackTop - 1]; /* Pattern */
2843 * Check that at least one of the objects is Unicode before
2847 if ((valuePtr->typePtr == &tclStringType)
2848 || (value2Ptr->typePtr == &tclStringType)) {
2849 Tcl_UniChar *ustring1, *ustring2;
2850 int length1, length2;
2852 ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &length1);
2853 ustring2 = Tcl_GetUnicodeFromObj(value2Ptr, &length2);
2854 match = TclUniCharMatch(ustring1, length1, ustring2, length2,
2857 match = Tcl_StringCaseMatch(TclGetString(valuePtr),
2858 TclGetString(value2Ptr), nocase);
2862 * Reuse value2Ptr object already on stack if possible.
2863 * Adjustment is 2 due to the nocase byte
2866 TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), match));
2867 if (Tcl_IsShared(value2Ptr)) {
2868 objResultPtr = Tcl_NewIntObj(match);
2869 NEXT_INST_F(2, 2, 1);
2870 } else { /* reuse the valuePtr object */
2871 Tcl_SetIntObj(value2Ptr, match);
2872 NEXT_INST_F(2, 1, 0);
2884 * Any type is allowed but the two operands must have the
2885 * same type. We will compute value op value2.
2888 Tcl_ObjType *t1Ptr, *t2Ptr;
2889 char *s1 = NULL; /* Init. avoids compiler warning. */
2890 char *s2 = NULL; /* Init. avoids compiler warning. */
2891 long i2 = 0; /* Init. avoids compiler warning. */
2892 double d1 = 0.0; /* Init. avoids compiler warning. */
2893 double d2 = 0.0; /* Init. avoids compiler warning. */
2894 long iResult = 0; /* Init. avoids compiler warning. */
2896 value2Ptr = stackPtr[stackTop];
2897 valuePtr = stackPtr[stackTop - 1];
2900 * Be careful in the equal-object case; 'NaN' isn't supposed
2901 * to be equal to even itself. [Bug 761471]
2904 t1Ptr = valuePtr->typePtr;
2905 if (valuePtr == value2Ptr) {
2907 * If we are numeric already, we can proceed to the main
2908 * equality check right now. Otherwise, we need to try to
2909 * coerce to a numeric type so we can see if we've got a
2910 * NaN but haven't parsed it as numeric.
2912 if (!IS_NUMERIC_TYPE(t1Ptr)) {
2913 if (t1Ptr == &tclListType) {
2916 * Only a list of length 1 can be NaN or such
2919 (void) Tcl_ListObjLength(NULL, valuePtr, &length);
2921 goto mustConvertForNaNCheck;
2925 * Too bad, we'll have to compute the string and
2926 * try the conversion
2929 mustConvertForNaNCheck:
2930 s1 = Tcl_GetStringFromObj(valuePtr, &length);
2931 if (TclLooksLikeInt(s1, length)) {
2932 GET_WIDE_OR_INT(iResult, valuePtr, i, w);
2934 (void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
2937 t1Ptr = valuePtr->typePtr;
2945 iResult = !((t1Ptr == &tclDoubleType)
2946 && IS_NAN(valuePtr->internalRep.doubleValue));
2953 iResult = ((t1Ptr == &tclDoubleType)
2954 && IS_NAN(valuePtr->internalRep.doubleValue));
2960 t2Ptr = value2Ptr->typePtr;
2963 * We only want to coerce numeric validation if neither type
2964 * is NULL. A NULL type means the arg is essentially an empty
2965 * object ("", {} or [list]).
2967 if (!( (!t1Ptr && !valuePtr->bytes)
2968 || (valuePtr->bytes && !valuePtr->length)
2969 || (!t2Ptr && !value2Ptr->bytes)
2970 || (value2Ptr->bytes && !value2Ptr->length))) {
2971 if (!IS_NUMERIC_TYPE(t1Ptr)) {
2972 s1 = Tcl_GetStringFromObj(valuePtr, &length);
2973 if (TclLooksLikeInt(s1, length)) {
2974 GET_WIDE_OR_INT(iResult, valuePtr, i, w);
2976 (void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
2979 t1Ptr = valuePtr->typePtr;
2981 if (!IS_NUMERIC_TYPE(t2Ptr)) {
2982 s2 = Tcl_GetStringFromObj(value2Ptr, &length);
2983 if (TclLooksLikeInt(s2, length)) {
2984 GET_WIDE_OR_INT(iResult, value2Ptr, i2, w);
2986 (void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
2989 t2Ptr = value2Ptr->typePtr;
2992 if (!IS_NUMERIC_TYPE(t1Ptr) || !IS_NUMERIC_TYPE(t2Ptr)) {
2994 * One operand is not numeric. Compare as strings. NOTE:
2995 * strcmp is not correct for \x00 < \x01, but that is
2996 * unlikely to occur here. We could use the TclUtfNCmp2
3000 s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
3001 s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
3004 if (s1len == s2len) {
3005 iResult = (strcmp(s1, s2) == 0);
3011 if (s1len == s2len) {
3012 iResult = (strcmp(s1, s2) != 0);
3018 iResult = (strcmp(s1, s2) < 0);
3021 iResult = (strcmp(s1, s2) > 0);
3024 iResult = (strcmp(s1, s2) <= 0);
3027 iResult = (strcmp(s1, s2) >= 0);
3030 } else if ((t1Ptr == &tclDoubleType)
3031 || (t2Ptr == &tclDoubleType)) {
3033 * Compare as doubles.
3035 if (t1Ptr == &tclDoubleType) {
3036 d1 = valuePtr->internalRep.doubleValue;
3037 GET_DOUBLE_VALUE(d2, value2Ptr, t2Ptr);
3038 } else { /* t1Ptr is integer, t2Ptr is double */
3039 GET_DOUBLE_VALUE(d1, valuePtr, t1Ptr);
3040 d2 = value2Ptr->internalRep.doubleValue;
3062 } else if ((t1Ptr == &tclWideIntType)
3063 || (t2Ptr == &tclWideIntType)) {
3066 * Compare as wide ints (neither are doubles)
3068 if (t1Ptr == &tclIntType) {
3069 w = Tcl_LongAsWide(valuePtr->internalRep.longValue);
3070 TclGetWide(w2,value2Ptr);
3071 } else if (t2Ptr == &tclIntType) {
3072 TclGetWide(w,valuePtr);
3073 w2 = Tcl_LongAsWide(value2Ptr->internalRep.longValue);
3075 TclGetWide(w,valuePtr);
3076 TclGetWide(w2,value2Ptr);
3102 i = valuePtr->internalRep.longValue;
3103 i2 = value2Ptr->internalRep.longValue;
3127 TRACE(("%.20s %.20s => %ld\n", O2S(valuePtr), O2S(value2Ptr), iResult));
3130 * Peep-hole optimisation: if you're about to jump, do jump
3135 #ifndef TCL_COMPILE_DEBUG
3137 case INST_JUMP_FALSE1:
3138 NEXT_INST_F((iResult? 2 : TclGetInt1AtPtr(pc+1)), 2, 0);
3139 case INST_JUMP_TRUE1:
3140 NEXT_INST_F((iResult? TclGetInt1AtPtr(pc+1) : 2), 2, 0);
3141 case INST_JUMP_FALSE4:
3142 NEXT_INST_F((iResult? 5 : TclGetInt4AtPtr(pc+1)), 2, 0);
3143 case INST_JUMP_TRUE4:
3144 NEXT_INST_F((iResult? TclGetInt4AtPtr(pc+1) : 5), 2, 0);
3147 objResultPtr = Tcl_NewIntObj(iResult);
3148 NEXT_INST_F(0, 2, 1);
3159 * Only integers are allowed. We compute value op value2.
3162 long i2 = 0, rem, negative;
3163 long iResult = 0; /* Init. avoids compiler warning. */
3164 Tcl_WideInt w2, wResult = W0;
3167 value2Ptr = stackPtr[stackTop];
3168 valuePtr = stackPtr[stackTop - 1];
3169 if (valuePtr->typePtr == &tclIntType) {
3170 i = valuePtr->internalRep.longValue;
3171 } else if (valuePtr->typePtr == &tclWideIntType) {
3172 TclGetWide(w,valuePtr);
3173 } else { /* try to convert to int */
3174 REQUIRE_WIDE_OR_INT(result, valuePtr, i, w);
3175 if (result != TCL_OK) {
3176 TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n",
3177 O2S(valuePtr), O2S(value2Ptr),
3179 valuePtr->typePtr->name : "null")));
3180 DECACHE_STACK_INFO();
3181 IllegalExprOperandType(interp, pc, valuePtr);
3186 if (value2Ptr->typePtr == &tclIntType) {
3187 i2 = value2Ptr->internalRep.longValue;
3188 } else if (value2Ptr->typePtr == &tclWideIntType) {
3189 TclGetWide(w2,value2Ptr);
3191 REQUIRE_WIDE_OR_INT(result, value2Ptr, i2, w2);
3192 if (result != TCL_OK) {
3193 TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n",
3194 O2S(valuePtr), O2S(value2Ptr),
3195 (value2Ptr->typePtr?
3196 value2Ptr->typePtr->name : "null")));
3197 DECACHE_STACK_INFO();
3198 IllegalExprOperandType(interp, pc, value2Ptr);
3207 * This code is tricky: C doesn't guarantee much about
3208 * the quotient or remainder, but Tcl does. The
3209 * remainder always has the same sign as the divisor and
3210 * a smaller absolute value.
3212 if (value2Ptr->typePtr == &tclWideIntType && w2 == W0) {
3213 if (valuePtr->typePtr == &tclIntType) {
3214 TRACE(("%ld "LLD" => DIVIDE BY ZERO\n", i, w2));
3216 TRACE((LLD" "LLD" => DIVIDE BY ZERO\n", w, w2));
3220 if (value2Ptr->typePtr == &tclIntType && i2 == 0) {
3221 if (valuePtr->typePtr == &tclIntType) {
3222 TRACE(("%ld %ld => DIVIDE BY ZERO\n", i, i2));
3224 TRACE((LLD" %ld => DIVIDE BY ZERO\n", w, i2));
3229 if (valuePtr->typePtr == &tclWideIntType
3230 || value2Ptr->typePtr == &tclWideIntType) {
3231 Tcl_WideInt wRemainder;
3235 if (valuePtr->typePtr == &tclIntType) {
3236 w = Tcl_LongAsWide(i);
3237 } else if (value2Ptr->typePtr == &tclIntType) {
3238 w2 = Tcl_LongAsWide(i2);
3245 wRemainder = w % w2;
3246 if (wRemainder < 0) {
3250 wRemainder = -wRemainder;
3252 wResult = wRemainder;
3272 * Shifts are never usefully 64-bits wide!
3274 FORCE_LONG(value2Ptr, i2, w2);
3275 if (valuePtr->typePtr == &tclWideIntType) {
3276 #ifdef TCL_COMPILE_DEBUG
3277 w2 = Tcl_LongAsWide(i2);
3278 #endif /* TCL_COMPILE_DEBUG */
3281 * Shift in steps when the shift gets large to prevent
3282 * annoying compiler/processor bugs. [Bug 868467]
3285 wResult = Tcl_LongAsWide(0);
3286 } else if (i2 > 60) {
3290 } else if (i2 > 30) {
3300 * Shift in steps when the shift gets large to prevent
3301 * annoying compiler/processor bugs. [Bug 868467]
3305 } else if (i2 > 60) {
3309 } else if (i2 > 30) {
3318 * The following code is a bit tricky: it ensures that
3319 * right shifts propagate the sign bit even on machines
3320 * where ">>" won't do it by default.
3323 * Shifts are never usefully 64-bits wide!
3325 FORCE_LONG(value2Ptr, i2, w2);
3326 if (valuePtr->typePtr == &tclWideIntType) {
3327 #ifdef TCL_COMPILE_DEBUG
3328 w2 = Tcl_LongAsWide(i2);
3329 #endif /* TCL_COMPILE_DEBUG */
3336 * Shift in steps when the shift gets large to prevent
3337 * annoying compiler/processor bugs. [Bug 868467]
3340 wResult = Tcl_LongAsWide(0);
3341 } else if (i2 > 60) {
3345 } else if (i2 > 30) {
3363 * Shift in steps when the shift gets large to prevent
3364 * annoying compiler/processor bugs. [Bug 868467]
3368 } else if (i2 > 60) {
3372 } else if (i2 > 30) {
3383 if (valuePtr->typePtr == &tclWideIntType
3384 || value2Ptr->typePtr == &tclWideIntType) {
3388 if (valuePtr->typePtr == &tclIntType) {
3389 w = Tcl_LongAsWide(i);
3390 } else if (value2Ptr->typePtr == &tclIntType) {
3391 w2 = Tcl_LongAsWide(i2);
3400 if (valuePtr->typePtr == &tclWideIntType
3401 || value2Ptr->typePtr == &tclWideIntType) {
3405 if (valuePtr->typePtr == &tclIntType) {
3406 w = Tcl_LongAsWide(i);
3407 } else if (value2Ptr->typePtr == &tclIntType) {
3408 w2 = Tcl_LongAsWide(i2);
3417 if (valuePtr->typePtr == &tclWideIntType
3418 || value2Ptr->typePtr == &tclWideIntType) {
3422 if (valuePtr->typePtr == &tclIntType) {
3423 w = Tcl_LongAsWide(i);
3424 } else if (value2Ptr->typePtr == &tclIntType) {
3425 w2 = Tcl_LongAsWide(i2);
3436 * Reuse the valuePtr object already on stack if possible.
3439 if (Tcl_IsShared(valuePtr)) {
3441 objResultPtr = Tcl_NewWideIntObj(wResult);
3442 TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
3444 objResultPtr = Tcl_NewLongObj(iResult);
3445 TRACE(("%ld %ld => %ld\n", i, i2, iResult));
3447 NEXT_INST_F(1, 2, 1);
3448 } else { /* reuse the valuePtr object */
3450 TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
3451 Tcl_SetWideIntObj(valuePtr, wResult);
3453 TRACE(("%ld %ld => %ld\n", i, i2, iResult));
3454 Tcl_SetLongObj(valuePtr, iResult);
3456 NEXT_INST_F(1, 1, 0);
3466 * Operands must be numeric and ints get converted to floats
3467 * if necessary. We compute value op value2.
3470 Tcl_ObjType *t1Ptr, *t2Ptr;
3471 long i2 = 0, quot, rem; /* Init. avoids compiler warning. */
3473 long iResult = 0; /* Init. avoids compiler warning. */
3474 double dResult = 0.0; /* Init. avoids compiler warning. */
3475 int doDouble = 0; /* 1 if doing floating arithmetic */
3476 Tcl_WideInt w2, wquot, wrem;
3477 Tcl_WideInt wResult = W0; /* Init. avoids compiler warning. */
3478 int doWide = 0; /* 1 if doing wide arithmetic. */
3480 value2Ptr = stackPtr[stackTop];
3481 valuePtr = stackPtr[stackTop - 1];
3482 t1Ptr = valuePtr->typePtr;
3483 t2Ptr = value2Ptr->typePtr;
3485 if (t1Ptr == &tclIntType) {
3486 i = valuePtr->internalRep.longValue;
3487 } else if (t1Ptr == &tclWideIntType) {
3488 TclGetWide(w,valuePtr);
3489 } else if ((t1Ptr == &tclDoubleType)
3490 && (valuePtr->bytes == NULL)) {
3492 * We can only use the internal rep directly if there is
3493 * no string rep. Otherwise the string rep might actually
3494 * look like an integer, which is preferred.
3497 d1 = valuePtr->internalRep.doubleValue;
3499 char *s = Tcl_GetStringFromObj(valuePtr, &length);
3500 if (TclLooksLikeInt(s, length)) {
3501 GET_WIDE_OR_INT(result, valuePtr, i, w);
3503 result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
3506 if (result != TCL_OK) {
3507 TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n",
3510 valuePtr->typePtr->name : "null")));
3511 DECACHE_STACK_INFO();
3512 IllegalExprOperandType(interp, pc, valuePtr);
3516 t1Ptr = valuePtr->typePtr;
3519 if (t2Ptr == &tclIntType) {
3520 i2 = value2Ptr->internalRep.longValue;
3521 } else if (t2Ptr == &tclWideIntType) {
3522 TclGetWide(w2,value2Ptr);
3523 } else if ((t2Ptr == &tclDoubleType)
3524 && (value2Ptr->bytes == NULL)) {
3526 * We can only use the internal rep directly if there is
3527 * no string rep. Otherwise the string rep might actually
3528 * look like an integer, which is preferred.
3531 d2 = value2Ptr->internalRep.doubleValue;
3533 char *s = Tcl_GetStringFromObj(value2Ptr, &length);
3534 if (TclLooksLikeInt(s, length)) {
3535 GET_WIDE_OR_INT(result, value2Ptr, i2, w2);
3537 result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
3540 if (result != TCL_OK) {
3541 TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n",
3543 (value2Ptr->typePtr?
3544 value2Ptr->typePtr->name : "null")));
3545 DECACHE_STACK_INFO();
3546 IllegalExprOperandType(interp, pc, value2Ptr);
3550 t2Ptr = value2Ptr->typePtr;
3553 if ((t1Ptr == &tclDoubleType) || (t2Ptr == &tclDoubleType)) {
3555 * Do double arithmetic.
3558 if (t1Ptr == &tclIntType) {
3559 d1 = i; /* promote value 1 to double */
3560 } else if (t2Ptr == &tclIntType) {
3561 d2 = i2; /* promote value 2 to double */
3562 } else if (t1Ptr == &tclWideIntType) {
3563 d1 = Tcl_WideAsDouble(w);
3564 } else if (t2Ptr == &tclWideIntType) {
3565 d2 = Tcl_WideAsDouble(w2);
3579 TRACE(("%.6g %.6g => DIVIDE BY ZERO\n", d1, d2));
3587 * Check now for IEEE floating-point error.
3590 if (IS_NAN(dResult) || IS_INF(dResult)) {
3591 TRACE(("%.20s %.20s => IEEE FLOATING PT ERROR\n",
3592 O2S(valuePtr), O2S(value2Ptr)));
3593 DECACHE_STACK_INFO();
3594 TclExprFloatError(interp, dResult);
3599 } else if ((t1Ptr == &tclWideIntType)
3600 || (t2Ptr == &tclWideIntType)) {
3602 * Do wide integer arithmetic.
3605 if (t1Ptr == &tclIntType) {
3606 w = Tcl_LongAsWide(i);
3607 } else if (t2Ptr == &tclIntType) {
3608 w2 = Tcl_LongAsWide(i2);
3622 * This code is tricky: C doesn't guarantee much
3623 * about the quotient or remainder, but Tcl does.
3624 * The remainder always has the same sign as the
3625 * divisor and a smaller absolute value.
3628 TRACE((LLD" "LLD" => DIVIDE BY ZERO\n", w, w2));
3645 * Do integer arithmetic.
3659 * This code is tricky: C doesn't guarantee much
3660 * about the quotient or remainder, but Tcl does.
3661 * The remainder always has the same sign as the
3662 * divisor and a smaller absolute value.
3665 TRACE(("%ld %ld => DIVIDE BY ZERO\n", i, i2));
3683 * Reuse the valuePtr object already on stack if possible.
3686 if (Tcl_IsShared(valuePtr)) {
3688 objResultPtr = Tcl_NewDoubleObj(dResult);
3689 TRACE(("%.6g %.6g => %.6g\n", d1, d2, dResult));
3690 } else if (doWide) {
3691 objResultPtr = Tcl_NewWideIntObj(wResult);
3692 TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
3694 objResultPtr = Tcl_NewLongObj(iResult);
3695 TRACE(("%ld %ld => %ld\n", i, i2, iResult));
3697 NEXT_INST_F(1, 2, 1);
3698 } else { /* reuse the valuePtr object */
3699 if (doDouble) { /* NB: stack top is off by 1 */
3700 TRACE(("%.6g %.6g => %.6g\n", d1, d2, dResult));
3701 Tcl_SetDoubleObj(valuePtr, dResult);
3702 } else if (doWide) {
3703 TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
3704 Tcl_SetWideIntObj(valuePtr, wResult);
3706 TRACE(("%ld %ld => %ld\n", i, i2, iResult));
3707 Tcl_SetLongObj(valuePtr, iResult);
3709 NEXT_INST_F(1, 1, 0);
3716 * Operand must be numeric.
3722 valuePtr = stackPtr[stackTop];
3723 tPtr = valuePtr->typePtr;
3724 if (!IS_INTEGER_TYPE(tPtr) && ((tPtr != &tclDoubleType)
3725 || (valuePtr->bytes != NULL))) {
3726 char *s = Tcl_GetStringFromObj(valuePtr, &length);
3727 if (TclLooksLikeInt(s, length)) {
3728 GET_WIDE_OR_INT(result, valuePtr, i, w);
3730 result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d);
3732 if (result != TCL_OK) {
3733 TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n",
3734 s, (tPtr? tPtr->name : "null")));
3735 DECACHE_STACK_INFO();
3736 IllegalExprOperandType(interp, pc, valuePtr);
3740 tPtr = valuePtr->typePtr;
3744 * Ensure that the operand's string rep is the same as the
3745 * formatted version of its internal rep. This makes sure
3746 * that "expr +000123" yields "83", not "000123". We
3747 * implement this by _discarding_ the string rep since we
3748 * know it will be regenerated, if needed later, by
3749 * formatting the internal rep's value.
3752 if (Tcl_IsShared(valuePtr)) {
3753 if (tPtr == &tclIntType) {
3754 i = valuePtr->internalRep.longValue;
3755 objResultPtr = Tcl_NewLongObj(i);
3756 } else if (tPtr == &tclWideIntType) {
3757 TclGetWide(w,valuePtr);
3758 objResultPtr = Tcl_NewWideIntObj(w);
3760 d = valuePtr->internalRep.doubleValue;
3761 objResultPtr = Tcl_NewDoubleObj(d);
3763 TRACE_WITH_OBJ(("%s => ", O2S(objResultPtr)), objResultPtr);
3764 NEXT_INST_F(1, 1, 1);
3766 Tcl_InvalidateStringRep(valuePtr);
3767 TRACE_WITH_OBJ(("%s => ", O2S(valuePtr)), valuePtr);
3768 NEXT_INST_F(1, 0, 0);
3776 * The operand must be numeric or a boolean string as
3777 * accepted by Tcl_GetBooleanFromObj(). If the operand
3778 * object is unshared modify it directly, otherwise
3779 * create a copy to modify: this is "copy on write".
3780 * Free any old string representation since it is now
3788 valuePtr = stackPtr[stackTop];
3789 tPtr = valuePtr->typePtr;
3790 if (!IS_INTEGER_TYPE(tPtr) && ((tPtr != &tclDoubleType)
3791 || (valuePtr->bytes != NULL))) {
3792 if ((tPtr == &tclBooleanType) && (valuePtr->bytes == NULL)) {
3793 valuePtr->typePtr = &tclIntType;
3795 char *s = Tcl_GetStringFromObj(valuePtr, &length);
3796 if (TclLooksLikeInt(s, length)) {
3797 GET_WIDE_OR_INT(result, valuePtr, i, w);
3799 result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
3802 if (result == TCL_ERROR && *pc == INST_LNOT) {
3803 result = Tcl_GetBooleanFromObj((Tcl_Interp *)NULL,
3804 valuePtr, &boolvar);
3805 i = (long)boolvar; /* i is long, not int! */
3807 if (result != TCL_OK) {
3808 TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n",
3809 s, (tPtr? tPtr->name : "null")));
3810 DECACHE_STACK_INFO();
3811 IllegalExprOperandType(interp, pc, valuePtr);
3816 tPtr = valuePtr->typePtr;
3819 if (Tcl_IsShared(valuePtr)) {
3821 * Create a new object.
3823 if ((tPtr == &tclIntType) || (tPtr == &tclBooleanType)) {
3824 i = valuePtr->internalRep.longValue;
3825 objResultPtr = Tcl_NewLongObj(
3826 (*pc == INST_UMINUS)? -i : !i);
3827 TRACE_WITH_OBJ(("%ld => ", i), objResultPtr);
3828 } else if (tPtr == &tclWideIntType) {
3829 TclGetWide(w,valuePtr);
3830 if (*pc == INST_UMINUS) {
3831 objResultPtr = Tcl_NewWideIntObj(-w);
3833 objResultPtr = Tcl_NewLongObj(w == W0);
3835 TRACE_WITH_OBJ((LLD" => ", w), objResultPtr);
3837 d = valuePtr->internalRep.doubleValue;
3838 if (*pc == INST_UMINUS) {
3839 objResultPtr = Tcl_NewDoubleObj(-d);
3842 * Should be able to use "!d", but apparently
3843 * some compilers can't handle it.
3845 objResultPtr = Tcl_NewLongObj((d==0.0)? 1 : 0);
3847 TRACE_WITH_OBJ(("%.6g => ", d), objResultPtr);
3849 NEXT_INST_F(1, 1, 1);
3852 * valuePtr is unshared. Modify it directly.
3854 if ((tPtr == &tclIntType) || (tPtr == &tclBooleanType)) {
3855 i = valuePtr->internalRep.longValue;
3856 Tcl_SetLongObj(valuePtr,
3857 (*pc == INST_UMINUS)? -i : !i);
3858 TRACE_WITH_OBJ(("%ld => ", i), valuePtr);
3859 } else if (tPtr == &tclWideIntType) {
3860 TclGetWide(w,valuePtr);
3861 if (*pc == INST_UMINUS) {
3862 Tcl_SetWideIntObj(valuePtr, -w);
3864 Tcl_SetLongObj(valuePtr, w == W0);
3866 TRACE_WITH_OBJ((LLD" => ", w), valuePtr);
3868 d = valuePtr->internalRep.doubleValue;
3869 if (*pc == INST_UMINUS) {
3870 Tcl_SetDoubleObj(valuePtr, -d);
3873 * Should be able to use "!d", but apparently
3874 * some compilers can't handle it.
3876 Tcl_SetLongObj(valuePtr, (d==0.0)? 1 : 0);
3878 TRACE_WITH_OBJ(("%.6g => ", d), valuePtr);
3880 NEXT_INST_F(1, 0, 0);
3887 * The operand must be an integer. If the operand object is
3888 * unshared modify it directly, otherwise modify a copy.
3889 * Free any old string representation since it is now
3895 valuePtr = stackPtr[stackTop];
3896 tPtr = valuePtr->typePtr;
3897 if (!IS_INTEGER_TYPE(tPtr)) {
3898 REQUIRE_WIDE_OR_INT(result, valuePtr, i, w);
3899 if (result != TCL_OK) { /* try to convert to double */
3900 TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n",
3901 O2S(valuePtr), (tPtr? tPtr->name : "null")));
3902 DECACHE_STACK_INFO();
3903 IllegalExprOperandType(interp, pc, valuePtr);
3909 if (valuePtr->typePtr == &tclWideIntType) {
3910 TclGetWide(w,valuePtr);
3911 if (Tcl_IsShared(valuePtr)) {
3912 objResultPtr = Tcl_NewWideIntObj(~w);
3913 TRACE(("0x%llx => (%llu)\n", w, ~w));
3914 NEXT_INST_F(1, 1, 1);
3917 * valuePtr is unshared. Modify it directly.
3919 Tcl_SetWideIntObj(valuePtr, ~w);
3920 TRACE(("0x%llx => (%llu)\n", w, ~w));
3921 NEXT_INST_F(1, 0, 0);
3924 i = valuePtr->internalRep.longValue;
3925 if (Tcl_IsShared(valuePtr)) {
3926 objResultPtr = Tcl_NewLongObj(~i);
3927 TRACE(("0x%lx => (%lu)\n", i, ~i));
3928 NEXT_INST_F(1, 1, 1);
3931 * valuePtr is unshared. Modify it directly.
3933 Tcl_SetLongObj(valuePtr, ~i);
3934 TRACE(("0x%lx => (%lu)\n", i, ~i));
3935 NEXT_INST_F(1, 0, 0);
3940 case INST_CALL_BUILTIN_FUNC1:
3941 opnd = TclGetUInt1AtPtr(pc+1);
3944 * Call one of the built-in Tcl math functions.
3947 BuiltinFunc *mathFuncPtr;
3949 if ((opnd < 0) || (opnd > LAST_BUILTIN_FUNC)) {
3950 TRACE(("UNRECOGNIZED BUILTIN FUNC CODE %d\n", opnd));
3951 panic("TclExecuteByteCode: unrecognized builtin function code %d", opnd);
3953 mathFuncPtr = &(tclBuiltinFuncTable[opnd]);
3954 DECACHE_STACK_INFO();
3955 result = (*mathFuncPtr->proc)(interp, eePtr,
3956 mathFuncPtr->clientData);
3958 if (result != TCL_OK) {
3961 TRACE_WITH_OBJ(("%d => ", opnd), stackPtr[stackTop]);
3963 NEXT_INST_F(2, 0, 0);
3965 case INST_CALL_FUNC1:
3966 opnd = TclGetUInt1AtPtr(pc+1);
3969 * Call a non-builtin Tcl math function previously
3970 * registered by a call to Tcl_CreateMathFunc.
3973 int objc = opnd; /* Number of arguments. The function name
3974 * is the 0-th argument. */
3975 Tcl_Obj **objv; /* The array of arguments. The function
3976 * name is objv[0]. */
3978 objv = &(stackPtr[stackTop - (objc-1)]); /* "objv[0]" */
3979 DECACHE_STACK_INFO();
3980 result = ExprCallMathFunc(interp, eePtr, objc, objv);
3982 if (result != TCL_OK) {
3985 TRACE_WITH_OBJ(("%d => ", objc), stackPtr[stackTop]);
3987 NEXT_INST_F(2, 0, 0);
3989 case INST_TRY_CVT_TO_NUMERIC:
3992 * Try to convert the topmost stack object to an int or
3993 * double object. This is done in order to support Tcl's
3994 * policy of interpreting operands if at all possible as
3995 * first integers, else floating-point numbers.
4001 int converted, needNew;
4003 valuePtr = stackPtr[stackTop];
4004 tPtr = valuePtr->typePtr;
4006 if (!IS_INTEGER_TYPE(tPtr) && ((tPtr != &tclDoubleType)
4007 || (valuePtr->bytes != NULL))) {
4008 if ((tPtr == &tclBooleanType) && (valuePtr->bytes == NULL)) {
4009 valuePtr->typePtr = &tclIntType;
4012 s = Tcl_GetStringFromObj(valuePtr, &length);
4013 if (TclLooksLikeInt(s, length)) {
4014 GET_WIDE_OR_INT(result, valuePtr, i, w);
4016 result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
4019 if (result == TCL_OK) {
4022 result = TCL_OK; /* reset the result variable */
4024 tPtr = valuePtr->typePtr;
4028 * Ensure that the topmost stack object, if numeric, has a
4029 * string rep the same as the formatted version of its
4030 * internal rep. This is used, e.g., to make sure that "expr
4031 * {0001}" yields "1", not "0001". We implement this by
4032 * _discarding_ the string rep since we know it will be
4033 * regenerated, if needed later, by formatting the internal
4034 * rep's value. Also check if there has been an IEEE
4035 * floating point error.
4038 objResultPtr = valuePtr;
4040 if (IS_NUMERIC_TYPE(tPtr)) {
4041 if (Tcl_IsShared(valuePtr)) {
4042 if (valuePtr->bytes != NULL) {
4044 * We only need to make a copy of the object
4045 * when it already had a string rep
4048 if (tPtr == &tclIntType) {
4049 i = valuePtr->internalRep.longValue;
4050 objResultPtr = Tcl_NewLongObj(i);
4051 } else if (tPtr == &tclWideIntType) {
4052 TclGetWide(w,valuePtr);
4053 objResultPtr = Tcl_NewWideIntObj(w);
4055 d = valuePtr->internalRep.doubleValue;
4056 objResultPtr = Tcl_NewDoubleObj(d);
4058 tPtr = objResultPtr->typePtr;
4061 Tcl_InvalidateStringRep(valuePtr);
4064 if (tPtr == &tclDoubleType) {
4065 d = objResultPtr->internalRep.doubleValue;
4066 if (IS_NAN(d) || IS_INF(d)) {
4067 TRACE(("\"%.20s\" => IEEE FLOATING PT ERROR\n",
4068 O2S(objResultPtr)));
4069 DECACHE_STACK_INFO();
4070 TclExprFloatError(interp, d);
4076 converted = converted; /* lint, converted not used. */
4077 TRACE(("\"%.20s\" => numeric, %s, %s\n", O2S(valuePtr),
4078 (converted? "converted" : "not converted"),
4079 (needNew? "new Tcl_Obj" : "same Tcl_Obj")));
4081 TRACE(("\"%.20s\" => not numeric\n", O2S(valuePtr)));
4084 NEXT_INST_F(1, 1, 1);
4086 NEXT_INST_F(1, 0, 0);
4091 DECACHE_STACK_INFO();
4092 Tcl_ResetResult(interp);
4096 goto processExceptionReturn;
4099 DECACHE_STACK_INFO();
4100 Tcl_ResetResult(interp);
4102 result = TCL_CONTINUE;
4104 goto processExceptionReturn;
4106 case INST_FOREACH_START4:
4107 opnd = TclGetUInt4AtPtr(pc+1);
4110 * Initialize the temporary local var that holds the count
4111 * of the number of iterations of the loop body to -1.
4114 ForeachInfo *infoPtr = (ForeachInfo *)
4115 codePtr->auxDataArrayPtr[opnd].clientData;
4116 int iterTmpIndex = infoPtr->loopCtTemp;
4117 Var *compiledLocals = iPtr->varFramePtr->compiledLocals;
4118 Var *iterVarPtr = &(compiledLocals[iterTmpIndex]);
4119 Tcl_Obj *oldValuePtr = iterVarPtr->value.objPtr;
4121 if (oldValuePtr == NULL) {
4122 iterVarPtr->value.objPtr = Tcl_NewLongObj(-1);
4123 Tcl_IncrRefCount(iterVarPtr->value.objPtr);
4125 Tcl_SetLongObj(oldValuePtr, -1);
4127 TclSetVarScalar(iterVarPtr);
4128 TclClearVarUndefined(iterVarPtr);
4129 TRACE(("%u => loop iter count temp %d\n",
4130 opnd, iterTmpIndex));
4133 #ifndef TCL_COMPILE_DEBUG
4135 * Remark that the compiler ALWAYS sets INST_FOREACH_STEP4
4136 * immediately after INST_FOREACH_START4 - let us just fall
4137 * through instead of jumping back to the top.
4142 NEXT_INST_F(5, 0, 0);
4144 case INST_FOREACH_STEP4:
4145 opnd = TclGetUInt4AtPtr(pc+1);
4148 * "Step" a foreach loop (i.e., begin its next iteration) by
4149 * assigning the next value list element to each loop var.
4152 ForeachInfo *infoPtr = (ForeachInfo *)
4153 codePtr->auxDataArrayPtr[opnd].clientData;
4154 ForeachVarList *varListPtr;
4155 int numLists = infoPtr->numLists;
4156 Var *compiledLocals = iPtr->varFramePtr->compiledLocals;
4158 Var *iterVarPtr, *listVarPtr;
4159 int iterNum, listTmpIndex, listLen, numVars;
4160 int varIndex, valIndex, continueLoop, j;
4163 * Increment the temp holding the loop iteration number.
4166 iterVarPtr = &(compiledLocals[infoPtr->loopCtTemp]);
4167 valuePtr = iterVarPtr->value.objPtr;
4168 iterNum = (valuePtr->internalRep.longValue + 1);
4169 Tcl_SetLongObj(valuePtr, iterNum);
4172 * Check whether all value lists are exhausted and we should
4177 listTmpIndex = infoPtr->firstValueTemp;
4178 for (i = 0; i < numLists; i++) {
4179 varListPtr = infoPtr->varLists[i];
4180 numVars = varListPtr->numVars;
4182 listVarPtr = &(compiledLocals[listTmpIndex]);
4183 listPtr = listVarPtr->value.objPtr;
4184 result = Tcl_ListObjLength(interp, listPtr, &listLen);
4185 if (result != TCL_OK) {
4186 TRACE_WITH_OBJ(("%u => ERROR converting list %ld, \"%s\": ",
4187 opnd, i, O2S(listPtr)), Tcl_GetObjResult(interp));
4190 if (listLen > (iterNum * numVars)) {
4197 * If some var in some var list still has a remaining list
4198 * element iterate one more time. Assign to var the next
4199 * element from its value list. We already checked above
4200 * that each list temp holds a valid list object.
4204 listTmpIndex = infoPtr->firstValueTemp;
4205 for (i = 0; i < numLists; i++) {
4206 varListPtr = infoPtr->varLists[i];
4207 numVars = varListPtr->numVars;
4209 listVarPtr = &(compiledLocals[listTmpIndex]);
4210 listPtr = listVarPtr->value.objPtr;
4212 valIndex = (iterNum * numVars);
4213 for (j = 0; j < numVars; j++) {
4217 * The call to TclPtrSetVar might shimmer listPtr,
4218 * so re-fetch pointers every iteration for safety.
4219 * See test foreach-10.1.
4222 Tcl_ListObjGetElements(NULL, listPtr,
4223 &listLen, &elements);
4224 if (valIndex >= listLen) {
4225 TclNewObj(valuePtr);
4227 valuePtr = elements[valIndex];
4230 varIndex = varListPtr->varIndexes[j];
4231 varPtr = &(varFramePtr->compiledLocals[varIndex]);
4232 part1 = varPtr->name;
4233 while (TclIsVarLink(varPtr)) {
4234 varPtr = varPtr->value.linkPtr;
4236 if (!((varPtr->flags & VAR_IN_HASHTABLE) && (varPtr->hPtr == NULL))
4237 && (varPtr->tracePtr == NULL)
4238 && (TclIsVarScalar(varPtr) || TclIsVarUndefined(varPtr))) {
4239 value2Ptr = varPtr->value.objPtr;
4240 if (valuePtr != value2Ptr) {
4241 if (value2Ptr != NULL) {
4242 TclDecrRefCount(value2Ptr);
4244 TclSetVarScalar(varPtr);
4245 TclClearVarUndefined(varPtr);
4247 varPtr->value.objPtr = valuePtr;
4248 Tcl_IncrRefCount(valuePtr);
4251 DECACHE_STACK_INFO();
4252 Tcl_IncrRefCount(valuePtr);
4253 value2Ptr = TclPtrSetVar(interp, varPtr, NULL, part1,
4254 NULL, valuePtr, TCL_LEAVE_ERR_MSG);
4255 TclDecrRefCount(valuePtr);
4257 if (value2Ptr == NULL) {
4258 TRACE_WITH_OBJ(("%u => ERROR init. index temp %d: ",
4260 Tcl_GetObjResult(interp));
4270 TRACE(("%u => %d lists, iter %d, %s loop\n", opnd, numLists,
4271 iterNum, (continueLoop? "continue" : "exit")));
4274 * Run-time peep-hole optimisation: the compiler ALWAYS follows
4275 * INST_FOREACH_STEP4 with an INST_JUMP_FALSE. We just skip that
4276 * instruction and jump direct from here.
4280 if (*pc == INST_JUMP_FALSE1) {
4281 NEXT_INST_F((continueLoop? 2 : TclGetInt1AtPtr(pc+1)), 0, 0);
4283 NEXT_INST_F((continueLoop? 5 : TclGetInt4AtPtr(pc+1)), 0, 0);
4287 case INST_BEGIN_CATCH4:
4289 * Record start of the catch command with exception range index
4290 * equal to the operand. Push the current stack depth onto the
4291 * special catch stack.
4293 catchStackPtr[++catchTop] = stackTop;
4294 TRACE(("%u => catchTop=%d, stackTop=%d\n",
4295 TclGetUInt4AtPtr(pc+1), catchTop, stackTop));
4296 NEXT_INST_F(5, 0, 0);
4298 case INST_END_CATCH:
4301 TRACE(("=> catchTop=%d\n", catchTop));
4302 NEXT_INST_F(1, 0, 0);
4304 case INST_PUSH_RESULT:
4305 objResultPtr = Tcl_GetObjResult(interp);
4306 TRACE_WITH_OBJ(("=> "), Tcl_GetObjResult(interp));
4309 * See the comments at INST_INVOKE_STK
4312 Tcl_Obj *newObjResultPtr;
4313 TclNewObj(newObjResultPtr);
4314 Tcl_IncrRefCount(newObjResultPtr);
4315 iPtr->objResultPtr = newObjResultPtr;
4318 NEXT_INST_F(1, 0, -1);
4320 case INST_PUSH_RETURN_CODE:
4321 objResultPtr = Tcl_NewLongObj(result);
4322 TRACE(("=> %u\n", result));
4323 NEXT_INST_F(1, 0, 1);
4326 panic("TclExecuteByteCode: unrecognized opCode %u", *pc);
4327 } /* end of switch on opCode */
4330 * Division by zero in an expression. Control only reaches this
4331 * point by "goto divideByZero".
4335 DECACHE_STACK_INFO();
4336 Tcl_ResetResult(interp);
4337 Tcl_AppendToObj(Tcl_GetObjResult(interp), "divide by zero", -1);
4338 Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero",
4346 * An external evaluation (INST_INVOKE or INST_EVAL) returned
4347 * something different from TCL_OK, or else INST_BREAK or
4348 * INST_CONTINUE were called.
4351 processExceptionReturn:
4352 #if TCL_COMPILE_DEBUG
4354 case INST_INVOKE_STK1:
4355 case INST_INVOKE_STK4:
4356 TRACE(("%u => ... after \"%.20s\": ", opnd, cmdNameBuf));
4360 * Note that the object at stacktop has to be used
4361 * before doing the cleanup.
4364 TRACE(("\"%.30s\" => ", O2S(stackPtr[stackTop])));
4370 if ((result == TCL_CONTINUE) || (result == TCL_BREAK)) {
4371 rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 0, codePtr);
4372 if (rangePtr == NULL) {
4373 TRACE_APPEND(("no encl. loop or catch, returning %s\n",
4374 StringForResultCode(result)));
4375 goto abnormalReturn;
4377 if (rangePtr->type == CATCH_EXCEPTION_RANGE) {
4378 TRACE_APPEND(("%s ...\n", StringForResultCode(result)));
4382 valuePtr = POP_OBJECT();
4383 TclDecrRefCount(valuePtr);
4385 if (result == TCL_BREAK) {
4387 pc = (codePtr->codeStart + rangePtr->breakOffset);
4388 TRACE_APPEND(("%s, range at %d, new pc %d\n",
4389 StringForResultCode(result),
4390 rangePtr->codeOffset, rangePtr->breakOffset));
4391 NEXT_INST_F(0, 0, 0);
4393 if (rangePtr->continueOffset == -1) {
4394 TRACE_APPEND(("%s, loop w/o continue, checking for catch\n",
4395 StringForResultCode(result)));
4399 pc = (codePtr->codeStart + rangePtr->continueOffset);
4400 TRACE_APPEND(("%s, range at %d, new pc %d\n",
4401 StringForResultCode(result),
4402 rangePtr->codeOffset, rangePtr->continueOffset));
4403 NEXT_INST_F(0, 0, 0);
4405 #if TCL_COMPILE_DEBUG
4406 } else if (traceInstructions) {
4407 if ((result != TCL_ERROR) && (result != TCL_RETURN)) {
4408 objPtr = Tcl_GetObjResult(interp);
4409 TRACE_APPEND(("OTHER RETURN CODE %d, result= \"%s\"\n ",
4410 result, O2S(objPtr)));
4412 objPtr = Tcl_GetObjResult(interp);
4413 TRACE_APPEND(("%s, result= \"%s\"\n",
4414 StringForResultCode(result), O2S(objPtr)));
4420 * Execution has generated an "exception" such as TCL_ERROR. If the
4421 * exception is an error, record information about what was being
4422 * executed when the error occurred. Find the closest enclosing
4423 * catch range, if any. If no enclosing catch range is found, stop
4424 * execution and return the "exception" code.
4428 if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
4429 bytes = GetSrcInfoForPc(pc, codePtr, &length);
4430 if (bytes != NULL) {
4431 DECACHE_STACK_INFO();
4432 Tcl_LogCommandInfo(interp, codePtr->source, bytes, length);
4434 iPtr->flags |= ERR_ALREADY_LOGGED;
4437 if (catchTop == -1) {
4438 #ifdef TCL_COMPILE_DEBUG
4439 if (traceInstructions) {
4440 fprintf(stdout, " ... no enclosing catch, returning %s\n",
4441 StringForResultCode(result));
4444 goto abnormalReturn;
4446 rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 1, codePtr);
4447 if (rangePtr == NULL) {
4449 * This is only possible when compiling a [catch] that sends its
4450 * script to INST_EVAL. Cannot correct the compiler without
4451 * breakingcompat with previous .tbc compiled scripts.
4453 #ifdef TCL_COMPILE_DEBUG
4454 if (traceInstructions) {
4455 fprintf(stdout, " ... no enclosing catch, returning %s\n",
4456 StringForResultCode(result));
4459 goto abnormalReturn;
4463 * A catch exception range (rangePtr) was found to handle an
4464 * "exception". It was found either by checkForCatch just above or
4465 * by an instruction during break, continue, or error processing.
4466 * Jump to its catchOffset after unwinding the operand stack to
4467 * the depth it had when starting to execute the range's catch
4472 while (stackTop > catchStackPtr[catchTop]) {
4473 valuePtr = POP_OBJECT();
4474 TclDecrRefCount(valuePtr);
4476 #ifdef TCL_COMPILE_DEBUG
4477 if (traceInstructions) {
4478 fprintf(stdout, " ... found catch at %d, catchTop=%d, unwound to %d, new pc %u\n",
4479 rangePtr->codeOffset, catchTop, catchStackPtr[catchTop],
4480 (unsigned int)(rangePtr->catchOffset));
4483 pc = (codePtr->codeStart + rangePtr->catchOffset);
4484 NEXT_INST_F(0, 0, 0); /* restart the execution loop at pc */
4487 * end of infinite loop dispatching on instructions.
4491 * Abnormal return code. Restore the stack to state it had when starting
4492 * to execute the ByteCode. Panic if the stack is below the initial level.
4496 while (stackTop > initStackTop) {
4497 valuePtr = POP_OBJECT();
4498 TclDecrRefCount(valuePtr);
4500 if (stackTop < initStackTop) {
4501 fprintf(stderr, "\nTclExecuteByteCode: abnormal return at pc %u: stack top %d < entry stack top %d\n",
4502 (unsigned int)(pc - codePtr->codeStart),
4503 (unsigned int) stackTop,
4504 (unsigned int) initStackTop);
4505 panic("TclExecuteByteCode execution failure: end stack top < start stack top");
4509 * Free the catch stack array if malloc'ed storage was used.
4512 if (catchStackPtr != catchStackStorage) {
4513 ckfree((char *) catchStackPtr);
4515 eePtr->stackTop = initStackTop;
4517 #undef STATIC_CATCH_STACK_SIZE
4520 #ifdef TCL_COMPILE_DEBUG
4522 *----------------------------------------------------------------------
4524 * PrintByteCodeInfo --
4526 * This procedure prints a summary about a bytecode object to stdout.
4527 * It is called by TclExecuteByteCode when starting to execute the
4528 * bytecode object if tclTraceExec has the value 2 or more.
4536 *----------------------------------------------------------------------
4540 PrintByteCodeInfo(codePtr)
4541 register ByteCode *codePtr; /* The bytecode whose summary is printed
4544 Proc *procPtr = codePtr->procPtr;
4545 Interp *iPtr = (Interp *) *codePtr->interpHandle;
4547 fprintf(stdout, "\nExecuting ByteCode 0x%x, refCt %u, epoch %u, interp 0x%x (epoch %u)\n",
4548 (unsigned int) codePtr, codePtr->refCount,
4549 codePtr->compileEpoch, (unsigned int) iPtr,
4550 iPtr->compileEpoch);
4552 fprintf(stdout, " Source: ");
4553 TclPrintSource(stdout, codePtr->source, 60);
4555 fprintf(stdout, "\n Cmds %d, src %d, inst %u, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n",
4556 codePtr->numCommands, codePtr->numSrcBytes,
4557 codePtr->numCodeBytes, codePtr->numLitObjects,
4558 codePtr->numAuxDataItems, codePtr->maxStackDepth,
4559 #ifdef TCL_COMPILE_STATS
4560 (codePtr->numSrcBytes?
4561 ((float)codePtr->structureSize)/((float)codePtr->numSrcBytes) : 0.0));
4565 #ifdef TCL_COMPILE_STATS
4566 fprintf(stdout, " Code %d = header %d+inst %d+litObj %d+exc %d+aux %d+cmdMap %d\n",
4567 codePtr->structureSize,
4568 (sizeof(ByteCode) - (sizeof(size_t) + sizeof(Tcl_Time))),
4569 codePtr->numCodeBytes,
4570 (codePtr->numLitObjects * sizeof(Tcl_Obj *)),
4571 (codePtr->numExceptRanges * sizeof(ExceptionRange)),
4572 (codePtr->numAuxDataItems * sizeof(AuxData)),
4573 codePtr->numCmdLocBytes);
4574 #endif /* TCL_COMPILE_STATS */
4575 if (procPtr != NULL) {
4577 " Proc 0x%x, refCt %d, args %d, compiled locals %d\n",
4578 (unsigned int) procPtr, procPtr->refCount,
4579 procPtr->numArgs, procPtr->numCompiledLocals);
4582 #endif /* TCL_COMPILE_DEBUG */
4585 *----------------------------------------------------------------------
4587 * ValidatePcAndStackTop --
4589 * This procedure is called by TclExecuteByteCode when debugging to
4590 * verify that the program counter and stack top are valid during
4597 * Prints a message to stderr and panics if either the pc or stack
4600 *----------------------------------------------------------------------
4603 #ifdef TCL_COMPILE_DEBUG
4605 ValidatePcAndStackTop(codePtr, pc, stackTop, stackLowerBound)
4606 register ByteCode *codePtr; /* The bytecode whose summary is printed
4608 unsigned char *pc; /* Points to first byte of a bytecode
4609 * instruction. The program counter. */
4610 int stackTop; /* Current stack top. Must be between
4611 * stackLowerBound and stackUpperBound
4613 int stackLowerBound; /* Smallest legal value for stackTop. */
4615 int stackUpperBound = stackLowerBound + codePtr->maxStackDepth;
4616 /* Greatest legal value for stackTop. */
4617 unsigned int relativePc = (unsigned int) (pc - codePtr->codeStart);
4618 unsigned int codeStart = (unsigned int) codePtr->codeStart;
4619 unsigned int codeEnd = (unsigned int)
4620 (codePtr->codeStart + codePtr->numCodeBytes);
4621 unsigned char opCode = *pc;
4623 if (((unsigned int) pc < codeStart) || ((unsigned int) pc > codeEnd)) {
4624 fprintf(stderr, "\nBad instruction pc 0x%x in TclExecuteByteCode\n",
4626 panic("TclExecuteByteCode execution failure: bad pc");
4628 if ((unsigned int) opCode > LAST_INST_OPCODE) {
4629 fprintf(stderr, "\nBad opcode %d at pc %u in TclExecuteByteCode\n",
4630 (unsigned int) opCode, relativePc);
4631 panic("TclExecuteByteCode execution failure: bad opcode");
4633 if ((stackTop < stackLowerBound) || (stackTop > stackUpperBound)) {
4635 char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars);
4636 char *ellipsis = "";
4638 fprintf(stderr, "\nBad stack top %d at pc %u in TclExecuteByteCode (min %i, max %i)",
4639 stackTop, relativePc, stackLowerBound, stackUpperBound);
4641 if (numChars > 100) {
4645 fprintf(stderr, "\n executing %.*s%s\n", numChars, cmd,
4648 fprintf(stderr, "\n");
4650 panic("TclExecuteByteCode execution failure: bad stack top");
4653 #endif /* TCL_COMPILE_DEBUG */
4656 *----------------------------------------------------------------------
4658 * IllegalExprOperandType --
4660 * Used by TclExecuteByteCode to add an error message to errorInfo
4661 * when an illegal operand type is detected by an expression
4662 * instruction. The argument opndPtr holds the operand object in error.
4668 * An error message is appended to errorInfo.
4670 *----------------------------------------------------------------------
4674 IllegalExprOperandType(interp, pc, opndPtr)
4675 Tcl_Interp *interp; /* Interpreter to which error information
4677 unsigned char *pc; /* Points to the instruction being executed
4678 * when the illegal type was found. */
4679 Tcl_Obj *opndPtr; /* Points to the operand holding the value
4680 * with the illegal type. */
4682 unsigned char opCode = *pc;
4684 Tcl_ResetResult(interp);
4685 if ((opndPtr->bytes == NULL) || (opndPtr->length == 0)) {
4686 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
4687 "can't use empty string as operand of \"",
4688 operatorStrings[opCode - INST_LOR], "\"", (char *) NULL);
4690 char *msg = "non-numeric string";
4693 int looksLikeInt = 0;
4695 s = Tcl_GetStringFromObj(opndPtr, &length);
4698 * strtod() isn't at all consistent about detecting Inf and
4699 * NaN between platforms.
4702 if ((s[0]=='n' || s[0]=='N') && (s[1]=='a' || s[1]=='A') &&
4703 (s[2]=='n' || s[2]=='N')) {
4704 msg = "non-numeric floating-point value";
4705 goto makeErrorMessage;
4707 if ((s[0]=='i' || s[0]=='I') && (s[1]=='n' || s[1]=='N') &&
4708 (s[2]=='f' || s[2]=='F')) {
4709 msg = "infinite floating-point value";
4710 goto makeErrorMessage;
4715 * We cannot use TclLooksLikeInt here because it passes strings
4716 * like "10;" [Bug 587140]. We'll accept as "looking like ints"
4717 * for the present purposes any string that looks formally like
4718 * a (decimal|octal|hex) integer.
4721 while (length && isspace(UCHAR(*p))) {
4725 if (length && ((*p == '+') || (*p == '-'))) {
4730 if ((*p == '0') && ((*(p+1) == 'x') || (*(p+1) == 'X'))) {
4733 looksLikeInt = ((length > 0) && isxdigit(UCHAR(*p)));
4737 while (length && isxdigit(UCHAR(*p))) {
4743 looksLikeInt = (length && isdigit(UCHAR(*p)));
4747 while (length && isdigit(UCHAR(*p))) {
4753 while (length && isspace(UCHAR(*p))) {
4757 looksLikeInt = !length;
4761 * If something that looks like an integer could not be
4762 * converted, then it *must* be a bad octal or too large
4763 * to represent [Bug 542588].
4766 if (TclCheckBadOctal(NULL, s)) {
4767 msg = "invalid octal number";
4769 msg = "integer value too large to represent";
4770 Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
4771 "integer value too large to represent", (char *) NULL);
4775 * See if the operand can be interpreted as a double in
4776 * order to improve the error message.
4781 if (Tcl_GetDouble((Tcl_Interp *) NULL, s, &d) == TCL_OK) {
4782 msg = "floating-point value";
4786 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't use ",
4787 msg, " as operand of \"", operatorStrings[opCode - INST_LOR],
4788 "\"", (char *) NULL);
4793 *----------------------------------------------------------------------
4795 * TclGetSrcInfoForPc, GetSrcInfoForPc --
4797 * Given a program counter value, finds the closest command in the
4798 * bytecode code unit's CmdLocation array and returns information about
4799 * that command's source: a pointer to its first byte and the number of
4803 * If a command is found that encloses the program counter value, a
4804 * pointer to the command's source is returned and the length of the
4805 * source is stored at *lengthPtr. If multiple commands resulted in
4806 * code at pc, information about the closest enclosing command is
4807 * returned. If no matching command is found, NULL is returned and
4808 * *lengthPtr is unchanged.
4813 *----------------------------------------------------------------------
4818 TclGetSrcInfoForPc (cfPtr)
4821 ByteCode* codePtr = (ByteCode*) cfPtr->data.tebc.codePtr;
4823 if (cfPtr->cmd.str.cmd == NULL) {
4824 cfPtr->cmd.str.cmd = GetSrcInfoForPc((char*) cfPtr->data.tebc.pc,
4826 &cfPtr->cmd.str.len);
4829 if (cfPtr->cmd.str.cmd != NULL) {
4830 /* We now have the command. We can get the srcOffset back and
4831 * from there find the list of word locations for this command
4838 Interp* iPtr = (Interp*) *codePtr->interpHandle;
4839 Tcl_HashEntry* hePtr = Tcl_FindHashEntry (iPtr->lineBCPtr, (char *) codePtr);
4843 srcOffset = cfPtr->cmd.str.cmd - codePtr->source;
4844 eclPtr = (ExtCmdLoc*) Tcl_GetHashValue (hePtr);
4848 for (i=0; i < eclPtr->nuloc; i++) {
4849 if (eclPtr->loc [i].srcOffset == srcOffset) {
4850 locPtr = &(eclPtr->loc [i]);
4856 if (locPtr == NULL) {Tcl_Panic ("LocSearch failure");}
4858 cfPtr->line = locPtr->line;
4859 cfPtr->nline = locPtr->nline;
4860 cfPtr->type = eclPtr->type;
4862 if (eclPtr->type == TCL_LOCATION_SOURCE) {
4863 cfPtr->data.eval.path = eclPtr->path;
4864 Tcl_IncrRefCount (cfPtr->data.eval.path);
4866 /* Do not set cfPtr->data.eval.path NULL for non-SOURCE
4867 * Needed for cfPtr->data.tebc.codePtr.
4874 GetSrcInfoForPc(pc, codePtr, lengthPtr)
4875 unsigned char *pc; /* The program counter value for which to
4876 * return the closest command's source info.
4877 * This points to a bytecode instruction
4878 * in codePtr's code. */
4879 ByteCode *codePtr; /* The bytecode sequence in which to look
4880 * up the command source for the pc. */
4881 int *lengthPtr; /* If non-NULL, the location where the
4882 * length of the command's source should be
4883 * stored. If NULL, no length is stored. */
4885 register int pcOffset = (pc - codePtr->codeStart);
4886 int numCmds = codePtr->numCommands;
4887 unsigned char *codeDeltaNext, *codeLengthNext;
4888 unsigned char *srcDeltaNext, *srcLengthNext;
4889 int codeOffset, codeLen, codeEnd, srcOffset, srcLen, delta, i;
4890 int bestDist = INT_MAX; /* Distance of pc to best cmd's start pc. */
4891 int bestSrcOffset = -1; /* Initialized to avoid compiler warning. */
4892 int bestSrcLength = -1; /* Initialized to avoid compiler warning. */
4894 if ((pcOffset < 0) || (pcOffset >= codePtr->numCodeBytes)) {
4899 * Decode the code and source offset and length for each command. The
4900 * closest enclosing command is the last one whose code started before
4904 codeDeltaNext = codePtr->codeDeltaStart;
4905 codeLengthNext = codePtr->codeLengthStart;
4906 srcDeltaNext = codePtr->srcDeltaStart;
4907 srcLengthNext = codePtr->srcLengthStart;
4908 codeOffset = srcOffset = 0;
4909 for (i = 0; i < numCmds; i++) {
4910 if ((unsigned int) (*codeDeltaNext) == (unsigned int) 0xFF) {
4912 delta = TclGetInt4AtPtr(codeDeltaNext);
4915 delta = TclGetInt1AtPtr(codeDeltaNext);
4918 codeOffset += delta;
4920 if ((unsigned int) (*codeLengthNext) == (unsigned int) 0xFF) {
4922 codeLen = TclGetInt4AtPtr(codeLengthNext);
4923 codeLengthNext += 4;
4925 codeLen = TclGetInt1AtPtr(codeLengthNext);
4928 codeEnd = (codeOffset + codeLen - 1);
4930 if ((unsigned int) (*srcDeltaNext) == (unsigned int) 0xFF) {
4932 delta = TclGetInt4AtPtr(srcDeltaNext);
4935 delta = TclGetInt1AtPtr(srcDeltaNext);
4940 if ((unsigned int) (*srcLengthNext) == (unsigned int) 0xFF) {
4942 srcLen = TclGetInt4AtPtr(srcLengthNext);
4945 srcLen = TclGetInt1AtPtr(srcLengthNext);
4949 if (codeOffset > pcOffset) { /* best cmd already found */
4951 } else if (pcOffset <= codeEnd) { /* this cmd's code encloses pc */
4952 int dist = (pcOffset - codeOffset);
4953 if (dist <= bestDist) {
4955 bestSrcOffset = srcOffset;
4956 bestSrcLength = srcLen;
4961 if (bestDist == INT_MAX) {
4965 if (lengthPtr != NULL) {
4966 *lengthPtr = bestSrcLength;
4968 return (codePtr->source + bestSrcOffset);
4972 *----------------------------------------------------------------------
4974 * GetExceptRangeForPc --
4976 * Given a program counter value, return the closest enclosing
4980 * In the normal case, catchOnly is 0 (false) and this procedure
4981 * returns a pointer to the most closely enclosing ExceptionRange
4982 * structure regardless of whether it is a loop or catch exception
4983 * range. This is appropriate when processing a TCL_BREAK or
4984 * TCL_CONTINUE, which will be "handled" either by a loop exception
4985 * range or a closer catch range. If catchOnly is nonzero, this
4986 * procedure ignores loop exception ranges and returns a pointer to the
4987 * closest catch range. If no matching ExceptionRange is found that
4988 * encloses pc, a NULL is returned.
4993 *----------------------------------------------------------------------
4996 static ExceptionRange *
4997 GetExceptRangeForPc(pc, catchOnly, codePtr)
4998 unsigned char *pc; /* The program counter value for which to
4999 * search for a closest enclosing exception
5000 * range. This points to a bytecode
5001 * instruction in codePtr's code. */
5002 int catchOnly; /* If 0, consider either loop or catch
5003 * ExceptionRanges in search. If nonzero
5004 * consider only catch ranges (and ignore
5005 * any closer loop ranges). */
5006 ByteCode* codePtr; /* Points to the ByteCode in which to search
5007 * for the enclosing ExceptionRange. */
5009 ExceptionRange *rangeArrayPtr;
5010 int numRanges = codePtr->numExceptRanges;
5011 register ExceptionRange *rangePtr;
5012 int pcOffset = (pc - codePtr->codeStart);
5015 if (numRanges == 0) {
5020 * This exploits peculiarities of our compiler: nested ranges
5021 * are always *after* their containing ranges, so that by scanning
5022 * backwards we are sure that the first matching range is indeed
5026 rangeArrayPtr = codePtr->exceptArrayPtr;
5027 rangePtr = rangeArrayPtr + numRanges;
5028 while (--rangePtr >= rangeArrayPtr) {
5029 start = rangePtr->codeOffset;
5030 if ((start <= pcOffset) &&
5031 (pcOffset < (start + rangePtr->numCodeBytes))) {
5033 || (rangePtr->type == CATCH_EXCEPTION_RANGE)) {
5042 *----------------------------------------------------------------------
5046 * This procedure is called by the TRACE and TRACE_WITH_OBJ macros
5047 * used in TclExecuteByteCode when debugging. It returns the name of
5048 * the bytecode instruction at a specified instruction pc.
5051 * A character string for the instruction.
5056 *----------------------------------------------------------------------
5059 #ifdef TCL_COMPILE_DEBUG
5062 unsigned char *pc; /* Points to the instruction whose name
5063 * should be returned. */
5065 unsigned char opCode = *pc;
5067 return tclInstructionTable[opCode].name;
5069 #endif /* TCL_COMPILE_DEBUG */
5072 *----------------------------------------------------------------------
5074 * VerifyExprObjType --
5076 * This procedure is called by the math functions to verify that
5077 * the object is either an int or double, coercing it if necessary.
5078 * If an error occurs during conversion, an error message is left
5079 * in the interpreter's result unless "interp" is NULL.
5082 * TCL_OK if it was int or double, TCL_ERROR otherwise
5085 * objPtr is ensured to be of tclIntType, tclWideIntType or
5088 *----------------------------------------------------------------------
5092 VerifyExprObjType(interp, objPtr)
5093 Tcl_Interp *interp; /* The interpreter in which to execute the
5095 Tcl_Obj *objPtr; /* Points to the object to type check. */
5097 if (IS_NUMERIC_TYPE(objPtr->typePtr)) {
5100 int length, result = TCL_OK;
5101 char *s = Tcl_GetStringFromObj(objPtr, &length);
5103 if (TclLooksLikeInt(s, length)) {
5106 GET_WIDE_OR_INT(result, objPtr, i, w);
5109 result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, objPtr, &d);
5111 if ((result != TCL_OK) && (interp != NULL)) {
5112 Tcl_ResetResult(interp);
5113 if (TclCheckBadOctal((Tcl_Interp *) NULL, s)) {
5114 Tcl_AppendToObj(Tcl_GetObjResult(interp),
5115 "argument to math function was an invalid octal number",
5118 Tcl_AppendToObj(Tcl_GetObjResult(interp),
5119 "argument to math function didn't have numeric value",
5128 *----------------------------------------------------------------------
5132 * This page contains the procedures that implement all of the
5133 * built-in math functions for expressions.
5136 * Each procedure returns TCL_OK if it succeeds and pushes an
5137 * Tcl object holding the result. If it fails it returns TCL_ERROR
5138 * and leaves an error message in the interpreter's result.
5143 *----------------------------------------------------------------------
5147 ExprUnaryFunc(interp, eePtr, clientData)
5148 Tcl_Interp *interp; /* The interpreter in which to execute the
5150 ExecEnv *eePtr; /* Points to the environment for executing
5152 ClientData clientData; /* Contains the address of a procedure that
5153 * takes one double argument and returns a
5156 Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
5157 register int stackTop; /* Cached top index of evaluation stack. */
5158 register Tcl_Obj *valuePtr;
5162 double (*func) _ANSI_ARGS_((double)) =
5163 (double (*)_ANSI_ARGS_((double))) clientData;
5166 * Set stackPtr and stackTop from eePtr.
5173 * Pop the function's argument from the evaluation stack. Convert it
5174 * to a double if necessary.
5177 valuePtr = POP_OBJECT();
5179 if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
5184 GET_DOUBLE_VALUE(d, valuePtr, valuePtr->typePtr);
5187 dResult = (*func)(d);
5188 if ((errno != 0) || IS_NAN(dResult) || IS_INF(dResult)) {
5189 TclExprFloatError(interp, dResult);
5195 * Push a Tcl object holding the result.
5198 PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
5201 * Reflect the change to stackTop back in eePtr.
5205 TclDecrRefCount(valuePtr);
5206 DECACHE_STACK_INFO();
5211 ExprBinaryFunc(interp, eePtr, clientData)
5212 Tcl_Interp *interp; /* The interpreter in which to execute the
5214 ExecEnv *eePtr; /* Points to the environment for executing
5216 ClientData clientData; /* Contains the address of a procedure that
5217 * takes two double arguments and
5218 * returns a double result. */
5220 Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
5221 register int stackTop; /* Cached top index of evaluation stack. */
5222 register Tcl_Obj *valuePtr, *value2Ptr;
5223 double d1, d2, dResult;
5226 double (*func) _ANSI_ARGS_((double, double))
5227 = (double (*)_ANSI_ARGS_((double, double))) clientData;
5230 * Set stackPtr and stackTop from eePtr.
5237 * Pop the function's two arguments from the evaluation stack. Convert
5238 * them to doubles if necessary.
5241 value2Ptr = POP_OBJECT();
5242 valuePtr = POP_OBJECT();
5244 if ((VerifyExprObjType(interp, valuePtr) != TCL_OK) ||
5245 (VerifyExprObjType(interp, value2Ptr) != TCL_OK)) {
5250 GET_DOUBLE_VALUE(d1, valuePtr, valuePtr->typePtr);
5251 GET_DOUBLE_VALUE(d2, value2Ptr, value2Ptr->typePtr);
5254 dResult = (*func)(d1, d2);
5255 if ((errno != 0) || IS_NAN(dResult) || IS_INF(dResult)) {
5256 TclExprFloatError(interp, dResult);
5262 * Push a Tcl object holding the result.
5265 PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
5268 * Reflect the change to stackTop back in eePtr.
5272 TclDecrRefCount(valuePtr);
5273 TclDecrRefCount(value2Ptr);
5274 DECACHE_STACK_INFO();
5279 ExprAbsFunc(interp, eePtr, clientData)
5280 Tcl_Interp *interp; /* The interpreter in which to execute the
5282 ExecEnv *eePtr; /* Points to the environment for executing
5284 ClientData clientData; /* Ignored. */
5286 Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
5287 register int stackTop; /* Cached top index of evaluation stack. */
5288 register Tcl_Obj *valuePtr;
5294 * Set stackPtr and stackTop from eePtr.
5301 * Pop the argument from the evaluation stack.
5304 valuePtr = POP_OBJECT();
5306 if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
5312 * Push a Tcl object with the result.
5314 if (valuePtr->typePtr == &tclIntType) {
5315 i = valuePtr->internalRep.longValue;
5317 if (i == LONG_MIN) {
5318 #ifdef TCL_WIDE_INT_IS_LONG
5319 Tcl_SetObjResult(interp, Tcl_NewStringObj(
5320 "integer value too large to represent", -1));
5321 Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
5322 "integer value too large to represent", (char *) NULL);
5327 * Special case: abs(MIN_INT) must promote to wide.
5330 PUSH_OBJECT( Tcl_NewWideIntObj(-(Tcl_WideInt) i) );
5340 PUSH_OBJECT(Tcl_NewLongObj(iResult));
5341 } else if (valuePtr->typePtr == &tclWideIntType) {
5342 Tcl_WideInt wResult, w;
5343 TclGetWide(w,valuePtr);
5347 Tcl_ResetResult(interp);
5348 Tcl_AppendToObj(Tcl_GetObjResult(interp),
5349 "integer value too large to represent", -1);
5350 Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
5351 "integer value too large to represent", (char *) NULL);
5358 PUSH_OBJECT(Tcl_NewWideIntObj(wResult));
5360 d = valuePtr->internalRep.doubleValue;
5366 if (IS_NAN(dResult) || IS_INF(dResult)) {
5367 TclExprFloatError(interp, dResult);
5371 PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
5375 * Reflect the change to stackTop back in eePtr.
5379 TclDecrRefCount(valuePtr);
5380 DECACHE_STACK_INFO();
5385 ExprDoubleFunc(interp, eePtr, clientData)
5386 Tcl_Interp *interp; /* The interpreter in which to execute the
5388 ExecEnv *eePtr; /* Points to the environment for executing
5390 ClientData clientData; /* Ignored. */
5392 Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
5393 register int stackTop; /* Cached top index of evaluation stack. */
5394 register Tcl_Obj *valuePtr;
5399 * Set stackPtr and stackTop from eePtr.
5406 * Pop the argument from the evaluation stack.
5409 valuePtr = POP_OBJECT();
5411 if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
5416 GET_DOUBLE_VALUE(dResult, valuePtr, valuePtr->typePtr);
5419 * Push a Tcl object with the result.
5422 PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
5425 * Reflect the change to stackTop back in eePtr.
5429 TclDecrRefCount(valuePtr);
5430 DECACHE_STACK_INFO();
5435 ExprIntFunc(interp, eePtr, clientData)
5436 Tcl_Interp *interp; /* The interpreter in which to execute the
5438 ExecEnv *eePtr; /* Points to the environment for executing
5440 ClientData clientData; /* Ignored. */
5442 Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
5443 register int stackTop; /* Cached top index of evaluation stack. */
5444 register Tcl_Obj *valuePtr;
5450 * Set stackPtr and stackTop from eePtr.
5457 * Pop the argument from the evaluation stack.
5460 valuePtr = POP_OBJECT();
5462 if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
5467 if (valuePtr->typePtr == &tclIntType) {
5468 iResult = valuePtr->internalRep.longValue;
5469 } else if (valuePtr->typePtr == &tclWideIntType) {
5470 TclGetLongFromWide(iResult,valuePtr);
5472 d = valuePtr->internalRep.doubleValue;
5474 if (d < (double) (long) LONG_MIN) {
5476 Tcl_ResetResult(interp);
5477 Tcl_AppendToObj(Tcl_GetObjResult(interp),
5478 "integer value too large to represent", -1);
5479 Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
5480 "integer value too large to represent", (char *) NULL);
5485 if (d > (double) LONG_MAX) {
5489 if (IS_NAN(d) || IS_INF(d)) {
5490 TclExprFloatError(interp, d);
5498 * Push a Tcl object with the result.
5501 PUSH_OBJECT(Tcl_NewLongObj(iResult));
5504 * Reflect the change to stackTop back in eePtr.
5508 TclDecrRefCount(valuePtr);
5509 DECACHE_STACK_INFO();
5514 ExprWideFunc(interp, eePtr, clientData)
5515 Tcl_Interp *interp; /* The interpreter in which to execute the
5517 ExecEnv *eePtr; /* Points to the environment for executing
5519 ClientData clientData; /* Ignored. */
5521 Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
5522 register int stackTop; /* Cached top index of evaluation stack. */
5523 register Tcl_Obj *valuePtr;
5524 Tcl_WideInt wResult;
5529 * Set stackPtr and stackTop from eePtr.
5536 * Pop the argument from the evaluation stack.
5539 valuePtr = POP_OBJECT();
5541 if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
5546 if (valuePtr->typePtr == &tclWideIntType) {
5547 TclGetWide(wResult,valuePtr);
5548 } else if (valuePtr->typePtr == &tclIntType) {
5549 wResult = Tcl_LongAsWide(valuePtr->internalRep.longValue);
5551 d = valuePtr->internalRep.doubleValue;
5553 if (d < Tcl_WideAsDouble(LLONG_MIN)) {
5555 Tcl_ResetResult(interp);
5556 Tcl_AppendToObj(Tcl_GetObjResult(interp),
5557 "integer value too large to represent", -1);
5558 Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
5559 "integer value too large to represent", (char *) NULL);
5564 if (d > Tcl_WideAsDouble(LLONG_MAX)) {
5568 if (IS_NAN(d) || IS_INF(d)) {
5569 TclExprFloatError(interp, d);
5573 wResult = Tcl_DoubleAsWide(d);
5577 * Push a Tcl object with the result.
5580 PUSH_OBJECT(Tcl_NewWideIntObj(wResult));
5583 * Reflect the change to stackTop back in eePtr.
5587 TclDecrRefCount(valuePtr);
5588 DECACHE_STACK_INFO();
5593 ExprRandFunc(interp, eePtr, clientData)
5594 Tcl_Interp *interp; /* The interpreter in which to execute the
5596 ExecEnv *eePtr; /* Points to the environment for executing
5598 ClientData clientData; /* Ignored. */
5600 Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
5601 register int stackTop; /* Cached top index of evaluation stack. */
5602 Interp *iPtr = (Interp *) interp;
5604 long tmp; /* Algorithm assumes at least 32 bits.
5605 * Only long guarantees that. See below. */
5607 if (!(iPtr->flags & RAND_SEED_INITIALIZED)) {
5608 iPtr->flags |= RAND_SEED_INITIALIZED;
5611 * Take into consideration the thread this interp is running in order
5612 * to insure different seeds in different threads (bug #416643)
5615 iPtr->randSeed = TclpGetClicks() + ((long)Tcl_GetCurrentThread()<<12);
5618 * Make sure 1 <= randSeed <= (2^31) - 2. See below.
5621 iPtr->randSeed &= (unsigned long) 0x7fffffff;
5622 if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
5623 iPtr->randSeed ^= 123459876;
5628 * Set stackPtr and stackTop from eePtr.
5634 * Generate the random number using the linear congruential
5635 * generator defined by the following recurrence:
5636 * seed = ( IA * seed ) mod IM
5637 * where IA is 16807 and IM is (2^31) - 1. The recurrence maps
5638 * a seed in the range [1, IM - 1] to a new seed in that same range.
5639 * The recurrence maps IM to 0, and maps 0 back to 0, so those two
5640 * values must not be allowed as initial values of seed.
5642 * In order to avoid potential problems with integer overflow, the
5643 * recurrence is implemented in terms of additional constants
5644 * IQ and IR such that
5646 * None of the operations in the implementation overflows a 32-bit
5647 * signed integer, and the C type long is guaranteed to be at least
5650 * For more details on how this algorithm works, refer to the following
5653 * S.K. Park & K.W. Miller, "Random number generators: good ones
5654 * are hard to find," Comm ACM 31(10):1192-1201, Oct 1988
5656 * W.H. Press & S.A. Teukolsky, "Portable random number
5657 * generators," Computers in Physics 6(5):522-524, Sep/Oct 1992.
5660 #define RAND_IA 16807
5661 #define RAND_IM 2147483647
5662 #define RAND_IQ 127773
5663 #define RAND_IR 2836
5664 #define RAND_MASK 123459876
5666 tmp = iPtr->randSeed/RAND_IQ;
5667 iPtr->randSeed = RAND_IA*(iPtr->randSeed - tmp*RAND_IQ) - RAND_IR*tmp;
5668 if (iPtr->randSeed < 0) {
5669 iPtr->randSeed += RAND_IM;
5673 * Since the recurrence keeps seed values in the range [1, RAND_IM - 1],
5674 * dividing by RAND_IM yields a double in the range (0, 1).
5677 dResult = iPtr->randSeed * (1.0/RAND_IM);
5680 * Push a Tcl object with the result.
5683 PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
5686 * Reflect the change to stackTop back in eePtr.
5689 DECACHE_STACK_INFO();
5694 ExprRoundFunc(interp, eePtr, clientData)
5695 Tcl_Interp *interp; /* The interpreter in which to execute the
5697 ExecEnv *eePtr; /* Points to the environment for executing
5699 ClientData clientData; /* Ignored. */
5701 Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
5702 register int stackTop; /* Cached top index of evaluation stack. */
5703 Tcl_Obj *valuePtr, *resPtr;
5708 * Set stackPtr and stackTop from eePtr.
5715 * Pop the argument from the evaluation stack.
5718 valuePtr = POP_OBJECT();
5720 if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
5725 if ((valuePtr->typePtr == &tclIntType) ||
5726 (valuePtr->typePtr == &tclWideIntType)) {
5732 * Round the number to the nearest integer. I'd like to use round(),
5733 * but it's C99 (or BSD), and not yet universal.
5736 d = valuePtr->internalRep.doubleValue;
5742 if (i <= Tcl_WideAsDouble(LLONG_MIN)) {
5744 } else if (i <= (double) LONG_MIN) {
5745 resPtr = Tcl_NewWideIntObj(Tcl_DoubleAsWide(i));
5747 resPtr = Tcl_NewLongObj((long) i);
5753 if (i >= Tcl_WideAsDouble(LLONG_MAX)) {
5755 } else if (i >= (double) LONG_MAX) {
5756 resPtr = Tcl_NewWideIntObj(Tcl_DoubleAsWide(i));
5758 resPtr = Tcl_NewLongObj((long) i);
5764 * Push the result object and free the argument Tcl_Obj.
5767 PUSH_OBJECT(resPtr);
5770 TclDecrRefCount(valuePtr);
5771 DECACHE_STACK_INFO();
5775 * Error return: result cannot be represented as an integer.
5779 Tcl_ResetResult(interp);
5780 Tcl_AppendToObj(Tcl_GetObjResult(interp),
5781 "integer value too large to represent", -1);
5782 Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
5783 "integer value too large to represent",
5790 ExprSrandFunc(interp, eePtr, clientData)
5791 Tcl_Interp *interp; /* The interpreter in which to execute the
5793 ExecEnv *eePtr; /* Points to the environment for executing
5795 ClientData clientData; /* Ignored. */
5797 Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
5798 register int stackTop; /* Cached top index of evaluation stack. */
5799 Interp *iPtr = (Interp *) interp;
5801 long i = 0; /* Initialized to avoid compiler warning. */
5804 * Set stackPtr and stackTop from eePtr.
5810 * Pop the argument from the evaluation stack. Use the value
5811 * to reset the random number seed.
5814 valuePtr = POP_OBJECT();
5816 if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
5820 if (Tcl_GetLongFromObj(NULL, valuePtr, &i) != TCL_OK) {
5823 if (Tcl_GetWideIntFromObj(interp, valuePtr, &w) != TCL_OK) {
5825 Tcl_AddErrorInfo(interp, "\n (argument to \"srand()\")");
5826 TclDecrRefCount(valuePtr);
5827 DECACHE_STACK_INFO();
5831 i = Tcl_WideAsLong(w);
5835 * Reset the seed. Make sure 1 <= randSeed <= 2^31 - 2.
5836 * See comments in ExprRandFunc() for more details.
5839 iPtr->flags |= RAND_SEED_INITIALIZED;
5841 iPtr->randSeed &= (unsigned long) 0x7fffffff;
5842 if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
5843 iPtr->randSeed ^= 123459876;
5847 * To avoid duplicating the random number generation code we simply
5848 * clean up our state and call the real random number function. That
5849 * function will always succeed.
5852 TclDecrRefCount(valuePtr);
5853 DECACHE_STACK_INFO();
5855 ExprRandFunc(interp, eePtr, clientData);
5860 *----------------------------------------------------------------------
5862 * ExprCallMathFunc --
5864 * This procedure is invoked to call a non-builtin math function
5865 * during the execution of an expression.
5868 * TCL_OK is returned if all went well and the function's value
5869 * was computed successfully. If an error occurred, TCL_ERROR
5870 * is returned and an error message is left in the interpreter's
5871 * result. After a successful return this procedure pushes a Tcl object
5872 * holding the result.
5875 * None, unless the called math function has side effects.
5877 *----------------------------------------------------------------------
5881 ExprCallMathFunc(interp, eePtr, objc, objv)
5882 Tcl_Interp *interp; /* The interpreter in which to execute the
5884 ExecEnv *eePtr; /* Points to the environment for executing
5886 int objc; /* Number of arguments. The function name is
5887 * the 0-th argument. */
5888 Tcl_Obj **objv; /* The array of arguments. The function name
5891 Interp *iPtr = (Interp *) interp;
5892 Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
5893 register int stackTop; /* Cached top index of evaluation stack. */
5895 Tcl_HashEntry *hPtr;
5896 MathFunc *mathFuncPtr; /* Information about math function. */
5897 Tcl_Value args[MAX_MATH_ARGS]; /* Arguments for function call. */
5898 Tcl_Value funcResult; /* Result of function call as Tcl_Value. */
5899 register Tcl_Obj *valuePtr;
5904 Tcl_ResetResult(interp);
5907 * Set stackPtr and stackTop from eePtr.
5913 * Look up the MathFunc record for the function.
5916 funcName = TclGetString(objv[0]);
5917 hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
5919 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
5920 "unknown math function \"", funcName, "\"", (char *) NULL);
5924 mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
5925 if (mathFuncPtr->numArgs != (objc-1)) {
5926 panic("ExprCallMathFunc: expected number of args %d != actual number %d",
5927 mathFuncPtr->numArgs, objc);
5933 * Collect the arguments for the function, if there are any, into the
5934 * array "args". Note that args[0] will have the Tcl_Value that
5935 * corresponds to objv[1].
5938 for (j = 1, k = 0; j < objc; j++, k++) {
5941 if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
5947 * Copy the object's numeric value to the argument record,
5948 * converting it if necessary.
5951 if (valuePtr->typePtr == &tclIntType) {
5952 i = valuePtr->internalRep.longValue;
5953 if (mathFuncPtr->argTypes[k] == TCL_DOUBLE) {
5954 args[k].type = TCL_DOUBLE;
5955 args[k].doubleValue = i;
5956 } else if (mathFuncPtr->argTypes[k] == TCL_WIDE_INT) {
5957 args[k].type = TCL_WIDE_INT;
5958 args[k].wideValue = Tcl_LongAsWide(i);
5960 args[k].type = TCL_INT;
5961 args[k].intValue = i;
5963 } else if (valuePtr->typePtr == &tclWideIntType) {
5965 TclGetWide(w,valuePtr);
5966 if (mathFuncPtr->argTypes[k] == TCL_DOUBLE) {
5967 args[k].type = TCL_DOUBLE;
5968 args[k].doubleValue = Tcl_WideAsDouble(w);
5969 } else if (mathFuncPtr->argTypes[k] == TCL_INT) {
5970 args[k].type = TCL_INT;
5971 args[k].intValue = Tcl_WideAsLong(w);
5973 args[k].type = TCL_WIDE_INT;
5974 args[k].wideValue = w;
5977 d = valuePtr->internalRep.doubleValue;
5978 if (mathFuncPtr->argTypes[k] == TCL_INT) {
5979 args[k].type = TCL_INT;
5980 args[k].intValue = (long) d;
5981 } else if (mathFuncPtr->argTypes[k] == TCL_WIDE_INT) {
5982 args[k].type = TCL_WIDE_INT;
5983 args[k].wideValue = Tcl_DoubleAsWide(d);
5985 args[k].type = TCL_DOUBLE;
5986 args[k].doubleValue = d;
5992 * Invoke the function and copy its result back into valuePtr.
5995 result = (*mathFuncPtr->proc)(mathFuncPtr->clientData, interp, args,
5997 if (result != TCL_OK) {
6002 * Pop the objc top stack elements and decrement their ref counts.
6005 k = (stackTop - (objc-1));
6006 while (stackTop >= k) {
6007 valuePtr = POP_OBJECT();
6008 TclDecrRefCount(valuePtr);
6012 * Push the call's object result.
6015 if (funcResult.type == TCL_INT) {
6016 PUSH_OBJECT(Tcl_NewLongObj(funcResult.intValue));
6017 } else if (funcResult.type == TCL_WIDE_INT) {
6018 PUSH_OBJECT(Tcl_NewWideIntObj(funcResult.wideValue));
6020 d = funcResult.doubleValue;
6021 if (IS_NAN(d) || IS_INF(d)) {
6022 TclExprFloatError(interp, d);
6026 PUSH_OBJECT(Tcl_NewDoubleObj(d));
6030 * Reflect the change to stackTop back in eePtr.
6034 DECACHE_STACK_INFO();
6039 *----------------------------------------------------------------------
6041 * TclExprFloatError --
6043 * This procedure is called when an error occurs during a
6044 * floating-point operation. It reads errno and sets
6045 * interp->objResultPtr accordingly.
6048 * interp->objResultPtr is set to hold an error message.
6053 *----------------------------------------------------------------------
6057 TclExprFloatError(interp, value)
6058 Tcl_Interp *interp; /* Where to store error message. */
6059 double value; /* Value returned after error; used to
6060 * distinguish underflows from overflows. */
6064 Tcl_ResetResult(interp);
6065 if ((errno == EDOM) || IS_NAN(value)) {
6066 s = "domain error: argument not in valid range";
6067 Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
6068 Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", s, (char *) NULL);
6069 } else if ((errno == ERANGE) || IS_INF(value)) {
6071 s = "floating-point value too small to represent";
6072 Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
6073 Tcl_SetErrorCode(interp, "ARITH", "UNDERFLOW", s, (char *) NULL);
6075 s = "floating-point value too large to represent";
6076 Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
6077 Tcl_SetErrorCode(interp, "ARITH", "OVERFLOW", s, (char *) NULL);
6080 char msg[64 + TCL_INTEGER_SPACE];
6082 sprintf(msg, "unknown floating-point error, errno = %d", errno);
6083 Tcl_AppendToObj(Tcl_GetObjResult(interp), msg, -1);
6084 Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN", msg, (char *) NULL);
6088 #ifdef TCL_COMPILE_STATS
6090 *----------------------------------------------------------------------
6094 * Procedure used while collecting compilation statistics to determine
6095 * the log base 2 of an integer.
6098 * Returns the log base 2 of the operand. If the argument is less
6099 * than or equal to zero, a zero is returned.
6104 *----------------------------------------------------------------------
6109 register int value; /* The integer for which to compute the
6112 register int n = value;
6113 register int result = 0;
6123 *----------------------------------------------------------------------
6127 * Implements the "evalstats" command that prints instruction execution
6131 * Standard Tcl results.
6136 *----------------------------------------------------------------------
6140 EvalStatsCmd(unused, interp, objc, objv)
6141 ClientData unused; /* Unused. */
6142 Tcl_Interp *interp; /* The current interpreter. */
6143 int objc; /* The number of arguments. */
6144 Tcl_Obj *CONST objv[]; /* The argument strings. */
6146 Interp *iPtr = (Interp *) interp;
6147 LiteralTable *globalTablePtr = &(iPtr->literalTable);
6148 ByteCodeStats *statsPtr = &(iPtr->stats);
6149 double totalCodeBytes, currentCodeBytes;
6150 double totalLiteralBytes, currentLiteralBytes;
6151 double objBytesIfUnshared, strBytesIfUnshared, sharingBytesSaved;
6152 double strBytesSharedMultX, strBytesSharedOnce;
6153 double numInstructions, currentHeaderBytes;
6154 long numCurrentByteCodes, numByteCodeLits;
6155 long refCountSum, literalMgmtBytes, sum;
6156 int numSharedMultX, numSharedOnce;
6157 int decadeHigh, minSizeDecade, maxSizeDecade, length, i;
6158 char *litTableStats;
6159 LiteralEntry *entryPtr;
6161 numInstructions = 0.0;
6162 for (i = 0; i < 256; i++) {
6163 if (statsPtr->instructionCount[i] != 0) {
6164 numInstructions += statsPtr->instructionCount[i];
6168 totalLiteralBytes = sizeof(LiteralTable)
6169 + iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)
6170 + (statsPtr->numLiteralsCreated * sizeof(LiteralEntry))
6171 + (statsPtr->numLiteralsCreated * sizeof(Tcl_Obj))
6172 + statsPtr->totalLitStringBytes;
6173 totalCodeBytes = statsPtr->totalByteCodeBytes + totalLiteralBytes;
6175 numCurrentByteCodes =
6176 statsPtr->numCompilations - statsPtr->numByteCodesFreed;
6177 currentHeaderBytes = numCurrentByteCodes
6178 * (sizeof(ByteCode) - (sizeof(size_t) + sizeof(Tcl_Time)));
6179 literalMgmtBytes = sizeof(LiteralTable)
6180 + (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *))
6181 + (iPtr->literalTable.numEntries * sizeof(LiteralEntry));
6182 currentLiteralBytes = literalMgmtBytes
6183 + iPtr->literalTable.numEntries * sizeof(Tcl_Obj)
6184 + statsPtr->currentLitStringBytes;
6185 currentCodeBytes = statsPtr->currentByteCodeBytes + currentLiteralBytes;
6188 * Summary statistics, total and current source and ByteCode sizes.
6191 fprintf(stdout, "\n----------------------------------------------------------------\n");
6193 "Compilation and execution statistics for interpreter 0x%x\n",
6194 (unsigned int) iPtr);
6196 fprintf(stdout, "\nNumber ByteCodes executed %ld\n",
6197 statsPtr->numExecutions);
6198 fprintf(stdout, "Number ByteCodes compiled %ld\n",
6199 statsPtr->numCompilations);
6200 fprintf(stdout, " Mean executions/compile %.1f\n",
6201 ((float)statsPtr->numExecutions) / ((float)statsPtr->numCompilations));
6203 fprintf(stdout, "\nInstructions executed %.0f\n",
6205 fprintf(stdout, " Mean inst/compile %.0f\n",
6206 numInstructions / statsPtr->numCompilations);
6207 fprintf(stdout, " Mean inst/execution %.0f\n",
6208 numInstructions / statsPtr->numExecutions);
6210 fprintf(stdout, "\nTotal ByteCodes %ld\n",
6211 statsPtr->numCompilations);
6212 fprintf(stdout, " Source bytes %.6g\n",
6213 statsPtr->totalSrcBytes);
6214 fprintf(stdout, " Code bytes %.6g\n",
6216 fprintf(stdout, " ByteCode bytes %.6g\n",
6217 statsPtr->totalByteCodeBytes);
6218 fprintf(stdout, " Literal bytes %.6g\n",
6220 fprintf(stdout, " table %d + bkts %d + entries %ld + objects %ld + strings %.6g\n",
6221 sizeof(LiteralTable),
6222 iPtr->literalTable.numBuckets * sizeof(LiteralEntry *),
6223 statsPtr->numLiteralsCreated * sizeof(LiteralEntry),
6224 statsPtr->numLiteralsCreated * sizeof(Tcl_Obj),
6225 statsPtr->totalLitStringBytes);
6226 fprintf(stdout, " Mean code/compile %.1f\n",
6227 totalCodeBytes / statsPtr->numCompilations);
6228 fprintf(stdout, " Mean code/source %.1f\n",
6229 totalCodeBytes / statsPtr->totalSrcBytes);
6231 fprintf(stdout, "\nCurrent (active) ByteCodes %ld\n",
6232 numCurrentByteCodes);
6233 fprintf(stdout, " Source bytes %.6g\n",
6234 statsPtr->currentSrcBytes);
6235 fprintf(stdout, " Code bytes %.6g\n",
6237 fprintf(stdout, " ByteCode bytes %.6g\n",
6238 statsPtr->currentByteCodeBytes);
6239 fprintf(stdout, " Literal bytes %.6g\n",
6240 currentLiteralBytes);
6241 fprintf(stdout, " table %d + bkts %d + entries %d + objects %d + strings %.6g\n",
6242 sizeof(LiteralTable),
6243 iPtr->literalTable.numBuckets * sizeof(LiteralEntry *),
6244 iPtr->literalTable.numEntries * sizeof(LiteralEntry),
6245 iPtr->literalTable.numEntries * sizeof(Tcl_Obj),
6246 statsPtr->currentLitStringBytes);
6247 fprintf(stdout, " Mean code/source %.1f\n",
6248 currentCodeBytes / statsPtr->currentSrcBytes);
6249 fprintf(stdout, " Code + source bytes %.6g (%0.1f mean code/src)\n",
6250 (currentCodeBytes + statsPtr->currentSrcBytes),
6251 (currentCodeBytes / statsPtr->currentSrcBytes) + 1.0);
6254 * Tcl_IsShared statistics check
6256 * This gives the refcount of each obj as Tcl_IsShared was called
6257 * for it. Shared objects must be duplicated before they can be
6262 fprintf(stdout, "\nTcl_IsShared object check (all objects):\n");
6263 fprintf(stdout, " Object had refcount <=1 (not shared) %ld\n",
6265 for (i = 2; i < TCL_MAX_SHARED_OBJ_STATS; i++) {
6266 fprintf(stdout, " refcount ==%d %ld\n",
6267 i, tclObjsShared[i]);
6268 numSharedMultX += tclObjsShared[i];
6270 fprintf(stdout, " refcount >=%d %ld\n",
6271 i, tclObjsShared[0]);
6272 numSharedMultX += tclObjsShared[0];
6273 fprintf(stdout, " Total shared objects %d\n",
6277 * Literal table statistics.
6280 numByteCodeLits = 0;
6284 objBytesIfUnshared = 0.0;
6285 strBytesIfUnshared = 0.0;
6286 strBytesSharedMultX = 0.0;
6287 strBytesSharedOnce = 0.0;
6288 for (i = 0; i < globalTablePtr->numBuckets; i++) {
6289 for (entryPtr = globalTablePtr->buckets[i]; entryPtr != NULL;
6290 entryPtr = entryPtr->nextPtr) {
6291 if (entryPtr->objPtr->typePtr == &tclByteCodeType) {
6294 (void) Tcl_GetStringFromObj(entryPtr->objPtr, &length);
6295 refCountSum += entryPtr->refCount;
6296 objBytesIfUnshared += (entryPtr->refCount * sizeof(Tcl_Obj));
6297 strBytesIfUnshared += (entryPtr->refCount * (length+1));
6298 if (entryPtr->refCount > 1) {
6300 strBytesSharedMultX += (length+1);
6303 strBytesSharedOnce += (length+1);
6307 sharingBytesSaved = (objBytesIfUnshared + strBytesIfUnshared)
6308 - currentLiteralBytes;
6310 fprintf(stdout, "\nTotal objects (all interps) %ld\n",
6312 fprintf(stdout, "Current objects %ld\n",
6313 (tclObjsAlloced - tclObjsFreed));
6314 fprintf(stdout, "Total literal objects %ld\n",
6315 statsPtr->numLiteralsCreated);
6317 fprintf(stdout, "\nCurrent literal objects %d (%0.1f%% of current objects)\n",
6318 globalTablePtr->numEntries,
6319 (globalTablePtr->numEntries * 100.0) / (tclObjsAlloced-tclObjsFreed));
6320 fprintf(stdout, " ByteCode literals %ld (%0.1f%% of current literals)\n",
6322 (numByteCodeLits * 100.0) / globalTablePtr->numEntries);
6323 fprintf(stdout, " Literals reused > 1x %d\n",
6325 fprintf(stdout, " Mean reference count %.2f\n",
6326 ((double) refCountSum) / globalTablePtr->numEntries);
6327 fprintf(stdout, " Mean len, str reused >1x %.2f\n",
6328 (numSharedMultX? (strBytesSharedMultX/numSharedMultX) : 0.0));
6329 fprintf(stdout, " Mean len, str used 1x %.2f\n",
6330 (numSharedOnce? (strBytesSharedOnce/numSharedOnce) : 0.0));
6331 fprintf(stdout, " Total sharing savings %.6g (%0.1f%% of bytes if no sharing)\n",
6333 (sharingBytesSaved * 100.0) / (objBytesIfUnshared + strBytesIfUnshared));
6334 fprintf(stdout, " Bytes with sharing %.6g\n",
6335 currentLiteralBytes);
6336 fprintf(stdout, " table %d + bkts %d + entries %d + objects %d + strings %.6g\n",
6337 sizeof(LiteralTable),
6338 iPtr->literalTable.numBuckets * sizeof(LiteralEntry *),
6339 iPtr->literalTable.numEntries * sizeof(LiteralEntry),
6340 iPtr->literalTable.numEntries * sizeof(Tcl_Obj),
6341 statsPtr->currentLitStringBytes);
6342 fprintf(stdout, " Bytes if no sharing %.6g = objects %.6g + strings %.6g\n",
6343 (objBytesIfUnshared + strBytesIfUnshared),
6344 objBytesIfUnshared, strBytesIfUnshared);
6345 fprintf(stdout, " String sharing savings %.6g = unshared %.6g - shared %.6g\n",
6346 (strBytesIfUnshared - statsPtr->currentLitStringBytes),
6347 strBytesIfUnshared, statsPtr->currentLitStringBytes);
6348 fprintf(stdout, " Literal mgmt overhead %ld (%0.1f%% of bytes with sharing)\n",
6350 (literalMgmtBytes * 100.0) / currentLiteralBytes);
6351 fprintf(stdout, " table %d + buckets %d + entries %d\n",
6352 sizeof(LiteralTable),
6353 iPtr->literalTable.numBuckets * sizeof(LiteralEntry *),
6354 iPtr->literalTable.numEntries * sizeof(LiteralEntry));
6357 * Breakdown of current ByteCode space requirements.
6360 fprintf(stdout, "\nBreakdown of current ByteCode requirements:\n");
6361 fprintf(stdout, " Bytes Pct of Avg per\n");
6362 fprintf(stdout, " total ByteCode\n");
6363 fprintf(stdout, "Total %12.6g 100.00%% %8.1f\n",
6364 statsPtr->currentByteCodeBytes,
6365 statsPtr->currentByteCodeBytes / numCurrentByteCodes);
6366 fprintf(stdout, "Header %12.6g %8.1f%% %8.1f\n",
6368 ((currentHeaderBytes * 100.0) / statsPtr->currentByteCodeBytes),
6369 currentHeaderBytes / numCurrentByteCodes);
6370 fprintf(stdout, "Instructions %12.6g %8.1f%% %8.1f\n",
6371 statsPtr->currentInstBytes,
6372 ((statsPtr->currentInstBytes * 100.0) / statsPtr->currentByteCodeBytes),
6373 statsPtr->currentInstBytes / numCurrentByteCodes);
6374 fprintf(stdout, "Literal ptr array %12.6g %8.1f%% %8.1f\n",
6375 statsPtr->currentLitBytes,
6376 ((statsPtr->currentLitBytes * 100.0) / statsPtr->currentByteCodeBytes),
6377 statsPtr->currentLitBytes / numCurrentByteCodes);
6378 fprintf(stdout, "Exception table %12.6g %8.1f%% %8.1f\n",
6379 statsPtr->currentExceptBytes,
6380 ((statsPtr->currentExceptBytes * 100.0) / statsPtr->currentByteCodeBytes),
6381 statsPtr->currentExceptBytes / numCurrentByteCodes);
6382 fprintf(stdout, "Auxiliary data %12.6g %8.1f%% %8.1f\n",
6383 statsPtr->currentAuxBytes,
6384 ((statsPtr->currentAuxBytes * 100.0) / statsPtr->currentByteCodeBytes),
6385 statsPtr->currentAuxBytes / numCurrentByteCodes);
6386 fprintf(stdout, "Command map %12.6g %8.1f%% %8.1f\n",
6387 statsPtr->currentCmdMapBytes,
6388 ((statsPtr->currentCmdMapBytes * 100.0) / statsPtr->currentByteCodeBytes),
6389 statsPtr->currentCmdMapBytes / numCurrentByteCodes);
6392 * Detailed literal statistics.
6395 fprintf(stdout, "\nLiteral string sizes:\n");
6396 fprintf(stdout, " Up to length Percentage\n");
6398 for (i = 31; i >= 0; i--) {
6399 if (statsPtr->literalCount[i] > 0) {
6405 for (i = 0; i <= maxSizeDecade; i++) {
6406 decadeHigh = (1 << (i+1)) - 1;
6407 sum += statsPtr->literalCount[i];
6408 fprintf(stdout, " %10d %8.0f%%\n",
6409 decadeHigh, (sum * 100.0) / statsPtr->numLiteralsCreated);
6412 litTableStats = TclLiteralStats(globalTablePtr);
6413 fprintf(stdout, "\nCurrent literal table statistics:\n%s\n",
6415 ckfree((char *) litTableStats);
6418 * Source and ByteCode size distributions.
6421 fprintf(stdout, "\nSource sizes:\n");
6422 fprintf(stdout, " Up to size Percentage\n");
6423 minSizeDecade = maxSizeDecade = 0;
6424 for (i = 0; i < 31; i++) {
6425 if (statsPtr->srcCount[i] > 0) {
6430 for (i = 31; i >= 0; i--) {
6431 if (statsPtr->srcCount[i] > 0) {
6437 for (i = minSizeDecade; i <= maxSizeDecade; i++) {
6438 decadeHigh = (1 << (i+1)) - 1;
6439 sum += statsPtr->srcCount[i];
6440 fprintf(stdout, " %10d %8.0f%%\n",
6441 decadeHigh, (sum * 100.0) / statsPtr->numCompilations);
6444 fprintf(stdout, "\nByteCode sizes:\n");
6445 fprintf(stdout, " Up to size Percentage\n");
6446 minSizeDecade = maxSizeDecade = 0;
6447 for (i = 0; i < 31; i++) {
6448 if (statsPtr->byteCodeCount[i] > 0) {
6453 for (i = 31; i >= 0; i--) {
6454 if (statsPtr->byteCodeCount[i] > 0) {
6460 for (i = minSizeDecade; i <= maxSizeDecade; i++) {
6461 decadeHigh = (1 << (i+1)) - 1;
6462 sum += statsPtr->byteCodeCount[i];
6463 fprintf(stdout, " %10d %8.0f%%\n",
6464 decadeHigh, (sum * 100.0) / statsPtr->numCompilations);
6467 fprintf(stdout, "\nByteCode longevity (excludes Current ByteCodes):\n");
6468 fprintf(stdout, " Up to ms Percentage\n");
6469 minSizeDecade = maxSizeDecade = 0;
6470 for (i = 0; i < 31; i++) {
6471 if (statsPtr->lifetimeCount[i] > 0) {
6476 for (i = 31; i >= 0; i--) {
6477 if (statsPtr->lifetimeCount[i] > 0) {
6483 for (i = minSizeDecade; i <= maxSizeDecade; i++) {
6484 decadeHigh = (1 << (i+1)) - 1;
6485 sum += statsPtr->lifetimeCount[i];
6486 fprintf(stdout, " %12.3f %8.0f%%\n",
6487 decadeHigh / 1000.0,
6488 (sum * 100.0) / statsPtr->numByteCodesFreed);
6492 * Instruction counts.
6495 fprintf(stdout, "\nInstruction counts:\n");
6496 for (i = 0; i <= LAST_INST_OPCODE; i++) {
6497 if (statsPtr->instructionCount[i]) {
6498 fprintf(stdout, "%20s %8ld %6.1f%%\n",
6499 tclInstructionTable[i].name,
6500 statsPtr->instructionCount[i],
6501 (statsPtr->instructionCount[i]*100.0) / numInstructions);
6505 fprintf(stdout, "\nInstructions NEVER executed:\n");
6506 for (i = 0; i <= LAST_INST_OPCODE; i++) {
6507 if (statsPtr->instructionCount[i] == 0) {
6508 fprintf(stdout, "%20s\n", tclInstructionTable[i].name);
6512 #ifdef TCL_MEM_DEBUG
6513 fprintf(stdout, "\nHeap Statistics:\n");
6514 TclDumpMemoryInfo(stdout);
6516 fprintf(stdout, "\n----------------------------------------------------------------\n");
6519 #endif /* TCL_COMPILE_STATS */
6521 #ifdef TCL_COMPILE_DEBUG
6523 *----------------------------------------------------------------------
6525 * StringForResultCode --
6527 * Procedure that returns a human-readable string representing a
6528 * Tcl result code such as TCL_ERROR.
6531 * If the result code is one of the standard Tcl return codes, the
6532 * result is a string representing that code such as "TCL_ERROR".
6533 * Otherwise, the result string is that code formatted as a
6534 * sequence of decimal digit characters. Note that the resulting
6535 * string must not be modified by the caller.
6540 *----------------------------------------------------------------------
6544 StringForResultCode(result)
6545 int result; /* The Tcl result code for which to
6546 * generate a string. */
6548 static char buf[TCL_INTEGER_SPACE];
6550 if ((result >= TCL_OK) && (result <= TCL_CONTINUE)) {
6551 return resultStrings[result];
6553 TclFormatInt(buf, result);
6556 #endif /* TCL_COMPILE_DEBUG */