summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2005-09-12 19:12:27 (GMT)
committerdgp <dgp@users.sourceforge.net>2005-09-12 19:12:27 (GMT)
commit3218809d9a888f4b5a70d09e8d518e57096b1a94 (patch)
treeff51879651981cfdd916310dca02c20ce38f51d6
parent370d515c007d39a48553f63862bbbb9afc9e54d9 (diff)
downloadtcl-3218809d9a888f4b5a70d09e8d518e57096b1a94.zip
tcl-3218809d9a888f4b5a70d09e8d518e57096b1a94.tar.gz
tcl-3218809d9a888f4b5a70d09e8d518e57096b1a94.tar.bz2
* generic/tclCmdAH.c: Added support for the "ll" width
* generic/tclStringObj.c: specifier to [format].
-rw-r--r--ChangeLog3
-rw-r--r--generic/tclCmdAH.c4
-rw-r--r--generic/tclStringObj.c123
3 files changed, 92 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index 6f62b46..9608b06 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 {