tclObj.c

Go to the documentation of this file.
00001 /*
00002  * tclObj.c --
00003  *
00004  *      This file contains Tcl object-related functions that are used by many
00005  *      Tcl commands.
00006  *
00007  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
00008  * Copyright (c) 1999 by Scriptics Corporation.
00009  * Copyright (c) 2001 by ActiveState Corporation.
00010  * Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
00011  * Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
00012  *
00013  * See the file "license.terms" for information on usage and redistribution of
00014  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
00015  *
00016  * RCS: @(#) $Id: tclObj.c,v 1.139 2007/12/13 15:23:19 dgp Exp $
00017  */
00018 
00019 #include "tclInt.h"
00020 #include "tommath.h"
00021 #include <float.h>
00022 
00023 /*
00024  * Table of all object types.
00025  */
00026 
00027 static Tcl_HashTable typeTable;
00028 static int typeTableInitialized = 0;    /* 0 means not yet initialized. */
00029 TCL_DECLARE_MUTEX(tableMutex)
00030 
00031 /*
00032  * Head of the list of free Tcl_Obj structs we maintain.
00033  */
00034 
00035 Tcl_Obj *tclFreeObjList = NULL;
00036 
00037 /*
00038  * The object allocator is single threaded. This mutex is referenced by the
00039  * TclNewObj macro, however, so must be visible.
00040  */
00041 
00042 #ifdef TCL_THREADS
00043 MODULE_SCOPE Tcl_Mutex tclObjMutex;
00044 Tcl_Mutex tclObjMutex;
00045 #endif
00046 
00047 /*
00048  * Pointer to a heap-allocated string of length zero that the Tcl core uses as
00049  * the value of an empty string representation for an object. This value is
00050  * shared by all new objects allocated by Tcl_NewObj.
00051  */
00052 
00053 char tclEmptyString = '\0';
00054 char *tclEmptyStringRep = &tclEmptyString;
00055 
00056 #if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
00057 /*
00058  * Thread local table that is used to check that a Tcl_Obj was not allocated
00059  * by some other thread.
00060  */
00061 typedef struct ThreadSpecificData {
00062     Tcl_HashTable *objThreadMap;
00063 } ThreadSpecificData;
00064 
00065 static Tcl_ThreadDataKey dataKey;
00066 #endif /* TCL_MEM_DEBUG && TCL_THREADS */
00067 
00068 /*
00069  * Nested Tcl_Obj deletion management support
00070  *
00071  * All context references used in the object freeing code are pointers to this
00072  * structure; every thread will have its own structure instance. The purpose
00073  * of this structure is to allow deeply nested collections of Tcl_Objs to be
00074  * freed without taking a vast depth of C stack (which could cause all sorts
00075  * of breakage.)
00076  */
00077 
00078 typedef struct PendingObjData {
00079     int deletionCount;          /* Count of the number of invokations of
00080                                  * TclFreeObj() are on the stack (at least
00081                                  * conceptually; many are actually expanded
00082                                  * macros). */
00083     Tcl_Obj *deletionStack;     /* Stack of objects that have had TclFreeObj()
00084                                  * invoked upon them but which can't be
00085                                  * deleted yet because they are in a nested
00086                                  * invokation of TclFreeObj(). By postponing
00087                                  * this way, we limit the maximum overall C
00088                                  * stack depth when deleting a complex object.
00089                                  * The down-side is that we alter the overall
00090                                  * behaviour by altering the order in which
00091                                  * objects are deleted, and we change the
00092                                  * order in which the string rep and the
00093                                  * internal rep of an object are deleted. Note
00094                                  * that code which assumes the previous
00095                                  * behaviour in either of these respects is
00096                                  * unsafe anyway; it was never documented as
00097                                  * to exactly what would happen in these
00098                                  * cases, and the overall contract of a
00099                                  * user-level Tcl_DecrRefCount() is still
00100                                  * preserved (assuming that a particular T_DRC
00101                                  * would delete an object is not very
00102                                  * safe). */
00103 } PendingObjData;
00104 
00105 /*
00106  * These are separated out so that some semantic content is attached
00107  * to them.
00108  */
00109 #define ObjDeletionLock(contextPtr)     ((contextPtr)->deletionCount++)
00110 #define ObjDeletionUnlock(contextPtr)   ((contextPtr)->deletionCount--)
00111 #define ObjDeletePending(contextPtr)    ((contextPtr)->deletionCount > 0)
00112 #define ObjOnStack(contextPtr)          ((contextPtr)->deletionStack != NULL)
00113 #define PushObjToDelete(contextPtr,objPtr) \
00114     /* The string rep is already invalidated so we can use the bytes value \
00115      * for our pointer chain: push onto the head of the stack. */ \
00116     (objPtr)->bytes = (char *) ((contextPtr)->deletionStack); \
00117     (contextPtr)->deletionStack = (objPtr)
00118 #define PopObjToDelete(contextPtr,objPtrVar) \
00119     (objPtrVar) = (contextPtr)->deletionStack; \
00120     (contextPtr)->deletionStack = (Tcl_Obj *) (objPtrVar)->bytes
00121 
00122 /*
00123  * Macro to set up the local reference to the deletion context.
00124  */
00125 #ifndef TCL_THREADS
00126 static PendingObjData pendingObjData;
00127 #define ObjInitDeletionContext(contextPtr) \
00128     PendingObjData *CONST contextPtr = &pendingObjData
00129 #else
00130 static Tcl_ThreadDataKey pendingObjDataKey;
00131 #define ObjInitDeletionContext(contextPtr) \
00132     PendingObjData *CONST contextPtr = (PendingObjData *) \
00133             Tcl_GetThreadData(&pendingObjDataKey, sizeof(PendingObjData))
00134 #endif
00135 
00136 /*
00137  * Macros to pack/unpack a bignum's fields in a Tcl_Obj internal rep
00138  */
00139 
00140 #define PACK_BIGNUM(bignum, objPtr) \
00141     if ((bignum).used > 0x7fff) { \
00142         mp_int *temp = (void *) ckalloc((unsigned) sizeof(mp_int)); \
00143         *temp = bignum; \
00144         (objPtr)->internalRep.ptrAndLongRep.ptr = (void*) temp; \
00145         (objPtr)->internalRep.ptrAndLongRep.value = (unsigned long)(-1); \
00146     } else { \
00147         if ((bignum).alloc > 0x7fff) { \
00148             mp_shrink(&(bignum)); \
00149         } \
00150         (objPtr)->internalRep.ptrAndLongRep.ptr = (void*) (bignum).dp; \
00151         (objPtr)->internalRep.ptrAndLongRep.value = ( ((bignum).sign << 30) \
00152                 | ((bignum).alloc << 15) | ((bignum).used)); \
00153     }
00154 
00155 #define UNPACK_BIGNUM(objPtr, bignum) \
00156     if ((objPtr)->internalRep.ptrAndLongRep.value == (unsigned long)(-1)) { \
00157         (bignum) = *((mp_int *) ((objPtr)->internalRep.ptrAndLongRep.ptr)); \
00158     } else { \
00159         (bignum).dp = (mp_digit*) (objPtr)->internalRep.ptrAndLongRep.ptr; \
00160         (bignum).sign = (objPtr)->internalRep.ptrAndLongRep.value >> 30; \
00161         (bignum).alloc = \
00162                 ((objPtr)->internalRep.ptrAndLongRep.value >> 15) & 0x7fff; \
00163         (bignum).used = (objPtr)->internalRep.ptrAndLongRep.value & 0x7fff; \
00164     }
00165 
00166 /*
00167  * Prototypes for functions defined later in this file:
00168  */
00169 
00170 static int              ParseBoolean(Tcl_Obj *objPtr);
00171 static int              SetBooleanFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
00172 static int              SetDoubleFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
00173 static int              SetIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
00174 static void             UpdateStringOfDouble(Tcl_Obj *objPtr);
00175 static void             UpdateStringOfInt(Tcl_Obj *objPtr);
00176 #ifndef NO_WIDE_TYPE
00177 static void             UpdateStringOfWideInt(Tcl_Obj *objPtr);
00178 static int              SetWideIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
00179 #endif
00180 static void             FreeBignum(Tcl_Obj *objPtr);
00181 static void             DupBignum(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
00182 static void             UpdateStringOfBignum(Tcl_Obj *objPtr);
00183 static int              GetBignumFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
00184                             int copy, mp_int *bignumValue);
00185 
00186 /*
00187  * Prototypes for the array hash key methods.
00188  */
00189 
00190 static Tcl_HashEntry *  AllocObjEntry(Tcl_HashTable *tablePtr, void *keyPtr);
00191 
00192 /*
00193  * Prototypes for the CommandName object type.
00194  */
00195 
00196 static void             DupCmdNameInternalRep(Tcl_Obj *objPtr,
00197                             Tcl_Obj *copyPtr);
00198 static void             FreeCmdNameInternalRep(Tcl_Obj *objPtr);
00199 static int              SetCmdNameFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
00200 
00201 /*
00202  * The structures below defines the Tcl object types defined in this file by
00203  * means of functions that can be invoked by generic object code. See also
00204  * tclStringObj.c, tclListObj.c, tclByteCode.c for other type manager
00205  * implementations.
00206  */
00207 
00208 static Tcl_ObjType oldBooleanType = {
00209     "boolean",                          /* name */
00210     NULL,                               /* freeIntRepProc */
00211     NULL,                               /* dupIntRepProc */
00212     NULL,                               /* updateStringProc */
00213     SetBooleanFromAny                   /* setFromAnyProc */
00214 };
00215 Tcl_ObjType tclBooleanType = {
00216     "booleanString",                    /* name */
00217     NULL,                               /* freeIntRepProc */
00218     NULL,                               /* dupIntRepProc */
00219     NULL,                               /* updateStringProc */
00220     SetBooleanFromAny                   /* setFromAnyProc */
00221 };
00222 Tcl_ObjType tclDoubleType = {
00223     "double",                           /* name */
00224     NULL,                               /* freeIntRepProc */
00225     NULL,                               /* dupIntRepProc */
00226     UpdateStringOfDouble,               /* updateStringProc */
00227     SetDoubleFromAny                    /* setFromAnyProc */
00228 };
00229 Tcl_ObjType tclIntType = {
00230     "int",                              /* name */
00231     NULL,                               /* freeIntRepProc */
00232     NULL,                               /* dupIntRepProc */
00233     UpdateStringOfInt,                  /* updateStringProc */
00234     SetIntFromAny                       /* setFromAnyProc */
00235 };
00236 #ifndef NO_WIDE_TYPE
00237 Tcl_ObjType tclWideIntType = {
00238     "wideInt",                          /* name */
00239     NULL,                               /* freeIntRepProc */
00240     NULL,                               /* dupIntRepProc */
00241     UpdateStringOfWideInt,              /* updateStringProc */
00242     SetWideIntFromAny                   /* setFromAnyProc */
00243 };
00244 #endif
00245 Tcl_ObjType tclBignumType = {
00246     "bignum",                           /* name */
00247     FreeBignum,                         /* freeIntRepProc */
00248     DupBignum,                          /* dupIntRepProc */
00249     UpdateStringOfBignum,               /* updateStringProc */
00250     NULL                                /* setFromAnyProc */
00251 };
00252 
00253 /*
00254  * The structure below defines the Tcl obj hash key type.
00255  */
00256 
00257 Tcl_HashKeyType tclObjHashKeyType = {
00258     TCL_HASH_KEY_TYPE_VERSION,  /* version */
00259     0,                          /* flags */
00260     TclHashObjKey,              /* hashKeyProc */
00261     TclCompareObjKeys,          /* compareKeysProc */
00262     AllocObjEntry,              /* allocEntryProc */
00263     TclFreeObjEntry             /* freeEntryProc */
00264 };
00265 
00266 /*
00267  * The structure below defines the command name Tcl object type by means of
00268  * functions that can be invoked by generic object code. Objects of this type
00269  * cache the Command pointer that results from looking up command names in the
00270  * command hashtable. Such objects appear as the zeroth ("command name")
00271  * argument in a Tcl command.
00272  *
00273  * NOTE: the ResolvedCmdName that gets cached is stored in the
00274  * twoPtrValue.ptr1 field, and the twoPtrValue.ptr2 field is unused. You might
00275  * think you could use the simpler otherValuePtr field to store the single
00276  * ResolvedCmdName pointer, but DO NOT DO THIS. It seems that some extensions
00277  * use the second internal pointer field of the twoPtrValue field for their
00278  * own purposes.
00279  */
00280 
00281 static Tcl_ObjType tclCmdNameType = {
00282     "cmdName",                          /* name */
00283     FreeCmdNameInternalRep,             /* freeIntRepProc */
00284     DupCmdNameInternalRep,              /* dupIntRepProc */
00285     NULL,                               /* updateStringProc */
00286     SetCmdNameFromAny                   /* setFromAnyProc */
00287 };
00288 
00289 /*
00290  * Structure containing a cached pointer to a command that is the result of
00291  * resolving the command's name in some namespace. It is the internal
00292  * representation for a cmdName object. It contains the pointer along with
00293  * some information that is used to check the pointer's validity.
00294  */
00295 
00296 typedef struct ResolvedCmdName {
00297     Command *cmdPtr;            /* A cached Command pointer. */
00298     Namespace *refNsPtr;        /* Points to the namespace containing the
00299                                  * reference (not the namespace that contains
00300                                  * the referenced command). NULL if the name
00301                                  * is fully qualified.*/
00302     long refNsId;               /* refNsPtr's unique namespace id. Used to
00303                                  * verify that refNsPtr is still valid (e.g.,
00304                                  * it's possible that the cmd's containing
00305                                  * namespace was deleted and a new one created
00306                                  * at the same address). */
00307     int refNsCmdEpoch;          /* Value of the referencing namespace's
00308                                  * cmdRefEpoch when the pointer was cached.
00309                                  * Before using the cached pointer, we check
00310                                  * if the namespace's epoch was incremented;
00311                                  * if so, this cached pointer is invalid. */
00312     int cmdEpoch;               /* Value of the command's cmdEpoch when this
00313                                  * pointer was cached. Before using the cached
00314                                  * pointer, we check if the cmd's epoch was
00315                                  * incremented; if so, the cmd was renamed,
00316                                  * deleted, hidden, or exposed, and so the
00317                                  * pointer is invalid. */
00318     int refCount;               /* Reference count: 1 for each cmdName object
00319                                  * that has a pointer to this ResolvedCmdName
00320                                  * structure as its internal rep. This
00321                                  * structure can be freed when refCount
00322                                  * becomes zero. */
00323 } ResolvedCmdName;
00324 
00325 /*
00326  *-------------------------------------------------------------------------
00327  *
00328  * TclInitObjectSubsystem --
00329  *
00330  *      This function is invoked to perform once-only initialization of the
00331  *      type table. It also registers the object types defined in this file.
00332  *
00333  * Results:
00334  *      None.
00335  *
00336  * Side effects:
00337  *      Initializes the table of defined object types "typeTable" with builtin
00338  *      object types defined in this file.
00339  *
00340  *-------------------------------------------------------------------------
00341  */
00342 
00343 void
00344 TclInitObjSubsystem(void)
00345 {
00346     Tcl_MutexLock(&tableMutex);
00347     typeTableInitialized = 1;
00348     Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS);
00349     Tcl_MutexUnlock(&tableMutex);
00350 
00351     Tcl_RegisterObjType(&tclByteArrayType);
00352     Tcl_RegisterObjType(&tclDoubleType);
00353     Tcl_RegisterObjType(&tclEndOffsetType);
00354     Tcl_RegisterObjType(&tclIntType);
00355     Tcl_RegisterObjType(&tclStringType);
00356     Tcl_RegisterObjType(&tclListType);
00357     Tcl_RegisterObjType(&tclDictType);
00358     Tcl_RegisterObjType(&tclByteCodeType);
00359     Tcl_RegisterObjType(&tclArraySearchType);
00360     Tcl_RegisterObjType(&tclCmdNameType);
00361     Tcl_RegisterObjType(&tclRegexpType);
00362     Tcl_RegisterObjType(&tclProcBodyType);
00363 
00364     /* For backward compatibility only ... */
00365     Tcl_RegisterObjType(&oldBooleanType);
00366 #ifndef NO_WIDE_TYPE
00367     Tcl_RegisterObjType(&tclWideIntType);
00368 #endif
00369 
00370 #ifdef TCL_COMPILE_STATS
00371     Tcl_MutexLock(&tclObjMutex);
00372     tclObjsAlloced = 0;
00373     tclObjsFreed = 0;
00374     {
00375         int i;
00376         for (i=0 ; i<TCL_MAX_SHARED_OBJ_STATS ; i++) {
00377             tclObjsShared[i] = 0;
00378         }
00379     }
00380     Tcl_MutexUnlock(&tclObjMutex);
00381 #endif
00382 }
00383 
00384 /*
00385  *----------------------------------------------------------------------
00386  *
00387  * TclFinalizeObjects --
00388  *
00389  *      This function is called by Tcl_Finalize to clean up all registered
00390  *      Tcl_ObjType's and to reset the tclFreeObjList.
00391  *
00392  * Results:
00393  *      None.
00394  *
00395  * Side effects:
00396  *      None.
00397  *
00398  *----------------------------------------------------------------------
00399  */
00400 
00401 void
00402 TclFinalizeObjects(void)
00403 {
00404     Tcl_MutexLock(&tableMutex);
00405     if (typeTableInitialized) {
00406         Tcl_DeleteHashTable(&typeTable);
00407         typeTableInitialized = 0;
00408     }
00409     Tcl_MutexUnlock(&tableMutex);
00410 
00411     /*
00412      * All we do here is reset the head pointer of the linked list of free
00413      * Tcl_Obj's to NULL; the memory finalization will take care of releasing
00414      * memory for us.
00415      */
00416     Tcl_MutexLock(&tclObjMutex);
00417     tclFreeObjList = NULL;
00418     Tcl_MutexUnlock(&tclObjMutex);
00419 }
00420 
00421 /*
00422  *--------------------------------------------------------------
00423  *
00424  * Tcl_RegisterObjType --
00425  *
00426  *      This function is called to register a new Tcl object type in the table
00427  *      of all object types supported by Tcl.
00428  *
00429  * Results:
00430  *      None.
00431  *
00432  * Side effects:
00433  *      The type is registered in the Tcl type table. If there was already a
00434  *      type with the same name as in typePtr, it is replaced with the new
00435  *      type.
00436  *
00437  *--------------------------------------------------------------
00438  */
00439 
00440 void
00441 Tcl_RegisterObjType(
00442     Tcl_ObjType *typePtr)       /* Information about object type; storage must
00443                                  * be statically allocated (must live
00444                                  * forever). */
00445 {
00446     int isNew;
00447 
00448     Tcl_MutexLock(&tableMutex);
00449     Tcl_SetHashValue(
00450             Tcl_CreateHashEntry(&typeTable, typePtr->name, &isNew), typePtr);
00451     Tcl_MutexUnlock(&tableMutex);
00452 }
00453 
00454 /*
00455  *----------------------------------------------------------------------
00456  *
00457  * Tcl_AppendAllObjTypes --
00458  *
00459  *      This function appends onto the argument object the name of each object
00460  *      type as a list element. This includes the builtin object types (e.g.
00461  *      int, list) as well as those added using Tcl_NewObj. These names can be
00462  *      used, for example, with Tcl_GetObjType to get pointers to the
00463  *      corresponding Tcl_ObjType structures.
00464  *
00465  * Results:
00466  *      The return value is normally TCL_OK; in this case the object
00467  *      referenced by objPtr has each type name appended to it. If an error
00468  *      occurs, TCL_ERROR is returned and the interpreter's result holds an
00469  *      error message.
00470  *
00471  * Side effects:
00472  *      If necessary, the object referenced by objPtr is converted into a list
00473  *      object.
00474  *
00475  *----------------------------------------------------------------------
00476  */
00477 
00478 int
00479 Tcl_AppendAllObjTypes(
00480     Tcl_Interp *interp,         /* Interpreter used for error reporting. */
00481     Tcl_Obj *objPtr)            /* Points to the Tcl object onto which the
00482                                  * name of each registered type is appended as
00483                                  * a list element. */
00484 {
00485     register Tcl_HashEntry *hPtr;
00486     Tcl_HashSearch search;
00487     int numElems;
00488 
00489     /*
00490      * Get the test for a valid list out of the way first.
00491      */
00492 
00493     if (TclListObjLength(interp, objPtr, &numElems) != TCL_OK) {
00494         return TCL_ERROR;
00495     }
00496 
00497     /*
00498      * Type names are NUL-terminated, not counted strings. This code relies on
00499      * that.
00500      */
00501 
00502     Tcl_MutexLock(&tableMutex);
00503     for (hPtr = Tcl_FirstHashEntry(&typeTable, &search);
00504             hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
00505         Tcl_ListObjAppendElement(NULL, objPtr,
00506                 Tcl_NewStringObj(Tcl_GetHashKey(&typeTable, hPtr), -1));
00507     }
00508     Tcl_MutexUnlock(&tableMutex);
00509     return TCL_OK;
00510 }
00511 
00512 /*
00513  *----------------------------------------------------------------------
00514  *
00515  * Tcl_GetObjType --
00516  *
00517  *      This function looks up an object type by name.
00518  *
00519  * Results:
00520  *      If an object type with name matching "typeName" is found, a pointer to
00521  *      its Tcl_ObjType structure is returned; otherwise, NULL is returned.
00522  *
00523  * Side effects:
00524  *      None.
00525  *
00526  *----------------------------------------------------------------------
00527  */
00528 
00529 Tcl_ObjType *
00530 Tcl_GetObjType(
00531     CONST char *typeName)       /* Name of Tcl object type to look up. */
00532 {
00533     register Tcl_HashEntry *hPtr;
00534     Tcl_ObjType *typePtr = NULL;
00535 
00536     Tcl_MutexLock(&tableMutex);
00537     hPtr = Tcl_FindHashEntry(&typeTable, typeName);
00538     if (hPtr != NULL) {
00539         typePtr = (Tcl_ObjType *) Tcl_GetHashValue(hPtr);
00540     }
00541     Tcl_MutexUnlock(&tableMutex);
00542     return typePtr;
00543 }
00544 
00545 /*
00546  *----------------------------------------------------------------------
00547  *
00548  * Tcl_ConvertToType --
00549  *
00550  *      Convert the Tcl object "objPtr" to have type "typePtr" if possible.
00551  *
00552  * Results:
00553  *      The return value is TCL_OK on success and TCL_ERROR on failure. If
00554  *      TCL_ERROR is returned, then the interpreter's result contains an error
00555  *      message unless "interp" is NULL. Passing a NULL "interp" allows this
00556  *      function to be used as a test whether the conversion could be done
00557  *      (and in fact was done).
00558  *
00559  * Side effects:
00560  *      Any internal representation for the old type is freed.
00561  *
00562  *----------------------------------------------------------------------
00563  */
00564 
00565 int
00566 Tcl_ConvertToType(
00567     Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
00568     Tcl_Obj *objPtr,            /* The object to convert. */
00569     Tcl_ObjType *typePtr)       /* The target type. */
00570 {
00571     if (objPtr->typePtr == typePtr) {
00572         return TCL_OK;
00573     }
00574 
00575     /*
00576      * Use the target type's Tcl_SetFromAnyProc to set "objPtr"s internal form
00577      * as appropriate for the target type. This frees the old internal
00578      * representation.
00579      */
00580 
00581     if (typePtr->setFromAnyProc == NULL) {
00582         Tcl_Panic("may not convert object to type %s", typePtr->name);
00583     }
00584 
00585     return typePtr->setFromAnyProc(interp, objPtr);
00586 }
00587 
00588 /*
00589  *----------------------------------------------------------------------
00590  *
00591  * TclDbInitNewObj --
00592  *
00593  *      Called via the TclNewObj or TclDbNewObj macros when TCL_MEM_DEBUG is
00594  *      enabled. This function will initialize the members of a Tcl_Obj
00595  *      struct. Initilization would be done inline via the TclNewObj macro
00596  *      when compiling without TCL_MEM_DEBUG.
00597  *
00598  * Results:
00599  *      The Tcl_Obj struct members are initialized.
00600  *
00601  * Side effects:
00602  *      None.
00603  *----------------------------------------------------------------------
00604  */
00605 
00606 #ifdef TCL_MEM_DEBUG
00607 void
00608 TclDbInitNewObj(
00609     register Tcl_Obj *objPtr)
00610 {
00611     objPtr->refCount = 0;
00612     objPtr->bytes = tclEmptyStringRep;
00613     objPtr->length = 0;
00614     objPtr->typePtr = NULL;
00615 
00616 #ifdef TCL_THREADS
00617     /*
00618      * Add entry to a thread local map used to check if a Tcl_Obj was
00619      * allocated by the currently executing thread.
00620      */
00621 
00622     if (!TclInExit()) {
00623         Tcl_HashEntry *hPtr;
00624         Tcl_HashTable *tablePtr;
00625         int isNew;
00626         ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
00627 
00628         if (tsdPtr->objThreadMap == NULL) {
00629             tsdPtr->objThreadMap = (Tcl_HashTable *)
00630                     ckalloc(sizeof(Tcl_HashTable));
00631             Tcl_InitHashTable(tsdPtr->objThreadMap, TCL_ONE_WORD_KEYS);
00632         }
00633         tablePtr = tsdPtr->objThreadMap;
00634         hPtr = Tcl_CreateHashEntry(tablePtr, (char *) objPtr, &isNew);
00635         if (!isNew) {
00636             Tcl_Panic("expected to create new entry for object map");
00637         }
00638         Tcl_SetHashValue(hPtr, NULL);
00639     }
00640 #endif /* TCL_THREADS */
00641 }
00642 #endif /* TCL_MEM_DEBUG */
00643 
00644 /*
00645  *----------------------------------------------------------------------
00646  *
00647  * Tcl_NewObj --
00648  *
00649  *      This function is normally called when not debugging: i.e., when
00650  *      TCL_MEM_DEBUG is not defined. It creates new Tcl objects that denote
00651  *      the empty string. These objects have a NULL object type and NULL
00652  *      string representation byte pointer. Type managers call this routine to
00653  *      allocate new objects that they further initialize.
00654  *
00655  *      When TCL_MEM_DEBUG is defined, this function just returns the result
00656  *      of calling the debugging version Tcl_DbNewObj.
00657  *
00658  * Results:
00659  *      The result is a newly allocated object that represents the empty
00660  *      string. The new object's typePtr is set NULL and its ref count is set
00661  *      to 0.
00662  *
00663  * Side effects:
00664  *      If compiling with TCL_COMPILE_STATS, this function increments the
00665  *      global count of allocated objects (tclObjsAlloced).
00666  *
00667  *----------------------------------------------------------------------
00668  */
00669 
00670 #ifdef TCL_MEM_DEBUG
00671 #undef Tcl_NewObj
00672 
00673 Tcl_Obj *
00674 Tcl_NewObj(void)
00675 {
00676     return Tcl_DbNewObj("unknown", 0);
00677 }
00678 
00679 #else /* if not TCL_MEM_DEBUG */
00680 
00681 Tcl_Obj *
00682 Tcl_NewObj(void)
00683 {
00684     register Tcl_Obj *objPtr;
00685 
00686     /*
00687      * Use the macro defined in tclInt.h - it will use the correct allocator.
00688      */
00689 
00690     TclNewObj(objPtr);
00691     return objPtr;
00692 }
00693 #endif /* TCL_MEM_DEBUG */
00694 
00695 /*
00696  *----------------------------------------------------------------------
00697  *
00698  * Tcl_DbNewObj --
00699  *
00700  *      This function is normally called when debugging: i.e., when
00701  *      TCL_MEM_DEBUG is defined. It creates new Tcl objects that denote the
00702  *      empty string. It is the same as the Tcl_NewObj function above except
00703  *      that it calls Tcl_DbCkalloc directly with the file name and line
00704  *      number from its caller. This simplifies debugging since then the
00705  *      [memory active] command will report the correct file name and line
00706  *      number when reporting objects that haven't been freed.
00707  *
00708  *      When TCL_MEM_DEBUG is not defined, this function just returns the
00709  *      result of calling Tcl_NewObj.
00710  *
00711  * Results:
00712  *      The result is a newly allocated that represents the empty string. The
00713  *      new object's typePtr is set NULL and its ref count is set to 0.
00714  *
00715  * Side effects:
00716  *      If compiling with TCL_COMPILE_STATS, this function increments the
00717  *      global count of allocated objects (tclObjsAlloced).
00718  *
00719  *----------------------------------------------------------------------
00720  */
00721 
00722 #ifdef TCL_MEM_DEBUG
00723 
00724 Tcl_Obj *
00725 Tcl_DbNewObj(
00726     register CONST char *file,  /* The name of the source file calling this
00727                                  * function; used for debugging. */
00728     register int line)          /* Line number in the source file; used for
00729                                  * debugging. */
00730 {
00731     register Tcl_Obj *objPtr;
00732 
00733     /*
00734      * Use the macro defined in tclInt.h - it will use the correct allocator.
00735      */
00736 
00737     TclDbNewObj(objPtr, file, line);
00738     return objPtr;
00739 }
00740 #else /* if not TCL_MEM_DEBUG */
00741 
00742 Tcl_Obj *
00743 Tcl_DbNewObj(
00744     CONST char *file,           /* The name of the source file calling this
00745                                  * function; used for debugging. */
00746     int line)                   /* Line number in the source file; used for
00747                                  * debugging. */
00748 {
00749     return Tcl_NewObj();
00750 }
00751 #endif /* TCL_MEM_DEBUG */
00752 
00753 /*
00754  *----------------------------------------------------------------------
00755  *
00756  * TclAllocateFreeObjects --
00757  *
00758  *      Function to allocate a number of free Tcl_Objs. This is done using a
00759  *      single ckalloc to reduce the overhead for Tcl_Obj allocation.
00760  *
00761  *      Assumes mutex is held.
00762  *
00763  * Results:
00764  *      None.
00765  *
00766  * Side effects:
00767  *      tclFreeObjList, the head of the list of free Tcl_Objs, is set to the
00768  *      first of a number of free Tcl_Obj's linked together by their
00769  *      internalRep.otherValuePtrs.
00770  *
00771  *----------------------------------------------------------------------
00772  */
00773 
00774 #define OBJS_TO_ALLOC_EACH_TIME 100
00775 
00776 void
00777 TclAllocateFreeObjects(void)
00778 {
00779     size_t bytesToAlloc = (OBJS_TO_ALLOC_EACH_TIME * sizeof(Tcl_Obj));
00780     char *basePtr;
00781     register Tcl_Obj *prevPtr, *objPtr;
00782     register int i;
00783 
00784     /*
00785      * This has been noted by Purify to be a potential leak. The problem is
00786      * that Tcl, when not TCL_MEM_DEBUG compiled, keeps around all allocated
00787      * Tcl_Obj's, pointed to by tclFreeObjList, when freed instead of actually
00788      * freeing the memory. TclFinalizeObjects() does not ckfree() this memory,
00789      * but leaves it to Tcl's memory subsystem finalization to release it.
00790      * Purify apparently can't figure that out, and fires a false alarm.
00791      */
00792 
00793     basePtr = (char *) ckalloc(bytesToAlloc);
00794 
00795     prevPtr = NULL;
00796     objPtr = (Tcl_Obj *) basePtr;
00797     for (i = 0; i < OBJS_TO_ALLOC_EACH_TIME; i++) {
00798         objPtr->internalRep.otherValuePtr = (void *) prevPtr;
00799         prevPtr = objPtr;
00800         objPtr++;
00801     }
00802     tclFreeObjList = prevPtr;
00803 }
00804 #undef OBJS_TO_ALLOC_EACH_TIME
00805 
00806 /*
00807  *----------------------------------------------------------------------
00808  *
00809  * TclFreeObj --
00810  *
00811  *      This function frees the memory associated with the argument object.
00812  *      It is called by the tcl.h macro Tcl_DecrRefCount when an object's ref
00813  *      count is zero. It is only "public" since it must be callable by that
00814  *      macro wherever the macro is used. It should not be directly called by
00815  *      clients.
00816  *
00817  * Results:
00818  *      None.
00819  *
00820  * Side effects:
00821  *      Deallocates the storage for the object's Tcl_Obj structure after
00822  *      deallocating the string representation and calling the type-specific
00823  *      Tcl_FreeInternalRepProc to deallocate the object's internal
00824  *      representation. If compiling with TCL_COMPILE_STATS, this function
00825  *      increments the global count of freed objects (tclObjsFreed).
00826  *
00827  *----------------------------------------------------------------------
00828  */
00829 
00830 #ifdef TCL_MEM_DEBUG
00831 void
00832 TclFreeObj(
00833     register Tcl_Obj *objPtr)   /* The object to be freed. */
00834 {
00835     register Tcl_ObjType *typePtr = objPtr->typePtr;
00836 
00837     /*
00838      * This macro declares a variable, so must come here...
00839      */
00840 
00841     ObjInitDeletionContext(context);
00842 
00843     if (objPtr->refCount < -1) {
00844         Tcl_Panic("Reference count for %lx was negative", objPtr);
00845     }
00846 
00847     /* Invalidate the string rep first so we can use the bytes value 
00848      * for our pointer chain, and signal an obj deletion (as opposed
00849      * to shimmering) with 'length == -1' */ 
00850     
00851     TclInvalidateStringRep(objPtr);
00852     objPtr->length = -1;
00853 
00854     if (ObjDeletePending(context)) {
00855         PushObjToDelete(context, objPtr);
00856     } else {
00857         TCL_DTRACE_OBJ_FREE(objPtr);
00858         if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
00859             ObjDeletionLock(context);
00860             typePtr->freeIntRepProc(objPtr);
00861             ObjDeletionUnlock(context);
00862         }
00863 
00864         Tcl_MutexLock(&tclObjMutex);
00865         ckfree((char *) objPtr);
00866         Tcl_MutexUnlock(&tclObjMutex);
00867         TclIncrObjsFreed();
00868         ObjDeletionLock(context);
00869         while (ObjOnStack(context)) {
00870             Tcl_Obj *objToFree;
00871 
00872             PopObjToDelete(context,objToFree);
00873             TCL_DTRACE_OBJ_FREE(objToFree);
00874             TclFreeIntRep(objToFree);
00875 
00876             Tcl_MutexLock(&tclObjMutex);
00877             ckfree((char *) objToFree);
00878             Tcl_MutexUnlock(&tclObjMutex);
00879             TclIncrObjsFreed();
00880         }
00881         ObjDeletionUnlock(context);
00882     }
00883 }
00884 #else /* TCL_MEM_DEBUG */
00885 
00886 void
00887 TclFreeObj(
00888     register Tcl_Obj *objPtr)   /* The object to be freed. */
00889 {
00890     /* Invalidate the string rep first so we can use the bytes value 
00891      * for our pointer chain, and signal an obj deletion (as opposed
00892      * to shimmering) with 'length == -1' */ 
00893 
00894     TclInvalidateStringRep(objPtr);
00895     objPtr->length = -1;
00896     
00897     if (!objPtr->typePtr || !objPtr->typePtr->freeIntRepProc) {
00898         /*
00899          * objPtr can be freed safely, as it will not attempt to free any
00900          * other objects: it will not cause recursive calls to this function.
00901          */
00902 
00903         TCL_DTRACE_OBJ_FREE(objPtr);
00904         TclFreeObjStorage(objPtr);
00905         TclIncrObjsFreed();
00906     } else {
00907         /*
00908          * This macro declares a variable, so must come here...
00909          */
00910 
00911         ObjInitDeletionContext(context);
00912 
00913         if (ObjDeletePending(context)) {
00914             PushObjToDelete(context, objPtr);
00915         } else {
00916             /*
00917              * Note that the contents of the while loop assume that the string
00918              * rep has already been freed and we don't want to do anything
00919              * fancy with adding to the queue inside ourselves. Must take care
00920              * to unstack the object first since freeing the internal rep can
00921              * add further objects to the stack. The code assumes that it is
00922              * the first thing in a block; all current usages in the core
00923              * satisfy this.
00924              */
00925 
00926             TCL_DTRACE_OBJ_FREE(objPtr);
00927             ObjDeletionLock(context);
00928             objPtr->typePtr->freeIntRepProc(objPtr);
00929             ObjDeletionUnlock(context);
00930 
00931             TclFreeObjStorage(objPtr);
00932             TclIncrObjsFreed();
00933             ObjDeletionLock(context);
00934             while (ObjOnStack(context)) {
00935                 Tcl_Obj *objToFree;
00936                 PopObjToDelete(context,objToFree);
00937                 TCL_DTRACE_OBJ_FREE(objToFree);
00938                 if ((objToFree->typePtr != NULL)
00939                         && (objToFree->typePtr->freeIntRepProc != NULL)) {
00940                     objToFree->typePtr->freeIntRepProc(objToFree);
00941                 }
00942                 TclFreeObjStorage(objToFree);
00943                 TclIncrObjsFreed();
00944             }
00945             ObjDeletionUnlock(context);
00946         }
00947     }
00948 }
00949 #endif
00950 
00951 /*
00952  *----------------------------------------------------------------------
00953  *
00954  * TclObjBeingDeleted --
00955  *
00956  *      This function returns 1 when the Tcl_Obj is being deleted. It is
00957  *      provided for the rare cases where the reason for the loss of an
00958  *      internal rep might be relevant. [FR 1512138]
00959  *
00960  * Results:
00961  *      1 if being deleted, 0 otherwise.
00962  *
00963  * Side effects:
00964  *      None.
00965  *
00966  *----------------------------------------------------------------------
00967  */
00968 
00969 int
00970 TclObjBeingDeleted(
00971     Tcl_Obj *objPtr)
00972 {
00973     return (objPtr->length == -1);
00974 }
00975 
00976 
00977 /*
00978  *----------------------------------------------------------------------
00979  *
00980  * Tcl_DuplicateObj --
00981  *
00982  *      Create and return a new object that is a duplicate of the argument
00983  *      object.
00984  *
00985  * Results:
00986  *      The return value is a pointer to a newly created Tcl_Obj. This object
00987  *      has reference count 0 and the same type, if any, as the source object
00988  *      objPtr. Also:
00989  *        1) If the source object has a valid string rep, we copy it;
00990  *           otherwise, the duplicate's string rep is set NULL to mark it
00991  *           invalid.
00992  *        2) If the source object has an internal representation (i.e. its
00993  *           typePtr is non-NULL), the new object's internal rep is set to a
00994  *           copy; otherwise the new internal rep is marked invalid.
00995  *
00996  * Side effects:
00997  *      What constitutes "copying" the internal representation depends on the
00998  *      type. For example, if the argument object is a list, the element
00999  *      objects it points to will not actually be copied but will be shared
01000  *      with the duplicate list. That is, the ref counts of the element
01001  *      objects will be incremented.
01002  *
01003  *----------------------------------------------------------------------
01004  */
01005 
01006 Tcl_Obj *
01007 Tcl_DuplicateObj(
01008     register Tcl_Obj *objPtr)           /* The object to duplicate. */
01009 {
01010     register Tcl_ObjType *typePtr = objPtr->typePtr;
01011     register Tcl_Obj *dupPtr;
01012 
01013     TclNewObj(dupPtr);
01014 
01015     if (objPtr->bytes == NULL) {
01016         dupPtr->bytes = NULL;
01017     } else if (objPtr->bytes != tclEmptyStringRep) {
01018         TclInitStringRep(dupPtr, objPtr->bytes, objPtr->length);
01019     }
01020 
01021     if (typePtr != NULL) {
01022         if (typePtr->dupIntRepProc == NULL) {
01023             dupPtr->internalRep = objPtr->internalRep;
01024             dupPtr->typePtr = typePtr;
01025         } else {
01026             (*typePtr->dupIntRepProc)(objPtr, dupPtr);
01027         }
01028     }
01029     return dupPtr;
01030 }
01031 
01032 /*
01033  *----------------------------------------------------------------------
01034  *
01035  * Tcl_GetString --
01036  *
01037  *      Returns the string representation byte array pointer for an object.
01038  *
01039  * Results:
01040  *      Returns a pointer to the string representation of objPtr. The byte
01041  *      array referenced by the returned pointer must not be modified by the
01042  *      caller. Furthermore, the caller must copy the bytes if they need to
01043  *      retain them since the object's string rep can change as a result of
01044  *      other operations.
01045  *
01046  * Side effects:
01047  *      May call the object's updateStringProc to update the string
01048  *      representation from the internal representation.
01049  *
01050  *----------------------------------------------------------------------
01051  */
01052 
01053 char *
01054 Tcl_GetString(
01055     register Tcl_Obj *objPtr)   /* Object whose string rep byte pointer should
01056                                  * be returned. */
01057 {
01058     if (objPtr->bytes != NULL) {
01059         return objPtr->bytes;
01060     }
01061 
01062     if (objPtr->typePtr->updateStringProc == NULL) {
01063         Tcl_Panic("UpdateStringProc should not be invoked for type %s",
01064                 objPtr->typePtr->name);
01065     }
01066     (*objPtr->typePtr->updateStringProc)(objPtr);
01067     return objPtr->bytes;
01068 }
01069 
01070 /*
01071  *----------------------------------------------------------------------
01072  *
01073  * Tcl_GetStringFromObj --
01074  *
01075  *      Returns the string representation's byte array pointer and length for
01076  *      an object.
01077  *
01078  * Results:
01079  *      Returns a pointer to the string representation of objPtr. If lengthPtr
01080  *      isn't NULL, the length of the string representation is stored at
01081  *      *lengthPtr. The byte array referenced by the returned pointer must not
01082  *      be modified by the caller. Furthermore, the caller must copy the bytes
01083  *      if they need to retain them since the object's string rep can change
01084  *      as a result of other operations.
01085  *
01086  * Side effects:
01087  *      May call the object's updateStringProc to update the string
01088  *      representation from the internal representation.
01089  *
01090  *----------------------------------------------------------------------
01091  */
01092 
01093 char *
01094 Tcl_GetStringFromObj(
01095     register Tcl_Obj *objPtr,   /* Object whose string rep byte pointer should
01096                                  * be returned. */
01097     register int *lengthPtr)    /* If non-NULL, the location where the string
01098                                  * rep's byte array length should * be stored.
01099                                  * If NULL, no length is stored. */
01100 {
01101     if (objPtr->bytes == NULL) {
01102         if (objPtr->typePtr->updateStringProc == NULL) {
01103             Tcl_Panic("UpdateStringProc should not be invoked for type %s",
01104                     objPtr->typePtr->name);
01105         }
01106         (*objPtr->typePtr->updateStringProc)(objPtr);
01107     }
01108 
01109     if (lengthPtr != NULL) {
01110         *lengthPtr = objPtr->length;
01111     }
01112     return objPtr->bytes;
01113 }
01114 
01115 /*
01116  *----------------------------------------------------------------------
01117  *
01118  * Tcl_InvalidateStringRep --
01119  *
01120  *      This function is called to invalidate an object's string
01121  *      representation.
01122  *
01123  * Results:
01124  *      None.
01125  *
01126  * Side effects:
01127  *      Deallocates the storage for any old string representation, then sets
01128  *      the string representation NULL to mark it invalid.
01129  *
01130  *----------------------------------------------------------------------
01131  */
01132 
01133 void
01134 Tcl_InvalidateStringRep(
01135     register Tcl_Obj *objPtr)   /* Object whose string rep byte pointer should
01136                                  * be freed. */
01137 {
01138     TclInvalidateStringRep(objPtr);
01139 }
01140 
01141 
01142 /*
01143  *----------------------------------------------------------------------
01144  *
01145  * Tcl_NewBooleanObj --
01146  *
01147  *      This function is normally called when not debugging: i.e., when
01148  *      TCL_MEM_DEBUG is not defined. It creates a new Tcl_Obj and
01149  *      initializes it from the argument boolean value. A nonzero "boolValue"
01150  *      is coerced to 1.
01151  *
01152  *      When TCL_MEM_DEBUG is defined, this function just returns the result
01153  *      of calling the debugging version Tcl_DbNewBooleanObj.
01154  *
01155  * Results:
01156  *      The newly created object is returned. This object will have an invalid
01157  *      string representation. The returned object has ref count 0.
01158  *
01159  * Side effects:
01160  *      None.
01161  *
01162  *----------------------------------------------------------------------
01163  */
01164 
01165 #ifdef TCL_MEM_DEBUG
01166 #undef Tcl_NewBooleanObj
01167 
01168 Tcl_Obj *
01169 Tcl_NewBooleanObj(
01170     register int boolValue)     /* Boolean used to initialize new object. */
01171 {
01172     return Tcl_DbNewBooleanObj(boolValue, "unknown", 0);
01173 }
01174 
01175 #else /* if not TCL_MEM_DEBUG */
01176 
01177 Tcl_Obj *
01178 Tcl_NewBooleanObj(
01179     register int boolValue)     /* Boolean used to initialize new object. */
01180 {
01181     register Tcl_Obj *objPtr;
01182 
01183     TclNewBooleanObj(objPtr, boolValue);
01184     return objPtr;
01185 }
01186 #endif /* TCL_MEM_DEBUG */
01187 
01188 /*
01189  *----------------------------------------------------------------------
01190  *
01191  * Tcl_DbNewBooleanObj --
01192  *
01193  *      This function is normally called when debugging: i.e., when
01194  *      TCL_MEM_DEBUG is defined. It creates new boolean objects. It is the
01195  *      same as the Tcl_NewBooleanObj function above except that it calls
01196  *      Tcl_DbCkalloc directly with the file name and line number from its
01197  *      caller. This simplifies debugging since then the [memory active]
01198  *      command will report the correct file name and line number when
01199  *      reporting objects that haven't been freed.
01200  *
01201  *      When TCL_MEM_DEBUG is not defined, this function just returns the
01202  *      result of calling Tcl_NewBooleanObj.
01203  *
01204  * Results:
01205  *      The newly created object is returned. This object will have an invalid
01206  *      string representation. The returned object has ref count 0.
01207  *
01208  * Side effects:
01209  *      None.
01210  *
01211  *----------------------------------------------------------------------
01212  */
01213 
01214 #ifdef TCL_MEM_DEBUG
01215 
01216 Tcl_Obj *
01217 Tcl_DbNewBooleanObj(
01218     register int boolValue,     /* Boolean used to initialize new object. */
01219     CONST char *file,           /* The name of the source file calling this
01220                                  * function; used for debugging. */
01221     int line)                   /* Line number in the source file; used for
01222                                  * debugging. */
01223 {
01224     register Tcl_Obj *objPtr;
01225 
01226     TclDbNewObj(objPtr, file, line);
01227     objPtr->bytes = NULL;
01228 
01229     objPtr->internalRep.longValue = (boolValue? 1 : 0);
01230     objPtr->typePtr = &tclIntType;
01231     return objPtr;
01232 }
01233 
01234 #else /* if not TCL_MEM_DEBUG */
01235 
01236 Tcl_Obj *
01237 Tcl_DbNewBooleanObj(
01238     register int boolValue,     /* Boolean used to initialize new object. */
01239     CONST char *file,           /* The name of the source file calling this
01240                                  * function; used for debugging. */
01241     int line)                   /* Line number in the source file; used for
01242                                  * debugging. */
01243 {
01244     return Tcl_NewBooleanObj(boolValue);
01245 }
01246 #endif /* TCL_MEM_DEBUG */
01247 
01248 /*
01249  *----------------------------------------------------------------------
01250  *
01251  * Tcl_SetBooleanObj --
01252  *
01253  *      Modify an object to be a boolean object and to have the specified
01254  *      boolean value. A nonzero "boolValue" is coerced to 1.
01255  *
01256  * Results:
01257  *      None.
01258  *
01259  * Side effects:
01260  *      The object's old string rep, if any, is freed. Also, any old internal
01261  *      rep is freed.
01262  *
01263  *----------------------------------------------------------------------
01264  */
01265 
01266 void
01267 Tcl_SetBooleanObj(
01268     register Tcl_Obj *objPtr,   /* Object whose internal rep to init. */
01269     register int boolValue)     /* Boolean used to set object's value. */
01270 {
01271     if (Tcl_IsShared(objPtr)) {
01272         Tcl_Panic("%s called with shared object", "Tcl_SetBooleanObj");
01273     }
01274 
01275     TclSetBooleanObj(objPtr, boolValue);
01276 }
01277 
01278 /*
01279  *----------------------------------------------------------------------
01280  *
01281  * Tcl_GetBooleanFromObj --
01282  *
01283  *      Attempt to return a boolean from the Tcl object "objPtr". This
01284  *      includes conversion from any of Tcl's numeric types.
01285  *
01286  * Results:
01287  *      The return value is a standard Tcl object result. If an error occurs
01288  *      during conversion, an error message is left in the interpreter's
01289  *      result unless "interp" is NULL.
01290  *
01291  * Side effects:
01292  *      The intrep of *objPtr may be changed.
01293  *
01294  *----------------------------------------------------------------------
01295  */
01296 
01297 int
01298 Tcl_GetBooleanFromObj(
01299     Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
01300     register Tcl_Obj *objPtr,   /* The object from which to get boolean. */
01301     register int *boolPtr)      /* Place to store resulting boolean. */
01302 {
01303     do {
01304         if (objPtr->typePtr == &tclIntType) {
01305             *boolPtr = (objPtr->internalRep.longValue != 0);
01306             return TCL_OK;
01307         }
01308         if (objPtr->typePtr == &tclBooleanType) {
01309             *boolPtr = (int) objPtr->internalRep.longValue;
01310             return TCL_OK;
01311         }
01312         if (objPtr->typePtr == &tclDoubleType) {
01313             /*
01314              * Caution: Don't be tempted to check directly for the "double"
01315              * Tcl_ObjType and then compare the intrep to 0.0. This isn't
01316              * reliable because a "double" Tcl_ObjType can hold the NaN value.
01317              * Use the API Tcl_GetDoubleFromObj, which does the checking and
01318              * sets the proper error message for us.
01319              */
01320 
01321             double d;
01322 
01323             if (Tcl_GetDoubleFromObj(interp, objPtr, &d) != TCL_OK) {
01324                 return TCL_ERROR;
01325             }
01326             *boolPtr = (d != 0.0);
01327             return TCL_OK;
01328         }
01329         if (objPtr->typePtr == &tclBignumType) {
01330             *boolPtr = 1;
01331             return TCL_OK;
01332         }
01333 #ifndef NO_WIDE_TYPE
01334         if (objPtr->typePtr == &tclWideIntType) {
01335             *boolPtr = (objPtr->internalRep.wideValue != 0);
01336             return TCL_OK;
01337         }
01338 #endif
01339     } while ((ParseBoolean(objPtr) == TCL_OK) || (TCL_OK ==
01340             TclParseNumber(interp, objPtr, "boolean value", NULL,-1,NULL,0)));
01341     return TCL_ERROR;
01342 }
01343 
01344 /*
01345  *----------------------------------------------------------------------
01346  *
01347  * SetBooleanFromAny --
01348  *
01349  *      Attempt to generate a boolean internal form for the Tcl object
01350  *      "objPtr".
01351  *
01352  * Results:
01353  *      The return value is a standard Tcl result. If an error occurs during
01354  *      conversion, an error message is left in the interpreter's result
01355  *      unless "interp" is NULL.
01356  *
01357  * Side effects:
01358  *      If no error occurs, an integer 1 or 0 is stored as "objPtr"s internal
01359  *      representation and the type of "objPtr" is set to boolean.
01360  *
01361  *----------------------------------------------------------------------
01362  */
01363 
01364 static int
01365 SetBooleanFromAny(
01366     Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
01367     register Tcl_Obj *objPtr)   /* The object to convert. */
01368 {
01369     /*
01370      * For some "pure" numeric Tcl_ObjTypes (no string rep), we can determine
01371      * whether a boolean conversion is possible without generating the string
01372      * rep.
01373      */
01374 
01375     if (objPtr->bytes == NULL) {
01376         if (objPtr->typePtr == &tclIntType) {
01377             switch (objPtr->internalRep.longValue) {
01378             case 0L: case 1L:
01379                 return TCL_OK;
01380             }
01381             goto badBoolean;
01382         }
01383 
01384         if (objPtr->typePtr == &tclBignumType) {
01385             goto badBoolean;
01386         }
01387 
01388 #ifndef NO_WIDE_TYPE
01389         if (objPtr->typePtr == &tclWideIntType) {
01390             goto badBoolean;
01391         }
01392 #endif
01393 
01394         if (objPtr->typePtr == &tclDoubleType) {
01395             goto badBoolean;
01396         }
01397     }
01398 
01399     if (ParseBoolean(objPtr) == TCL_OK) {
01400         return TCL_OK;
01401     }
01402 
01403   badBoolean:
01404     if (interp != NULL) {
01405         int length;
01406         char *str = Tcl_GetStringFromObj(objPtr, &length);
01407         Tcl_Obj *msg;
01408 
01409         TclNewLiteralStringObj(msg, "expected boolean value but got \"");
01410         Tcl_AppendLimitedToObj(msg, str, length, 50, "");
01411         Tcl_AppendToObj(msg, "\"", -1);
01412         Tcl_SetObjResult(interp, msg);
01413     }
01414     return TCL_ERROR;
01415 }
01416 
01417 static int
01418 ParseBoolean(
01419     register Tcl_Obj *objPtr)   /* The object to parse/convert. */
01420 {
01421     int i, length, newBool;
01422     char lowerCase[6], *str = TclGetStringFromObj(objPtr, &length);
01423 
01424     if ((length == 0) || (length > 5)) {
01425         /* longest valid boolean string rep. is "false" */
01426         return TCL_ERROR;
01427     }
01428 
01429     switch (str[0]) {
01430     case '0':
01431         if (length == 1) {
01432             newBool = 0;
01433             goto numericBoolean;
01434         }
01435         return TCL_ERROR;
01436     case '1':
01437         if (length == 1) {
01438             newBool = 1;
01439             goto numericBoolean;
01440         }
01441         return TCL_ERROR;
01442     }
01443 
01444     /*
01445      * Force to lower case for case-insensitive detection. Filter out known
01446      * invalid characters at the same time.
01447      */
01448 
01449     for (i=0; i < length; i++) {
01450         char c = str[i];
01451         switch (c) {
01452         case 'A': case 'E': case 'F': case 'L': case 'N':
01453         case 'O': case 'R': case 'S': case 'T': case 'U': case 'Y':
01454             lowerCase[i] = c + (char) ('a' - 'A');
01455             break;
01456         case 'a': case 'e': case 'f': case 'l': case 'n':
01457         case 'o': case 'r': case 's': case 't': case 'u': case 'y':
01458             lowerCase[i] = c;
01459             break;
01460         default:
01461             return TCL_ERROR;
01462         }
01463     }
01464     lowerCase[length] = 0;
01465     switch (lowerCase[0]) {
01466     case 'y':
01467         /*
01468          * Checking the 'y' is redundant, but makes the code clearer.
01469          */
01470         if (strncmp(lowerCase, "yes", (size_t) length) == 0) {
01471             newBool = 1;
01472             goto goodBoolean;
01473         }
01474         return TCL_ERROR;
01475     case 'n':
01476         if (strncmp(lowerCase, "no", (size_t) length) == 0) {
01477             newBool = 0;
01478             goto goodBoolean;
01479         }
01480         return TCL_ERROR;
01481     case 't':
01482         if (strncmp(lowerCase, "true", (size_t) length) == 0) {
01483             newBool = 1;
01484             goto goodBoolean;
01485         }
01486         return TCL_ERROR;
01487     case 'f':
01488         if (strncmp(lowerCase, "false", (size_t) length) == 0) {
01489             newBool = 0;
01490             goto goodBoolean;
01491         }
01492         return TCL_ERROR;
01493     case 'o':
01494         if (length < 2) {
01495             return TCL_ERROR;
01496         }
01497         if (strncmp(lowerCase, "on", (size_t) length) == 0) {
01498             newBool = 1;
01499             goto goodBoolean;
01500         } else if (strncmp(lowerCase, "off", (size_t) length) == 0) {
01501             newBool = 0;
01502             goto goodBoolean;
01503         }
01504         return TCL_ERROR;
01505     default:
01506         return TCL_ERROR;
01507     }
01508 
01509     /*
01510      * Free the old internalRep before setting the new one. We do this as late
01511      * as possible to allow the conversion code, in particular
01512      * Tcl_GetStringFromObj, to use that old internalRep.
01513      */
01514 
01515   goodBoolean:
01516     TclFreeIntRep(objPtr);
01517     objPtr->internalRep.longValue = newBool;
01518     objPtr->typePtr = &tclBooleanType;
01519     return TCL_OK;
01520 
01521   numericBoolean:
01522     TclFreeIntRep(objPtr);
01523     objPtr->internalRep.longValue = newBool;
01524     objPtr->typePtr = &tclIntType;
01525     return TCL_OK;
01526 }
01527 
01528 /*
01529  *----------------------------------------------------------------------
01530  *
01531  * Tcl_NewDoubleObj --
01532  *
01533  *      This function is normally called when not debugging: i.e., when
01534  *      TCL_MEM_DEBUG is not defined. It creates a new double object and
01535  *      initializes it from the argument double value.
01536  *
01537  *      When TCL_MEM_DEBUG is defined, this function just returns the result
01538  *      of calling the debugging version Tcl_DbNewDoubleObj.
01539  *
01540  * Results:
01541  *      The newly created object is returned. This object will have an
01542  *      invalid string representation. The returned object has ref count 0.
01543  *
01544  * Side effects:
01545  *      None.
01546  *
01547  *----------------------------------------------------------------------
01548  */
01549 
01550 #ifdef TCL_MEM_DEBUG
01551 #undef Tcl_NewDoubleObj
01552 
01553 Tcl_Obj *
01554 Tcl_NewDoubleObj(
01555     register double dblValue)   /* Double used to initialize the object. */
01556 {
01557     return Tcl_DbNewDoubleObj(dblValue, "unknown", 0);
01558 }
01559 
01560 #else /* if not TCL_MEM_DEBUG */
01561 
01562 Tcl_Obj *
01563 Tcl_NewDoubleObj(
01564     register double dblValue)   /* Double used to initialize the object. */
01565 {
01566     register Tcl_Obj *objPtr;
01567 
01568     TclNewDoubleObj(objPtr, dblValue);
01569     return objPtr;
01570 }
01571 #endif /* if TCL_MEM_DEBUG */
01572 
01573 /*
01574  *----------------------------------------------------------------------
01575  *
01576  * Tcl_DbNewDoubleObj --
01577  *
01578  *      This function is normally called when debugging: i.e., when
01579  *      TCL_MEM_DEBUG is defined. It creates new double objects. It is the
01580  *      same as the Tcl_NewDoubleObj function above except that it calls
01581  *      Tcl_DbCkalloc directly with the file name and line number from its
01582  *      caller. This simplifies debugging since then the [memory active]
01583  *      command will report the correct file name and line number when
01584  *      reporting objects that haven't been freed.
01585  *
01586  *      When TCL_MEM_DEBUG is not defined, this function just returns the
01587  *      result of calling Tcl_NewDoubleObj.
01588  *
01589  * Results:
01590  *      The newly created object is returned. This object will have an invalid
01591  *      string representation. The returned object has ref count 0.
01592  *
01593  * Side effects:
01594  *      None.
01595  *
01596  *----------------------------------------------------------------------
01597  */
01598 
01599 #ifdef TCL_MEM_DEBUG
01600 
01601 Tcl_Obj *
01602 Tcl_DbNewDoubleObj(
01603     register double dblValue,   /* Double used to initialize the object. */
01604     CONST char *file,           /* The name of the source file calling this
01605                                  * function; used for debugging. */
01606     int line)                   /* Line number in the source file; used for
01607                                  * debugging. */
01608 {
01609     register Tcl_Obj *objPtr;
01610 
01611     TclDbNewObj(objPtr, file, line);
01612     objPtr->bytes = NULL;
01613 
01614     objPtr->internalRep.doubleValue = dblValue;
01615     objPtr->typePtr = &tclDoubleType;
01616     return objPtr;
01617 }
01618 
01619 #else /* if not TCL_MEM_DEBUG */
01620 
01621 Tcl_Obj *
01622 Tcl_DbNewDoubleObj(
01623     register double dblValue,   /* Double used to initialize the object. */
01624     CONST char *file,           /* The name of the source file calling this
01625                                  * function; used for debugging. */
01626     int line)                   /* Line number in the source file; used for
01627                                  * debugging. */
01628 {
01629     return Tcl_NewDoubleObj(dblValue);
01630 }
01631 #endif /* TCL_MEM_DEBUG */
01632 
01633 /*
01634  *----------------------------------------------------------------------
01635  *
01636  * Tcl_SetDoubleObj --
01637  *
01638  *      Modify an object to be a double object and to have the specified
01639  *      double value.
01640  *
01641  * Results:
01642  *      None.
01643  *
01644  * Side effects:
01645  *      The object's old string rep, if any, is freed. Also, any old internal
01646  *      rep is freed.
01647  *
01648  *----------------------------------------------------------------------
01649  */
01650 
01651 void
01652 Tcl_SetDoubleObj(
01653     register Tcl_Obj *objPtr,   /* Object whose internal rep to init. */
01654     register double dblValue)   /* Double used to set the object's value. */
01655 {
01656     if (Tcl_IsShared(objPtr)) {
01657         Tcl_Panic("%s called with shared object", "Tcl_SetDoubleObj");
01658     }
01659 
01660     TclSetDoubleObj(objPtr, dblValue);
01661 }
01662 
01663 /*
01664  *----------------------------------------------------------------------
01665  *
01666  * Tcl_GetDoubleFromObj --
01667  *
01668  *      Attempt to return a double from the Tcl object "objPtr". If the object
01669  *      is not already a double, an attempt will be made to convert it to one.
01670  *
01671  * Results:
01672  *      The return value is a standard Tcl object result. If an error occurs
01673  *      during conversion, an error message is left in the interpreter's
01674  *      result unless "interp" is NULL.
01675  *
01676  * Side effects:
01677  *      If the object is not already a double, the conversion will free any
01678  *      old internal representation.
01679  *
01680  *----------------------------------------------------------------------
01681  */
01682 
01683 int
01684 Tcl_GetDoubleFromObj(
01685     Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
01686     register Tcl_Obj *objPtr,   /* The object from which to get a double. */
01687     register double *dblPtr)    /* Place to store resulting double. */
01688 {
01689     do {
01690         if (objPtr->typePtr == &tclDoubleType) {
01691             if (TclIsNaN(objPtr->internalRep.doubleValue)) {
01692                 if (interp != NULL) {
01693                     Tcl_SetObjResult(interp, Tcl_NewStringObj(
01694                             "floating point value is Not a Number", -1));
01695                 }
01696                 return TCL_ERROR;
01697             }
01698             *dblPtr = (double) objPtr->internalRep.doubleValue;
01699             return TCL_OK;
01700         }
01701         if (objPtr->typePtr == &tclIntType) {
01702             *dblPtr = objPtr->internalRep.longValue;
01703             return TCL_OK;
01704         }
01705         if (objPtr->typePtr == &tclBignumType) {
01706             mp_int big;
01707             UNPACK_BIGNUM( objPtr, big );
01708             *dblPtr = TclBignumToDouble( &big );
01709             return TCL_OK;
01710         }
01711 #ifndef NO_WIDE_TYPE
01712         if (objPtr->typePtr == &tclWideIntType) {
01713             *dblPtr = (double) objPtr->internalRep.wideValue;
01714             return TCL_OK;
01715         }
01716 #endif
01717     } while (SetDoubleFromAny(interp, objPtr) == TCL_OK);
01718     return TCL_ERROR;
01719 }
01720 
01721 /*
01722  *----------------------------------------------------------------------
01723  *
01724  * SetDoubleFromAny --
01725  *
01726  *      Attempt to generate an double-precision floating point internal form
01727  *      for the Tcl object "objPtr".
01728  *
01729  * Results:
01730  *      The return value is a standard Tcl object result. If an error occurs
01731  *      during conversion, an error message is left in the interpreter's
01732  *      result unless "interp" is NULL.
01733  *
01734  * Side effects:
01735  *      If no error occurs, a double is stored as "objPtr"s internal
01736  *      representation.
01737  *
01738  *----------------------------------------------------------------------
01739  */
01740 
01741 static int
01742 SetDoubleFromAny(
01743     Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
01744     register Tcl_Obj *objPtr)   /* The object to convert. */
01745 {
01746     return TclParseNumber(interp, objPtr, "floating-point number", NULL, -1,
01747             NULL, 0);
01748 }
01749 
01750 /*
01751  *----------------------------------------------------------------------
01752  *
01753  * UpdateStringOfDouble --
01754  *
01755  *      Update the string representation for a double-precision floating point
01756  *      object. This must obey the current tcl_precision value for
01757  *      double-to-string conversions. Note: This function does not free an
01758  *      existing old string rep so storage will be lost if this has not
01759  *      already been done.
01760  *
01761  * Results:
01762  *      None.
01763  *
01764  * Side effects:
01765  *      The object's string is set to a valid string that results from the
01766  *      double-to-string conversion.
01767  *
01768  *----------------------------------------------------------------------
01769  */
01770 
01771 static void
01772 UpdateStringOfDouble(
01773     register Tcl_Obj *objPtr)   /* Double obj with string rep to update. */
01774 {
01775     char buffer[TCL_DOUBLE_SPACE];
01776     register int len;
01777 
01778     Tcl_PrintDouble(NULL, objPtr->internalRep.doubleValue, buffer);
01779     len = strlen(buffer);
01780 
01781     objPtr->bytes = (char *) ckalloc((unsigned) len + 1);
01782     strcpy(objPtr->bytes, buffer);
01783     objPtr->length = len;
01784 }
01785 
01786 /*
01787  *----------------------------------------------------------------------
01788  *
01789  * Tcl_NewIntObj --
01790  *
01791  *      If a client is compiled with TCL_MEM_DEBUG defined, calls to
01792  *      Tcl_NewIntObj to create a new integer object end up calling the
01793  *      debugging function Tcl_DbNewLongObj instead.
01794  *
01795  *      Otherwise, if the client is compiled without TCL_MEM_DEBUG defined,
01796  *      calls to Tcl_NewIntObj result in a call to one of the two
01797  *      Tcl_NewIntObj implementations below. We provide two implementations so
01798  *      that the Tcl core can be compiled to do memory debugging of the core
01799  *      even if a client does not request it for itself.
01800  *
01801  *      Integer and long integer objects share the same "integer" type
01802  *      implementation. We store all integers as longs and Tcl_GetIntFromObj
01803  *      checks whether the current value of the long can be represented by an
01804  *      int.
01805  *
01806  * Results:
01807  *      The newly created object is returned. This object will have an invalid
01808  *      string representation. The returned object has ref count 0.
01809  *
01810  * Side effects:
01811  *      None.
01812  *
01813  *----------------------------------------------------------------------
01814  */
01815 
01816 #ifdef TCL_MEM_DEBUG
01817 #undef Tcl_NewIntObj
01818 
01819 Tcl_Obj *
01820 Tcl_NewIntObj(
01821     register int intValue)      /* Int used to initialize the new object. */
01822 {
01823     return Tcl_DbNewLongObj((long)intValue, "unknown", 0);
01824 }
01825 
01826 #else /* if not TCL_MEM_DEBUG */
01827 
01828 Tcl_Obj *
01829 Tcl_NewIntObj(
01830     register int intValue)      /* Int used to initialize the new object. */
01831 {
01832     register Tcl_Obj *objPtr;
01833 
01834     TclNewIntObj(objPtr, intValue);
01835     return objPtr;
01836 }
01837 #endif /* if TCL_MEM_DEBUG */
01838 
01839 /*
01840  *----------------------------------------------------------------------
01841  *
01842  * Tcl_SetIntObj --
01843  *
01844  *      Modify an object to be an integer and to have the specified integer
01845  *      value.
01846  *
01847  * Results:
01848  *      None.
01849  *
01850  * Side effects:
01851  *      The object's old string rep, if any, is freed. Also, any old internal
01852  *      rep is freed.
01853  *
01854  *----------------------------------------------------------------------
01855  */
01856 
01857 void
01858 Tcl_SetIntObj(
01859     register Tcl_Obj *objPtr,   /* Object whose internal rep to init. */
01860     register int intValue)      /* Integer used to set object's value. */
01861 {
01862     if (Tcl_IsShared(objPtr)) {
01863         Tcl_Panic("%s called with shared object", "Tcl_SetIntObj");
01864     }
01865 
01866     TclSetIntObj(objPtr, intValue);
01867 }
01868 
01869 /*
01870  *----------------------------------------------------------------------
01871  *
01872  * Tcl_GetIntFromObj --
01873  *
01874  *      Attempt to return an int from the Tcl object "objPtr". If the object
01875  *      is not already an int, an attempt will be made to convert it to one.
01876  *
01877  *      Integer and long integer objects share the same "integer" type
01878  *      implementation. We store all integers as longs and Tcl_GetIntFromObj
01879  *      checks whether the current value of the long can be represented by an
01880  *      int.
01881  *
01882  * Results:
01883  *      The return value is a standard Tcl object result. If an error occurs
01884  *      during conversion or if the long integer held by the object can not be
01885  *      represented by an int, an error message is left in the interpreter's
01886  *      result unless "interp" is NULL.
01887  *
01888  * Side effects:
01889  *      If the object is not already an int, the conversion will free any old
01890  *      internal representation.
01891  *
01892  *----------------------------------------------------------------------
01893  */
01894 
01895 int
01896 Tcl_GetIntFromObj(
01897     Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
01898     register Tcl_Obj *objPtr,   /* The object from which to get a int. */
01899     register int *intPtr)       /* Place to store resulting int. */
01900 {
01901 #if (LONG_MAX == INT_MAX)
01902     return TclGetLongFromObj(interp, objPtr, (long *) intPtr);
01903 #else
01904     long l;
01905 
01906     if (TclGetLongFromObj(interp, objPtr, &l) != TCL_OK) {
01907         return TCL_ERROR;
01908     }
01909     if ((ULONG_MAX > UINT_MAX) && ((l > UINT_MAX) || (l < -(long)UINT_MAX))) {
01910         if (interp != NULL) {
01911             CONST char *s =
01912                     "integer value too large to represent as non-long integer";
01913             Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
01914             Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
01915         }
01916         return TCL_ERROR;
01917     }
01918     *intPtr = (int) l;
01919     return TCL_OK;
01920 #endif
01921 }
01922 
01923 /*
01924  *----------------------------------------------------------------------
01925  *
01926  * SetIntFromAny --
01927  *
01928  *      Attempts to force the internal representation for a Tcl object to
01929  *      tclIntType, specifically.
01930  *
01931  * Results:
01932  *      The return value is a standard object Tcl result. If an error occurs
01933  *      during conversion, an error message is left in the interpreter's
01934  *      result unless "interp" is NULL.
01935  *
01936  *----------------------------------------------------------------------
01937  */
01938 
01939 static int
01940 SetIntFromAny(
01941     Tcl_Interp *interp,         /* Tcl interpreter */
01942     Tcl_Obj *objPtr)            /* Pointer to the object to convert */
01943 {
01944     long l;
01945     return TclGetLongFromObj(interp, objPtr, &l);
01946 }
01947 
01948 /*
01949  *----------------------------------------------------------------------
01950  *
01951  * UpdateStringOfInt --
01952  *
01953  *      Update the string representation for an integer object. Note: This
01954  *      function does not free an existing old string rep so storage will be
01955  *      lost if this has not already been done.
01956  *
01957  * Results:
01958  *      None.
01959  *
01960  * Side effects:
01961  *      The object's string is set to a valid string that results from the
01962  *      int-to-string conversion.
01963  *
01964  *----------------------------------------------------------------------
01965  */
01966 
01967 static void
01968 UpdateStringOfInt(
01969     register Tcl_Obj *objPtr)   /* Int object whose string rep to update. */
01970 {
01971     char buffer[TCL_INTEGER_SPACE];
01972     register int len;
01973 
01974     len = TclFormatInt(buffer, objPtr->internalRep.longValue);
01975 
01976     objPtr->bytes = ckalloc((unsigned) len + 1);
01977     strcpy(objPtr->bytes, buffer);
01978     objPtr->length = len;
01979 }
01980 
01981 /*
01982  *----------------------------------------------------------------------
01983  *
01984  * Tcl_NewLongObj --
01985  *
01986  *      If a client is compiled with TCL_MEM_DEBUG defined, calls to
01987  *      Tcl_NewLongObj to create a new long integer object end up calling the
01988  *      debugging function Tcl_DbNewLongObj instead.
01989  *
01990  *      Otherwise, if the client is compiled without TCL_MEM_DEBUG defined,
01991  *      calls to Tcl_NewLongObj result in a call to one of the two
01992  *      Tcl_NewLongObj implementations below. We provide two implementations
01993  *      so that the Tcl core can be compiled to do memory debugging of the
01994  *      core even if a client does not request it for itself.
01995  *
01996  *      Integer and long integer objects share the same "integer" type
01997  *      implementation. We store all integers as longs and Tcl_GetIntFromObj
01998  *      checks whether the current value of the long can be represented by an
01999  *      int.
02000  *
02001  * Results:
02002  *      The newly created object is returned. This object will have an invalid
02003  *      string representation. The returned object has ref count 0.
02004  *
02005  * Side effects:
02006  *      None.
02007  *
02008  *----------------------------------------------------------------------
02009  */
02010 
02011 #ifdef TCL_MEM_DEBUG
02012 #undef Tcl_NewLongObj
02013 
02014 Tcl_Obj *
02015 Tcl_NewLongObj(
02016     register long longValue)    /* Long integer used to initialize the
02017                                  * new object. */
02018 {
02019     return Tcl_DbNewLongObj(longValue, "unknown", 0);
02020 }
02021 
02022 #else /* if not TCL_MEM_DEBUG */
02023 
02024 Tcl_Obj *
02025 Tcl_NewLongObj(
02026     register long longValue)    /* Long integer used to initialize the
02027                                  * new object. */
02028 {
02029     register Tcl_Obj *objPtr;
02030 
02031     TclNewLongObj(objPtr, longValue);
02032     return objPtr;
02033 }
02034 #endif /* if TCL_MEM_DEBUG */
02035 
02036 /*
02037  *----------------------------------------------------------------------
02038  *
02039  * Tcl_DbNewLongObj --
02040  *
02041  *      If a client is compiled with TCL_MEM_DEBUG defined, calls to
02042  *      Tcl_NewIntObj and Tcl_NewLongObj to create new integer or long integer
02043  *      objects end up calling the debugging function Tcl_DbNewLongObj
02044  *      instead. We provide two implementations of Tcl_DbNewLongObj so that
02045  *      whether the Tcl core is compiled to do memory debugging of the core is
02046  *      independent of whether a client requests debugging for itself.
02047  *
02048  *      When the core is compiled with TCL_MEM_DEBUG defined, Tcl_DbNewLongObj
02049  *      calls Tcl_DbCkalloc directly with the file name and line number from
02050  *      its caller. This simplifies debugging since then the [memory active]
02051  *      command will report the caller's file name and line number when
02052  *      reporting objects that haven't been freed.
02053  *
02054  *      Otherwise, when the core is compiled without TCL_MEM_DEBUG defined,
02055  *      this function just returns the result of calling Tcl_NewLongObj.
02056  *
02057  * Results:
02058  *      The newly created long integer object is returned. This object will
02059  *      have an invalid string representation. The returned object has ref
02060  *      count 0.
02061  *
02062  * Side effects:
02063  *      Allocates memory.
02064  *
02065  *----------------------------------------------------------------------
02066  */
02067 
02068 #ifdef TCL_MEM_DEBUG
02069 
02070 Tcl_Obj *
02071 Tcl_DbNewLongObj(
02072     register long longValue,    /* Long integer used to initialize the new
02073                                  * object. */
02074     CONST char *file,           /* The name of the source file calling this
02075                                  * function; used for debugging. */
02076     int line)                   /* Line number in the source file; used for
02077                                  * debugging. */
02078 {
02079     register Tcl_Obj *objPtr;
02080 
02081     TclDbNewObj(objPtr, file, line);
02082     objPtr->bytes = NULL;
02083 
02084     objPtr->internalRep.longValue = longValue;
02085     objPtr->typePtr = &tclIntType;
02086     return objPtr;
02087 }
02088 
02089 #else /* if not TCL_MEM_DEBUG */
02090 
02091 Tcl_Obj *
02092 Tcl_DbNewLongObj(
02093     register long longValue,    /* Long integer used to initialize the new
02094                                  * object. */
02095     CONST char *file,           /* The name of the source file calling this
02096                                  * function; used for debugging. */
02097     int line)                   /* Line number in the source file; used for
02098                                  * debugging. */
02099 {
02100     return Tcl_NewLongObj(longValue);
02101 }
02102 #endif /* TCL_MEM_DEBUG */
02103 
02104 /*
02105  *----------------------------------------------------------------------
02106  *
02107  * Tcl_SetLongObj --
02108  *
02109  *      Modify an object to be an integer object and to have the specified
02110  *      long integer value.
02111  *
02112  * Results:
02113  *      None.
02114  *
02115  * Side effects:
02116  *      The object's old string rep, if any, is freed. Also, any old internal
02117  *      rep is freed.
02118  *
02119  *----------------------------------------------------------------------
02120  */
02121 
02122 void
02123 Tcl_SetLongObj(
02124     register Tcl_Obj *objPtr,   /* Object whose internal rep to init. */
02125     register long longValue)    /* Long integer used to initialize the
02126                                  * object's value. */
02127 {
02128     if (Tcl_IsShared(objPtr)) {
02129         Tcl_Panic("%s called with shared object", "Tcl_SetLongObj");
02130     }
02131 
02132     TclSetLongObj(objPtr, longValue);
02133 }
02134 
02135 /*
02136  *----------------------------------------------------------------------
02137  *
02138  * Tcl_GetLongFromObj --
02139  *
02140  *      Attempt to return an long integer from the Tcl object "objPtr". If the
02141  *      object is not already an int object, an attempt will be made to
02142  *      convert it to one.
02143  *
02144  * Results:
02145  *      The return value is a standard Tcl object result. If an error occurs
02146  *      during conversion, an error message is left in the interpreter's
02147  *      result unless "interp" is NULL.
02148  *
02149  * Side effects:
02150  *      If the object is not already an int object, the conversion will free
02151  *      any old internal representation.
02152  *
02153  *----------------------------------------------------------------------
02154  */
02155 
02156 int
02157 Tcl_GetLongFromObj(
02158     Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
02159     register Tcl_Obj *objPtr,   /* The object from which to get a long. */
02160     register long *longPtr)     /* Place to store resulting long. */
02161 {
02162     do {
02163         if (objPtr->typePtr == &tclIntType) {
02164             *longPtr = objPtr->internalRep.longValue;
02165             return TCL_OK;
02166         }
02167 #ifndef NO_WIDE_TYPE
02168         if (objPtr->typePtr == &tclWideIntType) {
02169             /*
02170              * We return any integer in the range -ULONG_MAX to ULONG_MAX
02171              * converted to a long, ignoring overflow. The rule preserves
02172              * existing semantics for conversion of integers on input, but
02173              * avoids inadvertent demotion of wide integers to 32-bit ones in
02174              * the internal rep.
02175              */
02176 
02177             Tcl_WideInt w = objPtr->internalRep.wideValue;
02178             if (w >= -(Tcl_WideInt)(ULONG_MAX)
02179                     && w <= (Tcl_WideInt)(ULONG_MAX)) {
02180                 *longPtr = Tcl_WideAsLong(w);
02181                 return TCL_OK;
02182             }
02183             goto tooLarge;
02184         }
02185 #endif
02186         if (objPtr->typePtr == &tclDoubleType) {
02187             if (interp != NULL) {
02188                 Tcl_Obj *msg;
02189 
02190                 TclNewLiteralStringObj(msg, "expected integer but got \"");
02191                 Tcl_AppendObjToObj(msg, objPtr);
02192                 Tcl_AppendToObj(msg, "\"", -1);
02193                 Tcl_SetObjResult(interp, msg);
02194             }
02195             return TCL_ERROR;
02196         }
02197         if (objPtr->typePtr == &tclBignumType) {
02198             /*
02199              * Must check for those bignum values that can fit in a long, even
02200              * when auto-narrowing is enabled. Only those values in the signed
02201              * long range get auto-narrowed to tclIntType, while all the
02202              * values in the unsigned long range will fit in a long.
02203              */
02204 
02205             mp_int big;
02206 
02207             UNPACK_BIGNUM(objPtr, big);
02208             if ((size_t)(big.used) <= (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1)
02209                     / DIGIT_BIT) {
02210                 unsigned long value = 0, numBytes = sizeof(long);
02211                 long scratch;
02212                 unsigned char *bytes = (unsigned char *)&scratch;
02213                 if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
02214                     while (numBytes-- > 0) {
02215                         value = (value << CHAR_BIT) | *bytes++;
02216                     }
02217                     if (big.sign) {
02218                         *longPtr = - (long) value;
02219                     } else {
02220                         *longPtr = (long) value;
02221                     }
02222                     return TCL_OK;
02223                 }
02224             }
02225 #ifndef NO_WIDE_TYPE
02226         tooLarge:
02227 #endif
02228             if (interp != NULL) {
02229                 char *s = "integer value too large to represent";
02230                 Tcl_Obj *msg = Tcl_NewStringObj(s, -1);
02231 
02232                 Tcl_SetObjResult(interp, msg);
02233                 Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
02234             }
02235             return TCL_ERROR;
02236         }
02237     } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
02238             TCL_PARSE_INTEGER_ONLY)==TCL_OK);
02239     return TCL_ERROR;
02240 }
02241 #ifndef NO_WIDE_TYPE
02242 
02243 /*
02244  *----------------------------------------------------------------------
02245  *
02246  * UpdateStringOfWideInt --
02247  *
02248  *      Update the string representation for a wide integer object. Note: this
02249  *      function does not free an existing old string rep so storage will be
02250  *      lost if this has not already been done.
02251  *
02252  * Results:
02253  *      None.
02254  *
02255  * Side effects:
02256  *      The object's string is set to a valid string that results from the
02257  *      wideInt-to-string conversion.
02258  *
02259  *----------------------------------------------------------------------
02260  */
02261 
02262 static void
02263 UpdateStringOfWideInt(
02264     register Tcl_Obj *objPtr)   /* Int object whose string rep to update. */
02265 {
02266     char buffer[TCL_INTEGER_SPACE+2];
02267     register unsigned len;
02268     register Tcl_WideInt wideVal = objPtr->internalRep.wideValue;
02269 
02270     /*
02271      * Note that sprintf will generate a compiler warning under Mingw claiming
02272      * %I64 is an unknown format specifier. Just ignore this warning. We can't
02273      * use %L as the format specifier since that gets printed as a 32 bit
02274      * value.
02275      */
02276 
02277     sprintf(buffer, "%" TCL_LL_MODIFIER "d", wideVal);
02278     len = strlen(buffer);
02279     objPtr->bytes = ckalloc((unsigned) len + 1);
02280     memcpy(objPtr->bytes, buffer, len + 1);
02281     objPtr->length = len;
02282 }
02283 #endif /* !NO_WIDE_TYPE */
02284 
02285 /*
02286  *----------------------------------------------------------------------
02287  *
02288  * Tcl_NewWideIntObj --
02289  *
02290  *      If a client is compiled with TCL_MEM_DEBUG defined, calls to
02291  *      Tcl_NewWideIntObj to create a new 64-bit integer object end up calling
02292  *      the debugging function Tcl_DbNewWideIntObj instead.
02293  *
02294  *      Otherwise, if the client is compiled without TCL_MEM_DEBUG defined,
02295  *      calls to Tcl_NewWideIntObj result in a call to one of the two
02296  *      Tcl_NewWideIntObj implementations below. We provide two
02297  *      implementations so that the Tcl core can be compiled to do memory
02298  *      debugging of the core even if a client does not request it for itself.
02299  *
02300  * Results:
02301  *      The newly created object is returned. This object will have an invalid
02302  *      string representation. The returned object has ref count 0.
02303  *
02304  * Side effects:
02305  *      None.
02306  *
02307  *----------------------------------------------------------------------
02308  */
02309 
02310 #ifdef TCL_MEM_DEBUG
02311 #undef Tcl_NewWideIntObj
02312 
02313 Tcl_Obj *
02314 Tcl_NewWideIntObj(
02315     register Tcl_WideInt wideValue)
02316                                 /* Wide integer used to initialize the new
02317                                  * object. */
02318 {
02319     return Tcl_DbNewWideIntObj(wideValue, "unknown", 0);
02320 }
02321 
02322 #else /* if not TCL_MEM_DEBUG */
02323 
02324 Tcl_Obj *
02325 Tcl_NewWideIntObj(
02326     register Tcl_WideInt wideValue)
02327                                 /* Wide integer used to initialize the new
02328                                  * object. */
02329 {
02330     register Tcl_Obj *objPtr;
02331 
02332     TclNewObj(objPtr);
02333     Tcl_SetWideIntObj(objPtr, wideValue);
02334     return objPtr;
02335 }
02336 #endif /* if TCL_MEM_DEBUG */
02337 
02338 /*
02339  *----------------------------------------------------------------------
02340  *
02341  * Tcl_DbNewWideIntObj --
02342  *
02343  *      If a client is compiled with TCL_MEM_DEBUG defined, calls to
02344  *      Tcl_NewWideIntObj to create new wide integer end up calling the
02345  *      debugging function Tcl_DbNewWideIntObj instead. We provide two
02346  *      implementations of Tcl_DbNewWideIntObj so that whether the Tcl core is
02347  *      compiled to do memory debugging of the core is independent of whether
02348  *      a client requests debugging for itself.
02349  *
02350  *      When the core is compiled with TCL_MEM_DEBUG defined,
02351  *      Tcl_DbNewWideIntObj calls Tcl_DbCkalloc directly with the file name
02352  *      and line number from its caller. This simplifies debugging since then
02353  *      the checkmem command will report the caller's file name and line
02354  *      number when reporting objects that haven't been freed.
02355  *
02356  *      Otherwise, when the core is compiled without TCL_MEM_DEBUG defined,
02357  *      this function just returns the result of calling Tcl_NewWideIntObj.
02358  *
02359  * Results:
02360  *      The newly created wide integer object is returned. This object will
02361  *      have an invalid string representation. The returned object has ref
02362  *      count 0.
02363  *
02364  * Side effects:
02365  *      Allocates memory.
02366  *
02367  *----------------------------------------------------------------------
02368  */
02369 
02370 #ifdef TCL_MEM_DEBUG
02371 
02372 Tcl_Obj *
02373 Tcl_DbNewWideIntObj(
02374     register Tcl_WideInt wideValue,
02375                                 /* Wide integer used to initialize the new
02376                                  * object. */
02377     CONST char *file,           /* The name of the source file calling this
02378                                  * function; used for debugging. */
02379     int line)                   /* Line number in the source file; used for
02380                                  * debugging. */
02381 {
02382     register Tcl_Obj *objPtr;
02383 
02384     TclDbNewObj(objPtr, file, line);
02385     Tcl_SetWideIntObj(objPtr, wideValue);
02386     return objPtr;
02387 }
02388 
02389 #else /* if not TCL_MEM_DEBUG */
02390 
02391 Tcl_Obj *
02392 Tcl_DbNewWideIntObj(
02393     register Tcl_WideInt wideValue,
02394                                 /* Long integer used to initialize the new
02395                                  * object. */
02396     CONST char *file,           /* The name of the source file calling this
02397                                  * function; used for debugging. */
02398     int line)                   /* Line number in the source file; used for
02399                                  * debugging. */
02400 {
02401     return Tcl_NewWideIntObj(wideValue);
02402 }
02403 #endif /* TCL_MEM_DEBUG */
02404 
02405 /*
02406  *----------------------------------------------------------------------
02407  *
02408  * Tcl_SetWideIntObj --
02409  *
02410  *      Modify an object to be a wide integer object and to have the specified
02411  *      wide integer value.
02412  *
02413  * Results:
02414  *      None.
02415  *
02416  * Side effects:
02417  *      The object's old string rep, if any, is freed. Also, any old internal
02418  *      rep is freed.
02419  *
02420  *----------------------------------------------------------------------
02421  */
02422 
02423 void
02424 Tcl_SetWideIntObj(
02425     register Tcl_Obj *objPtr,   /* Object w. internal rep to init. */
02426     register Tcl_WideInt wideValue)
02427                                 /* Wide integer used to initialize the
02428                                  * object's value. */
02429 {
02430     if (Tcl_IsShared(objPtr)) {
02431         Tcl_Panic("%s called with shared object", "Tcl_SetWideIntObj");
02432     }
02433 
02434     if ((wideValue >= (Tcl_WideInt) LONG_MIN)
02435             && (wideValue <= (Tcl_WideInt) LONG_MAX)) {
02436         TclSetLongObj(objPtr, (long) wideValue);
02437     } else {
02438 #ifndef NO_WIDE_TYPE
02439         TclSetWideIntObj(objPtr, wideValue);
02440 #else
02441         mp_int big;
02442 
02443         TclBNInitBignumFromWideInt(&big, wideValue);
02444         Tcl_SetBignumObj(objPtr, &big);
02445 #endif
02446     }
02447 }
02448 
02449 /*
02450  *----------------------------------------------------------------------
02451  *
02452  * Tcl_GetWideIntFromObj --
02453  *
02454  *      Attempt to return a wide integer from the Tcl object "objPtr". If the
02455  *      object is not already a wide int object, an attempt will be made to
02456  *      convert it to one.
02457  *
02458  * Results:
02459  *      The return value is a standard Tcl object result. If an error occurs
02460  *      during conversion, an error message is left in the interpreter's
02461  *      result unless "interp" is NULL.
02462  *
02463  * Side effects:
02464  *      If the object is not already an int object, the conversion will free
02465  *      any old internal representation.
02466  *
02467  *----------------------------------------------------------------------
02468  */
02469 
02470 int
02471 Tcl_GetWideIntFromObj(
02472     Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
02473     register Tcl_Obj *objPtr,   /* Object from which to get a wide int. */
02474     register Tcl_WideInt *wideIntPtr)
02475                                 /* Place to store resulting long. */
02476 {
02477     do {
02478 #ifndef NO_WIDE_TYPE
02479         if (objPtr->typePtr == &tclWideIntType) {
02480             *wideIntPtr = objPtr->internalRep.wideValue;
02481             return TCL_OK;
02482         }
02483 #endif
02484         if (objPtr->typePtr == &tclIntType) {
02485             *wideIntPtr = (Tcl_WideInt) objPtr->internalRep.longValue;
02486             return TCL_OK;
02487         }
02488         if (objPtr->typePtr == &tclDoubleType) {
02489             if (interp != NULL) {
02490                 Tcl_Obj *msg;
02491 
02492                 TclNewLiteralStringObj(msg, "expected integer but got \"");
02493                 Tcl_AppendObjToObj(msg, objPtr);
02494                 Tcl_AppendToObj(msg, "\"", -1);
02495                 Tcl_SetObjResult(interp, msg);
02496             }
02497             return TCL_ERROR;
02498         }
02499         if (objPtr->typePtr == &tclBignumType) {
02500             /*
02501              * Must check for those bignum values that can fit in a
02502              * Tcl_WideInt, even when auto-narrowing is enabled.
02503              */
02504 
02505             mp_int big;
02506 
02507             UNPACK_BIGNUM(objPtr, big);
02508             if ((size_t)(big.used) <= (CHAR_BIT * sizeof(Tcl_WideInt)
02509                      + DIGIT_BIT - 1) / DIGIT_BIT) {
02510                 Tcl_WideUInt value = 0;
02511                 unsigned long numBytes = sizeof(Tcl_WideInt);
02512                 Tcl_WideInt scratch;
02513                 unsigned char *bytes = (unsigned char *) &scratch;
02514 
02515                 if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
02516                     while (numBytes-- > 0) {
02517                         value = (value << CHAR_BIT) | *bytes++;
02518                     }
02519                     if (big.sign) {
02520                         *wideIntPtr = - (Tcl_WideInt) value;
02521                     } else {
02522                         *wideIntPtr = (Tcl_WideInt) value;
02523                     }
02524                     return TCL_OK;
02525                 }
02526             }
02527             if (interp != NULL) {
02528                 char *s = "integer value too large to represent";
02529                 Tcl_Obj* msg = Tcl_NewStringObj(s, -1);
02530 
02531                 Tcl_SetObjResult(interp, msg);
02532                 Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
02533             }
02534             return TCL_ERROR;
02535         }
02536     } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
02537             TCL_PARSE_INTEGER_ONLY)==TCL_OK);
02538     return TCL_ERROR;
02539 }
02540 #ifndef NO_WIDE_TYPE
02541 
02542 /*
02543  *----------------------------------------------------------------------
02544  *
02545  * SetWideIntFromAny --
02546  *
02547  *      Attempts to force the internal representation for a Tcl object to
02548  *      tclWideIntType, specifically.
02549  *
02550  * Results:
02551  *      The return value is a standard object Tcl result. If an error occurs
02552  *      during conversion, an error message is left in the interpreter's
02553  *      result unless "interp" is NULL.
02554  *
02555  *----------------------------------------------------------------------
02556  */
02557 
02558 static int
02559 SetWideIntFromAny(
02560     Tcl_Interp *interp,         /* Tcl interpreter */
02561     Tcl_Obj *objPtr)            /* Pointer to the object to convert */
02562 {
02563     Tcl_WideInt w;
02564     return Tcl_GetWideIntFromObj(interp, objPtr, &w);
02565 }
02566 #endif /* !NO_WIDE_TYPE */
02567 
02568 /*
02569  *----------------------------------------------------------------------
02570  *
02571  * FreeBignum --
02572  *
02573  *      This function frees the internal rep of a bignum.
02574  *
02575  * Results:
02576  *      None.
02577  *
02578  *----------------------------------------------------------------------
02579  */
02580 
02581 static void
02582 FreeBignum(
02583     Tcl_Obj *objPtr)
02584 {
02585     mp_int toFree;              /* Bignum to free */
02586 
02587     UNPACK_BIGNUM(objPtr, toFree);
02588     mp_clear(&toFree);
02589     if ((long)(objPtr->internalRep.ptrAndLongRep.value) < 0) {
02590         ckfree((char *)objPtr->internalRep.ptrAndLongRep.ptr);
02591     }
02592 }
02593 
02594 /*
02595  *----------------------------------------------------------------------
02596  *
02597  * DupBignum --
02598  *
02599  *      This function duplicates the internal rep of a bignum.
02600  *
02601  * Results:
02602  *      None.
02603  *
02604  * Side effects:
02605  *      The destination object receies a copy of the source object
02606  *
02607  *----------------------------------------------------------------------
02608  */
02609 
02610 static void
02611 DupBignum(
02612     Tcl_Obj *srcPtr,
02613     Tcl_Obj *copyPtr)
02614 {
02615     mp_int bignumVal;
02616     mp_int bignumCopy;
02617 
02618     copyPtr->typePtr = &tclBignumType;
02619     UNPACK_BIGNUM(srcPtr, bignumVal);
02620     if (mp_init_copy(&bignumCopy, &bignumVal) != MP_OKAY) {
02621         Tcl_Panic("initialization failure in DupBignum");
02622     }
02623     PACK_BIGNUM(bignumCopy, copyPtr);
02624 }
02625 
02626 /*
02627  *----------------------------------------------------------------------
02628  *
02629  * UpdateStringOfBignum --
02630  *
02631  *      This function updates the string representation of a bignum object.
02632  *
02633  * Results:
02634  *      None.
02635  *
02636  * Side effects:
02637  *      The object's string is set to whatever results from the bignum-
02638  *      to-string conversion.
02639  *
02640  * The object's existing string representation is NOT freed; memory will leak
02641  * if the string rep is still valid at the time this function is called.
02642  *
02643  *----------------------------------------------------------------------
02644  */
02645 
02646 static void
02647 UpdateStringOfBignum(
02648     Tcl_Obj *objPtr)
02649 {
02650     mp_int bignumVal;
02651     int size;
02652     int status;
02653     char* stringVal;
02654 
02655     UNPACK_BIGNUM(objPtr, bignumVal);
02656     status = mp_radix_size(&bignumVal, 10, &size);
02657     if (status != MP_OKAY) {
02658         Tcl_Panic("radix size failure in UpdateStringOfBignum");
02659     }
02660     if (size == 3) {
02661         /*
02662          * mp_radix_size() returns 3 when more than INT_MAX bytes would be
02663          * needed to hold the string rep (because mp_radix_size ignores
02664          * integer overflow issues). When we know the string rep will be more
02665          * than 3, we can conclude the string rep would overflow our string
02666          * length limits.
02667          *
02668          * Note that so long as we enforce our bignums to the size that fits
02669          * in a packed bignum, this branch will never be taken.
02670          */
02671 
02672         Tcl_Panic("UpdateStringOfBignum: string length limit exceeded");
02673     }
02674     stringVal = ckalloc((size_t) size);
02675     status = mp_toradix_n(&bignumVal, stringVal, 10, size);
02676     if (status != MP_OKAY) {
02677         Tcl_Panic("conversion failure in UpdateStringOfBignum");
02678     }
02679     objPtr->bytes = stringVal;
02680     objPtr->length = size - 1;  /* size includes a trailing null byte */
02681 }
02682 
02683 /*
02684  *----------------------------------------------------------------------
02685  *
02686  * Tcl_NewBignumObj --
02687  *
02688  *      Creates an initializes a bignum object.
02689  *
02690  * Results:
02691  *      Returns the newly created object.
02692  *
02693  * Side effects:
02694  *      The bignum value is cleared, since ownership has transferred to Tcl.
02695  *
02696  *----------------------------------------------------------------------
02697  */
02698 
02699 #ifdef TCL_MEM_DEBUG
02700 #undef Tcl_NewBignumObj
02701 
02702 Tcl_Obj *
02703 Tcl_NewBignumObj(
02704     mp_int *bignumValue)
02705 {
02706     return Tcl_DbNewBignumObj(bignumValue, "unknown", 0);
02707 }
02708 #else
02709 Tcl_Obj *
02710 Tcl_NewBignumObj(
02711     mp_int *bignumValue)
02712 {
02713     Tcl_Obj* objPtr;
02714 
02715     TclNewObj(objPtr);
02716     Tcl_SetBignumObj(objPtr, bignumValue);
02717     return objPtr;
02718 }
02719 #endif
02720 
02721 /*
02722  *----------------------------------------------------------------------
02723  *
02724  * Tcl_DbNewBignumObj --
02725  *
02726  *      This function is normally called when debugging: that is, when
02727  *      TCL_MEM_DEBUG is defined. It constructs a bignum object, recording the
02728  *      creation point so that [memory active] can report it.
02729  *
02730  * Results:
02731  *      Returns the newly created object.
02732  *
02733  * Side effects:
02734  *      The bignum value is cleared, since ownership has transferred to Tcl.
02735  *
02736  *----------------------------------------------------------------------
02737  */
02738 
02739 #ifdef TCL_MEM_DEBUG
02740 Tcl_Obj *
02741 Tcl_DbNewBignumObj(
02742     mp_int *bignumValue,
02743     CONST char *file,
02744     int line)
02745 {
02746     Tcl_Obj *objPtr;
02747 
02748     TclDbNewObj(objPtr, file, line);
02749     Tcl_SetBignumObj(objPtr, bignumValue);
02750     return objPtr;
02751 }
02752 #else
02753 Tcl_Obj *
02754 Tcl_DbNewBignumObj(
02755     mp_int *bignumValue,
02756     CONST char *file,
02757     int line)
02758 {
02759     return Tcl_NewBignumObj(bignumValue);
02760 }
02761 #endif
02762 
02763 /*
02764  *----------------------------------------------------------------------
02765  *
02766  * GetBignumFromObj --
02767  *
02768  *      This function retrieves a 'bignum' value from a Tcl object, converting
02769  *      the object if necessary. Either copies or transfers the mp_int value
02770  *      depending on the copy flag value passed in.
02771  *
02772  * Results:
02773  *      Returns TCL_OK if the conversion is successful, TCL_ERROR otherwise.
02774  *
02775  * Side effects:
02776  *      A copy of bignum is stored in *bignumValue, which is expected to be
02777  *      uninitialized or cleared. If conversion fails, and the 'interp'
02778  *      argument is not NULL, an error message is stored in the interpreter
02779  *      result.
02780  *
02781  *----------------------------------------------------------------------
02782  */
02783 
02784 static int
02785 GetBignumFromObj(
02786     Tcl_Interp *interp,         /* Tcl interpreter for error reporting */
02787     Tcl_Obj *objPtr,            /* Object to read */
02788     int copy,                   /* Whether to copy the returned bignum value */
02789     mp_int *bignumValue)        /* Returned bignum value. */
02790 {
02791     do {
02792         if (objPtr->typePtr == &tclBignumType) {
02793             if (copy || Tcl_IsShared(objPtr)) {
02794                 mp_int temp;
02795                 UNPACK_BIGNUM(objPtr, temp);
02796                 mp_init_copy(bignumValue, &temp);
02797             } else {
02798                 UNPACK_BIGNUM(objPtr, *bignumValue);
02799                 objPtr->internalRep.ptrAndLongRep.ptr = NULL;
02800                 objPtr->internalRep.ptrAndLongRep.value = 0;
02801                 objPtr->typePtr = NULL;
02802                 if (objPtr->bytes == NULL) {
02803                     TclInitStringRep(objPtr, tclEmptyStringRep, 0);
02804                 }
02805             }
02806             return TCL_OK;
02807         }
02808         if (objPtr->typePtr == &tclIntType) {
02809             TclBNInitBignumFromLong(bignumValue, objPtr->internalRep.longValue);
02810             return TCL_OK;
02811         }
02812 #ifndef NO_WIDE_TYPE
02813         if (objPtr->typePtr == &tclWideIntType) {
02814             TclBNInitBignumFromWideInt(bignumValue,
02815                     objPtr->internalRep.wideValue);
02816             return TCL_OK;
02817         }
02818 #endif
02819         if (objPtr->typePtr == &tclDoubleType) {
02820             if (interp != NULL) {
02821                 Tcl_Obj *msg;
02822 
02823                 TclNewLiteralStringObj(msg, "expected integer but got \"");
02824                 Tcl_AppendObjToObj(msg, objPtr);
02825                 Tcl_AppendToObj(msg, "\"", -1);
02826                 Tcl_SetObjResult(interp, msg);
02827             }
02828             return TCL_ERROR;
02829         }
02830     } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
02831             TCL_PARSE_INTEGER_ONLY)==TCL_OK);
02832     return TCL_ERROR;
02833 }
02834 
02835 /*
02836  *----------------------------------------------------------------------
02837  *
02838  * Tcl_GetBignumFromObj --
02839  *
02840  *      This function retrieves a 'bignum' value from a Tcl object, converting
02841  *      the object if necessary.
02842  *
02843  * Results:
02844  *      Returns TCL_OK if the conversion is successful, TCL_ERROR otherwise.
02845  *
02846  * Side effects:
02847  *      A copy of bignum is stored in *bignumValue, which is expected to be
02848  *      uninitialized or cleared. If conversion fails, an the 'interp'
02849  *      argument is not NULL, an error message is stored in the interpreter
02850  *      result.
02851  *
02852  *      It is expected that the caller will NOT have invoked mp_init on the
02853  *      bignum value before passing it in. Tcl will initialize the mp_int as
02854  *      it sets the value. The value is a copy of the value in objPtr, so it
02855  *      becomes the responsibility of the caller to call mp_clear on it.
02856  *
02857  *----------------------------------------------------------------------
02858  */
02859 
02860 int
02861 Tcl_GetBignumFromObj(
02862     Tcl_Interp *interp,         /* Tcl interpreter for error reporting */
02863     Tcl_Obj *objPtr,            /* Object to read */
02864     mp_int *bignumValue)        /* Returned bignum value. */
02865 {
02866     return GetBignumFromObj(interp, objPtr, 1, bignumValue);
02867 }
02868 
02869 /*
02870  *----------------------------------------------------------------------
02871  *
02872  * Tcl_TakeBignumFromObj --
02873  *
02874  *      This function retrieves a 'bignum' value from a Tcl object, converting
02875  *      the object if necessary.
02876  *
02877  * Results:
02878  *      Returns TCL_OK if the conversion is successful, TCL_ERROR otherwise.
02879  *
02880  * Side effects:
02881  *      A copy of bignum is stored in *bignumValue, which is expected to be
02882  *      uninitialized or cleared. If conversion fails, an the 'interp'
02883  *      argument is not NULL, an error message is stored in the interpreter
02884  *      result.
02885  *
02886  *      It is expected that the caller will NOT have invoked mp_init on the
02887  *      bignum value before passing it in. Tcl will initialize the mp_int as
02888  *      it sets the value. The value is transferred from the internals of
02889  *      objPtr to the caller, passing responsibility of the caller to call
02890  *      mp_clear on it. The objPtr is cleared to hold an empty value.
02891  *
02892  *----------------------------------------------------------------------
02893  */
02894 
02895 int
02896 Tcl_TakeBignumFromObj(
02897     Tcl_Interp *interp,         /* Tcl interpreter for error reporting */
02898     Tcl_Obj *objPtr,            /* Object to read */
02899     mp_int *bignumValue)        /* Returned bignum value. */
02900 {
02901     return GetBignumFromObj(interp, objPtr, 0, bignumValue);
02902 }
02903 
02904 /*
02905  *----------------------------------------------------------------------
02906  *
02907  * Tcl_SetBignumObj --
02908  *
02909  *      This function sets the value of a Tcl_Obj to a large integer.
02910  *
02911  * Results:
02912  *      None.
02913  *
02914  * Side effects:
02915  *      Object value is stored. The bignum value is cleared, since ownership
02916  *      has transferred to Tcl.
02917  *
02918  *----------------------------------------------------------------------
02919  */
02920 
02921 void
02922 Tcl_SetBignumObj(
02923     Tcl_Obj *objPtr,            /* Object to set */
02924     mp_int *bignumValue)        /* Value to store */
02925 {
02926     if (Tcl_IsShared(objPtr)) {
02927         Tcl_Panic("%s called with shared object", "Tcl_SetBignumObj");
02928     }
02929     if ((size_t)(bignumValue->used)
02930             <= (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1) / DIGIT_BIT) {
02931         unsigned long value = 0, numBytes = sizeof(long);
02932         long scratch;
02933         unsigned char *bytes = (unsigned char *)&scratch;
02934         if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
02935             goto tooLargeForLong;
02936         }
02937         while (numBytes-- > 0) {
02938             value = (value << CHAR_BIT) | *bytes++;
02939         }
02940         if (value > (((~(unsigned long)0) >> 1) + bignumValue->sign)) {
02941             goto tooLargeForLong;
02942         }
02943         if (bignumValue->sign) {
02944             TclSetLongObj(objPtr, -(long)value);
02945         } else {
02946             TclSetLongObj(objPtr, (long)value);
02947         }
02948         mp_clear(bignumValue);
02949         return;
02950     }
02951   tooLargeForLong:
02952 #ifndef NO_WIDE_TYPE
02953     if ((size_t)(bignumValue->used)
02954             <= (CHAR_BIT * sizeof(Tcl_WideInt) + DIGIT_BIT - 1) / DIGIT_BIT) {
02955         Tcl_WideUInt value = 0;
02956         unsigned long numBytes = sizeof(Tcl_WideInt);
02957         Tcl_WideInt scratch;
02958         unsigned char *bytes = (unsigned char *)&scratch;
02959         if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
02960             goto tooLargeForWide;
02961         }
02962         while (numBytes-- > 0) {
02963             value = (value << CHAR_BIT) | *bytes++;
02964         }
02965         if (value > (((~(Tcl_WideUInt)0) >> 1) + bignumValue->sign)) {
02966             goto tooLargeForWide;
02967         }
02968         if (bignumValue->sign) {
02969             TclSetWideIntObj(objPtr, -(Tcl_WideInt)value);
02970         } else {
02971             TclSetWideIntObj(objPtr, (Tcl_WideInt)value);
02972         }
02973         mp_clear(bignumValue);
02974         return;
02975     }
02976   tooLargeForWide:
02977 #endif
02978     TclInvalidateStringRep(objPtr);
02979     TclFreeIntRep(objPtr);
02980     TclSetBignumIntRep(objPtr, bignumValue);
02981 }
02982 
02983 void
02984 TclSetBignumIntRep(
02985     Tcl_Obj *objPtr,
02986     mp_int *bignumValue)
02987 {
02988     objPtr->typePtr = &tclBignumType;
02989     PACK_BIGNUM(*bignumValue, objPtr);
02990 
02991     /*
02992      * Clear the mp_int value.
02993      * Don't call mp_clear() because it would free the digit array
02994      * we just packed into the Tcl_Obj.
02995      */
02996 
02997     bignumValue->dp = NULL;
02998     bignumValue->alloc = bignumValue->used = 0;
02999     bignumValue->sign = MP_NEG;
03000 }
03001 
03002 /*
03003  *----------------------------------------------------------------------
03004  *
03005  * TclGetNumberFromObj --
03006  *
03007  * Results:
03008  *
03009  * Side effects:
03010  *
03011  *----------------------------------------------------------------------
03012  */
03013 
03014 int TclGetNumberFromObj(
03015     Tcl_Interp *interp,
03016     Tcl_Obj *objPtr,
03017     ClientData *clientDataPtr,
03018     int *typePtr)
03019 {
03020     do {
03021         if (objPtr->typePtr == &tclDoubleType) {
03022             if (TclIsNaN(objPtr->internalRep.doubleValue)) {
03023                 *typePtr = TCL_NUMBER_NAN;
03024             } else {
03025                 *typePtr = TCL_NUMBER_DOUBLE;
03026             }
03027             *clientDataPtr = &(objPtr->internalRep.doubleValue);
03028             return TCL_OK;
03029         }
03030         if (objPtr->typePtr == &tclIntType) {
03031             *typePtr = TCL_NUMBER_LONG;
03032             *clientDataPtr = &(objPtr->internalRep.longValue);
03033             return TCL_OK;
03034         }
03035 #ifndef NO_WIDE_TYPE
03036         if (objPtr->typePtr == &tclWideIntType) {
03037             *typePtr = TCL_NUMBER_WIDE;
03038             *clientDataPtr = &(objPtr->internalRep.wideValue);
03039             return TCL_OK;
03040         }
03041 #endif
03042         if (objPtr->typePtr == &tclBignumType) {
03043             static Tcl_ThreadDataKey bignumKey;
03044             mp_int *bigPtr = Tcl_GetThreadData(&bignumKey,
03045                     (int) sizeof(mp_int));
03046             UNPACK_BIGNUM( objPtr, *bigPtr );
03047             *typePtr = TCL_NUMBER_BIG;
03048             *clientDataPtr = bigPtr;
03049             return TCL_OK;
03050         }
03051     } while (TCL_OK ==
03052             TclParseNumber(interp, objPtr, "number", NULL, -1, NULL, 0));
03053     return TCL_ERROR;
03054 }
03055 
03056 /*
03057  *----------------------------------------------------------------------
03058  *
03059  * Tcl_DbIncrRefCount --
03060  *
03061  *      This function is normally called when debugging: i.e., when
03062  *      TCL_MEM_DEBUG is defined. This checks to see whether or not the memory
03063  *      has been freed before incrementing the ref count.
03064  *
03065  *      When TCL_MEM_DEBUG is not defined, this function just increments the
03066  *      reference count of the object.
03067  *
03068  * Results:
03069  *      None.
03070  *
03071  * Side effects:
03072  *      The object's ref count is incremented.
03073  *
03074  *----------------------------------------------------------------------
03075  */
03076 
03077 void
03078 Tcl_DbIncrRefCount(
03079     register Tcl_Obj *objPtr,   /* The object we are registering a reference
03080                                  * to. */
03081     CONST char *file,           /* The name of the source file calling this
03082                                  * function; used for debugging. */
03083     int line)                   /* Line number in the source file; used for
03084                                  * debugging. */
03085 {
03086 #ifdef TCL_MEM_DEBUG
03087     if (objPtr->refCount == 0x61616161) {
03088         fprintf(stderr, "file = %s, line = %d\n", file, line);
03089         fflush(stderr);
03090         Tcl_Panic("incrementing refCount of previously disposed object");
03091     }
03092 
03093 # ifdef TCL_THREADS
03094     /*
03095      * Check to make sure that the Tcl_Obj was allocated by the current
03096      * thread. Don't do this check when shutting down since thread local
03097      * storage can be finalized before the last Tcl_Obj is freed.
03098      */
03099 
03100     if (!TclInExit()) {
03101         Tcl_HashTable *tablePtr;
03102         Tcl_HashEntry *hPtr;
03103         ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
03104 
03105         tablePtr = tsdPtr->objThreadMap;
03106         if (!tablePtr) {
03107             Tcl_Panic("object table not initialized");
03108         }
03109         hPtr = Tcl_FindHashEntry(tablePtr, (char *) objPtr);
03110         if (!hPtr) {
03111             Tcl_Panic("%s%s",
03112                     "Trying to incr ref count of "
03113                     "Tcl_Obj allocated in another thread");
03114         }
03115     }
03116 # endif
03117 #endif
03118     ++(objPtr)->refCount;
03119 }
03120 
03121 /*
03122  *----------------------------------------------------------------------
03123  *
03124  * Tcl_DbDecrRefCount --
03125  *
03126  *      This function is normally called when debugging: i.e., when
03127  *      TCL_MEM_DEBUG is defined. This checks to see whether or not the memory
03128  *      has been freed before decrementing the ref count.
03129  *
03130  *      When TCL_MEM_DEBUG is not defined, this function just decrements the
03131  *      reference count of the object.
03132  *
03133  * Results:
03134  *      None.
03135  *
03136  * Side effects:
03137  *      The object's ref count is incremented.
03138  *
03139  *----------------------------------------------------------------------
03140  */
03141 
03142 void
03143 Tcl_DbDecrRefCount(
03144     register Tcl_Obj *objPtr,   /* The object we are releasing a reference
03145                                  * to. */
03146     CONST char *file,           /* The name of the source file calling this
03147                                  * function; used for debugging. */
03148     int line)                   /* Line number in the source file; used for
03149                                  * debugging. */
03150 {
03151 #ifdef TCL_MEM_DEBUG
03152     if (objPtr->refCount == 0x61616161) {
03153         fprintf(stderr, "file = %s, line = %d\n", file, line);
03154         fflush(stderr);
03155         Tcl_Panic("decrementing refCount of previously disposed object");
03156     }
03157 
03158 # ifdef TCL_THREADS
03159     /*
03160      * Check to make sure that the Tcl_Obj was allocated by the current
03161      * thread. Don't do this check when shutting down since thread local
03162      * storage can be finalized before the last Tcl_Obj is freed.
03163      */
03164 
03165     if (!TclInExit()) {
03166         Tcl_HashTable *tablePtr;
03167         Tcl_HashEntry *hPtr;
03168         ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
03169 
03170         tablePtr = tsdPtr->objThreadMap;
03171         if (!tablePtr) {
03172             Tcl_Panic("object table not initialized");
03173         }
03174         hPtr = Tcl_FindHashEntry(tablePtr, (char *) objPtr);
03175         if (!hPtr) {
03176             Tcl_Panic("%s%s",
03177                     "Trying to decr ref count of "
03178                     "Tcl_Obj allocated in another thread");
03179         }
03180 
03181         /* If the Tcl_Obj is going to be deleted, remove the entry */
03182         if ((((objPtr)->refCount) - 1) <= 0) {
03183             Tcl_DeleteHashEntry(hPtr);
03184         }
03185     }
03186 # endif
03187 #endif
03188     if (--(objPtr)->refCount <= 0) {
03189         TclFreeObj(objPtr);
03190     }
03191 }
03192 
03193 /*
03194  *----------------------------------------------------------------------
03195  *
03196  * Tcl_DbIsShared --
03197  *
03198  *      This function is normally called when debugging: i.e., when
03199  *      TCL_MEM_DEBUG is defined. It tests whether the object has a ref count
03200  *      greater than one.
03201  *
03202  *      When TCL_MEM_DEBUG is not defined, this function just tests if the
03203  *      object has a ref count greater than one.
03204  *
03205  * Results:
03206  *      None.
03207  *
03208  * Side effects:
03209  *      None.
03210  *
03211  *----------------------------------------------------------------------
03212  */
03213 
03214 int
03215 Tcl_DbIsShared(
03216     register Tcl_Obj *objPtr,   /* The object to test for being shared. */
03217     CONST char *file,           /* The name of the source file calling this
03218                                  * function; used for debugging. */
03219     int line)                   /* Line number in the source file; used for
03220                                  * debugging. */
03221 {
03222 #ifdef TCL_MEM_DEBUG
03223     if (objPtr->refCount == 0x61616161) {
03224         fprintf(stderr, "file = %s, line = %d\n", file, line);
03225         fflush(stderr);
03226         Tcl_Panic("checking whether previously disposed object is shared");
03227     }
03228 
03229 # ifdef TCL_THREADS
03230     /*
03231      * Check to make sure that the Tcl_Obj was allocated by the current
03232      * thread. Don't do this check when shutting down since thread local
03233      * storage can be finalized before the last Tcl_Obj is freed.
03234      */
03235 
03236     if (!TclInExit()) {
03237         Tcl_HashTable *tablePtr;
03238         Tcl_HashEntry *hPtr;
03239         ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
03240         tablePtr = tsdPtr->objThreadMap;
03241         if (!tablePtr) {
03242             Tcl_Panic("object table not initialized");
03243         }
03244         hPtr = Tcl_FindHashEntry(tablePtr, (char *) objPtr);
03245         if (!hPtr) {
03246             Tcl_Panic("%s%s",
03247                     "Trying to check shared status of"
03248                     "Tcl_Obj allocated in another thread");
03249         }
03250     }
03251 # endif
03252 #endif
03253 
03254 #ifdef TCL_COMPILE_STATS
03255     Tcl_MutexLock(&tclObjMutex);
03256     if ((objPtr)->refCount <= 1) {
03257         tclObjsShared[1]++;
03258     } else if ((objPtr)->refCount < TCL_MAX_SHARED_OBJ_STATS) {
03259         tclObjsShared[(objPtr)->refCount]++;
03260     } else {
03261         tclObjsShared[0]++;
03262     }
03263     Tcl_MutexUnlock(&tclObjMutex);
03264 #endif
03265 
03266     return ((objPtr)->refCount > 1);
03267 }
03268 
03269 /*
03270  *----------------------------------------------------------------------
03271  *
03272  * Tcl_InitObjHashTable --
03273  *
03274  *      Given storage for a hash table, set up the fields to prepare the hash
03275  *      table for use, the keys are Tcl_Obj *.
03276  *
03277  * Results:
03278  *      None.
03279  *
03280  * Side effects:
03281  *      TablePtr is now ready to be passed to Tcl_FindHashEntry and
03282  *      Tcl_CreateHashEntry.
03283  *
03284  *----------------------------------------------------------------------
03285  */
03286 
03287 void
03288 Tcl_InitObjHashTable(
03289     register Tcl_HashTable *tablePtr)
03290                                 /* Pointer to table record, which is supplied
03291                                  * by the caller. */
03292 {
03293     Tcl_InitCustomHashTable(tablePtr, TCL_CUSTOM_PTR_KEYS,
03294             &tclObjHashKeyType);
03295 }
03296 
03297 /*
03298  *----------------------------------------------------------------------
03299  *
03300  * AllocObjEntry --
03301  *
03302  *      Allocate space for a Tcl_HashEntry containing the Tcl_Obj * key.
03303  *
03304  * Results:
03305  *      The return value is a pointer to the created entry.
03306  *
03307  * Side effects:
03308  *      Increments the reference count on the object.
03309  *
03310  *----------------------------------------------------------------------
03311  */
03312 
03313 static Tcl_HashEntry *
03314 AllocObjEntry(
03315     Tcl_HashTable *tablePtr,    /* Hash table. */
03316     void *keyPtr)               /* Key to store in the hash table entry. */
03317 {
03318     Tcl_Obj *objPtr = (Tcl_Obj *) keyPtr;
03319     Tcl_HashEntry *hPtr;
03320 
03321     hPtr = (Tcl_HashEntry *) ckalloc((unsigned) (sizeof(Tcl_HashEntry)));
03322     hPtr->key.oneWordValue = (char *) objPtr;
03323     Tcl_IncrRefCount(objPtr);
03324     hPtr->clientData = NULL;
03325 
03326     return hPtr;
03327 }
03328 
03329 /*
03330  *----------------------------------------------------------------------
03331  *
03332  * TclCompareObjKeys --
03333  *
03334  *      Compares two Tcl_Obj * keys.
03335  *
03336  * Results:
03337  *      The return value is 0 if they are different and 1 if they are the
03338  *      same.
03339  *
03340  * Side effects:
03341  *      None.
03342  *
03343  *----------------------------------------------------------------------
03344  */
03345 
03346 int
03347 TclCompareObjKeys(
03348     void *keyPtr,               /* New key to compare. */
03349     Tcl_HashEntry *hPtr)        /* Existing key to compare. */
03350 {
03351     Tcl_Obj *objPtr1 = (Tcl_Obj *) keyPtr;
03352     Tcl_Obj *objPtr2 = (Tcl_Obj *) hPtr->key.oneWordValue;
03353     register CONST char *p1, *p2;
03354     register int l1, l2;
03355 
03356     /*
03357      * If the object pointers are the same then they match.
03358      */
03359 
03360     if (objPtr1 == objPtr2) {
03361         return 1;
03362     }
03363 
03364     /*
03365      * Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being
03366      * in a register.
03367      */
03368 
03369     p1 = TclGetString(objPtr1);
03370     l1 = objPtr1->length;
03371     p2 = TclGetString(objPtr2);
03372     l2 = objPtr2->length;
03373 
03374     /*
03375      * Only compare if the string representations are of the same length.
03376      */
03377 
03378     if (l1 == l2) {
03379         for (;; p1++, p2++, l1--) {
03380             if (*p1 != *p2) {
03381                 break;
03382             }
03383             if (l1 == 0) {
03384                 return 1;
03385             }
03386         }
03387     }
03388 
03389     return 0;
03390 }
03391 
03392 /*
03393  *----------------------------------------------------------------------
03394  *
03395  * TclFreeObjEntry --
03396  *
03397  *      Frees space for a Tcl_HashEntry containing the Tcl_Obj * key.
03398  *
03399  * Results:
03400  *      The return value is a pointer to the created entry.
03401  *
03402  * Side effects:
03403  *      Decrements the reference count of the object.
03404  *
03405  *----------------------------------------------------------------------
03406  */
03407 
03408 void
03409 TclFreeObjEntry(
03410     Tcl_HashEntry *hPtr)        /* Hash entry to free. */
03411 {
03412     Tcl_Obj *objPtr = (Tcl_Obj *) hPtr->key.oneWordValue;
03413 
03414     Tcl_DecrRefCount(objPtr);
03415     ckfree((char *) hPtr);
03416 }
03417 
03418 /*
03419  *----------------------------------------------------------------------
03420  *
03421  * TclHashObjKey --
03422  *
03423  *      Compute a one-word summary of the string representation of the
03424  *      Tcl_Obj, which can be used to generate a hash index.
03425  *
03426  * Results:
03427  *      The return value is a one-word summary of the information in the
03428  *      string representation of the Tcl_Obj.
03429  *
03430  * Side effects:
03431  *      None.
03432  *
03433  *----------------------------------------------------------------------
03434  */
03435 
03436 unsigned int
03437 TclHashObjKey(
03438     Tcl_HashTable *tablePtr,    /* Hash table. */
03439     void *keyPtr)               /* Key from which to compute hash value. */
03440 {
03441     Tcl_Obj *objPtr = (Tcl_Obj *) keyPtr;
03442     CONST char *string = TclGetString(objPtr);
03443     int length = objPtr->length;
03444     unsigned int result = 0;
03445     int i;
03446 
03447     /*
03448      * I tried a zillion different hash functions and asked many other people
03449      * for advice. Many people had their own favorite functions, all
03450      * different, but no-one had much idea why they were good ones. I chose
03451      * the one below (multiply by 9 and add new character) because of the
03452      * following reasons:
03453      *
03454      * 1. Multiplying by 10 is perfect for keys that are decimal strings, and
03455      *    multiplying by 9 is just about as good.
03456      * 2. Times-9 is (shift-left-3) plus (old). This means that each
03457      *    character's bits hang around in the low-order bits of the hash value
03458      *    for ever, plus they spread fairly rapidly up to the high-order bits
03459      *    to fill out the hash value. This seems works well both for decimal
03460      *    and *non-decimal strings.
03461      */
03462 
03463     for (i=0 ; i<length ; i++) {
03464         result += (result << 3) + string[i];
03465     }
03466     return result;
03467 }
03468 
03469 /*
03470  *----------------------------------------------------------------------
03471  *
03472  * Tcl_GetCommandFromObj --
03473  *
03474  *      Returns the command specified by the name in a Tcl_Obj.
03475  *
03476  * Results:
03477  *      Returns a token for the command if it is found. Otherwise, if it can't
03478  *      be found or there is an error, returns NULL.
03479  *
03480  * Side effects:
03481  *      May update the internal representation for the object, caching the
03482  *      command reference so that the next time this function is called with
03483  *      the same object, the command can be found quickly.
03484  *
03485  *----------------------------------------------------------------------
03486  */
03487 
03488 Tcl_Command
03489 Tcl_GetCommandFromObj(
03490     Tcl_Interp *interp,         /* The interpreter in which to resolve the
03491                                  * command and to report errors. */
03492     register Tcl_Obj *objPtr)   /* The object containing the command's name.
03493                                  * If the name starts with "::", will be
03494                                  * looked up in global namespace. Else, looked
03495                                  * up first in the current namespace, then in
03496                                  * global namespace. */
03497 {
03498     register ResolvedCmdName *resPtr;
03499     register Command *cmdPtr;
03500     Namespace *refNsPtr;
03501     int result;
03502 
03503     /*
03504      * Get the internal representation, converting to a command type if
03505      * needed. The internal representation is a ResolvedCmdName that points to
03506      * the actual command.
03507      *
03508      * Check the context namespace and the namespace epoch of the resolved
03509      * symbol to make sure that it is fresh. Note that we verify that the
03510      * namespace id of the context namespace is the same as the one we cached;
03511      * this insures that the namespace wasn't deleted and a new one created at
03512      * the same address with the same command epoch. Note that fully qualified
03513      * names have a NULL refNsPtr, these checks needn't be made.
03514      *
03515      * Check also that the command's epoch is up to date, and that the command
03516      * is not deleted.
03517      *
03518      * If any check fails, then force another conversion to the command type,
03519      * to discard the old rep and create a new one.      
03520      */
03521 
03522     resPtr = (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
03523     if ((objPtr->typePtr != &tclCmdNameType)
03524             || (resPtr == NULL)
03525             || (cmdPtr = resPtr->cmdPtr, cmdPtr->cmdEpoch != resPtr->cmdEpoch)
03526             || (interp != cmdPtr->nsPtr->interp)
03527             || (cmdPtr->flags & CMD_IS_DELETED)
03528             || ((resPtr->refNsPtr != NULL) && 
03529                      (((refNsPtr = (Namespace *) TclGetCurrentNamespace(interp))
03530                              != resPtr->refNsPtr)
03531                      || (resPtr->refNsId != refNsPtr->nsId)
03532                      || (resPtr->refNsCmdEpoch != refNsPtr->cmdRefEpoch)))
03533         ) {
03534         
03535         result = tclCmdNameType.setFromAnyProc(interp, objPtr);
03536         
03537         resPtr = (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
03538         if ((result == TCL_OK) && resPtr) {
03539             cmdPtr = resPtr->cmdPtr;
03540         } else {
03541             cmdPtr = NULL;
03542         }
03543     }
03544     
03545     return (Tcl_Command) cmdPtr;
03546 }
03547 
03548 /*
03549  *----------------------------------------------------------------------
03550  *
03551  * TclSetCmdNameObj --
03552  *
03553  *      Modify an object to be an CmdName object that refers to the argument
03554  *      Command structure.
03555  *
03556  * Results:
03557  *      None.
03558  *
03559  * Side effects:
03560  *      The object's old internal rep is freed. It's string rep is not
03561  *      changed. The refcount in the Command structure is incremented to keep
03562  *      it from being freed if the command is later deleted until
03563  *      TclExecuteByteCode has a chance to recognize that it was deleted.
03564  *
03565  *----------------------------------------------------------------------
03566  */
03567 
03568 void
03569 TclSetCmdNameObj(
03570     Tcl_Interp *interp,         /* Points to interpreter containing command
03571                                  * that should be cached in objPtr. */
03572     register Tcl_Obj *objPtr,   /* Points to Tcl object to be changed to a
03573                                  * CmdName object. */
03574     Command *cmdPtr)            /* Points to Command structure that the
03575                                  * CmdName object should refer to. */
03576 {
03577     Interp *iPtr = (Interp *) interp;
03578     register ResolvedCmdName *resPtr;
03579     register Namespace *currNsPtr;
03580     char *name;
03581 
03582     if (objPtr->typePtr == &tclCmdNameType) {
03583         return;
03584     }
03585 
03586     cmdPtr->refCount++;
03587     resPtr = (ResolvedCmdName *) ckalloc(sizeof(ResolvedCmdName));
03588     resPtr->cmdPtr = cmdPtr;
03589     resPtr->cmdEpoch = cmdPtr->cmdEpoch;
03590     resPtr->refCount = 1;
03591 
03592     name = TclGetString(objPtr);
03593     if ((*name++ == ':') && (*name == ':')) {
03594         /*
03595          * The name is fully qualified: set the referring namespace to
03596          * NULL. 
03597          */
03598 
03599         resPtr->refNsPtr = NULL;
03600     } else {
03601         /*
03602          * Get the current namespace.
03603          */
03604 
03605         currNsPtr = iPtr->varFramePtr->nsPtr;
03606         
03607         resPtr->refNsPtr = currNsPtr;
03608         resPtr->refNsId = currNsPtr->nsId;
03609         resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
03610     }
03611 
03612     TclFreeIntRep(objPtr);
03613     objPtr->internalRep.twoPtrValue.ptr1 = (void *) resPtr;
03614     objPtr->internalRep.twoPtrValue.ptr2 = NULL;
03615     objPtr->typePtr = &tclCmdNameType;
03616 }
03617 
03618 /*
03619  *----------------------------------------------------------------------
03620  *
03621  * FreeCmdNameInternalRep --
03622  *
03623  *      Frees the resources associated with a cmdName object's internal
03624  *      representation.
03625  *
03626  * Results:
03627  *      None.
03628  *
03629  * Side effects:
03630  *      Decrements the ref count of any cached ResolvedCmdName structure
03631  *      pointed to by the cmdName's internal representation. If this is the
03632  *      last use of the ResolvedCmdName, it is freed. This in turn decrements
03633  *      the ref count of the Command structure pointed to by the
03634  *      ResolvedSymbol, which may free the Command structure.
03635  *
03636  *----------------------------------------------------------------------
03637  */
03638 
03639 static void
03640 FreeCmdNameInternalRep(
03641     register Tcl_Obj *objPtr)   /* CmdName object with internal
03642                                  * representation to free. */
03643 {
03644     register ResolvedCmdName *resPtr =
03645         (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
03646 
03647     if (resPtr != NULL) {
03648         /*
03649          * Decrement the reference count of the ResolvedCmdName structure. If
03650          * there are no more uses, free the ResolvedCmdName structure.
03651          */
03652 
03653         resPtr->refCount--;
03654         if (resPtr->refCount == 0) {
03655             /*
03656              * Now free the cached command, unless it is still in its hash
03657              * table or if there are other references to it from other cmdName
03658              * objects.
03659              */
03660 
03661             Command *cmdPtr = resPtr->cmdPtr;
03662             TclCleanupCommandMacro(cmdPtr);
03663             ckfree((char *) resPtr);
03664         }
03665     }
03666 }
03667 
03668 /*
03669  *----------------------------------------------------------------------
03670  *
03671  * DupCmdNameInternalRep --
03672  *
03673  *      Initialize the internal representation of an cmdName Tcl_Obj to a copy
03674  *      of the internal representation of an existing cmdName object.
03675  *
03676  * Results:
03677  *      None.
03678  *
03679  * Side effects:
03680  *      "copyPtr"s internal rep is set to point to the ResolvedCmdName
03681  *      structure corresponding to "srcPtr"s internal rep. Increments the ref
03682  *      count of the ResolvedCmdName structure pointed to by the cmdName's
03683  *      internal representation.
03684  *
03685  *----------------------------------------------------------------------
03686  */
03687 
03688 static void
03689 DupCmdNameInternalRep(
03690     Tcl_Obj *srcPtr,            /* Object with internal rep to copy. */
03691     register Tcl_Obj *copyPtr)  /* Object with internal rep to set. */
03692 {
03693     register ResolvedCmdName *resPtr = (ResolvedCmdName *)
03694             srcPtr->internalRep.twoPtrValue.ptr1;
03695 
03696     copyPtr->internalRep.twoPtrValue.ptr1 = (void *) resPtr;
03697     copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
03698     if (resPtr != NULL) {
03699         resPtr->refCount++;
03700     }
03701     copyPtr->typePtr = &tclCmdNameType;
03702 }
03703 
03704 /*
03705  *----------------------------------------------------------------------
03706  *
03707  * SetCmdNameFromAny --
03708  *
03709  *      Generate an cmdName internal form for the Tcl object "objPtr".
03710  *
03711  * Results:
03712  *      The return value is a standard Tcl result. The conversion always
03713  *      succeeds and TCL_OK is returned.
03714  *
03715  * Side effects:
03716  *      A pointer to a ResolvedCmdName structure that holds a cached pointer
03717  *      to the command with a name that matches objPtr's string rep is stored
03718  *      as objPtr's internal representation. This ResolvedCmdName pointer will
03719  *      be NULL if no matching command was found. The ref count of the cached
03720  *      Command's structure (if any) is also incremented.
03721  *
03722  *----------------------------------------------------------------------
03723  */
03724 
03725 static int
03726 SetCmdNameFromAny(
03727     Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
03728     register Tcl_Obj *objPtr)   /* The object to convert. */
03729 {
03730     Interp *iPtr = (Interp *) interp;
03731     char *name;
03732     register Command *cmdPtr;
03733     Namespace *currNsPtr;
03734     register ResolvedCmdName *resPtr;
03735 
03736     /*
03737      * Find the Command structure, if any, that describes the command called
03738      * "name". Build a ResolvedCmdName that holds a cached pointer to this
03739      * Command, and bump the reference count in the referenced Command
03740      * structure. A Command structure will not be deleted as long as it is
03741      * referenced from a CmdName object.
03742      */
03743 
03744     name = TclGetString(objPtr);
03745     cmdPtr = (Command *) Tcl_FindCommand(interp, name, /*ns*/ NULL, /*flags*/ 0);
03746 
03747     /*
03748      * Free the old internalRep before setting the new one. Do this after
03749      * getting the string rep to allow the conversion code (in particular,
03750      * Tcl_GetStringFromObj) to use that old internalRep.
03751      */
03752 
03753     if (cmdPtr) {
03754         cmdPtr->refCount++;
03755         resPtr = (ResolvedCmdName *) objPtr->internalRep.otherValuePtr;
03756         if ((objPtr->typePtr == &tclCmdNameType)
03757                 && resPtr && (resPtr->refCount == 1)) {
03758             /*
03759              * Reuse the old ResolvedCmdName struct instead of freeing it
03760              */
03761             
03762             Command *oldCmdPtr = resPtr->cmdPtr;
03763             if (--oldCmdPtr->refCount == 0) {
03764                 TclCleanupCommandMacro(oldCmdPtr);
03765             }
03766         } else {
03767             TclFreeIntRep(objPtr);
03768             resPtr = (ResolvedCmdName *) ckalloc(sizeof(ResolvedCmdName));
03769             resPtr->refCount = 1;
03770             objPtr->internalRep.twoPtrValue.ptr1 = (void *) resPtr;
03771             objPtr->internalRep.twoPtrValue.ptr2 = NULL;
03772             objPtr->typePtr = &tclCmdNameType;
03773         }
03774         resPtr->cmdPtr = cmdPtr;
03775         resPtr->cmdEpoch = cmdPtr->cmdEpoch;
03776         if ((*name++ == ':') && (*name == ':')) {
03777             /*
03778              * The name is fully qualified: set the referring namespace to 
03779              * NULL. 
03780              */
03781 
03782             resPtr->refNsPtr = NULL;
03783         } else {
03784             /*
03785              * Get the current namespace.
03786              */
03787 
03788             currNsPtr = iPtr->varFramePtr->nsPtr;
03789             
03790             resPtr->refNsPtr = currNsPtr;
03791             resPtr->refNsId = currNsPtr->nsId;
03792             resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
03793         }
03794     } else {
03795         TclFreeIntRep(objPtr);
03796         objPtr->internalRep.twoPtrValue.ptr1 = NULL;
03797         objPtr->internalRep.twoPtrValue.ptr2 = NULL;
03798         objPtr->typePtr = &tclCmdNameType;
03799     }
03800     return TCL_OK;
03801 }
03802 
03803 /*
03804  * Local Variables:
03805  * mode: c
03806  * c-basic-offset: 4
03807  * fill-column: 78
03808  * End:
03809  */



Generated on Wed Mar 12 12:18:20 2008 by  doxygen 1.5.1