From 3bcf8eb0d444214b5859f1e0fdfd62973031db5d Mon Sep 17 00:00:00 2001 From: rmikielis Date: Thu, 25 Jun 2026 15:03:04 +0200 Subject: [PATCH] stdio/format: fix printing sign for long double JIRA: RTOS-1368 --- stdio/format.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/stdio/format.c b/stdio/format.c index d92a9f97..1086cd03 100644 --- a/stdio/format.c +++ b/stdio/format.c @@ -621,7 +621,7 @@ static int format_sprintfScientificForm(struct buffer *buff, struct bigdouble *b } -static int format_sprintfDouble(void *ctx, feedfunc feed, double d, uint32_t flags, int minFieldWidth, int precision, char format) +static int format_sprintfDouble(void *ctx, feedfunc feed, double d, uint32_t flags, int minFieldWidth, int precision, char format, uint8_t msb) { struct buffer buff; char sign = 0; @@ -640,7 +640,7 @@ static int format_sprintfDouble(void *ctx, feedfunc feed, double d, uint32_t fla } /* check sign */ - if (((num64 >> 63) & 1) != 0) { + if (msb != 0) { sign = '-'; d = -d; } @@ -654,6 +654,7 @@ static int format_sprintfDouble(void *ctx, feedfunc feed, double d, uint32_t fla sign = '\0'; } num64 = format_u64FromDouble(d); + num64 |= ((uint64_t)msb << 63); CHECK_FAIL(ret, format_bufferInit(&buff, 2 * precision + 6)); @@ -1178,19 +1179,26 @@ int format_parse(void *ctx, feedfunc feed, const char *format, va_list args) case 'f': case 'g': { #ifndef IO_NO_FLOAT - double doubleNumber; + long double doubleNumber; + uint8_t msb = 0; + if (fmt == 'g' || fmt == 'G') { flags |= FLAG_NO_TRAILING_ZEROS; } if ((flags & FLAG_LONG_DOUBLE) != 0) { /* NOTE: support for long double is incomplete */ - doubleNumber = (double)va_arg((args), long double); + doubleNumber = va_arg((args), long double); } else { - doubleNumber = (double)va_arg((args), double); + doubleNumber = (long double)va_arg((args), double); + } + + /* preserve sign bit during down-conversion to double */ + if (__builtin_signbit(doubleNumber) != 0) { + msb = 1; } - CHECK_FAIL(ret, format_sprintfDouble(ctx, feed, doubleNumber, flags, minFieldWidth, precision, tolower(fmt))); + CHECK_FAIL(ret, format_sprintfDouble(ctx, feed, (double)doubleNumber, flags, minFieldWidth, precision, tolower(fmt), msb)); break; #else if ((flags & FLAG_LONG_DOUBLE) != 0) {