|
From: Naftali S. <nsc...@gm...> - 2012-07-20 04:12:19
|
Here's a patch I developed to add missing '%f' functionality to
VG_(printf). Floating point formatting code comes from dietlib.
This is my first patch to Valgrind (so you can go easy on me). And I have
a couple more in the pipeline...
--- m_debuglog.c 2011-10-26 17:24:45.000000000 -0400
+++ m_debuglog.c 2012-02-20 15:23:55.882688040 -0500
@@ -415,4 +456,20 @@
}
+static Char* local_strchr ( const Char* s, Char c )
+{
+ while (True) {
+ if (*s == c) return (Char*)s;
+ if (*s == 0) return NULL;
+ s++;
+ }
+}
+static Char* local_strcpy ( Char* dest, const Char* src )
+{
+ Char* dest_orig = dest;
+ while (*src) *dest++ = *src++;
+ *dest = 0;
+ return dest_orig;
+}
+
static HChar local_toupper ( HChar c )
{
@@ -538,4 +595,81 @@
+/* From dietlibc-0.31 */
+static int __dtostr( double d, char *buf, UInt maxlen, UInt prec, UInt
prec2, int g )
+{
+ union { unsigned long long l; double d; } u = { .d = d };
+ signed long e = ((u.l>>52)&((1<<11)-1)) - 1023, e10 = 1 +
(long)(e*0.30102999566398119802); /* log10(2) */
+ UInt i; double backup = d, tmp; char *oldbuf = buf;
+ if ( d == 0.0 ) { prec2 = prec2==0 ? 1 : prec2+2; prec2 = prec2>maxlen ?
8 : prec2; i=0; if ( prec2 && (long long)u.l < 0 ) { buf[0]='-'; ++i; }
+ for ( ; i < prec2; ++i) buf[i] = '0'; buf[buf[0]=='0'?1:2] = '.'; buf[i]
= 0; return i; }
+ if ( d < 0.0 ) { d=-d; *buf='-'; --maxlen; ++buf; }
+ tmp = 0.5; for ( i = 0; i < prec2; i++ ) { tmp *= 0.1; } d += tmp;
+ if ( d < 1.0 ) { *buf = '0'; --maxlen; ++buf; }
+ if ( e10 > 0 )
+ {
+ int first = 1; tmp = 10.0; i = e10; while ( i > 10 ) { tmp = tmp * 1e10;
i -= 10; } while ( i > 1 ) { tmp = tmp * 10; --i; }
+ while ( tmp > 0.9 ) { double fraction = d/tmp; char digit =
(int)fraction; if ( !first || digit ) {
+ first = 0; *buf = digit + '0'; ++buf;
+ if ( !maxlen ) /* use scientific notation */
+ {
+ int len = __dtostr( backup/tmp, oldbuf, maxlen, prec, prec2, 0 );
+ int initial = 1; if ( len == 0 ) return 0; maxlen -= len; buf += len;
+ if ( maxlen > 0 ) { *buf='e'; ++buf; } --maxlen;
+ for ( len = 1000; len > 0; len /= 10 ) if ( e10 >= len || !initial )
+ { if ( maxlen > 0 ) { *buf = (e10/len) + '0'; ++buf; } --maxlen; initial
= 0; e10 = e10%len; }
+ if ( maxlen > 0 ) goto fini;
+ return 0;
+ }
+ d -= digit * tmp; --maxlen;
+ } tmp /= 10.0; }
+ } else { tmp = 0.1; }
+ if ( buf == oldbuf) { if ( !maxlen ) return 0; --maxlen; *buf = '0';
++buf; }
+ if ( prec2 || prec > (UInt)(buf - oldbuf) + 1 ) /* more digits wanted */
+ {
+ if ( !maxlen ) return 0; --maxlen; *buf = '.'; ++buf;
+ if ( g ) { if ( prec2 ) prec = prec2; prec -= buf - oldbuf - 1; } else {
prec -= buf - oldbuf - 1; if ( prec2 ) prec = prec2; }
+ if ( prec > maxlen ) return 0;
+ while ( prec > 0 ) { double fraction = d/tmp; char digit = (int)fraction;
*buf = digit + '0'; ++buf; d -= digit * tmp; tmp /= 10.0; --prec; }
+ }
+fini: *buf = 0;
+ return buf - oldbuf;
+}
+
+#define A_WRITE(buf,sz) { int _; for ( _ = 0; _ < sz; _++ ) send(
buf[_], send_arg2 ); }
+#define B_WRITE(buf,sz) { if ((unsigned long)(sz) > (((unsigned
long)(int)(-1))>>1) || len+(int)(sz)<len) return -1; A_WRITE( buf, sz ); }
while (0)
+
+static int write_pad( UInt* dlen, void (*send)(HChar,void*), void*
send_arg2, UInt len, const char *padding) { int nr=0; if
(len<0||*dlen+len<len) return -1;
+ for (;len>15;len-=16,nr+=16) { A_WRITE( padding, 16 ); } if (len>0) {
A_WRITE( padding, len ); nr+=len; } *dlen += nr; return 0; }
+
+static
+UInt myvprintf_float32 ( void (*send)(HChar,void*), void* send_arg2, Int
flags, Int g, Int width, Int preci, double d )
+{
+ static const char spaces[16] = " ", zeros[16] =
"0000000000000000";
+ UInt len = 0;
+ char buf[500];
+ char *s = buf + 1, *sign = s;
+ int todo = d < +0.0;
+ unsigned long sz = __dtostr( d, s, sizeof( buf ) - 1, width, preci, g );
+ if (g) { char *tmp,*tmp1; if ( ( tmp = local_strchr( s, '.' ) ) ) { tmp1
= local_strchr( tmp, 'e' ); while ( *tmp ) ++tmp; if ( tmp1 ) tmp = tmp1;
+ while ( *--tmp == '0' ) ; if ( *tmp != '.' ) ++tmp; *tmp = 0; if ( tmp1 )
local_strcpy( tmp, tmp1 ); } }
+ sz = local_strlen( s );
+ while ( s[sz-1] == '0' && s[sz-2] == '0' ) sz--;
+ if ( sz > 30 )
+ {
+ int ln = (char*)local_strchr( s, '.' ) - s - 1 - (*sign=='-');
s[sz=19+(*sign=='-')] = '.'; s[sz+1] = 0;
+ for ( ; sz > 1+(*sign=='-'); sz-- ) { s[sz] = s[sz-1]; s[sz-1] = '.'; }
+ sz = 19+(*sign=='-'); s[sz++] = 'e'; s[sz++] = '+'; s[sz++] =
'0'+(ln/100); s[sz++] = '0'+((ln%100)/10); s[sz++] = '0'+(ln%10);
+ }
+ if ( width < sz ) width = sz;
+ if ( todo ) { s += todo; sz -= todo; width -= todo; }
+ preci = sz;
+ if ( !(flags & VG_MSG_LJUSTIFY) ) { if ( write_pad( &len, send,
send_arg2, width-preci, zeros ) ) return -1; }
+ if ( todo ) { B_WRITE( sign, todo ); len += todo; }
+ if ( write_pad( &len, send, send_arg2, preci-sz, spaces ) ) return -1;
+ B_WRITE( s, sz ); len += sz;
+ if ( flags & VG_MSG_LJUSTIFY ) { if ( write_pad( &len, send, send_arg2,
width-preci, zeros ) ) return -1; }
+ return len;
+}
+
/* Write P into the buffer according to these args:
* If SIGN is true, p is a signed.
@@ -615,4 +749,5 @@
/* A simple vprintf(). */
/* EXPORTED */
+UInt VG_(precision) = 12;
UInt
VG_(debugLog_vprintf) (
@@ -700,4 +835,10 @@
switch (format[i]) {
+ case 'g': /* %g */
+ ret += myvprintf_float32( send, send_arg2, flags, 1, width
? width : 1, VG_(precision), va_arg(vargs, double) );
+ break;
+ case 'f': /* %f */
+ ret += myvprintf_float32( send, send_arg2, flags, 0, width
? width : 1, VG_(precision), va_arg(vargs, double) );
+ break;
case 'o': /* %o */
if (flags & VG_MSG_ALTFORMAT) {
|
|
From: Julian S. <js...@ac...> - 2012-07-20 16:53:38
|
Please open a bug report and put the patch on the bug report.
Patches on the mailing list tend to get forgotten about.
Also, please clarify what problem the patch solves. I'm not
currently aware of any requirement for %f in the system.
J
On Friday, July 20, 2012, Naftali Schwartz wrote:
> Here's a patch I developed to add missing '%f' functionality to
> VG_(printf). Floating point formatting code comes from dietlib.
>
> This is my first patch to Valgrind (so you can go easy on me). And I have
> a couple more in the pipeline...
>
> --- m_debuglog.c 2011-10-26 17:24:45.000000000 -0400
> +++ m_debuglog.c 2012-02-20 15:23:55.882688040 -0500
> @@ -415,4 +456,20 @@
> }
>
> +static Char* local_strchr ( const Char* s, Char c )
> +{
> + while (True) {
> + if (*s == c) return (Char*)s;
> + if (*s == 0) return NULL;
> + s++;
> + }
> +}
> +static Char* local_strcpy ( Char* dest, const Char* src )
> +{
> + Char* dest_orig = dest;
> + while (*src) *dest++ = *src++;
> + *dest = 0;
> + return dest_orig;
> +}
> +
> static HChar local_toupper ( HChar c )
> {
> @@ -538,4 +595,81 @@
>
>
> +/* From dietlibc-0.31 */
> +static int __dtostr( double d, char *buf, UInt maxlen, UInt prec, UInt
> prec2, int g )
> +{
> + union { unsigned long long l; double d; } u = { .d = d };
> + signed long e = ((u.l>>52)&((1<<11)-1)) - 1023, e10 = 1 +
> (long)(e*0.30102999566398119802); /* log10(2) */
> + UInt i; double backup = d, tmp; char *oldbuf = buf;
> + if ( d == 0.0 ) { prec2 = prec2==0 ? 1 : prec2+2; prec2 = prec2>maxlen ?
> 8 : prec2; i=0; if ( prec2 && (long long)u.l < 0 ) { buf[0]='-'; ++i; }
> + for ( ; i < prec2; ++i) buf[i] = '0'; buf[buf[0]=='0'?1:2] = '.'; buf[i]
> = 0; return i; }
> + if ( d < 0.0 ) { d=-d; *buf='-'; --maxlen; ++buf; }
> + tmp = 0.5; for ( i = 0; i < prec2; i++ ) { tmp *= 0.1; } d += tmp;
> + if ( d < 1.0 ) { *buf = '0'; --maxlen; ++buf; }
> + if ( e10 > 0 )
> + {
> + int first = 1; tmp = 10.0; i = e10; while ( i > 10 ) { tmp = tmp * 1e10;
> i -= 10; } while ( i > 1 ) { tmp = tmp * 10; --i; }
> + while ( tmp > 0.9 ) { double fraction = d/tmp; char digit =
> (int)fraction; if ( !first || digit ) {
> + first = 0; *buf = digit + '0'; ++buf;
> + if ( !maxlen ) /* use scientific notation */
> + {
> + int len = __dtostr( backup/tmp, oldbuf, maxlen, prec, prec2, 0 );
> + int initial = 1; if ( len == 0 ) return 0; maxlen -= len; buf += len;
> + if ( maxlen > 0 ) { *buf='e'; ++buf; } --maxlen;
> + for ( len = 1000; len > 0; len /= 10 ) if ( e10 >= len || !initial )
> + { if ( maxlen > 0 ) { *buf = (e10/len) + '0'; ++buf; } --maxlen; initial
> = 0; e10 = e10%len; }
> + if ( maxlen > 0 ) goto fini;
> + return 0;
> + }
> + d -= digit * tmp; --maxlen;
> + } tmp /= 10.0; }
> + } else { tmp = 0.1; }
> + if ( buf == oldbuf) { if ( !maxlen ) return 0; --maxlen; *buf = '0';
> ++buf; }
> + if ( prec2 || prec > (UInt)(buf - oldbuf) + 1 ) /* more digits wanted */
> + {
> + if ( !maxlen ) return 0; --maxlen; *buf = '.'; ++buf;
> + if ( g ) { if ( prec2 ) prec = prec2; prec -= buf - oldbuf - 1; } else {
> prec -= buf - oldbuf - 1; if ( prec2 ) prec = prec2; }
> + if ( prec > maxlen ) return 0;
> + while ( prec > 0 ) { double fraction = d/tmp; char digit = (int)fraction;
> *buf = digit + '0'; ++buf; d -= digit * tmp; tmp /= 10.0; --prec; }
> + }
> +fini: *buf = 0;
> + return buf - oldbuf;
> +}
> +
> +#define A_WRITE(buf,sz) { int _; for ( _ = 0; _ < sz; _++ ) send(
> buf[_], send_arg2 ); }
> +#define B_WRITE(buf,sz) { if ((unsigned long)(sz) > (((unsigned
> long)(int)(-1))>>1) || len+(int)(sz)<len) return -1; A_WRITE( buf, sz ); }
> while (0)
> +
> +static int write_pad( UInt* dlen, void (*send)(HChar,void*), void*
> send_arg2, UInt len, const char *padding) { int nr=0; if
> (len<0||*dlen+len<len) return -1;
> + for (;len>15;len-=16,nr+=16) { A_WRITE( padding, 16 ); } if (len>0) {
> A_WRITE( padding, len ); nr+=len; } *dlen += nr; return 0; }
> +
> +static
> +UInt myvprintf_float32 ( void (*send)(HChar,void*), void* send_arg2, Int
> flags, Int g, Int width, Int preci, double d )
> +{
> + static const char spaces[16] = " ", zeros[16] =
> "0000000000000000";
> + UInt len = 0;
> + char buf[500];
> + char *s = buf + 1, *sign = s;
> + int todo = d < +0.0;
> + unsigned long sz = __dtostr( d, s, sizeof( buf ) - 1, width, preci, g );
> + if (g) { char *tmp,*tmp1; if ( ( tmp = local_strchr( s, '.' ) ) ) { tmp1
> = local_strchr( tmp, 'e' ); while ( *tmp ) ++tmp; if ( tmp1 ) tmp = tmp1;
> + while ( *--tmp == '0' ) ; if ( *tmp != '.' ) ++tmp; *tmp = 0; if ( tmp1 )
> local_strcpy( tmp, tmp1 ); } }
> + sz = local_strlen( s );
> + while ( s[sz-1] == '0' && s[sz-2] == '0' ) sz--;
> + if ( sz > 30 )
> + {
> + int ln = (char*)local_strchr( s, '.' ) - s - 1 - (*sign=='-');
> s[sz=19+(*sign=='-')] = '.'; s[sz+1] = 0;
> + for ( ; sz > 1+(*sign=='-'); sz-- ) { s[sz] = s[sz-1]; s[sz-1] = '.'; }
> + sz = 19+(*sign=='-'); s[sz++] = 'e'; s[sz++] = '+'; s[sz++] =
> '0'+(ln/100); s[sz++] = '0'+((ln%100)/10); s[sz++] = '0'+(ln%10);
> + }
> + if ( width < sz ) width = sz;
> + if ( todo ) { s += todo; sz -= todo; width -= todo; }
> + preci = sz;
> + if ( !(flags & VG_MSG_LJUSTIFY) ) { if ( write_pad( &len, send,
> send_arg2, width-preci, zeros ) ) return -1; }
> + if ( todo ) { B_WRITE( sign, todo ); len += todo; }
> + if ( write_pad( &len, send, send_arg2, preci-sz, spaces ) ) return -1;
> + B_WRITE( s, sz ); len += sz;
> + if ( flags & VG_MSG_LJUSTIFY ) { if ( write_pad( &len, send, send_arg2,
> width-preci, zeros ) ) return -1; }
> + return len;
> +}
> +
> /* Write P into the buffer according to these args:
> * If SIGN is true, p is a signed.
> @@ -615,4 +749,5 @@
> /* A simple vprintf(). */
> /* EXPORTED */
> +UInt VG_(precision) = 12;
> UInt
> VG_(debugLog_vprintf) (
> @@ -700,4 +835,10 @@
>
> switch (format[i]) {
> + case 'g': /* %g */
> + ret += myvprintf_float32( send, send_arg2, flags, 1, width
> ? width : 1, VG_(precision), va_arg(vargs, double) );
> + break;
> + case 'f': /* %f */
> + ret += myvprintf_float32( send, send_arg2, flags, 0, width
> ? width : 1, VG_(precision), va_arg(vargs, double) );
> + break;
> case 'o': /* %o */
> if (flags & VG_MSG_ALTFORMAT) {
|
|
From: Florian K. <br...@ac...> - 2012-07-20 17:26:12
|
On 07/20/2012 12:49 PM, Julian Seward wrote: > > Please open a bug report and put the patch on the bug report. > Patches on the mailing list tend to get forgotten about. > > Also, please clarify what problem the patch solves. I'm not > currently aware of any requirement for %f in the system. Ahem.. Enhancing VG_(printf) in this manner is mentioned in http://valgrind.org/help/projects.html Not a bad thing, I'd say. Florian |
|
From: Julian S. <js...@ac...> - 2012-07-20 21:37:21
|
On Friday, July 20, 2012, Florian Krohm wrote: > Ahem.. Enhancing VG_(printf) in this manner is mentioned in > http://valgrind.org/help/projects.html > Not a bad thing, I'd say. Ah yes, my mistake. True, there are places where we have kludged around the lack of %f, particularly in Cachegrind and Massif, so it would be no bad thing to have. J |
|
From: Nicholas N. <n.n...@gm...> - 2012-10-13 02:25:33
|
On Sat, Jul 21, 2012 at 7:32 AM, Julian Seward <js...@ac...> wrote: > >> Ahem.. Enhancing VG_(printf) in this manner is mentioned in >> http://valgrind.org/help/projects.html >> Not a bad thing, I'd say. > > Ah yes, my mistake. True, there are places where we have kludged > around the lack of %f, particularly in Cachegrind and Massif, so > it would be no bad thing to have. Yeah, I've wanted it often in the past. Looks like this patch never made it into the repo... a shame. Nick |