lib: os: cbprintf: correctly handle signed vs unsigned char

Whether char is signed or unsigned is toolchain and target specific.
Rather than assume it's signed (which is true for x86, but not for
ARM), do the right thing based on whether the minimum representable
value is less than zero.

Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
This commit is contained in:
Peter Bigot 2021-01-06 10:59:49 -06:00 committed by Carles Cufí
commit 8eda19a898

View file

@ -79,12 +79,22 @@ enum specifier_cat_enum {
SPECIFIER_FP, SPECIFIER_FP,
}; };
#define CHAR_IS_SIGNED (CHAR_MIN != 0)
#if CHAR_IS_SIGNED
#define CASE_SINT_CHAR case 'c':
#define CASE_UINT_CHAR
#else
#define CASE_SINT_CHAR
#define CASE_UINT_CHAR case 'c':
#endif
/* Case label to identify conversions for signed integral values. The /* Case label to identify conversions for signed integral values. The
* corresponding argument_value tag is sint and category is * corresponding argument_value tag is sint and category is
* SPECIFIER_SINT. * SPECIFIER_SINT.
*/ */
#define SINT_CONV_CASES \ #define SINT_CONV_CASES \
'd': \ 'd': \
CASE_SINT_CHAR \
case 'i' case 'i'
/* Case label to identify conversions for signed integral arguments. /* Case label to identify conversions for signed integral arguments.
@ -92,8 +102,8 @@ enum specifier_cat_enum {
* SPECIFIER_UINT. * SPECIFIER_UINT.
*/ */
#define UINT_CONV_CASES \ #define UINT_CONV_CASES \
'c': \ 'o': \
case 'o': \ CASE_UINT_CHAR \
case 'u': \ case 'u': \
case 'x': \ case 'x': \
case 'X' case 'X'
@ -1515,7 +1525,7 @@ int cbvprintf(cbprintf_cb out, void *ctx, const char *fp, va_list ap)
} }
case 'c': case 'c':
bps = buf; bps = buf;
buf[0] = value->uint; buf[0] = CHAR_IS_SIGNED ? value->sint : value->uint;
bpe = buf + 1; bpe = buf + 1;
break; break;
case 'd': case 'd':