@@ -546,13 +546,31 @@ SvFromTclObj(pTHX_ Tcl_Obj *objPtr)
546
546
*/
547
547
sv = newSV (0 );
548
548
}
549
- else if (objPtr -> typePtr == tclIntTypePtr ) {
550
- sv = newSViv (objPtr -> internalRep .longValue );
549
+ else if (objPtr -> typePtr == NULL ) {
550
+ goto handle_as_string ;
551
+ }
552
+ else if ((tclIntTypePtr != NULL && objPtr -> typePtr == tclIntTypePtr ) ||
553
+ (tclWideIntTypePtr != NULL && objPtr -> typePtr == tclWideIntTypePtr )) {
554
+ /*
555
+ * Tcl TIP 484 means that value type 'int' may be 64-bit (or wider?)
556
+ * even on 32-bit systems
557
+ */
558
+ Tcl_WideInt w ;
559
+ int code = Tcl_GetWideIntFromObj (NULL , objPtr , & w ); /* this must return TCL_OK */
560
+ if (IVSIZE >= sizeof (Tcl_WideInt ) ||
561
+ (w >= (Tcl_WideInt )IV_MIN && w <= (Tcl_WideInt )IV_MAX )
562
+ ) {
563
+ sv = newSViv (w );
564
+ } else if (w >= (Tcl_WideInt )UV_MIN && w <= (Tcl_WideInt )UV_MAX ) {
565
+ sv = newSVuv (w );
566
+ } else {
567
+ goto handle_as_string ;
568
+ }
551
569
}
552
570
else if (objPtr -> typePtr == tclDoubleTypePtr ) {
553
571
sv = newSVnv (objPtr -> internalRep .doubleValue );
554
572
}
555
- else if (objPtr -> typePtr == tclBooleanTypePtr ) {
573
+ else if (tclBooleanTypePtr != NULL && objPtr -> typePtr == tclBooleanTypePtr ) {
556
574
/*
557
575
* Booleans can originate as words (yes/true/...), so if there is a
558
576
* string rep, use it instead. We could check if the first byte
@@ -566,7 +584,7 @@ SvFromTclObj(pTHX_ Tcl_Obj *objPtr)
566
584
sv = newSVpvn (str , len );
567
585
}
568
586
}
569
- else if (objPtr -> typePtr == tclByteArrayTypePtr ) {
587
+ else if (tclByteArrayTypePtr != NULL && objPtr -> typePtr == tclByteArrayTypePtr ) {
570
588
str = (const char * ) Tcl_GetByteArrayFromObj (objPtr , & len );
571
589
sv = newSVpvn (str , len );
572
590
}
@@ -601,8 +619,9 @@ SvFromTclObj(pTHX_ Tcl_Obj *objPtr)
601
619
}
602
620
}
603
621
/* tclStringTypePtr is true unicode */
604
- /* tclWideIntTypePtr is 64-bit int */
622
+ /* may also be handling int/wideInt outside of [IV_MIN,UV_MAX] */
605
623
else {
624
+ handle_as_string :
606
625
str = Tcl_GetStringFromObj (objPtr , & len );
607
626
sv = newSVpvn (str , len );
608
627
/* should turn on, but let's check this first for efficiency */
@@ -1838,13 +1857,38 @@ BOOT:
1838
1857
hvInterps = newHV ();
1839
1858
}
1840
1859
1841
- tclBooleanTypePtr = Tcl_GetObjType ("boolean" );
1842
- tclByteArrayTypePtr = Tcl_GetObjType ("bytearray" );
1843
1860
tclDoubleTypePtr = Tcl_GetObjType ("double" );
1844
- tclIntTypePtr = Tcl_GetObjType ("int" );
1845
1861
tclListTypePtr = Tcl_GetObjType ("list" );
1846
1862
tclStringTypePtr = Tcl_GetObjType ("string" );
1847
- tclWideIntTypePtr = Tcl_GetObjType ("wideInt" );
1863
+ {
1864
+ /* As of Tcl 9.0, Tcl_GetObjType() returns NULL for these types */
1865
+ Tcl_Obj * objPtr ;
1866
+
1867
+ objPtr = Tcl_NewBooleanObj (0 );
1868
+ if (strcmp ("boolean" , objPtr -> typePtr -> name ) == 0 ) {
1869
+ tclBooleanTypePtr = objPtr -> typePtr ;
1870
+ }
1871
+ Tcl_DecrRefCount (objPtr );
1872
+
1873
+ objPtr = Tcl_NewIntObj (0 );
1874
+ if (strcmp ("int" , objPtr -> typePtr -> name ) == 0 ) {
1875
+ tclIntTypePtr = objPtr -> typePtr ;
1876
+ }
1877
+ Tcl_DecrRefCount (objPtr );
1878
+ #if !defined(TCL_WIDE_INT_IS_LONG ) && LONGLONGSIZE > IVSIZE
1879
+ objPtr = Tcl_NewWideIntObj ((Tcl_WideInt )IV_MIN - 1 );
1880
+ if (strcmp ("wideInt" , objPtr -> typePtr -> name ) == 0 ) {
1881
+ tclWideIntTypePtr = objPtr -> typePtr ;
1882
+ }
1883
+ Tcl_DecrRefCount (objPtr );
1884
+ #endif
1885
+
1886
+ objPtr = Tcl_NewByteArrayObj (NULL , 0 );
1887
+ if (strcmp ("bytearray" , objPtr -> typePtr -> name ) == 0 ) {
1888
+ tclByteArrayTypePtr = objPtr -> typePtr ;
1889
+ }
1890
+ Tcl_DecrRefCount (objPtr );
1891
+ }
1848
1892
1849
1893
/* set up constant subs */
1850
1894
{
0 commit comments