From 0ef6738e26cd65ed96fa67471d9c149e3e92edf8 Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 11 Oct 2020 16:28:42 +0300 Subject: [PATCH] stdio: Add 'x' conversion to *scanf --- src/stdio/_scanf.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/stdio/_scanf.c b/src/stdio/_scanf.c index d4b19a1..3bbed9e 100644 --- a/src/stdio/_scanf.c +++ b/src/stdio/_scanf.c @@ -71,24 +71,45 @@ int __libc_vscanf(const char *format, // Conversion spec ch = *format++; - if (ch == 'u') { + if (ch == 'u' || ch == 'x') { // At least one should be numeric uintmax_t rv = 0; + int dig; if (peek() == EOF || !isdigit(peek())) { goto err; } - while (isdigit(peek())) { - rv *= 10; - rv += (peek() - '0'); - pop(); + switch (ch) { + case 'u': + while (isdigit(peek())) { + rv *= 10; + rv += (peek() - '0'); + pop(); + } + break; + case 'x': + while (isxdigit((dig = peek()))) { + rv <<= 4; + if (dig >= 'A' && dig <= 'F') { + rv |= (dig - 'A' + 0xA); + } else if (dig >= 'a' && dig <= 'f') { + rv |= (dig - 'a' + 0xA); + } else { + rv |= dig - '0'; + } + pop(); + } + break; } switch (lenmod) { case PL_0: *va_arg(ap, int *) = (int) rv; break; + case PL_h: + *va_arg(ap, short *) = (short) rv; + break; case PL_l: *va_arg(ap, long *) = (long) rv; break; @@ -101,7 +122,7 @@ int __libc_vscanf(const char *format, } ++n_convert; } else { - ygg_debug_trace("%s: unknown conversion spec: %%%u\n", __func__, ch); + ygg_debug_trace("%s: unknown conversion spec: %%%c\n", __func__, ch); while (1); } } else {