diff --git a/include/misc/printk.h b/include/misc/printk.h index 63746b8dbd..83064e4e06 100644 --- a/include/misc/printk.h +++ b/include/misc/printk.h @@ -33,8 +33,11 @@ extern "C" { * - character: \%c * - percent: \%\% * - * No other conversion specification capabilities are supported, such as flags, - * field width, precision, or length attributes. + * Field width (with or without leading zeroes) are supported. + * Length attributes such as 'h' and 'l' are supported. However, + * integral values with %lld and %lli are only printed if they fit in 32 bits, + * otherwise 'ERR' is printed. Full 64-bit values may be printed with %llx. + * Flags and precision attributes are not supported. * * @param fmt Format string. * @param ... Optional list of format arguments. diff --git a/misc/printk.c b/misc/printk.c index b6d05e9eab..a774deb6d0 100644 --- a/misc/printk.c +++ b/misc/printk.c @@ -82,6 +82,13 @@ void *__printk_get_hook(void) return _char_out; } +static void print_err(out_func_t out, void *ctx) +{ + out('E', ctx); + out('R', ctx); + out('R', ctx); +} + /** * @brief Printk internals * @@ -141,11 +148,25 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap) goto still_might_format; case 'd': case 'i': { - long d; - if (long_ctr < 2) { - d = va_arg(ap, long); + s32_t d; + + if (long_ctr == 0) { + d = va_arg(ap, int); + } else if (long_ctr == 1) { + long ld = va_arg(ap, long); + if (ld > INT32_MAX || ld < INT32_MIN) { + print_err(out, ctx); + break; + } + d = (s32_t)ld; } else { - d = (long)va_arg(ap, long long); + long long lld = va_arg(ap, long long); + if (lld > INT32_MAX || + lld < INT32_MIN) { + print_err(out, ctx); + break; + } + d = (s32_t)lld; } if (d < 0) { @@ -158,14 +179,27 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap) break; } case 'u': { - unsigned long u; + u32_t u; - if (long_ctr < 2) { - u = va_arg(ap, unsigned long); + if (long_ctr == 0) { + u = va_arg(ap, unsigned int); + } else if (long_ctr == 1) { + long lu = va_arg(ap, unsigned long); + if (lu > INT32_MAX) { + print_err(out, ctx); + break; + } + u = (u32_t)lu; } else { - u = (unsigned long)va_arg(ap, - unsigned long long); + unsigned long long llu = + va_arg(ap, unsigned long long); + if (llu > INT32_MAX) { + print_err(out, ctx); + break; + } + u = (u32_t)llu; } + _printk_dec_ulong(out, ctx, u, padding, min_width); break; diff --git a/tests/kernel/common/src/printk.c b/tests/kernel/common/src/printk.c index bf41dd6233..685397e5b2 100644 --- a/tests/kernel/common/src/printk.c +++ b/tests/kernel/common/src/printk.c @@ -25,7 +25,7 @@ char *expected = "22 113 10000 32768 40000 22\n" "42 42 42 42\n" "42 42 0042 00000042\n" "255 42 abcdef 0x0000002a 42\n" - "-1 4294967295 ffffffffffffffff\n" + "ERR -1 ERR ffffffffffffffff\n" ; @@ -86,7 +86,7 @@ void test_printk(void) printk("%u %2u %4u %8u\n", 42, 42, 42, 42); printk("%u %02u %04u %08u\n", 42, 42, 42, 42); printk("%-8u%-6d%-4x%-2p%8d\n", 0xFF, 42, 0xABCDEF, (char *)42, 42); - printk("%lld %llu %llx\n", -1LL, -1ULL, -1ULL); + printk("%lld %lld %llu %llx\n", 0xFFFFFFFFFULL, -1LL, -1ULL, -1ULL); ram_console[pos] = '\0'; zassert_true((strcmp(ram_console, expected) == 0), "printk failed"); @@ -117,8 +117,8 @@ void test_printk(void) "%-8u%-6d%-4x%-2p%8d\n", 0xFF, 42, 0xABCDEF, (char *)42, 42); count += snprintk(ram_console + count, sizeof(ram_console) - count, - "%lld %llu %llx\n", - -1LL, -1ULL, -1ULL); + "%lld %lld %llu %llx\n", + 0xFFFFFFFFFULL, -1LL, -1ULL, -1ULL); ram_console[count] = '\0'; zassert_true((strcmp(ram_console, expected) == 0), "snprintk failed"); }