Fork me on GitHub

source: git/external/tcl/tclObj.c@ c18dca6

Last change on this file since c18dca6 was adeddd8, checked in by Pavel Demin <pavel-demin@…>, 5 years ago

remove debug code from Tcl

  • Property mode set to 100644
File size: 45.7 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 * Prototypes for procedures defined later in this file:
41 */
42
43static void DupBooleanInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
44 Tcl_Obj *copyPtr));
45static void DupDoubleInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
46 Tcl_Obj *copyPtr));
47static void DupIntInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
48 Tcl_Obj *copyPtr));
49static void FinalizeTypeTable _ANSI_ARGS_((void));
50static void FinalizeFreeObjList _ANSI_ARGS_((void));
51static void InitTypeTable _ANSI_ARGS_((void));
52static int SetBooleanFromAny _ANSI_ARGS_((Tcl_Interp *interp,
53 Tcl_Obj *objPtr));
54static int SetDoubleFromAny _ANSI_ARGS_((Tcl_Interp *interp,
55 Tcl_Obj *objPtr));
56static int SetIntFromAny _ANSI_ARGS_((Tcl_Interp *interp,
57 Tcl_Obj *objPtr));
58static void UpdateStringOfBoolean _ANSI_ARGS_((Tcl_Obj *objPtr));
59static void UpdateStringOfDouble _ANSI_ARGS_((Tcl_Obj *objPtr));
60static void UpdateStringOfInt _ANSI_ARGS_((Tcl_Obj *objPtr));
61
62/*
63 * The structures below defines the Tcl object types defined in this file by
64 * means of procedures that can be invoked by generic object code. See also
65 * tclStringObj.c, tclListObj.c, tclByteCode.c for other type manager
66 * implementations.
67 */
68
69Tcl_ObjType tclBooleanType = {
70 "boolean", /* name */
71 (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
72 DupBooleanInternalRep, /* dupIntRepProc */
73 UpdateStringOfBoolean, /* updateStringProc */
74 SetBooleanFromAny /* setFromAnyProc */
75};
76
77Tcl_ObjType tclDoubleType = {
78 "double", /* name */
79 (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
80 DupDoubleInternalRep, /* dupIntRepProc */
81 UpdateStringOfDouble, /* updateStringProc */
82 SetDoubleFromAny /* setFromAnyProc */
83};
84
85Tcl_ObjType tclIntType = {
86 "int", /* name */
87 (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
88 DupIntInternalRep, /* dupIntRepProc */
89 UpdateStringOfInt, /* updateStringProc */
90 SetIntFromAny /* setFromAnyProc */
91};
92
93
94/*
95 *--------------------------------------------------------------
96 *
97 * InitTypeTable --
98 *
99 * This procedure is invoked to perform once-only initialization of
100 * the type table. It also registers the object types defined in
101 * this file.
102 *
103 * Results:
104 * None.
105 *
106 * Side effects:
107 * Initializes the table of defined object types "typeTable" with
108 * builtin object types defined in this file. It also initializes the
109 * value of tclEmptyStringRep, which points to the heap-allocated
110 * string of length zero used as the string representation for
111 * newly-created objects.
112 *
113 *--------------------------------------------------------------
114 */
115
116static void
117InitTypeTable()
118{
119 typeTableInitialized = 1;
120
121 Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS);
122 Tcl_RegisterObjType(&tclBooleanType);
123 Tcl_RegisterObjType(&tclDoubleType);
124 Tcl_RegisterObjType(&tclIntType);
125 Tcl_RegisterObjType(&tclStringType);
126 Tcl_RegisterObjType(&tclListType);
127 Tcl_RegisterObjType(&tclByteCodeType);
128 Tcl_RegisterObjType(&tclProcBodyType);
129
130 tclEmptyStringRep = (char *) ckalloc((unsigned) 1);
131 tclEmptyStringRep[0] = '\0';
132}
133
134
135/*
136 *----------------------------------------------------------------------
137 *
138 * FinalizeTypeTable --
139 *
140 * This procedure is called by Tcl_Finalize after all exit handlers
141 * have been run to free up storage associated with the table of Tcl
142 * object types.
143 *
144 * Results:
145 * None.
146 *
147 * Side effects:
148 * Deletes all entries in the hash table of object types, "typeTable".
149 * Then sets "typeTableInitialized" to 0 so that the Tcl type system
150 * will be properly reinitialized if Tcl is restarted. Also deallocates
151 * the storage for tclEmptyStringRep.
152 *
153 *----------------------------------------------------------------------
154 */
155
156static void
157FinalizeTypeTable()
158{
159 if (typeTableInitialized) {
160 Tcl_DeleteHashTable(&typeTable);
161 ckfree(tclEmptyStringRep);
162 typeTableInitialized = 0;
163 }
164}
165
166
167/*
168 *----------------------------------------------------------------------
169 *
170 * FinalizeFreeObjList --
171 *
172 * Resets the free object list so it can later be reinitialized.
173 *
174 * Results:
175 * None.
176 *
177 * Side effects:
178 * Resets the value of tclFreeObjList.
179 *
180 *----------------------------------------------------------------------
181 */
182
183static void
184FinalizeFreeObjList()
185{
186 tclFreeObjList = NULL;
187}
188
189
190/*
191 *----------------------------------------------------------------------
192 *
193 * TclFinalizeCompExecEnv --
194 *
195 * Clean up the compiler execution environment so it can later be
196 * properly reinitialized.
197 *
198 * Results:
199 * None.
200 *
201 * Side effects:
202 * Cleans up the execution environment
203 *
204 *----------------------------------------------------------------------
205 */
206
207void
208TclFinalizeCompExecEnv()
209{
210 FinalizeTypeTable();
211 FinalizeFreeObjList();
212 TclFinalizeExecEnv();
213}
214
215
216/*
217 *--------------------------------------------------------------
218 *
219 * Tcl_RegisterObjType --
220 *
221 * This procedure is called to register a new Tcl object type
222 * in the table of all object types supported by Tcl.
223 *
224 * Results:
225 * None.
226 *
227 * Side effects:
228 * The type is registered in the Tcl type table. If there was already
229 * a type with the same name as in typePtr, it is replaced with the
230 * new type.
231 *
232 *--------------------------------------------------------------
233 */
234
235void
236Tcl_RegisterObjType(typePtr)
237 Tcl_ObjType *typePtr; /* Information about object type;
238 * storage must be statically
239 * allocated (must live forever). */
240{
241 register Tcl_HashEntry *hPtr;
242 int new;
243
244 if (!typeTableInitialized) {
245 InitTypeTable();
246 }
247
248 /*
249 * If there's already an object type with the given name, remove it.
250 */
251
252 hPtr = Tcl_FindHashEntry(&typeTable, typePtr->name);
253 if (hPtr != (Tcl_HashEntry *) NULL) {
254 Tcl_DeleteHashEntry(hPtr);
255 }
256
257 /*
258 * Now insert the new object type.
259 */
260
261 hPtr = Tcl_CreateHashEntry(&typeTable, typePtr->name, &new);
262 if (new) {
263 Tcl_SetHashValue(hPtr, typePtr);
264 }
265}
266
267
268/*
269 *----------------------------------------------------------------------
270 *
271 * Tcl_AppendAllObjTypes --
272 *
273 * This procedure appends onto the argument object the name of each
274 * object type as a list element. This includes the builtin object
275 * types (e.g. int, list) as well as those added using
276 * Tcl_CreateObjType. These names can be used, for example, with
277 * Tcl_GetObjType to get pointers to the corresponding Tcl_ObjType
278 * structures.
279 *
280 * Results:
281 * The return value is normally TCL_OK; in this case the object
282 * referenced by objPtr has each type name appended to it. If an
283 * error occurs, TCL_ERROR is returned and the interpreter's result
284 * holds an error message.
285 *
286 * Side effects:
287 * If necessary, the object referenced by objPtr is converted into
288 * a list object.
289 *
290 *----------------------------------------------------------------------
291 */
292
293int
294Tcl_AppendAllObjTypes(interp, objPtr)
295 Tcl_Interp *interp; /* Interpreter used for error reporting. */
296 Tcl_Obj *objPtr; /* Points to the Tcl object onto which the
297 * name of each registered type is appended
298 * as a list element. */
299{
300 register Tcl_HashEntry *hPtr;
301 Tcl_HashSearch search;
302 Tcl_ObjType *typePtr;
303 int result;
304
305 if (!typeTableInitialized) {
306 InitTypeTable();
307 }
308
309 /*
310 * This code assumes that types names do not contain embedded NULLs.
311 */
312
313 for (hPtr = Tcl_FirstHashEntry(&typeTable, &search);
314 hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
315 typePtr = (Tcl_ObjType *) Tcl_GetHashValue(hPtr);
316 result = Tcl_ListObjAppendElement(interp, objPtr,
317 Tcl_NewStringObj(typePtr->name, -1));
318 if (result == TCL_ERROR) {
319 return result;
320 }
321 }
322 return TCL_OK;
323}
324
325
326/*
327 *----------------------------------------------------------------------
328 *
329 * Tcl_GetObjType --
330 *
331 * This procedure looks up an object type by name.
332 *
333 * Results:
334 * If an object type with name matching "typeName" is found, a pointer
335 * to its Tcl_ObjType structure is returned; otherwise, NULL is
336 * returned.
337 *
338 * Side effects:
339 * None.
340 *
341 *----------------------------------------------------------------------
342 */
343
344Tcl_ObjType *
345Tcl_GetObjType(typeName)
346 char *typeName; /* Name of Tcl object type to look up. */
347{
348 register Tcl_HashEntry *hPtr;
349 Tcl_ObjType *typePtr;
350
351 if (!typeTableInitialized) {
352 InitTypeTable();
353 }
354
355 hPtr = Tcl_FindHashEntry(&typeTable, typeName);
356 if (hPtr != (Tcl_HashEntry *) NULL) {
357 typePtr = (Tcl_ObjType *) Tcl_GetHashValue(hPtr);
358 return typePtr;
359 }
360 return NULL;
361}
362
363
364/*
365 *----------------------------------------------------------------------
366 *
367 * Tcl_ConvertToType --
368 *
369 * Convert the Tcl object "objPtr" to have type "typePtr" if possible.
370 *
371 * Results:
372 * The return value is TCL_OK on success and TCL_ERROR on failure. If
373 * TCL_ERROR is returned, then the interpreter's result contains an
374 * error message unless "interp" is NULL. Passing a NULL "interp"
375 * allows this procedure to be used as a test whether the conversion
376 * could be done (and in fact was done).
377 *
378 * Side effects:
379 * Any internal representation for the old type is freed.
380 *
381 *----------------------------------------------------------------------
382 */
383
384int
385Tcl_ConvertToType(interp, objPtr, typePtr)
386 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
387 Tcl_Obj *objPtr; /* The object to convert. */
388 Tcl_ObjType *typePtr; /* The target type. */
389{
390 if (objPtr->typePtr == typePtr) {
391 return TCL_OK;
392 }
393
394 /*
395 * Use the target type's Tcl_SetFromAnyProc to set "objPtr"s internal
396 * form as appropriate for the target type. This frees the old internal
397 * representation.
398 */
399
400 return typePtr->setFromAnyProc(interp, objPtr);
401}
402
403
404/*
405 *----------------------------------------------------------------------
406 *
407 * Tcl_NewObj --
408 *
409 * This procedure creates new Tcl objects that denote the empty string.
410 * These objects have a NULL object type and NULL string representation
411 * byte pointer. Type managers call this routine to allocate new objects
412 * that they further initialize.
413 *
414 * Results:
415 * The result is a newly allocated object that represents the empty
416 * string. The new object's typePtr is set NULL and its ref count
417 * is set to 0.
418 *
419 *----------------------------------------------------------------------
420 */
421
422Tcl_Obj *
423Tcl_NewObj()
424{
425 register Tcl_Obj *objPtr;
426
427 /*
428 * Allocate the object using the list of free Tcl_Objs we maintain.
429 */
430
431 if (tclFreeObjList == NULL) {
432 TclAllocateFreeObjects();
433 }
434 objPtr = tclFreeObjList;
435 tclFreeObjList = (Tcl_Obj *) tclFreeObjList->internalRep.otherValuePtr;
436
437 objPtr->refCount = 0;
438 objPtr->bytes = tclEmptyStringRep;
439 objPtr->length = 0;
440 objPtr->typePtr = NULL;
441 return objPtr;
442}
443
444
445/*
446 *----------------------------------------------------------------------
447 *
448 * TclAllocateFreeObjects --
449 *
450 * Procedure to allocate a number of free Tcl_Objs. This is done using
451 * a single ckalloc to reduce the overhead for Tcl_Obj allocation.
452 *
453 * Results:
454 * None.
455 *
456 * Side effects:
457 * tclFreeObjList, the head of the list of free Tcl_Objs, is set to the
458 * first of a number of free Tcl_Obj's linked together by their
459 * internalRep.otherValuePtrs.
460 *
461 *----------------------------------------------------------------------
462 */
463
464#define OBJS_TO_ALLOC_EACH_TIME 100
465
466void
467TclAllocateFreeObjects()
468{
469 Tcl_Obj tmp[2];
470 size_t objSizePlusPadding = /* NB: this assumes byte addressing. */
471 ((int)(&(tmp[1])) - (int)(&(tmp[0])));
472 size_t bytesToAlloc = (OBJS_TO_ALLOC_EACH_TIME * objSizePlusPadding);
473 char *basePtr;
474 register Tcl_Obj *prevPtr, *objPtr;
475 register int i;
476
477 basePtr = (char *) ckalloc(bytesToAlloc);
478 memset(basePtr, 0, bytesToAlloc);
479
480 prevPtr = NULL;
481 objPtr = (Tcl_Obj *) basePtr;
482 for (i = 0; i < OBJS_TO_ALLOC_EACH_TIME; i++) {
483 objPtr->internalRep.otherValuePtr = (VOID *) prevPtr;
484 prevPtr = objPtr;
485 objPtr = (Tcl_Obj *) (((char *)objPtr) + objSizePlusPadding);
486 }
487 tclFreeObjList = prevPtr;
488}
489#undef OBJS_TO_ALLOC_EACH_TIME
490
491
492/*
493 *----------------------------------------------------------------------
494 *
495 * TclFreeObj --
496 *
497 * This procedure frees the memory associated with the argument
498 * object. It is called by the tcl.h macro Tcl_DecrRefCount when an
499 * object's ref count is zero. It is only "public" since it must
500 * be callable by that macro wherever the macro is used. It should not
501 * be directly called by clients.
502 *
503 * Results:
504 * None.
505 *
506 * Side effects:
507 * Deallocates the storage for the object's Tcl_Obj structure
508 * after deallocating the string representation and calling the
509 * type-specific Tcl_FreeInternalRepProc to deallocate the object's
510 * internal representation.
511 *
512 *----------------------------------------------------------------------
513 */
514
515void
516TclFreeObj(objPtr)
517 register Tcl_Obj *objPtr; /* The object to be freed. */
518{
519 register Tcl_ObjType *typePtr = objPtr->typePtr;
520
521 Tcl_InvalidateStringRep(objPtr);
522 if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
523 typePtr->freeIntRepProc(objPtr);
524 }
525
526 /*
527 * Deallocate the object by adding it onto the list of free
528 * Tcl_Objs we maintain.
529 */
530
531 objPtr->internalRep.otherValuePtr = (VOID *) tclFreeObjList;
532 tclFreeObjList = objPtr;
533}
534
535
536/*
537 *----------------------------------------------------------------------
538 *
539 * Tcl_DuplicateObj --
540 *
541 * Create and return a new object that is a duplicate of the argument
542 * object.
543 *
544 * Results:
545 * The return value is a pointer to a newly created Tcl_Obj. This
546 * object has reference count 0 and the same type, if any, as the
547 * source object objPtr. Also:
548 * 1) If the source object has a valid string rep, we copy it;
549 * otherwise, the duplicate's string rep is set NULL to mark
550 * it invalid.
551 * 2) If the source object has an internal representation (i.e. its
552 * typePtr is non-NULL), the new object's internal rep is set to
553 * a copy; otherwise the new internal rep is marked invalid.
554 *
555 * Side effects:
556 * What constitutes "copying" the internal representation depends on
557 * the type. For example, if the argument object is a list,
558 * the element objects it points to will not actually be copied but
559 * will be shared with the duplicate list. That is, the ref counts of
560 * the element objects will be incremented.
561 *
562 *----------------------------------------------------------------------
563 */
564
565Tcl_Obj *
566Tcl_DuplicateObj(objPtr)
567 register Tcl_Obj *objPtr; /* The object to duplicate. */
568{
569 register Tcl_ObjType *typePtr = objPtr->typePtr;
570 register Tcl_Obj *dupPtr;
571
572 TclNewObj(dupPtr);
573
574 if (objPtr->bytes == NULL) {
575 dupPtr->bytes = NULL;
576 } else if (objPtr->bytes != tclEmptyStringRep) {
577 int len = objPtr->length;
578
579 dupPtr->bytes = (char *) ckalloc((unsigned) len+1);
580 if (len > 0) {
581 memcpy((VOID *) dupPtr->bytes, (VOID *) objPtr->bytes,
582 (unsigned) len);
583 }
584 dupPtr->bytes[len] = '\0';
585 dupPtr->length = len;
586 }
587
588 if (typePtr != NULL) {
589 typePtr->dupIntRepProc(objPtr, dupPtr);
590 }
591 return dupPtr;
592}
593
594
595/*
596 *----------------------------------------------------------------------
597 *
598 * Tcl_GetStringFromObj --
599 *
600 * Returns the string representation's byte array pointer and length
601 * for an object.
602 *
603 * Results:
604 * Returns a pointer to the string representation of objPtr. If
605 * lengthPtr isn't NULL, the length of the string representation is
606 * stored at *lengthPtr. The byte array referenced by the returned
607 * pointer must not be modified by the caller. Furthermore, the
608 * caller must copy the bytes if they need to retain them since the
609 * object's string rep can change as a result of other operations.
610 *
611 * Side effects:
612 * May call the object's updateStringProc to update the string
613 * representation from the internal representation.
614 *
615 *----------------------------------------------------------------------
616 */
617
618char *
619Tcl_GetStringFromObj(objPtr, lengthPtr)
620 register Tcl_Obj *objPtr; /* Object whose string rep byte pointer
621 * should be returned. */
622 register int *lengthPtr; /* If non-NULL, the location where the
623 * string rep's byte array length should be
624 * stored. If NULL, no length is stored. */
625{
626 if (objPtr->bytes != NULL) {
627 if (lengthPtr != NULL) {
628 *lengthPtr = objPtr->length;
629 }
630 return objPtr->bytes;
631 }
632
633 objPtr->typePtr->updateStringProc(objPtr);
634 if (lengthPtr != NULL) {
635 *lengthPtr = objPtr->length;
636 }
637 return objPtr->bytes;
638}
639
640
641/*
642 *----------------------------------------------------------------------
643 *
644 * Tcl_InvalidateStringRep --
645 *
646 * This procedure is called to invalidate an object's string
647 * representation.
648 *
649 * Results:
650 * None.
651 *
652 * Side effects:
653 * Deallocates the storage for any old string representation, then
654 * sets the string representation NULL to mark it invalid.
655 *
656 *----------------------------------------------------------------------
657 */
658
659void
660Tcl_InvalidateStringRep(objPtr)
661 register Tcl_Obj *objPtr; /* Object whose string rep byte pointer
662 * should be freed. */
663{
664 if (objPtr->bytes != NULL) {
665 if (objPtr->bytes != tclEmptyStringRep) {
666 ckfree((char *) objPtr->bytes);
667 }
668 objPtr->bytes = NULL;
669 }
670}
671
672
673/*
674 *----------------------------------------------------------------------
675 *
676 * Tcl_NewBooleanObj --
677 *
678 * This procedure creates a new boolean object and initializes it from
679 * the argument boolean value. A nonzero "boolValue" is coerced to 1.
680 *
681 * Results:
682 * The newly created object is returned. This object will have an
683 * invalid string representation. The returned object has ref count 0.
684 *
685 * Side effects:
686 * None.
687 *
688 *----------------------------------------------------------------------
689 */
690
691Tcl_Obj *
692Tcl_NewBooleanObj(boolValue)
693 register int boolValue; /* Boolean used to initialize new object. */
694{
695 register Tcl_Obj *objPtr;
696
697 TclNewObj(objPtr);
698 objPtr->bytes = NULL;
699
700 objPtr->internalRep.longValue = (boolValue? 1 : 0);
701 objPtr->typePtr = &tclBooleanType;
702 return objPtr;
703}
704
705
706/*
707 *----------------------------------------------------------------------
708 *
709 * Tcl_SetBooleanObj --
710 *
711 * Modify an object to be a boolean object and to have the specified
712 * boolean value. A nonzero "boolValue" is coerced to 1.
713 *
714 * Results:
715 * None.
716 *
717 * Side effects:
718 * The object's old string rep, if any, is freed. Also, any old
719 * internal rep is freed.
720 *
721 *----------------------------------------------------------------------
722 */
723
724void
725Tcl_SetBooleanObj(objPtr, boolValue)
726 register Tcl_Obj *objPtr; /* Object whose internal rep to init. */
727 register int boolValue; /* Boolean used to set object's value. */
728{
729 register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
730
731 if (Tcl_IsShared(objPtr)) {
732 panic("Tcl_SetBooleanObj called with shared object");
733 }
734
735 Tcl_InvalidateStringRep(objPtr);
736 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
737 oldTypePtr->freeIntRepProc(objPtr);
738 }
739
740 objPtr->internalRep.longValue = (boolValue? 1 : 0);
741 objPtr->typePtr = &tclBooleanType;
742}
743
744
745/*
746 *----------------------------------------------------------------------
747 *
748 * Tcl_GetBooleanFromObj --
749 *
750 * Attempt to return a boolean from the Tcl object "objPtr". If the
751 * object is not already a boolean, an attempt will be made to convert
752 * it to one.
753 *
754 * Results:
755 * The return value is a standard Tcl object result. If an error occurs
756 * during conversion, an error message is left in the interpreter's
757 * result unless "interp" is NULL.
758 *
759 * Side effects:
760 * If the object is not already a boolean, the conversion will free
761 * any old internal representation.
762 *
763 *----------------------------------------------------------------------
764 */
765
766int
767Tcl_GetBooleanFromObj(interp, objPtr, boolPtr)
768 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
769 register Tcl_Obj *objPtr; /* The object from which to get boolean. */
770 register int *boolPtr; /* Place to store resulting boolean. */
771{
772 register int result;
773
774 result = SetBooleanFromAny(interp, objPtr);
775 if (result == TCL_OK) {
776 *boolPtr = (int) objPtr->internalRep.longValue;
777 }
778 return result;
779}
780
781
782/*
783 *----------------------------------------------------------------------
784 *
785 * DupBooleanInternalRep --
786 *
787 * Initialize the internal representation of a boolean Tcl_Obj to a
788 * copy of the internal representation of an existing boolean object.
789 *
790 * Results:
791 * None.
792 *
793 * Side effects:
794 * "copyPtr"s internal rep is set to the boolean (an integer)
795 * corresponding to "srcPtr"s internal rep.
796 *
797 *----------------------------------------------------------------------
798 */
799
800static void
801DupBooleanInternalRep(srcPtr, copyPtr)
802 register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
803 register Tcl_Obj *copyPtr; /* Object with internal rep to set. */
804{
805 copyPtr->internalRep.longValue = srcPtr->internalRep.longValue;
806 copyPtr->typePtr = &tclBooleanType;
807}
808
809
810/*
811 *----------------------------------------------------------------------
812 *
813 * SetBooleanFromAny --
814 *
815 * Attempt to generate a boolean internal form for the Tcl object
816 * "objPtr".
817 *
818 * Results:
819 * The return value is a standard Tcl result. If an error occurs during
820 * conversion, an error message is left in the interpreter's result
821 * unless "interp" is NULL.
822 *
823 * Side effects:
824 * If no error occurs, an integer 1 or 0 is stored as "objPtr"s
825 * internal representation and the type of "objPtr" is set to boolean.
826 *
827 *----------------------------------------------------------------------
828 */
829
830static int
831SetBooleanFromAny(interp, objPtr)
832 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
833 register Tcl_Obj *objPtr; /* The object to convert. */
834{
835 Tcl_ObjType *oldTypePtr = objPtr->typePtr;
836 char *string, *end;
837 register char c;
838 char lowerCase[10];
839 int newBool, length;
840 register int i;
841 double dbl;
842
843 /*
844 * Get the string representation. Make it up-to-date if necessary.
845 */
846
847 string = TclGetStringFromObj(objPtr, &length);
848
849 /*
850 * Copy the string converting its characters to lower case.
851 */
852
853 for (i = 0; (i < 9) && (i < length); i++) {
854 c = string[i];
855 if (isupper(UCHAR(c))) {
856 c = (char) tolower(UCHAR(c));
857 }
858 lowerCase[i] = c;
859 }
860 lowerCase[i] = 0;
861
862 /*
863 * Parse the string as a boolean. We use an implementation here that
864 * doesn't report errors in interp if interp is NULL.
865 */
866
867 c = lowerCase[0];
868 if ((c == '0') && (lowerCase[1] == '\0')) {
869 newBool = 0;
870 } else if ((c == '1') && (lowerCase[1] == '\0')) {
871 newBool = 1;
872 } else if ((c == 'y') && (strncmp(lowerCase, "yes", (size_t) length) == 0)) {
873 newBool = 1;
874 } else if ((c == 'n') && (strncmp(lowerCase, "no", (size_t) length) == 0)) {
875 newBool = 0;
876 } else if ((c == 't') && (strncmp(lowerCase, "true", (size_t) length) == 0)) {
877 newBool = 1;
878 } else if ((c == 'f') && (strncmp(lowerCase, "false", (size_t) length) == 0)) {
879 newBool = 0;
880 } else if ((c == 'o') && (length >= 2)) {
881 if (strncmp(lowerCase, "on", (size_t) length) == 0) {
882 newBool = 1;
883 } else if (strncmp(lowerCase, "off", (size_t) length) == 0) {
884 newBool = 0;
885 } else {
886 goto badBoolean;
887 }
888 } else {
889 /*
890 * Still might be a string containing the characters representing an
891 * int or double that wasn't handled above. This would be a string
892 * like "27" or "1.0" that is non-zero and not "1". Such a string
893 * whould result in the boolean value true. We try converting to
894 * double. If that succeeds and the resulting double is non-zero, we
895 * have a "true". Note that numbers can't have embedded NULLs.
896 */
897
898 dbl = strtod(string, &end);
899 if (end == string) {
900 goto badBoolean;
901 }
902
903 /*
904 * Make sure the string has no garbage after the end of the double.
905 */
906
907 while ((end < (string+length)) && isspace(UCHAR(*end))) {
908 end++;
909 }
910 if (end != (string+length)) {
911 goto badBoolean;
912 }
913 newBool = (dbl != 0.0);
914 }
915
916 /*
917 * Free the old internalRep before setting the new one. We do this as
918 * late as possible to allow the conversion code, in particular
919 * Tcl_GetStringFromObj, to use that old internalRep.
920 */
921
922 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
923 oldTypePtr->freeIntRepProc(objPtr);
924 }
925
926 objPtr->internalRep.longValue = newBool;
927 objPtr->typePtr = &tclBooleanType;
928 return TCL_OK;
929
930 badBoolean:
931 if (interp != NULL) {
932 /*
933 * Must copy string before resetting the result in case a caller
934 * is trying to convert the interpreter's result to a boolean.
935 */
936
937 char buf[100];
938 sprintf(buf, "expected boolean value but got \"%.50s\"", string);
939 Tcl_ResetResult(interp);
940 Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
941 }
942 return TCL_ERROR;
943}
944
945
946/*
947 *----------------------------------------------------------------------
948 *
949 * UpdateStringOfBoolean --
950 *
951 * Update the string representation for a boolean object.
952 * Note: This procedure does not free an existing old string rep
953 * so storage will be lost if this has not already been done.
954 *
955 * Results:
956 * None.
957 *
958 * Side effects:
959 * The object's string is set to a valid string that results from
960 * the boolean-to-string conversion.
961 *
962 *----------------------------------------------------------------------
963 */
964
965static void
966UpdateStringOfBoolean(objPtr)
967 register Tcl_Obj *objPtr; /* Int object whose string rep to update. */
968{
969 char *s = ckalloc((unsigned) 2);
970
971 s[0] = (char) (objPtr->internalRep.longValue? '1' : '0');
972 s[1] = '\0';
973 objPtr->bytes = s;
974 objPtr->length = 1;
975}
976
977
978/*
979 *----------------------------------------------------------------------
980 *
981 * Tcl_NewDoubleObj --
982 *
983 * This procedure creates a new double object and initializes it from
984 * the argument double value.
985 *
986 * Results:
987 * The newly created object is returned. This object will have an
988 * invalid string representation. The returned object has ref count 0.
989 *
990 * Side effects:
991 * None.
992 *
993 *----------------------------------------------------------------------
994 */
995
996Tcl_Obj *
997Tcl_NewDoubleObj(dblValue)
998 register double dblValue; /* Double used to initialize the object. */
999{
1000 register Tcl_Obj *objPtr;
1001
1002 TclNewObj(objPtr);
1003 objPtr->bytes = NULL;
1004
1005 objPtr->internalRep.doubleValue = dblValue;
1006 objPtr->typePtr = &tclDoubleType;
1007 return objPtr;
1008}
1009
1010
1011/*
1012 *----------------------------------------------------------------------
1013 *
1014 * Tcl_SetDoubleObj --
1015 *
1016 * Modify an object to be a double object and to have the specified
1017 * double value.
1018 *
1019 * Results:
1020 * None.
1021 *
1022 * Side effects:
1023 * The object's old string rep, if any, is freed. Also, any old
1024 * internal rep is freed.
1025 *
1026 *----------------------------------------------------------------------
1027 */
1028
1029void
1030Tcl_SetDoubleObj(objPtr, dblValue)
1031 register Tcl_Obj *objPtr; /* Object whose internal rep to init. */
1032 register double dblValue; /* Double used to set the object's value. */
1033{
1034 register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
1035
1036 if (Tcl_IsShared(objPtr)) {
1037 panic("Tcl_SetDoubleObj called with shared object");
1038 }
1039
1040 Tcl_InvalidateStringRep(objPtr);
1041 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
1042 oldTypePtr->freeIntRepProc(objPtr);
1043 }
1044
1045 objPtr->internalRep.doubleValue = dblValue;
1046 objPtr->typePtr = &tclDoubleType;
1047}
1048
1049
1050/*
1051 *----------------------------------------------------------------------
1052 *
1053 * Tcl_GetDoubleFromObj --
1054 *
1055 * Attempt to return a double from the Tcl object "objPtr". If the
1056 * object is not already a double, an attempt will be made to convert
1057 * it to one.
1058 *
1059 * Results:
1060 * The return value is a standard Tcl object result. If an error occurs
1061 * during conversion, an error message is left in the interpreter's
1062 * result unless "interp" is NULL.
1063 *
1064 * Side effects:
1065 * If the object is not already a double, the conversion will free
1066 * any old internal representation.
1067 *
1068 *----------------------------------------------------------------------
1069 */
1070
1071int
1072Tcl_GetDoubleFromObj(interp, objPtr, dblPtr)
1073 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
1074 register Tcl_Obj *objPtr; /* The object from which to get a double. */
1075 register double *dblPtr; /* Place to store resulting double. */
1076{
1077 register int result;
1078
1079 if (objPtr->typePtr == &tclDoubleType) {
1080 *dblPtr = objPtr->internalRep.doubleValue;
1081 return TCL_OK;
1082 }
1083
1084 result = SetDoubleFromAny(interp, objPtr);
1085 if (result == TCL_OK) {
1086 *dblPtr = objPtr->internalRep.doubleValue;
1087 }
1088 return result;
1089}
1090
1091
1092/*
1093 *----------------------------------------------------------------------
1094 *
1095 * DupDoubleInternalRep --
1096 *
1097 * Initialize the internal representation of a double Tcl_Obj to a
1098 * copy of the internal representation of an existing double object.
1099 *
1100 * Results:
1101 * None.
1102 *
1103 * Side effects:
1104 * "copyPtr"s internal rep is set to the double precision floating
1105 * point number corresponding to "srcPtr"s internal rep.
1106 *
1107 *----------------------------------------------------------------------
1108 */
1109
1110static void
1111DupDoubleInternalRep(srcPtr, copyPtr)
1112 register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
1113 register Tcl_Obj *copyPtr; /* Object with internal rep to set. */
1114{
1115 copyPtr->internalRep.doubleValue = srcPtr->internalRep.doubleValue;
1116 copyPtr->typePtr = &tclDoubleType;
1117}
1118
1119
1120/*
1121 *----------------------------------------------------------------------
1122 *
1123 * SetDoubleFromAny --
1124 *
1125 * Attempt to generate an double-precision floating point internal form
1126 * for the Tcl object "objPtr".
1127 *
1128 * Results:
1129 * The return value is a standard Tcl object result. If an error occurs
1130 * during conversion, an error message is left in the interpreter's
1131 * result unless "interp" is NULL.
1132 *
1133 * Side effects:
1134 * If no error occurs, a double is stored as "objPtr"s internal
1135 * representation.
1136 *
1137 *----------------------------------------------------------------------
1138 */
1139
1140static int
1141SetDoubleFromAny(interp, objPtr)
1142 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
1143 register Tcl_Obj *objPtr; /* The object to convert. */
1144{
1145 Tcl_ObjType *oldTypePtr = objPtr->typePtr;
1146 char *string, *end;
1147 double newDouble;
1148 int length;
1149
1150 /*
1151 * Get the string representation. Make it up-to-date if necessary.
1152 */
1153
1154 string = TclGetStringFromObj(objPtr, &length);
1155
1156 /*
1157 * Now parse "objPtr"s string as an double. Numbers can't have embedded
1158 * NULLs. We use an implementation here that doesn't report errors in
1159 * interp if interp is NULL.
1160 */
1161
1162 errno = 0;
1163 newDouble = strtod(string, &end);
1164 if (end == string) {
1165 badDouble:
1166 if (interp != NULL) {
1167 /*
1168 * Must copy string before resetting the result in case a caller
1169 * is trying to convert the interpreter's result to an int.
1170 */
1171
1172 char buf[100];
1173 sprintf(buf, "expected floating-point number but got \"%.50s\"",
1174 string);
1175 Tcl_ResetResult(interp);
1176 Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
1177 }
1178 return TCL_ERROR;
1179 }
1180 if (errno != 0) {
1181 if (interp != NULL) {
1182 TclExprFloatError(interp, newDouble);
1183 }
1184 return TCL_ERROR;
1185 }
1186
1187 /*
1188 * Make sure that the string has no garbage after the end of the double.
1189 */
1190
1191 while ((end < (string+length)) && isspace(UCHAR(*end))) {
1192 end++;
1193 }
1194 if (end != (string+length)) {
1195 goto badDouble;
1196 }
1197
1198 /*
1199 * The conversion to double succeeded. Free the old internalRep before
1200 * setting the new one. We do this as late as possible to allow the
1201 * conversion code, in particular Tcl_GetStringFromObj, to use that old
1202 * internalRep.
1203 */
1204
1205 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
1206 oldTypePtr->freeIntRepProc(objPtr);
1207 }
1208
1209 objPtr->internalRep.doubleValue = newDouble;
1210 objPtr->typePtr = &tclDoubleType;
1211 return TCL_OK;
1212}
1213
1214
1215/*
1216 *----------------------------------------------------------------------
1217 *
1218 * UpdateStringOfDouble --
1219 *
1220 * Update the string representation for a double-precision floating
1221 * point object. This must obey the current tcl_precision value for
1222 * double-to-string conversions. Note: This procedure does not free an
1223 * existing old string rep so storage will be lost if this has not
1224 * already been done.
1225 *
1226 * Results:
1227 * None.
1228 *
1229 * Side effects:
1230 * The object's string is set to a valid string that results from
1231 * the double-to-string conversion.
1232 *
1233 *----------------------------------------------------------------------
1234 */
1235
1236static void
1237UpdateStringOfDouble(objPtr)
1238 register Tcl_Obj *objPtr; /* Double obj with string rep to update. */
1239{
1240 char buffer[TCL_DOUBLE_SPACE];
1241 register int len;
1242
1243 Tcl_PrintDouble((Tcl_Interp *) NULL, objPtr->internalRep.doubleValue,
1244 buffer);
1245 len = strlen(buffer);
1246
1247 objPtr->bytes = (char *) ckalloc((unsigned) len + 1);
1248 strcpy(objPtr->bytes, buffer);
1249 objPtr->length = len;
1250}
1251
1252
1253/*
1254 *----------------------------------------------------------------------
1255 *
1256 * Tcl_NewIntObj --
1257 *
1258 * Calls to Tcl_NewIntObj result in a call to one of the two
1259 * Tcl_NewIntObj implementations below. We provide two implementations
1260 * so that the Tcl core can be compiled to do memory debugging of the
1261 * core even if a client does not request it for itself.
1262 *
1263 * Integer and long integer objects share the same "integer" type
1264 * implementation. We store all integers as longs and Tcl_GetIntFromObj
1265 * checks whether the current value of the long can be represented by
1266 * an int.
1267 *
1268 * Results:
1269 * The newly created object is returned. This object will have an
1270 * invalid string representation. The returned object has ref count 0.
1271 *
1272 * Side effects:
1273 * None.
1274 *
1275 *----------------------------------------------------------------------
1276 */
1277
1278Tcl_Obj *
1279Tcl_NewIntObj(intValue)
1280 register int intValue; /* Int used to initialize the new object. */
1281{
1282 register Tcl_Obj *objPtr;
1283
1284 TclNewObj(objPtr);
1285 objPtr->bytes = NULL;
1286
1287 objPtr->internalRep.longValue = (long)intValue;
1288 objPtr->typePtr = &tclIntType;
1289 return objPtr;
1290}
1291
1292
1293/*
1294 *----------------------------------------------------------------------
1295 *
1296 * Tcl_SetIntObj --
1297 *
1298 * Modify an object to be an integer and to have the specified integer
1299 * value.
1300 *
1301 * Results:
1302 * None.
1303 *
1304 * Side effects:
1305 * The object's old string rep, if any, is freed. Also, any old
1306 * internal rep is freed.
1307 *
1308 *----------------------------------------------------------------------
1309 */
1310
1311void
1312Tcl_SetIntObj(objPtr, intValue)
1313 register Tcl_Obj *objPtr; /* Object whose internal rep to init. */
1314 register int intValue; /* Integer used to set object's value. */
1315{
1316 register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
1317
1318 if (Tcl_IsShared(objPtr)) {
1319 panic("Tcl_SetIntObj called with shared object");
1320 }
1321
1322 Tcl_InvalidateStringRep(objPtr);
1323 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
1324 oldTypePtr->freeIntRepProc(objPtr);
1325 }
1326
1327 objPtr->internalRep.longValue = (long) intValue;
1328 objPtr->typePtr = &tclIntType;
1329}
1330
1331
1332/*
1333 *----------------------------------------------------------------------
1334 *
1335 * Tcl_GetIntFromObj --
1336 *
1337 * Attempt to return an int from the Tcl object "objPtr". If the object
1338 * is not already an int, an attempt will be made to convert it to one.
1339 *
1340 * Integer and long integer objects share the same "integer" type
1341 * implementation. We store all integers as longs and Tcl_GetIntFromObj
1342 * checks whether the current value of the long can be represented by
1343 * an int.
1344 *
1345 * Results:
1346 * The return value is a standard Tcl object result. If an error occurs
1347 * during conversion or if the long integer held by the object
1348 * can not be represented by an int, an error message is left in
1349 * the interpreter's result unless "interp" is NULL.
1350 *
1351 * Side effects:
1352 * If the object is not already an int, the conversion will free
1353 * any old internal representation.
1354 *
1355 *----------------------------------------------------------------------
1356 */
1357
1358int
1359Tcl_GetIntFromObj(interp, objPtr, intPtr)
1360 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
1361 register Tcl_Obj *objPtr; /* The object from which to get a int. */
1362 register int *intPtr; /* Place to store resulting int. */
1363{
1364 register long l;
1365 int result;
1366
1367 if (objPtr->typePtr != &tclIntType) {
1368 result = SetIntFromAny(interp, objPtr);
1369 if (result != TCL_OK) {
1370 return result;
1371 }
1372 }
1373 l = objPtr->internalRep.longValue;
1374 if (((long)((int)l)) == l) {
1375 *intPtr = (int)objPtr->internalRep.longValue;
1376 return TCL_OK;
1377 }
1378 if (interp != NULL) {
1379 Tcl_ResetResult(interp);
1380 Tcl_AppendToObj(Tcl_GetObjResult(interp),
1381 "integer value too large to represent as non-long integer", -1);
1382 }
1383 return TCL_ERROR;
1384}
1385
1386
1387/*
1388 *----------------------------------------------------------------------
1389 *
1390 * DupIntInternalRep --
1391 *
1392 * Initialize the internal representation of an int Tcl_Obj to a
1393 * copy of the internal representation of an existing int object.
1394 *
1395 * Results:
1396 * None.
1397 *
1398 * Side effects:
1399 * "copyPtr"s internal rep is set to the integer corresponding to
1400 * "srcPtr"s internal rep.
1401 *
1402 *----------------------------------------------------------------------
1403 */
1404
1405static void
1406DupIntInternalRep(srcPtr, copyPtr)
1407 register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
1408 register Tcl_Obj *copyPtr; /* Object with internal rep to set. */
1409{
1410 copyPtr->internalRep.longValue = srcPtr->internalRep.longValue;
1411 copyPtr->typePtr = &tclIntType;
1412}
1413
1414
1415/*
1416 *----------------------------------------------------------------------
1417 *
1418 * SetIntFromAny --
1419 *
1420 * Attempt to generate an integer internal form for the Tcl object
1421 * "objPtr".
1422 *
1423 * Results:
1424 * The return value is a standard object Tcl result. If an error occurs
1425 * during conversion, an error message is left in the interpreter's
1426 * result unless "interp" is NULL.
1427 *
1428 * Side effects:
1429 * If no error occurs, an int is stored as "objPtr"s internal
1430 * representation.
1431 *
1432 *----------------------------------------------------------------------
1433 */
1434
1435static int
1436SetIntFromAny(interp, objPtr)
1437 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
1438 register Tcl_Obj *objPtr; /* The object to convert. */
1439{
1440 Tcl_ObjType *oldTypePtr = objPtr->typePtr;
1441 char *string, *end;
1442 int length;
1443 register char *p;
1444 long newLong;
1445
1446 /*
1447 * Get the string representation. Make it up-to-date if necessary.
1448 */
1449
1450 string = TclGetStringFromObj(objPtr, &length);
1451
1452 /*
1453 * Now parse "objPtr"s string as an int. We use an implementation here
1454 * that doesn't report errors in interp if interp is NULL. Note: use
1455 * strtoul instead of strtol for integer conversions to allow full-size
1456 * unsigned numbers, but don't depend on strtoul to handle sign
1457 * characters; it won't in some implementations.
1458 */
1459
1460 errno = 0;
1461 for (p = string; isspace(UCHAR(*p)); p++) {
1462 /* Empty loop body. */
1463 }
1464 if (*p == '-') {
1465 p++;
1466 newLong = -((long)strtoul(p, &end, 0));
1467 } else if (*p == '+') {
1468 p++;
1469 newLong = strtoul(p, &end, 0);
1470 } else {
1471 newLong = strtoul(p, &end, 0);
1472 }
1473 if (end == p) {
1474 badInteger:
1475 if (interp != NULL) {
1476 /*
1477 * Must copy string before resetting the result in case a caller
1478 * is trying to convert the interpreter's result to an int.
1479 */
1480
1481 char buf[100];
1482 sprintf(buf, "expected integer but got \"%.50s\"", string);
1483 Tcl_ResetResult(interp);
1484 Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
1485 }
1486 return TCL_ERROR;
1487 }
1488 if (errno == ERANGE) {
1489 if (interp != NULL) {
1490 char *s = "integer value too large to represent";
1491 Tcl_ResetResult(interp);
1492 Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
1493 Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
1494 }
1495 return TCL_ERROR;
1496 }
1497
1498 /*
1499 * Make sure that the string has no garbage after the end of the int.
1500 */
1501
1502 while ((end < (string+length)) && isspace(UCHAR(*end))) {
1503 end++;
1504 }
1505 if (end != (string+length)) {
1506 goto badInteger;
1507 }
1508
1509 /*
1510 * The conversion to int succeeded. Free the old internalRep before
1511 * setting the new one. We do this as late as possible to allow the
1512 * conversion code, in particular Tcl_GetStringFromObj, to use that old
1513 * internalRep.
1514 */
1515
1516 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
1517 oldTypePtr->freeIntRepProc(objPtr);
1518 }
1519
1520 objPtr->internalRep.longValue = newLong;
1521 objPtr->typePtr = &tclIntType;
1522 return TCL_OK;
1523}
1524
1525
1526/*
1527 *----------------------------------------------------------------------
1528 *
1529 * UpdateStringOfInt --
1530 *
1531 * Update the string representation for an integer object.
1532 * Note: This procedure does not free an existing old string rep
1533 * so storage will be lost if this has not already been done.
1534 *
1535 * Results:
1536 * None.
1537 *
1538 * Side effects:
1539 * The object's string is set to a valid string that results from
1540 * the int-to-string conversion.
1541 *
1542 *----------------------------------------------------------------------
1543 */
1544
1545static void
1546UpdateStringOfInt(objPtr)
1547 register Tcl_Obj *objPtr; /* Int object whose string rep to update. */
1548{
1549 char buffer[TCL_DOUBLE_SPACE];
1550 register int len;
1551
1552 len = TclFormatInt(buffer, objPtr->internalRep.longValue);
1553
1554 objPtr->bytes = ckalloc((unsigned) len + 1);
1555 strcpy(objPtr->bytes, buffer);
1556 objPtr->length = len;
1557}
1558
1559
1560/*
1561 *----------------------------------------------------------------------
1562 *
1563 * Tcl_NewLongObj --
1564 *
1565 * Calls to Tcl_NewLongObj result in a call to one of the two
1566 * Tcl_NewLongObj implementations below. We provide two implementations
1567 * so that the Tcl core can be compiled to do memory debugging of the
1568 * core even if a client does not request it for itself.
1569 *
1570 * Integer and long integer objects share the same "integer" type
1571 * implementation. We store all integers as longs and Tcl_GetIntFromObj
1572 * checks whether the current value of the long can be represented by
1573 * an int.
1574 *
1575 * Results:
1576 * The newly created object is returned. This object will have an
1577 * invalid string representation. The returned object has ref count 0.
1578 *
1579 * Side effects:
1580 * None.
1581 *
1582 *----------------------------------------------------------------------
1583 */
1584
1585Tcl_Obj *
1586Tcl_NewLongObj(longValue)
1587 register long longValue; /* Long integer used to initialize the
1588 * new object. */
1589{
1590 register Tcl_Obj *objPtr;
1591
1592 TclNewObj(objPtr);
1593 objPtr->bytes = NULL;
1594
1595 objPtr->internalRep.longValue = longValue;
1596 objPtr->typePtr = &tclIntType;
1597 return objPtr;
1598}
1599
1600
1601/*
1602 *----------------------------------------------------------------------
1603 *
1604 * Tcl_DbNewLongObj --
1605 *
1606 * This procedure just returns the result of calling Tcl_NewLongObj.
1607 *
1608 * Results:
1609 * The newly created long integer object is returned. This object
1610 * will have an invalid string representation. The returned object has
1611 * ref count 0.
1612 *
1613 * Side effects:
1614 * Allocates memory.
1615 *
1616 *----------------------------------------------------------------------
1617 */
1618
1619Tcl_Obj *
1620Tcl_DbNewLongObj(longValue, file, line)
1621 register long longValue; /* Long integer used to initialize the
1622 * new object. */
1623 char *file; /* The name of the source file calling this
1624 * procedure; used for debugging. */
1625 int line; /* Line number in the source file; used
1626 * for debugging. */
1627{
1628 return Tcl_NewLongObj(longValue);
1629}
1630
1631
1632/*
1633 *----------------------------------------------------------------------
1634 *
1635 * Tcl_SetLongObj --
1636 *
1637 * Modify an object to be an integer object and to have the specified
1638 * long integer value.
1639 *
1640 * Results:
1641 * None.
1642 *
1643 * Side effects:
1644 * The object's old string rep, if any, is freed. Also, any old
1645 * internal rep is freed.
1646 *
1647 *----------------------------------------------------------------------
1648 */
1649
1650void
1651Tcl_SetLongObj(objPtr, longValue)
1652 register Tcl_Obj *objPtr; /* Object whose internal rep to init. */
1653 register long longValue; /* Long integer used to initialize the
1654 * object's value. */
1655{
1656 register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
1657
1658 if (Tcl_IsShared(objPtr)) {
1659 panic("Tcl_SetLongObj called with shared object");
1660 }
1661
1662 Tcl_InvalidateStringRep(objPtr);
1663 if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
1664 oldTypePtr->freeIntRepProc(objPtr);
1665 }
1666
1667 objPtr->internalRep.longValue = longValue;
1668 objPtr->typePtr = &tclIntType;
1669}
1670
1671
1672/*
1673 *----------------------------------------------------------------------
1674 *
1675 * Tcl_GetLongFromObj --
1676 *
1677 * Attempt to return an long integer from the Tcl object "objPtr". If
1678 * the object is not already an int object, an attempt will be made to
1679 * convert it to one.
1680 *
1681 * Results:
1682 * The return value is a standard Tcl object result. If an error occurs
1683 * during conversion, an error message is left in the interpreter's
1684 * result unless "interp" is NULL.
1685 *
1686 * Side effects:
1687 * If the object is not already an int object, the conversion will free
1688 * any old internal representation.
1689 *
1690 *----------------------------------------------------------------------
1691 */
1692
1693int
1694Tcl_GetLongFromObj(interp, objPtr, longPtr)
1695 Tcl_Interp *interp; /* Used for error reporting if not NULL. */
1696 register Tcl_Obj *objPtr; /* The object from which to get a long. */
1697 register long *longPtr; /* Place to store resulting long. */
1698{
1699 register int result;
1700
1701 if (objPtr->typePtr == &tclIntType) {
1702 *longPtr = objPtr->internalRep.longValue;
1703 return TCL_OK;
1704 }
1705 result = SetIntFromAny(interp, objPtr);
1706 if (result == TCL_OK) {
1707 *longPtr = objPtr->internalRep.longValue;
1708 }
1709 return result;
1710}
Note: See TracBrowser for help on using the repository browser.