tclObj.cGo 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 1.5.1 |