Index: src/printf.c ================================================================== --- src/printf.c +++ src/printf.c @@ -409,16 +409,15 @@ #endif if( infop->type==etFLOAT ) realvalue += rounder; /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ exp = 0; if( realvalue>0.0 ){ - int k = 0; - while( realvalue>=1e8 && k++<100 ){ realvalue *= 1e-8; exp+=8; } - while( realvalue>=10.0 && k++<100 ){ realvalue *= 0.1; exp++; } - while( realvalue<1e-8 && k++<100 ){ realvalue *= 1e8; exp-=8; } - while( realvalue<1.0 && k++<100 ){ realvalue *= 10.0; exp--; } - if( k>=100 ){ + while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; } + while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; } + while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; } + while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; } + if( exp>350 || exp<-350 ){ bufpt = "NaN"; length = 3; break; } } Index: src/test1.c ================================================================== --- src/test1.c +++ src/test1.c @@ -11,11 +11,11 @@ ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.34 2004/02/21 19:02:30 drh Exp $ +** $Id: test1.c,v 1.35 2004/02/21 19:41:04 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include "os.h" #include @@ -529,10 +529,40 @@ z = sqlite_mprintf(argv[1], a[0], a[1], r); Tcl_AppendResult(interp, z, 0); sqlite_freemem(z); return TCL_OK; } + +/* +** Usage: sqlite_mprintf_str FORMAT DOUBLE DOUBLE +** +** Call mprintf with a single double argument which is the product of the +** two arguments given above. This is used to generate overflow and underflow +** doubles to test that they are converted properly. +*/ +static int sqlite_mprintf_scaled( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + int i; + double r[2]; + char *z; + if( argc!=4 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FORMAT DOUBLE DOUBLE\"", 0); + return TCL_ERROR; + } + for(i=2; i<4; i++){ + if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR; + } + z = sqlite_mprintf(argv[1], r[0]*r[1]); + Tcl_AppendResult(interp, z, 0); + sqlite_freemem(z); + return TCL_OK; +} /* ** Usage: sqlite_malloc_fail N ** ** Rig sqliteMalloc() to fail on the N-th call. Turn off this mechanism @@ -950,10 +980,11 @@ Tcl_CmdProc *xProc; } aCmd[] = { { "sqlite_mprintf_int", (Tcl_CmdProc*)sqlite_mprintf_int }, { "sqlite_mprintf_str", (Tcl_CmdProc*)sqlite_mprintf_str }, { "sqlite_mprintf_double", (Tcl_CmdProc*)sqlite_mprintf_double }, + { "sqlite_mprintf_scaled", (Tcl_CmdProc*)sqlite_mprintf_scaled }, { "sqlite_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z }, { "sqlite_open", (Tcl_CmdProc*)sqlite_test_open }, { "sqlite_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid }, { "sqlite_exec_printf", (Tcl_CmdProc*)test_exec_printf }, { "sqlite_get_table_printf", (Tcl_CmdProc*)test_get_table_printf }, Index: test/printf.test ================================================================== --- test/printf.test +++ test/printf.test @@ -9,11 +9,11 @@ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the sqlite_*_printf() interface. # -# $Id: printf.test,v 1.7 2004/02/02 12:29:25 drh Exp $ +# $Id: printf.test,v 1.8 2004/02/21 19:41:05 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl set n 1 @@ -110,6 +110,17 @@ do_test printf-6.1 { sqlite_mprintf_z_test , one two three four five six } {,one,two,three,four,five,six} + +do_test printf-7.1 { + sqlite_mprintf_scaled {A double: %g} 1.0e307 1.0 +} {A double: 1e+307} +do_test printf-7.2 { + sqlite_mprintf_scaled {A double: %g} 1.0e307 10.0 +} {A double: 1e+308} +do_test printf-7.3 { + sqlite_mprintf_scaled {A double: %g} 1.0e307 100.0 +} {A double: NaN} + finish_test