diff options
author | brolley <brolley> | 2008-02-27 16:42:05 +0000 |
---|---|---|
committer | brolley <brolley> | 2008-02-27 16:42:05 +0000 |
commit | 67bae0e3d979d554acaeb2a09cf4f7463ee713da (patch) | |
tree | a272efeb7ec76b998e9c1b57e9109f594dfa1fb5 /runtime/vsprintf.c | |
parent | 33c514bdedd1d2753f7d29a8926223e30986c639 (diff) | |
download | systemtap-steved-67bae0e3d979d554acaeb2a09cf4f7463ee713da.tar.gz systemtap-steved-67bae0e3d979d554acaeb2a09cf4f7463ee713da.tar.xz systemtap-steved-67bae0e3d979d554acaeb2a09cf4f7463ee713da.zip |
2008-02-27 Dave Brolley <brolley@redhat.com>
PR5189
* vsprintf.c (_stp_vsnprintf): Extract arguments of type int64_t for
dynamic width and precision. Implement width and precision correctly for
the %b format specifier. Implement the %m specifier.
Diffstat (limited to 'runtime/vsprintf.c')
-rw-r--r-- | runtime/vsprintf.c | 78 |
1 files changed, 67 insertions, 11 deletions
diff --git a/runtime/vsprintf.c b/runtime/vsprintf.c index 061aba3f..f8283e5c 100644 --- a/runtime/vsprintf.c +++ b/runtime/vsprintf.c @@ -1,6 +1,6 @@ /* -*- linux-c -*- * vsprintf.c - * Copyright (C) 2006 Red Hat Inc. + * Copyright (C) 2006, 2008 Red Hat Inc. * Based on code from the Linux kernel * Copyright (C) 1991, 1992 Linus Torvalds * @@ -115,6 +115,22 @@ static char * number(char * buf, char * end, uint64_t num, int base, int size, i return buf; } +static int check_binary_precision (int precision) { + /* precision can be unspecified (-1) or one of 1, 2, 4 or 8. */ + switch (precision) { + case -1: + case 1: + case 2: + case 4: + case 8: + break; + default: + precision = -1; + break; + } + return precision; +} + int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) { int len; @@ -164,7 +180,7 @@ int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) else if (*fmt == '*') { ++fmt; /* it's the next argument */ - field_width = va_arg(args, int); + field_width = va_arg(args, int64_t); if (field_width < 0) { field_width = -field_width; flags |= STP_LEFT; @@ -180,7 +196,7 @@ int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) else if (*fmt == '*') { ++fmt; /* it's the next argument */ - precision = va_arg(args, int); + precision = va_arg(args, int64_t); } if (precision < 0) precision = 0; @@ -203,7 +219,36 @@ int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) switch (*fmt) { case 'b': num = va_arg(args, int64_t); - switch(field_width) { + + /* Only certain values are valid for the precision. */ + precision = check_binary_precision (precision); + + /* Unspecified field width defaults to the specified + precision and vice versa. If neither is specified, + then both default to 8. */ + if (field_width == -1) { + if (precision == -1) { + field_width = 8; + precision = 8; + } + else + field_width = precision; + } + else if (precision == -1) { + precision = check_binary_precision (field_width); + if (precision == -1) + precision = 8; + } + + len = precision; + if (!(flags & STP_LEFT)) { + while (len < field_width--) { + if (str <= end) + *str = '\0'; + ++str; + } + } + switch(precision) { case 1: if(str <= end) *(int8_t *)str = (int8_t)num; @@ -214,26 +259,37 @@ int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) *(int16_t *)str = (int16_t)num; str+=2; break; - case 8: - if((str + 7) <= end) - *(int64_t *)str = num; - str+=8; - break; case 4: - default: // "%4b" by default if((str + 3) <= end) *(int32_t *)str = num; str+=4; break; + default: // "%.8b" by default + case 8: + if((str + 7) <= end) + *(int64_t *)str = num; + str+=8; + break; + } + while (len < field_width--) { + if (str <= end) + *str = '\0'; + ++str; } continue; case 's': + case 'm': s = va_arg(args, char *); if ((unsigned long)s < PAGE_SIZE) s = "<NULL>"; - len = strnlen(s, precision); + if (*fmt == 's') + len = strnlen(s, precision); + else if (precision > 0) + len = precision; + else + len = 1; if (!(flags & STP_LEFT)) { while (len < field_width--) { |