/[dtapublic]/projs/ets/trunk/src/c_tcl_base_7_5_w_mods/tclcompile.h
ViewVC logotype

Diff of /projs/ets/trunk/src/c_tcl_base_7_5_w_mods/tclcompile.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

to_be_filed/sf_code/esrgpcpj/shared/tcl_base/tclcompile.h revision 29 by dashley, Sat Oct 8 07:08:47 2016 UTC projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclcompile.h revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tcl_base/tclcompile.h,v 1.1.1.1 2001/06/13 04:36:28 dtashley Exp $ */  
   
 /*  
  * tclCompile.h --  
  *  
  * Copyright (c) 1996-1998 Sun Microsystems, Inc.  
  *  
  * See the file "license.terms" for information on usage and redistribution  
  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.  
  *  
  * RCS: @(#) $Id: tclcompile.h,v 1.1.1.1 2001/06/13 04:36:28 dtashley Exp $  
  */  
   
 #ifndef _TCLCOMPILATION  
 #define _TCLCOMPILATION 1  
   
 #ifndef _TCLINT  
 #include "tclInt.h"  
 #endif /* _TCLINT */  
   
 #ifdef BUILD_tcl  
 # undef TCL_STORAGE_CLASS  
 # define TCL_STORAGE_CLASS DLLEXPORT  
 #endif  
   
 /*  
  *------------------------------------------------------------------------  
  * Variables related to compilation. These are used in tclCompile.c,  
  * tclExecute.c, tclBasic.c, and their clients.  
  *------------------------------------------------------------------------  
  */  
   
 /*  
  * Variable that denotes the command name Tcl object type. Objects of this  
  * type cache the Command pointer that results from looking up command names  
  * in the command hashtable.  
  */  
   
 extern Tcl_ObjType      tclCmdNameType;  
   
 /*  
  * Variable that controls whether compilation tracing is enabled and, if so,  
  * what level of tracing is desired:  
  *    0: no compilation tracing  
  *    1: summarize compilation of top level cmds and proc bodies  
  *    2: display all instructions of each ByteCode compiled  
  * This variable is linked to the Tcl variable "tcl_traceCompile".  
  */  
   
 extern int              tclTraceCompile;  
   
 /*  
  * Variable that controls whether execution tracing is enabled and, if so,  
  * what level of tracing is desired:  
  *    0: no execution tracing  
  *    1: trace invocations of Tcl procs only  
  *    2: trace invocations of all (not compiled away) commands  
  *    3: display each instruction executed  
  * This variable is linked to the Tcl variable "tcl_traceExec".  
  */  
   
 extern int              tclTraceExec;  
   
 /*  
  *------------------------------------------------------------------------  
  * Data structures related to compilation.  
  *------------------------------------------------------------------------  
  */  
   
 /*  
  * The structure used to implement Tcl "exceptions" (exceptional returns):  
  * for example, those generated in loops by the break and continue commands,  
  * and those generated by scripts and caught by the catch command. This  
  * ExceptionRange structure describes a range of code (e.g., a loop body),  
  * the kind of exceptions (e.g., a break or continue) that might occur, and  
  * the PC offsets to jump to if a matching exception does occur. Exception  
  * ranges can nest so this structure includes a nesting level that is used  
  * at runtime to find the closest exception range surrounding a PC. For  
  * example, when a break command is executed, the ExceptionRange structure  
  * for the most deeply nested loop, if any, is found and used. These  
  * structures are also generated for the "next" subcommands of for loops  
  * since a break there terminates the for command. This means a for command  
  * actually generates two LoopInfo structures.  
  */  
   
 typedef enum {  
     LOOP_EXCEPTION_RANGE,       /* Exception's range is part of a loop.  
                                  * Break and continue "exceptions" cause  
                                  * jumps to appropriate PC offsets. */  
     CATCH_EXCEPTION_RANGE       /* Exception's range is controlled by a  
                                  * catch command. Errors in the range cause  
                                  * a jump to a catch PC offset. */  
 } ExceptionRangeType;  
   
 typedef struct ExceptionRange {  
     ExceptionRangeType type;    /* The kind of ExceptionRange. */  
     int nestingLevel;           /* Static depth of the exception range.  
                                  * Used to find the most deeply-nested  
                                  * range surrounding a PC at runtime. */  
     int codeOffset;             /* Offset of the first instruction byte of  
                                  * the code range. */  
     int numCodeBytes;           /* Number of bytes in the code range. */  
     int breakOffset;            /* If LOOP_EXCEPTION_RANGE, the target PC  
                                  * offset for a break command in the range. */  
     int continueOffset;         /* If LOOP_EXCEPTION_RANGE and not -1, the  
                                  * target PC offset for a continue command in  
                                  * the code range. Otherwise, ignore this range  
                                  * when processing a continue command. */  
     int catchOffset;            /* If a CATCH_EXCEPTION_RANGE, the target PC  
                                  * offset for any "exception" in range. */  
 } ExceptionRange;  
   
 /*  
  * Structure used to map between instruction pc and source locations. It  
  * defines for each compiled Tcl command its code's starting offset and  
  * its source's starting offset and length. Note that the code offset  
  * increases monotonically: that is, the table is sorted in code offset  
  * order. The source offset is not monotonic.  
  */  
   
 typedef struct CmdLocation {  
     int codeOffset;             /* Offset of first byte of command code. */  
     int numCodeBytes;           /* Number of bytes for command's code. */  
     int srcOffset;              /* Offset of first char of the command. */  
     int numSrcBytes;            /* Number of command source chars. */  
 } CmdLocation;  
   
 /*  
  * CompileProcs need the ability to record information during compilation  
  * that can be used by bytecode instructions during execution. The AuxData  
  * structure provides this "auxiliary data" mechanism. An arbitrary number  
  * of these structures can be stored in the ByteCode record (during  
  * compilation they are stored in a CompileEnv structure). Each AuxData  
  * record holds one word of client-specified data (often a pointer) and is  
  * given an index that instructions can later use to look up the structure  
  * and its data.  
  *  
  * The following definitions declare the types of procedures that are called  
  * to duplicate or free this auxiliary data when the containing ByteCode  
  * objects are duplicated and freed. Pointers to these procedures are kept  
  * in the AuxData structure.  
  */  
   
 typedef ClientData (AuxDataDupProc)  _ANSI_ARGS_((ClientData clientData));  
 typedef void       (AuxDataFreeProc) _ANSI_ARGS_((ClientData clientData));  
   
 /*  
  * We define a separate AuxDataType struct to hold type-related information  
  * for the AuxData structure. This separation makes it possible for clients  
  * outside of the TCL core to manipulate (in a limited fashion!) AuxData;  
  * for example, it makes it possible to pickle and unpickle AuxData structs.  
  */  
   
 typedef struct AuxDataType {  
     char *name;                                 /* the name of the type. Types can be  
                                  * registered and found by name */  
     AuxDataDupProc *dupProc;    /* Callback procedure to invoke when the  
                                  * aux data is duplicated (e.g., when the  
                                  * ByteCode structure containing the aux  
                                  * data is duplicated). NULL means just  
                                  * copy the source clientData bits; no  
                                  * proc need be called. */  
     AuxDataFreeProc *freeProc;  /* Callback procedure to invoke when the  
                                  * aux data is freed. NULL means no  
                                  * proc need be called. */  
 } AuxDataType;  
   
 /*  
  * The definition of the AuxData structure that holds information created  
  * during compilation by CompileProcs and used by instructions during  
  * execution.  
  */  
   
 typedef struct AuxData {  
     AuxDataType *type;          /* pointer to the AuxData type associated with  
                              * this ClientData. */  
     ClientData clientData;      /* The compilation data itself. */  
 } AuxData;  
   
 /*  
  * Structure defining the compilation environment. After compilation, fields  
  * describing bytecode instructions are copied out into the more compact  
  * ByteCode structure defined below.  
  */  
   
 #define COMPILEENV_INIT_CODE_BYTES    250  
 #define COMPILEENV_INIT_NUM_OBJECTS    60  
 #define COMPILEENV_INIT_EXCEPT_RANGES   5  
 #define COMPILEENV_INIT_CMD_MAP_SIZE   40  
 #define COMPILEENV_INIT_AUX_DATA_SIZE   5  
   
 typedef struct CompileEnv {  
     Interp *iPtr;               /* Interpreter containing the code being  
                                  * compiled. Commands and their compile  
                                  * procs are specific to an interpreter so  
                                  * the code emitted will depend on the  
                                  * interpreter. */  
     char *source;               /* The source string being compiled by  
                                  * SetByteCodeFromAny. This pointer is not  
                                  * owned by the CompileEnv and must not be  
                                  * freed or changed by it. */  
     int numSrcBytes;            /* Number of bytes in source. */  
     Proc *procPtr;              /* If a procedure is being compiled, a  
                                  * pointer to its Proc structure; otherwise  
                                  * NULL. Used to compile local variables.  
                                  * Set from information provided by  
                                  * ObjInterpProc in tclProc.c. */  
     int numCommands;            /* Number of commands compiled. */  
     int exceptDepth;            /* Current exception range nesting level;  
                                  * -1 if not in any range currently. */  
     int maxExceptDepth;         /* Max nesting level of exception ranges;  
                                  * -1 if no ranges have been compiled. */  
     int maxStackDepth;          /* Maximum number of stack elements needed  
                                  * to execute the code. Set by compilation  
                                  * procedures before returning. */  
     LiteralTable localLitTable; /* Contains LiteralEntry's describing  
                                  * all Tcl objects referenced by this  
                                  * compiled code. Indexed by the string  
                                  * representations of the literals. Used to  
                                  * avoid creating duplicate objects. */  
     int exprIsJustVarRef;       /* Set 1 if the expression last compiled by  
                                  * TclCompileExpr consisted of just a  
                                  * variable reference as in the expression  
                                  * of "if $b then...". Otherwise 0. Used  
                                  * to implement expr's 2 level substitution  
                                  * semantics properly. */  
     int exprIsComparison;       /* Set 1 if the top-level operator in the  
                                  * expression last compiled is a comparison.  
                                  * Otherwise 0. If 1, since the operands  
                                  * might be strings, the expr is compiled  
                                  * out-of-line to implement expr's 2 level  
                                  * substitution semantics properly. */  
     unsigned char *codeStart;   /* Points to the first byte of the code. */  
     unsigned char *codeNext;    /* Points to next code array byte to use. */  
     unsigned char *codeEnd;     /* Points just after the last allocated  
                                  * code array byte. */  
     int mallocedCodeArray;      /* Set 1 if code array was expanded  
                                  * and codeStart points into the heap.*/  
     LiteralEntry *literalArrayPtr;  
                                 /* Points to start of LiteralEntry array. */  
     int literalArrayNext;       /* Index of next free object array entry. */  
     int literalArrayEnd;        /* Index just after last obj array entry. */  
     int mallocedLiteralArray;   /* 1 if object array was expanded and  
                                  * objArray points into the heap, else 0. */  
     ExceptionRange *exceptArrayPtr;  
                                 /* Points to start of the ExceptionRange  
                                  * array. */  
     int exceptArrayNext;        /* Next free ExceptionRange array index.  
                                  * exceptArrayNext is the number of ranges  
                                  * and (exceptArrayNext-1) is the index of  
                                  * the current range's array entry. */  
     int exceptArrayEnd;         /* Index after the last ExceptionRange  
                                  * array entry. */  
     int mallocedExceptArray;    /* 1 if ExceptionRange array was expanded  
                                  * and exceptArrayPtr points in heap,  
                                  * else 0. */  
     CmdLocation *cmdMapPtr;     /* Points to start of CmdLocation array.  
                                  * numCommands is the index of the next  
                                  * entry to use; (numCommands-1) is the  
                                  * entry index for the last command. */  
     int cmdMapEnd;              /* Index after last CmdLocation entry. */  
     int mallocedCmdMap;         /* 1 if command map array was expanded and  
                                  * cmdMapPtr points in the heap, else 0. */  
     AuxData *auxDataArrayPtr;   /* Points to auxiliary data array start. */  
     int auxDataArrayNext;       /* Next free compile aux data array index.  
                                  * auxDataArrayNext is the number of aux  
                                  * data items and (auxDataArrayNext-1) is  
                                  * index of current aux data array entry. */  
     int auxDataArrayEnd;        /* Index after last aux data array entry. */  
     int mallocedAuxDataArray;   /* 1 if aux data array was expanded and  
                                  * auxDataArrayPtr points in heap else 0. */  
     unsigned char staticCodeSpace[COMPILEENV_INIT_CODE_BYTES];  
                                 /* Initial storage for code. */  
     LiteralEntry staticLiteralSpace[COMPILEENV_INIT_NUM_OBJECTS];  
                                 /* Initial storage of LiteralEntry array. */  
     ExceptionRange staticExceptArraySpace[COMPILEENV_INIT_EXCEPT_RANGES];  
                                 /* Initial ExceptionRange array storage. */  
     CmdLocation staticCmdMapSpace[COMPILEENV_INIT_CMD_MAP_SIZE];  
                                 /* Initial storage for cmd location map. */  
     AuxData staticAuxDataArraySpace[COMPILEENV_INIT_AUX_DATA_SIZE];  
                                 /* Initial storage for aux data array. */  
 } CompileEnv;  
   
 /*  
  * The structure defining the bytecode instructions resulting from compiling  
  * a Tcl script. Note that this structure is variable length: a single heap  
  * object is allocated to hold the ByteCode structure immediately followed  
  * by the code bytes, the literal object array, the ExceptionRange array,  
  * the CmdLocation map, and the compilation AuxData array.  
  */  
   
 /*  
  * A PRECOMPILED bytecode struct is one that was generated from a compiled  
  * image rather than implicitly compiled from source  
  */  
 #define TCL_BYTECODE_PRECOMPILED                0x0001  
   
 typedef struct ByteCode {  
     TclHandle interpHandle;     /* Handle for interpreter containing the  
                                  * compiled code.  Commands and their compile  
                                  * procs are specific to an interpreter so the  
                                  * code emitted will depend on the  
                                  * interpreter. */  
     int compileEpoch;           /* Value of iPtr->compileEpoch when this  
                                  * ByteCode was compiled. Used to invalidate  
                                  * code when, e.g., commands with compile  
                                  * procs are redefined. */  
     Namespace *nsPtr;           /* Namespace context in which this code  
                                  * was compiled. If the code is executed  
                                  * if a different namespace, it must be  
                                  * recompiled. */  
     int nsEpoch;                /* Value of nsPtr->resolverEpoch when this  
                                  * ByteCode was compiled. Used to invalidate  
                                  * code when new namespace resolution rules  
                                  * are put into effect. */  
     int refCount;               /* Reference count: set 1 when created  
                                  * plus 1 for each execution of the code  
                                  * currently active. This structure can be  
                                  * freed when refCount becomes zero. */  
     unsigned int flags;         /* flags describing state for the codebyte.  
                                  * this variable holds ORed values from the  
                                  * TCL_BYTECODE_ masks defined above */  
     char *source;               /* The source string from which this  
                                  * ByteCode was compiled. Note that this  
                                  * pointer is not owned by the ByteCode and  
                                  * must not be freed or modified by it. */  
     Proc *procPtr;              /* If the ByteCode was compiled from a  
                                  * procedure body, this is a pointer to its  
                                  * Proc structure; otherwise NULL. This  
                                  * pointer is also not owned by the ByteCode  
                                  * and must not be freed by it. */  
     size_t structureSize;       /* Number of bytes in the ByteCode structure  
                                  * itself. Does not include heap space for  
                                  * literal Tcl objects or storage referenced  
                                  * by AuxData entries. */  
     int numCommands;            /* Number of commands compiled. */  
     int numSrcBytes;            /* Number of source bytes compiled. */  
     int numCodeBytes;           /* Number of code bytes. */  
     int numLitObjects;          /* Number of objects in literal array. */  
     int numExceptRanges;        /* Number of ExceptionRange array elems. */  
     int numAuxDataItems;        /* Number of AuxData items. */  
     int numCmdLocBytes;         /* Number of bytes needed for encoded  
                                  * command location information. */  
     int maxExceptDepth;         /* Maximum nesting level of ExceptionRanges;  
                                  * -1 if no ranges were compiled. */  
     int maxStackDepth;          /* Maximum number of stack elements needed  
                                  * to execute the code. */  
     unsigned char *codeStart;   /* Points to the first byte of the code.  
                                  * This is just after the final ByteCode  
                                  * member cmdMapPtr. */  
     Tcl_Obj **objArrayPtr;      /* Points to the start of the literal  
                                  * object array. This is just after the  
                                  * last code byte. */  
     ExceptionRange *exceptArrayPtr;  
                                 /* Points to the start of the ExceptionRange  
                                  * array. This is just after the last  
                                  * object in the object array. */  
     AuxData *auxDataArrayPtr;   /* Points to the start of the auxiliary data  
                                  * array. This is just after the last entry  
                                  * in the ExceptionRange array. */  
     unsigned char *codeDeltaStart;  
                                 /* Points to the first of a sequence of  
                                  * bytes that encode the change in the  
                                  * starting offset of each command's code.  
                                  * If -127<=delta<=127, it is encoded as 1  
                                  * byte, otherwise 0xFF (128) appears and  
                                  * the delta is encoded by the next 4 bytes.  
                                  * Code deltas are always positive. This  
                                  * sequence is just after the last entry in  
                                  * the AuxData array. */  
     unsigned char *codeLengthStart;  
                                 /* Points to the first of a sequence of  
                                  * bytes that encode the length of each  
                                  * command's code. The encoding is the same  
                                  * as for code deltas. Code lengths are  
                                  * always positive. This sequence is just  
                                  * after the last entry in the code delta  
                                  * sequence. */  
     unsigned char *srcDeltaStart;  
                                 /* Points to the first of a sequence of  
                                  * bytes that encode the change in the  
                                  * starting offset of each command's source.  
                                  * The encoding is the same as for code  
                                  * deltas. Source deltas can be negative.  
                                  * This sequence is just after the last byte  
                                  * in the code length sequence. */  
     unsigned char *srcLengthStart;  
                                 /* Points to the first of a sequence of  
                                  * bytes that encode the length of each  
                                  * command's source. The encoding is the  
                                  * same as for code deltas. Source lengths  
                                  * are always positive. This sequence is  
                                  * just after the last byte in the source  
                                  * delta sequence. */  
 #ifdef TCL_COMPILE_STATS  
     Tcl_Time createTime;        /* Absolute time when the ByteCode was  
                                  * created. */  
 #endif /* TCL_COMPILE_STATS */  
 } ByteCode;  
   
 /*  
  * Opcodes for the Tcl bytecode instructions. These must correspond to the  
  * entries in the table of instruction descriptions, instructionTable, in  
  * tclCompile.c. Also, the order and number of the expression opcodes  
  * (e.g., INST_LOR) must match the entries in the array operatorStrings in  
  * tclExecute.c.  
  */  
   
 /* Opcodes 0 to 9 */  
 #define INST_DONE                       0  
 #define INST_PUSH1                      1  
 #define INST_PUSH4                      2  
 #define INST_POP                        3  
 #define INST_DUP                        4  
 #define INST_CONCAT1                    5  
 #define INST_INVOKE_STK1                6  
 #define INST_INVOKE_STK4                7  
 #define INST_EVAL_STK                   8  
 #define INST_EXPR_STK                   9  
   
 /* Opcodes 10 to 23 */  
 #define INST_LOAD_SCALAR1               10  
 #define INST_LOAD_SCALAR4               11  
 #define INST_LOAD_SCALAR_STK            12  
 #define INST_LOAD_ARRAY1                13  
 #define INST_LOAD_ARRAY4                14  
 #define INST_LOAD_ARRAY_STK             15  
 #define INST_LOAD_STK                   16  
 #define INST_STORE_SCALAR1              17  
 #define INST_STORE_SCALAR4              18  
 #define INST_STORE_SCALAR_STK           19  
 #define INST_STORE_ARRAY1               20  
 #define INST_STORE_ARRAY4               21  
 #define INST_STORE_ARRAY_STK            22  
 #define INST_STORE_STK                  23  
   
 /* Opcodes 24 to 33 */  
 #define INST_INCR_SCALAR1               24  
 #define INST_INCR_SCALAR_STK            25  
 #define INST_INCR_ARRAY1                26  
 #define INST_INCR_ARRAY_STK             27  
 #define INST_INCR_STK                   28  
 #define INST_INCR_SCALAR1_IMM           29  
 #define INST_INCR_SCALAR_STK_IMM        30  
 #define INST_INCR_ARRAY1_IMM            31  
 #define INST_INCR_ARRAY_STK_IMM         32  
 #define INST_INCR_STK_IMM               33  
   
 /* Opcodes 34 to 39 */  
 #define INST_JUMP1                      34  
 #define INST_JUMP4                      35  
 #define INST_JUMP_TRUE1                 36  
 #define INST_JUMP_TRUE4                 37  
 #define INST_JUMP_FALSE1                38  
 #define INST_JUMP_FALSE4                39  
   
 /* Opcodes 40 to 64 */  
 #define INST_LOR                        40  
 #define INST_LAND                       41  
 #define INST_BITOR                      42  
 #define INST_BITXOR                     43  
 #define INST_BITAND                     44  
 #define INST_EQ                         45  
 #define INST_NEQ                        46  
 #define INST_LT                         47  
 #define INST_GT                         48  
 #define INST_LE                         49  
 #define INST_GE                         50  
 #define INST_LSHIFT                     51  
 #define INST_RSHIFT                     52  
 #define INST_ADD                        53  
 #define INST_SUB                        54  
 #define INST_MULT                       55  
 #define INST_DIV                        56  
 #define INST_MOD                        57  
 #define INST_UPLUS                      58  
 #define INST_UMINUS                     59  
 #define INST_BITNOT                     60  
 #define INST_LNOT                       61  
 #define INST_CALL_BUILTIN_FUNC1         62  
 #define INST_CALL_FUNC1                 63  
 #define INST_TRY_CVT_TO_NUMERIC         64  
   
 /* Opcodes 65 to 66 */  
 #define INST_BREAK                      65  
 #define INST_CONTINUE                   66  
   
 /* Opcodes 67 to 68 */  
 #define INST_FOREACH_START4             67  
 #define INST_FOREACH_STEP4              68  
   
 /* Opcodes 69 to 72 */  
 #define INST_BEGIN_CATCH4               69  
 #define INST_END_CATCH                  70  
 #define INST_PUSH_RESULT                71  
 #define INST_PUSH_RETURN_CODE           72  
   
 /* The last opcode */  
 #define LAST_INST_OPCODE                72  
   
 /*  
  * Table describing the Tcl bytecode instructions: their name (for  
  * displaying code), total number of code bytes required (including  
  * operand bytes), and a description of the type of each operand.  
  * These operand types include signed and unsigned integers of length  
  * one and four bytes. The unsigned integers are used for indexes or  
  * for, e.g., the count of objects to push in a "push" instruction.  
  */  
   
 #define MAX_INSTRUCTION_OPERANDS 2  
   
 typedef enum InstOperandType {  
     OPERAND_NONE,  
     OPERAND_INT1,               /* One byte signed integer. */  
     OPERAND_INT4,               /* Four byte signed integer. */  
     OPERAND_UINT1,              /* One byte unsigned integer. */  
     OPERAND_UINT4               /* Four byte unsigned integer. */  
 } InstOperandType;  
   
 typedef struct InstructionDesc {  
     char *name;                 /* Name of instruction. */  
     int numBytes;               /* Total number of bytes for instruction. */  
     int numOperands;            /* Number of operands. */  
     InstOperandType opTypes[MAX_INSTRUCTION_OPERANDS];  
                                 /* The type of each operand. */  
 } InstructionDesc;  
   
 extern InstructionDesc instructionTable[];  
   
 /*  
  * Definitions of the values of the INST_CALL_BUILTIN_FUNC instruction's  
  * operand byte. Each value denotes a builtin Tcl math function. These  
  * values must correspond to the entries in the builtinFuncTable array  
  * below and to the values stored in the tclInt.h MathFunc structure's  
  * builtinFuncIndex field.  
  */  
   
 #define BUILTIN_FUNC_ACOS               0  
 #define BUILTIN_FUNC_ASIN               1  
 #define BUILTIN_FUNC_ATAN               2  
 #define BUILTIN_FUNC_ATAN2              3  
 #define BUILTIN_FUNC_CEIL               4  
 #define BUILTIN_FUNC_COS                5  
 #define BUILTIN_FUNC_COSH               6  
 #define BUILTIN_FUNC_EXP                7  
 #define BUILTIN_FUNC_FLOOR              8  
 #define BUILTIN_FUNC_FMOD               9  
 #define BUILTIN_FUNC_HYPOT              10  
 #define BUILTIN_FUNC_LOG                11  
 #define BUILTIN_FUNC_LOG10              12  
 #define BUILTIN_FUNC_POW                13  
 #define BUILTIN_FUNC_SIN                14  
 #define BUILTIN_FUNC_SINH               15  
 #define BUILTIN_FUNC_SQRT               16  
 #define BUILTIN_FUNC_TAN                17  
 #define BUILTIN_FUNC_TANH               18  
 #define BUILTIN_FUNC_ABS                19  
 #define BUILTIN_FUNC_DOUBLE             20  
 #define BUILTIN_FUNC_INT                21  
 #define BUILTIN_FUNC_RAND               22  
 #define BUILTIN_FUNC_ROUND              23  
 #define BUILTIN_FUNC_SRAND              24  
   
 #define LAST_BUILTIN_FUNC               24  
   
 /*  
  * Table describing the built-in math functions. Entries in this table are  
  * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's  
  * operand byte.  
  */  
   
 typedef int (CallBuiltinFuncProc) _ANSI_ARGS_((Tcl_Interp *interp,  
         ExecEnv *eePtr, ClientData clientData));  
   
 typedef struct {  
     char *name;                 /* Name of function. */  
     int numArgs;                /* Number of arguments for function. */  
     Tcl_ValueType argTypes[MAX_MATH_ARGS];  
                                 /* Acceptable types for each argument. */  
     CallBuiltinFuncProc *proc;  /* Procedure implementing this function. */  
     ClientData clientData;      /* Additional argument to pass to the  
                                  * function when invoking it. */  
 } BuiltinFunc;  
   
 extern BuiltinFunc builtinFuncTable[];  
   
 /*  
  * Compilation of some Tcl constructs such as if commands and the logical or  
  * (||) and logical and (&&) operators in expressions requires the  
  * generation of forward jumps. Since the PC target of these jumps isn't  
  * known when the jumps are emitted, we record the offset of each jump in an  
  * array of JumpFixup structures. There is one array for each sequence of  
  * jumps to one target PC. When we learn the target PC, we update the jumps  
  * with the correct distance. Also, if the distance is too great (> 127  
  * bytes), we replace the single-byte jump with a four byte jump  
  * instruction, move the instructions after the jump down, and update the  
  * code offsets for any commands between the jump and the target.  
  */  
   
 typedef enum {  
     TCL_UNCONDITIONAL_JUMP,  
     TCL_TRUE_JUMP,  
     TCL_FALSE_JUMP  
 } TclJumpType;  
   
 typedef struct JumpFixup {  
     TclJumpType jumpType;       /* Indicates the kind of jump. */  
     int codeOffset;             /* Offset of the first byte of the one-byte  
                                  * forward jump's code. */  
     int cmdIndex;               /* Index of the first command after the one  
                                  * for which the jump was emitted. Used to  
                                  * update the code offsets for subsequent  
                                  * commands if the two-byte jump at jumpPc  
                                  * must be replaced with a five-byte one. */  
     int exceptIndex;            /* Index of the first range entry in the  
                                  * ExceptionRange array after the current  
                                  * one. This field is used to adjust the  
                                  * code offsets in subsequent ExceptionRange  
                                  * records when a jump is grown from 2 bytes  
                                  * to 5 bytes. */  
 } JumpFixup;  
   
 #define JUMPFIXUP_INIT_ENTRIES    10  
   
 typedef struct JumpFixupArray {  
     JumpFixup *fixup;           /* Points to start of jump fixup array. */  
     int next;                   /* Index of next free array entry. */  
     int end;                    /* Index of last usable entry in array. */  
     int mallocedArray;          /* 1 if array was expanded and fixups points  
                                  * into the heap, else 0. */  
     JumpFixup staticFixupSpace[JUMPFIXUP_INIT_ENTRIES];  
                                 /* Initial storage for jump fixup array. */  
 } JumpFixupArray;  
   
 /*  
  * The structure describing one variable list of a foreach command. Note  
  * that only foreach commands inside procedure bodies are compiled inline so  
  * a ForeachVarList structure always describes local variables. Furthermore,  
  * only scalar variables are supported for inline-compiled foreach loops.  
  */  
   
 typedef struct ForeachVarList {  
     int numVars;                /* The number of variables in the list. */  
     int varIndexes[1];          /* An array of the indexes ("slot numbers")  
                                  * for each variable in the procedure's  
                                  * array of local variables. Only scalar  
                                  * variables are supported. The actual  
                                  * size of this field will be large enough  
                                  * to numVars indexes. THIS MUST BE THE  
                                  * LAST FIELD IN THE STRUCTURE! */  
 } ForeachVarList;  
   
 /*  
  * Structure used to hold information about a foreach command that is needed  
  * during program execution. These structures are stored in CompileEnv and  
  * ByteCode structures as auxiliary data.  
  */  
   
 typedef struct ForeachInfo {  
     int numLists;               /* The number of both the variable and value  
                                  * lists of the foreach command. */  
     int firstValueTemp;         /* Index of the first temp var in a proc  
                                  * frame used to point to a value list. */  
     int loopCtTemp;             /* Index of temp var in a proc frame  
                                  * holding the loop's iteration count. Used  
                                  * to determine next value list element to  
                                  * assign each loop var. */  
     ForeachVarList *varLists[1];/* An array of pointers to ForeachVarList  
                                  * structures describing each var list. The  
                                  * actual size of this field will be large  
                                  * enough to numVars indexes. THIS MUST BE  
                                  * THE LAST FIELD IN THE STRUCTURE! */  
 } ForeachInfo;  
   
 extern AuxDataType              tclForeachInfoType;  
   
 /*  
  * Structure containing a cached pointer to a command that is the result  
  * of resolving the command's name in some namespace. It is the internal  
  * representation for a cmdName object. It contains the pointer along  
  * with some information that is used to check the pointer's validity.  
  */  
   
 typedef struct ResolvedCmdName {  
     Command *cmdPtr;            /* A cached Command pointer. */  
     Namespace *refNsPtr;        /* Points to the namespace containing the  
                                  * reference (not the namespace that  
                                  * contains the referenced command). */  
     long refNsId;               /* refNsPtr's unique namespace id. Used to  
                                  * verify that refNsPtr is still valid  
                                  * (e.g., it's possible that the cmd's  
                                  * containing namespace was deleted and a  
                                  * new one created at the same address). */  
     int refNsCmdEpoch;          /* Value of the referencing namespace's  
                                  * cmdRefEpoch when the pointer was cached.  
                                  * Before using the cached pointer, we check  
                                  * if the namespace's epoch was incremented;  
                                  * if so, this cached pointer is invalid. */  
     int cmdEpoch;               /* Value of the command's cmdEpoch when this  
                                  * pointer was cached. Before using the  
                                  * cached pointer, we check if the cmd's  
                                  * epoch was incremented; if so, the cmd was  
                                  * renamed, deleted, hidden, or exposed, and  
                                  * so the pointer is invalid. */  
     int refCount;               /* Reference count: 1 for each cmdName  
                                  * object that has a pointer to this  
                                  * ResolvedCmdName structure as its internal  
                                  * rep. This structure can be freed when  
                                  * refCount becomes zero. */  
 } ResolvedCmdName;  
   
 /*  
  *----------------------------------------------------------------  
  * Procedures shared among Tcl bytecode compilation and execution  
  * modules but not used outside:  
  *----------------------------------------------------------------  
  */  
   
 EXTERN void             TclCleanupByteCode _ANSI_ARGS_((ByteCode *codePtr));  
 EXTERN int              TclCompileCmdWord _ANSI_ARGS_((Tcl_Interp *interp,  
                             Tcl_Token *tokenPtr, int count,  
                             CompileEnv *envPtr));  
 EXTERN int              TclCompileExpr _ANSI_ARGS_((Tcl_Interp *interp,  
                             char *script, int numBytes,  
                             CompileEnv *envPtr));  
 EXTERN int              TclCompileExprWords _ANSI_ARGS_((Tcl_Interp *interp,  
                             Tcl_Token *tokenPtr, int numWords,  
                             CompileEnv *envPtr));  
 EXTERN int              TclCompileScript _ANSI_ARGS_((Tcl_Interp *interp,  
                             char *script, int numBytes, int nested,  
                             CompileEnv *envPtr));  
 EXTERN int              TclCompileTokens _ANSI_ARGS_((Tcl_Interp *interp,  
                             Tcl_Token *tokenPtr, int count,  
                             CompileEnv *envPtr));  
 EXTERN int              TclCreateAuxData _ANSI_ARGS_((ClientData clientData,  
                             AuxDataType *typePtr, CompileEnv *envPtr));  
 EXTERN int              TclCreateExceptRange _ANSI_ARGS_((  
                             ExceptionRangeType type, CompileEnv *envPtr));  
 EXTERN ExecEnv *        TclCreateExecEnv _ANSI_ARGS_((Tcl_Interp *interp));  
 EXTERN void             TclDeleteExecEnv _ANSI_ARGS_((ExecEnv *eePtr));  
 EXTERN void             TclDeleteLiteralTable _ANSI_ARGS_((  
                             Tcl_Interp *interp, LiteralTable *tablePtr));  
 EXTERN void             TclEmitForwardJump _ANSI_ARGS_((CompileEnv *envPtr,  
                             TclJumpType jumpType, JumpFixup *jumpFixupPtr));  
 EXTERN ExceptionRange * TclGetExceptionRangeForPc _ANSI_ARGS_((  
                             unsigned char *pc, int catchOnly,  
                             ByteCode* codePtr));  
 EXTERN InstructionDesc * TclGetInstructionTable _ANSI_ARGS_(());  
 EXTERN int              TclExecuteByteCode _ANSI_ARGS_((Tcl_Interp *interp,  
                             ByteCode *codePtr));  
 EXTERN void             TclExpandCodeArray _ANSI_ARGS_((  
                             CompileEnv *envPtr));  
 EXTERN void             TclExpandJumpFixupArray _ANSI_ARGS_((  
                             JumpFixupArray *fixupArrayPtr));  
 EXTERN void             TclFinalizeAuxDataTypeTable _ANSI_ARGS_((void));  
 EXTERN int              TclFindCompiledLocal _ANSI_ARGS_((char *name,  
                             int nameChars, int create, int flags,  
                             Proc *procPtr));  
 EXTERN LiteralEntry *   TclLookupLiteralEntry _ANSI_ARGS_((  
                             Tcl_Interp *interp, Tcl_Obj *objPtr));  
 EXTERN int              TclFixupForwardJump _ANSI_ARGS_((  
                             CompileEnv *envPtr, JumpFixup *jumpFixupPtr,  
                             int jumpDist, int distThreshold));  
 EXTERN void             TclFreeCompileEnv _ANSI_ARGS_((CompileEnv *envPtr));  
 EXTERN void             TclFreeJumpFixupArray _ANSI_ARGS_((  
                             JumpFixupArray *fixupArrayPtr));  
 EXTERN void             TclInitAuxDataTypeTable _ANSI_ARGS_((void));  
 EXTERN void             TclInitByteCodeObj _ANSI_ARGS_((Tcl_Obj *objPtr,  
                             CompileEnv *envPtr));  
 EXTERN void             TclInitCompilation _ANSI_ARGS_((void));  
 EXTERN void             TclInitCompileEnv _ANSI_ARGS_((Tcl_Interp *interp,  
                             CompileEnv *envPtr, char *string,  
                             int numBytes));  
 EXTERN void             TclInitJumpFixupArray _ANSI_ARGS_((  
                             JumpFixupArray *fixupArrayPtr));  
 EXTERN void             TclInitLiteralTable _ANSI_ARGS_((  
                             LiteralTable *tablePtr));  
 #ifdef TCL_COMPILE_STATS  
 EXTERN char *           TclLiteralStats _ANSI_ARGS_((  
                             LiteralTable *tablePtr));  
 EXTERN int              TclLog2 _ANSI_ARGS_((int value));  
 #endif  
 #ifdef TCL_COMPILE_DEBUG  
 EXTERN void             TclPrintByteCodeObj _ANSI_ARGS_((Tcl_Interp *interp,  
                             Tcl_Obj *objPtr));  
 #endif  
 EXTERN int              TclPrintInstruction _ANSI_ARGS_((ByteCode* codePtr,  
                             unsigned char *pc));  
 EXTERN void             TclPrintObject _ANSI_ARGS_((FILE *outFile,  
                             Tcl_Obj *objPtr, int maxChars));  
 EXTERN void             TclPrintSource _ANSI_ARGS_((FILE *outFile,  
                             char *string, int maxChars));  
 EXTERN void             TclRegisterAuxDataType _ANSI_ARGS_((AuxDataType *typePtr));  
 EXTERN int              TclRegisterLiteral _ANSI_ARGS_((CompileEnv *envPtr,  
                             char *bytes, int length, int onHeap));  
 EXTERN void             TclReleaseLiteral _ANSI_ARGS_((Tcl_Interp *interp,  
                             Tcl_Obj *objPtr));  
 EXTERN void             TclSetCmdNameObj _ANSI_ARGS_((Tcl_Interp *interp,  
                             Tcl_Obj *objPtr, Command *cmdPtr));  
 #ifdef TCL_COMPILE_DEBUG  
 EXTERN void             TclVerifyGlobalLiteralTable _ANSI_ARGS_((  
                             Interp *iPtr));  
 EXTERN void             TclVerifyLocalLiteralTable _ANSI_ARGS_((  
                             CompileEnv *envPtr));  
 #endif  
   
 /*  
  *----------------------------------------------------------------  
  * Macros used by Tcl bytecode compilation and execution modules  
  * inside the Tcl core but not used outside.  
  *----------------------------------------------------------------  
  */  
   
 /*  
  * Macro to emit an opcode byte into a CompileEnv's code array.  
  * The ANSI C "prototype" for this macro is:  
  *  
  * EXTERN void  TclEmitOpcode _ANSI_ARGS_((unsigned char op,  
  *                  CompileEnv *envPtr));  
  */  
   
 #define TclEmitOpcode(op, envPtr) \  
     if ((envPtr)->codeNext == (envPtr)->codeEnd) \  
         TclExpandCodeArray(envPtr); \  
     *(envPtr)->codeNext++ = (unsigned char) (op)  
   
 /*  
  * Macro to emit an integer operand.  
  * The ANSI C "prototype" for this macro is:  
  *  
  * EXTERN void  TclEmitInt1 _ANSI_ARGS_((int i, CompileEnv *envPtr));  
  */  
   
 #define TclEmitInt1(i, envPtr) \  
     if ((envPtr)->codeNext == (envPtr)->codeEnd) \  
         TclExpandCodeArray(envPtr); \  
     *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i))  
   
 /*  
  * Macros to emit an instruction with signed or unsigned integer operands.  
  * Four byte integers are stored in "big-endian" order with the high order  
  * byte stored at the lowest address.  
  * The ANSI C "prototypes" for these macros are:  
  *  
  * EXTERN void  TclEmitInstInt1 _ANSI_ARGS_((unsigned char op, int i,  
  *                  CompileEnv *envPtr));  
  * EXTERN void  TclEmitInstInt4 _ANSI_ARGS_((unsigned char op, int i,  
  *                  CompileEnv *envPtr));  
  */  
   
 #define TclEmitInstInt1(op, i, envPtr) \  
     if (((envPtr)->codeNext + 2) > (envPtr)->codeEnd) { \  
         TclExpandCodeArray(envPtr); \  
     } \  
     *(envPtr)->codeNext++ = (unsigned char) (op); \  
     *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i))  
   
 #define TclEmitInstInt4(op, i, envPtr) \  
     if (((envPtr)->codeNext + 5) > (envPtr)->codeEnd) { \  
         TclExpandCodeArray(envPtr); \  
     } \  
     *(envPtr)->codeNext++ = (unsigned char) (op); \  
     *(envPtr)->codeNext++ = \  
         (unsigned char) ((unsigned int) (i) >> 24); \  
     *(envPtr)->codeNext++ = \  
         (unsigned char) ((unsigned int) (i) >> 16); \  
     *(envPtr)->codeNext++ = \  
         (unsigned char) ((unsigned int) (i) >>  8); \  
     *(envPtr)->codeNext++ = \  
         (unsigned char) ((unsigned int) (i)      )  
       
 /*  
  * Macro to push a Tcl object onto the Tcl evaluation stack. It emits the  
  * object's one or four byte array index into the CompileEnv's code  
  * array. These support, respectively, a maximum of 256 (2**8) and 2**32  
  * objects in a CompileEnv. The ANSI C "prototype" for this macro is:  
  *  
  * EXTERN void  TclEmitPush _ANSI_ARGS_((int objIndex, CompileEnv *envPtr));  
  */  
   
 #define TclEmitPush(objIndex, envPtr) \  
     if ((objIndex) <= 255) { \  
         TclEmitInstInt1(INST_PUSH1, (objIndex), (envPtr)); \  
     } else { \  
         TclEmitInstInt4(INST_PUSH4, (objIndex), (envPtr)); \  
     }  
   
 /*  
  * Macros to update a (signed or unsigned) integer starting at a pointer.  
  * The two variants depend on the number of bytes. The ANSI C "prototypes"  
  * for these macros are:  
  *  
  * EXTERN void  TclStoreInt1AtPtr _ANSI_ARGS_((int i, unsigned char *p));  
  * EXTERN void  TclStoreInt4AtPtr _ANSI_ARGS_((int i, unsigned char *p));  
  */  
       
 #define TclStoreInt1AtPtr(i, p) \  
     *(p)   = (unsigned char) ((unsigned int) (i))  
       
 #define TclStoreInt4AtPtr(i, p) \  
     *(p)   = (unsigned char) ((unsigned int) (i) >> 24); \  
     *(p+1) = (unsigned char) ((unsigned int) (i) >> 16); \  
     *(p+2) = (unsigned char) ((unsigned int) (i) >>  8); \  
     *(p+3) = (unsigned char) ((unsigned int) (i)      )  
   
 /*  
  * Macros to update instructions at a particular pc with a new op code  
  * and a (signed or unsigned) int operand. The ANSI C "prototypes" for  
  * these macros are:  
  *  
  * EXTERN void  TclUpdateInstInt1AtPc _ANSI_ARGS_((unsigned char op, int i,  
  *                  unsigned char *pc));  
  * EXTERN void  TclUpdateInstInt4AtPc _ANSI_ARGS_((unsigned char op, int i,  
  *                  unsigned char *pc));  
  */  
   
 #define TclUpdateInstInt1AtPc(op, i, pc) \  
     *(pc) = (unsigned char) (op); \  
     TclStoreInt1AtPtr((i), ((pc)+1))  
   
 #define TclUpdateInstInt4AtPc(op, i, pc) \  
     *(pc) = (unsigned char) (op); \  
     TclStoreInt4AtPtr((i), ((pc)+1))  
       
 /*  
  * Macros to get a signed integer (GET_INT{1,2}) or an unsigned int  
  * (GET_UINT{1,2}) from a pointer. There are two variants for each  
  * return type that depend on the number of bytes fetched.  
  * The ANSI C "prototypes" for these macros are:  
  *  
  * EXTERN int           TclGetInt1AtPtr  _ANSI_ARGS_((unsigned char *p));  
  * EXTERN int           TclGetInt4AtPtr  _ANSI_ARGS_((unsigned char *p));  
  * EXTERN unsigned int  TclGetUInt1AtPtr _ANSI_ARGS_((unsigned char *p));  
  * EXTERN unsigned int  TclGetUInt4AtPtr _ANSI_ARGS_((unsigned char *p));  
  */  
   
 /*  
  * The TclGetInt1AtPtr macro is tricky because we want to do sign  
  * extension on the 1-byte value. Unfortunately the "char" type isn't  
  * signed on all platforms so sign-extension doesn't always happen  
  * automatically. Sometimes we can explicitly declare the pointer to be  
  * signed, but other times we have to explicitly sign-extend the value  
  * in software.  
  */  
   
 #ifndef __CHAR_UNSIGNED__  
 #   define TclGetInt1AtPtr(p) ((int) *((char *) p))  
 #else  
 #   ifdef HAVE_SIGNED_CHAR  
 #       define TclGetInt1AtPtr(p) ((int) *((signed char *) p))  
 #    else  
 #       define TclGetInt1AtPtr(p) (((int) *((char *) p)) \  
                 | ((*(p) & 0200) ? (-256) : 0))  
 #    endif  
 #endif  
   
 #define TclGetInt4AtPtr(p) (((int) TclGetInt1AtPtr(p) << 24) | \  
                                             (*((p)+1) << 16) | \  
                                             (*((p)+2) <<  8) | \  
                                             (*((p)+3)))  
   
 #define TclGetUInt1AtPtr(p) ((unsigned int) *(p))  
 #define TclGetUInt4AtPtr(p) ((unsigned int) (*(p)     << 24) | \  
                                             (*((p)+1) << 16) | \  
                                             (*((p)+2) <<  8) | \  
                                             (*((p)+3)))  
   
 /*  
  * Macros used to compute the minimum and maximum of two integers.  
  * The ANSI C "prototypes" for these macros are:  
  *  
  * EXTERN int  TclMin _ANSI_ARGS_((int i, int j));  
  * EXTERN int  TclMax _ANSI_ARGS_((int i, int j));  
  */  
   
 #define TclMin(i, j)   ((((int) i) < ((int) j))? (i) : (j))  
 #define TclMax(i, j)   ((((int) i) > ((int) j))? (i) : (j))  
   
 # undef TCL_STORAGE_CLASS  
 # define TCL_STORAGE_CLASS DLLIMPORT  
   
 #endif /* _TCLCOMPILATION */  
   
   
 /* $History: tclcompile.h $  
  *  
  * *****************  Version 1  *****************  
  * User: Dtashley     Date: 1/02/01    Time: 1:27a  
  * Created in $/IjuScripter, IjuConsole/Source/Tcl Base  
  * Initial check-in.  
  */  
   
 /* End of TCLCOMPILE.H */  
1    /* $Header$ */
2    /*
3     * tclCompile.h --
4     *
5     * Copyright (c) 1996-1998 Sun Microsystems, Inc.
6     *
7     * See the file "license.terms" for information on usage and redistribution
8     * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
9     *
10     * RCS: @(#) $Id: tclcompile.h,v 1.1.1.1 2001/06/13 04:36:28 dtashley Exp $
11     */
12    
13    #ifndef _TCLCOMPILATION
14    #define _TCLCOMPILATION 1
15    
16    #ifndef _TCLINT
17    #include "tclInt.h"
18    #endif /* _TCLINT */
19    
20    #ifdef BUILD_tcl
21    # undef TCL_STORAGE_CLASS
22    # define TCL_STORAGE_CLASS DLLEXPORT
23    #endif
24    
25    /*
26     *------------------------------------------------------------------------
27     * Variables related to compilation. These are used in tclCompile.c,
28     * tclExecute.c, tclBasic.c, and their clients.
29     *------------------------------------------------------------------------
30     */
31    
32    /*
33     * Variable that denotes the command name Tcl object type. Objects of this
34     * type cache the Command pointer that results from looking up command names
35     * in the command hashtable.
36     */
37    
38    extern Tcl_ObjType      tclCmdNameType;
39    
40    /*
41     * Variable that controls whether compilation tracing is enabled and, if so,
42     * what level of tracing is desired:
43     *    0: no compilation tracing
44     *    1: summarize compilation of top level cmds and proc bodies
45     *    2: display all instructions of each ByteCode compiled
46     * This variable is linked to the Tcl variable "tcl_traceCompile".
47     */
48    
49    extern int              tclTraceCompile;
50    
51    /*
52     * Variable that controls whether execution tracing is enabled and, if so,
53     * what level of tracing is desired:
54     *    0: no execution tracing
55     *    1: trace invocations of Tcl procs only
56     *    2: trace invocations of all (not compiled away) commands
57     *    3: display each instruction executed
58     * This variable is linked to the Tcl variable "tcl_traceExec".
59     */
60    
61    extern int              tclTraceExec;
62    
63    /*
64     *------------------------------------------------------------------------
65     * Data structures related to compilation.
66     *------------------------------------------------------------------------
67     */
68    
69    /*
70     * The structure used to implement Tcl "exceptions" (exceptional returns):
71     * for example, those generated in loops by the break and continue commands,
72     * and those generated by scripts and caught by the catch command. This
73     * ExceptionRange structure describes a range of code (e.g., a loop body),
74     * the kind of exceptions (e.g., a break or continue) that might occur, and
75     * the PC offsets to jump to if a matching exception does occur. Exception
76     * ranges can nest so this structure includes a nesting level that is used
77     * at runtime to find the closest exception range surrounding a PC. For
78     * example, when a break command is executed, the ExceptionRange structure
79     * for the most deeply nested loop, if any, is found and used. These
80     * structures are also generated for the "next" subcommands of for loops
81     * since a break there terminates the for command. This means a for command
82     * actually generates two LoopInfo structures.
83     */
84    
85    typedef enum {
86        LOOP_EXCEPTION_RANGE,       /* Exception's range is part of a loop.
87                                     * Break and continue "exceptions" cause
88                                     * jumps to appropriate PC offsets. */
89        CATCH_EXCEPTION_RANGE       /* Exception's range is controlled by a
90                                     * catch command. Errors in the range cause
91                                     * a jump to a catch PC offset. */
92    } ExceptionRangeType;
93    
94    typedef struct ExceptionRange {
95        ExceptionRangeType type;    /* The kind of ExceptionRange. */
96        int nestingLevel;           /* Static depth of the exception range.
97                                     * Used to find the most deeply-nested
98                                     * range surrounding a PC at runtime. */
99        int codeOffset;             /* Offset of the first instruction byte of
100                                     * the code range. */
101        int numCodeBytes;           /* Number of bytes in the code range. */
102        int breakOffset;            /* If LOOP_EXCEPTION_RANGE, the target PC
103                                     * offset for a break command in the range. */
104        int continueOffset;         /* If LOOP_EXCEPTION_RANGE and not -1, the
105                                     * target PC offset for a continue command in
106                                     * the code range. Otherwise, ignore this range
107                                     * when processing a continue command. */
108        int catchOffset;            /* If a CATCH_EXCEPTION_RANGE, the target PC
109                                     * offset for any "exception" in range. */
110    } ExceptionRange;
111    
112    /*
113     * Structure used to map between instruction pc and source locations. It
114     * defines for each compiled Tcl command its code's starting offset and
115     * its source's starting offset and length. Note that the code offset
116     * increases monotonically: that is, the table is sorted in code offset
117     * order. The source offset is not monotonic.
118     */
119    
120    typedef struct CmdLocation {
121        int codeOffset;             /* Offset of first byte of command code. */
122        int numCodeBytes;           /* Number of bytes for command's code. */
123        int srcOffset;              /* Offset of first char of the command. */
124        int numSrcBytes;            /* Number of command source chars. */
125    } CmdLocation;
126    
127    /*
128     * CompileProcs need the ability to record information during compilation
129     * that can be used by bytecode instructions during execution. The AuxData
130     * structure provides this "auxiliary data" mechanism. An arbitrary number
131     * of these structures can be stored in the ByteCode record (during
132     * compilation they are stored in a CompileEnv structure). Each AuxData
133     * record holds one word of client-specified data (often a pointer) and is
134     * given an index that instructions can later use to look up the structure
135     * and its data.
136     *
137     * The following definitions declare the types of procedures that are called
138     * to duplicate or free this auxiliary data when the containing ByteCode
139     * objects are duplicated and freed. Pointers to these procedures are kept
140     * in the AuxData structure.
141     */
142    
143    typedef ClientData (AuxDataDupProc)  _ANSI_ARGS_((ClientData clientData));
144    typedef void       (AuxDataFreeProc) _ANSI_ARGS_((ClientData clientData));
145    
146    /*
147     * We define a separate AuxDataType struct to hold type-related information
148     * for the AuxData structure. This separation makes it possible for clients
149     * outside of the TCL core to manipulate (in a limited fashion!) AuxData;
150     * for example, it makes it possible to pickle and unpickle AuxData structs.
151     */
152    
153    typedef struct AuxDataType {
154        char *name;                                 /* the name of the type. Types can be
155                                     * registered and found by name */
156        AuxDataDupProc *dupProc;    /* Callback procedure to invoke when the
157                                     * aux data is duplicated (e.g., when the
158                                     * ByteCode structure containing the aux
159                                     * data is duplicated). NULL means just
160                                     * copy the source clientData bits; no
161                                     * proc need be called. */
162        AuxDataFreeProc *freeProc;  /* Callback procedure to invoke when the
163                                     * aux data is freed. NULL means no
164                                     * proc need be called. */
165    } AuxDataType;
166    
167    /*
168     * The definition of the AuxData structure that holds information created
169     * during compilation by CompileProcs and used by instructions during
170     * execution.
171     */
172    
173    typedef struct AuxData {
174        AuxDataType *type;          /* pointer to the AuxData type associated with
175                                 * this ClientData. */
176        ClientData clientData;      /* The compilation data itself. */
177    } AuxData;
178    
179    /*
180     * Structure defining the compilation environment. After compilation, fields
181     * describing bytecode instructions are copied out into the more compact
182     * ByteCode structure defined below.
183     */
184    
185    #define COMPILEENV_INIT_CODE_BYTES    250
186    #define COMPILEENV_INIT_NUM_OBJECTS    60
187    #define COMPILEENV_INIT_EXCEPT_RANGES   5
188    #define COMPILEENV_INIT_CMD_MAP_SIZE   40
189    #define COMPILEENV_INIT_AUX_DATA_SIZE   5
190    
191    typedef struct CompileEnv {
192        Interp *iPtr;               /* Interpreter containing the code being
193                                     * compiled. Commands and their compile
194                                     * procs are specific to an interpreter so
195                                     * the code emitted will depend on the
196                                     * interpreter. */
197        char *source;               /* The source string being compiled by
198                                     * SetByteCodeFromAny. This pointer is not
199                                     * owned by the CompileEnv and must not be
200                                     * freed or changed by it. */
201        int numSrcBytes;            /* Number of bytes in source. */
202        Proc *procPtr;              /* If a procedure is being compiled, a
203                                     * pointer to its Proc structure; otherwise
204                                     * NULL. Used to compile local variables.
205                                     * Set from information provided by
206                                     * ObjInterpProc in tclProc.c. */
207        int numCommands;            /* Number of commands compiled. */
208        int exceptDepth;            /* Current exception range nesting level;
209                                     * -1 if not in any range currently. */
210        int maxExceptDepth;         /* Max nesting level of exception ranges;
211                                     * -1 if no ranges have been compiled. */
212        int maxStackDepth;          /* Maximum number of stack elements needed
213                                     * to execute the code. Set by compilation
214                                     * procedures before returning. */
215        LiteralTable localLitTable; /* Contains LiteralEntry's describing
216                                     * all Tcl objects referenced by this
217                                     * compiled code. Indexed by the string
218                                     * representations of the literals. Used to
219                                     * avoid creating duplicate objects. */
220        int exprIsJustVarRef;       /* Set 1 if the expression last compiled by
221                                     * TclCompileExpr consisted of just a
222                                     * variable reference as in the expression
223                                     * of "if $b then...". Otherwise 0. Used
224                                     * to implement expr's 2 level substitution
225                                     * semantics properly. */
226        int exprIsComparison;       /* Set 1 if the top-level operator in the
227                                     * expression last compiled is a comparison.
228                                     * Otherwise 0. If 1, since the operands
229                                     * might be strings, the expr is compiled
230                                     * out-of-line to implement expr's 2 level
231                                     * substitution semantics properly. */
232        unsigned char *codeStart;   /* Points to the first byte of the code. */
233        unsigned char *codeNext;    /* Points to next code array byte to use. */
234        unsigned char *codeEnd;     /* Points just after the last allocated
235                                     * code array byte. */
236        int mallocedCodeArray;      /* Set 1 if code array was expanded
237                                     * and codeStart points into the heap.*/
238        LiteralEntry *literalArrayPtr;
239                                    /* Points to start of LiteralEntry array. */
240        int literalArrayNext;       /* Index of next free object array entry. */
241        int literalArrayEnd;        /* Index just after last obj array entry. */
242        int mallocedLiteralArray;   /* 1 if object array was expanded and
243                                     * objArray points into the heap, else 0. */
244        ExceptionRange *exceptArrayPtr;
245                                    /* Points to start of the ExceptionRange
246                                     * array. */
247        int exceptArrayNext;        /* Next free ExceptionRange array index.
248                                     * exceptArrayNext is the number of ranges
249                                     * and (exceptArrayNext-1) is the index of
250                                     * the current range's array entry. */
251        int exceptArrayEnd;         /* Index after the last ExceptionRange
252                                     * array entry. */
253        int mallocedExceptArray;    /* 1 if ExceptionRange array was expanded
254                                     * and exceptArrayPtr points in heap,
255                                     * else 0. */
256        CmdLocation *cmdMapPtr;     /* Points to start of CmdLocation array.
257                                     * numCommands is the index of the next
258                                     * entry to use; (numCommands-1) is the
259                                     * entry index for the last command. */
260        int cmdMapEnd;              /* Index after last CmdLocation entry. */
261        int mallocedCmdMap;         /* 1 if command map array was expanded and
262                                     * cmdMapPtr points in the heap, else 0. */
263        AuxData *auxDataArrayPtr;   /* Points to auxiliary data array start. */
264        int auxDataArrayNext;       /* Next free compile aux data array index.
265                                     * auxDataArrayNext is the number of aux
266                                     * data items and (auxDataArrayNext-1) is
267                                     * index of current aux data array entry. */
268        int auxDataArrayEnd;        /* Index after last aux data array entry. */
269        int mallocedAuxDataArray;   /* 1 if aux data array was expanded and
270                                     * auxDataArrayPtr points in heap else 0. */
271        unsigned char staticCodeSpace[COMPILEENV_INIT_CODE_BYTES];
272                                    /* Initial storage for code. */
273        LiteralEntry staticLiteralSpace[COMPILEENV_INIT_NUM_OBJECTS];
274                                    /* Initial storage of LiteralEntry array. */
275        ExceptionRange staticExceptArraySpace[COMPILEENV_INIT_EXCEPT_RANGES];
276                                    /* Initial ExceptionRange array storage. */
277        CmdLocation staticCmdMapSpace[COMPILEENV_INIT_CMD_MAP_SIZE];
278                                    /* Initial storage for cmd location map. */
279        AuxData staticAuxDataArraySpace[COMPILEENV_INIT_AUX_DATA_SIZE];
280                                    /* Initial storage for aux data array. */
281    } CompileEnv;
282    
283    /*
284     * The structure defining the bytecode instructions resulting from compiling
285     * a Tcl script. Note that this structure is variable length: a single heap
286     * object is allocated to hold the ByteCode structure immediately followed
287     * by the code bytes, the literal object array, the ExceptionRange array,
288     * the CmdLocation map, and the compilation AuxData array.
289     */
290    
291    /*
292     * A PRECOMPILED bytecode struct is one that was generated from a compiled
293     * image rather than implicitly compiled from source
294     */
295    #define TCL_BYTECODE_PRECOMPILED                0x0001
296    
297    typedef struct ByteCode {
298        TclHandle interpHandle;     /* Handle for interpreter containing the
299                                     * compiled code.  Commands and their compile
300                                     * procs are specific to an interpreter so the
301                                     * code emitted will depend on the
302                                     * interpreter. */
303        int compileEpoch;           /* Value of iPtr->compileEpoch when this
304                                     * ByteCode was compiled. Used to invalidate
305                                     * code when, e.g., commands with compile
306                                     * procs are redefined. */
307        Namespace *nsPtr;           /* Namespace context in which this code
308                                     * was compiled. If the code is executed
309                                     * if a different namespace, it must be
310                                     * recompiled. */
311        int nsEpoch;                /* Value of nsPtr->resolverEpoch when this
312                                     * ByteCode was compiled. Used to invalidate
313                                     * code when new namespace resolution rules
314                                     * are put into effect. */
315        int refCount;               /* Reference count: set 1 when created
316                                     * plus 1 for each execution of the code
317                                     * currently active. This structure can be
318                                     * freed when refCount becomes zero. */
319        unsigned int flags;         /* flags describing state for the codebyte.
320                                     * this variable holds ORed values from the
321                                     * TCL_BYTECODE_ masks defined above */
322        char *source;               /* The source string from which this
323                                     * ByteCode was compiled. Note that this
324                                     * pointer is not owned by the ByteCode and
325                                     * must not be freed or modified by it. */
326        Proc *procPtr;              /* If the ByteCode was compiled from a
327                                     * procedure body, this is a pointer to its
328                                     * Proc structure; otherwise NULL. This
329                                     * pointer is also not owned by the ByteCode
330                                     * and must not be freed by it. */
331        size_t structureSize;       /* Number of bytes in the ByteCode structure
332                                     * itself. Does not include heap space for
333                                     * literal Tcl objects or storage referenced
334                                     * by AuxData entries. */
335        int numCommands;            /* Number of commands compiled. */
336        int numSrcBytes;            /* Number of source bytes compiled. */
337        int numCodeBytes;           /* Number of code bytes. */
338        int numLitObjects;          /* Number of objects in literal array. */
339        int numExceptRanges;        /* Number of ExceptionRange array elems. */
340        int numAuxDataItems;        /* Number of AuxData items. */
341        int numCmdLocBytes;         /* Number of bytes needed for encoded
342                                     * command location information. */
343        int maxExceptDepth;         /* Maximum nesting level of ExceptionRanges;
344                                     * -1 if no ranges were compiled. */
345        int maxStackDepth;          /* Maximum number of stack elements needed
346                                     * to execute the code. */
347        unsigned char *codeStart;   /* Points to the first byte of the code.
348                                     * This is just after the final ByteCode
349                                     * member cmdMapPtr. */
350        Tcl_Obj **objArrayPtr;      /* Points to the start of the literal
351                                     * object array. This is just after the
352                                     * last code byte. */
353        ExceptionRange *exceptArrayPtr;
354                                    /* Points to the start of the ExceptionRange
355                                     * array. This is just after the last
356                                     * object in the object array. */
357        AuxData *auxDataArrayPtr;   /* Points to the start of the auxiliary data
358                                     * array. This is just after the last entry
359                                     * in the ExceptionRange array. */
360        unsigned char *codeDeltaStart;
361                                    /* Points to the first of a sequence of
362                                     * bytes that encode the change in the
363                                     * starting offset of each command's code.
364                                     * If -127<=delta<=127, it is encoded as 1
365                                     * byte, otherwise 0xFF (128) appears and
366                                     * the delta is encoded by the next 4 bytes.
367                                     * Code deltas are always positive. This
368                                     * sequence is just after the last entry in
369                                     * the AuxData array. */
370        unsigned char *codeLengthStart;
371                                    /* Points to the first of a sequence of
372                                     * bytes that encode the length of each
373                                     * command's code. The encoding is the same
374                                     * as for code deltas. Code lengths are
375                                     * always positive. This sequence is just
376                                     * after the last entry in the code delta
377                                     * sequence. */
378        unsigned char *srcDeltaStart;
379                                    /* Points to the first of a sequence of
380                                     * bytes that encode the change in the
381                                     * starting offset of each command's source.
382                                     * The encoding is the same as for code
383                                     * deltas. Source deltas can be negative.
384                                     * This sequence is just after the last byte
385                                     * in the code length sequence. */
386        unsigned char *srcLengthStart;
387                                    /* Points to the first of a sequence of
388                                     * bytes that encode the length of each
389                                     * command's source. The encoding is the
390                                     * same as for code deltas. Source lengths
391                                     * are always positive. This sequence is
392                                     * just after the last byte in the source
393                                     * delta sequence. */
394    #ifdef TCL_COMPILE_STATS
395        Tcl_Time createTime;        /* Absolute time when the ByteCode was
396                                     * created. */
397    #endif /* TCL_COMPILE_STATS */
398    } ByteCode;
399    
400    /*
401     * Opcodes for the Tcl bytecode instructions. These must correspond to the
402     * entries in the table of instruction descriptions, instructionTable, in
403     * tclCompile.c. Also, the order and number of the expression opcodes
404     * (e.g., INST_LOR) must match the entries in the array operatorStrings in
405     * tclExecute.c.
406     */
407    
408    /* Opcodes 0 to 9 */
409    #define INST_DONE                       0
410    #define INST_PUSH1                      1
411    #define INST_PUSH4                      2
412    #define INST_POP                        3
413    #define INST_DUP                        4
414    #define INST_CONCAT1                    5
415    #define INST_INVOKE_STK1                6
416    #define INST_INVOKE_STK4                7
417    #define INST_EVAL_STK                   8
418    #define INST_EXPR_STK                   9
419    
420    /* Opcodes 10 to 23 */
421    #define INST_LOAD_SCALAR1               10
422    #define INST_LOAD_SCALAR4               11
423    #define INST_LOAD_SCALAR_STK            12
424    #define INST_LOAD_ARRAY1                13
425    #define INST_LOAD_ARRAY4                14
426    #define INST_LOAD_ARRAY_STK             15
427    #define INST_LOAD_STK                   16
428    #define INST_STORE_SCALAR1              17
429    #define INST_STORE_SCALAR4              18
430    #define INST_STORE_SCALAR_STK           19
431    #define INST_STORE_ARRAY1               20
432    #define INST_STORE_ARRAY4               21
433    #define INST_STORE_ARRAY_STK            22
434    #define INST_STORE_STK                  23
435    
436    /* Opcodes 24 to 33 */
437    #define INST_INCR_SCALAR1               24
438    #define INST_INCR_SCALAR_STK            25
439    #define INST_INCR_ARRAY1                26
440    #define INST_INCR_ARRAY_STK             27
441    #define INST_INCR_STK                   28
442    #define INST_INCR_SCALAR1_IMM           29
443    #define INST_INCR_SCALAR_STK_IMM        30
444    #define INST_INCR_ARRAY1_IMM            31
445    #define INST_INCR_ARRAY_STK_IMM         32
446    #define INST_INCR_STK_IMM               33
447    
448    /* Opcodes 34 to 39 */
449    #define INST_JUMP1                      34
450    #define INST_JUMP4                      35
451    #define INST_JUMP_TRUE1                 36
452    #define INST_JUMP_TRUE4                 37
453    #define INST_JUMP_FALSE1                38
454    #define INST_JUMP_FALSE4                39
455    
456    /* Opcodes 40 to 64 */
457    #define INST_LOR                        40
458    #define INST_LAND                       41
459    #define INST_BITOR                      42
460    #define INST_BITXOR                     43
461    #define INST_BITAND                     44
462    #define INST_EQ                         45
463    #define INST_NEQ                        46
464    #define INST_LT                         47
465    #define INST_GT                         48
466    #define INST_LE                         49
467    #define INST_GE                         50
468    #define INST_LSHIFT                     51
469    #define INST_RSHIFT                     52
470    #define INST_ADD                        53
471    #define INST_SUB                        54
472    #define INST_MULT                       55
473    #define INST_DIV                        56
474    #define INST_MOD                        57
475    #define INST_UPLUS                      58
476    #define INST_UMINUS                     59
477    #define INST_BITNOT                     60
478    #define INST_LNOT                       61
479    #define INST_CALL_BUILTIN_FUNC1         62
480    #define INST_CALL_FUNC1                 63
481    #define INST_TRY_CVT_TO_NUMERIC         64
482    
483    /* Opcodes 65 to 66 */
484    #define INST_BREAK                      65
485    #define INST_CONTINUE                   66
486    
487    /* Opcodes 67 to 68 */
488    #define INST_FOREACH_START4             67
489    #define INST_FOREACH_STEP4              68
490    
491    /* Opcodes 69 to 72 */
492    #define INST_BEGIN_CATCH4               69
493    #define INST_END_CATCH                  70
494    #define INST_PUSH_RESULT                71
495    #define INST_PUSH_RETURN_CODE           72
496    
497    /* The last opcode */
498    #define LAST_INST_OPCODE                72
499    
500    /*
501     * Table describing the Tcl bytecode instructions: their name (for
502     * displaying code), total number of code bytes required (including
503     * operand bytes), and a description of the type of each operand.
504     * These operand types include signed and unsigned integers of length
505     * one and four bytes. The unsigned integers are used for indexes or
506     * for, e.g., the count of objects to push in a "push" instruction.
507     */
508    
509    #define MAX_INSTRUCTION_OPERANDS 2
510    
511    typedef enum InstOperandType {
512        OPERAND_NONE,
513        OPERAND_INT1,               /* One byte signed integer. */
514        OPERAND_INT4,               /* Four byte signed integer. */
515        OPERAND_UINT1,              /* One byte unsigned integer. */
516        OPERAND_UINT4               /* Four byte unsigned integer. */
517    } InstOperandType;
518    
519    typedef struct InstructionDesc {
520        char *name;                 /* Name of instruction. */
521        int numBytes;               /* Total number of bytes for instruction. */
522        int numOperands;            /* Number of operands. */
523        InstOperandType opTypes[MAX_INSTRUCTION_OPERANDS];
524                                    /* The type of each operand. */
525    } InstructionDesc;
526    
527    extern InstructionDesc instructionTable[];
528    
529    /*
530     * Definitions of the values of the INST_CALL_BUILTIN_FUNC instruction's
531     * operand byte. Each value denotes a builtin Tcl math function. These
532     * values must correspond to the entries in the builtinFuncTable array
533     * below and to the values stored in the tclInt.h MathFunc structure's
534     * builtinFuncIndex field.
535     */
536    
537    #define BUILTIN_FUNC_ACOS               0
538    #define BUILTIN_FUNC_ASIN               1
539    #define BUILTIN_FUNC_ATAN               2
540    #define BUILTIN_FUNC_ATAN2              3
541    #define BUILTIN_FUNC_CEIL               4
542    #define BUILTIN_FUNC_COS                5
543    #define BUILTIN_FUNC_COSH               6
544    #define BUILTIN_FUNC_EXP                7
545    #define BUILTIN_FUNC_FLOOR              8
546    #define BUILTIN_FUNC_FMOD               9
547    #define BUILTIN_FUNC_HYPOT              10
548    #define BUILTIN_FUNC_LOG                11
549    #define BUILTIN_FUNC_LOG10              12
550    #define BUILTIN_FUNC_POW                13
551    #define BUILTIN_FUNC_SIN                14
552    #define BUILTIN_FUNC_SINH               15
553    #define BUILTIN_FUNC_SQRT               16
554    #define BUILTIN_FUNC_TAN                17
555    #define BUILTIN_FUNC_TANH               18
556    #define BUILTIN_FUNC_ABS                19
557    #define BUILTIN_FUNC_DOUBLE             20
558    #define BUILTIN_FUNC_INT                21
559    #define BUILTIN_FUNC_RAND               22
560    #define BUILTIN_FUNC_ROUND              23
561    #define BUILTIN_FUNC_SRAND              24
562    
563    #define LAST_BUILTIN_FUNC               24
564    
565    /*
566     * Table describing the built-in math functions. Entries in this table are
567     * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
568     * operand byte.
569     */
570    
571    typedef int (CallBuiltinFuncProc) _ANSI_ARGS_((Tcl_Interp *interp,
572            ExecEnv *eePtr, ClientData clientData));
573    
574    typedef struct {
575        char *name;                 /* Name of function. */
576        int numArgs;                /* Number of arguments for function. */
577        Tcl_ValueType argTypes[MAX_MATH_ARGS];
578                                    /* Acceptable types for each argument. */
579        CallBuiltinFuncProc *proc;  /* Procedure implementing this function. */
580        ClientData clientData;      /* Additional argument to pass to the
581                                     * function when invoking it. */
582    } BuiltinFunc;
583    
584    extern BuiltinFunc builtinFuncTable[];
585    
586    /*
587     * Compilation of some Tcl constructs such as if commands and the logical or
588     * (||) and logical and (&&) operators in expressions requires the
589     * generation of forward jumps. Since the PC target of these jumps isn't
590     * known when the jumps are emitted, we record the offset of each jump in an
591     * array of JumpFixup structures. There is one array for each sequence of
592     * jumps to one target PC. When we learn the target PC, we update the jumps
593     * with the correct distance. Also, if the distance is too great (> 127
594     * bytes), we replace the single-byte jump with a four byte jump
595     * instruction, move the instructions after the jump down, and update the
596     * code offsets for any commands between the jump and the target.
597     */
598    
599    typedef enum {
600        TCL_UNCONDITIONAL_JUMP,
601        TCL_TRUE_JUMP,
602        TCL_FALSE_JUMP
603    } TclJumpType;
604    
605    typedef struct JumpFixup {
606        TclJumpType jumpType;       /* Indicates the kind of jump. */
607        int codeOffset;             /* Offset of the first byte of the one-byte
608                                     * forward jump's code. */
609        int cmdIndex;               /* Index of the first command after the one
610                                     * for which the jump was emitted. Used to
611                                     * update the code offsets for subsequent
612                                     * commands if the two-byte jump at jumpPc
613                                     * must be replaced with a five-byte one. */
614        int exceptIndex;            /* Index of the first range entry in the
615                                     * ExceptionRange array after the current
616                                     * one. This field is used to adjust the
617                                     * code offsets in subsequent ExceptionRange
618                                     * records when a jump is grown from 2 bytes
619                                     * to 5 bytes. */
620    } JumpFixup;
621    
622    #define JUMPFIXUP_INIT_ENTRIES    10
623    
624    typedef struct JumpFixupArray {
625        JumpFixup *fixup;           /* Points to start of jump fixup array. */
626        int next;                   /* Index of next free array entry. */
627        int end;                    /* Index of last usable entry in array. */
628        int mallocedArray;          /* 1 if array was expanded and fixups points
629                                     * into the heap, else 0. */
630        JumpFixup staticFixupSpace[JUMPFIXUP_INIT_ENTRIES];
631                                    /* Initial storage for jump fixup array. */
632    } JumpFixupArray;
633    
634    /*
635     * The structure describing one variable list of a foreach command. Note
636     * that only foreach commands inside procedure bodies are compiled inline so
637     * a ForeachVarList structure always describes local variables. Furthermore,
638     * only scalar variables are supported for inline-compiled foreach loops.
639     */
640    
641    typedef struct ForeachVarList {
642        int numVars;                /* The number of variables in the list. */
643        int varIndexes[1];          /* An array of the indexes ("slot numbers")
644                                     * for each variable in the procedure's
645                                     * array of local variables. Only scalar
646                                     * variables are supported. The actual
647                                     * size of this field will be large enough
648                                     * to numVars indexes. THIS MUST BE THE
649                                     * LAST FIELD IN THE STRUCTURE! */
650    } ForeachVarList;
651    
652    /*
653     * Structure used to hold information about a foreach command that is needed
654     * during program execution. These structures are stored in CompileEnv and
655     * ByteCode structures as auxiliary data.
656     */
657    
658    typedef struct ForeachInfo {
659        int numLists;               /* The number of both the variable and value
660                                     * lists of the foreach command. */
661        int firstValueTemp;         /* Index of the first temp var in a proc
662                                     * frame used to point to a value list. */
663        int loopCtTemp;             /* Index of temp var in a proc frame
664                                     * holding the loop's iteration count. Used
665                                     * to determine next value list element to
666                                     * assign each loop var. */
667        ForeachVarList *varLists[1];/* An array of pointers to ForeachVarList
668                                     * structures describing each var list. The
669                                     * actual size of this field will be large
670                                     * enough to numVars indexes. THIS MUST BE
671                                     * THE LAST FIELD IN THE STRUCTURE! */
672    } ForeachInfo;
673    
674    extern AuxDataType              tclForeachInfoType;
675    
676    /*
677     * Structure containing a cached pointer to a command that is the result
678     * of resolving the command's name in some namespace. It is the internal
679     * representation for a cmdName object. It contains the pointer along
680     * with some information that is used to check the pointer's validity.
681     */
682    
683    typedef struct ResolvedCmdName {
684        Command *cmdPtr;            /* A cached Command pointer. */
685        Namespace *refNsPtr;        /* Points to the namespace containing the
686                                     * reference (not the namespace that
687                                     * contains the referenced command). */
688        long refNsId;               /* refNsPtr's unique namespace id. Used to
689                                     * verify that refNsPtr is still valid
690                                     * (e.g., it's possible that the cmd's
691                                     * containing namespace was deleted and a
692                                     * new one created at the same address). */
693        int refNsCmdEpoch;          /* Value of the referencing namespace's
694                                     * cmdRefEpoch when the pointer was cached.
695                                     * Before using the cached pointer, we check
696                                     * if the namespace's epoch was incremented;
697                                     * if so, this cached pointer is invalid. */
698        int cmdEpoch;               /* Value of the command's cmdEpoch when this
699                                     * pointer was cached. Before using the
700                                     * cached pointer, we check if the cmd's
701                                     * epoch was incremented; if so, the cmd was
702                                     * renamed, deleted, hidden, or exposed, and
703                                     * so the pointer is invalid. */
704        int refCount;               /* Reference count: 1 for each cmdName
705                                     * object that has a pointer to this
706                                     * ResolvedCmdName structure as its internal
707                                     * rep. This structure can be freed when
708                                     * refCount becomes zero. */
709    } ResolvedCmdName;
710    
711    /*
712     *----------------------------------------------------------------
713     * Procedures shared among Tcl bytecode compilation and execution
714     * modules but not used outside:
715     *----------------------------------------------------------------
716     */
717    
718    EXTERN void             TclCleanupByteCode _ANSI_ARGS_((ByteCode *codePtr));
719    EXTERN int              TclCompileCmdWord _ANSI_ARGS_((Tcl_Interp *interp,
720                                Tcl_Token *tokenPtr, int count,
721                                CompileEnv *envPtr));
722    EXTERN int              TclCompileExpr _ANSI_ARGS_((Tcl_Interp *interp,
723                                char *script, int numBytes,
724                                CompileEnv *envPtr));
725    EXTERN int              TclCompileExprWords _ANSI_ARGS_((Tcl_Interp *interp,
726                                Tcl_Token *tokenPtr, int numWords,
727                                CompileEnv *envPtr));
728    EXTERN int              TclCompileScript _ANSI_ARGS_((Tcl_Interp *interp,
729                                char *script, int numBytes, int nested,
730                                CompileEnv *envPtr));
731    EXTERN int              TclCompileTokens _ANSI_ARGS_((Tcl_Interp *interp,
732                                Tcl_Token *tokenPtr, int count,
733                                CompileEnv *envPtr));
734    EXTERN int              TclCreateAuxData _ANSI_ARGS_((ClientData clientData,
735                                AuxDataType *typePtr, CompileEnv *envPtr));
736    EXTERN int              TclCreateExceptRange _ANSI_ARGS_((
737                                ExceptionRangeType type, CompileEnv *envPtr));
738    EXTERN ExecEnv *        TclCreateExecEnv _ANSI_ARGS_((Tcl_Interp *interp));
739    EXTERN void             TclDeleteExecEnv _ANSI_ARGS_((ExecEnv *eePtr));
740    EXTERN void             TclDeleteLiteralTable _ANSI_ARGS_((
741                                Tcl_Interp *interp, LiteralTable *tablePtr));
742    EXTERN void             TclEmitForwardJump _ANSI_ARGS_((CompileEnv *envPtr,
743                                TclJumpType jumpType, JumpFixup *jumpFixupPtr));
744    EXTERN ExceptionRange * TclGetExceptionRangeForPc _ANSI_ARGS_((
745                                unsigned char *pc, int catchOnly,
746                                ByteCode* codePtr));
747    EXTERN InstructionDesc * TclGetInstructionTable _ANSI_ARGS_(());
748    EXTERN int              TclExecuteByteCode _ANSI_ARGS_((Tcl_Interp *interp,
749                                ByteCode *codePtr));
750    EXTERN void             TclExpandCodeArray _ANSI_ARGS_((
751                                CompileEnv *envPtr));
752    EXTERN void             TclExpandJumpFixupArray _ANSI_ARGS_((
753                                JumpFixupArray *fixupArrayPtr));
754    EXTERN void             TclFinalizeAuxDataTypeTable _ANSI_ARGS_((void));
755    EXTERN int              TclFindCompiledLocal _ANSI_ARGS_((char *name,
756                                int nameChars, int create, int flags,
757                                Proc *procPtr));
758    EXTERN LiteralEntry *   TclLookupLiteralEntry _ANSI_ARGS_((
759                                Tcl_Interp *interp, Tcl_Obj *objPtr));
760    EXTERN int              TclFixupForwardJump _ANSI_ARGS_((
761                                CompileEnv *envPtr, JumpFixup *jumpFixupPtr,
762                                int jumpDist, int distThreshold));
763    EXTERN void             TclFreeCompileEnv _ANSI_ARGS_((CompileEnv *envPtr));
764    EXTERN void             TclFreeJumpFixupArray _ANSI_ARGS_((
765                                JumpFixupArray *fixupArrayPtr));
766    EXTERN void             TclInitAuxDataTypeTable _ANSI_ARGS_((void));
767    EXTERN void             TclInitByteCodeObj _ANSI_ARGS_((Tcl_Obj *objPtr,
768                                CompileEnv *envPtr));
769    EXTERN void             TclInitCompilation _ANSI_ARGS_((void));
770    EXTERN void             TclInitCompileEnv _ANSI_ARGS_((Tcl_Interp *interp,
771                                CompileEnv *envPtr, char *string,
772                                int numBytes));
773    EXTERN void             TclInitJumpFixupArray _ANSI_ARGS_((
774                                JumpFixupArray *fixupArrayPtr));
775    EXTERN void             TclInitLiteralTable _ANSI_ARGS_((
776                                LiteralTable *tablePtr));
777    #ifdef TCL_COMPILE_STATS
778    EXTERN char *           TclLiteralStats _ANSI_ARGS_((
779                                LiteralTable *tablePtr));
780    EXTERN int              TclLog2 _ANSI_ARGS_((int value));
781    #endif
782    #ifdef TCL_COMPILE_DEBUG
783    EXTERN void             TclPrintByteCodeObj _ANSI_ARGS_((Tcl_Interp *interp,
784                                Tcl_Obj *objPtr));
785    #endif
786    EXTERN int              TclPrintInstruction _ANSI_ARGS_((ByteCode* codePtr,
787                                unsigned char *pc));
788    EXTERN void             TclPrintObject _ANSI_ARGS_((FILE *outFile,
789                                Tcl_Obj *objPtr, int maxChars));
790    EXTERN void             TclPrintSource _ANSI_ARGS_((FILE *outFile,
791                                char *string, int maxChars));
792    EXTERN void             TclRegisterAuxDataType _ANSI_ARGS_((AuxDataType *typePtr));
793    EXTERN int              TclRegisterLiteral _ANSI_ARGS_((CompileEnv *envPtr,
794                                char *bytes, int length, int onHeap));
795    EXTERN void             TclReleaseLiteral _ANSI_ARGS_((Tcl_Interp *interp,
796                                Tcl_Obj *objPtr));
797    EXTERN void             TclSetCmdNameObj _ANSI_ARGS_((Tcl_Interp *interp,
798                                Tcl_Obj *objPtr, Command *cmdPtr));
799    #ifdef TCL_COMPILE_DEBUG
800    EXTERN void             TclVerifyGlobalLiteralTable _ANSI_ARGS_((
801                                Interp *iPtr));
802    EXTERN void             TclVerifyLocalLiteralTable _ANSI_ARGS_((
803                                CompileEnv *envPtr));
804    #endif
805    
806    /*
807     *----------------------------------------------------------------
808     * Macros used by Tcl bytecode compilation and execution modules
809     * inside the Tcl core but not used outside.
810     *----------------------------------------------------------------
811     */
812    
813    /*
814     * Macro to emit an opcode byte into a CompileEnv's code array.
815     * The ANSI C "prototype" for this macro is:
816     *
817     * EXTERN void  TclEmitOpcode _ANSI_ARGS_((unsigned char op,
818     *                  CompileEnv *envPtr));
819     */
820    
821    #define TclEmitOpcode(op, envPtr) \
822        if ((envPtr)->codeNext == (envPtr)->codeEnd) \
823            TclExpandCodeArray(envPtr); \
824        *(envPtr)->codeNext++ = (unsigned char) (op)
825    
826    /*
827     * Macro to emit an integer operand.
828     * The ANSI C "prototype" for this macro is:
829     *
830     * EXTERN void  TclEmitInt1 _ANSI_ARGS_((int i, CompileEnv *envPtr));
831     */
832    
833    #define TclEmitInt1(i, envPtr) \
834        if ((envPtr)->codeNext == (envPtr)->codeEnd) \
835            TclExpandCodeArray(envPtr); \
836        *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i))
837    
838    /*
839     * Macros to emit an instruction with signed or unsigned integer operands.
840     * Four byte integers are stored in "big-endian" order with the high order
841     * byte stored at the lowest address.
842     * The ANSI C "prototypes" for these macros are:
843     *
844     * EXTERN void  TclEmitInstInt1 _ANSI_ARGS_((unsigned char op, int i,
845     *                  CompileEnv *envPtr));
846     * EXTERN void  TclEmitInstInt4 _ANSI_ARGS_((unsigned char op, int i,
847     *                  CompileEnv *envPtr));
848     */
849    
850    #define TclEmitInstInt1(op, i, envPtr) \
851        if (((envPtr)->codeNext + 2) > (envPtr)->codeEnd) { \
852            TclExpandCodeArray(envPtr); \
853        } \
854        *(envPtr)->codeNext++ = (unsigned char) (op); \
855        *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i))
856    
857    #define TclEmitInstInt4(op, i, envPtr) \
858        if (((envPtr)->codeNext + 5) > (envPtr)->codeEnd) { \
859            TclExpandCodeArray(envPtr); \
860        } \
861        *(envPtr)->codeNext++ = (unsigned char) (op); \
862        *(envPtr)->codeNext++ = \
863            (unsigned char) ((unsigned int) (i) >> 24); \
864        *(envPtr)->codeNext++ = \
865            (unsigned char) ((unsigned int) (i) >> 16); \
866        *(envPtr)->codeNext++ = \
867            (unsigned char) ((unsigned int) (i) >>  8); \
868        *(envPtr)->codeNext++ = \
869            (unsigned char) ((unsigned int) (i)      )
870        
871    /*
872     * Macro to push a Tcl object onto the Tcl evaluation stack. It emits the
873     * object's one or four byte array index into the CompileEnv's code
874     * array. These support, respectively, a maximum of 256 (2**8) and 2**32
875     * objects in a CompileEnv. The ANSI C "prototype" for this macro is:
876     *
877     * EXTERN void  TclEmitPush _ANSI_ARGS_((int objIndex, CompileEnv *envPtr));
878     */
879    
880    #define TclEmitPush(objIndex, envPtr) \
881        if ((objIndex) <= 255) { \
882            TclEmitInstInt1(INST_PUSH1, (objIndex), (envPtr)); \
883        } else { \
884            TclEmitInstInt4(INST_PUSH4, (objIndex), (envPtr)); \
885        }
886    
887    /*
888     * Macros to update a (signed or unsigned) integer starting at a pointer.
889     * The two variants depend on the number of bytes. The ANSI C "prototypes"
890     * for these macros are:
891     *
892     * EXTERN void  TclStoreInt1AtPtr _ANSI_ARGS_((int i, unsigned char *p));
893     * EXTERN void  TclStoreInt4AtPtr _ANSI_ARGS_((int i, unsigned char *p));
894     */
895        
896    #define TclStoreInt1AtPtr(i, p) \
897        *(p)   = (unsigned char) ((unsigned int) (i))
898        
899    #define TclStoreInt4AtPtr(i, p) \
900        *(p)   = (unsigned char) ((unsigned int) (i) >> 24); \
901        *(p+1) = (unsigned char) ((unsigned int) (i) >> 16); \
902        *(p+2) = (unsigned char) ((unsigned int) (i) >>  8); \
903        *(p+3) = (unsigned char) ((unsigned int) (i)      )
904    
905    /*
906     * Macros to update instructions at a particular pc with a new op code
907     * and a (signed or unsigned) int operand. The ANSI C "prototypes" for
908     * these macros are:
909     *
910     * EXTERN void  TclUpdateInstInt1AtPc _ANSI_ARGS_((unsigned char op, int i,
911     *                  unsigned char *pc));
912     * EXTERN void  TclUpdateInstInt4AtPc _ANSI_ARGS_((unsigned char op, int i,
913     *                  unsigned char *pc));
914     */
915    
916    #define TclUpdateInstInt1AtPc(op, i, pc) \
917        *(pc) = (unsigned char) (op); \
918        TclStoreInt1AtPtr((i), ((pc)+1))
919    
920    #define TclUpdateInstInt4AtPc(op, i, pc) \
921        *(pc) = (unsigned char) (op); \
922        TclStoreInt4AtPtr((i), ((pc)+1))
923        
924    /*
925     * Macros to get a signed integer (GET_INT{1,2}) or an unsigned int
926     * (GET_UINT{1,2}) from a pointer. There are two variants for each
927     * return type that depend on the number of bytes fetched.
928     * The ANSI C "prototypes" for these macros are:
929     *
930     * EXTERN int           TclGetInt1AtPtr  _ANSI_ARGS_((unsigned char *p));
931     * EXTERN int           TclGetInt4AtPtr  _ANSI_ARGS_((unsigned char *p));
932     * EXTERN unsigned int  TclGetUInt1AtPtr _ANSI_ARGS_((unsigned char *p));
933     * EXTERN unsigned int  TclGetUInt4AtPtr _ANSI_ARGS_((unsigned char *p));
934     */
935    
936    /*
937     * The TclGetInt1AtPtr macro is tricky because we want to do sign
938     * extension on the 1-byte value. Unfortunately the "char" type isn't
939     * signed on all platforms so sign-extension doesn't always happen
940     * automatically. Sometimes we can explicitly declare the pointer to be
941     * signed, but other times we have to explicitly sign-extend the value
942     * in software.
943     */
944    
945    #ifndef __CHAR_UNSIGNED__
946    #   define TclGetInt1AtPtr(p) ((int) *((char *) p))
947    #else
948    #   ifdef HAVE_SIGNED_CHAR
949    #       define TclGetInt1AtPtr(p) ((int) *((signed char *) p))
950    #    else
951    #       define TclGetInt1AtPtr(p) (((int) *((char *) p)) \
952                    | ((*(p) & 0200) ? (-256) : 0))
953    #    endif
954    #endif
955    
956    #define TclGetInt4AtPtr(p) (((int) TclGetInt1AtPtr(p) << 24) | \
957                                                (*((p)+1) << 16) | \
958                                                (*((p)+2) <<  8) | \
959                                                (*((p)+3)))
960    
961    #define TclGetUInt1AtPtr(p) ((unsigned int) *(p))
962    #define TclGetUInt4AtPtr(p) ((unsigned int) (*(p)     << 24) | \
963                                                (*((p)+1) << 16) | \
964                                                (*((p)+2) <<  8) | \
965                                                (*((p)+3)))
966    
967    /*
968     * Macros used to compute the minimum and maximum of two integers.
969     * The ANSI C "prototypes" for these macros are:
970     *
971     * EXTERN int  TclMin _ANSI_ARGS_((int i, int j));
972     * EXTERN int  TclMax _ANSI_ARGS_((int i, int j));
973     */
974    
975    #define TclMin(i, j)   ((((int) i) < ((int) j))? (i) : (j))
976    #define TclMax(i, j)   ((((int) i) > ((int) j))? (i) : (j))
977    
978    # undef TCL_STORAGE_CLASS
979    # define TCL_STORAGE_CLASS DLLIMPORT
980    
981    #endif /* _TCLCOMPILATION */
982    
983    /* End of tclcompile.h */

Legend:
Removed from v.29  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25