source: trunk/tcl/tclObj.c@ 15

Last change on this file since 15 was 2, checked in by Pavel Demin, 16 years ago

first commit

File size: 59.6 KB
Line 
1/*
2 * tclObj.c --
3 *
4 * This file contains Tcl object-related procedures that are used by
5 * many Tcl commands.
6 *
7 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
8 *
9 * See the file "license.terms" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 *
12 * RCS: @(#) $Id: tclObj.c,v 1.1 2008-06-04 13:58:08 demin Exp $
13 */
14
15#include "tclInt.h"
16#include "tclPort.h"
17
18/*
19 * Table of all object types.
20 */
21
22static Tcl_HashTable typeTable;
23static int typeTableInitialized = 0; /* 0 means not yet initialized. */
24
25/*
26 * Head of the list of free Tcl_Objs we maintain.
27 */
28
29Tcl_Obj *tclFreeObjList = NULL;
30
31/*
32 * Pointer to a heap-allocated string of length zero that the Tcl core uses
33 * as the value of an empty string representation for an object. This value
34 * is shared by all new objects allocated by Tcl_NewObj.
35 */
36
37char *tclEmptyStringRep = NULL;
38
39/*
40 * Count of the number of Tcl objects every allocated (by Tcl_NewObj) and
41 * freed (by TclFreeObj).
42 */
43
44#ifdef TCL_COMPILE_STATS
45long tclObjsAlloced = 0;
46long tclObjsFreed = 0;
47#endif /* TCL_COMPILE_STATS */
48
49/*
50 * Prototypes for procedures defined later in this file:
51 */
52
53static void DupBooleanInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
54 Tcl_Obj *copyPtr));
55static void DupDoubleInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
56 Tcl_Obj *copyPtr));
57static void DupIntInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
58 Tcl_Obj *copyPtr));
59static void FinalizeTypeTable _ANSI_ARGS_((void));
60static void FinalizeFreeObjList _ANSI_ARGS_((void));
61static void InitTypeTable _ANSI_ARGS_((void));
62static int SetBooleanFromAny _ANSI_ARGS_((Tcl_Interp *interp,
63 Tcl_Obj *objPtr));
64static int SetDoubleFromAny _ANSI_ARGS_((Tcl_Interp *interp,
65 Tcl_Obj *objPtr));
66static int SetIntFromAny _ANSI_ARGS_((Tcl_Interp *interp,
67 Tcl_Obj *objPtr));
68static void UpdateStringOfBoolean _ANSI_ARGS_((Tcl_Obj *objPtr));
69static void UpdateStringOfDouble _ANSI_ARGS_((Tcl_Obj *objPtr));
70static void UpdateStringOfInt _ANSI_ARGS_((Tcl_Obj *objPtr));
71
72/*
73 * The structures below defines the Tcl object types defined in this file by
74 * means of procedures that can be invoked by generic object code. See also
75 * tclStringObj.c, tclListObj.c, tclByteCode.c for other type manager
76 * implementations.
77 */
78
79Tcl_ObjType tclBooleanType = {
80 "boolean", /* name */
81 (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
82 DupBooleanInternalRep, /* dupIntRepProc */
83 UpdateStringOfBoolean, /* updateStringProc */
84 SetBooleanFromAny /* setFromAnyProc */
85};
86
87Tcl_ObjType tclDoubleType = {
88 "double", /* name */
89 (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
90 DupDoubleInternalRep, /* dupIntRepProc */
91 UpdateStringOfDouble, /* updateStringProc */
92 SetDoubleFromAny /* setFromAnyProc */
93};
94
95Tcl_ObjType tclIntType = {
96 "int", /* name */
97 (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
98 DupIntInternalRep, /* dupIntRepProc */
99 UpdateStringOfInt, /* updateStringProc */
100 SetIntFromAny /* setFromAnyProc */
101};
102
103
104/*
105 *--------------------------------------------------------------
106 *
107 * InitTypeTable --
108 *
109 * This procedure is invoked to perform once-only initialization of
110 * the type table. It also registers the object types defined in
111 * this file.
112 *
113 * Results:
114 * None.
115 *
116 * Side effects:
117 * Initializes the table of defined object types "typeTable" with
118 * builtin object types defined in this file. It also initializes the
119 * value of tclEmptyStringRep, which points to the heap-allocated
120 * string of length zero used as the string representation for
121 * newly-created objects.
122 *
123 *--------------------------------------------------------------
124 */
125
126static void
127InitTypeTable()
128{
129 typeTableInitialized = 1;
130
131 Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS);
132 Tcl_RegisterObjType(&tclBooleanType);
133 Tcl_RegisterObjType(&tclDoubleType);
134 Tcl_RegisterObjType(&tclIntType);
135 Tcl_RegisterObjType(&tclStringType);
136 Tcl_RegisterObjType(&tclListType);
137 Tcl_RegisterObjType(&tclByteCodeType);
138 Tcl_RegisterObjType(&tclProcBodyType);
139
140 tclEmptyStringRep = (char *) ckalloc((unsigned) 1);
141 tclEmptyStringRep[0] = '\0';
142}
143
144
145/*
146 *----------------------------------------------------------------------
147 *
148 * FinalizeTypeTable --
149 *
150 * This procedure is called by Tcl_Finalize after all exit handlers
151 * have been run to free up storage associated with the table of Tcl
152 * object types.
153 *
154 * Results:
155 * None.
156 *
157 * Side effects:
158 * Deletes all entries in the hash table of object types, "typeTable".
159 * Then sets "typeTableInitialized" to 0 so that the Tcl type system
160 * will be properly reinitialized if Tcl is restarted. Also deallocates
161 * the storage for tclEmptyStringRep.
162 *
163 *----------------------------------------------------------------------
164 */
165
166static void
167FinalizeTypeTable()
168{
169 if (typeTableInitialized) {
170 Tcl_DeleteHashTable(&typeTable);
171 ckfree(tclEmptyStringRep);
172 typeTableInitialized = 0;
173 }
174}
175
176
177/*
178 *----------------------------------------------------------------------
179 *
180 * FinalizeFreeObjList --
181 *
182 * Resets the free object list so it can later be reinitialized.
183 *
184 * Results:
185 * None.
186 *
187 * Side effects:
188 * Resets the value of tclFreeObjList.
189 *
190 *----------------------------------------------------------------------
191 */
192
193static void
194FinalizeFreeObjList()
195{
196 tclFreeObjList = NULL;
197}
198
199
200/*
201 *----------------------------------------------------------------------
202 *
203 * TclFinalizeCompExecEnv --
204 *
205 * Clean up the compiler execution environment so it can later be
206 * properly reinitialized.
207 *
208 * Results:
209 * None.
210 *
211 * Side effects:
212 * Cleans up the execution environment
213 *
214 *----------------------------------------------------------------------
215 */
216
217void
218TclFinalizeCompExecEnv()
219{
220 FinalizeTypeTable();
221 FinalizeFreeObjList();
222 TclFinalizeExecEnv();
223}
224
225
226/*
227 *--------------------------------------------------------------
228 *
229 * Tcl_RegisterObjType --
230 *
231 * This procedure is called to register a new Tcl object type
232 * in the table of all object types supported by Tcl.
233 *
234 * Results:
235 * None.
236 *
237 * Side effects:
238 * The type is registered in the Tcl type table. If there was already
239 * a type with the same name as in typePtr, it is replaced with the
240 * new type.
241 *
242 *--------------------------------------------------------------
243 */
244
245void
246Tcl_RegisterObjType(typePtr)
247 Tcl_ObjType *typePtr; /* Information about object type;
248 * storage must be statically
249 * allocated (must live forever). */
250{
251 register Tcl_HashEntry *hPtr;
252 int new;
253
254 if (!typeTableInitialized) {
255 InitTypeTable();
256 }
257
258 /*
259 * If there's already an object type with the given name, remove it.
260 */
261
262 hPtr = Tcl_FindHashEntry(&typeTable, typePtr->name);
263 if (hPtr != (Tcl_HashEntry *) NULL) {
264 Tcl_DeleteHashEntry(hPtr);
265 }
266
267 /*
268 * Now insert the new object type.
269 */
270
271 hPtr = Tcl_CreateHashEntry(&typeTable, typePtr->name, &new);
272 if (new) {
273 Tcl_SetHashValue(hPtr, typePtr);
274 }
275}
276
277
278/*
279 *----------------------------------------------------------------------
280 *
281 * Tcl_AppendAllObjTypes --
282 *
283 * This procedure appends onto the argument object the name of each
284 * object type as a list element. This includes the builtin object
285 * types (e.g. int, list) as well as those added using
286 * Tcl_CreateObjType. These names can be used, for example, with
287 * Tcl_GetObjType to get pointers to the corresponding Tcl_ObjType
288 * structures.
289 *
290 * Results:
291 * The return value is normally TCL_OK; in this case the object
292 * referenced by objPtr has each type name appended to it. If an
293 * error occurs, TCL_ERROR is returned and the interpreter's result
294 * holds an error message.
295 *
296 * Side effects:
297 * If necessary, the object referenced by objPtr is converted into
298 * a list object.
299 *
300 *----------------------------------------------------------------------
301 */
302
303int
304Tcl_AppendAllObjTypes(interp, objPtr)
305 Tcl_Interp *interp; /* Interpreter used for error reporting. */
306 Tcl_Obj *objPtr; /* Points to the Tcl object onto which the
307 * name of each registered type is appended
308 * as a list element. */
309{
310 register Tcl_HashEntry *hPtr;
311 Tcl_HashSearch search;
312 Tcl_ObjType *typePtr;
313 int result;
314
315 if (!typeTableInitialized) {
316 InitTypeTable();
317 }
318
319 /*
320 * This code assumes that types names do not contain embedded NULLs.
321 */
322
323 for (hPtr = Tcl_FirstHashEntry(&typeTable, &search);
324 hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
325 typePtr = (Tcl_ObjType *) Tcl_GetHashValue(hPtr);
326 result = Tcl_ListObjAppendElement(interp, objPtr,
327 Tcl_NewStringObj(typePtr->name, -1));
328 if (result == TCL_ERROR) {
329 return result;
330 }
331 }
332 return TCL_OK;
333}
334
335
336/*
337 *----------------------------------------------------------------------
338 *
339 * Tcl_GetObjType --
340 *
341 * This procedure looks up an object type by name.
342 *
343 * Results:
344 * If an object type with name matching "typeName" is found, a pointer
345 * to its Tcl_ObjType structure is returned; otherwise, NULL is
346 * returned.
347 *
348 * Side effects:
349 * None.
350 *
351 *----------------------------------------------------------------------
352 */
353
354Tcl_ObjType *
355Tcl_GetObjType(typeName)
356 char *typeName; /* Name of Tcl object type to look up. */
357{
358 register Tcl_HashEntry *hPtr;
359 Tcl_ObjType *typePtr;
360
361 if (!typeTableInitialized) {
362 InitTypeTable();
363 }
364
365 hPtr = Tcl_FindHashEntry(&typeTable, typeName);
366 if (hPtr != (Tcl_HashEntry *) NULL) {
367 typePtr = (Tcl_ObjType *) Tcl_GetHashValue(hPtr);
368 return typePtr;
369 }
370 return NULL;
371}
372
373
374/*
375 *----------------------------------------------------------------------
376 *
377 * Tcl_ConvertToType --
378 *
379 * Convert the Tcl object "objPtr" to have type "typePtr" if possible.
380 *
381 * Results:
382 * The return value is TCL_OK on success and TCL_ERROR on failure. If
383 * TCL_ERROR is returned, then the interpreter's result contains an
384 * error message unless "interp" is NULL. Passing a NULL "interp"
385 * allows this procedure to be used as a test whether the conversion
386 * could be done (and in fact was done).
387 *
388 * Side effects:
389 * Any internal representation for the old type is freed.
390 *
391 *----------------------------------------------------------------------
392 */
393
394int
395Tcl_ConvertToType(interp, objPtr, typePtr)
396 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
397 Tcl_Obj *objPtr; /* The object to convert. */
398 Tcl_ObjType *typePtr; /* The target type. */
399{
400 if (objPtr->typePtr == typePtr) {
401 return TCL_OK;
402 }
403
404 /*
405 * Use the target type's Tcl_SetFromAnyProc to set "objPtr"s internal
406 * form as appropriate for the target type. This frees the old internal
407 * representation.
408 */
409
410 return typePtr->setFromAnyProc(interp, objPtr);
411}
412
413
414/*
415 *----------------------------------------------------------------------
416 *
417 * Tcl_NewObj --
418 *
419 * This procedure is normally called when not debugging: i.e., when
420 * TCL_MEM_DEBUG is not defined. It creates new Tcl objects that denote
421 * the empty string. These objects have a NULL object type and NULL
422 * string representation byte pointer. Type managers call this routine
423 * to allocate new objects that they further initialize.
424 *
425 * When TCL_MEM_DEBUG is defined, this procedure just returns the
426 * result of calling the debugging version Tcl_DbNewObj.
427 *
428 * Results:
429 * The result is a newly allocated object that represents the empty
430 * string. The new object's typePtr is set NULL and its ref count
431 * is set to 0.
432 *
433 * Side effects:
434 * If compiling with TCL_COMPILE_STATS, this procedure increments
435 * the global count of allocated objects (tclObjsAlloced).
436 *
437 *----------------------------------------------------------------------
438 */
439
440#ifdef TCL_MEM_DEBUG
441#undef Tcl_NewObj
442
443Tcl_Obj *
444Tcl_NewObj()
445{
446 return Tcl_DbNewObj("unknown", 0);
447}
448
449#else /* if not TCL_MEM_DEBUG */
450
451Tcl_Obj *
452Tcl_NewObj()
453{
454 register Tcl_Obj *objPtr;
455
456 /*
457 * Allocate the object using the list of free Tcl_Objs we maintain.
458 */
459
460 if (tclFreeObjList == NULL) {
461 TclAllocateFreeObjects();
462 }
463 objPtr = tclFreeObjList;
464 tclFreeObjList = (Tcl_Obj *) tclFreeObjList->internalRep.otherValuePtr;
465
466 objPtr->refCount = 0;
467 objPtr->bytes = tclEmptyStringRep;
468 objPtr->length = 0;
469 objPtr->typePtr = NULL;
470#ifdef TCL_COMPILE_STATS
471 tclObjsAlloced++;
472#endif /* TCL_COMPILE_STATS */
473 return objPtr;
474}
475#endif /* TCL_MEM_DEBUG */
476
477
478/*
479 *----------------------------------------------------------------------
480 *
481 * Tcl_DbNewObj --
482 *
483 * This procedure is normally called when debugging: i.e., when
484 * TCL_MEM_DEBUG is defined. It creates new Tcl objects that denote the
485 * empty string. It is the same as the Tcl_NewObj procedure above
486 * except that it calls Tcl_DbCkalloc directly with the file name and
487 * line number from its caller. This simplifies debugging since then
488 * the checkmem command will report the correct file name and line
489 * number when reporting objects that haven't been freed.
490 *
491 * When TCL_MEM_DEBUG is not defined, this procedure just returns the
492 * result of calling Tcl_NewObj.
493 *
494 * Results:
495 * The result is a newly allocated that represents the empty string.
496 * The new object's typePtr is set NULL and its ref count is set to 0.
497 *
498 * Side effects:
499 * If compiling with TCL_COMPILE_STATS, this procedure increments
500 * the global count of allocated objects (tclObjsAlloced).
501 *
502 *----------------------------------------------------------------------
503 */
504
505#ifdef TCL_MEM_DEBUG
506
507Tcl_Obj *
508Tcl_DbNewObj(file, line)
509 register char *file; /* The name of the source file calling this
510 * procedure; used for debugging. */
511 register int line; /* Line number in the source file; used
512 * for debugging. */
513{
514 register Tcl_Obj *objPtr;
515
516 /*
517 * If debugging Tcl's memory usage, allocate the object using ckalloc.
518 * Otherwise, allocate it using the list of free Tcl_Objs we maintain.
519 */
520
521 objPtr = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), file, line);
522 objPtr->refCount = 0;
523 objPtr->bytes = tclEmptyStringRep;
524 objPtr->length = 0;
525 objPtr->typePtr = NULL;
526#ifdef TCL_COMPILE_STATS
527 tclObjsAlloced++;
528#endif /* TCL_COMPILE_STATS */
529 return objPtr;
530}
531
532#else /* if not TCL_MEM_DEBUG */
533
534Tcl_Obj *
535Tcl_DbNewObj(file, line)
536 char *file; /* The name of the source file calling this
537 * procedure; used for debugging. */
538 int line; /* Line number in the source file; used
539 * for debugging. */
540{
541 return Tcl_NewObj();
542}
543#endif /* TCL_MEM_DEBUG */
544
545
546/*
547 *----------------------------------------------------------------------
548 *
549 * TclAllocateFreeObjects --
550 *
551 * Procedure to allocate a number of free Tcl_Objs. This is done using
552 * a single ckalloc to reduce the overhead for Tcl_Obj allocation.
553 *
554 * Results:
555 * None.
556 *
557 * Side effects:
558 * tclFreeObjList, the head of the list of free Tcl_Objs, is set to the
559 * first of a number of free Tcl_Obj's linked together by their
560 * internalRep.otherValuePtrs.
561 *
562 *----------------------------------------------------------------------
563 */
564
565#define OBJS_TO_ALLOC_EACH_TIME 100
566
567void
568TclAllocateFreeObjects()
569{
570 Tcl_Obj tmp[2];
571 size_t objSizePlusPadding = /* NB: this assumes byte addressing. */
572 ((int)(&(tmp[1])) - (int)(&(tmp[0])));
573 size_t bytesToAlloc = (OBJS_TO_ALLOC_EACH_TIME * objSizePlusPadding);
574 char *basePtr;
575 register Tcl_Obj *prevPtr, *objPtr;
576 register int i;
577
578 basePtr = (char *) ckalloc(bytesToAlloc);
579 memset(basePtr, 0, bytesToAlloc);
580
581 prevPtr = NULL;
582 objPtr = (Tcl_Obj *) basePtr;
583 for (i = 0; i < OBJS_TO_ALLOC_EACH_TIME; i++) {
584 objPtr->internalRep.otherValuePtr = (VOID *) prevPtr;
585 prevPtr = objPtr;
586 objPtr = (Tcl_Obj *) (((char *)objPtr) + objSizePlusPadding);
587 }
588 tclFreeObjList = prevPtr;
589}
590#undef OBJS_TO_ALLOC_EACH_TIME
591
592
593/*
594 *----------------------------------------------------------------------
595 *
596 * TclFreeObj --
597 *
598 * This procedure frees the memory associated with the argument
599 * object. It is called by the tcl.h macro Tcl_DecrRefCount when an
600 * object's ref count is zero. It is only "public" since it must
601 * be callable by that macro wherever the macro is used. It should not
602 * be directly called by clients.
603 *
604 * Results:
605 * None.
606 *
607 * Side effects:
608 * Deallocates the storage for the object's Tcl_Obj structure
609 * after deallocating the string representation and calling the
610 * type-specific Tcl_FreeInternalRepProc to deallocate the object's
611 * internal representation. If compiling with TCL_COMPILE_STATS,
612 * this procedure increments the global count of freed objects
613 * (tclObjsFreed).
614 *
615 *----------------------------------------------------------------------
616 */
617
618void
619TclFreeObj(objPtr)
620 register Tcl_Obj *objPtr; /* The object to be freed. */
621{
622 register Tcl_ObjType *typePtr = objPtr->typePtr;
623
624#ifdef TCL_MEM_DEBUG
625 if ((objPtr)->refCount < -1) {
626 panic("Reference count for %lx was negative", objPtr);
627 }
628#endif /* TCL_MEM_DEBUG */
629
630 Tcl_InvalidateStringRep(objPtr);
631 if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
632 typePtr->freeIntRepProc(objPtr);
633 }
634
635 /*
636 * If debugging Tcl's memory usage, deallocate the object using ckfree.
637 * Otherwise, deallocate it by adding it onto the list of free
638 * Tcl_Objs we maintain.
639 */
640
641#ifdef TCL_MEM_DEBUG
642 ckfree((char *) objPtr);
643#else
644 objPtr->internalRep.otherValuePtr = (VOID *) tclFreeObjList;
645 tclFreeObjList = objPtr;
646#endif /* TCL_MEM_DEBUG */
647
648#ifdef TCL_COMPILE_STATS
649 tclObjsFreed++;
650#endif /* TCL_COMPILE_STATS */
651}
652
653
654/*
655 *----------------------------------------------------------------------
656 *
657 * Tcl_DuplicateObj --
658 *
659 * Create and return a new object that is a duplicate of the argument
660 * object.
661 *
662 * Results:
663 * The return value is a pointer to a newly created Tcl_Obj. This
664 * object has reference count 0 and the same type, if any, as the
665 * source object objPtr. Also:
666 * 1) If the source object has a valid string rep, we copy it;
667 * otherwise, the duplicate's string rep is set NULL to mark
668 * it invalid.
669 * 2) If the source object has an internal representation (i.e. its
670 * typePtr is non-NULL), the new object's internal rep is set to
671 * a copy; otherwise the new internal rep is marked invalid.
672 *
673 * Side effects:
674 * What constitutes "copying" the internal representation depends on
675 * the type. For example, if the argument object is a list,
676 * the element objects it points to will not actually be copied but
677 * will be shared with the duplicate list. That is, the ref counts of
678 * the element objects will be incremented.
679 *
680 *----------------------------------------------------------------------
681 */
682
683Tcl_Obj *
684Tcl_DuplicateObj(objPtr)
685 register Tcl_Obj *objPtr; /* The object to duplicate. */
686{
687 register Tcl_ObjType *typePtr = objPtr->typePtr;
688 register Tcl_Obj *dupPtr;
689
690 TclNewObj(dupPtr);
691
692 if (objPtr->bytes == NULL) {
693 dupPtr->bytes = NULL;
694 } else if (objPtr->bytes != tclEmptyStringRep) {
695 int len = objPtr->length;
696
697 dupPtr->bytes = (char *) ckalloc((unsigned) len+1);
698 if (len > 0) {
699 memcpy((VOID *) dupPtr->bytes, (VOID *) objPtr->bytes,
700 (unsigned) len);
701 }
702 dupPtr->bytes[len] = '\0';
703 dupPtr->length = len;
704 }
705
706 if (typePtr != NULL) {
707 typePtr->dupIntRepProc(objPtr, dupPtr);
708 }
709 return dupPtr;
710}
711
712
713/*
714 *----------------------------------------------------------------------
715 *
716 * Tcl_GetStringFromObj --
717 *
718 * Returns the string representation's byte array pointer and length
719 * for an object.
720 *
721 * Results:
722 * Returns a pointer to the string representation of objPtr. If
723 * lengthPtr isn't NULL, the length of the string representation is
724 * stored at *lengthPtr. The byte array referenced by the returned
725 * pointer must not be modified by the caller. Furthermore, the
726 * caller must copy the bytes if they need to retain them since the
727 * object's string rep can change as a result of other operations.
728 *
729 * Side effects:
730 * May call the object's updateStringProc to update the string
731 * representation from the internal representation.
732 *
733 *----------------------------------------------------------------------
734 */
735
736char *
737Tcl_GetStringFromObj(objPtr, lengthPtr)
738 register Tcl_Obj *objPtr; /* Object whose string rep byte pointer
739 * should be returned. */
740 register int *lengthPtr; /* If non-NULL, the location where the
741 * string rep's byte array length should be
742 * stored. If NULL, no length is stored. */
743{
744 if (objPtr->bytes != NULL) {
745 if (lengthPtr != NULL) {
746 *lengthPtr = objPtr->length;
747 }
748 return objPtr->bytes;
749 }
750
751 objPtr->typePtr->updateStringProc(objPtr);
752 if (lengthPtr != NULL) {
753 *lengthPtr = objPtr->length;
754 }
755 return objPtr->bytes;
756}
757
758
759/*
760 *----------------------------------------------------------------------
761 *
762 * Tcl_InvalidateStringRep --
763 *
764 * This procedure is called to invalidate an object's string
765 * representation.
766 *
767 * Results:
768 * None.
769 *
770 * Side effects:
771 * Deallocates the storage for any old string representation, then
772 * sets the string representation NULL to mark it invalid.
773 *
774 *----------------------------------------------------------------------
775 */
776
777void
778Tcl_InvalidateStringRep(objPtr)
779 register Tcl_Obj *objPtr; /* Object whose string rep byte pointer
780 * should be freed. */
781{
782 if (objPtr->bytes != NULL) {
783 if (objPtr->bytes != tclEmptyStringRep) {
784 ckfree((char *) objPtr->bytes);
785 }
786 objPtr->bytes = NULL;
787 }
788}
789
790
791/*
792 *----------------------------------------------------------------------
793 *
794 * Tcl_NewBooleanObj --
795 *
796 * This procedure is normally called when not debugging: i.e., when
797 * TCL_MEM_DEBUG is not defined. It creates a new boolean object and
798 * initializes it from the argument boolean value. A nonzero
799 * "boolValue" is coerced to 1.
800 *
801 * When TCL_MEM_DEBUG is defined, this procedure just returns the
802 * result of calling the debugging version Tcl_DbNewBooleanObj.
803 *
804 * Results:
805 * The newly created object is returned. This object will have an
806 * invalid string representation. The returned object has ref count 0.
807 *
808 * Side effects:
809 * None.
810 *
811 *----------------------------------------------------------------------
812 */
813
814#ifdef TCL_MEM_DEBUG
815#undef Tcl_NewBooleanObj
816
817Tcl_Obj *
818Tcl_NewBooleanObj(boolValue)
819 register int boolValue; /* Boolean used to initialize new object. */
820{
821 return Tcl_DbNewBooleanObj(boolValue, "unknown", 0);
822}
823
824#else /* if not TCL_MEM_DEBUG */
825
826Tcl_Obj *
827Tcl_NewBooleanObj(boolValue)
828 register int boolValue; /* Boolean used to initialize new object. */
829{
830 register Tcl_Obj *objPtr;
831
832 TclNewObj(objPtr);
833 objPtr->bytes = NULL;
834
835 objPtr->internalRep.longValue = (boolValue? 1 : 0);
836 objPtr->typePtr = &tclBooleanType;
837 return objPtr;
838}
839#endif /* TCL_MEM_DEBUG */
840
841
842/*
843 *----------------------------------------------------------------------
844 *
845 * Tcl_DbNewBooleanObj --
846 *
847 * This procedure is normally called when debugging: i.e., when
848 * TCL_MEM_DEBUG is defined. It creates new boolean objects. It is the
849 * same as the Tcl_NewBooleanObj procedure above except that it calls
850 * Tcl_DbCkalloc directly with the file name and line number from its
851 * caller. This simplifies debugging since then the checkmem command
852 * will report the correct file name and line number when reporting
853 * objects that haven't been freed.
854 *
855 * When TCL_MEM_DEBUG is not defined, this procedure just returns the
856 * result of calling Tcl_NewBooleanObj.
857 *
858 * Results:
859 * The newly created object is returned. This object will have an
860 * invalid string representation. The returned object has ref count 0.
861 *
862 * Side effects:
863 * None.
864 *
865 *----------------------------------------------------------------------
866 */
867
868#ifdef TCL_MEM_DEBUG
869
870Tcl_Obj *
871Tcl_DbNewBooleanObj(boolValue, file, line)
872 register int boolValue; /* Boolean used to initialize new object. */
873 char *file; /* The name of the source file calling this
874 * procedure; used for debugging. */
875 int line; /* Line number in the source file; used
876 * for debugging. */
877{
878 register Tcl_Obj *objPtr;
879
880 TclDbNewObj(objPtr, file, line);
881 objPtr->bytes = NULL;
882
883 objPtr->internalRep.longValue = (boolValue? 1 : 0);
884 objPtr->typePtr = &tclBooleanType;
885 return objPtr;
886}
887
888#else /* if not TCL_MEM_DEBUG */
889
890Tcl_Obj *
891Tcl_DbNewBooleanObj(boolValue, file, line)
892 register int boolValue; /* Boolean used to initialize new object. */
893 char *file; /* The name of the source file calling this
894 * procedure; used for debugging. */
895 int line; /* Line number in the source file; used
896 * for debugging. */
897{
898 return Tcl_NewBooleanObj(boolValue);
899}
900#endif /* TCL_MEM_DEBUG */
901
902
903/*
904 *----------------------------------------------------------------------
905 *
906 * Tcl_SetBooleanObj --
907 *
908 * Modify an object to be a boolean object and to have the specified
909 * boolean value. A nonzero "boolValue" is coerced to 1.
910 *
911 * Results:
912 * None.
913 *
914 * Side effects:
915 * The object's old string rep, if any, is freed. Also, any old
916 * internal rep is freed.
917 *
918 *----------------------------------------------------------------------
919 */
920
921void
922Tcl_SetBooleanObj(objPtr, boolValue)
923 register Tcl_Obj *objPtr; /* Object whose internal rep to init. */
924 register int boolValue; /* Boolean used to set object's value. */
925{
926 register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
927
928 if (Tcl_IsShared(objPtr)) {
929 panic("Tcl_SetBooleanObj called with shared object");
930 }
931
932 Tcl_InvalidateStringRep(objPtr);
933 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
934 oldTypePtr->freeIntRepProc(objPtr);
935 }
936
937 objPtr->internalRep.longValue = (boolValue? 1 : 0);
938 objPtr->typePtr = &tclBooleanType;
939}
940
941
942/*
943 *----------------------------------------------------------------------
944 *
945 * Tcl_GetBooleanFromObj --
946 *
947 * Attempt to return a boolean from the Tcl object "objPtr". If the
948 * object is not already a boolean, an attempt will be made to convert
949 * it to one.
950 *
951 * Results:
952 * The return value is a standard Tcl object result. If an error occurs
953 * during conversion, an error message is left in the interpreter's
954 * result unless "interp" is NULL.
955 *
956 * Side effects:
957 * If the object is not already a boolean, the conversion will free
958 * any old internal representation.
959 *
960 *----------------------------------------------------------------------
961 */
962
963int
964Tcl_GetBooleanFromObj(interp, objPtr, boolPtr)
965 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
966 register Tcl_Obj *objPtr; /* The object from which to get boolean. */
967 register int *boolPtr; /* Place to store resulting boolean. */
968{
969 register int result;
970
971 result = SetBooleanFromAny(interp, objPtr);
972 if (result == TCL_OK) {
973 *boolPtr = (int) objPtr->internalRep.longValue;
974 }
975 return result;
976}
977
978
979/*
980 *----------------------------------------------------------------------
981 *
982 * DupBooleanInternalRep --
983 *
984 * Initialize the internal representation of a boolean Tcl_Obj to a
985 * copy of the internal representation of an existing boolean object.
986 *
987 * Results:
988 * None.
989 *
990 * Side effects:
991 * "copyPtr"s internal rep is set to the boolean (an integer)
992 * corresponding to "srcPtr"s internal rep.
993 *
994 *----------------------------------------------------------------------
995 */
996
997static void
998DupBooleanInternalRep(srcPtr, copyPtr)
999 register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
1000 register Tcl_Obj *copyPtr; /* Object with internal rep to set. */
1001{
1002 copyPtr->internalRep.longValue = srcPtr->internalRep.longValue;
1003 copyPtr->typePtr = &tclBooleanType;
1004}
1005
1006
1007/*
1008 *----------------------------------------------------------------------
1009 *
1010 * SetBooleanFromAny --
1011 *
1012 * Attempt to generate a boolean internal form for the Tcl object
1013 * "objPtr".
1014 *
1015 * Results:
1016 * The return value is a standard Tcl result. If an error occurs during
1017 * conversion, an error message is left in the interpreter's result
1018 * unless "interp" is NULL.
1019 *
1020 * Side effects:
1021 * If no error occurs, an integer 1 or 0 is stored as "objPtr"s
1022 * internal representation and the type of "objPtr" is set to boolean.
1023 *
1024 *----------------------------------------------------------------------
1025 */
1026
1027static int
1028SetBooleanFromAny(interp, objPtr)
1029 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
1030 register Tcl_Obj *objPtr; /* The object to convert. */
1031{
1032 Tcl_ObjType *oldTypePtr = objPtr->typePtr;
1033 char *string, *end;
1034 register char c;
1035 char lowerCase[10];
1036 int newBool, length;
1037 register int i;
1038 double dbl;
1039
1040 /*
1041 * Get the string representation. Make it up-to-date if necessary.
1042 */
1043
1044 string = TclGetStringFromObj(objPtr, &length);
1045
1046 /*
1047 * Copy the string converting its characters to lower case.
1048 */
1049
1050 for (i = 0; (i < 9) && (i < length); i++) {
1051 c = string[i];
1052 if (isupper(UCHAR(c))) {
1053 c = (char) tolower(UCHAR(c));
1054 }
1055 lowerCase[i] = c;
1056 }
1057 lowerCase[i] = 0;
1058
1059 /*
1060 * Parse the string as a boolean. We use an implementation here that
1061 * doesn't report errors in interp if interp is NULL.
1062 */
1063
1064 c = lowerCase[0];
1065 if ((c == '0') && (lowerCase[1] == '\0')) {
1066 newBool = 0;
1067 } else if ((c == '1') && (lowerCase[1] == '\0')) {
1068 newBool = 1;
1069 } else if ((c == 'y') && (strncmp(lowerCase, "yes", (size_t) length) == 0)) {
1070 newBool = 1;
1071 } else if ((c == 'n') && (strncmp(lowerCase, "no", (size_t) length) == 0)) {
1072 newBool = 0;
1073 } else if ((c == 't') && (strncmp(lowerCase, "true", (size_t) length) == 0)) {
1074 newBool = 1;
1075 } else if ((c == 'f') && (strncmp(lowerCase, "false", (size_t) length) == 0)) {
1076 newBool = 0;
1077 } else if ((c == 'o') && (length >= 2)) {
1078 if (strncmp(lowerCase, "on", (size_t) length) == 0) {
1079 newBool = 1;
1080 } else if (strncmp(lowerCase, "off", (size_t) length) == 0) {
1081 newBool = 0;
1082 } else {
1083 goto badBoolean;
1084 }
1085 } else {
1086 /*
1087 * Still might be a string containing the characters representing an
1088 * int or double that wasn't handled above. This would be a string
1089 * like "27" or "1.0" that is non-zero and not "1". Such a string
1090 * whould result in the boolean value true. We try converting to
1091 * double. If that succeeds and the resulting double is non-zero, we
1092 * have a "true". Note that numbers can't have embedded NULLs.
1093 */
1094
1095 dbl = strtod(string, &end);
1096 if (end == string) {
1097 goto badBoolean;
1098 }
1099
1100 /*
1101 * Make sure the string has no garbage after the end of the double.
1102 */
1103
1104 while ((end < (string+length)) && isspace(UCHAR(*end))) {
1105 end++;
1106 }
1107 if (end != (string+length)) {
1108 goto badBoolean;
1109 }
1110 newBool = (dbl != 0.0);
1111 }
1112
1113 /*
1114 * Free the old internalRep before setting the new one. We do this as
1115 * late as possible to allow the conversion code, in particular
1116 * Tcl_GetStringFromObj, to use that old internalRep.
1117 */
1118
1119 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
1120 oldTypePtr->freeIntRepProc(objPtr);
1121 }
1122
1123 objPtr->internalRep.longValue = newBool;
1124 objPtr->typePtr = &tclBooleanType;
1125 return TCL_OK;
1126
1127 badBoolean:
1128 if (interp != NULL) {
1129 /*
1130 * Must copy string before resetting the result in case a caller
1131 * is trying to convert the interpreter's result to a boolean.
1132 */
1133
1134 char buf[100];
1135 sprintf(buf, "expected boolean value but got \"%.50s\"", string);
1136 Tcl_ResetResult(interp);
1137 Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
1138 }
1139 return TCL_ERROR;
1140}
1141
1142
1143/*
1144 *----------------------------------------------------------------------
1145 *
1146 * UpdateStringOfBoolean --
1147 *
1148 * Update the string representation for a boolean object.
1149 * Note: This procedure does not free an existing old string rep
1150 * so storage will be lost if this has not already been done.
1151 *
1152 * Results:
1153 * None.
1154 *
1155 * Side effects:
1156 * The object's string is set to a valid string that results from
1157 * the boolean-to-string conversion.
1158 *
1159 *----------------------------------------------------------------------
1160 */
1161
1162static void
1163UpdateStringOfBoolean(objPtr)
1164 register Tcl_Obj *objPtr; /* Int object whose string rep to update. */
1165{
1166 char *s = ckalloc((unsigned) 2);
1167
1168 s[0] = (char) (objPtr->internalRep.longValue? '1' : '0');
1169 s[1] = '\0';
1170 objPtr->bytes = s;
1171 objPtr->length = 1;
1172}
1173
1174
1175/*
1176 *----------------------------------------------------------------------
1177 *
1178 * Tcl_NewDoubleObj --
1179 *
1180 * This procedure is normally called when not debugging: i.e., when
1181 * TCL_MEM_DEBUG is not defined. It creates a new double object and
1182 * initializes it from the argument double value.
1183 *
1184 * When TCL_MEM_DEBUG is defined, this procedure just returns the
1185 * result of calling the debugging version Tcl_DbNewDoubleObj.
1186 *
1187 * Results:
1188 * The newly created object is returned. This object will have an
1189 * invalid string representation. The returned object has ref count 0.
1190 *
1191 * Side effects:
1192 * None.
1193 *
1194 *----------------------------------------------------------------------
1195 */
1196
1197#ifdef TCL_MEM_DEBUG
1198#undef Tcl_NewDoubleObj
1199
1200Tcl_Obj *
1201Tcl_NewDoubleObj(dblValue)
1202 register double dblValue; /* Double used to initialize the object. */
1203{
1204 return Tcl_DbNewDoubleObj(dblValue, "unknown", 0);
1205}
1206
1207#else /* if not TCL_MEM_DEBUG */
1208
1209Tcl_Obj *
1210Tcl_NewDoubleObj(dblValue)
1211 register double dblValue; /* Double used to initialize the object. */
1212{
1213 register Tcl_Obj *objPtr;
1214
1215 TclNewObj(objPtr);
1216 objPtr->bytes = NULL;
1217
1218 objPtr->internalRep.doubleValue = dblValue;
1219 objPtr->typePtr = &tclDoubleType;
1220 return objPtr;
1221}
1222#endif /* if TCL_MEM_DEBUG */
1223
1224
1225/*
1226 *----------------------------------------------------------------------
1227 *
1228 * Tcl_DbNewDoubleObj --
1229 *
1230 * This procedure is normally called when debugging: i.e., when
1231 * TCL_MEM_DEBUG is defined. It creates new double objects. It is the
1232 * same as the Tcl_NewDoubleObj procedure above except that it calls
1233 * Tcl_DbCkalloc directly with the file name and line number from its
1234 * caller. This simplifies debugging since then the checkmem command
1235 * will report the correct file name and line number when reporting
1236 * objects that haven't been freed.
1237 *
1238 * When TCL_MEM_DEBUG is not defined, this procedure just returns the
1239 * result of calling Tcl_NewDoubleObj.
1240 *
1241 * Results:
1242 * The newly created object is returned. This object will have an
1243 * invalid string representation. The returned object has ref count 0.
1244 *
1245 * Side effects:
1246 * None.
1247 *
1248 *----------------------------------------------------------------------
1249 */
1250
1251#ifdef TCL_MEM_DEBUG
1252
1253Tcl_Obj *
1254Tcl_DbNewDoubleObj(dblValue, file, line)
1255 register double dblValue; /* Double used to initialize the object. */
1256 char *file; /* The name of the source file calling this
1257 * procedure; used for debugging. */
1258 int line; /* Line number in the source file; used
1259 * for debugging. */
1260{
1261 register Tcl_Obj *objPtr;
1262
1263 TclDbNewObj(objPtr, file, line);
1264 objPtr->bytes = NULL;
1265
1266 objPtr->internalRep.doubleValue = dblValue;
1267 objPtr->typePtr = &tclDoubleType;
1268 return objPtr;
1269}
1270
1271#else /* if not TCL_MEM_DEBUG */
1272
1273Tcl_Obj *
1274Tcl_DbNewDoubleObj(dblValue, file, line)
1275 register double dblValue; /* Double used to initialize the object. */
1276 char *file; /* The name of the source file calling this
1277 * procedure; used for debugging. */
1278 int line; /* Line number in the source file; used
1279 * for debugging. */
1280{
1281 return Tcl_NewDoubleObj(dblValue);
1282}
1283#endif /* TCL_MEM_DEBUG */
1284
1285
1286/*
1287 *----------------------------------------------------------------------
1288 *
1289 * Tcl_SetDoubleObj --
1290 *
1291 * Modify an object to be a double object and to have the specified
1292 * double value.
1293 *
1294 * Results:
1295 * None.
1296 *
1297 * Side effects:
1298 * The object's old string rep, if any, is freed. Also, any old
1299 * internal rep is freed.
1300 *
1301 *----------------------------------------------------------------------
1302 */
1303
1304void
1305Tcl_SetDoubleObj(objPtr, dblValue)
1306 register Tcl_Obj *objPtr; /* Object whose internal rep to init. */
1307 register double dblValue; /* Double used to set the object's value. */
1308{
1309 register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
1310
1311 if (Tcl_IsShared(objPtr)) {
1312 panic("Tcl_SetDoubleObj called with shared object");
1313 }
1314
1315 Tcl_InvalidateStringRep(objPtr);
1316 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
1317 oldTypePtr->freeIntRepProc(objPtr);
1318 }
1319
1320 objPtr->internalRep.doubleValue = dblValue;
1321 objPtr->typePtr = &tclDoubleType;
1322}
1323
1324
1325/*
1326 *----------------------------------------------------------------------
1327 *
1328 * Tcl_GetDoubleFromObj --
1329 *
1330 * Attempt to return a double from the Tcl object "objPtr". If the
1331 * object is not already a double, an attempt will be made to convert
1332 * it to one.
1333 *
1334 * Results:
1335 * The return value is a standard Tcl object result. If an error occurs
1336 * during conversion, an error message is left in the interpreter's
1337 * result unless "interp" is NULL.
1338 *
1339 * Side effects:
1340 * If the object is not already a double, the conversion will free
1341 * any old internal representation.
1342 *
1343 *----------------------------------------------------------------------
1344 */
1345
1346int
1347Tcl_GetDoubleFromObj(interp, objPtr, dblPtr)
1348 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
1349 register Tcl_Obj *objPtr; /* The object from which to get a double. */
1350 register double *dblPtr; /* Place to store resulting double. */
1351{
1352 register int result;
1353
1354 if (objPtr->typePtr == &tclDoubleType) {
1355 *dblPtr = objPtr->internalRep.doubleValue;
1356 return TCL_OK;
1357 }
1358
1359 result = SetDoubleFromAny(interp, objPtr);
1360 if (result == TCL_OK) {
1361 *dblPtr = objPtr->internalRep.doubleValue;
1362 }
1363 return result;
1364}
1365
1366
1367/*
1368 *----------------------------------------------------------------------
1369 *
1370 * DupDoubleInternalRep --
1371 *
1372 * Initialize the internal representation of a double Tcl_Obj to a
1373 * copy of the internal representation of an existing double object.
1374 *
1375 * Results:
1376 * None.
1377 *
1378 * Side effects:
1379 * "copyPtr"s internal rep is set to the double precision floating
1380 * point number corresponding to "srcPtr"s internal rep.
1381 *
1382 *----------------------------------------------------------------------
1383 */
1384
1385static void
1386DupDoubleInternalRep(srcPtr, copyPtr)
1387 register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
1388 register Tcl_Obj *copyPtr; /* Object with internal rep to set. */
1389{
1390 copyPtr->internalRep.doubleValue = srcPtr->internalRep.doubleValue;
1391 copyPtr->typePtr = &tclDoubleType;
1392}
1393
1394
1395/*
1396 *----------------------------------------------------------------------
1397 *
1398 * SetDoubleFromAny --
1399 *
1400 * Attempt to generate an double-precision floating point internal form
1401 * for the Tcl object "objPtr".
1402 *
1403 * Results:
1404 * The return value is a standard Tcl object result. If an error occurs
1405 * during conversion, an error message is left in the interpreter's
1406 * result unless "interp" is NULL.
1407 *
1408 * Side effects:
1409 * If no error occurs, a double is stored as "objPtr"s internal
1410 * representation.
1411 *
1412 *----------------------------------------------------------------------
1413 */
1414
1415static int
1416SetDoubleFromAny(interp, objPtr)
1417 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
1418 register Tcl_Obj *objPtr; /* The object to convert. */
1419{
1420 Tcl_ObjType *oldTypePtr = objPtr->typePtr;
1421 char *string, *end;
1422 double newDouble;
1423 int length;
1424
1425 /*
1426 * Get the string representation. Make it up-to-date if necessary.
1427 */
1428
1429 string = TclGetStringFromObj(objPtr, &length);
1430
1431 /*
1432 * Now parse "objPtr"s string as an double. Numbers can't have embedded
1433 * NULLs. We use an implementation here that doesn't report errors in
1434 * interp if interp is NULL.
1435 */
1436
1437 errno = 0;
1438 newDouble = strtod(string, &end);
1439 if (end == string) {
1440 badDouble:
1441 if (interp != NULL) {
1442 /*
1443 * Must copy string before resetting the result in case a caller
1444 * is trying to convert the interpreter's result to an int.
1445 */
1446
1447 char buf[100];
1448 sprintf(buf, "expected floating-point number but got \"%.50s\"",
1449 string);
1450 Tcl_ResetResult(interp);
1451 Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
1452 }
1453 return TCL_ERROR;
1454 }
1455 if (errno != 0) {
1456 if (interp != NULL) {
1457 TclExprFloatError(interp, newDouble);
1458 }
1459 return TCL_ERROR;
1460 }
1461
1462 /*
1463 * Make sure that the string has no garbage after the end of the double.
1464 */
1465
1466 while ((end < (string+length)) && isspace(UCHAR(*end))) {
1467 end++;
1468 }
1469 if (end != (string+length)) {
1470 goto badDouble;
1471 }
1472
1473 /*
1474 * The conversion to double succeeded. Free the old internalRep before
1475 * setting the new one. We do this as late as possible to allow the
1476 * conversion code, in particular Tcl_GetStringFromObj, to use that old
1477 * internalRep.
1478 */
1479
1480 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
1481 oldTypePtr->freeIntRepProc(objPtr);
1482 }
1483
1484 objPtr->internalRep.doubleValue = newDouble;
1485 objPtr->typePtr = &tclDoubleType;
1486 return TCL_OK;
1487}
1488
1489
1490/*
1491 *----------------------------------------------------------------------
1492 *
1493 * UpdateStringOfDouble --
1494 *
1495 * Update the string representation for a double-precision floating
1496 * point object. This must obey the current tcl_precision value for
1497 * double-to-string conversions. Note: This procedure does not free an
1498 * existing old string rep so storage will be lost if this has not
1499 * already been done.
1500 *
1501 * Results:
1502 * None.
1503 *
1504 * Side effects:
1505 * The object's string is set to a valid string that results from
1506 * the double-to-string conversion.
1507 *
1508 *----------------------------------------------------------------------
1509 */
1510
1511static void
1512UpdateStringOfDouble(objPtr)
1513 register Tcl_Obj *objPtr; /* Double obj with string rep to update. */
1514{
1515 char buffer[TCL_DOUBLE_SPACE];
1516 register int len;
1517
1518 Tcl_PrintDouble((Tcl_Interp *) NULL, objPtr->internalRep.doubleValue,
1519 buffer);
1520 len = strlen(buffer);
1521
1522 objPtr->bytes = (char *) ckalloc((unsigned) len + 1);
1523 strcpy(objPtr->bytes, buffer);
1524 objPtr->length = len;
1525}
1526
1527
1528/*
1529 *----------------------------------------------------------------------
1530 *
1531 * Tcl_NewIntObj --
1532 *
1533 * If a client is compiled with TCL_MEM_DEBUG defined, calls to
1534 * Tcl_NewIntObj to create a new integer object end up calling the
1535 * debugging procedure Tcl_DbNewLongObj instead.
1536 *
1537 * Otherwise, if the client is compiled without TCL_MEM_DEBUG defined,
1538 * calls to Tcl_NewIntObj result in a call to one of the two
1539 * Tcl_NewIntObj implementations below. We provide two implementations
1540 * so that the Tcl core can be compiled to do memory debugging of the
1541 * core even if a client does not request it for itself.
1542 *
1543 * Integer and long integer objects share the same "integer" type
1544 * implementation. We store all integers as longs and Tcl_GetIntFromObj
1545 * checks whether the current value of the long can be represented by
1546 * an int.
1547 *
1548 * Results:
1549 * The newly created object is returned. This object will have an
1550 * invalid string representation. The returned object has ref count 0.
1551 *
1552 * Side effects:
1553 * None.
1554 *
1555 *----------------------------------------------------------------------
1556 */
1557
1558#ifdef TCL_MEM_DEBUG
1559#undef Tcl_NewIntObj
1560
1561Tcl_Obj *
1562Tcl_NewIntObj(intValue)
1563 register int intValue; /* Int used to initialize the new object. */
1564{
1565 return Tcl_DbNewLongObj((long)intValue, "unknown", 0);
1566}
1567
1568#else /* if not TCL_MEM_DEBUG */
1569
1570Tcl_Obj *
1571Tcl_NewIntObj(intValue)
1572 register int intValue; /* Int used to initialize the new object. */
1573{
1574 register Tcl_Obj *objPtr;
1575
1576 TclNewObj(objPtr);
1577 objPtr->bytes = NULL;
1578
1579 objPtr->internalRep.longValue = (long)intValue;
1580 objPtr->typePtr = &tclIntType;
1581 return objPtr;
1582}
1583#endif /* if TCL_MEM_DEBUG */
1584
1585
1586/*
1587 *----------------------------------------------------------------------
1588 *
1589 * Tcl_SetIntObj --
1590 *
1591 * Modify an object to be an integer and to have the specified integer
1592 * value.
1593 *
1594 * Results:
1595 * None.
1596 *
1597 * Side effects:
1598 * The object's old string rep, if any, is freed. Also, any old
1599 * internal rep is freed.
1600 *
1601 *----------------------------------------------------------------------
1602 */
1603
1604void
1605Tcl_SetIntObj(objPtr, intValue)
1606 register Tcl_Obj *objPtr; /* Object whose internal rep to init. */
1607 register int intValue; /* Integer used to set object's value. */
1608{
1609 register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
1610
1611 if (Tcl_IsShared(objPtr)) {
1612 panic("Tcl_SetIntObj called with shared object");
1613 }
1614
1615 Tcl_InvalidateStringRep(objPtr);
1616 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
1617 oldTypePtr->freeIntRepProc(objPtr);
1618 }
1619
1620 objPtr->internalRep.longValue = (long) intValue;
1621 objPtr->typePtr = &tclIntType;
1622}
1623
1624
1625/*
1626 *----------------------------------------------------------------------
1627 *
1628 * Tcl_GetIntFromObj --
1629 *
1630 * Attempt to return an int from the Tcl object "objPtr". If the object
1631 * is not already an int, an attempt will be made to convert it to one.
1632 *
1633 * Integer and long integer objects share the same "integer" type
1634 * implementation. We store all integers as longs and Tcl_GetIntFromObj
1635 * checks whether the current value of the long can be represented by
1636 * an int.
1637 *
1638 * Results:
1639 * The return value is a standard Tcl object result. If an error occurs
1640 * during conversion or if the long integer held by the object
1641 * can not be represented by an int, an error message is left in
1642 * the interpreter's result unless "interp" is NULL.
1643 *
1644 * Side effects:
1645 * If the object is not already an int, the conversion will free
1646 * any old internal representation.
1647 *
1648 *----------------------------------------------------------------------
1649 */
1650
1651int
1652Tcl_GetIntFromObj(interp, objPtr, intPtr)
1653 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
1654 register Tcl_Obj *objPtr; /* The object from which to get a int. */
1655 register int *intPtr; /* Place to store resulting int. */
1656{
1657 register long l;
1658 int result;
1659
1660 if (objPtr->typePtr != &tclIntType) {
1661 result = SetIntFromAny(interp, objPtr);
1662 if (result != TCL_OK) {
1663 return result;
1664 }
1665 }
1666 l = objPtr->internalRep.longValue;
1667 if (((long)((int)l)) == l) {
1668 *intPtr = (int)objPtr->internalRep.longValue;
1669 return TCL_OK;
1670 }
1671 if (interp != NULL) {
1672 Tcl_ResetResult(interp);
1673 Tcl_AppendToObj(Tcl_GetObjResult(interp),
1674 "integer value too large to represent as non-long integer", -1);
1675 }
1676 return TCL_ERROR;
1677}
1678
1679
1680/*
1681 *----------------------------------------------------------------------
1682 *
1683 * DupIntInternalRep --
1684 *
1685 * Initialize the internal representation of an int Tcl_Obj to a
1686 * copy of the internal representation of an existing int object.
1687 *
1688 * Results:
1689 * None.
1690 *
1691 * Side effects:
1692 * "copyPtr"s internal rep is set to the integer corresponding to
1693 * "srcPtr"s internal rep.
1694 *
1695 *----------------------------------------------------------------------
1696 */
1697
1698static void
1699DupIntInternalRep(srcPtr, copyPtr)
1700 register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
1701 register Tcl_Obj *copyPtr; /* Object with internal rep to set. */
1702{
1703 copyPtr->internalRep.longValue = srcPtr->internalRep.longValue;
1704 copyPtr->typePtr = &tclIntType;
1705}
1706
1707
1708/*
1709 *----------------------------------------------------------------------
1710 *
1711 * SetIntFromAny --
1712 *
1713 * Attempt to generate an integer internal form for the Tcl object
1714 * "objPtr".
1715 *
1716 * Results:
1717 * The return value is a standard object Tcl result. If an error occurs
1718 * during conversion, an error message is left in the interpreter's
1719 * result unless "interp" is NULL.
1720 *
1721 * Side effects:
1722 * If no error occurs, an int is stored as "objPtr"s internal
1723 * representation.
1724 *
1725 *----------------------------------------------------------------------
1726 */
1727
1728static int
1729SetIntFromAny(interp, objPtr)
1730 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
1731 register Tcl_Obj *objPtr; /* The object to convert. */
1732{
1733 Tcl_ObjType *oldTypePtr = objPtr->typePtr;
1734 char *string, *end;
1735 int length;
1736 register char *p;
1737 long newLong;
1738
1739 /*
1740 * Get the string representation. Make it up-to-date if necessary.
1741 */
1742
1743 string = TclGetStringFromObj(objPtr, &length);
1744
1745 /*
1746 * Now parse "objPtr"s string as an int. We use an implementation here
1747 * that doesn't report errors in interp if interp is NULL. Note: use
1748 * strtoul instead of strtol for integer conversions to allow full-size
1749 * unsigned numbers, but don't depend on strtoul to handle sign
1750 * characters; it won't in some implementations.
1751 */
1752
1753 errno = 0;
1754 for (p = string; isspace(UCHAR(*p)); p++) {
1755 /* Empty loop body. */
1756 }
1757 if (*p == '-') {
1758 p++;
1759 newLong = -((long)strtoul(p, &end, 0));
1760 } else if (*p == '+') {
1761 p++;
1762 newLong = strtoul(p, &end, 0);
1763 } else {
1764 newLong = strtoul(p, &end, 0);
1765 }
1766 if (end == p) {
1767 badInteger:
1768 if (interp != NULL) {
1769 /*
1770 * Must copy string before resetting the result in case a caller
1771 * is trying to convert the interpreter's result to an int.
1772 */
1773
1774 char buf[100];
1775 sprintf(buf, "expected integer but got \"%.50s\"", string);
1776 Tcl_ResetResult(interp);
1777 Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
1778 }
1779 return TCL_ERROR;
1780 }
1781 if (errno == ERANGE) {
1782 if (interp != NULL) {
1783 char *s = "integer value too large to represent";
1784 Tcl_ResetResult(interp);
1785 Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
1786 Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
1787 }
1788 return TCL_ERROR;
1789 }
1790
1791 /*
1792 * Make sure that the string has no garbage after the end of the int.
1793 */
1794
1795 while ((end < (string+length)) && isspace(UCHAR(*end))) {
1796 end++;
1797 }
1798 if (end != (string+length)) {
1799 goto badInteger;
1800 }
1801
1802 /*
1803 * The conversion to int succeeded. Free the old internalRep before
1804 * setting the new one. We do this as late as possible to allow the
1805 * conversion code, in particular Tcl_GetStringFromObj, to use that old
1806 * internalRep.
1807 */
1808
1809 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
1810 oldTypePtr->freeIntRepProc(objPtr);
1811 }
1812
1813 objPtr->internalRep.longValue = newLong;
1814 objPtr->typePtr = &tclIntType;
1815 return TCL_OK;
1816}
1817
1818
1819/*
1820 *----------------------------------------------------------------------
1821 *
1822 * UpdateStringOfInt --
1823 *
1824 * Update the string representation for an integer object.
1825 * Note: This procedure does not free an existing old string rep
1826 * so storage will be lost if this has not already been done.
1827 *
1828 * Results:
1829 * None.
1830 *
1831 * Side effects:
1832 * The object's string is set to a valid string that results from
1833 * the int-to-string conversion.
1834 *
1835 *----------------------------------------------------------------------
1836 */
1837
1838static void
1839UpdateStringOfInt(objPtr)
1840 register Tcl_Obj *objPtr; /* Int object whose string rep to update. */
1841{
1842 char buffer[TCL_DOUBLE_SPACE];
1843 register int len;
1844
1845 len = TclFormatInt(buffer, objPtr->internalRep.longValue);
1846
1847 objPtr->bytes = ckalloc((unsigned) len + 1);
1848 strcpy(objPtr->bytes, buffer);
1849 objPtr->length = len;
1850}
1851
1852
1853/*
1854 *----------------------------------------------------------------------
1855 *
1856 * Tcl_NewLongObj --
1857 *
1858 * If a client is compiled with TCL_MEM_DEBUG defined, calls to
1859 * Tcl_NewLongObj to create a new long integer object end up calling
1860 * the debugging procedure Tcl_DbNewLongObj instead.
1861 *
1862 * Otherwise, if the client is compiled without TCL_MEM_DEBUG defined,
1863 * calls to Tcl_NewLongObj result in a call to one of the two
1864 * Tcl_NewLongObj implementations below. We provide two implementations
1865 * so that the Tcl core can be compiled to do memory debugging of the
1866 * core even if a client does not request it for itself.
1867 *
1868 * Integer and long integer objects share the same "integer" type
1869 * implementation. We store all integers as longs and Tcl_GetIntFromObj
1870 * checks whether the current value of the long can be represented by
1871 * an int.
1872 *
1873 * Results:
1874 * The newly created object is returned. This object will have an
1875 * invalid string representation. The returned object has ref count 0.
1876 *
1877 * Side effects:
1878 * None.
1879 *
1880 *----------------------------------------------------------------------
1881 */
1882
1883#ifdef TCL_MEM_DEBUG
1884#undef Tcl_NewLongObj
1885
1886Tcl_Obj *
1887Tcl_NewLongObj(longValue)
1888 register long longValue; /* Long integer used to initialize the
1889 * new object. */
1890{
1891 return Tcl_DbNewLongObj(longValue, "unknown", 0);
1892}
1893
1894#else /* if not TCL_MEM_DEBUG */
1895
1896Tcl_Obj *
1897Tcl_NewLongObj(longValue)
1898 register long longValue; /* Long integer used to initialize the
1899 * new object. */
1900{
1901 register Tcl_Obj *objPtr;
1902
1903 TclNewObj(objPtr);
1904 objPtr->bytes = NULL;
1905
1906 objPtr->internalRep.longValue = longValue;
1907 objPtr->typePtr = &tclIntType;
1908 return objPtr;
1909}
1910#endif /* if TCL_MEM_DEBUG */
1911
1912
1913/*
1914 *----------------------------------------------------------------------
1915 *
1916 * Tcl_DbNewLongObj --
1917 *
1918 * If a client is compiled with TCL_MEM_DEBUG defined, calls to
1919 * Tcl_NewIntObj and Tcl_NewLongObj to create new integer or
1920 * long integer objects end up calling the debugging procedure
1921 * Tcl_DbNewLongObj instead. We provide two implementations of
1922 * Tcl_DbNewLongObj so that whether the Tcl core is compiled to do
1923 * memory debugging of the core is independent of whether a client
1924 * requests debugging for itself.
1925 *
1926 * When the core is compiled with TCL_MEM_DEBUG defined,
1927 * Tcl_DbNewLongObj calls Tcl_DbCkalloc directly with the file name and
1928 * line number from its caller. This simplifies debugging since then
1929 * the checkmem command will report the caller's file name and line
1930 * number when reporting objects that haven't been freed.
1931 *
1932 * Otherwise, when the core is compiled without TCL_MEM_DEBUG defined,
1933 * this procedure just returns the result of calling Tcl_NewLongObj.
1934 *
1935 * Results:
1936 * The newly created long integer object is returned. This object
1937 * will have an invalid string representation. The returned object has
1938 * ref count 0.
1939 *
1940 * Side effects:
1941 * Allocates memory.
1942 *
1943 *----------------------------------------------------------------------
1944 */
1945
1946#ifdef TCL_MEM_DEBUG
1947
1948Tcl_Obj *
1949Tcl_DbNewLongObj(longValue, file, line)
1950 register long longValue; /* Long integer used to initialize the
1951 * new object. */
1952 char *file; /* The name of the source file calling this
1953 * procedure; used for debugging. */
1954 int line; /* Line number in the source file; used
1955 * for debugging. */
1956{
1957 register Tcl_Obj *objPtr;
1958
1959 TclDbNewObj(objPtr, file, line);
1960 objPtr->bytes = NULL;
1961
1962 objPtr->internalRep.longValue = longValue;
1963 objPtr->typePtr = &tclIntType;
1964 return objPtr;
1965}
1966
1967#else /* if not TCL_MEM_DEBUG */
1968
1969Tcl_Obj *
1970Tcl_DbNewLongObj(longValue, file, line)
1971 register long longValue; /* Long integer used to initialize the
1972 * new object. */
1973 char *file; /* The name of the source file calling this
1974 * procedure; used for debugging. */
1975 int line; /* Line number in the source file; used
1976 * for debugging. */
1977{
1978 return Tcl_NewLongObj(longValue);
1979}
1980#endif /* TCL_MEM_DEBUG */
1981
1982
1983/*
1984 *----------------------------------------------------------------------
1985 *
1986 * Tcl_SetLongObj --
1987 *
1988 * Modify an object to be an integer object and to have the specified
1989 * long integer value.
1990 *
1991 * Results:
1992 * None.
1993 *
1994 * Side effects:
1995 * The object's old string rep, if any, is freed. Also, any old
1996 * internal rep is freed.
1997 *
1998 *----------------------------------------------------------------------
1999 */
2000
2001void
2002Tcl_SetLongObj(objPtr, longValue)
2003 register Tcl_Obj *objPtr; /* Object whose internal rep to init. */
2004 register long longValue; /* Long integer used to initialize the
2005 * object's value. */
2006{
2007 register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
2008
2009 if (Tcl_IsShared(objPtr)) {
2010 panic("Tcl_SetLongObj called with shared object");
2011 }
2012
2013 Tcl_InvalidateStringRep(objPtr);
2014 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
2015 oldTypePtr->freeIntRepProc(objPtr);
2016 }
2017
2018 objPtr->internalRep.longValue = longValue;
2019 objPtr->typePtr = &tclIntType;
2020}
2021
2022
2023/*
2024 *----------------------------------------------------------------------
2025 *
2026 * Tcl_GetLongFromObj --
2027 *
2028 * Attempt to return an long integer from the Tcl object "objPtr". If
2029 * the object is not already an int object, an attempt will be made to
2030 * convert it to one.
2031 *
2032 * Results:
2033 * The return value is a standard Tcl object result. If an error occurs
2034 * during conversion, an error message is left in the interpreter's
2035 * result unless "interp" is NULL.
2036 *
2037 * Side effects:
2038 * If the object is not already an int object, the conversion will free
2039 * any old internal representation.
2040 *
2041 *----------------------------------------------------------------------
2042 */
2043
2044int
2045Tcl_GetLongFromObj(interp, objPtr, longPtr)
2046 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
2047 register Tcl_Obj *objPtr; /* The object from which to get a long. */
2048 register long *longPtr; /* Place to store resulting long. */
2049{
2050 register int result;
2051
2052 if (objPtr->typePtr == &tclIntType) {
2053 *longPtr = objPtr->internalRep.longValue;
2054 return TCL_OK;
2055 }
2056 result = SetIntFromAny(interp, objPtr);
2057 if (result == TCL_OK) {
2058 *longPtr = objPtr->internalRep.longValue;
2059 }
2060 return result;
2061}
2062
2063
2064/*
2065 *----------------------------------------------------------------------
2066 *
2067 * Tcl_DbIncrRefCount --
2068 *
2069 * This procedure is normally called when debugging: i.e., when
2070 * TCL_MEM_DEBUG is defined. This checks to see whether or not
2071 * the memory has been freed before incrementing the ref count.
2072 *
2073 * When TCL_MEM_DEBUG is not defined, this procedure just increments
2074 * the reference count of the object.
2075 *
2076 * Results:
2077 * None.
2078 *
2079 * Side effects:
2080 * The object's ref count is incremented.
2081 *
2082 *----------------------------------------------------------------------
2083 */
2084
2085void
2086Tcl_DbIncrRefCount(objPtr, file, line)
2087 register Tcl_Obj *objPtr; /* The object we are adding a reference to. */
2088 char *file; /* The name of the source file calling this
2089 * procedure; used for debugging. */
2090 int line; /* Line number in the source file; used
2091 * for debugging. */
2092{
2093#ifdef TCL_MEM_DEBUG
2094 if (objPtr->refCount == 0x61616161) {
2095 fprintf(stderr, "file = %s, line = %d\n", file, line);
2096 fflush(stderr);
2097 panic("Trying to increment refCount of previously disposed object.");
2098 }
2099#endif
2100 ++(objPtr)->refCount;
2101}
2102
2103
2104/*
2105 *----------------------------------------------------------------------
2106 *
2107 * Tcl_DbDecrRefCount --
2108 *
2109 * This procedure is normally called when debugging: i.e., when
2110 * TCL_MEM_DEBUG is defined. This checks to see whether or not
2111 * the memory has been freed before incrementing the ref count.
2112 *
2113 * When TCL_MEM_DEBUG is not defined, this procedure just increments
2114 * the reference count of the object.
2115 *
2116 * Results:
2117 * None.
2118 *
2119 * Side effects:
2120 * The object's ref count is incremented.
2121 *
2122 *----------------------------------------------------------------------
2123 */
2124
2125void
2126Tcl_DbDecrRefCount(objPtr, file, line)
2127 register Tcl_Obj *objPtr; /* The object we are adding a reference to. */
2128 char *file; /* The name of the source file calling this
2129 * procedure; used for debugging. */
2130 int line; /* Line number in the source file; used
2131 * for debugging. */
2132{
2133#ifdef TCL_MEM_DEBUG
2134 if (objPtr->refCount == 0x61616161) {
2135 fprintf(stderr, "file = %s, line = %d\n", file, line);
2136 fflush(stderr);
2137 panic("Trying to decrement refCount of previously disposed object.");
2138 }
2139#endif
2140 if (--(objPtr)->refCount <= 0) {
2141 TclFreeObj(objPtr);
2142 }
2143}
2144
2145
2146/*
2147 *----------------------------------------------------------------------
2148 *
2149 * Tcl_DbIsShared --
2150 *
2151 * This procedure is normally called when debugging: i.e., when
2152 * TCL_MEM_DEBUG is defined. This checks to see whether or not
2153 * the memory has been freed before incrementing the ref count.
2154 *
2155 * When TCL_MEM_DEBUG is not defined, this procedure just decrements
2156 * the reference count of the object and throws it away if the count
2157 * is 0 or less.
2158 *
2159 * Results:
2160 * None.
2161 *
2162 * Side effects:
2163 * The object's ref count is incremented.
2164 *
2165 *----------------------------------------------------------------------
2166 */
2167
2168int
2169Tcl_DbIsShared(objPtr, file, line)
2170 register Tcl_Obj *objPtr; /* The object we are adding a reference to. */
2171 char *file; /* The name of the source file calling this
2172 * procedure; used for debugging. */
2173 int line; /* Line number in the source file; used
2174 * for debugging. */
2175{
2176#ifdef TCL_MEM_DEBUG
2177 if (objPtr->refCount == 0x61616161) {
2178 fprintf(stderr, "file = %s, line = %d\n", file, line);
2179 fflush(stderr);
2180 panic("Trying to check whether previously disposed object is shared.");
2181 }
2182#endif
2183 return ((objPtr)->refCount > 1);
2184}
Note: See TracBrowser for help on using the repository browser.