Subversion Repositories Open64

[/] [sim/] [fsim/] [shell/] [tclsh/] [generic/] [tclExecute.c] - Blame information for rev 2072

Details | Compare with Previous | View Log

<
Line No. Rev Author Line
1 2072 malin
/*
2
 * tclExecute.c --
3
 *
4
 *  This file contains procedures that execute byte-compiled Tcl
5
 *  commands.
6
 *
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
 *
11
 * See the file "license.terms" for information on usage and redistribution
12
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13
 *
14
 * RCS: @(#) $Id: tclExecute.c,v 1.94.2.18 2005/12/12 11:28:22 rmax Exp $
15
 */
16
 
17
#include "tclInt.h"
18
#include "tclCompile.h"
19
 
20
#ifndef TCL_NO_MATH
21
#   include "tclMath.h"
22
#endif
23
 
24
/*
25
 * The stuff below is a bit of a hack so that this file can be used
26
 * in environments that include no UNIX, i.e. no errno.  Just define
27
 * errno here.
28
 */
29
 
30
#ifndef TCL_GENERIC_ONLY
31
#   include "tclPort.h"
32
#else /* TCL_GENERIC_ONLY */
33
#   ifndef NO_FLOAT_H
34
# include <float.h>
35
#   else /* NO_FLOAT_H */
36
# ifndef NO_VALUES_H
37
#     include <values.h>
38
# endif /* !NO_VALUES_H */
39
#   endif /* !NO_FLOAT_H */
40
#   define NO_ERRNO_H
41
#endif /* !TCL_GENERIC_ONLY */
42
 
43
#ifdef NO_ERRNO_H
44
int errno;
45
#   define EDOM   33
46
#   define ERANGE 34
47
#endif
48
 
49
/*
50
 * Need DBL_MAX for IS_INF() macro...
51
 */
52
#ifndef DBL_MAX
53
#   ifdef MAXDOUBLE
54
# define DBL_MAX MAXDOUBLE
55
#   else /* !MAXDOUBLE */
56
/*
57
 * This value is from the Solaris headers, but doubles seem to be the
58
 * same size everywhere.  Long doubles aren't, but we don't use those.
59
 */
60
# define DBL_MAX 1.79769313486231570e+308
61
#   endif /* MAXDOUBLE */
62
#endif /* !DBL_MAX */
63
 
64
/*
65
 * Boolean flag indicating whether the Tcl bytecode interpreter has been
66
 * initialized.
67
 */
68
 
69
static int execInitialized = 0;
70
TCL_DECLARE_MUTEX(execMutex)
71
 
72
#ifdef TCL_COMPILE_DEBUG
73
/*
74
 * Variable that controls whether execution tracing is enabled and, if so,
75
 * what level of tracing is desired:
76
 *    0: no execution tracing
77
 *    1: trace invocations of Tcl procs only
78
 *    2: trace invocations of all (not compiled away) commands
79
 *    3: display each instruction executed
80
 * This variable is linked to the Tcl variable "tcl_traceExec".
81
 */
82
 
83
int tclTraceExec = 0;
84
#endif
85
 
86
/*
87
 * Mapping from expression instruction opcodes to strings; used for error
88
 * messages. Note that these entries must match the order and number of the
89
 * expression opcodes (e.g., INST_LOR) in tclCompile.h.
90
 */
91
 
92
static char *operatorStrings[] = {
93
    "||", "&&", "|", "^", "&", "==", "!=", "<", ">", "<=", ">=", "<<", ">>",
94
    "+", "-", "*", "/", "%", "+", "-", "~", "!",
95
    "BUILTIN FUNCTION", "FUNCTION",
96
    "", "", "", "", "", "", "", "", "eq", "ne",
97
};
98
 
99
/*
100
 * Mapping from Tcl result codes to strings; used for error and debugging
101
 * messages.
102
 */
103
 
104
#ifdef TCL_COMPILE_DEBUG
105
static char *resultStrings[] = {
106
    "TCL_OK", "TCL_ERROR", "TCL_RETURN", "TCL_BREAK", "TCL_CONTINUE"
107
};
108
#endif
109
 
110
/*
111
 * These are used by evalstats to monitor object usage in Tcl.
112
 */
113
 
114
#ifdef TCL_COMPILE_STATS
115
long    tclObjsAlloced = 0;
116
long    tclObjsFreed   = 0;
117
#define TCL_MAX_SHARED_OBJ_STATS 5
118
long    tclObjsShared[TCL_MAX_SHARED_OBJ_STATS] = { 0, 0, 0, 0, 0 };
119
#endif /* TCL_COMPILE_STATS */
120
 
121
/*
122
 * Macros for testing floating-point values for certain special cases. Test
123
 * for not-a-number by comparing a value against itself; test for infinity
124
 * by comparing against the largest floating-point value.
125
 */
126
 
127
#define IS_NAN(v) ((v) != (v))
128
#define IS_INF(v) (((v) > DBL_MAX) || ((v) < -DBL_MAX))
129
 
130
/*
131
 * The new macro for ending an instruction; note that a
132
 * reasonable C-optimiser will resolve all branches
133
 * at compile time. (result) is always a constant; the macro
134
 * NEXT_INST_F handles constant (nCleanup), NEXT_INST_V is
135
 * resolved at runtime for variable (nCleanup).
136
 *
137
 * ARGUMENTS:
138
 *    pcAdjustment: how much to increment pc
139
 *    nCleanup: how many objects to remove from the stack
140
 *    result: 0 indicates no object should be pushed on the
141
 *       stack; otherwise, push objResultPtr. If (result < 0),
142
 *       objResultPtr already has the correct reference count.
143
 */
144
 
145
#define NEXT_INST_F(pcAdjustment, nCleanup, result) \
146
     if (nCleanup == 0) {\
147
   if (result != 0) {\
148
       if ((result) > 0) {\
149
     PUSH_OBJECT(objResultPtr);\
150
       } else {\
151
     stackPtr[++stackTop] = objResultPtr;\
152
       }\
153
   } \
154
   pc += (pcAdjustment);\
155
   goto cleanup0;\
156
     } else if (result != 0) {\
157
   if ((result) > 0) {\
158
       Tcl_IncrRefCount(objResultPtr);\
159
   }\
160
   pc += (pcAdjustment);\
161
   switch (nCleanup) {\
162
       case 1: goto cleanup1_pushObjResultPtr;\
163
       case 2: goto cleanup2_pushObjResultPtr;\
164
       default: panic("ERROR: bad usage of macro NEXT_INST_F");\
165
   }\
166
     } else {\
167
   pc += (pcAdjustment);\
168
   switch (nCleanup) {\
169
       case 1: goto cleanup1;\
170
       case 2: goto cleanup2;\
171
       default: panic("ERROR: bad usage of macro NEXT_INST_F");\
172
   }\
173
     }
174
 
175
#define NEXT_INST_V(pcAdjustment, nCleanup, result) \
176
    pc += (pcAdjustment);\
177
    cleanup = (nCleanup);\
178
    if (result) {\
179
  if ((result) > 0) {\
180
      Tcl_IncrRefCount(objResultPtr);\
181
  }\
182
  goto cleanupV_pushObjResultPtr;\
183
    } else {\
184
  goto cleanupV;\
185
    }
186
 
187
 
188
/*
189
 * Macros used to cache often-referenced Tcl evaluation stack information
190
 * in local variables. Note that a DECACHE_STACK_INFO()-CACHE_STACK_INFO()
191
 * pair must surround any call inside TclExecuteByteCode (and a few other
192
 * procedures that use this scheme) that could result in a recursive call
193
 * to TclExecuteByteCode.
194
 */
195
 
196
#define CACHE_STACK_INFO() \
197
    stackPtr = eePtr->stackPtr; \
198
    stackTop = eePtr->stackTop
199
 
200
#define DECACHE_STACK_INFO() \
201
    eePtr->stackTop = stackTop
202
 
203
 
204
/*
205
 * Macros used to access items on the Tcl evaluation stack. PUSH_OBJECT
206
 * increments the object's ref count since it makes the stack have another
207
 * reference pointing to the object. However, POP_OBJECT does not decrement
208
 * the ref count. This is because the stack may hold the only reference to
209
 * the object, so the object would be destroyed if its ref count were
210
 * decremented before the caller had a chance to, e.g., store it in a
211
 * variable. It is the caller's responsibility to decrement the ref count
212
 * when it is finished with an object.
213
 *
214
 * WARNING! It is essential that objPtr only appear once in the PUSH_OBJECT
215
 * macro. The actual parameter might be an expression with side effects,
216
 * and this ensures that it will be executed only once.
217
 */
218
 
219
#define PUSH_OBJECT(objPtr) \
220
    Tcl_IncrRefCount(stackPtr[++stackTop] = (objPtr))
221
 
222
#define POP_OBJECT() \
223
    (stackPtr[stackTop--])
224
 
225
/*
226
 * Macros used to trace instruction execution. The macros TRACE,
227
 * TRACE_WITH_OBJ, and O2S are only used inside TclExecuteByteCode.
228
 * O2S is only used in TRACE* calls to get a string from an object.
229
 */
230
 
231
#ifdef TCL_COMPILE_DEBUG
232
#   define TRACE(a) \
233
    if (traceInstructions) { \
234
        fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, stackTop, \
235
         (unsigned int)(pc - codePtr->codeStart), \
236
         GetOpcodeName(pc)); \
237
  printf a; \
238
    }
239
#   define TRACE_APPEND(a) \
240
    if (traceInstructions) { \
241
  printf a; \
242
    }
243
#   define TRACE_WITH_OBJ(a, objPtr) \
244
    if (traceInstructions) { \
245
        fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, stackTop, \
246
         (unsigned int)(pc - codePtr->codeStart), \
247
         GetOpcodeName(pc)); \
248
  printf a; \
249
        TclPrintObject(stdout, objPtr, 30); \
250
        fprintf(stdout, "\n"); \
251
    }
252
#   define O2S(objPtr) \
253
    (objPtr ? TclGetString(objPtr) : "")
254
#else /* !TCL_COMPILE_DEBUG */
255
#   define TRACE(a)
256
#   define TRACE_APPEND(a)
257
#   define TRACE_WITH_OBJ(a, objPtr)
258
#   define O2S(objPtr)
259
#endif /* TCL_COMPILE_DEBUG */
260
 
261
/*
262
 * Macro to read a string containing either a wide or an int and
263
 * decide which it is while decoding it at the same time.  This
264
 * enforces the policy that integer constants between LONG_MIN and
265
 * LONG_MAX (inclusive) are represented by normal longs, and integer
266
 * constants outside that range are represented by wide ints.
267
 *
268
 * GET_WIDE_OR_INT is the same as REQUIRE_WIDE_OR_INT except it never
269
 * generates an error message.
270
 */
271
#define REQUIRE_WIDE_OR_INT(resultVar, objPtr, longVar, wideVar)  \
272
    (resultVar) = Tcl_GetWideIntFromObj(interp, (objPtr), &(wideVar));  \
273
    if ((resultVar) == TCL_OK && (wideVar) >= Tcl_LongAsWide(LONG_MIN)  \
274
      && (wideVar) <= Tcl_LongAsWide(LONG_MAX)) {     \
275
  (objPtr)->typePtr = &tclIntType;        \
276
  (objPtr)->internalRep.longValue = (longVar)     \
277
    = Tcl_WideAsLong(wideVar);        \
278
    }
279
#define GET_WIDE_OR_INT(resultVar, objPtr, longVar, wideVar)    \
280
    (resultVar) = Tcl_GetWideIntFromObj((Tcl_Interp *) NULL, (objPtr),  \
281
      &(wideVar));            \
282
    if ((resultVar) == TCL_OK && (wideVar) >= Tcl_LongAsWide(LONG_MIN)  \
283
      && (wideVar) <= Tcl_LongAsWide(LONG_MAX)) {     \
284
  (objPtr)->typePtr = &tclIntType;        \
285
  (objPtr)->internalRep.longValue = (longVar)     \
286
    = Tcl_WideAsLong(wideVar);        \
287
    }
288
/*
289
 * Combined with REQUIRE_WIDE_OR_INT, this gets a long value from
290
 * an obj.
291
 */
292
#define FORCE_LONG(objPtr, longVar, wideVar)        \
293
    if ((objPtr)->typePtr == &tclWideIntType) {       \
294
  (longVar) = Tcl_WideAsLong(wideVar);        \
295
    }
296
#define IS_INTEGER_TYPE(typePtr)          \
297
  ((typePtr) == &tclIntType || (typePtr) == &tclWideIntType)
298
#define IS_NUMERIC_TYPE(typePtr)          \
299
  (IS_INTEGER_TYPE(typePtr) || (typePtr) == &tclDoubleType)
300
 
301
#define W0  Tcl_LongAsWide(0)
302
/*
303
 * For tracing that uses wide values.
304
 */
305
#define LLD       "%" TCL_LL_MODIFIER "d"
306
 
307
#ifndef TCL_WIDE_INT_IS_LONG
308
/*
309
 * Extract a double value from a general numeric object.
310
 */
311
#define GET_DOUBLE_VALUE(doubleVar, objPtr, typePtr)      \
312
    if ((typePtr) == &tclIntType) {         \
313
  (doubleVar) = (double) (objPtr)->internalRep.longValue;   \
314
    } else if ((typePtr) == &tclWideIntType) {        \
315
  (doubleVar) = Tcl_WideAsDouble((objPtr)->internalRep.wideValue);\
316
    } else {                \
317
  (doubleVar) = (objPtr)->internalRep.doubleValue;    \
318
    }
319
#else /* TCL_WIDE_INT_IS_LONG */
320
#define GET_DOUBLE_VALUE(doubleVar, objPtr, typePtr)      \
321
    if (((typePtr) == &tclIntType) || ((typePtr) == &tclWideIntType)) { \
322
  (doubleVar) = (double) (objPtr)->internalRep.longValue;   \
323
    } else {                \
324
  (doubleVar) = (objPtr)->internalRep.doubleValue;    \
325
    }
326
#endif /* TCL_WIDE_INT_IS_LONG */
327
 
328
/*
329
 * Declarations for local procedures to this file:
330
 */
331
 
332
static int    TclExecuteByteCode _ANSI_ARGS_((Tcl_Interp *interp,
333
          ByteCode *codePtr));
334
static int    ExprAbsFunc _ANSI_ARGS_((Tcl_Interp *interp,
335
          ExecEnv *eePtr, ClientData clientData));
336
static int    ExprBinaryFunc _ANSI_ARGS_((Tcl_Interp *interp,
337
          ExecEnv *eePtr, ClientData clientData));
338
static int    ExprCallMathFunc _ANSI_ARGS_((Tcl_Interp *interp,
339
          ExecEnv *eePtr, int objc, Tcl_Obj **objv));
340
static int    ExprDoubleFunc _ANSI_ARGS_((Tcl_Interp *interp,
341
          ExecEnv *eePtr, ClientData clientData));
342
static int    ExprIntFunc _ANSI_ARGS_((Tcl_Interp *interp,
343
          ExecEnv *eePtr, ClientData clientData));
344
static int    ExprRandFunc _ANSI_ARGS_((Tcl_Interp *interp,
345
          ExecEnv *eePtr, ClientData clientData));
346
static int    ExprRoundFunc _ANSI_ARGS_((Tcl_Interp *interp,
347
          ExecEnv *eePtr, ClientData clientData));
348
static int    ExprSrandFunc _ANSI_ARGS_((Tcl_Interp *interp,
349
          ExecEnv *eePtr, ClientData clientData));
350
static int    ExprUnaryFunc _ANSI_ARGS_((Tcl_Interp *interp,
351
          ExecEnv *eePtr, ClientData clientData));
352
static int    ExprWideFunc _ANSI_ARGS_((Tcl_Interp *interp,
353
          ExecEnv *eePtr, ClientData clientData));
354
#ifdef TCL_COMPILE_STATS
355
static int              EvalStatsCmd _ANSI_ARGS_((ClientData clientData,
356
                            Tcl_Interp *interp, int objc,
357
          Tcl_Obj *CONST objv[]));
358
#endif /* TCL_COMPILE_STATS */
359
#ifdef TCL_COMPILE_DEBUG
360
static char *   GetOpcodeName _ANSI_ARGS_((unsigned char *pc));
361
#endif /* TCL_COMPILE_DEBUG */
362
static ExceptionRange * GetExceptRangeForPc _ANSI_ARGS_((unsigned char *pc,
363
          int catchOnly, ByteCode* codePtr));
364
static char *   GetSrcInfoForPc _ANSI_ARGS_((unsigned char *pc,
365
                ByteCode* codePtr, int *lengthPtr));
366
static void   GrowEvaluationStack _ANSI_ARGS_((ExecEnv *eePtr));
367
static void   IllegalExprOperandType _ANSI_ARGS_((
368
          Tcl_Interp *interp, unsigned char *pc,
369
          Tcl_Obj *opndPtr));
370
static void   InitByteCodeExecution _ANSI_ARGS_((
371
          Tcl_Interp *interp));
372
#ifdef TCL_COMPILE_DEBUG
373
static void   PrintByteCodeInfo _ANSI_ARGS_((ByteCode *codePtr));
374
static char *   StringForResultCode _ANSI_ARGS_((int result));
375
static void   ValidatePcAndStackTop _ANSI_ARGS_((
376
          ByteCode *codePtr, unsigned char *pc,
377
          int stackTop, int stackLowerBound));
378
#endif /* TCL_COMPILE_DEBUG */
379
static int    VerifyExprObjType _ANSI_ARGS_((Tcl_Interp *interp,
380
          Tcl_Obj *objPtr));
381
 
382
/*
383
 * Table describing the built-in math functions. Entries in this table are
384
 * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
385
 * operand byte.
386
 */
387
 
388
BuiltinFunc tclBuiltinFuncTable[] = {
389
#ifndef TCL_NO_MATH
390
    {"acos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) acos},
391
    {"asin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) asin},
392
    {"atan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) atan},
393
    {"atan2", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) atan2},
394
    {"ceil", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) ceil},
395
    {"cos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cos},
396
    {"cosh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cosh},
397
    {"exp", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) exp},
398
    {"floor", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) floor},
399
    {"fmod", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) fmod},
400
    {"hypot", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) hypot},
401
    {"log", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log},
402
    {"log10", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log10},
403
    {"pow", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) pow},
404
    {"sin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sin},
405
    {"sinh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sinh},
406
    {"sqrt", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sqrt},
407
    {"tan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tan},
408
    {"tanh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tanh},
409
#endif
410
    {"abs", 1, {TCL_EITHER}, ExprAbsFunc, 0},
411
    {"double", 1, {TCL_EITHER}, ExprDoubleFunc, 0},
412
    {"int", 1, {TCL_EITHER}, ExprIntFunc, 0},
413
    {"rand", 0, {TCL_EITHER}, ExprRandFunc, 0}, /* NOTE: rand takes no args. */
414
    {"round", 1, {TCL_EITHER}, ExprRoundFunc, 0},
415
    {"srand", 1, {TCL_INT}, ExprSrandFunc, 0},
416
    {"wide", 1, {TCL_EITHER}, ExprWideFunc, 0},
417
    {0},
418
};
419
 
420
/*
421
 *----------------------------------------------------------------------
422
 *
423
 * InitByteCodeExecution --
424
 *
425
 *  This procedure is called once to initialize the Tcl bytecode
426
 *  interpreter.
427
 *
428
 * Results:
429
 *  None.
430
 *
431
 * Side effects:
432
 *  This procedure initializes the array of instruction names. If
433
 *  compiling with the TCL_COMPILE_STATS flag, it initializes the
434
 *  array that counts the executions of each instruction and it
435
 *  creates the "evalstats" command. It also establishes the link
436
 *      between the Tcl "tcl_traceExec" and C "tclTraceExec" variables.
437
 *
438
 *----------------------------------------------------------------------
439
 */
440
 
441
static void
442
InitByteCodeExecution(interp)
443
    Tcl_Interp *interp;   /* Interpreter for which the Tcl variable
444
         * "tcl_traceExec" is linked to control
445
         * instruction tracing. */
446
{
447
#ifdef TCL_COMPILE_DEBUG
448
    if (Tcl_LinkVar(interp, "tcl_traceExec", (char *) &tclTraceExec,
449
        TCL_LINK_INT) != TCL_OK) {
450
  panic("InitByteCodeExecution: can't create link for tcl_traceExec variable");
451
    }
452
#endif
453
#ifdef TCL_COMPILE_STATS
454
    Tcl_CreateObjCommand(interp, "evalstats", EvalStatsCmd,
455
      (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
456
#endif /* TCL_COMPILE_STATS */
457
}
458
 
459
/*
460
 *----------------------------------------------------------------------
461
 *
462
 * TclCreateExecEnv --
463
 *
464
 *  This procedure creates a new execution environment for Tcl bytecode
465
 *  execution. An ExecEnv points to a Tcl evaluation stack. An ExecEnv
466
 *  is typically created once for each Tcl interpreter (Interp
467
 *  structure) and recursively passed to TclExecuteByteCode to execute
468
 *  ByteCode sequences for nested commands.
469
 *
470
 * Results:
471
 *  A newly allocated ExecEnv is returned. This points to an empty
472
 *  evaluation stack of the standard initial size.
473
 *
474
 * Side effects:
475
 *  The bytecode interpreter is also initialized here, as this
476
 *  procedure will be called before any call to TclExecuteByteCode.
477
 *
478
 *----------------------------------------------------------------------
479
 */
480
 
481
#define TCL_STACK_INITIAL_SIZE 2000
482
 
483
ExecEnv *
484
TclCreateExecEnv(interp)
485
    Tcl_Interp *interp;   /* Interpreter for which the execution
486
         * environment is being created. */
487
{
488
    ExecEnv *eePtr = (ExecEnv *) ckalloc(sizeof(ExecEnv));
489
    Tcl_Obj **stackPtr;
490
 
491
    stackPtr = (Tcl_Obj **)
492
  ckalloc((size_t) (TCL_STACK_INITIAL_SIZE * sizeof(Tcl_Obj *)));
493
 
494
    /*
495
     * Use the bottom pointer to keep a reference count; the
496
     * execution environment holds a reference.
497
     */
498
 
499
    stackPtr++;
500
    eePtr->stackPtr = stackPtr;
501
    stackPtr[-1] = (Tcl_Obj *) ((char *) 1);
502
 
503
    eePtr->stackTop = -1;
504
    eePtr->stackEnd = (TCL_STACK_INITIAL_SIZE - 2);
505
 
506
    eePtr->errorInfo = Tcl_NewStringObj("::errorInfo", -1);
507
    Tcl_IncrRefCount(eePtr->errorInfo);
508
 
509
    eePtr->errorCode = Tcl_NewStringObj("::errorCode", -1);
510
    Tcl_IncrRefCount(eePtr->errorCode);
511
 
512
    Tcl_MutexLock(&execMutex);
513
    if (!execInitialized) {
514
  TclInitAuxDataTypeTable();
515
  InitByteCodeExecution(interp);
516
  execInitialized = 1;
517
    }
518
    Tcl_MutexUnlock(&execMutex);
519
 
520
    return eePtr;
521
}
522
#undef TCL_STACK_INITIAL_SIZE
523
 
524
/*
525
 *----------------------------------------------------------------------
526
 *
527
 * TclDeleteExecEnv --
528
 *
529
 *  Frees the storage for an ExecEnv.
530
 *
531
 * Results:
532
 *  None.
533
 *
534
 * Side effects:
535
 *  Storage for an ExecEnv and its contained storage (e.g. the
536
 *  evaluation stack) is freed.
537
 *
538
 *----------------------------------------------------------------------
539
 */
540
 
541
void
542
TclDeleteExecEnv(eePtr)
543
    ExecEnv *eePtr;   /* Execution environment to free. */
544
{
545
    if (eePtr->stackPtr[-1] == (Tcl_Obj *) ((char *) 1)) {
546
  ckfree((char *) (eePtr->stackPtr-1));
547
    } else {
548
  panic("ERROR: freeing an execEnv whose stack is still in use.\n");
549
    }
550
    TclDecrRefCount(eePtr->errorInfo);
551
    TclDecrRefCount(eePtr->errorCode);
552
    ckfree((char *) eePtr);
553
}
554
 
555
/*
556
 *----------------------------------------------------------------------
557
 *
558
 * TclFinalizeExecution --
559
 *
560
 *  Finalizes the execution environment setup so that it can be
561
 *  later reinitialized.
562
 *
563
 * Results:
564
 *  None.
565
 *
566
 * Side effects:
567
 *  After this call, the next time TclCreateExecEnv will be called
568
 *  it will call InitByteCodeExecution.
569
 *
570
 *----------------------------------------------------------------------
571
 */
572
 
573
void
574
TclFinalizeExecution()
575
{
576
    Tcl_MutexLock(&execMutex);
577
    execInitialized = 0;
578
    Tcl_MutexUnlock(&execMutex);
579
    TclFinalizeAuxDataTypeTable();
580
}
581
 
582
/*
583
 *----------------------------------------------------------------------
584
 *
585
 * GrowEvaluationStack --
586
 *
587
 *  This procedure grows a Tcl evaluation stack stored in an ExecEnv.
588
 *
589
 * Results:
590
 *  None.
591
 *
592
 * Side effects:
593
 *  The size of the evaluation stack is doubled.
594
 *
595
 *----------------------------------------------------------------------
596
 */
597
 
598
static void
599
GrowEvaluationStack(eePtr)
600
    register ExecEnv *eePtr; /* Points to the ExecEnv with an evaluation
601
            * stack to enlarge. */
602
{
603
    /*
604
     * The current Tcl stack elements are stored from eePtr->stackPtr[0]
605
     * to eePtr->stackPtr[eePtr->stackEnd] (inclusive).
606
     */
607
 
608
    int currElems = (eePtr->stackEnd + 1);
609
    int newElems  = 2*currElems;
610
    int currBytes = currElems * sizeof(Tcl_Obj *);
611
    int newBytes  = 2*currBytes;
612
    Tcl_Obj **newStackPtr = (Tcl_Obj **) ckalloc((unsigned) newBytes);
613
    Tcl_Obj **oldStackPtr = eePtr->stackPtr;
614
 
615
    /*
616
     * We keep the stack reference count as a (char *), as that
617
     * works nicely as a portable pointer-sized counter.
618
     */
619
 
620
    char *refCount = (char *) oldStackPtr[-1];
621
 
622
    /*
623
     * Copy the existing stack items to the new stack space, free the old
624
     * storage if appropriate, and record the refCount of the new stack
625
     * held by the environment.
626
     */
627
 
628
    newStackPtr++;
629
    memcpy((VOID *) newStackPtr, (VOID *) oldStackPtr,
630
     (size_t) currBytes);
631
 
632
    if (refCount == (char *) 1) {
633
  ckfree((VOID *) (oldStackPtr-1));
634
    } else {
635
  /*
636
   * Remove the reference corresponding to the
637
   * environment pointer.
638
   */
639
 
640
  oldStackPtr[-1] = (Tcl_Obj *) (refCount-1);
641
    }
642
 
643
    eePtr->stackPtr = newStackPtr;
644
    eePtr->stackEnd = (newElems - 2); /* index of last usable item */
645
    newStackPtr[-1] = (Tcl_Obj *) ((char *) 1);
646
}
647
 
648
/*
649
 *--------------------------------------------------------------
650
 *
651
 * Tcl_ExprObj --
652
 *
653
 *  Evaluate an expression in a Tcl_Obj.
654
 *
655
 * Results:
656
 *  A standard Tcl object result. If the result is other than TCL_OK,
657
 *  then the interpreter's result contains an error message. If the
658
 *  result is TCL_OK, then a pointer to the expression's result value
659
 *  object is stored in resultPtrPtr. In that case, the object's ref
660
 *  count is incremented to reflect the reference returned to the
661
 *  caller; the caller is then responsible for the resulting object
662
 *  and must, for example, decrement the ref count when it is finished
663
 *  with the object.
664
 *
665
 * Side effects:
666
 *  Any side effects caused by subcommands in the expression, if any.
667
 *  The interpreter result is not modified unless there is an error.
668
 *
669
 *--------------------------------------------------------------
670
 */
671
 
672
int
673
Tcl_ExprObj(interp, objPtr, resultPtrPtr)
674
    Tcl_Interp *interp;   /* Context in which to evaluate the
675
         * expression. */
676
    register Tcl_Obj *objPtr; /* Points to Tcl object containing
677
         * expression to evaluate. */
678
    Tcl_Obj **resultPtrPtr; /* Where the Tcl_Obj* that is the expression
679
         * result is stored if no errors occur. */
680
{
681
    Interp *iPtr = (Interp *) interp;
682
    CompileEnv compEnv;   /* Compilation environment structure
683
         * allocated in frame. */
684
    LiteralTable *localTablePtr = &(compEnv.localLitTable);
685
    register ByteCode *codePtr = NULL;
686
            /* Tcl Internal type of bytecode.
687
         * Initialized to avoid compiler warning. */
688
    AuxData *auxDataPtr;
689
    LiteralEntry *entryPtr;
690
    Tcl_Obj *saveObjPtr;
691
    char *string;
692
    int length, i, result;
693
 
694
    /*
695
     * First handle some common expressions specially.
696
     */
697
 
698
    string = Tcl_GetStringFromObj(objPtr, &length);
699
    if (length == 1) {
700
  if (*string == '0') {
701
      *resultPtrPtr = Tcl_NewLongObj(0);
702
      Tcl_IncrRefCount(*resultPtrPtr);
703
      return TCL_OK;
704
  } else if (*string == '1') {
705
      *resultPtrPtr = Tcl_NewLongObj(1);
706
      Tcl_IncrRefCount(*resultPtrPtr);
707
      return TCL_OK;
708
  }
709
    } else if ((length == 2) && (*string == '!')) {
710
  if (*(string+1) == '0') {
711
      *resultPtrPtr = Tcl_NewLongObj(1);
712
      Tcl_IncrRefCount(*resultPtrPtr);
713
      return TCL_OK;
714
  } else if (*(string+1) == '1') {
715
      *resultPtrPtr = Tcl_NewLongObj(0);
716
      Tcl_IncrRefCount(*resultPtrPtr);
717
      return TCL_OK;
718
  }
719
    }
720
 
721
    /*
722
     * Get the ByteCode from the object. If it exists, make sure it hasn't
723
     * been invalidated by, e.g., someone redefining a command with a
724
     * compile procedure (this might make the compiled code wrong). If
725
     * necessary, convert the object to be a ByteCode object and compile it.
726
     * Also, if the code was compiled in/for a different interpreter, we
727
     * recompile it.
728
     *
729
     * Precompiled expressions, however, are immutable and therefore
730
     * they are not recompiled, even if the epoch has changed.
731
     *
732
     */
733
 
734
    if (objPtr->typePtr == &tclByteCodeType) {
735
  codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
736
  if (((Interp *) *codePtr->interpHandle != iPtr)
737
          || (codePtr->compileEpoch != iPtr->compileEpoch)) {
738
            if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
739
                if ((Interp *) *codePtr->interpHandle != iPtr) {
740
                    panic("Tcl_ExprObj: compiled expression jumped interps");
741
                }
742
          codePtr->compileEpoch = iPtr->compileEpoch;
743
            } else {
744
                (*tclByteCodeType.freeIntRepProc)(objPtr);
745
                objPtr->typePtr = (Tcl_ObjType *) NULL;
746
            }
747
  }
748
    }
749
    if (objPtr->typePtr != &tclByteCodeType) {
750
  TclInitCompileEnv(interp, &compEnv, string, length);
751
  result = TclCompileExpr(interp, string, length, &compEnv);
752
 
753
  /*
754
   * Free the compilation environment's literal table bucket array if
755
   * it was dynamically allocated.
756
   */
757
 
758
  if (localTablePtr->buckets != localTablePtr->staticBuckets) {
759
      ckfree((char *) localTablePtr->buckets);
760
  }
761
 
762
  if (result != TCL_OK) {
763
      /*
764
       * Compilation errors. Free storage allocated for compilation.
765
       */
766
 
767
#ifdef TCL_COMPILE_DEBUG
768
      TclVerifyLocalLiteralTable(&compEnv);
769
#endif /*TCL_COMPILE_DEBUG*/
770
      entryPtr = compEnv.literalArrayPtr;
771
      for (i = 0;  i < compEnv.literalArrayNext;  i++) {
772
    TclReleaseLiteral(interp, entryPtr->objPtr);
773
    entryPtr++;
774
      }
775
#ifdef TCL_COMPILE_DEBUG
776
      TclVerifyGlobalLiteralTable(iPtr);
777
#endif /*TCL_COMPILE_DEBUG*/
778
 
779
      auxDataPtr = compEnv.auxDataArrayPtr;
780
      for (i = 0;  i < compEnv.auxDataArrayNext;  i++) {
781
    if (auxDataPtr->type->freeProc != NULL) {
782
        auxDataPtr->type->freeProc(auxDataPtr->clientData);
783
    }
784
    auxDataPtr++;
785
      }
786
      TclFreeCompileEnv(&compEnv);
787
      return result;
788
  }
789
 
790
  /*
791
   * Successful compilation. If the expression yielded no
792
   * instructions, push an zero object as the expression's result.
793
   */
794
 
795
  if (compEnv.codeNext == compEnv.codeStart) {
796
      TclEmitPush(TclRegisterLiteral(&compEnv, "0", 1, /*onHeap*/ 0),
797
              &compEnv);
798
  }
799
 
800
  /*
801
   * Add a "done" instruction as the last instruction and change the
802
   * object into a ByteCode object. Ownership of the literal objects
803
   * and aux data items is given to the ByteCode object.
804
   */
805
 
806
  compEnv.numSrcBytes = iPtr->termOffset;
807
  TclEmitOpcode(INST_DONE, &compEnv);
808
  TclInitByteCodeObj(objPtr, &compEnv);
809
  TclFreeCompileEnv(&compEnv);
810
  codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
811
#ifdef TCL_COMPILE_DEBUG
812
  if (tclTraceCompile == 2) {
813
      TclPrintByteCodeObj(interp, objPtr);
814
  }
815
#endif /* TCL_COMPILE_DEBUG */
816
    }
817
 
818
    /*
819
     * Execute the expression after first saving the interpreter's result.
820
     */
821
 
822
    saveObjPtr = Tcl_GetObjResult(interp);
823
    Tcl_IncrRefCount(saveObjPtr);
824
    Tcl_ResetResult(interp);
825
 
826
    /*
827
     * Increment the code's ref count while it is being executed. If
828
     * afterwards no references to it remain, free the code.
829
     */
830
 
831
    codePtr->refCount++;
832
    result = TclExecuteByteCode(interp, codePtr);
833
    codePtr->refCount--;
834
    if (codePtr->refCount <= 0) {
835
  TclCleanupByteCode(codePtr);
836
  objPtr->typePtr = NULL;
837
  objPtr->internalRep.otherValuePtr = NULL;
838
    }
839
 
840
    /*
841
     * If the expression evaluated successfully, store a pointer to its
842
     * value object in resultPtrPtr then restore the old interpreter result.
843
     * We increment the object's ref count to reflect the reference that we
844
     * are returning to the caller. We also decrement the ref count of the
845
     * interpreter's result object after calling Tcl_SetResult since we
846
     * next store into that field directly.
847
     */
848
 
849
    if (result == TCL_OK) {
850
  *resultPtrPtr = iPtr->objResultPtr;
851
  Tcl_IncrRefCount(iPtr->objResultPtr);
852
 
853
  Tcl_SetObjResult(interp, saveObjPtr);
854
    }
855
    TclDecrRefCount(saveObjPtr);
856
    return result;
857
}
858
 
859
/*
860
 *----------------------------------------------------------------------
861
 *
862
 * TclCompEvalObj --
863
 *
864
 *  This procedure evaluates the script contained in a Tcl_Obj by
865
 *      first compiling it and then passing it to TclExecuteByteCode.
866
 *
867
 * Results:
868
 *  The return value is one of the return codes defined in tcl.h
869
 *  (such as TCL_OK), and interp->objResultPtr refers to a Tcl object
870
 *  that either contains the result of executing the code or an
871
 *  error message.
872
 *
873
 * Side effects:
874
 *  Almost certainly, depending on the ByteCode's instructions.
875
 *
876
 *----------------------------------------------------------------------
877
 */
878
 
879
int
880
TclCompEvalObj(interp, objPtr)
881
    Tcl_Interp *interp;
882
    Tcl_Obj *objPtr;
883
{
884
    register Interp *iPtr = (Interp *) interp;
885
    register ByteCode* codePtr;   /* Tcl Internal type of bytecode. */
886
    int oldCount = iPtr->cmdCount;  /* Used to tell whether any commands
887
           * at all were executed. */
888
    char *script;
889
    int numSrcBytes;
890
    int result;
891
    Namespace *namespacePtr;
892
 
893
 
894
    /*
895
     * Check that the interpreter is ready to execute scripts
896
     */
897
 
898
    iPtr->numLevels++;
899
    if (TclInterpReady(interp) == TCL_ERROR) {
900
  iPtr->numLevels--;
901
  return TCL_ERROR;
902
    }
903
 
904
    if (iPtr->varFramePtr != NULL) {
905
        namespacePtr = iPtr->varFramePtr->nsPtr;
906
    } else {
907
        namespacePtr = iPtr->globalNsPtr;
908
    }
909
 
910
    /*
911
     * If the object is not already of tclByteCodeType, compile it (and
912
     * reset the compilation flags in the interpreter; this should be
913
     * done after any compilation).
914
     * Otherwise, check that it is "fresh" enough.
915
     */
916
 
917
    if (objPtr->typePtr != &tclByteCodeType) {
918
        recompileObj:
919
  iPtr->errorLine = 1;
920
  result = tclByteCodeType.setFromAnyProc(interp, objPtr);
921
  if (result != TCL_OK) {
922
      iPtr->numLevels--;
923
      return result;
924
  }
925
  codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
926
    } else {
927
  /*
928
   * Make sure the Bytecode hasn't been invalidated by, e.g., someone
929
   * redefining a command with a compile procedure (this might make the
930
   * compiled code wrong).
931
   * The object needs to be recompiled if it was compiled in/for a
932
   * different interpreter, or for a different namespace, or for the
933
   * same namespace but with different name resolution rules.
934
   * Precompiled objects, however, are immutable and therefore
935
   * they are not recompiled, even if the epoch has changed.
936
   *
937
   * To be pedantically correct, we should also check that the
938
   * originating procPtr is the same as the current context procPtr
939
   * (assuming one exists at all - none for global level).  This
940
   * code is #def'ed out because [info body] was changed to never
941
   * return a bytecode type object, which should obviate us from
942
   * the extra checks here.
943
   */
944
  codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
945
  if (((Interp *) *codePtr->interpHandle != iPtr)
946
          || (codePtr->compileEpoch != iPtr->compileEpoch)
947
#ifdef CHECK_PROC_ORIGINATION /* [Bug: 3412 Pedantic] */
948
    || (codePtr->procPtr != NULL && !(iPtr->varFramePtr &&
949
      iPtr->varFramePtr->procPtr == codePtr->procPtr))
950
#endif
951
          || (codePtr->nsPtr != namespacePtr)
952
          || (codePtr->nsEpoch != namespacePtr->resolverEpoch)) {
953
            if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
954
                if ((Interp *) *codePtr->interpHandle != iPtr) {
955
                    panic("Tcl_EvalObj: compiled script jumped interps");
956
                }
957
          codePtr->compileEpoch = iPtr->compileEpoch;
958
            } else {
959
    /*
960
     * This byteCode is invalid: free it and recompile
961
     */
962
                tclByteCodeType.freeIntRepProc(objPtr);
963
    goto recompileObj;
964
      }
965
  }
966
    }
967
 
968
    /*
969
     * Execute the commands. If the code was compiled from an empty string,
970
     * don't bother executing the code.
971
     */
972
 
973
    numSrcBytes = codePtr->numSrcBytes;
974
    if ((numSrcBytes > 0) || (codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
975
  /*
976
   * Increment the code's ref count while it is being executed. If
977
   * afterwards no references to it remain, free the code.
978
   */
979
 
980
  codePtr->refCount++;
981
  result = TclExecuteByteCode(interp, codePtr);
982
  codePtr->refCount--;
983
  if (codePtr->refCount <= 0) {
984
      TclCleanupByteCode(codePtr);
985
  }
986
    } else {
987
  result = TCL_OK;
988
    }
989
    iPtr->numLevels--;
990
 
991
 
992
    /*
993
     * If no commands at all were executed, check for asynchronous
994
     * handlers so that they at least get one change to execute.
995
     * This is needed to handle event loops written in Tcl with
996
     * empty bodies.
997
     */
998
 
999
    if ((oldCount == iPtr->cmdCount) && Tcl_AsyncReady()) {
1000
  result = Tcl_AsyncInvoke(interp, result);
1001
 
1002
 
1003
  /*
1004
   * If an error occurred, record information about what was being
1005
   * executed when the error occurred.
1006
   */
1007
 
1008
  if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
1009
      script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
1010
      Tcl_LogCommandInfo(interp, script, script, numSrcBytes);
1011
  }
1012
    }
1013
 
1014
    /*
1015
     * Set the interpreter's termOffset member to the offset of the
1016
     * character just after the last one executed. We approximate the offset
1017
     * of the last character executed by using the number of characters
1018
     * compiled.
1019
     */
1020
 
1021
    iPtr->termOffset = numSrcBytes;
1022
    iPtr->flags &= ~ERR_ALREADY_LOGGED;
1023
 
1024
    return result;
1025
}
1026
 
1027
/*
1028
 *----------------------------------------------------------------------
1029
 *
1030
 * TclExecuteByteCode --
1031
 *
1032
 *  This procedure executes the instructions of a ByteCode structure.
1033
 *  It returns when a "done" instruction is executed or an error occurs.
1034
 *
1035
 * Results:
1036
 *  The return value is one of the return codes defined in tcl.h
1037
 *  (such as TCL_OK), and interp->objResultPtr refers to a Tcl object
1038
 *  that either contains the result of executing the code or an
1039
 *  error message.
1040
 *
1041
 * Side effects:
1042
 *  Almost certainly, depending on the ByteCode's instructions.
1043
 *
1044
 *----------------------------------------------------------------------
1045
 */
1046
 
1047
static int
1048
TclExecuteByteCode(interp, codePtr)
1049
    Tcl_Interp *interp;   /* Token for command interpreter. */
1050
    ByteCode *codePtr;    /* The bytecode sequence to interpret. */
1051
{
1052
    Interp *iPtr = (Interp *) interp;
1053
    ExecEnv *eePtr = iPtr->execEnvPtr;
1054
            /* Points to the execution environment. */
1055
    register Tcl_Obj **stackPtr = eePtr->stackPtr;
1056
            /* Cached evaluation stack base pointer. */
1057
    register int stackTop = eePtr->stackTop;
1058
            /* Cached top index of evaluation stack. */
1059
    register unsigned char *pc = codePtr->codeStart;
1060
        /* The current program counter. */
1061
    int opnd;     /* Current instruction's operand byte(s). */
1062
    int pcAdjustment;   /* Hold pc adjustment after instruction. */
1063
    int initStackTop = stackTop;/* Stack top at start of execution. */
1064
    ExceptionRange *rangePtr; /* Points to closest loop or catch exception
1065
         * range enclosing the pc. Used by various
1066
         * instructions and processCatch to
1067
         * process break, continue, and errors. */
1068
    int result = TCL_OK;  /* Return code returned after execution. */
1069
    int storeFlags;
1070
    Tcl_Obj *valuePtr, *value2Ptr, *objPtr;
1071
    char *bytes;
1072
    int length;
1073
    long i = 0;     /* Init. avoids compiler warning. */
1074
    Tcl_WideInt w;
1075
    register int cleanup;
1076
    Tcl_Obj *objResultPtr;
1077
    char *part1, *part2;
1078
    Var *varPtr, *arrayPtr;
1079
    CallFrame *varFramePtr = iPtr->varFramePtr;
1080
#ifdef TCL_COMPILE_DEBUG
1081
    int traceInstructions = (tclTraceExec == 3);
1082
    char cmdNameBuf[21];
1083
#endif
1084
 
1085
    /*
1086
     * This procedure uses a stack to hold information about catch commands.
1087
     * This information is the current operand stack top when starting to
1088
     * execute the code for each catch command. It starts out with stack-
1089
     * allocated space but uses dynamically-allocated storage if needed.
1090
     */
1091
 
1092
#define STATIC_CATCH_STACK_SIZE 4
1093
    int (catchStackStorage[STATIC_CATCH_STACK_SIZE]);
1094
    int *catchStackPtr = catchStackStorage;
1095
    int catchTop = -1;
1096
 
1097
#ifdef TCL_COMPILE_DEBUG
1098
    if (tclTraceExec >= 2) {
1099
  PrintByteCodeInfo(codePtr);
1100
  fprintf(stdout, "  Starting stack top=%d\n", eePtr->stackTop);
1101
  fflush(stdout);
1102
    }
1103
    opnd = 0;     /* Init. avoids compiler warning. */
1104
#endif
1105
 
1106
#ifdef TCL_COMPILE_STATS
1107
    iPtr->stats.numExecutions++;
1108
#endif
1109
 
1110
    /*
1111
     * Make sure the catch stack is large enough to hold the maximum number
1112
     * of catch commands that could ever be executing at the same time. This
1113
     * will be no more than the exception range array's depth.
1114
     */
1115
 
1116
    if (codePtr->maxExceptDepth > STATIC_CATCH_STACK_SIZE) {
1117
  catchStackPtr = (int *)
1118
          ckalloc(codePtr->maxExceptDepth * sizeof(int));
1119
    }
1120
 
1121
    /*
1122
     * Make sure the stack has enough room to execute this ByteCode.
1123
     */
1124
 
1125
    while ((stackTop + codePtr->maxStackDepth) > eePtr->stackEnd) {
1126
        GrowEvaluationStack(eePtr);
1127
        stackPtr = eePtr->stackPtr;
1128
    }
1129
 
1130
    /*
1131
     * Loop executing instructions until a "done" instruction, a
1132
     * TCL_RETURN, or some error.
1133
     */
1134
 
1135
    goto cleanup0;
1136
 
1137
 
1138
    /*
1139
     * Targets for standard instruction endings; unrolled
1140
     * for speed in the most frequent cases (instructions that
1141
     * consume up to two stack elements).
1142
     *
1143
     * This used to be a "for(;;)" loop, with each instruction doing
1144
     * its own cleanup.
1145
     */
1146
 
1147
    cleanupV_pushObjResultPtr:
1148
    switch (cleanup) {
1149
        case 0:
1150
      stackPtr[++stackTop] = (objResultPtr);
1151
      goto cleanup0;
1152
        default:
1153
      cleanup -= 2;
1154
      while (cleanup--) {
1155
    valuePtr = POP_OBJECT();
1156
    TclDecrRefCount(valuePtr);
1157
      }
1158
        case 2:
1159
        cleanup2_pushObjResultPtr:
1160
      valuePtr = POP_OBJECT();
1161
      TclDecrRefCount(valuePtr);
1162
        case 1:
1163
        cleanup1_pushObjResultPtr:
1164
      valuePtr = stackPtr[stackTop];
1165
      TclDecrRefCount(valuePtr);
1166
    }
1167
    stackPtr[stackTop] = objResultPtr;
1168
    goto cleanup0;
1169
 
1170
    cleanupV:
1171
    switch (cleanup) {
1172
        default:
1173
      cleanup -= 2;
1174
      while (cleanup--) {
1175
    valuePtr = POP_OBJECT();
1176
    TclDecrRefCount(valuePtr);
1177
      }
1178
        case 2:
1179
        cleanup2:
1180
      valuePtr = POP_OBJECT();
1181
      TclDecrRefCount(valuePtr);
1182
        case 1:
1183
        cleanup1:
1184
      valuePtr = POP_OBJECT();
1185
      TclDecrRefCount(valuePtr);
1186
        case 0:
1187
      /*
1188
       * We really want to do nothing now, but this is needed
1189
       * for some compilers (SunPro CC)
1190
       */
1191
      break;
1192
    }
1193
 
1194
    cleanup0:
1195
 
1196
#ifdef TCL_COMPILE_DEBUG
1197
    ValidatePcAndStackTop(codePtr, pc, stackTop, initStackTop);
1198
    if (traceInstructions) {
1199
  fprintf(stdout, "%2d: %2d ", iPtr->numLevels, stackTop);
1200
  TclPrintInstruction(codePtr, pc);
1201
  fflush(stdout);
1202
    }
1203
#endif /* TCL_COMPILE_DEBUG */
1204
 
1205
#ifdef TCL_COMPILE_STATS
1206
    iPtr->stats.instructionCount[*pc]++;
1207
#endif
1208
    switch (*pc) {
1209
    case INST_DONE:
1210
  if (stackTop <= initStackTop) {
1211
      stackTop--;
1212
      goto abnormalReturn;
1213
  }
1214
 
1215
  /*
1216
   * Set the interpreter's object result to point to the
1217
   * topmost object from the stack, and check for a possible
1218
   * [catch]. The stackTop's level and refCount will be handled
1219
   * by "processCatch" or "abnormalReturn".
1220
   */
1221
 
1222
  valuePtr = stackPtr[stackTop];
1223
  Tcl_SetObjResult(interp, valuePtr);
1224
#ifdef TCL_COMPILE_DEBUG
1225
  TRACE_WITH_OBJ(("=> return code=%d, result=", result),
1226
          iPtr->objResultPtr);
1227
  if (traceInstructions) {
1228
      fprintf(stdout, "\n");
1229
  }
1230
#endif
1231
  goto checkForCatch;
1232
 
1233
    case INST_PUSH1:
1234
  objResultPtr = codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)];
1235
  TRACE_WITH_OBJ(("%u => ", TclGetInt1AtPtr(pc+1)), objResultPtr);
1236
  NEXT_INST_F(2, 0, 1);
1237
 
1238
    case INST_PUSH4:
1239
  objResultPtr = codePtr->objArrayPtr[TclGetUInt4AtPtr(pc+1)];
1240
  TRACE_WITH_OBJ(("%u => ", TclGetUInt4AtPtr(pc+1)), objResultPtr);
1241
  NEXT_INST_F(5, 0, 1);
1242
 
1243
    case INST_POP:
1244
  TRACE_WITH_OBJ(("=> discarding "), stackPtr[stackTop]);
1245
  valuePtr = POP_OBJECT();
1246
  TclDecrRefCount(valuePtr);
1247
  NEXT_INST_F(1, 0, 0);
1248
 
1249
    case INST_DUP:
1250
  objResultPtr = stackPtr[stackTop];
1251
  TRACE_WITH_OBJ(("=> "), objResultPtr);
1252
  NEXT_INST_F(1, 0, 1);
1253
 
1254
    case INST_OVER:
1255
  opnd = TclGetUInt4AtPtr( pc+1 );
1256
  objResultPtr = stackPtr[ stackTop - opnd ];
1257
  TRACE_WITH_OBJ(("=> "), objResultPtr);
1258
  NEXT_INST_F(5, 0, 1);
1259
 
1260
    case INST_CONCAT1:
1261
  opnd = TclGetUInt1AtPtr(pc+1);
1262
  {
1263
      int totalLen = 0;
1264
 
1265
      /*
1266
       * Peephole optimisation for appending an empty string.
1267
       * This enables replacing 'K $x [set x{}]' by '$x[set x{}]'
1268
       * for fastest execution. Avoid doing the optimisation for wide
1269
       * ints - a case where equal strings may refer to different values
1270
       * (see [Bug 1251791]).
1271
       */
1272
 
1273
      if ((opnd == 2) && (stackPtr[stackTop-1]->typePtr != &tclWideIntType)) {
1274
    Tcl_GetStringFromObj(stackPtr[stackTop], &length);
1275
    if (length == 0) {
1276
        /* Just drop the top item from the stack */
1277
        NEXT_INST_F(2, 1, 0);
1278
    }
1279
      }
1280
 
1281
      /*
1282
       * Concatenate strings (with no separators) from the top
1283
       * opnd items on the stack starting with the deepest item.
1284
       * First, determine how many characters are needed.
1285
       */
1286
 
1287
      for (i = (stackTop - (opnd-1));  i <= stackTop;  i++) {
1288
    bytes = Tcl_GetStringFromObj(stackPtr[i], &length);
1289
    if (bytes != NULL) {
1290
        totalLen += length;
1291
    }
1292
      }
1293
 
1294
      /*
1295
       * Initialize the new append string object by appending the
1296
       * strings of the opnd stack objects. Also pop the objects.
1297
       */
1298
 
1299
      TclNewObj(objResultPtr);
1300
      if (totalLen > 0) {
1301
    char *p = (char *) ckalloc((unsigned) (totalLen + 1));
1302
    objResultPtr->bytes = p;
1303
    objResultPtr->length = totalLen;
1304
    for (i = (stackTop - (opnd-1));  i <= stackTop;  i++) {
1305
        valuePtr = stackPtr[i];
1306
        bytes = Tcl_GetStringFromObj(valuePtr, &length);
1307
        if (bytes != NULL) {
1308
      memcpy((VOID *) p, (VOID *) bytes,
1309
             (size_t) length);
1310
      p += length;
1311
        }
1312
    }
1313
    *p = '\0';
1314
      }
1315
 
1316
      TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
1317
      NEXT_INST_V(2, opnd, 1);
1318
  }
1319
 
1320
    case INST_INVOKE_STK4:
1321
  opnd = TclGetUInt4AtPtr(pc+1);
1322
  pcAdjustment = 5;
1323
  goto doInvocation;
1324
 
1325
    case INST_INVOKE_STK1:
1326
  opnd = TclGetUInt1AtPtr(pc+1);
1327
  pcAdjustment = 2;
1328
 
1329
    doInvocation:
1330
  {
1331
      int objc = opnd; /* The number of arguments. */
1332
      Tcl_Obj **objv;  /* The array of argument objects. */
1333
 
1334
      /*
1335
       * We keep the stack reference count as a (char *), as that
1336
       * works nicely as a portable pointer-sized counter.
1337
       */
1338
 
1339
      char **preservedStackRefCountPtr;
1340
 
1341
      /*
1342
       * Reference to memory block containing
1343
       * objv array (must be kept live throughout
1344
       * trace and command invokations.)
1345
       */
1346
 
1347
      objv = &(stackPtr[stackTop - (objc-1)]);
1348
 
1349
#ifdef TCL_COMPILE_DEBUG
1350
      if (tclTraceExec >= 2) {
1351
    if (traceInstructions) {
1352
        strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
1353
        TRACE(("%u => call ", objc));
1354
    } else {
1355
        fprintf(stdout, "%d: (%u) invoking ",
1356
          iPtr->numLevels,
1357
          (unsigned int)(pc - codePtr->codeStart));
1358
    }
1359
    for (i = 0;  i < objc;  i++) {
1360
        TclPrintObject(stdout, objv[i], 15);
1361
        fprintf(stdout, " ");
1362
    }
1363
    fprintf(stdout, "\n");
1364
    fflush(stdout);
1365
      }
1366
#endif /*TCL_COMPILE_DEBUG*/
1367
 
1368
      /*
1369
       * If trace procedures will be called, we need a
1370
       * command string to pass to TclEvalObjvInternal; note
1371
       * that a copy of the string will be made there to
1372
       * include the ending \0.
1373
       */
1374
 
1375
      bytes = NULL;
1376
      length = 0;
1377
      if (iPtr->tracePtr != NULL) {
1378
    Trace *tracePtr, *nextTracePtr;
1379
 
1380
    for (tracePtr = iPtr->tracePtr;  tracePtr != NULL;
1381
         tracePtr = nextTracePtr) {
1382
        nextTracePtr = tracePtr->nextPtr;
1383
        if (tracePtr->level == 0 ||
1384
      iPtr->numLevels <= tracePtr->level) {
1385
      /*
1386
       * Traces will be called: get command string
1387
       */
1388
 
1389
      bytes = GetSrcInfoForPc(pc, codePtr, &length);
1390
      break;
1391
        }
1392
    }
1393
      } else {
1394
    Command *cmdPtr;
1395
    cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
1396
    if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) {
1397
        bytes = GetSrcInfoForPc(pc, codePtr, &length);
1398
    }
1399
      }
1400
 
1401
      /*
1402
       * A reference to part of the stack vector itself
1403
       * escapes our control: increase its refCount
1404
       * to stop it from being deallocated by a recursive
1405
       * call to ourselves.  The extra variable is needed
1406
       * because all others are liable to change due to the
1407
       * trace procedures.
1408
       */
1409
 
1410
      preservedStackRefCountPtr = (char **) (stackPtr-1);
1411
      ++*preservedStackRefCountPtr;
1412
 
1413
      /*
1414
       * Finally, let TclEvalObjvInternal handle the command.
1415
       */
1416
 
1417
      DECACHE_STACK_INFO();
1418
      Tcl_ResetResult(interp);
1419
      result = TclEvalObjvInternal(interp, objc, objv, bytes, length, 0);
1420
      CACHE_STACK_INFO();
1421
 
1422
      /*
1423
       * If the old stack is going to be released, it is
1424
       * safe to do so now, since no references to objv are
1425
       * going to be used from now on.
1426
       */
1427
 
1428
      --*preservedStackRefCountPtr;
1429
      if (*preservedStackRefCountPtr == (char *) 0) {
1430
    ckfree((VOID *) preservedStackRefCountPtr);
1431
      }
1432
 
1433
      if (result == TCL_OK) {
1434
    /*
1435
     * Push the call's object result and continue execution
1436
     * with the next instruction.
1437
     */
1438
 
1439
    TRACE_WITH_OBJ(("%u => ... after \"%.20s\": TCL_OK, result=",
1440
            objc, cmdNameBuf), Tcl_GetObjResult(interp));
1441
 
1442
    objResultPtr = Tcl_GetObjResult(interp);
1443
 
1444
    /*
1445
     * Reset the interp's result to avoid possible duplications
1446
     * of large objects [Bug 781585]. We do not call
1447
     * Tcl_ResetResult() to avoid any side effects caused by
1448
     * the resetting of errorInfo and errorCode [Bug 804681],
1449
     * which are not needed here. We chose instead to manipulate
1450
     * the interp's object result directly.
1451
     *
1452
     * Note that the result object is now in objResultPtr, it
1453
     * keeps the refCount it had in its role of iPtr->objResultPtr.
1454
     */
1455
    {
1456
        Tcl_Obj *newObjResultPtr;
1457
        TclNewObj(newObjResultPtr);
1458
        Tcl_IncrRefCount(newObjResultPtr);
1459
        iPtr->objResultPtr = newObjResultPtr;
1460
    }
1461
 
1462
    NEXT_INST_V(pcAdjustment, opnd, -1);
1463
      } else {
1464
    cleanup = opnd;
1465
    goto processExceptionReturn;
1466
      }
1467
  }
1468
 
1469
    case INST_EVAL_STK:
1470
  /*
1471
   * Note to maintainers: it is important that INST_EVAL_STK
1472
   * pop its argument from the stack before jumping to
1473
   * checkForCatch! DO NOT OPTIMISE!
1474
   */
1475
 
1476
  objPtr = stackPtr[stackTop];
1477
  DECACHE_STACK_INFO();
1478
  result = TclCompEvalObj(interp, objPtr);
1479
  CACHE_STACK_INFO();
1480
  if (result == TCL_OK) {
1481
      /*
1482
       * Normal return; push the eval's object result.
1483
       */
1484
 
1485
      objResultPtr = Tcl_GetObjResult(interp);
1486
      TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)),
1487
         Tcl_GetObjResult(interp));
1488
 
1489
      /*
1490
       * Reset the interp's result to avoid possible duplications
1491
       * of large objects [Bug 781585]. We do not call
1492
       * Tcl_ResetResult() to avoid any side effects caused by
1493
       * the resetting of errorInfo and errorCode [Bug 804681],
1494
       * which are not needed here. We chose instead to manipulate
1495
       * the interp's object result directly.
1496
       *
1497
       * Note that the result object is now in objResultPtr, it
1498
       * keeps the refCount it had in its role of iPtr->objResultPtr.
1499
       */
1500
      {
1501
          Tcl_Obj *newObjResultPtr;
1502
    TclNewObj(newObjResultPtr);
1503
    Tcl_IncrRefCount(newObjResultPtr);
1504
    iPtr->objResultPtr = newObjResultPtr;
1505
      }
1506
 
1507
      NEXT_INST_F(1, 1, -1);
1508
  } else {
1509
      cleanup = 1;
1510
      goto processExceptionReturn;
1511
  }
1512
 
1513
    case INST_EXPR_STK:
1514
  objPtr = stackPtr[stackTop];
1515
  DECACHE_STACK_INFO();
1516
  Tcl_ResetResult(interp);
1517
  result = Tcl_ExprObj(interp, objPtr, &valuePtr);
1518
  CACHE_STACK_INFO();
1519
  if (result != TCL_OK) {
1520
      TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ",
1521
          O2S(objPtr)), Tcl_GetObjResult(interp));
1522
      goto checkForCatch;
1523
  }
1524
  objResultPtr = valuePtr;
1525
  TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)), valuePtr);
1526
  NEXT_INST_F(1, 1, -1); /* already has right refct */
1527
 
1528
    /*
1529
     * ---------------------------------------------------------
1530
     *     Start of INST_LOAD instructions.
1531
     *
1532
     * WARNING: more 'goto' here than your doctor recommended!
1533
     * The different instructions set the value of some variables
1534
     * and then jump to somme common execution code.
1535
     */
1536
 
1537
    case INST_LOAD_SCALAR1:
1538
  opnd = TclGetUInt1AtPtr(pc+1);
1539
  varPtr = &(varFramePtr->compiledLocals[opnd]);
1540
  part1 = varPtr->name;
1541
  while (TclIsVarLink(varPtr)) {
1542
      varPtr = varPtr->value.linkPtr;
1543
  }
1544
  TRACE(("%u => ", opnd));
1545
  if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)
1546
          && (varPtr->tracePtr == NULL)) {
1547
      /*
1548
       * No errors, no traces: just get the value.
1549
       */
1550
      objResultPtr = varPtr->value.objPtr;
1551
      TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
1552
      NEXT_INST_F(2, 0, 1);
1553
  }
1554
  pcAdjustment = 2;
1555
  cleanup = 0;
1556
  arrayPtr = NULL;
1557
  part2 = NULL;
1558
  goto doCallPtrGetVar;
1559
 
1560
    case INST_LOAD_SCALAR4:
1561
  opnd = TclGetUInt4AtPtr(pc+1);
1562
  varPtr = &(varFramePtr->compiledLocals[opnd]);
1563
  part1 = varPtr->name;
1564
  while (TclIsVarLink(varPtr)) {
1565
      varPtr = varPtr->value.linkPtr;
1566
  }
1567
  TRACE(("%u => ", opnd));
1568
  if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)
1569
          && (varPtr->tracePtr == NULL)) {
1570
      /*
1571
       * No errors, no traces: just get the value.
1572
       */
1573
      objResultPtr = varPtr->value.objPtr;
1574
      TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
1575
      NEXT_INST_F(5, 0, 1);
1576
  }
1577
  pcAdjustment = 5;
1578
  cleanup = 0;
1579
  arrayPtr = NULL;
1580
  part2 = NULL;
1581
  goto doCallPtrGetVar;
1582
 
1583
    case INST_LOAD_ARRAY_STK:
1584
  cleanup = 2;
1585
  part2 = Tcl_GetString(stackPtr[stackTop]);  /* element name */
1586
  objPtr = stackPtr[stackTop-1]; /* array name */
1587
  TRACE(("\"%.30s(%.30s)\" => ", O2S(objPtr), part2));
1588
  goto doLoadStk;
1589
 
1590
    case INST_LOAD_STK:
1591
    case INST_LOAD_SCALAR_STK:
1592
  cleanup = 1;
1593
  part2 = NULL;
1594
  objPtr = stackPtr[stackTop]; /* variable name */
1595
  TRACE(("\"%.30s\" => ", O2S(objPtr)));
1596
 
1597
    doLoadStk:
1598
  part1 = TclGetString(objPtr);
1599
  varPtr = TclObjLookupVar(interp, objPtr, part2,
1600
           TCL_LEAVE_ERR_MSG, "read",
1601
                 /*createPart1*/ 0,
1602
           /*createPart2*/ 1, &arrayPtr);
1603
  if (varPtr == NULL) {
1604
      TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
1605
      result = TCL_ERROR;
1606
      goto checkForCatch;
1607
  }
1608
  if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)
1609
          && (varPtr->tracePtr == NULL)
1610
          && ((arrayPtr == NULL)
1611
            || (arrayPtr->tracePtr == NULL))) {
1612
      /*
1613
       * No errors, no traces: just get the value.
1614
       */
1615
      objResultPtr = varPtr->value.objPtr;
1616
      TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
1617
      NEXT_INST_V(1, cleanup, 1);
1618
  }
1619
  pcAdjustment = 1;
1620
  goto doCallPtrGetVar;
1621
 
1622
    case INST_LOAD_ARRAY4:
1623
  opnd = TclGetUInt4AtPtr(pc+1);
1624
  pcAdjustment = 5;
1625
  goto doLoadArray;
1626
 
1627
    case INST_LOAD_ARRAY1:
1628
  opnd = TclGetUInt1AtPtr(pc+1);
1629
  pcAdjustment = 2;
1630
 
1631
    doLoadArray:
1632
  part2 = TclGetString(stackPtr[stackTop]);
1633
  arrayPtr = &(varFramePtr->compiledLocals[opnd]);
1634
  part1 = arrayPtr->name;
1635
  while (TclIsVarLink(arrayPtr)) {
1636
      arrayPtr = arrayPtr->value.linkPtr;
1637
  }
1638
  TRACE(("%u \"%.30s\" => ", opnd, part2));
1639
  varPtr = TclLookupArrayElement(interp, part1, part2,
1640
          TCL_LEAVE_ERR_MSG, "read", 0, 1, arrayPtr);
1641
  if (varPtr == NULL) {
1642
      TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
1643
      result = TCL_ERROR;
1644
      goto checkForCatch;
1645
  }
1646
  if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)
1647
          && (varPtr->tracePtr == NULL)
1648
          && ((arrayPtr == NULL)
1649
            || (arrayPtr->tracePtr == NULL))) {
1650
      /*
1651
       * No errors, no traces: just get the value.
1652
       */
1653
      objResultPtr = varPtr->value.objPtr;
1654
      TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
1655
      NEXT_INST_F(pcAdjustment, 1, 1);
1656
  }
1657
  cleanup = 1;
1658
  goto doCallPtrGetVar;
1659
 
1660
    doCallPtrGetVar:
1661
  /*
1662
   * There are either errors or the variable is traced:
1663
   * call TclPtrGetVar to process fully.
1664
   */
1665
 
1666
  DECACHE_STACK_INFO();
1667
  objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1,
1668
          part2, TCL_LEAVE_ERR_MSG);
1669
  CACHE_STACK_INFO();
1670
  if (objResultPtr == NULL) {
1671
      TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
1672
      result = TCL_ERROR;
1673
      goto checkForCatch;
1674
  }
1675
  TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
1676
  NEXT_INST_V(pcAdjustment, cleanup, 1);
1677
 
1678
    /*
1679
     *     End of INST_LOAD instructions.
1680
     * ---------------------------------------------------------
1681
     */
1682
 
1683
    /*
1684
     * ---------------------------------------------------------
1685
     *     Start of INST_STORE and related instructions.
1686
     *
1687
     * WARNING: more 'goto' here than your doctor recommended!
1688
     * The different instructions set the value of some variables
1689
     * and then jump to somme common execution code.
1690
     */
1691
 
1692
    case INST_LAPPEND_STK:
1693
  valuePtr = stackPtr[stackTop]; /* value to append */
1694
  part2 = NULL;
1695
  storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
1696
          | TCL_LIST_ELEMENT | TCL_TRACE_READS);
1697
  goto doStoreStk;
1698
 
1699
    case INST_LAPPEND_ARRAY_STK:
1700
  valuePtr = stackPtr[stackTop]; /* value to append */
1701
  part2 = TclGetString(stackPtr[stackTop - 1]);
1702
  storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
1703
          | TCL_LIST_ELEMENT | TCL_TRACE_READS);
1704
  goto doStoreStk;
1705
 
1706
    case INST_APPEND_STK:
1707
  valuePtr = stackPtr[stackTop]; /* value to append */
1708
  part2 = NULL;
1709
  storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
1710
  goto doStoreStk;
1711
 
1712
    case INST_APPEND_ARRAY_STK:
1713
  valuePtr = stackPtr[stackTop]; /* value to append */
1714
  part2 = TclGetString(stackPtr[stackTop - 1]);
1715
  storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
1716
  goto doStoreStk;
1717
 
1718
    case INST_STORE_ARRAY_STK:
1719
  valuePtr = stackPtr[stackTop];
1720
  part2 = TclGetString(stackPtr[stackTop - 1]);
1721
  storeFlags = TCL_LEAVE_ERR_MSG;
1722
  goto doStoreStk;
1723
 
1724
    case INST_STORE_STK:
1725
    case INST_STORE_SCALAR_STK:
1726
  valuePtr = stackPtr[stackTop];
1727
  part2 = NULL;
1728
  storeFlags = TCL_LEAVE_ERR_MSG;
1729
 
1730
    doStoreStk:
1731
  objPtr = stackPtr[stackTop - 1 - (part2 != NULL)]; /* variable name */
1732
  part1 = TclGetString(objPtr);
1733
#ifdef TCL_COMPILE_DEBUG
1734
  if (part2 == NULL) {
1735
      TRACE(("\"%.30s\" <- \"%.30s\" =>",
1736
              part1, O2S(valuePtr)));
1737
  } else {
1738
      TRACE(("\"%.30s(%.30s)\" <- \"%.30s\" => ",
1739
        part1, part2, O2S(valuePtr)));
1740
  }
1741
#endif
1742
  varPtr = TclObjLookupVar(interp, objPtr, part2,
1743
           TCL_LEAVE_ERR_MSG, "set",
1744
                 /*createPart1*/ 1,
1745
           /*createPart2*/ 1, &arrayPtr);
1746
  if (varPtr == NULL) {
1747
      TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
1748
      result = TCL_ERROR;
1749
      goto checkForCatch;
1750
  }
1751
  cleanup = ((part2 == NULL)? 2 : 3);
1752
  pcAdjustment = 1;
1753
  goto doCallPtrSetVar;
1754
 
1755
    case INST_LAPPEND_ARRAY4:
1756
  opnd = TclGetUInt4AtPtr(pc+1);
1757
  pcAdjustment = 5;
1758
  storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
1759
          | TCL_LIST_ELEMENT | TCL_TRACE_READS);
1760
  goto doStoreArray;
1761
 
1762
    case INST_LAPPEND_ARRAY1:
1763
  opnd = TclGetUInt1AtPtr(pc+1);
1764
  pcAdjustment = 2;
1765
  storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
1766
          | TCL_LIST_ELEMENT | TCL_TRACE_READS);
1767
  goto doStoreArray;
1768
 
1769
    case INST_APPEND_ARRAY4:
1770
  opnd = TclGetUInt4AtPtr(pc+1);
1771
  pcAdjustment = 5;
1772
  storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
1773
  goto doStoreArray;
1774
 
1775
    case INST_APPEND_ARRAY1:
1776
  opnd = TclGetUInt1AtPtr(pc+1);
1777
  pcAdjustment = 2;
1778
  storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
1779
  goto doStoreArray;
1780
 
1781
    case INST_STORE_ARRAY4:
1782
  opnd = TclGetUInt4AtPtr(pc+1);
1783
  pcAdjustment = 5;
1784
  storeFlags = TCL_LEAVE_ERR_MSG;
1785
  goto doStoreArray;
1786
 
1787
    case INST_STORE_ARRAY1:
1788
  opnd = TclGetUInt1AtPtr(pc+1);
1789
  pcAdjustment = 2;
1790
  storeFlags = TCL_LEAVE_ERR_MSG;
1791
 
1792
    doStoreArray:
1793
  valuePtr = stackPtr[stackTop];
1794
  part2 = TclGetString(stackPtr[stackTop - 1]);
1795
  arrayPtr = &(varFramePtr->compiledLocals[opnd]);
1796
  part1 = arrayPtr->name;
1797
  TRACE(("%u \"%.30s\" <- \"%.30s\" => ",
1798
        opnd, part2, O2S(valuePtr)));
1799
  while (TclIsVarLink(arrayPtr)) {
1800
      arrayPtr = arrayPtr->value.linkPtr;
1801
  }
1802
  varPtr = TclLookupArrayElement(interp, part1, part2,
1803
          TCL_LEAVE_ERR_MSG, "set", 1, 1, arrayPtr);
1804
  if (varPtr == NULL) {
1805
      TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
1806
      result = TCL_ERROR;
1807
      goto checkForCatch;
1808
  }
1809
  cleanup = 2;
1810
  goto doCallPtrSetVar;
1811
 
1812
    case INST_LAPPEND_SCALAR4:
1813
  opnd = TclGetUInt4AtPtr(pc+1);
1814
  pcAdjustment = 5;
1815
  storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
1816
          | TCL_LIST_ELEMENT | TCL_TRACE_READS);
1817
  goto doStoreScalar;
1818
 
1819
    case INST_LAPPEND_SCALAR1:
1820
  opnd = TclGetUInt1AtPtr(pc+1);
1821
  pcAdjustment = 2;
1822
  storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
1823
          | TCL_LIST_ELEMENT | TCL_TRACE_READS);
1824
  goto doStoreScalar;
1825
 
1826
    case INST_APPEND_SCALAR4:
1827
  opnd = TclGetUInt4AtPtr(pc+1);
1828
  pcAdjustment = 5;
1829
  storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
1830
  goto doStoreScalar;
1831
 
1832
    case INST_APPEND_SCALAR1:
1833
  opnd = TclGetUInt1AtPtr(pc+1);
1834
  pcAdjustment = 2;
1835
  storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
1836
  goto doStoreScalar;
1837
 
1838
    case INST_STORE_SCALAR4:
1839
  opnd = TclGetUInt4AtPtr(pc+1);
1840
  pcAdjustment = 5;
1841
  storeFlags = TCL_LEAVE_ERR_MSG;
1842
  goto doStoreScalar;
1843
 
1844
    case INST_STORE_SCALAR1:
1845
  opnd = TclGetUInt1AtPtr(pc+1);
1846
  pcAdjustment = 2;
1847
  storeFlags = TCL_LEAVE_ERR_MSG;
1848
 
1849
    doStoreScalar:
1850
  valuePtr = stackPtr[stackTop];
1851
  varPtr = &(varFramePtr->compiledLocals[opnd]);
1852
  part1 = varPtr->name;
1853
  TRACE(("%u <- \"%.30s\" => ", opnd, O2S(valuePtr)));
1854
  while (TclIsVarLink(varPtr)) {
1855
      varPtr = varPtr->value.linkPtr;
1856
  }
1857
  cleanup = 1;
1858
  arrayPtr = NULL;
1859
  part2 = NULL;
1860
 
1861
    doCallPtrSetVar:
1862
  if ((storeFlags == TCL_LEAVE_ERR_MSG)
1863
          && !((varPtr->flags & VAR_IN_HASHTABLE)
1864
            && (varPtr->hPtr == NULL))
1865
          && (varPtr->tracePtr == NULL)
1866
          && (TclIsVarScalar(varPtr)
1867
            || TclIsVarUndefined(varPtr))
1868
          && ((arrayPtr == NULL)
1869
            || (arrayPtr->tracePtr == NULL))) {
1870
      /*
1871
       * No traces, no errors, plain 'set': we can safely inline.
1872
       * The value *will* be set to what's requested, so that
1873
       * the stack top remains pointing to the same Tcl_Obj.
1874
       */
1875
      valuePtr = varPtr->value.objPtr;
1876
      objResultPtr = stackPtr[stackTop];
1877
      if (valuePtr != objResultPtr) {
1878
    if (valuePtr != NULL) {
1879
        TclDecrRefCount(valuePtr);
1880
    } else {
1881
        TclSetVarScalar(varPtr);
1882
        TclClearVarUndefined(varPtr);
1883
    }
1884
    varPtr->value.objPtr = objResultPtr;
1885
    Tcl_IncrRefCount(objResultPtr);
1886
      }
1887
#ifndef TCL_COMPILE_DEBUG
1888
      if (*(pc+pcAdjustment) == INST_POP) {
1889
    NEXT_INST_V((pcAdjustment+1), cleanup, 0);
1890
      }
1891
#else
1892
  TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
1893
#endif
1894
      NEXT_INST_V(pcAdjustment, cleanup, 1);
1895
  } else {
1896
      DECACHE_STACK_INFO();
1897
      objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr,
1898
              part1, part2, valuePtr, storeFlags);
1899
      CACHE_STACK_INFO();
1900
      if (objResultPtr == NULL) {
1901
    TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
1902
    result = TCL_ERROR;
1903
    goto checkForCatch;
1904
      }
1905
  }
1906
#ifndef TCL_COMPILE_DEBUG
1907
  if (*(pc+pcAdjustment) == INST_POP) {
1908
      NEXT_INST_V((pcAdjustment+1), cleanup, 0);
1909
  }
1910
#endif
1911
  TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
1912
  NEXT_INST_V(pcAdjustment, cleanup, 1);
1913
 
1914
 
1915
    /*
1916
     *     End of INST_STORE and related instructions.
1917
     * ---------------------------------------------------------
1918
     */
1919
 
1920
    /*
1921
     * ---------------------------------------------------------
1922
     *     Start of INST_INCR instructions.
1923
     *
1924
     * WARNING: more 'goto' here than your doctor recommended!
1925
     * The different instructions set the value of some variables
1926
     * and then jump to somme common execution code.
1927
     */
1928
 
1929
    case INST_INCR_SCALAR1:
1930
    case INST_INCR_ARRAY1:
1931
    case INST_INCR_ARRAY_STK:
1932
    case INST_INCR_SCALAR_STK:
1933
    case INST_INCR_STK:
1934
  opnd = TclGetUInt1AtPtr(pc+1);
1935
  valuePtr = stackPtr[stackTop];
1936
  if (valuePtr->typePtr == &tclIntType) {
1937
      i = valuePtr->internalRep.longValue;
1938
  } else if (valuePtr->typePtr == &tclWideIntType) {
1939
      TclGetLongFromWide(i,valuePtr);
1940
  } else {
1941
      REQUIRE_WIDE_OR_INT(result, valuePtr, i, w);
1942
      if (result != TCL_OK) {
1943
    TRACE_WITH_OBJ(("%u (by %s) => ERROR converting increment amount to int: ",
1944
            opnd, O2S(valuePtr)), Tcl_GetObjResult(interp));
1945
    DECACHE_STACK_INFO();
1946
    Tcl_AddErrorInfo(interp, "\n    (reading increment)");
1947
    CACHE_STACK_INFO();
1948
    goto checkForCatch;
1949
      }
1950
      FORCE_LONG(valuePtr, i, w);
1951
  }
1952
  stackTop--;
1953
  TclDecrRefCount(valuePtr);
1954
  switch (*pc) {
1955
      case INST_INCR_SCALAR1:
1956
    pcAdjustment = 2;
1957
    goto doIncrScalar;
1958
      case INST_INCR_ARRAY1:
1959
    pcAdjustment = 2;
1960
    goto doIncrArray;
1961
      default:
1962
    pcAdjustment = 1;
1963
    goto doIncrStk;
1964
  }
1965
 
1966
    case INST_INCR_ARRAY_STK_IMM:
1967
    case INST_INCR_SCALAR_STK_IMM:
1968
    case INST_INCR_STK_IMM:
1969
  i = TclGetInt1AtPtr(pc+1);
1970
  pcAdjustment = 2;
1971
 
1972
    doIncrStk:
1973
  if ((*pc == INST_INCR_ARRAY_STK_IMM)
1974
          || (*pc == INST_INCR_ARRAY_STK)) {
1975
      part2 = TclGetString(stackPtr[stackTop]);
1976
      objPtr = stackPtr[stackTop - 1];
1977
      TRACE(("\"%.30s(%.30s)\" (by %ld) => ",
1978
        O2S(objPtr), part2, i));
1979
  } else {
1980
      part2 = NULL;
1981
      objPtr = stackPtr[stackTop];
1982
      TRACE(("\"%.30s\" (by %ld) => ", O2S(objPtr), i));
1983
  }
1984
  part1 = TclGetString(objPtr);
1985
 
1986
  varPtr = TclObjLookupVar(interp, objPtr, part2,
1987
          TCL_LEAVE_ERR_MSG, "read", 0, 1, &arrayPtr);
1988
  if (varPtr == NULL) {
1989
      DECACHE_STACK_INFO();
1990
      Tcl_AddObjErrorInfo(interp,
1991
              "\n    (reading value of variable to increment)", -1);
1992
      CACHE_STACK_INFO();
1993
      TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
1994
      result = TCL_ERROR;
1995
      goto checkForCatch;
1996
  }
1997
  cleanup = ((part2 == NULL)? 1 : 2);
1998
  goto doIncrVar;
1999
 
2000
    case INST_INCR_ARRAY1_IMM:
2001
  opnd = TclGetUInt1AtPtr(pc+1);
2002
  i = TclGetInt1AtPtr(pc+2);
2003
  pcAdjustment = 3;
2004
 
2005
    doIncrArray:
2006
  part2 = TclGetString(stackPtr[stackTop]);
2007
  arrayPtr = &(varFramePtr->compiledLocals[opnd]);
2008
  part1 = arrayPtr->name;
2009
  while (TclIsVarLink(arrayPtr)) {
2010
      arrayPtr = arrayPtr->value.linkPtr;
2011
  }
2012
  TRACE(("%u \"%.30s\" (by %ld) => ",
2013
        opnd, part2, i));
2014
  varPtr = TclLookupArrayElement(interp, part1, part2,
2015
          TCL_LEAVE_ERR_MSG, "read", 0, 1, arrayPtr);
2016
  if (varPtr == NULL) {
2017
      TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
2018
      result = TCL_ERROR;
2019
      goto checkForCatch;
2020
  }
2021
  cleanup = 1;
2022
  goto doIncrVar;
2023
 
2024
    case INST_INCR_SCALAR1_IMM:
2025
  opnd = TclGetUInt1AtPtr(pc+1);
2026
  i = TclGetInt1AtPtr(pc+2);
2027
  pcAdjustment = 3;
2028
 
2029
    doIncrScalar:
2030
  varPtr = &(varFramePtr->compiledLocals[opnd]);
2031
  part1 = varPtr->name;
2032
  while (TclIsVarLink(varPtr)) {
2033
      varPtr = varPtr->value.linkPtr;
2034
  }
2035
  arrayPtr = NULL;
2036
  part2 = NULL;
2037
  cleanup = 0;
2038
  TRACE(("%u %ld => ", opnd, i));
2039
 
2040
 
2041
    doIncrVar:
2042
  objPtr = varPtr->value.objPtr;
2043
  if (TclIsVarScalar(varPtr)
2044
          && !TclIsVarUndefined(varPtr)
2045
          && (varPtr->tracePtr == NULL)
2046
          && ((arrayPtr == NULL)
2047
            || (arrayPtr->tracePtr == NULL))
2048
          && (objPtr->typePtr == &tclIntType)) {
2049
      /*
2050
       * No errors, no traces, the variable already has an
2051
       * integer value: inline processing.
2052
       */
2053
 
2054
      i += objPtr->internalRep.longValue;
2055
      if (Tcl_IsShared(objPtr)) {
2056
    objResultPtr = Tcl_NewLongObj(i);
2057
    TclDecrRefCount(objPtr);
2058
    Tcl_IncrRefCount(objResultPtr);
2059
    varPtr->value.objPtr = objResultPtr;
2060
      } else {
2061
    Tcl_SetLongObj(objPtr, i);
2062
    objResultPtr = objPtr;
2063
      }
2064
      TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
2065
  } else {
2066
      DECACHE_STACK_INFO();
2067
      objResultPtr = TclPtrIncrVar(interp, varPtr, arrayPtr, part1,
2068
                    part2, i, TCL_LEAVE_ERR_MSG);
2069
      CACHE_STACK_INFO();
2070
      if (objResultPtr == NULL) {
2071
    TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
2072
    result = TCL_ERROR;
2073
    goto checkForCatch;
2074
      }
2075
  }
2076
  TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
2077
#ifndef TCL_COMPILE_DEBUG
2078
  if (*(pc+pcAdjustment) == INST_POP) {
2079
      NEXT_INST_V((pcAdjustment+1), cleanup, 0);
2080
  }
2081
#endif
2082
  NEXT_INST_V(pcAdjustment, cleanup, 1);
2083
 
2084
    /*
2085
     *     End of INST_INCR instructions.
2086
     * ---------------------------------------------------------
2087
     */
2088
 
2089
 
2090
    case INST_JUMP1:
2091
  opnd = TclGetInt1AtPtr(pc+1);
2092
  TRACE(("%d => new pc %u\n", opnd,
2093
          (unsigned int)(pc + opnd - codePtr->codeStart)));
2094
  NEXT_INST_F(opnd, 0, 0);
2095
 
2096
    case INST_JUMP4:
2097
  opnd = TclGetInt4AtPtr(pc+1);
2098
  TRACE(("%d => new pc %u\n", opnd,
2099
          (unsigned int)(pc + opnd - codePtr->codeStart)));
2100
  NEXT_INST_F(opnd, 0, 0);
2101
 
2102
    case INST_JUMP_FALSE4:
2103
  opnd = 5;                             /* TRUE */
2104
  pcAdjustment = TclGetInt4AtPtr(pc+1); /* FALSE */
2105
  goto doJumpTrue;
2106
 
2107
    case INST_JUMP_TRUE4:
2108
  opnd = TclGetInt4AtPtr(pc+1);         /* TRUE */
2109
  pcAdjustment = 5;                     /* FALSE */
2110
  goto doJumpTrue;
2111
 
2112
    case INST_JUMP_FALSE1:
2113
  opnd = 2;                             /* TRUE */
2114
  pcAdjustment = TclGetInt1AtPtr(pc+1); /* FALSE */
2115
  goto doJumpTrue;
2116
 
2117
    case INST_JUMP_TRUE1:
2118
  opnd = TclGetInt1AtPtr(pc+1);          /* TRUE */
2119
  pcAdjustment = 2;                      /* FALSE */
2120
 
2121
    doJumpTrue:
2122
  {
2123
      int b;
2124
 
2125
      valuePtr = stackPtr[stackTop];
2126
      if (valuePtr->typePtr == &tclIntType) {
2127
    b = (valuePtr->internalRep.longValue != 0);
2128
      } else if (valuePtr->typePtr == &tclDoubleType) {
2129
    b = (valuePtr->internalRep.doubleValue != 0.0);
2130
      } else if (valuePtr->typePtr == &tclWideIntType) {
2131
    TclGetWide(w,valuePtr);
2132
    b = (w != W0);
2133
      } else {
2134
    result = Tcl_GetBooleanFromObj(interp, valuePtr, &b);
2135
    if (result != TCL_OK) {
2136
        TRACE_WITH_OBJ(("%d => ERROR: ", opnd), Tcl_GetObjResult(interp));
2137
        goto checkForCatch;
2138
    }
2139
      }
2140
#ifndef TCL_COMPILE_DEBUG
2141
      NEXT_INST_F((b? opnd : pcAdjustment), 1, 0);
2142
#else
2143
      if (b) {
2144
    if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE1)) {
2145
        TRACE(("%d => %.20s true, new pc %u\n", opnd, O2S(valuePtr),
2146
                (unsigned int)(pc+opnd - codePtr->codeStart)));
2147
    } else {
2148
        TRACE(("%d => %.20s true\n", pcAdjustment, O2S(valuePtr)));
2149
    }
2150
    NEXT_INST_F(opnd, 1, 0);
2151
      } else {
2152
    if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE1)) {
2153
        TRACE(("%d => %.20s false\n", opnd, O2S(valuePtr)));
2154
    } else {
2155
        opnd = pcAdjustment;
2156
        TRACE(("%d => %.20s false, new pc %u\n", opnd, O2S(valuePtr),
2157
                (unsigned int)(pc + opnd - codePtr->codeStart)));
2158
    }
2159
    NEXT_INST_F(pcAdjustment, 1, 0);
2160
      }
2161
#endif
2162
  }
2163
 
2164
    case INST_LOR:
2165
    case INST_LAND:
2166
    {
2167
  /*
2168
   * Operands must be boolean or numeric. No int->double
2169
   * conversions are performed.
2170
   */
2171
 
2172
  int i1, i2;
2173
  int iResult;
2174
  char *s;
2175
  Tcl_ObjType *t1Ptr, *t2Ptr;
2176
 
2177
  value2Ptr = stackPtr[stackTop];
2178
  valuePtr  = stackPtr[stackTop - 1];;
2179
  t1Ptr = valuePtr->typePtr;
2180
  t2Ptr = value2Ptr->typePtr;
2181
 
2182
  if ((t1Ptr == &tclIntType) || (t1Ptr == &tclBooleanType)) {
2183
      i1 = (valuePtr->internalRep.longValue != 0);
2184
  } else if (t1Ptr == &tclWideIntType) {
2185
      TclGetWide(w,valuePtr);
2186
      i1 = (w != W0);
2187
  } else if (t1Ptr == &tclDoubleType) {
2188
      i1 = (valuePtr->internalRep.doubleValue != 0.0);
2189
  } else {
2190
      s = Tcl_GetStringFromObj(valuePtr, &length);
2191
      if (TclLooksLikeInt(s, length)) {
2192
    GET_WIDE_OR_INT(result, valuePtr, i, w);
2193
    if (valuePtr->typePtr == &tclIntType) {
2194
        i1 = (i != 0);
2195
    } else {
2196
        i1 = (w != W0);
2197
    }
2198
      } else {
2199
    result = Tcl_GetBooleanFromObj((Tcl_Interp *) NULL,
2200
                 valuePtr, &i1);
2201
    i1 = (i1 != 0);
2202
      }
2203
      if (result != TCL_OK) {
2204
    TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr),
2205
            (t1Ptr? t1Ptr->name : "null")));
2206
    DECACHE_STACK_INFO();
2207
    IllegalExprOperandType(interp, pc, valuePtr);
2208
    CACHE_STACK_INFO();
2209
    goto checkForCatch;
2210
      }
2211
  }
2212
 
2213
  if ((t2Ptr == &tclIntType) || (t2Ptr == &tclBooleanType)) {
2214
      i2 = (value2Ptr->internalRep.longValue != 0);
2215
  } else if (t2Ptr == &tclWideIntType) {
2216
      TclGetWide(w,value2Ptr);
2217
      i2 = (w != W0);
2218
  } else if (t2Ptr == &tclDoubleType) {
2219
      i2 = (value2Ptr->internalRep.doubleValue != 0.0);
2220
  } else {
2221
      s = Tcl_GetStringFromObj(value2Ptr, &length);
2222
      if (TclLooksLikeInt(s, length)) {
2223
    GET_WIDE_OR_INT(result, value2Ptr, i, w);
2224
    if (value2Ptr->typePtr == &tclIntType) {
2225
        i2 = (i != 0);
2226
    } else {
2227
        i2 = (w != W0);
2228
    }
2229
      } else {
2230
    result = Tcl_GetBooleanFromObj((Tcl_Interp *) NULL, value2Ptr, &i2);
2231
      }
2232
      if (result != TCL_OK) {
2233
    TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(value2Ptr),
2234
            (t2Ptr? t2Ptr->name : "null")));
2235
    DECACHE_STACK_INFO();
2236
    IllegalExprOperandType(interp, pc, value2Ptr);
2237
    CACHE_STACK_INFO();
2238
    goto checkForCatch;
2239
      }
2240
  }
2241
 
2242
  /*
2243
   * Reuse the valuePtr object already on stack if possible.
2244
   */
2245
 
2246
  if (*pc == INST_LOR) {
2247
      iResult = (i1 || i2);
2248
  } else {
2249
      iResult = (i1 && i2);
2250
  }
2251
  if (Tcl_IsShared(valuePtr)) {
2252
      objResultPtr = Tcl_NewLongObj(iResult);
2253
      TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
2254
      NEXT_INST_F(1, 2, 1);
2255
  } else {  /* reuse the valuePtr object */
2256
      TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
2257
      Tcl_SetLongObj(valuePtr, iResult);
2258
      NEXT_INST_F(1, 1, 0);
2259
  }
2260
    }
2261
 
2262
    /*
2263
     * ---------------------------------------------------------
2264
     *     Start of INST_LIST and related instructions.
2265
     */
2266
 
2267
    case INST_LIST:
2268
  /*
2269
   * Pop the opnd (objc) top stack elements into a new list obj
2270
   * and then decrement their ref counts.
2271
   */
2272
 
2273
  opnd = TclGetUInt4AtPtr(pc+1);
2274
  objResultPtr = Tcl_NewListObj(opnd, &(stackPtr[stackTop - (opnd-1)]));
2275
  TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
2276
  NEXT_INST_V(5, opnd, 1);
2277
 
2278
    case INST_LIST_LENGTH:
2279
  valuePtr = stackPtr[stackTop];
2280
 
2281
  result = Tcl_ListObjLength(interp, valuePtr, &length);
2282
  if (result != TCL_OK) {
2283
      TRACE_WITH_OBJ(("%.30s => ERROR: ", O2S(valuePtr)),
2284
              Tcl_GetObjResult(interp));
2285
      goto checkForCatch;
2286
  }
2287
  objResultPtr = Tcl_NewIntObj(length);
2288
  TRACE(("%.20s => %d\n", O2S(valuePtr), length));
2289
  NEXT_INST_F(1, 1, 1);
2290
 
2291
    case INST_LIST_INDEX:
2292
  /*** lindex with objc == 3 ***/
2293
 
2294
  /*
2295
   * Pop the two operands
2296
   */
2297
  value2Ptr = stackPtr[stackTop];
2298
  valuePtr  = stackPtr[stackTop- 1];
2299
 
2300
  /*
2301
   * Extract the desired list element
2302
   */
2303
  objResultPtr = TclLindexList(interp, valuePtr, value2Ptr);
2304
  if (objResultPtr == NULL) {
2305
      TRACE_WITH_OBJ(("%.30s %.30s => ERROR: ", O2S(valuePtr), O2S(value2Ptr)),
2306
              Tcl_GetObjResult(interp));
2307
      result = TCL_ERROR;
2308
      goto checkForCatch;
2309
  }
2310
 
2311
  /*
2312
   * Stash the list element on the stack
2313
   */
2314
  TRACE(("%.20s %.20s => %s\n",
2315
          O2S(valuePtr), O2S(value2Ptr), O2S(objResultPtr)));
2316
  NEXT_INST_F(1, 2, -1); /* already has the correct refCount */
2317
 
2318
    case INST_LIST_INDEX_MULTI:
2319
    {
2320
  /*
2321
   * 'lindex' with multiple index args:
2322
   *
2323
   * Determine the count of index args.
2324
   */
2325
 
2326
  int numIdx;
2327
 
2328
  opnd = TclGetUInt4AtPtr(pc+1);
2329
  numIdx = opnd-1;
2330
 
2331
  /*
2332
   * Do the 'lindex' operation.
2333
   */
2334
  objResultPtr = TclLindexFlat(interp, stackPtr[stackTop - numIdx],
2335
          numIdx, stackPtr + stackTop - numIdx + 1);
2336
 
2337
  /*
2338
   * Check for errors
2339
   */
2340
  if (objResultPtr == NULL) {
2341
      TRACE_WITH_OBJ(("%d => ERROR: ", opnd), Tcl_GetObjResult(interp));
2342
      result = TCL_ERROR;
2343
      goto checkForCatch;
2344
  }
2345
 
2346
  /*
2347
   * Set result
2348
   */
2349
  TRACE(("%d => %s\n", opnd, O2S(objResultPtr)));
2350
  NEXT_INST_V(5, opnd, -1);
2351
    }
2352
 
2353
    case INST_LSET_FLAT:
2354
    {
2355
  /*
2356
   * Lset with 3, 5, or more args.  Get the number
2357
   * of index args.
2358
   */
2359
  int numIdx;
2360
 
2361
  opnd = TclGetUInt4AtPtr( pc + 1 );
2362
  numIdx = opnd - 2;
2363
 
2364
  /*
2365
   * Get the old value of variable, and remove the stack ref.
2366
   * This is safe because the variable still references the
2367
   * object; the ref count will never go zero here.
2368
   */
2369
  value2Ptr = POP_OBJECT();
2370
  TclDecrRefCount(value2Ptr); /* This one should be done here */
2371
 
2372
  /*
2373
   * Get the new element value.
2374
   */
2375
  valuePtr = stackPtr[stackTop];
2376
 
2377
  /*
2378
   * Compute the new variable value
2379
   */
2380
  objResultPtr = TclLsetFlat(interp, value2Ptr, numIdx,
2381
          stackPtr + stackTop - numIdx, valuePtr);
2382
 
2383
 
2384
  /*
2385
   * Check for errors
2386
   */
2387
  if (objResultPtr == NULL) {
2388
      TRACE_WITH_OBJ(("%d => ERROR: ", opnd), Tcl_GetObjResult(interp));
2389
      result = TCL_ERROR;
2390
      goto checkForCatch;
2391
  }
2392
 
2393
  /*
2394
   * Set result
2395
   */
2396
  TRACE(("%d => %s\n", opnd, O2S(objResultPtr)));
2397
  NEXT_INST_V(5, (numIdx+1), -1);
2398
    }
2399
 
2400
    case INST_LSET_LIST:
2401
  /*
2402
   * 'lset' with 4 args.
2403
   *
2404
   * Get the old value of variable, and remove the stack ref.
2405
   * This is safe because the variable still references the
2406
   * object; the ref count will never go zero here.
2407
   */
2408
  objPtr = POP_OBJECT();
2409
  TclDecrRefCount(objPtr); /* This one should be done here */
2410
 
2411
  /*
2412
   * Get the new element value, and the index list
2413
   */
2414
  valuePtr = stackPtr[stackTop];
2415
  value2Ptr = stackPtr[stackTop - 1];
2416
 
2417
  /*
2418
   * Compute the new variable value
2419
   */
2420
  objResultPtr = TclLsetList(interp, objPtr, value2Ptr, valuePtr);
2421
 
2422
  /*
2423
   * Check for errors
2424
   */
2425
  if (objResultPtr == NULL) {
2426
      TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ", O2S(value2Ptr)),
2427
              Tcl_GetObjResult(interp));
2428
      result = TCL_ERROR;
2429
      goto checkForCatch;
2430
  }
2431
 
2432
  /*
2433
   * Set result
2434
   */
2435
  TRACE(("=> %s\n", O2S(objResultPtr)));
2436
  NEXT_INST_F(1, 2, -1);
2437
 
2438
    /*
2439
     *     End of INST_LIST and related instructions.
2440
     * ---------------------------------------------------------
2441
     */
2442
 
2443
    case INST_STR_EQ:
2444
    case INST_STR_NEQ:
2445
    {
2446
  /*
2447
   * String (in)equality check
2448
   */
2449
  int iResult;
2450
 
2451
  value2Ptr = stackPtr[stackTop];
2452
  valuePtr = stackPtr[stackTop - 1];
2453
 
2454
  if (valuePtr == value2Ptr) {
2455
      /*
2456
       * On the off-chance that the objects are the same,
2457
       * we don't really have to think hard about equality.
2458
       */
2459
      iResult = (*pc == INST_STR_EQ);
2460
  } else {
2461
      char *s1, *s2;
2462
      int s1len, s2len;
2463
 
2464
      s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
2465
      s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
2466
      if (s1len == s2len) {
2467
    /*
2468
     * We only need to check (in)equality when
2469
     * we have equal length strings.
2470
     */
2471
    if (*pc == INST_STR_NEQ) {
2472
        iResult = (strcmp(s1, s2) != 0);
2473
    } else {
2474
        /* INST_STR_EQ */
2475
        iResult = (strcmp(s1, s2) == 0);
2476
    }
2477
      } else {
2478
    iResult = (*pc == INST_STR_NEQ);
2479
      }
2480
  }
2481
 
2482
  TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
2483
 
2484
  /*
2485
   * Peep-hole optimisation: if you're about to jump, do jump
2486
   * from here.
2487
   */
2488
 
2489
  pc++;
2490
#ifndef TCL_COMPILE_DEBUG
2491
  switch (*pc) {
2492
      case INST_JUMP_FALSE1:
2493
    NEXT_INST_F((iResult? 2 : TclGetInt1AtPtr(pc+1)), 2, 0);
2494
      case INST_JUMP_TRUE1:
2495
    NEXT_INST_F((iResult? TclGetInt1AtPtr(pc+1) : 2), 2, 0);
2496
      case INST_JUMP_FALSE4:
2497
    NEXT_INST_F((iResult? 5 : TclGetInt4AtPtr(pc+1)), 2, 0);
2498
      case INST_JUMP_TRUE4:
2499
    NEXT_INST_F((iResult? TclGetInt4AtPtr(pc+1) : 5), 2, 0);
2500
  }
2501
#endif
2502
  objResultPtr = Tcl_NewIntObj(iResult);
2503
  NEXT_INST_F(0, 2, 1);
2504
    }
2505
 
2506
    case INST_STR_CMP:
2507
    {
2508
  /*
2509
   * String compare
2510
   */
2511
  CONST char *s1, *s2;
2512
  int s1len, s2len, iResult;
2513
 
2514
  value2Ptr = stackPtr[stackTop];
2515
  valuePtr = stackPtr[stackTop - 1];
2516
 
2517
  /*
2518
   * The comparison function should compare up to the
2519
   * minimum byte length only.
2520
   */
2521
  if (valuePtr == value2Ptr) {
2522
      /*
2523
       * In the pure equality case, set lengths too for
2524
       * the checks below (or we could goto beyond it).
2525
       */
2526
      iResult = s1len = s2len = 0;
2527
  } else if ((valuePtr->typePtr == &tclByteArrayType)
2528
          && (value2Ptr->typePtr == &tclByteArrayType)) {
2529
      s1 = (char *) Tcl_GetByteArrayFromObj(valuePtr, &s1len);
2530
      s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len);
2531
      iResult = memcmp(s1, s2,
2532
              (size_t) ((s1len < s2len) ? s1len : s2len));
2533
  } else if (((valuePtr->typePtr == &tclStringType)
2534
          && (value2Ptr->typePtr == &tclStringType))) {
2535
      /*
2536
       * Do a unicode-specific comparison if both of the args are of
2537
       * String type.  If the char length == byte length, we can do a
2538
       * memcmp.  In benchmark testing this proved the most efficient
2539
       * check between the unicode and string comparison operations.
2540
       */
2541
 
2542
      s1len = Tcl_GetCharLength(valuePtr);
2543
      s2len = Tcl_GetCharLength(value2Ptr);
2544
      if ((s1len == valuePtr->length) && (s2len == value2Ptr->length)) {
2545
    iResult = memcmp(valuePtr->bytes, value2Ptr->bytes,
2546
      (unsigned) ((s1len < s2len) ? s1len : s2len));
2547
      } else {
2548
    iResult = TclUniCharNcmp(Tcl_GetUnicode(valuePtr),
2549
      Tcl_GetUnicode(value2Ptr),
2550
      (unsigned) ((s1len < s2len) ? s1len : s2len));
2551
      }
2552
  } else {
2553
      /*
2554
       * We can't do a simple memcmp in order to handle the
2555
       * special Tcl \xC0\x80 null encoding for utf-8.
2556
       */
2557
      s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
2558
      s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
2559
      iResult = TclpUtfNcmp2(s1, s2,
2560
              (size_t) ((s1len < s2len) ? s1len : s2len));
2561
  }
2562
 
2563
  /*
2564
   * Make sure only -1,0,1 is returned
2565
   */
2566
  if (iResult == 0) {
2567
      iResult = s1len - s2len;
2568
  }
2569
  if (iResult < 0) {
2570
      iResult = -1;
2571
  } else if (iResult > 0) {
2572
      iResult = 1;
2573
  }
2574
 
2575
  objResultPtr = Tcl_NewIntObj(iResult);
2576
  TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
2577
  NEXT_INST_F(1, 2, 1);
2578
    }
2579
 
2580
    case INST_STR_LEN:
2581
    {
2582
  int length1;
2583
 
2584
  valuePtr = stackPtr[stackTop];
2585
 
2586
  if (valuePtr->typePtr == &tclByteArrayType) {
2587
      (void) Tcl_GetByteArrayFromObj(valuePtr, &length1);
2588
  } else {
2589
      length1 = Tcl_GetCharLength(valuePtr);
2590
  }
2591
  objResultPtr = Tcl_NewIntObj(length1);
2592
  TRACE(("%.20s => %d\n", O2S(valuePtr), length1));
2593
  NEXT_INST_F(1, 1, 1);
2594
    }
2595
 
2596
    case INST_STR_INDEX:
2597
    {
2598
  /*
2599
   * String compare
2600
   */
2601
  int index;
2602
  bytes = NULL; /* lint */
2603
 
2604
  value2Ptr = stackPtr[stackTop];
2605
  valuePtr = stackPtr[stackTop - 1];
2606
 
2607
  /*
2608
   * If we have a ByteArray object, avoid indexing in the
2609
   * Utf string since the byte array contains one byte per
2610
   * character.  Otherwise, use the Unicode string rep to
2611
   * get the index'th char.
2612
   */
2613
 
2614
  if (valuePtr->typePtr == &tclByteArrayType) {
2615
      bytes = (char *)Tcl_GetByteArrayFromObj(valuePtr, &length);
2616
  } else {
2617
      /*
2618
       * Get Unicode char length to calulate what 'end' means.
2619
       */
2620
      length = Tcl_GetCharLength(valuePtr);
2621
  }
2622
 
2623
  result = TclGetIntForIndex(interp, value2Ptr, length - 1, &index);
2624
  if (result != TCL_OK) {
2625
      goto checkForCatch;
2626
  }
2627
 
2628
  if ((index >= 0) && (index < length)) {
2629
      if (valuePtr->typePtr == &tclByteArrayType) {
2630
    objResultPtr = Tcl_NewByteArrayObj((unsigned char *)
2631
            (&bytes[index]), 1);
2632
      } else if (valuePtr->bytes && length == valuePtr->length) {
2633
    objResultPtr = Tcl_NewStringObj((CONST char *)
2634
            (&valuePtr->bytes[index]), 1);
2635
      } else {
2636
    char buf[TCL_UTF_MAX];
2637
    Tcl_UniChar ch;
2638
 
2639
    ch = Tcl_GetUniChar(valuePtr, index);
2640
    /*
2641
     * This could be:
2642
     * Tcl_NewUnicodeObj((CONST Tcl_UniChar *)&ch, 1)
2643
     * but creating the object as a string seems to be
2644
     * faster in practical use.
2645
     */
2646
    length = Tcl_UniCharToUtf(ch, buf);
2647
    objResultPtr = Tcl_NewStringObj(buf, length);
2648
      }
2649
  } else {
2650
      TclNewObj(objResultPtr);
2651
  }
2652
 
2653
  TRACE(("%.20s %.20s => %s\n", O2S(valuePtr), O2S(value2Ptr),
2654
          O2S(objResultPtr)));
2655
  NEXT_INST_F(1, 2, 1);
2656
    }
2657
 
2658
    case INST_STR_MATCH:
2659
    {
2660
  int nocase, match;
2661
 
2662
  nocase    = TclGetInt1AtPtr(pc+1);
2663
  valuePtr  = stackPtr[stackTop];         /* String */
2664
  value2Ptr = stackPtr[stackTop - 1]; /* Pattern */
2665
 
2666
  /*
2667
   * Check that at least one of the objects is Unicode before
2668
   * promoting both.
2669
   */
2670
 
2671
  if ((valuePtr->typePtr == &tclStringType)
2672
          || (value2Ptr->typePtr == &tclStringType)) {
2673
      Tcl_UniChar *ustring1, *ustring2;
2674
      int length1, length2;
2675
 
2676
      ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &length1);
2677
      ustring2 = Tcl_GetUnicodeFromObj(value2Ptr, &length2);
2678
      match = TclUniCharMatch(ustring1, length1, ustring2, length2,
2679
        nocase);
2680
  } else {
2681
      match = Tcl_StringCaseMatch(TclGetString(valuePtr),
2682
        TclGetString(value2Ptr), nocase);
2683
  }
2684
 
2685
  /*
2686
   * Reuse value2Ptr object already on stack if possible.
2687
   * Adjustment is 2 due to the nocase byte
2688
   */
2689
 
2690
  TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), match));
2691
  if (Tcl_IsShared(value2Ptr)) {
2692
      objResultPtr = Tcl_NewIntObj(match);
2693
      NEXT_INST_F(2, 2, 1);
2694
  } else {  /* reuse the valuePtr object */
2695
      Tcl_SetIntObj(value2Ptr, match);
2696
      NEXT_INST_F(2, 1, 0);
2697
  }
2698
    }
2699
 
2700
    case INST_EQ:
2701
    case INST_NEQ:
2702
    case INST_LT:
2703
    case INST_GT:
2704
    case INST_LE:
2705
    case INST_GE:
2706
    {
2707
  /*
2708
   * Any type is allowed but the two operands must have the
2709
   * same type. We will compute value op value2.
2710
   */
2711
 
2712
  Tcl_ObjType *t1Ptr, *t2Ptr;
2713
  char *s1 = NULL;  /* Init. avoids compiler warning. */
2714
  char *s2 = NULL;  /* Init. avoids compiler warning. */
2715
  long i2 = 0;    /* Init. avoids compiler warning. */
2716
  double d1 = 0.0;  /* Init. avoids compiler warning. */
2717
  double d2 = 0.0;  /* Init. avoids compiler warning. */
2718
  long iResult = 0; /* Init. avoids compiler warning. */
2719
 
2720
  value2Ptr = stackPtr[stackTop];
2721
  valuePtr  = stackPtr[stackTop - 1];
2722
 
2723
  /*
2724
   * Be careful in the equal-object case; 'NaN' isn't supposed
2725
   * to be equal to even itself. [Bug 761471]
2726
   */
2727
 
2728
  t1Ptr = valuePtr->typePtr;
2729
  if (valuePtr == value2Ptr) {
2730
      /*
2731
       * If we are numeric already, we can proceed to the main
2732
       * equality check right now.  Otherwise, we need to try to
2733
       * coerce to a numeric type so we can see if we've got a
2734
       * NaN but haven't parsed it as numeric.
2735
       */
2736
      if (!IS_NUMERIC_TYPE(t1Ptr)) {
2737
    if (t1Ptr == &tclListType) {
2738
        int length;
2739
        /*
2740
         * Only a list of length 1 can be NaN or such
2741
         * things.
2742
         */
2743
        (void) Tcl_ListObjLength(NULL, valuePtr, &length);
2744
        if (length == 1) {
2745
      goto mustConvertForNaNCheck;
2746
        }
2747
    } else {
2748
        /*
2749
         * Too bad, we'll have to compute the string and
2750
         * try the conversion
2751
         */
2752
 
2753
      mustConvertForNaNCheck:
2754
        s1 = Tcl_GetStringFromObj(valuePtr, &length);
2755
        if (TclLooksLikeInt(s1, length)) {
2756
      GET_WIDE_OR_INT(iResult, valuePtr, i, w);
2757
        } else {
2758
      (void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
2759
        valuePtr, &d1);
2760
        }
2761
        t1Ptr = valuePtr->typePtr;
2762
    }
2763
      }
2764
 
2765
      switch (*pc) {
2766
      case INST_EQ:
2767
      case INST_LE:
2768
      case INST_GE:
2769
    iResult = !((t1Ptr == &tclDoubleType)
2770
      && IS_NAN(valuePtr->internalRep.doubleValue));
2771
    break;
2772
      case INST_LT:
2773
      case INST_GT:
2774
    iResult = 0;
2775
    break;
2776
      case INST_NEQ:
2777
    iResult = ((t1Ptr == &tclDoubleType)
2778
      && IS_NAN(valuePtr->internalRep.doubleValue));
2779
    break;
2780
      }
2781
      goto foundResult;
2782
  }
2783
 
2784
  t2Ptr = value2Ptr->typePtr;
2785
 
2786
  /*
2787
   * We only want to coerce numeric validation if neither type
2788
   * is NULL.  A NULL type means the arg is essentially an empty
2789
   * object ("", {} or [list]).
2790
   */
2791
  if (!(     (!t1Ptr && !valuePtr->bytes)
2792
          || (valuePtr->bytes && !valuePtr->length)
2793
       || (!t2Ptr && !value2Ptr->bytes)
2794
       || (value2Ptr->bytes && !value2Ptr->length))) {
2795
      if (!IS_NUMERIC_TYPE(t1Ptr)) {
2796
    s1 = Tcl_GetStringFromObj(valuePtr, &length);
2797
    if (TclLooksLikeInt(s1, length)) {
2798
        GET_WIDE_OR_INT(iResult, valuePtr, i, w);
2799
    } else {
2800
        (void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
2801
                valuePtr, &d1);
2802
    }
2803
    t1Ptr = valuePtr->typePtr;
2804
      }
2805
      if (!IS_NUMERIC_TYPE(t2Ptr)) {
2806
    s2 = Tcl_GetStringFromObj(value2Ptr, &length);
2807
    if (TclLooksLikeInt(s2, length)) {
2808
        GET_WIDE_OR_INT(iResult, value2Ptr, i2, w);
2809
    } else {
2810
        (void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
2811
                value2Ptr, &d2);
2812
    }
2813
    t2Ptr = value2Ptr->typePtr;
2814
      }
2815
  }
2816
  if (!IS_NUMERIC_TYPE(t1Ptr) || !IS_NUMERIC_TYPE(t2Ptr)) {
2817
      /*
2818
       * One operand is not numeric. Compare as strings.  NOTE:
2819
       * strcmp is not correct for \x00 < \x01, but that is
2820
       * unlikely to occur here.  We could use the TclUtfNCmp2
2821
       * to handle this.
2822
       */
2823
      int s1len, s2len;
2824
      s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
2825
      s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
2826
      switch (*pc) {
2827
          case INST_EQ:
2828
        if (s1len == s2len) {
2829
      iResult = (strcmp(s1, s2) == 0);
2830
        } else {
2831
      iResult = 0;
2832
        }
2833
        break;
2834
          case INST_NEQ:
2835
        if (s1len == s2len) {
2836
      iResult = (strcmp(s1, s2) != 0);
2837
        } else {
2838
      iResult = 1;
2839
        }
2840
        break;
2841
          case INST_LT:
2842
        iResult = (strcmp(s1, s2) < 0);
2843
        break;
2844
          case INST_GT:
2845
        iResult = (strcmp(s1, s2) > 0);
2846
        break;
2847
          case INST_LE:
2848
        iResult = (strcmp(s1, s2) <= 0);
2849
        break;
2850
          case INST_GE:
2851
        iResult = (strcmp(s1, s2) >= 0);
2852
        break;
2853
      }
2854
  } else if ((t1Ptr == &tclDoubleType)
2855
       || (t2Ptr == &tclDoubleType)) {
2856
      /*
2857
       * Compare as doubles.
2858
       */
2859
      if (t1Ptr == &tclDoubleType) {
2860
    d1 = valuePtr->internalRep.doubleValue;
2861
    GET_DOUBLE_VALUE(d2, value2Ptr, t2Ptr);
2862
      } else {  /* t1Ptr is integer, t2Ptr is double */
2863
    GET_DOUBLE_VALUE(d1, valuePtr, t1Ptr);
2864
    d2 = value2Ptr->internalRep.doubleValue;
2865
      }
2866
      switch (*pc) {
2867
          case INST_EQ:
2868
        iResult = d1 == d2;
2869
        break;
2870
          case INST_NEQ:
2871
        iResult = d1 != d2;
2872
        break;
2873
          case INST_LT:
2874
        iResult = d1 < d2;
2875
        break;
2876
          case INST_GT:
2877
        iResult = d1 > d2;
2878
        break;
2879
          case INST_LE:
2880
        iResult = d1 <= d2;
2881
        break;
2882
          case INST_GE:
2883
        iResult = d1 >= d2;
2884
        break;
2885
      }
2886
  } else if ((t1Ptr == &tclWideIntType)
2887
          || (t2Ptr == &tclWideIntType)) {
2888
      Tcl_WideInt w2;
2889
      /*
2890
       * Compare as wide ints (neither are doubles)
2891
       */
2892
      if (t1Ptr == &tclIntType) {
2893
    w  = Tcl_LongAsWide(valuePtr->internalRep.longValue);
2894
    TclGetWide(w2,value2Ptr);
2895
      } else if (t2Ptr == &tclIntType) {
2896
    TclGetWide(w,valuePtr);
2897
    w2 = Tcl_LongAsWide(value2Ptr->internalRep.longValue);
2898
      } else {
2899
    TclGetWide(w,valuePtr);
2900
    TclGetWide(w2,value2Ptr);
2901
      }
2902
      switch (*pc) {
2903
          case INST_EQ:
2904
        iResult = w == w2;
2905
        break;
2906
          case INST_NEQ:
2907
        iResult = w != w2;
2908
        break;
2909
          case INST_LT:
2910
        iResult = w < w2;
2911
        break;
2912
          case INST_GT:
2913
        iResult = w > w2;
2914
        break;
2915
          case INST_LE:
2916
        iResult = w <= w2;
2917
        break;
2918
          case INST_GE:
2919
        iResult = w >= w2;
2920
        break;
2921
      }
2922
  } else {
2923
      /*
2924
       * Compare as ints.
2925
       */
2926
      i  = valuePtr->internalRep.longValue;
2927
      i2 = value2Ptr->internalRep.longValue;
2928
      switch (*pc) {
2929
          case INST_EQ:
2930
        iResult = i == i2;
2931
        break;
2932
          case INST_NEQ:
2933
        iResult = i != i2;
2934
        break;
2935
          case INST_LT:
2936
        iResult = i < i2;
2937
        break;
2938
          case INST_GT:
2939
        iResult = i > i2;
2940
        break;
2941
          case INST_LE:
2942
        iResult = i <= i2;
2943
        break;
2944
          case INST_GE:
2945
        iResult = i >= i2;
2946
        break;
2947
      }
2948
  }
2949
 
2950
    foundResult:
2951
  TRACE(("%.20s %.20s => %ld\n", O2S(valuePtr), O2S(value2Ptr), iResult));
2952
 
2953
  /*
2954
   * Peep-hole optimisation: if you're about to jump, do jump
2955
   * from here.
2956
   */
2957
 
2958
  pc++;
2959
#ifndef TCL_COMPILE_DEBUG
2960
  switch (*pc) {
2961
      case INST_JUMP_FALSE1:
2962
    NEXT_INST_F((iResult? 2 : TclGetInt1AtPtr(pc+1)), 2, 0);
2963
      case INST_JUMP_TRUE1:
2964
    NEXT_INST_F((iResult? TclGetInt1AtPtr(pc+1) : 2), 2, 0);
2965
      case INST_JUMP_FALSE4:
2966
    NEXT_INST_F((iResult? 5 : TclGetInt4AtPtr(pc+1)), 2, 0);
2967
      case INST_JUMP_TRUE4:
2968
    NEXT_INST_F((iResult? TclGetInt4AtPtr(pc+1) : 5), 2, 0);
2969
  }
2970
#endif
2971
  objResultPtr = Tcl_NewIntObj(iResult);
2972
  NEXT_INST_F(0, 2, 1);
2973
    }
2974
 
2975
    case INST_MOD:
2976
    case INST_LSHIFT:
2977
    case INST_RSHIFT:
2978
    case INST_BITOR:
2979
    case INST_BITXOR:
2980
    case INST_BITAND:
2981
    {
2982
  /*
2983
   * Only integers are allowed. We compute value op value2.
2984
   */
2985
 
2986
  long i2 = 0, rem, negative;
2987
  long iResult = 0; /* Init. avoids compiler warning. */
2988
  Tcl_WideInt w2, wResult = W0;
2989
  int doWide = 0;
2990
 
2991
  value2Ptr = stackPtr[stackTop];
2992
  valuePtr  = stackPtr[stackTop - 1];
2993
  if (valuePtr->typePtr == &tclIntType) {
2994
      i = valuePtr->internalRep.longValue;
2995
  } else if (valuePtr->typePtr == &tclWideIntType) {
2996
      TclGetWide(w,valuePtr);
2997
  } else {  /* try to convert to int */
2998
      REQUIRE_WIDE_OR_INT(result, valuePtr, i, w);
2999
      if (result != TCL_OK) {
3000
    TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n",
3001
            O2S(valuePtr), O2S(value2Ptr),
3002
            (valuePtr->typePtr?
3003
           valuePtr->typePtr->name : "null")));
3004
    DECACHE_STACK_INFO();
3005
    IllegalExprOperandType(interp, pc, valuePtr);
3006
    CACHE_STACK_INFO();
3007
    goto checkForCatch;
3008
      }
3009
  }
3010
  if (value2Ptr->typePtr == &tclIntType) {
3011
      i2 = value2Ptr->internalRep.longValue;
3012
  } else if (value2Ptr->typePtr == &tclWideIntType) {
3013
      TclGetWide(w2,value2Ptr);
3014
  } else {
3015
      REQUIRE_WIDE_OR_INT(result, value2Ptr, i2, w2);
3016
      if (result != TCL_OK) {
3017
    TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n",
3018
            O2S(valuePtr), O2S(value2Ptr),
3019
            (value2Ptr->typePtr?
3020
          value2Ptr->typePtr->name : "null")));
3021
    DECACHE_STACK_INFO();
3022
    IllegalExprOperandType(interp, pc, value2Ptr);
3023
    CACHE_STACK_INFO();
3024
    goto checkForCatch;
3025
      }
3026
  }
3027
 
3028
  switch (*pc) {
3029
  case INST_MOD:
3030
      /*
3031
       * This code is tricky: C doesn't guarantee much about
3032
       * the quotient or remainder, but Tcl does. The
3033
       * remainder always has the same sign as the divisor and
3034
       * a smaller absolute value.
3035
       */
3036
      if (value2Ptr->typePtr == &tclWideIntType && w2 == W0) {
3037
    if (valuePtr->typePtr == &tclIntType) {
3038
        TRACE(("%ld "LLD" => DIVIDE BY ZERO\n", i, w2));
3039
    } else {
3040
        TRACE((LLD" "LLD" => DIVIDE BY ZERO\n", w, w2));
3041
    }
3042
    goto divideByZero;
3043
      }
3044
      if (value2Ptr->typePtr == &tclIntType && i2 == 0) {
3045
    if (valuePtr->typePtr == &tclIntType) {
3046
        TRACE(("%ld %ld => DIVIDE BY ZERO\n", i, i2));
3047
    } else {
3048
        TRACE((LLD" %ld => DIVIDE BY ZERO\n", w, i2));
3049
    }
3050
    goto divideByZero;
3051
      }
3052
      negative = 0;
3053
      if (valuePtr->typePtr == &tclWideIntType
3054
    || value2Ptr->typePtr == &tclWideIntType) {
3055
    Tcl_WideInt wRemainder;
3056
    /*
3057
     * Promote to wide
3058
     */
3059
    if (valuePtr->typePtr == &tclIntType) {
3060
        w = Tcl_LongAsWide(i);
3061
    } else if (value2Ptr->typePtr == &tclIntType) {
3062
        w2 = Tcl_LongAsWide(i2);
3063
    }
3064
    if (w2 < 0) {
3065
        w2 = -w2;
3066
        w = -w;
3067
        negative = 1;
3068
    }
3069
    wRemainder  = w % w2;
3070
    if (wRemainder < 0) {
3071
        wRemainder += w2;
3072
    }
3073
    if (negative) {
3074
        wRemainder = -wRemainder;
3075
    }
3076
    wResult = wRemainder;
3077
    doWide = 1;
3078
    break;
3079
      }
3080
      if (i2 < 0) {
3081
    i2 = -i2;
3082
    i = -i;
3083
    negative = 1;
3084
      }
3085
      rem  = i % i2;
3086
      if (rem < 0) {
3087
    rem += i2;
3088
      }
3089
      if (negative) {
3090
    rem = -rem;
3091
      }
3092
      iResult = rem;
3093
      break;
3094
  case INST_LSHIFT:
3095
      /*
3096
       * Shifts are never usefully 64-bits wide!
3097
       */
3098
      FORCE_LONG(value2Ptr, i2, w2);
3099
      if (valuePtr->typePtr == &tclWideIntType) {
3100
#ifdef TCL_COMPILE_DEBUG
3101
    w2 = Tcl_LongAsWide(i2);
3102
#endif /* TCL_COMPILE_DEBUG */
3103
    wResult = w;
3104
    /*
3105
     * Shift in steps when the shift gets large to prevent
3106
     * annoying compiler/processor bugs. [Bug 868467]
3107
     */
3108
    if (i2 >= 64) {
3109
        wResult = Tcl_LongAsWide(0);
3110
    } else if (i2 > 60) {
3111
        wResult = w << 30;
3112
        wResult <<= 30;
3113
        wResult <<= i2-60;
3114
    } else if (i2 > 30) {
3115
        wResult = w << 30;
3116
        wResult <<= i2-30;
3117
    } else {
3118
        wResult = w << i2;
3119
    }
3120
    doWide = 1;
3121
    break;
3122
      }
3123
      /*
3124
       * Shift in steps when the shift gets large to prevent
3125
       * annoying compiler/processor bugs. [Bug 868467]
3126
       */
3127
      if (i2 >= 64) {
3128
    iResult = 0;
3129
      } else if (i2 > 60) {
3130
    iResult = i << 30;
3131
    iResult <<= 30;
3132
    iResult <<= i2-60;
3133
      } else if (i2 > 30) {
3134
    iResult = i << 30;
3135
    iResult <<= i2-30;
3136
      } else {
3137
    iResult = i << i2;
3138
      }
3139
      break;
3140
  case INST_RSHIFT:
3141
      /*
3142
       * The following code is a bit tricky: it ensures that
3143
       * right shifts propagate the sign bit even on machines
3144
       * where ">>" won't do it by default.
3145
       */
3146
      /*
3147
       * Shifts are never usefully 64-bits wide!
3148
       */
3149
      FORCE_LONG(value2Ptr, i2, w2);
3150
      if (valuePtr->typePtr == &tclWideIntType) {
3151
#ifdef TCL_COMPILE_DEBUG
3152
    w2 = Tcl_LongAsWide(i2);
3153
#endif /* TCL_COMPILE_DEBUG */
3154
    if (w < 0) {
3155
        wResult = ~w;
3156
    } else {
3157
        wResult = w;
3158
    }
3159
    /*
3160
     * Shift in steps when the shift gets large to prevent
3161
     * annoying compiler/processor bugs. [Bug 868467]
3162
     */
3163
    if (i2 >= 64) {
3164
        wResult = Tcl_LongAsWide(0);
3165
    } else if (i2 > 60) {
3166
        wResult >>= 30;
3167
        wResult >>= 30;
3168
        wResult >>= i2-60;
3169
    } else if (i2 > 30) {
3170
        wResult >>= 30;
3171
        wResult >>= i2-30;
3172
    } else {
3173
        wResult >>= i2;
3174
    }
3175
    if (w < 0) {
3176
        wResult = ~wResult;
3177
    }
3178
    doWide = 1;
3179
    break;
3180
      }
3181
      if (i < 0) {
3182
    iResult = ~i;
3183
      } else {
3184
    iResult = i;
3185
      }
3186
      /*
3187
       * Shift in steps when the shift gets large to prevent
3188
       * annoying compiler/processor bugs. [Bug 868467]
3189
       */
3190
      if (i2 >= 64) {
3191
    iResult = 0;
3192
      } else if (i2 > 60) {
3193
    iResult >>= 30;
3194
    iResult >>= 30;
3195
    iResult >>= i2-60;
3196
      } else if (i2 > 30) {
3197
    iResult >>= 30;
3198
    iResult >>= i2-30;
3199
      } else {
3200
    iResult >>= i2;
3201
      }
3202
      if (i < 0) {
3203
    iResult = ~iResult;
3204
      }
3205
      break;
3206
  case INST_BITOR:
3207
      if (valuePtr->typePtr == &tclWideIntType
3208
    || value2Ptr->typePtr == &tclWideIntType) {
3209
    /*
3210
     * Promote to wide
3211
     */
3212
    if (valuePtr->typePtr == &tclIntType) {
3213
        w = Tcl_LongAsWide(i);
3214
    } else if (value2Ptr->typePtr == &tclIntType) {
3215
        w2 = Tcl_LongAsWide(i2);
3216
    }
3217
    wResult = w | w2;
3218
    doWide = 1;
3219
    break;
3220
      }
3221
      iResult = i | i2;
3222
      break;
3223
  case INST_BITXOR:
3224
      if (valuePtr->typePtr == &tclWideIntType
3225
    || value2Ptr->typePtr == &tclWideIntType) {
3226
    /*
3227
     * Promote to wide
3228
     */
3229
    if (valuePtr->typePtr == &tclIntType) {
3230
        w = Tcl_LongAsWide(i);
3231
    } else if (value2Ptr->typePtr == &tclIntType) {
3232
        w2 = Tcl_LongAsWide(i2);
3233
    }
3234
    wResult = w ^ w2;
3235
    doWide = 1;
3236
    break;
3237
      }
3238
      iResult = i ^ i2;
3239
      break;
3240
  case INST_BITAND:
3241
      if (valuePtr->typePtr == &tclWideIntType
3242
    || value2Ptr->typePtr == &tclWideIntType) {
3243
    /*
3244
     * Promote to wide
3245
     */
3246
    if (valuePtr->typePtr == &tclIntType) {
3247
        w = Tcl_LongAsWide(i);
3248
    } else if (value2Ptr->typePtr == &tclIntType) {
3249
        w2 = Tcl_LongAsWide(i2);
3250
    }
3251
    wResult = w & w2;
3252
    doWide = 1;
3253
    break;
3254
      }
3255
      iResult = i & i2;
3256
      break;
3257
  }
3258
 
3259
  /*
3260
   * Reuse the valuePtr object already on stack if possible.
3261
   */
3262
 
3263
  if (Tcl_IsShared(valuePtr)) {
3264
      if (doWide) {
3265
    objResultPtr = Tcl_NewWideIntObj(wResult);
3266
    TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
3267
      } else {
3268
    objResultPtr = Tcl_NewLongObj(iResult);
3269
    TRACE(("%ld %ld => %ld\n", i, i2, iResult));
3270
      }
3271
      NEXT_INST_F(1, 2, 1);
3272
  } else {  /* reuse the valuePtr object */
3273
      if (doWide) {
3274
    TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
3275
    Tcl_SetWideIntObj(valuePtr, wResult);
3276
      } else {
3277
    TRACE(("%ld %ld => %ld\n", i, i2, iResult));
3278
    Tcl_SetLongObj(valuePtr, iResult);
3279
      }
3280
      NEXT_INST_F(1, 1, 0);
3281
  }
3282
    }
3283
 
3284
    case INST_ADD:
3285
    case INST_SUB:
3286
    case INST_MULT:
3287
    case INST_DIV:
3288
    {
3289
  /*
3290
   * Operands must be numeric and ints get converted to floats
3291
   * if necessary. We compute value op value2.
3292
   */
3293
 
3294
  Tcl_ObjType *t1Ptr, *t2Ptr;
3295
  long i2 = 0, quot, rem; /* Init. avoids compiler warning. */
3296
  double d1, d2;
3297
  long iResult = 0; /* Init. avoids compiler warning. */
3298
  double dResult = 0.0; /* Init. avoids compiler warning. */
3299
  int doDouble = 0; /* 1 if doing floating arithmetic */
3300
  Tcl_WideInt w2, wquot, wrem;
3301
  Tcl_WideInt wResult = W0; /* Init. avoids compiler warning. */
3302
  int doWide = 0;   /* 1 if doing wide arithmetic. */
3303
 
3304
  value2Ptr = stackPtr[stackTop];
3305
  valuePtr  = stackPtr[stackTop - 1];
3306
  t1Ptr = valuePtr->typePtr;
3307
  t2Ptr = value2Ptr->typePtr;
3308
 
3309
  if (t1Ptr == &tclIntType) {
3310
      i = valuePtr->internalRep.longValue;
3311
  } else if (t1Ptr == &tclWideIntType) {
3312
      TclGetWide(w,valuePtr);
3313
  } else if ((t1Ptr == &tclDoubleType)
3314
       && (valuePtr->bytes == NULL)) {
3315
      /*
3316
       * We can only use the internal rep directly if there is
3317
       * no string rep.  Otherwise the string rep might actually
3318
       * look like an integer, which is preferred.
3319
       */
3320
 
3321
      d1 = valuePtr->internalRep.doubleValue;
3322
  } else {
3323
      char *s = Tcl_GetStringFromObj(valuePtr, &length);
3324
      if (TclLooksLikeInt(s, length)) {
3325
    GET_WIDE_OR_INT(result, valuePtr, i, w);
3326
      } else {
3327
    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
3328
                valuePtr, &d1);
3329
      }
3330
      if (result != TCL_OK) {
3331
    TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n",
3332
            s, O2S(valuePtr),
3333
            (valuePtr->typePtr?
3334
          valuePtr->typePtr->name : "null")));
3335
    DECACHE_STACK_INFO();
3336
    IllegalExprOperandType(interp, pc, valuePtr);
3337
    CACHE_STACK_INFO();
3338
    goto checkForCatch;
3339
      }
3340
      t1Ptr = valuePtr->typePtr;
3341
  }
3342
 
3343
  if (t2Ptr == &tclIntType) {
3344
      i2 = value2Ptr->internalRep.longValue;
3345
  } else if (t2Ptr == &tclWideIntType) {
3346
      TclGetWide(w2,value2Ptr);
3347
  } else if ((t2Ptr == &tclDoubleType)
3348
       && (value2Ptr->bytes == NULL)) {
3349
      /*
3350
       * We can only use the internal rep directly if there is
3351
       * no string rep.  Otherwise the string rep might actually
3352
       * look like an integer, which is preferred.
3353
       */
3354
 
3355
      d2 = value2Ptr->internalRep.doubleValue;
3356
  } else {
3357
      char *s = Tcl_GetStringFromObj(value2Ptr, &length);
3358
      if (TclLooksLikeInt(s, length)) {
3359
    GET_WIDE_OR_INT(result, value2Ptr, i2, w2);
3360
      } else {
3361
    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
3362
            value2Ptr, &d2);
3363
      }
3364
      if (result != TCL_OK) {
3365
    TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n",
3366
            O2S(value2Ptr), s,
3367
            (value2Ptr->typePtr?
3368
          value2Ptr->typePtr->name : "null")));
3369
    DECACHE_STACK_INFO();
3370
    IllegalExprOperandType(interp, pc, value2Ptr);
3371
    CACHE_STACK_INFO();
3372
    goto checkForCatch;
3373
      }
3374
      t2Ptr = value2Ptr->typePtr;
3375
  }
3376
 
3377
  if ((t1Ptr == &tclDoubleType) || (t2Ptr == &tclDoubleType)) {
3378
      /*
3379
       * Do double arithmetic.
3380
       */
3381
      doDouble = 1;
3382
      if (t1Ptr == &tclIntType) {
3383
    d1 = i;       /* promote value 1 to double */
3384
      } else if (t2Ptr == &tclIntType) {
3385
    d2 = i2;      /* promote value 2 to double */
3386
      } else if (t1Ptr == &tclWideIntType) {
3387
    d1 = Tcl_WideAsDouble(w);
3388
      } else if (t2Ptr == &tclWideIntType) {
3389
    d2 = Tcl_WideAsDouble(w2);
3390
      }
3391
      switch (*pc) {
3392
          case INST_ADD:
3393
        dResult = d1 + d2;
3394
        break;
3395
          case INST_SUB:
3396
        dResult = d1 - d2;
3397
        break;
3398
          case INST_MULT:
3399
        dResult = d1 * d2;
3400
        break;
3401
          case INST_DIV:
3402
        if (d2 == 0.0) {
3403
      TRACE(("%.6g %.6g => DIVIDE BY ZERO\n", d1, d2));
3404
      goto divideByZero;
3405
        }
3406
        dResult = d1 / d2;
3407
        break;
3408
      }
3409
 
3410
      /*
3411
       * Check now for IEEE floating-point error.
3412
       */
3413
 
3414
      if (IS_NAN(dResult) || IS_INF(dResult)) {
3415
    TRACE(("%.20s %.20s => IEEE FLOATING PT ERROR\n",
3416
            O2S(valuePtr), O2S(value2Ptr)));
3417
    DECACHE_STACK_INFO();
3418
    TclExprFloatError(interp, dResult);
3419
    CACHE_STACK_INFO();
3420
    result = TCL_ERROR;
3421
    goto checkForCatch;
3422
      }
3423
  } else if ((t1Ptr == &tclWideIntType)
3424
       || (t2Ptr == &tclWideIntType)) {
3425
      /*
3426
       * Do wide integer arithmetic.
3427
       */
3428
      doWide = 1;
3429
      if (t1Ptr == &tclIntType) {
3430
    w = Tcl_LongAsWide(i);
3431
      } else if (t2Ptr == &tclIntType) {
3432
    w2 = Tcl_LongAsWide(i2);
3433
      }
3434
      switch (*pc) {
3435
          case INST_ADD:
3436
        wResult = w + w2;
3437
        break;
3438
          case INST_SUB:
3439
        wResult = w - w2;
3440
        break;
3441
          case INST_MULT:
3442
        wResult = w * w2;
3443
        break;
3444
          case INST_DIV:
3445
        /*
3446
         * This code is tricky: C doesn't guarantee much
3447
         * about the quotient or remainder, but Tcl does.
3448
         * The remainder always has the same sign as the
3449
         * divisor and a smaller absolute value.
3450
         */
3451
        if (w2 == W0) {
3452
      TRACE((LLD" "LLD" => DIVIDE BY ZERO\n", w, w2));
3453
      goto divideByZero;
3454
        }
3455
        if (w2 < 0) {
3456
      w2 = -w2;
3457
      w = -w;
3458
        }
3459
        wquot = w / w2;
3460
        wrem  = w % w2;
3461
        if (wrem < W0) {
3462
      wquot -= 1;
3463
        }
3464
        wResult = wquot;
3465
        break;
3466
      }
3467
  } else {
3468
      /*
3469
         * Do integer arithmetic.
3470
         */
3471
      switch (*pc) {
3472
          case INST_ADD:
3473
        iResult = i + i2;
3474
        break;
3475
          case INST_SUB:
3476
        iResult = i - i2;
3477
        break;
3478
          case INST_MULT:
3479
        iResult = i * i2;
3480
        break;
3481
          case INST_DIV:
3482
        /*
3483
         * This code is tricky: C doesn't guarantee much
3484
         * about the quotient or remainder, but Tcl does.
3485
         * The remainder always has the same sign as the
3486
         * divisor and a smaller absolute value.
3487
         */
3488
        if (i2 == 0) {
3489
      TRACE(("%ld %ld => DIVIDE BY ZERO\n", i, i2));
3490
      goto divideByZero;
3491
        }
3492
        if (i2 < 0) {
3493
      i2 = -i2;
3494
      i = -i;
3495
        }
3496
        quot = i / i2;
3497
        rem  = i % i2;
3498
        if (rem < 0) {
3499
      quot -= 1;
3500
        }
3501
        iResult = quot;
3502
        break;
3503
      }
3504
  }
3505
 
3506
  /*
3507
   * Reuse the valuePtr object already on stack if possible.
3508
   */
3509
 
3510
  if (Tcl_IsShared(valuePtr)) {
3511
      if (doDouble) {
3512
    objResultPtr = Tcl_NewDoubleObj(dResult);
3513
    TRACE(("%.6g %.6g => %.6g\n", d1, d2, dResult));
3514
      } else if (doWide) {
3515
    objResultPtr = Tcl_NewWideIntObj(wResult);
3516
    TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
3517
      } else {
3518
    objResultPtr = Tcl_NewLongObj(iResult);
3519
    TRACE(("%ld %ld => %ld\n", i, i2, iResult));
3520
      }
3521
      NEXT_INST_F(1, 2, 1);
3522
  } else {      /* reuse the valuePtr object */
3523
      if (doDouble) { /* NB: stack top is off by 1 */
3524
    TRACE(("%.6g %.6g => %.6g\n", d1, d2, dResult));
3525
    Tcl_SetDoubleObj(valuePtr, dResult);
3526
      } else if (doWide) {
3527
    TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
3528
    Tcl_SetWideIntObj(valuePtr, wResult);
3529
      } else {
3530
    TRACE(("%ld %ld => %ld\n", i, i2, iResult));
3531
    Tcl_SetLongObj(valuePtr, iResult);
3532
      }
3533
      NEXT_INST_F(1, 1, 0);
3534
  }
3535
    }
3536
 
3537
    case INST_UPLUS:
3538
    {
3539
  /*
3540
   * Operand must be numeric.
3541
   */
3542
 
3543
  double d;
3544
  Tcl_ObjType *tPtr;
3545
 
3546
  valuePtr = stackPtr[stackTop];
3547
  tPtr = valuePtr->typePtr;
3548
  if (!IS_INTEGER_TYPE(tPtr) && ((tPtr != &tclDoubleType)
3549
                || (valuePtr->bytes != NULL))) {
3550
      char *s = Tcl_GetStringFromObj(valuePtr, &length);
3551
      if (TclLooksLikeInt(s, length)) {
3552
    GET_WIDE_OR_INT(result, valuePtr, i, w);
3553
      } else {
3554
    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d);
3555
      }
3556
      if (result != TCL_OK) {
3557
    TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n",
3558
            s, (tPtr? tPtr->name : "null")));
3559
    DECACHE_STACK_INFO();
3560
    IllegalExprOperandType(interp, pc, valuePtr);
3561
    CACHE_STACK_INFO();
3562
    goto checkForCatch;
3563
      }
3564
      tPtr = valuePtr->typePtr;
3565
  }
3566
 
3567
  /*
3568
   * Ensure that the operand's string rep is the same as the
3569
   * formatted version of its internal rep. This makes sure
3570
   * that "expr +000123" yields "83", not "000123". We
3571
   * implement this by _discarding_ the string rep since we
3572
   * know it will be regenerated, if needed later, by
3573
   * formatting the internal rep's value.
3574
   */
3575
 
3576
  if (Tcl_IsShared(valuePtr)) {
3577
      if (tPtr == &tclIntType) {
3578
    i = valuePtr->internalRep.longValue;
3579
    objResultPtr = Tcl_NewLongObj(i);
3580
      } else if (tPtr == &tclWideIntType) {
3581
    TclGetWide(w,valuePtr);
3582
    objResultPtr = Tcl_NewWideIntObj(w);
3583
      } else {
3584
    d = valuePtr->internalRep.doubleValue;
3585
    objResultPtr = Tcl_NewDoubleObj(d);
3586
      }
3587
      TRACE_WITH_OBJ(("%s => ", O2S(objResultPtr)), objResultPtr);
3588
      NEXT_INST_F(1, 1, 1);
3589
  } else {
3590
      Tcl_InvalidateStringRep(valuePtr);
3591
      TRACE_WITH_OBJ(("%s => ", O2S(valuePtr)), valuePtr);
3592
      NEXT_INST_F(1, 0, 0);
3593
  }
3594
    }
3595
 
3596
    case INST_UMINUS:
3597
    case INST_LNOT:
3598
    {
3599
  /*
3600
   * The operand must be numeric or a boolean string as
3601
   * accepted by Tcl_GetBooleanFromObj(). If the operand
3602
   * object is unshared modify it directly, otherwise
3603
   * create a copy to modify: this is "copy on write".
3604
   * Free any old string representation since it is now
3605
   * invalid.
3606
   */
3607
 
3608
  double d;
3609
  int boolvar;
3610
  Tcl_ObjType *tPtr;
3611
 
3612
  valuePtr = stackPtr[stackTop];
3613
  tPtr = valuePtr->typePtr;
3614
  if (!IS_INTEGER_TYPE(tPtr) && ((tPtr != &tclDoubleType)
3615
          || (valuePtr->bytes != NULL))) {
3616
      if ((tPtr == &tclBooleanType) && (valuePtr->bytes == NULL)) {
3617
    valuePtr->typePtr = &tclIntType;
3618
      } else {
3619
    char *s = Tcl_GetStringFromObj(valuePtr, &length);
3620
    if (TclLooksLikeInt(s, length)) {
3621
        GET_WIDE_OR_INT(result, valuePtr, i, w);
3622
    } else {
3623
        result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
3624
                valuePtr, &d);
3625
    }
3626
    if (result == TCL_ERROR && *pc == INST_LNOT) {
3627
        result = Tcl_GetBooleanFromObj((Tcl_Interp *)NULL,
3628
                valuePtr, &boolvar);
3629
        i = (long)boolvar; /* i is long, not int! */
3630
    }
3631
    if (result != TCL_OK) {
3632
        TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n",
3633
                s, (tPtr? tPtr->name : "null")));
3634
        DECACHE_STACK_INFO();
3635
        IllegalExprOperandType(interp, pc, valuePtr);
3636
        CACHE_STACK_INFO();
3637
        goto checkForCatch;
3638
    }
3639
      }
3640
      tPtr = valuePtr->typePtr;
3641
  }
3642
 
3643
  if (Tcl_IsShared(valuePtr)) {
3644
      /*
3645
       * Create a new object.
3646
       */
3647
      if ((tPtr == &tclIntType) || (tPtr == &tclBooleanType)) {
3648
    i = valuePtr->internalRep.longValue;
3649
    objResultPtr = Tcl_NewLongObj(
3650
        (*pc == INST_UMINUS)? -i : !i);
3651
    TRACE_WITH_OBJ(("%ld => ", i), objResultPtr);
3652
      } else if (tPtr == &tclWideIntType) {
3653
    TclGetWide(w,valuePtr);
3654
    if (*pc == INST_UMINUS) {
3655
        objResultPtr = Tcl_NewWideIntObj(-w);
3656
    } else {
3657
        objResultPtr = Tcl_NewLongObj(w == W0);
3658
    }
3659
    TRACE_WITH_OBJ((LLD" => ", w), objResultPtr);
3660
      } else {
3661
    d = valuePtr->internalRep.doubleValue;
3662
    if (*pc == INST_UMINUS) {
3663
        objResultPtr = Tcl_NewDoubleObj(-d);
3664
    } else {
3665
        /*
3666
         * Should be able to use "!d", but apparently
3667
         * some compilers can't handle it.
3668
         */
3669
        objResultPtr = Tcl_NewLongObj((d==0.0)? 1 : 0);
3670
    }
3671
    TRACE_WITH_OBJ(("%.6g => ", d), objResultPtr);
3672
      }
3673
      NEXT_INST_F(1, 1, 1);
3674
  } else {
3675
      /*
3676
       * valuePtr is unshared. Modify it directly.
3677
       */
3678
      if ((tPtr == &tclIntType) || (tPtr == &tclBooleanType)) {
3679
    i = valuePtr->internalRep.longValue;
3680
    Tcl_SetLongObj(valuePtr,
3681
                  (*pc == INST_UMINUS)? -i : !i);
3682
    TRACE_WITH_OBJ(("%ld => ", i), valuePtr);
3683
      } else if (tPtr == &tclWideIntType) {
3684
    TclGetWide(w,valuePtr);
3685
    if (*pc == INST_UMINUS) {
3686
        Tcl_SetWideIntObj(valuePtr, -w);
3687
    } else {
3688
        Tcl_SetLongObj(valuePtr, w == W0);
3689
    }
3690
    TRACE_WITH_OBJ((LLD" => ", w), valuePtr);
3691
      } else {
3692
    d = valuePtr->internalRep.doubleValue;
3693
    if (*pc == INST_UMINUS) {
3694
        Tcl_SetDoubleObj(valuePtr, -d);
3695
    } else {
3696
        /*
3697
         * Should be able to use "!d", but apparently
3698
         * some compilers can't handle it.
3699
         */
3700
        Tcl_SetLongObj(valuePtr, (d==0.0)? 1 : 0);
3701
    }
3702
    TRACE_WITH_OBJ(("%.6g => ", d), valuePtr);
3703
      }
3704
      NEXT_INST_F(1, 0, 0);
3705
  }
3706
    }
3707
 
3708
    case INST_BITNOT:
3709
    {
3710
  /*
3711
   * The operand must be an integer. If the operand object is
3712
   * unshared modify it directly, otherwise modify a copy.
3713
   * Free any old string representation since it is now
3714
   * invalid.
3715
   */
3716
 
3717
  Tcl_ObjType *tPtr;
3718
 
3719
  valuePtr = stackPtr[stackTop];
3720
  tPtr = valuePtr->typePtr;
3721
  if (!IS_INTEGER_TYPE(tPtr)) {
3722
      REQUIRE_WIDE_OR_INT(result, valuePtr, i, w);
3723
      if (result != TCL_OK) {   /* try to convert to double */
3724
    TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n",
3725
            O2S(valuePtr), (tPtr? tPtr->name : "null")));
3726
    DECACHE_STACK_INFO();
3727
    IllegalExprOperandType(interp, pc, valuePtr);
3728
    CACHE_STACK_INFO();
3729
    goto checkForCatch;
3730
      }
3731
  }
3732
 
3733
  if (valuePtr->typePtr == &tclWideIntType) {
3734
      TclGetWide(w,valuePtr);
3735
      if (Tcl_IsShared(valuePtr)) {
3736
    objResultPtr = Tcl_NewWideIntObj(~w);
3737
    TRACE(("0x%llx => (%llu)\n", w, ~w));
3738
    NEXT_INST_F(1, 1, 1);
3739
      } else {
3740
    /*
3741
     * valuePtr is unshared. Modify it directly.
3742
     */
3743
    Tcl_SetWideIntObj(valuePtr, ~w);
3744
    TRACE(("0x%llx => (%llu)\n", w, ~w));
3745
    NEXT_INST_F(1, 0, 0);
3746
      }
3747
  } else {
3748
      i = valuePtr->internalRep.longValue;
3749
      if (Tcl_IsShared(valuePtr)) {
3750
    objResultPtr = Tcl_NewLongObj(~i);
3751
    TRACE(("0x%lx => (%lu)\n", i, ~i));
3752
    NEXT_INST_F(1, 1, 1);
3753
      } else {
3754
    /*
3755
     * valuePtr is unshared. Modify it directly.
3756
     */
3757
    Tcl_SetLongObj(valuePtr, ~i);
3758
    TRACE(("0x%lx => (%lu)\n", i, ~i));
3759
    NEXT_INST_F(1, 0, 0);
3760
      }
3761
  }
3762
    }
3763
 
3764
    case INST_CALL_BUILTIN_FUNC1:
3765
  opnd = TclGetUInt1AtPtr(pc+1);
3766
  {
3767
      /*
3768
       * Call one of the built-in Tcl math functions.
3769
       */
3770
 
3771
      BuiltinFunc *mathFuncPtr;
3772
 
3773
      if ((opnd < 0) || (opnd > LAST_BUILTIN_FUNC)) {
3774
    TRACE(("UNRECOGNIZED BUILTIN FUNC CODE %d\n", opnd));
3775
    panic("TclExecuteByteCode: unrecognized builtin function code %d", opnd);
3776
      }
3777
      mathFuncPtr = &(tclBuiltinFuncTable[opnd]);
3778
      DECACHE_STACK_INFO();
3779
      result = (*mathFuncPtr->proc)(interp, eePtr,
3780
              mathFuncPtr->clientData);
3781
      CACHE_STACK_INFO();
3782
      if (result != TCL_OK) {
3783
    goto checkForCatch;
3784
      }
3785
      TRACE_WITH_OBJ(("%d => ", opnd), stackPtr[stackTop]);
3786
  }
3787
  NEXT_INST_F(2, 0, 0);
3788
 
3789
    case INST_CALL_FUNC1:
3790
  opnd = TclGetUInt1AtPtr(pc+1);
3791
  {
3792
      /*
3793
       * Call a non-builtin Tcl math function previously
3794
       * registered by a call to Tcl_CreateMathFunc.
3795
       */
3796
 
3797
      int objc = opnd;   /* Number of arguments. The function name
3798
        * is the 0-th argument. */
3799
      Tcl_Obj **objv;    /* The array of arguments. The function
3800
        * name is objv[0]. */
3801
 
3802
      objv = &(stackPtr[stackTop - (objc-1)]); /* "objv[0]" */
3803
      DECACHE_STACK_INFO();
3804
      result = ExprCallMathFunc(interp, eePtr, objc, objv);
3805
      CACHE_STACK_INFO();
3806
      if (result != TCL_OK) {
3807
    goto checkForCatch;
3808
      }
3809
      TRACE_WITH_OBJ(("%d => ", objc), stackPtr[stackTop]);
3810
  }
3811
  NEXT_INST_F(2, 0, 0);
3812
 
3813
    case INST_TRY_CVT_TO_NUMERIC:
3814
    {
3815
  /*
3816
   * Try to convert the topmost stack object to an int or
3817
   * double object. This is done in order to support Tcl's
3818
   * policy of interpreting operands if at all possible as
3819
   * first integers, else floating-point numbers.
3820
   */
3821
 
3822
  double d;
3823
  char *s;
3824
  Tcl_ObjType *tPtr;
3825
  int converted, needNew;
3826
 
3827
  valuePtr = stackPtr[stackTop];
3828
  tPtr = valuePtr->typePtr;
3829
  converted = 0;
3830
  if (!IS_INTEGER_TYPE(tPtr) && ((tPtr != &tclDoubleType)
3831
          || (valuePtr->bytes != NULL))) {
3832
      if ((tPtr == &tclBooleanType) && (valuePtr->bytes == NULL)) {
3833
    valuePtr->typePtr = &tclIntType;
3834
    converted = 1;
3835
      } else {
3836
    s = Tcl_GetStringFromObj(valuePtr, &length);
3837
    if (TclLooksLikeInt(s, length)) {
3838
        GET_WIDE_OR_INT(result, valuePtr, i, w);
3839
    } else {
3840
        result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
3841
                valuePtr, &d);
3842
    }
3843
    if (result == TCL_OK) {
3844
        converted = 1;
3845
    }
3846
    result = TCL_OK; /* reset the result variable */
3847
      }
3848
      tPtr = valuePtr->typePtr;
3849
  }
3850
 
3851
  /*
3852
   * Ensure that the topmost stack object, if numeric, has a
3853
   * string rep the same as the formatted version of its
3854
   * internal rep. This is used, e.g., to make sure that "expr
3855
   * {0001}" yields "1", not "0001". We implement this by
3856
   * _discarding_ the string rep since we know it will be
3857
   * regenerated, if needed later, by formatting the internal
3858
   * rep's value. Also check if there has been an IEEE
3859
   * floating point error.
3860
   */
3861
 
3862
  objResultPtr = valuePtr;
3863
  needNew = 0;
3864
  if (IS_NUMERIC_TYPE(tPtr)) {
3865
      if (Tcl_IsShared(valuePtr)) {
3866
    if (valuePtr->bytes != NULL) {
3867
        /*
3868
         * We only need to make a copy of the object
3869
         * when it already had a string rep
3870
         */
3871
        needNew = 1;
3872
        if (tPtr == &tclIntType) {
3873
      i = valuePtr->internalRep.longValue;
3874
      objResultPtr = Tcl_NewLongObj(i);
3875
        } else if (tPtr == &tclWideIntType) {
3876
      TclGetWide(w,valuePtr);
3877
      objResultPtr = Tcl_NewWideIntObj(w);
3878
        } else {
3879
      d = valuePtr->internalRep.doubleValue;
3880
      objResultPtr = Tcl_NewDoubleObj(d);
3881
        }
3882
        tPtr = objResultPtr->typePtr;
3883
    }
3884
      } else {
3885
    Tcl_InvalidateStringRep(valuePtr);
3886
      }
3887
 
3888
      if (tPtr == &tclDoubleType) {
3889
    d = objResultPtr->internalRep.doubleValue;
3890
    if (IS_NAN(d) || IS_INF(d)) {
3891
        TRACE(("\"%.20s\" => IEEE FLOATING PT ERROR\n",
3892
                O2S(objResultPtr)));
3893
        DECACHE_STACK_INFO();
3894
        TclExprFloatError(interp, d);
3895
        CACHE_STACK_INFO();
3896
        result = TCL_ERROR;
3897
        goto checkForCatch;
3898
    }
3899
      }
3900
      converted = converted;  /* lint, converted not used. */
3901
      TRACE(("\"%.20s\" => numeric, %s, %s\n", O2S(valuePtr),
3902
              (converted? "converted" : "not converted"),
3903
        (needNew? "new Tcl_Obj" : "same Tcl_Obj")));
3904
  } else {
3905
      TRACE(("\"%.20s\" => not numeric\n", O2S(valuePtr)));
3906
  }
3907
  if (needNew) {
3908
      NEXT_INST_F(1, 1, 1);
3909
  } else {
3910
      NEXT_INST_F(1, 0, 0);
3911
  }
3912
    }
3913
 
3914
    case INST_BREAK:
3915
  DECACHE_STACK_INFO();
3916
  Tcl_ResetResult(interp);
3917
  CACHE_STACK_INFO();
3918
  result = TCL_BREAK;
3919
  cleanup = 0;
3920
  goto processExceptionReturn;
3921
 
3922
    case INST_CONTINUE:
3923
  DECACHE_STACK_INFO();
3924
  Tcl_ResetResult(interp);
3925
  CACHE_STACK_INFO();
3926
  result = TCL_CONTINUE;
3927
  cleanup = 0;
3928
  goto processExceptionReturn;
3929
 
3930
    case INST_FOREACH_START4:
3931
  opnd = TclGetUInt4AtPtr(pc+1);
3932
  {
3933
      /*
3934
       * Initialize the temporary local var that holds the count
3935
       * of the number of iterations of the loop body to -1.
3936
       */
3937
 
3938
      ForeachInfo *infoPtr = (ForeachInfo *)
3939
              codePtr->auxDataArrayPtr[opnd].clientData;
3940
      int iterTmpIndex = infoPtr->loopCtTemp;
3941
      Var *compiledLocals = iPtr->varFramePtr->compiledLocals;
3942
      Var *iterVarPtr = &(compiledLocals[iterTmpIndex]);
3943
      Tcl_Obj *oldValuePtr = iterVarPtr->value.objPtr;
3944
 
3945
      if (oldValuePtr == NULL) {
3946
    iterVarPtr->value.objPtr = Tcl_NewLongObj(-1);
3947
    Tcl_IncrRefCount(iterVarPtr->value.objPtr);
3948
      } else {
3949
    Tcl_SetLongObj(oldValuePtr, -1);
3950
      }
3951
      TclSetVarScalar(iterVarPtr);
3952
      TclClearVarUndefined(iterVarPtr);
3953
      TRACE(("%u => loop iter count temp %d\n",
3954
       opnd, iterTmpIndex));
3955
  }
3956
 
3957
#ifndef TCL_COMPILE_DEBUG
3958
  /*
3959
   * Remark that the compiler ALWAYS sets INST_FOREACH_STEP4
3960
   * immediately after INST_FOREACH_START4 - let us just fall
3961
   * through instead of jumping back to the top.
3962
   */
3963
 
3964
  pc += 5;
3965
#else
3966
  NEXT_INST_F(5, 0, 0);
3967
#endif
3968
    case INST_FOREACH_STEP4:
3969
  opnd = TclGetUInt4AtPtr(pc+1);
3970
  {
3971
      /*
3972
       * "Step" a foreach loop (i.e., begin its next iteration) by
3973
       * assigning the next value list element to each loop var.
3974
       */
3975
 
3976
      ForeachInfo *infoPtr = (ForeachInfo *)
3977
              codePtr->auxDataArrayPtr[opnd].clientData;
3978
      ForeachVarList *varListPtr;
3979
      int numLists = infoPtr->numLists;
3980
      Var *compiledLocals = iPtr->varFramePtr->compiledLocals;
3981
      Tcl_Obj *listPtr;
3982
      List *listRepPtr;
3983
      Var *iterVarPtr, *listVarPtr;
3984
      int iterNum, listTmpIndex, listLen, numVars;
3985
      int varIndex, valIndex, continueLoop, j;
3986
 
3987
      /*
3988
       * Increment the temp holding the loop iteration number.
3989
       */
3990
 
3991
      iterVarPtr = &(compiledLocals[infoPtr->loopCtTemp]);
3992
      valuePtr = iterVarPtr->value.objPtr;
3993
      iterNum = (valuePtr->internalRep.longValue + 1);
3994
      Tcl_SetLongObj(valuePtr, iterNum);
3995
 
3996
      /*
3997
       * Check whether all value lists are exhausted and we should
3998
       * stop the loop.
3999
       */
4000
 
4001
      continueLoop = 0;
4002
      listTmpIndex = infoPtr->firstValueTemp;
4003
      for (i = 0;  i < numLists;  i++) {
4004
    varListPtr = infoPtr->varLists[i];
4005
    numVars = varListPtr->numVars;
4006
 
4007
    listVarPtr = &(compiledLocals[listTmpIndex]);
4008
    listPtr = listVarPtr->value.objPtr;
4009
    result = Tcl_ListObjLength(interp, listPtr, &listLen);
4010
    if (result != TCL_OK) {
4011
        TRACE_WITH_OBJ(("%u => ERROR converting list %ld, \"%s\": ",
4012
                opnd, i, O2S(listPtr)), Tcl_GetObjResult(interp));
4013
        goto checkForCatch;
4014
    }
4015
    if (listLen > (iterNum * numVars)) {
4016
        continueLoop = 1;
4017
    }
4018
    listTmpIndex++;
4019
      }
4020
 
4021
      /*
4022
       * If some var in some var list still has a remaining list
4023
       * element iterate one more time. Assign to var the next
4024
       * element from its value list. We already checked above
4025
       * that each list temp holds a valid list object.
4026
       */
4027
 
4028
      if (continueLoop) {
4029
    listTmpIndex = infoPtr->firstValueTemp;
4030
    for (i = 0;  i < numLists;  i++) {
4031
        varListPtr = infoPtr->varLists[i];
4032
        numVars = varListPtr->numVars;
4033
 
4034
        listVarPtr = &(compiledLocals[listTmpIndex]);
4035
        listPtr = listVarPtr->value.objPtr;
4036
        listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
4037
        listLen = listRepPtr->elemCount;
4038
 
4039
        valIndex = (iterNum * numVars);
4040
        for (j = 0;  j < numVars;  j++) {
4041
      if (valIndex >= listLen) {
4042
          TclNewObj(valuePtr);
4043
      } else {
4044
          valuePtr = listRepPtr->elements[valIndex];
4045
      }
4046
 
4047
      varIndex = varListPtr->varIndexes[j];
4048
      varPtr = &(varFramePtr->compiledLocals[varIndex]);
4049
      part1 = varPtr->name;
4050
      while (TclIsVarLink(varPtr)) {
4051
          varPtr = varPtr->value.linkPtr;
4052
      }
4053
      if (!((varPtr->flags & VAR_IN_HASHTABLE) && (varPtr->hPtr == NULL))
4054
              && (varPtr->tracePtr == NULL)
4055
              && (TclIsVarScalar(varPtr) || TclIsVarUndefined(varPtr))) {
4056
          value2Ptr = varPtr->value.objPtr;
4057
          if (valuePtr != value2Ptr) {
4058
        if (value2Ptr != NULL) {
4059
            TclDecrRefCount(value2Ptr);
4060
        } else {
4061
            TclSetVarScalar(varPtr);
4062
            TclClearVarUndefined(varPtr);
4063
        }
4064
        varPtr->value.objPtr = valuePtr;
4065
        Tcl_IncrRefCount(valuePtr);
4066
          }
4067
      } else {
4068
          DECACHE_STACK_INFO();
4069
          Tcl_IncrRefCount(valuePtr);
4070
          value2Ptr = TclPtrSetVar(interp, varPtr, NULL, part1,
4071
                 NULL, valuePtr, TCL_LEAVE_ERR_MSG);
4072
          TclDecrRefCount(valuePtr);
4073
          CACHE_STACK_INFO();
4074
          if (value2Ptr == NULL) {
4075
        TRACE_WITH_OBJ(("%u => ERROR init. index temp %d: ",
4076
            opnd, varIndex),
4077
                 Tcl_GetObjResult(interp));
4078
        result = TCL_ERROR;
4079
        goto checkForCatch;
4080
          }
4081
      }
4082
      valIndex++;
4083
        }
4084
        listTmpIndex++;
4085
    }
4086
      }
4087
      TRACE(("%u => %d lists, iter %d, %s loop\n", opnd, numLists,
4088
              iterNum, (continueLoop? "continue" : "exit")));
4089
 
4090
      /*
4091
       * Run-time peep-hole optimisation: the compiler ALWAYS follows
4092
       * INST_FOREACH_STEP4 with an INST_JUMP_FALSE. We just skip that
4093
       * instruction and jump direct from here.
4094
       */
4095
 
4096
      pc += 5;
4097
      if (*pc == INST_JUMP_FALSE1) {
4098
    NEXT_INST_F((continueLoop? 2 : TclGetInt1AtPtr(pc+1)), 0, 0);
4099
      } else {
4100
    NEXT_INST_F((continueLoop? 5 : TclGetInt4AtPtr(pc+1)), 0, 0);
4101
      }
4102
  }
4103
 
4104
    case INST_BEGIN_CATCH4:
4105
  /*
4106
   * Record start of the catch command with exception range index
4107
   * equal to the operand. Push the current stack depth onto the
4108
   * special catch stack.
4109
   */
4110
  catchStackPtr[++catchTop] = stackTop;
4111
  TRACE(("%u => catchTop=%d, stackTop=%d\n",
4112
         TclGetUInt4AtPtr(pc+1), catchTop, stackTop));
4113
  NEXT_INST_F(5, 0, 0);
4114
 
4115
    case INST_END_CATCH:
4116
  catchTop--;
4117
  result = TCL_OK;
4118
  TRACE(("=> catchTop=%d\n", catchTop));
4119
  NEXT_INST_F(1, 0, 0);
4120
 
4121
    case INST_PUSH_RESULT:
4122
  objResultPtr = Tcl_GetObjResult(interp);
4123
  TRACE_WITH_OBJ(("=> "), Tcl_GetObjResult(interp));
4124
 
4125
  /*
4126
   * See the comments at INST_INVOKE_STK
4127
   */
4128
  {
4129
      Tcl_Obj *newObjResultPtr;
4130
      TclNewObj(newObjResultPtr);
4131
      Tcl_IncrRefCount(newObjResultPtr);
4132
      iPtr->objResultPtr = newObjResultPtr;
4133
  }
4134
 
4135
  NEXT_INST_F(1, 0, -1);
4136
 
4137
    case INST_PUSH_RETURN_CODE:
4138
  objResultPtr = Tcl_NewLongObj(result);
4139
  TRACE(("=> %u\n", result));
4140
  NEXT_INST_F(1, 0, 1);
4141
 
4142
    default:
4143
  panic("TclExecuteByteCode: unrecognized opCode %u", *pc);
4144
    } /* end of switch on opCode */
4145
 
4146
    /*
4147
     * Division by zero in an expression. Control only reaches this
4148
     * point by "goto divideByZero".
4149
     */
4150
 
4151
 divideByZero:
4152
    DECACHE_STACK_INFO();
4153
    Tcl_ResetResult(interp);
4154
    Tcl_AppendToObj(Tcl_GetObjResult(interp), "divide by zero", -1);
4155
    Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero",
4156
            (char *) NULL);
4157
    CACHE_STACK_INFO();
4158
 
4159
    result = TCL_ERROR;
4160
    goto checkForCatch;
4161
 
4162
    /*
4163
     * An external evaluation (INST_INVOKE or INST_EVAL) returned
4164
     * something different from TCL_OK, or else INST_BREAK or
4165
     * INST_CONTINUE were called.
4166
     */
4167
 
4168
 processExceptionReturn:
4169
#if TCL_COMPILE_DEBUG
4170
    switch (*pc) {
4171
        case INST_INVOKE_STK1:
4172
        case INST_INVOKE_STK4:
4173
      TRACE(("%u => ... after \"%.20s\": ", opnd, cmdNameBuf));
4174
      break;
4175
        case INST_EVAL_STK:
4176
      /*
4177
       * Note that the object at stacktop has to be used
4178
       * before doing the cleanup.
4179
       */
4180
 
4181
      TRACE(("\"%.30s\" => ", O2S(stackPtr[stackTop])));
4182
      break;
4183
        default:
4184
      TRACE(("=> "));
4185
    }
4186
#endif
4187
    if ((result == TCL_CONTINUE) || (result == TCL_BREAK)) {
4188
  rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 0, codePtr);
4189
  if (rangePtr == NULL) {
4190
      TRACE_APPEND(("no encl. loop or catch, returning %s\n",
4191
              StringForResultCode(result)));
4192
      goto abnormalReturn;
4193
  }
4194
  if (rangePtr->type == CATCH_EXCEPTION_RANGE) {
4195
      TRACE_APPEND(("%s ...\n", StringForResultCode(result)));
4196
      goto processCatch;
4197
  }
4198
  while (cleanup--) {
4199
      valuePtr = POP_OBJECT();
4200
      TclDecrRefCount(valuePtr);
4201
  }
4202
  if (result == TCL_BREAK) {
4203
      result = TCL_OK;
4204
      pc = (codePtr->codeStart + rangePtr->breakOffset);
4205
      TRACE_APPEND(("%s, range at %d, new pc %d\n",
4206
       StringForResultCode(result),
4207
       rangePtr->codeOffset, rangePtr->breakOffset));
4208
      NEXT_INST_F(0, 0, 0);
4209
  } else {
4210
      if (rangePtr->continueOffset == -1) {
4211
    TRACE_APPEND(("%s, loop w/o continue, checking for catch\n",
4212
            StringForResultCode(result)));
4213
    goto checkForCatch;
4214
      }
4215
      result = TCL_OK;
4216
      pc = (codePtr->codeStart + rangePtr->continueOffset);
4217
      TRACE_APPEND(("%s, range at %d, new pc %d\n",
4218
       StringForResultCode(result),
4219
       rangePtr->codeOffset, rangePtr->continueOffset));
4220
      NEXT_INST_F(0, 0, 0);
4221
  }
4222
#if TCL_COMPILE_DEBUG
4223
    } else if (traceInstructions) {
4224
  if ((result != TCL_ERROR) && (result != TCL_RETURN))  {
4225
      objPtr = Tcl_GetObjResult(interp);
4226
      TRACE_APPEND(("OTHER RETURN CODE %d, result= \"%s\"\n ",
4227
        result, O2S(objPtr)));
4228
  } else {
4229
      objPtr = Tcl_GetObjResult(interp);
4230
      TRACE_APPEND(("%s, result= \"%s\"\n",
4231
              StringForResultCode(result), O2S(objPtr)));
4232
  }
4233
#endif
4234
    }
4235
 
4236
    /*
4237
     * Execution has generated an "exception" such as TCL_ERROR. If the
4238
     * exception is an error, record information about what was being
4239
     * executed when the error occurred. Find the closest enclosing
4240
     * catch range, if any. If no enclosing catch range is found, stop
4241
     * execution and return the "exception" code.
4242
     */
4243
 
4244
 checkForCatch:
4245
    if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
4246
  bytes = GetSrcInfoForPc(pc, codePtr, &length);
4247
  if (bytes != NULL) {
4248
      DECACHE_STACK_INFO();
4249
      Tcl_LogCommandInfo(interp, codePtr->source, bytes, length);
4250
            CACHE_STACK_INFO();
4251
      iPtr->flags |= ERR_ALREADY_LOGGED;
4252
  }
4253
    }
4254
    if (catchTop == -1) {
4255
#ifdef TCL_COMPILE_DEBUG
4256
  if (traceInstructions) {
4257
      fprintf(stdout, "   ... no enclosing catch, returning %s\n",
4258
              StringForResultCode(result));
4259
  }
4260
#endif
4261
  goto abnormalReturn;
4262
    }
4263
    rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 1, codePtr);
4264
    if (rangePtr == NULL) {
4265
  /*
4266
   * This is only possible when compiling a [catch] that sends its
4267
   * script to INST_EVAL. Cannot correct the compiler without
4268
   * breakingcompat with previous .tbc compiled scripts.
4269
   */
4270
#ifdef TCL_COMPILE_DEBUG
4271
  if (traceInstructions) {
4272
      fprintf(stdout, "   ... no enclosing catch, returning %s\n",
4273
              StringForResultCode(result));
4274
  }
4275
#endif
4276
  goto abnormalReturn;
4277
    }
4278
 
4279
    /*
4280
     * A catch exception range (rangePtr) was found to handle an
4281
     * "exception". It was found either by checkForCatch just above or
4282
     * by an instruction during break, continue, or error processing.
4283
     * Jump to its catchOffset after unwinding the operand stack to
4284
     * the depth it had when starting to execute the range's catch
4285
     * command.
4286
     */
4287
 
4288
 processCatch:
4289
    while (stackTop > catchStackPtr[catchTop]) {
4290
  valuePtr = POP_OBJECT();
4291
  TclDecrRefCount(valuePtr);
4292
    }
4293
#ifdef TCL_COMPILE_DEBUG
4294
    if (traceInstructions) {
4295
  fprintf(stdout, "  ... found catch at %d, catchTop=%d, unwound to %d, new pc %u\n",
4296
          rangePtr->codeOffset, catchTop, catchStackPtr[catchTop],
4297
          (unsigned int)(rangePtr->catchOffset));
4298
    }
4299
#endif
4300
    pc = (codePtr->codeStart + rangePtr->catchOffset);
4301
    NEXT_INST_F(0, 0, 0); /* restart the execution loop at pc */
4302
 
4303
    /*
4304
     * end of infinite loop dispatching on instructions.
4305
     */
4306
 
4307
    /*
4308
     * Abnormal return code. Restore the stack to state it had when starting
4309
     * to execute the ByteCode. Panic if the stack is below the initial level.
4310
     */
4311
 
4312
 abnormalReturn:
4313
    while (stackTop > initStackTop) {
4314
  valuePtr = POP_OBJECT();
4315
  TclDecrRefCount(valuePtr);
4316
    }
4317
    if (stackTop < initStackTop) {
4318
  fprintf(stderr, "\nTclExecuteByteCode: abnormal return at pc %u: stack top %d < entry stack top %d\n",
4319
          (unsigned int)(pc - codePtr->codeStart),
4320
    (unsigned int) stackTop,
4321
    (unsigned int) initStackTop);
4322
  panic("TclExecuteByteCode execution failure: end stack top < start stack top");
4323
    }
4324
 
4325
    /*
4326
     * Free the catch stack array if malloc'ed storage was used.
4327
     */
4328
 
4329
    if (catchStackPtr != catchStackStorage) {
4330
  ckfree((char *) catchStackPtr);
4331
    }
4332
    eePtr->stackTop = initStackTop;
4333
    return result;
4334
#undef STATIC_CATCH_STACK_SIZE
4335
}
4336
 
4337
#ifdef TCL_COMPILE_DEBUG
4338
/*
4339
 *----------------------------------------------------------------------
4340
 *
4341
 * PrintByteCodeInfo --
4342
 *
4343
 *  This procedure prints a summary about a bytecode object to stdout.
4344
 *  It is called by TclExecuteByteCode when starting to execute the
4345
 *  bytecode object if tclTraceExec has the value 2 or more.
4346
 *
4347
 * Results:
4348
 *  None.
4349
 *
4350
 * Side effects:
4351
 *  None.
4352
 *
4353
 *----------------------------------------------------------------------
4354
 */
4355
 
4356
static void
4357
PrintByteCodeInfo(codePtr)
4358
    register ByteCode *codePtr; /* The bytecode whose summary is printed
4359
         * to stdout. */
4360
{
4361
    Proc *procPtr = codePtr->procPtr;
4362
    Interp *iPtr = (Interp *) *codePtr->interpHandle;
4363
 
4364
    fprintf(stdout, "\nExecuting ByteCode 0x%x, refCt %u, epoch %u, interp 0x%x (epoch %u)\n",
4365
      (unsigned int) codePtr, codePtr->refCount,
4366
      codePtr->compileEpoch, (unsigned int) iPtr,
4367
      iPtr->compileEpoch);
4368
 
4369
    fprintf(stdout, "  Source: ");
4370
    TclPrintSource(stdout, codePtr->source, 60);
4371
 
4372
    fprintf(stdout, "\n  Cmds %d, src %d, inst %u, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n",
4373
            codePtr->numCommands, codePtr->numSrcBytes,
4374
      codePtr->numCodeBytes, codePtr->numLitObjects,
4375
      codePtr->numAuxDataItems, codePtr->maxStackDepth,
4376
#ifdef TCL_COMPILE_STATS
4377
      (codePtr->numSrcBytes?
4378
              ((float)codePtr->structureSize)/((float)codePtr->numSrcBytes) : 0.0));
4379
#else
4380
      0.0);
4381
#endif
4382
#ifdef TCL_COMPILE_STATS
4383
    fprintf(stdout, "  Code %d = header %d+inst %d+litObj %d+exc %d+aux %d+cmdMap %d\n",
4384
      codePtr->structureSize,
4385
      (sizeof(ByteCode) - (sizeof(size_t) + sizeof(Tcl_Time))),
4386
      codePtr->numCodeBytes,
4387
      (codePtr->numLitObjects * sizeof(Tcl_Obj *)),
4388
      (codePtr->numExceptRanges * sizeof(ExceptionRange)),
4389
      (codePtr->numAuxDataItems * sizeof(AuxData)),
4390
      codePtr->numCmdLocBytes);
4391
#endif /* TCL_COMPILE_STATS */
4392
    if (procPtr != NULL) {
4393
  fprintf(stdout,
4394
    "  Proc 0x%x, refCt %d, args %d, compiled locals %d\n",
4395
    (unsigned int) procPtr, procPtr->refCount,
4396
    procPtr->numArgs, procPtr->numCompiledLocals);
4397
    }
4398
}
4399
#endif /* TCL_COMPILE_DEBUG */
4400
 
4401
/*
4402
 *----------------------------------------------------------------------
4403
 *
4404
 * ValidatePcAndStackTop --
4405
 *
4406
 *  This procedure is called by TclExecuteByteCode when debugging to
4407
 *  verify that the program counter and stack top are valid during
4408
 *  execution.
4409
 *
4410
 * Results:
4411
 *  None.
4412
 *
4413
 * Side effects:
4414
 *  Prints a message to stderr and panics if either the pc or stack
4415
 *  top are invalid.
4416
 *
4417
 *----------------------------------------------------------------------
4418
 */
4419
 
4420
#ifdef TCL_COMPILE_DEBUG
4421
static void
4422
ValidatePcAndStackTop(codePtr, pc, stackTop, stackLowerBound)
4423
    register ByteCode *codePtr; /* The bytecode whose summary is printed
4424
         * to stdout. */
4425
    unsigned char *pc;    /* Points to first byte of a bytecode
4426
         * instruction. The program counter. */
4427
    int stackTop;   /* Current stack top. Must be between
4428
         * stackLowerBound and stackUpperBound
4429
         * (inclusive). */
4430
    int stackLowerBound;  /* Smallest legal value for stackTop. */
4431
{
4432
    int stackUpperBound = stackLowerBound +  codePtr->maxStackDepth;
4433
                                /* Greatest legal value for stackTop. */
4434
    unsigned int relativePc = (unsigned int) (pc - codePtr->codeStart);
4435
    unsigned int codeStart = (unsigned int) codePtr->codeStart;
4436
    unsigned int codeEnd = (unsigned int)
4437
      (codePtr->codeStart + codePtr->numCodeBytes);
4438
    unsigned char opCode = *pc;
4439
 
4440
    if (((unsigned int) pc < codeStart) || ((unsigned int) pc > codeEnd)) {
4441
  fprintf(stderr, "\nBad instruction pc 0x%x in TclExecuteByteCode\n",
4442
    (unsigned int) pc);
4443
  panic("TclExecuteByteCode execution failure: bad pc");
4444
    }
4445
    if ((unsigned int) opCode > LAST_INST_OPCODE) {
4446
  fprintf(stderr, "\nBad opcode %d at pc %u in TclExecuteByteCode\n",
4447
    (unsigned int) opCode, relativePc);
4448
        panic("TclExecuteByteCode execution failure: bad opcode");
4449
    }
4450
    if ((stackTop < stackLowerBound) || (stackTop > stackUpperBound)) {
4451
  int numChars;
4452
  char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars);
4453
  char *ellipsis = "";
4454
 
4455
  fprintf(stderr, "\nBad stack top %d at pc %u in TclExecuteByteCode (min %i, max %i)",
4456
    stackTop, relativePc, stackLowerBound, stackUpperBound);
4457
  if (cmd != NULL) {
4458
      if (numChars > 100) {
4459
    numChars = 100;
4460
    ellipsis = "...";
4461
      }
4462
      fprintf(stderr, "\n executing %.*s%s\n", numChars, cmd,
4463
        ellipsis);
4464
  } else {
4465
      fprintf(stderr, "\n");
4466
  }
4467
  panic("TclExecuteByteCode execution failure: bad stack top");
4468
    }
4469
}
4470
#endif /* TCL_COMPILE_DEBUG */
4471
 
4472
/*
4473
 *----------------------------------------------------------------------
4474
 *
4475
 * IllegalExprOperandType --
4476
 *
4477
 *  Used by TclExecuteByteCode to add an error message to errorInfo
4478
 *  when an illegal operand type is detected by an expression
4479
 *  instruction. The argument opndPtr holds the operand object in error.
4480
 *
4481
 * Results:
4482
 *  None.
4483
 *
4484
 * Side effects:
4485
 *  An error message is appended to errorInfo.
4486
 *
4487
 *----------------------------------------------------------------------
4488
 */
4489
 
4490
static void
4491
IllegalExprOperandType(interp, pc, opndPtr)
4492
    Tcl_Interp *interp;   /* Interpreter to which error information
4493
         * pertains. */
4494
    unsigned char *pc;    /* Points to the instruction being executed
4495
         * when the illegal type was found. */
4496
    Tcl_Obj *opndPtr;   /* Points to the operand holding the value
4497
         * with the illegal type. */
4498
{
4499
    unsigned char opCode = *pc;
4500
 
4501
    Tcl_ResetResult(interp);
4502
    if ((opndPtr->bytes == NULL) || (opndPtr->length == 0)) {
4503
  Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
4504
    "can't use empty string as operand of \"",
4505
    operatorStrings[opCode - INST_LOR], "\"", (char *) NULL);
4506
    } else {
4507
  char *msg = "non-numeric string";
4508
  char *s, *p;
4509
  int length;
4510
  int looksLikeInt = 0;
4511
 
4512
  s = Tcl_GetStringFromObj(opndPtr, &length);
4513
  p = s;
4514
  /*
4515
   * strtod() isn't at all consistent about detecting Inf and
4516
   * NaN between platforms.
4517
   */
4518
  if (length == 3) {
4519
      if ((s[0]=='n' || s[0]=='N') && (s[1]=='a' || s[1]=='A') &&
4520
        (s[2]=='n' || s[2]=='N')) {
4521
    msg = "non-numeric floating-point value";
4522
    goto makeErrorMessage;
4523
      }
4524
      if ((s[0]=='i' || s[0]=='I') && (s[1]=='n' || s[1]=='N') &&
4525
        (s[2]=='f' || s[2]=='F')) {
4526
    msg = "infinite floating-point value";
4527
    goto makeErrorMessage;
4528
      }
4529
  }
4530
 
4531
  /*
4532
   * We cannot use TclLooksLikeInt here because it passes strings
4533
   * like "10;" [Bug 587140]. We'll accept as "looking like ints"
4534
   * for the present purposes any string that looks formally like
4535
   * a (decimal|octal|hex) integer.
4536
   */
4537
 
4538
  while (length && isspace(UCHAR(*p))) {
4539
      length--;
4540
      p++;
4541
  }
4542
  if (length && ((*p == '+') || (*p == '-'))) {
4543
      length--;
4544
      p++;
4545
  }
4546
  if (length) {
4547
      if ((*p == '0') && ((*(p+1) == 'x') || (*(p+1) == 'X'))) {
4548
    p += 2;
4549
    length -= 2;
4550
    looksLikeInt = ((length > 0) && isxdigit(UCHAR(*p)));
4551
    if (looksLikeInt) {
4552
        length--;
4553
        p++;
4554
        while (length && isxdigit(UCHAR(*p))) {
4555
      length--;
4556
      p++;
4557
        }
4558
    }
4559
      } else {
4560
    looksLikeInt = (length && isdigit(UCHAR(*p)));
4561
    if (looksLikeInt) {
4562
        length--;
4563
        p++;
4564
        while (length && isdigit(UCHAR(*p))) {
4565
      length--;
4566
      p++;
4567
        }
4568
    }
4569
      }
4570
      while (length && isspace(UCHAR(*p))) {
4571
    length--;
4572
    p++;
4573
      }
4574
      looksLikeInt = !length;
4575
  }
4576
  if (looksLikeInt) {
4577
      /*
4578
       * If something that looks like an integer could not be
4579
       * converted, then it *must* be a bad octal or too large
4580
       * to represent [Bug 542588].
4581
       */
4582
 
4583
      if (TclCheckBadOctal(NULL, s)) {
4584
    msg = "invalid octal number";
4585
      } else {
4586
    msg = "integer value too large to represent";
4587
    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
4588
        "integer value too large to represent", (char *) NULL);
4589
      }
4590
  } else {
4591
      /*
4592
       * See if the operand can be interpreted as a double in
4593
       * order to improve the error message.
4594
       */
4595
 
4596
      double d;
4597
 
4598
      if (Tcl_GetDouble((Tcl_Interp *) NULL, s, &d) == TCL_OK) {
4599
    msg = "floating-point value";
4600
      }
4601
  }
4602
      makeErrorMessage:
4603
  Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't use ",
4604
    msg, " as operand of \"", operatorStrings[opCode - INST_LOR],
4605
    "\"", (char *) NULL);
4606
    }
4607
}
4608
 
4609
/*
4610
 *----------------------------------------------------------------------
4611
 *
4612
 * GetSrcInfoForPc --
4613
 *
4614
 *  Given a program counter value, finds the closest command in the
4615
 *  bytecode code unit's CmdLocation array and returns information about
4616
 *  that command's source: a pointer to its first byte and the number of
4617
 *  characters.
4618
 *
4619
 * Results:
4620
 *  If a command is found that encloses the program counter value, a
4621
 *  pointer to the command's source is returned and the length of the
4622
 *  source is stored at *lengthPtr. If multiple commands resulted in
4623
 *  code at pc, information about the closest enclosing command is
4624
 *  returned. If no matching command is found, NULL is returned and
4625
 *  *lengthPtr is unchanged.
4626
 *
4627
 * Side effects:
4628
 *  None.
4629
 *
4630
 *----------------------------------------------------------------------
4631
 */
4632
 
4633
static char *
4634
GetSrcInfoForPc(pc, codePtr, lengthPtr)
4635
    unsigned char *pc;    /* The program counter value for which to
4636
         * return the closest command's source info.
4637
         * This points to a bytecode instruction
4638
         * in codePtr's code. */
4639
    ByteCode *codePtr;    /* The bytecode sequence in which to look
4640
         * up the command source for the pc. */
4641
    int *lengthPtr;   /* If non-NULL, the location where the
4642
         * length of the command's source should be
4643
         * stored. If NULL, no length is stored. */
4644
{
4645
    register int pcOffset = (pc - codePtr->codeStart);
4646
    int numCmds = codePtr->numCommands;
4647
    unsigned char *codeDeltaNext, *codeLengthNext;
4648
    unsigned char *srcDeltaNext, *srcLengthNext;
4649
    int codeOffset, codeLen, codeEnd, srcOffset, srcLen, delta, i;
4650
    int bestDist = INT_MAX; /* Distance of pc to best cmd's start pc. */
4651
    int bestSrcOffset = -1; /* Initialized to avoid compiler warning. */
4652
    int bestSrcLength = -1; /* Initialized to avoid compiler warning. */
4653
 
4654
    if ((pcOffset < 0) || (pcOffset >= codePtr->numCodeBytes)) {
4655
  return NULL;
4656
    }
4657
 
4658
    /*
4659
     * Decode the code and source offset and length for each command. The
4660
     * closest enclosing command is the last one whose code started before
4661
     * pcOffset.
4662
     */
4663
 
4664
    codeDeltaNext = codePtr->codeDeltaStart;
4665
    codeLengthNext = codePtr->codeLengthStart;
4666
    srcDeltaNext  = codePtr->srcDeltaStart;
4667
    srcLengthNext = codePtr->srcLengthStart;
4668
    codeOffset = srcOffset = 0;
4669
    for (i = 0;  i < numCmds;  i++) {
4670
  if ((unsigned int) (*codeDeltaNext) == (unsigned int) 0xFF) {
4671
      codeDeltaNext++;
4672
      delta = TclGetInt4AtPtr(codeDeltaNext);
4673
      codeDeltaNext += 4;
4674
  } else {
4675
      delta = TclGetInt1AtPtr(codeDeltaNext);
4676
      codeDeltaNext++;
4677
  }
4678
  codeOffset += delta;
4679
 
4680
  if ((unsigned int) (*codeLengthNext) == (unsigned int) 0xFF) {
4681
      codeLengthNext++;
4682
      codeLen = TclGetInt4AtPtr(codeLengthNext);
4683
      codeLengthNext += 4;
4684
  } else {
4685
      codeLen = TclGetInt1AtPtr(codeLengthNext);
4686
      codeLengthNext++;
4687
  }
4688
  codeEnd = (codeOffset + codeLen - 1);
4689
 
4690
  if ((unsigned int) (*srcDeltaNext) == (unsigned int) 0xFF) {
4691
      srcDeltaNext++;
4692
      delta = TclGetInt4AtPtr(srcDeltaNext);
4693
      srcDeltaNext += 4;
4694
  } else {
4695
      delta = TclGetInt1AtPtr(srcDeltaNext);
4696
      srcDeltaNext++;
4697
  }
4698
  srcOffset += delta;
4699
 
4700
  if ((unsigned int) (*srcLengthNext) == (unsigned int) 0xFF) {
4701
      srcLengthNext++;
4702
      srcLen = TclGetInt4AtPtr(srcLengthNext);
4703
      srcLengthNext += 4;
4704
  } else {
4705
      srcLen = TclGetInt1AtPtr(srcLengthNext);
4706
      srcLengthNext++;
4707
  }
4708
 
4709
  if (codeOffset > pcOffset) {      /* best cmd already found */
4710
      break;
4711
  } else if (pcOffset <= codeEnd) { /* this cmd's code encloses pc */
4712
      int dist = (pcOffset - codeOffset);
4713
      if (dist <= bestDist) {
4714
    bestDist = dist;
4715
    bestSrcOffset = srcOffset;
4716
    bestSrcLength = srcLen;
4717
      }
4718
  }
4719
    }
4720
 
4721
    if (bestDist == INT_MAX) {
4722
  return NULL;
4723
    }
4724
 
4725
    if (lengthPtr != NULL) {
4726
  *lengthPtr = bestSrcLength;
4727
    }
4728
    return (codePtr->source + bestSrcOffset);
4729
}
4730
 
4731
/*
4732
 *----------------------------------------------------------------------
4733
 *
4734
 * GetExceptRangeForPc --
4735
 *
4736
 *  Given a program counter value, return the closest enclosing
4737
 *  ExceptionRange.
4738
 *
4739
 * Results:
4740
 *  In the normal case, catchOnly is 0 (false) and this procedure
4741
 *  returns a pointer to the most closely enclosing ExceptionRange
4742
 *  structure regardless of whether it is a loop or catch exception
4743
 *  range. This is appropriate when processing a TCL_BREAK or
4744
 *  TCL_CONTINUE, which will be "handled" either by a loop exception
4745
 *  range or a closer catch range. If catchOnly is nonzero, this
4746
 *  procedure ignores loop exception ranges and returns a pointer to the
4747
 *  closest catch range. If no matching ExceptionRange is found that
4748
 *  encloses pc, a NULL is returned.
4749
 *
4750
 * Side effects:
4751
 *  None.
4752
 *
4753
 *----------------------------------------------------------------------
4754
 */
4755
 
4756
static ExceptionRange *
4757
GetExceptRangeForPc(pc, catchOnly, codePtr)
4758
    unsigned char *pc;    /* The program counter value for which to
4759
         * search for a closest enclosing exception
4760
         * range. This points to a bytecode
4761
         * instruction in codePtr's code. */
4762
    int catchOnly;    /* If 0, consider either loop or catch
4763
         * ExceptionRanges in search. If nonzero
4764
         * consider only catch ranges (and ignore
4765
         * any closer loop ranges). */
4766
    ByteCode* codePtr;    /* Points to the ByteCode in which to search
4767
         * for the enclosing ExceptionRange. */
4768
{
4769
    ExceptionRange *rangeArrayPtr;
4770
    int numRanges = codePtr->numExceptRanges;
4771
    register ExceptionRange *rangePtr;
4772
    int pcOffset = (pc - codePtr->codeStart);
4773
    register int start;
4774
 
4775
    if (numRanges == 0) {
4776
  return NULL;
4777
    }
4778
 
4779
    /*
4780
     * This exploits peculiarities of our compiler: nested ranges
4781
     * are always *after* their containing ranges, so that by scanning
4782
     * backwards we are sure that the first matching range is indeed
4783
     * the deepest.
4784
     */
4785
 
4786
    rangeArrayPtr = codePtr->exceptArrayPtr;
4787
    rangePtr = rangeArrayPtr + numRanges;
4788
    while (--rangePtr >= rangeArrayPtr) {
4789
  start = rangePtr->codeOffset;
4790
  if ((start <= pcOffset) &&
4791
          (pcOffset < (start + rangePtr->numCodeBytes))) {
4792
      if ((!catchOnly)
4793
        || (rangePtr->type == CATCH_EXCEPTION_RANGE)) {
4794
    return rangePtr;
4795
      }
4796
  }
4797
    }
4798
    return NULL;
4799
}
4800
 
4801
/*
4802
 *----------------------------------------------------------------------
4803
 *
4804
 * GetOpcodeName --
4805
 *
4806
 *  This procedure is called by the TRACE and TRACE_WITH_OBJ macros
4807
 *  used in TclExecuteByteCode when debugging. It returns the name of
4808
 *  the bytecode instruction at a specified instruction pc.
4809
 *
4810
 * Results:
4811
 *  A character string for the instruction.
4812
 *
4813
 * Side effects:
4814
 *  None.
4815
 *
4816
 *----------------------------------------------------------------------
4817
 */
4818
 
4819
#ifdef TCL_COMPILE_DEBUG
4820
static char *
4821
GetOpcodeName(pc)
4822
    unsigned char *pc;    /* Points to the instruction whose name
4823
         * should be returned. */
4824
{
4825
    unsigned char opCode = *pc;
4826
 
4827
    return tclInstructionTable[opCode].name;
4828
}
4829
#endif /* TCL_COMPILE_DEBUG */
4830
 
4831
/*
4832
 *----------------------------------------------------------------------
4833
 *
4834
 * VerifyExprObjType --
4835
 *
4836
 *  This procedure is called by the math functions to verify that
4837
 *  the object is either an int or double, coercing it if necessary.
4838
 *  If an error occurs during conversion, an error message is left
4839
 *  in the interpreter's result unless "interp" is NULL.
4840
 *
4841
 * Results:
4842
 *  TCL_OK if it was int or double, TCL_ERROR otherwise
4843
 *
4844
 * Side effects:
4845
 *  objPtr is ensured to be of tclIntType, tclWideIntType or
4846
 *  tclDoubleType.
4847
 *
4848
 *----------------------------------------------------------------------
4849
 */
4850
 
4851
static int
4852
VerifyExprObjType(interp, objPtr)
4853
    Tcl_Interp *interp;   /* The interpreter in which to execute the
4854
         * function. */
4855
    Tcl_Obj *objPtr;    /* Points to the object to type check. */
4856
{
4857
    if (IS_NUMERIC_TYPE(objPtr->typePtr)) {
4858
  return TCL_OK;
4859
    } else {
4860
  int length, result = TCL_OK;
4861
  char *s = Tcl_GetStringFromObj(objPtr, &length);
4862
 
4863
  if (TclLooksLikeInt(s, length)) {
4864
      long i;
4865
      Tcl_WideInt w;
4866
      GET_WIDE_OR_INT(result, objPtr, i, w);
4867
  } else {
4868
      double d;
4869
      result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, objPtr, &d);
4870
  }
4871
  if ((result != TCL_OK) && (interp != NULL)) {
4872
      Tcl_ResetResult(interp);
4873
      if (TclCheckBadOctal((Tcl_Interp *) NULL, s)) {
4874
    Tcl_AppendToObj(Tcl_GetObjResult(interp),
4875
      "argument to math function was an invalid octal number",
4876
      -1);
4877
      } else {
4878
    Tcl_AppendToObj(Tcl_GetObjResult(interp),
4879
      "argument to math function didn't have numeric value",
4880
      -1);
4881
      }
4882
  }
4883
  return result;
4884
    }
4885
}
4886
 
4887
/*
4888
 *----------------------------------------------------------------------
4889
 *
4890
 * Math Functions --
4891
 *
4892
 *  This page contains the procedures that implement all of the
4893
 *  built-in math functions for expressions.
4894
 *
4895
 * Results:
4896
 *  Each procedure returns TCL_OK if it succeeds and pushes an
4897
 *  Tcl object holding the result. If it fails it returns TCL_ERROR
4898
 *  and leaves an error message in the interpreter's result.
4899
 *
4900
 * Side effects:
4901
 *  None.
4902
 *
4903
 *----------------------------------------------------------------------
4904
 */
4905
 
4906
static int
4907
ExprUnaryFunc(interp, eePtr, clientData)
4908
    Tcl_Interp *interp;   /* The interpreter in which to execute the
4909
         * function. */
4910
    ExecEnv *eePtr;   /* Points to the environment for executing
4911
         * the function. */
4912
    ClientData clientData;  /* Contains the address of a procedure that
4913
         * takes one double argument and returns a
4914
         * double result. */
4915
{
4916
    Tcl_Obj **stackPtr;   /* Cached evaluation stack base pointer. */
4917
    register int stackTop;  /* Cached top index of evaluation stack. */
4918
    register Tcl_Obj *valuePtr;
4919
    double d, dResult;
4920
    int result;
4921
 
4922
    double (*func) _ANSI_ARGS_((double)) =
4923
  (double (*)_ANSI_ARGS_((double))) clientData;
4924
 
4925
    /*
4926
     * Set stackPtr and stackTop from eePtr.
4927
     */
4928
 
4929
    result = TCL_OK;
4930
    CACHE_STACK_INFO();
4931
 
4932
    /*
4933
     * Pop the function's argument from the evaluation stack. Convert it
4934
     * to a double if necessary.
4935
     */
4936
 
4937
    valuePtr = POP_OBJECT();
4938
 
4939
    if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
4940
  result = TCL_ERROR;
4941
  goto done;
4942
    }
4943
 
4944
    GET_DOUBLE_VALUE(d, valuePtr, valuePtr->typePtr);
4945
 
4946
    errno = 0;
4947
    dResult = (*func)(d);
4948
    if ((errno != 0) || IS_NAN(dResult) || IS_INF(dResult)) {
4949
  TclExprFloatError(interp, dResult);
4950
  result = TCL_ERROR;
4951
  goto done;
4952
    }
4953
 
4954
    /*
4955
     * Push a Tcl object holding the result.
4956
     */
4957
 
4958
    PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
4959
 
4960
    /*
4961
     * Reflect the change to stackTop back in eePtr.
4962
     */
4963
 
4964
    done:
4965
    TclDecrRefCount(valuePtr);
4966
    DECACHE_STACK_INFO();
4967
    return result;
4968
}
4969
 
4970
static int
4971
ExprBinaryFunc(interp, eePtr, clientData)
4972
    Tcl_Interp *interp;   /* The interpreter in which to execute the
4973
         * function. */
4974
    ExecEnv *eePtr;   /* Points to the environment for executing
4975
         * the function. */
4976
    ClientData clientData;  /* Contains the address of a procedure that
4977