diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | generic/tclCmdAH.c | 4 | ||||
-rw-r--r-- | generic/tclStringObj.c | 123 |
3 files changed, 92 insertions, 38 deletions
@@ -2,6 +2,9 @@ [kennykb-numerics-branch] Merge updates from HEAD. + * generic/tclCmdAH.c: Added support for the "ll" width + * generic/tclStringObj.c: specifier to [format]. + * generic/tclStringObj.c (TclAppendFormattedObjs): Bug fix: make sure %ld formats force the collection of a wide value, when the value could be a different long. diff --git a/generic/tclCmdAH.c b/generic/tclCmdAH.c index 33fe242..b59df68 100644 --- a/generic/tclCmdAH.c +++ b/generic/tclCmdAH.c @@ -10,12 +10,14 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclCmdAH.c,v 1.57.2.8 2005/09/09 18:48:40 dgp Exp $ + * RCS: @(#) $Id: tclCmdAH.c,v 1.57.2.9 2005/09/12 19:12:27 dgp Exp $ */ #include "tclInt.h" #include <locale.h> +#define NEW_FORMAT 1 + /* * Prototypes for local procedures defined in this file: */ diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index b55ffeb..73a559f 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -33,9 +33,10 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclStringObj.c,v 1.35.2.6 2005/09/12 14:47:16 dgp Exp $ */ + * RCS: @(#) $Id: tclStringObj.c,v 1.35.2.7 2005/09/12 19:12:27 dgp Exp $ */ #include "tclInt.h" +#include "tommath.h" /* * Prototypes for functions defined later in this file: @@ -1723,7 +1724,7 @@ TclAppendFormattedObjs(interp, baseObj, format, objc, objv) while (*format != '\0') { char *end; int gotMinus, gotHash, gotZero, gotSpace, gotPlus, sawFlag; - int width, gotPrecision, precision, useShort, useWide; + int width, gotPrecision, precision, useShort, useWide, useBig; int newXpg, numChars, allocSegment = 0; Tcl_Obj *segment; Tcl_UniChar ch; @@ -1866,17 +1867,23 @@ TclAppendFormattedObjs(interp, baseObj, format, objc, objv) /* 5. Length modifier */ - useShort = useWide = 0; + useShort = useWide = useBig = 0; if (ch == 'h') { useShort = 1; format += step; step = Tcl_UtfToUniChar(format, &ch); } else if (ch == 'l') { + format += step; + step = Tcl_UtfToUniChar(format, &ch); + if (ch == 'l') { + useBig = 1; + format += step; + step = Tcl_UtfToUniChar(format, &ch); + } else { #ifndef TCL_WIDE_INT_IS_LONG useWide = 1; #endif - format += step; - step = Tcl_UtfToUniChar(format, &ch); + } } format += step; @@ -1914,6 +1921,10 @@ TclAppendFormattedObjs(interp, baseObj, format, objc, objv) } case 'u': + if (useBig) { + msg = "unsigned bignum format is invalid"; + goto errorMsg; + } case 'd': case 'o': case 'x': @@ -1921,26 +1932,54 @@ TclAppendFormattedObjs(interp, baseObj, format, objc, objv) short int s; long l; Tcl_WideInt w; + mp_int big; int isNegative = 0; - if (useWide) { - if (Tcl_GetWideIntFromObj(interp, segment, &w) != TCL_OK) { + if (useBig) { + if (Tcl_GetBignumFromObj(interp, segment, &big) != TCL_OK) { goto error; } - } else if (Tcl_GetLongFromObj(NULL, segment, &l) != TCL_OK) { - if (Tcl_GetWideIntFromObj(interp, segment, &w) != TCL_OK) { - goto error; - } - l = Tcl_WideAsLong(w); - } - - if (useShort) { - s = (short int) l; - isNegative = (s < (short int)0); + isNegative = (big.sign == MP_NEG); } else if (useWide) { + if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) { + Tcl_Obj *objPtr; + if (Tcl_GetBignumFromObj(interp, segment, &big) != TCL_OK) { + goto error; + } + mp_mod_2d(&big, (int) CHAR_BIT * sizeof(Tcl_WideInt), &big); + objPtr = Tcl_NewBignumObj(&big); + Tcl_IncrRefCount(objPtr); + Tcl_GetWideIntFromObj(NULL, objPtr, &w); + Tcl_DecrRefCount(objPtr); + } isNegative = (w < (Tcl_WideInt)0); + } else if (Tcl_GetLongFromObj(NULL, segment, &l) != TCL_OK) { + if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) { + Tcl_Obj *objPtr; + if (Tcl_GetBignumFromObj(interp, segment, &big) != TCL_OK) { + goto error; + } + mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big); + objPtr = Tcl_NewBignumObj(&big); + Tcl_IncrRefCount(objPtr); + Tcl_GetLongFromObj(NULL, objPtr, &l); + Tcl_DecrRefCount(objPtr); + } else { + l = Tcl_WideAsLong(w); + } + if (useShort) { + s = (short int) l; + isNegative = (s < (short int)0); + } else { + isNegative = (l < (long)0); + } } else { - isNegative = (l < (long)0); + if (useShort) { + s = (short int) l; + isNegative = (s < (short int)0); + } else { + isNegative = (l < (long)0); + } } segment = Tcl_NewObj(); @@ -1948,7 +1987,7 @@ TclAppendFormattedObjs(interp, baseObj, format, objc, objv) Tcl_IncrRefCount(segment); if (isNegative || gotPlus) { - if (ch == 'd') { + if (useBig || (ch == 'd')) { if (isNegative) { Tcl_AppendToObj(segment, "-", 1); } else { @@ -1976,26 +2015,18 @@ TclAppendFormattedObjs(interp, baseObj, format, objc, objv) Tcl_Obj *pure; CONST char *bytes; - if (isNegative) { - if (useShort) { - pure = Tcl_NewIntObj((int)(-s)); - } else if (useWide) { - pure = Tcl_NewWideIntObj(-w); - } else { - pure = Tcl_NewLongObj(-l); - } + if (useShort) { + pure = Tcl_NewIntObj((int)(s)); + } else if (useWide) { + pure = Tcl_NewWideIntObj(w); + } else if (useBig) { + pure = Tcl_NewBignumObj(&big); } else { - if (useShort) { - pure = Tcl_NewIntObj((int)(s)); - } else if (useWide) { - pure = Tcl_NewWideIntObj(w); - } else { - pure = Tcl_NewLongObj(l); - } + pure = Tcl_NewLongObj(l); } Tcl_IncrRefCount(pure); bytes = Tcl_GetStringFromObj(pure, &length); - /* Handle things like -INT_MIN == INT_MIN */ + /* Already did the sign above */ if (*bytes == '-') { length--; bytes++; } @@ -2026,7 +2057,8 @@ TclAppendFormattedObjs(interp, baseObj, format, objc, objv) case 'x': case 'X': { Tcl_WideUInt bits; - int length, numDigits = 0, base = 16; + int length, numBits = 4, numDigits = 0, base = 16; + int index = 0, shift = 0; Tcl_Obj *pure; char *bytes; @@ -2035,6 +2067,7 @@ TclAppendFormattedObjs(interp, baseObj, format, objc, objv) } if (ch == 'o') { base = 8; + numBits = 3; } if (useShort) { unsigned short int us = (unsigned short int) s; @@ -2050,6 +2083,14 @@ TclAppendFormattedObjs(interp, baseObj, format, objc, objv) numDigits++; uw /= base; } + } else if (useBig) { + int leftover = (big.used * DIGIT_BIT) % numBits; + mp_digit mask = (~(mp_digit)0) << (DIGIT_BIT-leftover); + numDigits = 1 + ((big.used * DIGIT_BIT) / numBits); + while ((mask & big.dp[big.used-1]) == 0) { + numDigits--; + mask >>= numBits; + } } else { unsigned long int ul = (unsigned long int) l; bits = (Tcl_WideUInt) ul; @@ -2067,7 +2108,15 @@ TclAppendFormattedObjs(interp, baseObj, format, objc, objv) bytes = Tcl_GetString(pure); length = numDigits; while (numDigits--) { - int digitOffset = (int) (bits % base); + int digitOffset; + if (useBig) { + if (shift<CHAR_BIT*sizeof(Tcl_WideUInt)-DIGIT_BIT) { + bits |= (big.dp[index++] << shift); + shift += DIGIT_BIT; + } + shift -= numBits; + } + digitOffset = (int) (bits % base); if (digitOffset > 9) { bytes[numDigits] = 'a' + digitOffset - 10; } else { |