Support format flags for field padding, such as "%08x", allowing register dumps to be easier on the eyes. Signed-off-by: Andrew Jones <drjones@xxxxxxxxxx> --- lib/printf.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 14 deletions(-) diff --git a/lib/printf.c b/lib/printf.c index 867eb1926f742..89308fb26b7d2 100644 --- a/lib/printf.c +++ b/lib/printf.c @@ -6,6 +6,11 @@ typedef struct pstream { int added; } pstream_t; +typedef struct strprops { + char pad; + int npad; +} strprops_t; + static void addchar(pstream_t *p, char c) { if (p->remain) { @@ -15,15 +20,35 @@ static void addchar(pstream_t *p, char c) ++p->added; } -void print_str(pstream_t *p, const char *s) +void print_str(pstream_t *p, const char *s, strprops_t props) { + const char *s_orig = s; + int npad = props.npad; + + if (npad > 0) { + npad -= strlen(s_orig); + while (npad > 0) { + addchar(p, props.pad); + --npad; + } + } + while (*s) addchar(p, *s++); + + if (npad < 0) { + props.pad = ' '; /* ignore '0' flag with '-' flag */ + npad += strlen(s_orig); + while (npad < 0) { + addchar(p, props.pad); + ++npad; + } + } } static char digits[16] = "0123456789abcdef"; -void print_int(pstream_t *ps, long long n, int base) +void print_int(pstream_t *ps, long long n, int base, strprops_t props) { char buf[sizeof(long) * 3 + 2], *p = buf; int s = 0, i; @@ -54,10 +79,11 @@ void print_int(pstream_t *ps, long long n, int base) *p = 0; - print_str(ps, buf); + print_str(ps, buf, props); } -void print_unsigned(pstream_t *ps, unsigned long long n, int base) +void print_unsigned(pstream_t *ps, unsigned long long n, int base, + strprops_t props) { char buf[sizeof(long) * 3 + 1], *p = buf; int i; @@ -80,7 +106,23 @@ void print_unsigned(pstream_t *ps, unsigned long long n, int base) *p = 0; - print_str(ps, buf); + print_str(ps, buf, props); +} + +static int fmtnum(const char **fmt) +{ + const char *f = *fmt; + int len = 0, num; + + if (*f == '-') + ++f, ++len; + + while (*f >= '0' && *f <= '9') + ++f, ++len; + + num = atol(*fmt); + *fmt += len; + return num; } int vsnprintf(char *buf, int size, const char *fmt, va_list va) @@ -93,6 +135,9 @@ int vsnprintf(char *buf, int size, const char *fmt, va_list va) while (*fmt) { char f = *fmt++; int nlong = 0; + strprops_t props; + memset(&props, 0, sizeof(props)); + props.pad = ' '; if (f != '%') { addchar(&s, f); @@ -110,41 +155,50 @@ int vsnprintf(char *buf, int size, const char *fmt, va_list va) case '\0': --fmt; break; + case '0': + props.pad = '0'; + ++fmt; + /* fall through */ + case '1'...'9': + case '-': + --fmt; + props.npad = fmtnum(&fmt); + goto morefmt; case 'l': ++nlong; goto morefmt; case 'd': switch (nlong) { case 0: - print_int(&s, va_arg(va, int), 10); + print_int(&s, va_arg(va, int), 10, props); break; case 1: - print_int(&s, va_arg(va, long), 10); + print_int(&s, va_arg(va, long), 10, props); break; default: - print_int(&s, va_arg(va, long long), 10); + print_int(&s, va_arg(va, long long), 10, props); break; } break; case 'x': switch (nlong) { case 0: - print_unsigned(&s, va_arg(va, unsigned), 16); + print_unsigned(&s, va_arg(va, unsigned), 16, props); break; case 1: - print_unsigned(&s, va_arg(va, unsigned long), 16); + print_unsigned(&s, va_arg(va, unsigned long), 16, props); break; default: - print_unsigned(&s, va_arg(va, unsigned long long), 16); + print_unsigned(&s, va_arg(va, unsigned long long), 16, props); break; } break; case 'p': - print_str(&s, "0x"); - print_unsigned(&s, (unsigned long)va_arg(va, void *), 16); + print_str(&s, "0x", props); + print_unsigned(&s, (unsigned long)va_arg(va, void *), 16, props); break; case 's': - print_str(&s, va_arg(va, const char *)); + print_str(&s, va_arg(va, const char *), props); break; default: addchar(&s, f); -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html