Merge patch from Jeremy Fitzhardinge:
14-sprintf
Update to core VG_(printf)/sprintf/vprintf. They've been modified to
return the number of characters they generated (either printed, put
into the buffer, or sent). Also adds a new %y format, which takes an
Addr argument and looks up a symbol. It takes a '(' flag (ie: "%(y")
which surrounds the symbol in parens if it could be found.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1253 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_mylibc.c b/coregrind/vg_mylibc.c
index ebefad6..38af87a 100644
--- a/coregrind/vg_mylibc.c
+++ b/coregrind/vg_mylibc.c
@@ -390,43 +390,50 @@
#define VG_MSG_SIGNED 1 /* The value is signed. */
#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
-
+#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
/* Copy a string into the buffer. */
-static void
+static UInt
myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
Bool capitalise )
{
# define MAYBE_TOUPPER(ch) (capitalise ? VG_(toupper)(ch) : (ch))
-
+ UInt ret = 0;
Int i, extra;
Int len = VG_(strlen)(str);
if (width == 0) {
+ ret += len;
for (i = 0; i < len; i++)
send(MAYBE_TOUPPER(str[i]));
- return;
+ return ret;
}
if (len > width) {
+ ret += width;
for (i = 0; i < width; i++)
send(MAYBE_TOUPPER(str[i]));
- return;
+ return ret;
}
extra = width - len;
if (flags & VG_MSG_LJUSTIFY) {
+ ret += extra;
for (i = 0; i < extra; i++)
send(' ');
}
+ ret += len;
for (i = 0; i < len; i++)
send(MAYBE_TOUPPER(str[i]));
if (!(flags & VG_MSG_LJUSTIFY)) {
+ ret += extra;
for (i = 0; i < extra; i++)
send(' ');
}
# undef MAYBE_TOUPPER
+
+ return ret;
}
/* Write P into the buffer according to these args:
@@ -435,7 +442,7 @@
* If WITH_ZERO is true, '0' must be added.
* WIDTH is the width of the field.
*/
-static void
+static UInt
myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
{
Char buf[40];
@@ -443,9 +450,10 @@
Int i;
Bool neg = False;
Char *digits = "0123456789ABCDEF";
-
+ UInt ret = 0;
+
if (base < 2 || base > 16)
- return;
+ return ret;
if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
p = - (Long)p;
@@ -472,20 +480,24 @@
}
/* Reverse copy to buffer. */
+ ret += ind;
for (i = ind -1; i >= 0; i--)
send(buf[i]);
-
if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
- for(; ind < width; ind++)
+ for(; ind < width; ind++) {
+ ret++;
send((flags & VG_MSG_ZJUSTIFY) ? '0': ' ');
+ }
}
+ return ret;
}
/* A simple vprintf(). */
-void
+UInt
VG_(vprintf) ( void(*send)(Char), const Char *format, va_list vargs )
{
+ UInt ret = 0;
int i;
int flags;
int width;
@@ -499,6 +511,7 @@
for (i = 0; format[i] != 0; i++) {
if (format[i] != '%') {
send(format[i]);
+ ret++;
continue;
}
i++;
@@ -508,11 +521,16 @@
if (format[i] == '%') {
/* `%%' is replaced by `%'. */
send('%');
+ ret++;
continue;
}
flags = 0;
is_long = False;
width = 0; /* length of the field. */
+ if (format[i] == '(') {
+ flags |= VG_MSG_PAREN;
+ i++;
+ }
/* If '-' follows '%', justify on the left. */
if (format[i] == '-') {
flags |= VG_MSG_LJUSTIFY;
@@ -537,47 +555,68 @@
case 'd': /* %d */
flags |= VG_MSG_SIGNED;
if (is_long)
- myvprintf_int64(send, flags, 10, width,
- (ULong)(va_arg (vargs, Long)));
+ ret += myvprintf_int64(send, flags, 10, width,
+ (ULong)(va_arg (vargs, Long)));
else
- myvprintf_int64(send, flags, 10, width,
- (ULong)(va_arg (vargs, Int)));
+ ret += myvprintf_int64(send, flags, 10, width,
+ (ULong)(va_arg (vargs, Int)));
break;
case 'u': /* %u */
if (is_long)
- myvprintf_int64(send, flags, 10, width,
- (ULong)(va_arg (vargs, ULong)));
+ ret += myvprintf_int64(send, flags, 10, width,
+ (ULong)(va_arg (vargs, ULong)));
else
- myvprintf_int64(send, flags, 10, width,
- (ULong)(va_arg (vargs, UInt)));
+ ret += myvprintf_int64(send, flags, 10, width,
+ (ULong)(va_arg (vargs, UInt)));
break;
case 'p': /* %p */
+ ret += 2;
send('0');
send('x');
- myvprintf_int64(send, flags, 16, width,
- (ULong)((UInt)va_arg (vargs, void *)));
+ ret += myvprintf_int64(send, flags, 16, width,
+ (ULong)((UInt)va_arg (vargs, void *)));
break;
case 'x': /* %x */
if (is_long)
- myvprintf_int64(send, flags, 16, width,
- (ULong)(va_arg (vargs, ULong)));
+ ret += myvprintf_int64(send, flags, 16, width,
+ (ULong)(va_arg (vargs, ULong)));
else
- myvprintf_int64(send, flags, 16, width,
- (ULong)(va_arg (vargs, UInt)));
+ ret += myvprintf_int64(send, flags, 16, width,
+ (ULong)(va_arg (vargs, UInt)));
break;
case 'c': /* %c */
+ ret++;
send(va_arg (vargs, int));
break;
case 's': case 'S': { /* %s */
char *str = va_arg (vargs, char *);
if (str == (char*) 0) str = "(null)";
- myvprintf_str(send, flags, width, str, format[i]=='S');
+ ret += myvprintf_str(send, flags, width, str, format[i]=='S');
break;
- }
+ }
+ case 'y': { /* %y - print symbol */
+ Char buf[100];
+ Char *cp = buf;
+ Addr a = va_arg(vargs, Addr);
+
+ if (flags & VG_MSG_PAREN)
+ *cp++ = '(';
+ if (VG_(get_fnname)(a, cp, sizeof(buf)-2)) {
+ if (flags & VG_MSG_PAREN) {
+ cp += VG_(strlen)(cp);
+ *cp++ = ')';
+ *cp = '\0';
+ }
+ ret += myvprintf_str(send, flags, width, buf, 0);
+ }
+
+ break;
+ }
default:
break;
}
}
+ return ret;
}
@@ -601,20 +640,23 @@
myprintf_buf[n_myprintf_buf] = 0;
}
-void VG_(printf) ( const char *format, ... )
+UInt VG_(printf) ( const char *format, ... )
{
+ UInt ret;
va_list vargs;
va_start(vargs,format);
n_myprintf_buf = 0;
myprintf_buf[n_myprintf_buf] = 0;
- VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
+ ret = VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
if (n_myprintf_buf > 0 && VG_(clo_logfile_fd) >= 0)
VG_(write)
- ( VG_(clo_logfile_fd), myprintf_buf, VG_(strlen)(myprintf_buf));
+ ( VG_(clo_logfile_fd), myprintf_buf, ret);
va_end(vargs);
+
+ return ret;
}
@@ -626,16 +668,21 @@
*vg_sprintf_ptr++ = c;
}
-void VG_(sprintf) ( Char* buf, Char *format, ... )
+UInt VG_(sprintf) ( Char* buf, Char *format, ... )
{
+ UInt ret;
+
va_list vargs;
va_start(vargs,format);
vg_sprintf_ptr = buf;
- VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
+ ret = VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
add_to_vg_sprintf_buf(0);
va_end(vargs);
+
+ vg_assert(VG_(strlen)(buf) == ret);
+ return ret;
}