kvprintf(): Fix '+' conversion handling

For example, printf("%+i", 1) prints "+1".  However, kvprintf() did
print just "1" for this example.  According to PRINTF(3):

  A sign must always be placed before a number produced by a signed
  conversion.

For "%+r" radix conversions, keep the "+" handling as it is, since this
is a non-standard conversion.  For "%+p" pointer conversions, continue
to ignore the sign modifier to be in line with libc.

This change allows to support the ' conversion modifier in the future.

Reviewed by: imp
Pull Request: https://github.com/freebsd/freebsd-src/pull/1310
This commit is contained in:
Sebastian Huber
2024-06-14 09:30:28 +02:00
parent 48618b1060
commit ce1fb41a6c

View File

@@ -95,9 +95,9 @@ _IO_Vprintf(IO_Put_char put_char, void *arg, char const *fmt, va_list ap)
char nbuf[MAXNBUF]; char nbuf[MAXNBUF];
const char *p, *percent, *q; const char *p, *percent, *q;
u_char *up; u_char *up;
int ch, n; int ch, n, sign;
uintmax_t num; uintmax_t num;
int base, lflag, tmp, width, ladjust, sharpflag, neg, sign, dot; int base, lflag, tmp, width, ladjust, sharpflag, dot;
int cflag, hflag, jflag; int cflag, hflag, jflag;
RTEMS_STATIC_ASSERT(sizeof(intmax_t) == sizeof(long long), _IO_Vprintf_j); RTEMS_STATIC_ASSERT(sizeof(intmax_t) == sizeof(long long), _IO_Vprintf_j);
#if __SIZEOF_PTRDIFF_T__ == __SIZEOF_LONG__ #if __SIZEOF_PTRDIFF_T__ == __SIZEOF_LONG__
@@ -128,7 +128,7 @@ _IO_Vprintf(IO_Put_char put_char, void *arg, char const *fmt, va_list ap)
PCHAR(ch); PCHAR(ch);
} }
percent = fmt - 1; percent = fmt - 1;
lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; lflag = 0; ladjust = 0; sharpflag = 0;
sign = 0; dot = 0; dwidth = 0; upper = 0; sign = 0; dot = 0; dwidth = 0; upper = 0;
cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
reswitch: switch (ch = (u_char)*fmt++) { reswitch: switch (ch = (u_char)*fmt++) {
@@ -139,7 +139,7 @@ reswitch: switch (ch = (u_char)*fmt++) {
sharpflag = 1; sharpflag = 1;
goto reswitch; goto reswitch;
case '+': case '+':
sign = 1; sign = '+';
goto reswitch; goto reswitch;
case '-': case '-':
ladjust = 1; ladjust = 1;
@@ -205,7 +205,6 @@ reswitch: switch (ch = (u_char)*fmt++) {
case 'd': case 'd':
case 'i': case 'i':
base = 10; base = 10;
sign = 1;
goto handle_sign; goto handle_sign;
case 'h': case 'h':
if (hflag) { if (hflag) {
@@ -267,13 +266,11 @@ reswitch: switch (ch = (u_char)*fmt++) {
goto handle_nosign; goto handle_nosign;
case 'y': case 'y':
base = 16; base = 16;
sign = 1;
goto handle_sign; goto handle_sign;
case 'z': case 'z':
zflag = 1; zflag = 1;
goto reswitch; goto reswitch;
handle_nosign: handle_nosign:
sign = 0;
if (jflag) if (jflag)
num = va_arg(ap, uintmax_t); num = va_arg(ap, uintmax_t);
#if __SIZEOF_PTRDIFF_T__ != __SIZEOF_LONG__ #if __SIZEOF_PTRDIFF_T__ != __SIZEOF_LONG__
@@ -312,11 +309,11 @@ handle_sign:
num = (signed char)va_arg(ap, int); num = (signed char)va_arg(ap, int);
else else
num = va_arg(ap, int); num = va_arg(ap, int);
number: if ((intmax_t)num < 0) {
if (sign && (intmax_t)num < 0) { sign = '-';
neg = 1;
num = -(intmax_t)num; num = -(intmax_t)num;
} }
number:
p = ksprintn(nbuf, num, base, &n, upper); p = ksprintn(nbuf, num, base, &n, upper);
tmp = 0; tmp = 0;
if (sharpflag && num != 0) { if (sharpflag && num != 0) {
@@ -325,7 +322,7 @@ number:
else if (base == 16) else if (base == 16)
tmp += 2; tmp += 2;
} }
if (neg) if (sign)
tmp++; tmp++;
if (!ladjust && padc == '0') if (!ladjust && padc == '0')
@@ -335,8 +332,8 @@ number:
if (!ladjust) if (!ladjust)
while (width-- > 0) while (width-- > 0)
PCHAR(' '); PCHAR(' ');
if (neg) if (sign)
PCHAR('-'); PCHAR(sign);
if (sharpflag && num != 0) { if (sharpflag && num != 0) {
if (base == 8) { if (base == 8) {
PCHAR('0'); PCHAR('0');