8000 mpprint: Rework integer vararg handling. · micropython/micropython@3f9b9c4 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3f9b9c4

Browse files
committed
mpprint: Rework integer vararg handling.
This adds support for %llx (needed by XINT_FMT for printing cell objects) and incidentally support for capitalized output of %P. Signed-off-by: Jeff Epler <jepler@gmail.com>
1 parent 4661e10 commit 3f9b9c4

File tree

1 file changed

+49
-38
lines changed

1 file changed

+49
-38
lines changed

py/mpprint.c

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -446,16 +446,26 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
446446
}
447447
}
448448

449-
// parse long specifiers (only for LP64 model where they make a difference)
450-
#ifndef __LP64__
451-
const
452-
#endif
449+
// parse long and long long specifiers (only where they make a difference)
450+
#if LONG_MAX > INT_MAX
453451
bool long_arg = false;
452+
#endif
453+
454+
#if (MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D) || defined(_WIN64)
455+
bool long_long_arg = false;
456+
#endif
457+
454458
if (*fmt == 'l') {
455459
++fmt;
456-
#ifdef __LP64__
460+
#if LONG_MAX > INT_MAX
457461
long_arg = true;
458462
#endif
463+
#if (MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D) || defined(_WIN64)
464+
if (*fmt == 'l') {
465+
++fmt;
466+
long_long_arg = true;
467+
}
468+
#endif
459469
}
460470

461471
if (*fmt == '\0') {
@@ -501,35 +511,48 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
501511
chrs += mp_print_strn(print, str, len, flags, fill, width);
502512
break;
503513
}
504-
case 'd': {
505-
mp_int_t val;
506-
if (long_arg) {
507-
val = va_arg(args, long int);
508-
} else {
509-
val = va_arg(args, int);
510-
}
511-
chrs += mp_print_int(print, val, 1, 10, 'a', flags, fill, width);
512-
break;
513-
}
514+
case 'p':
515+
case 'P':
516+
case 'd':
514517
case 'u':
515518
case 'x':
516519
case 'X': {
517-
int base = 16 - ((*fmt + 1) & 6); // maps char u/x/X to base 10/16/16
518-
char fmt_c = (*fmt & 0xf0) - 'P' + 'A'; // maps char u/x/X to char a/a/A
520+
char fmt_chr = *fmt;
519521
mp_uint_t val;
520-
if (long_arg) {
521-
val = va_arg(args, unsigned long int);
522+
if (fmt_chr == 'p' || fmt_chr == 'P') {
523+
val = va_arg(args, intptr_t);
524+
}
525+
#if (MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D) || defined(_WIN64)
526+
else if (long_long_arg) {
527+
val = va_arg(args, unsigned long long);
528+
}
529+
#endif
530+
#if LONG_MAX > INT_MAX
531+
else if (long_arg) {
532+
if (sizeof(long) != sizeof(mp_uint_t) && fmt_chr == 'd') {
533+
val = va_arg(args, long);
534+
} else {
535+
val = va_arg(args, unsigned long);
536+
}
537+
}
538+
#endif
539+
else {
540+
if (sizeof(int) != sizeof(mp_uint_t) && fmt_chr == 'd') {
541+
val = va_arg(args, int);
542+
} else {
543+
val = va_arg(args, unsigned);
544+
}
545+
}
546+
int base;
547+
char fmt_c = (fmt_chr & 0xf0) - 'P' +< 10000 /span> 'A'; // maps char u/x/X to char a/a/A
548+
if (fmt_chr == 'd' || fmt_chr == 'u') {
549+
base = 10;
522550
} else {
523-
val = va_arg(args, unsigned int);
551+
base = 16;
524552
}
525-
chrs += mp_print_int(print, val, 0, base, fmt_c, flags, fill, width);
553+
chrs += mp_print_int(print, val, fmt_chr == 'd', base, fmt_c, flags, fill, width);
526554
break;
527555
}
528-
case 'p':
529-
case 'P': // don't bother to handle upcase for 'P'
530-
// Use unsigned long int to work on both ILP32 and LP64 systems
531-
chrs += mp_print_int(print, va_arg(args, unsigned long int), 0, 16, 'a', flags, fill, width);
532-
break;
533556
#if MICROPY_PY_BUILTINS_FLOAT
534557
case 'e':
535558
case 'E':
@@ -545,18 +568,6 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
545568
#endif
546569
break;
547570
}
548-
#endif
549-
// Because 'l' is eaten above, another 'l' means %ll. We need to support
550-
// this length specifier for OBJ_REPR_D (64-bit NaN boxing).
551-
// TODO Either enable this unconditionally, or provide a specific config var.
552-
#if (MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D) || defined(_WIN64)
553-
case 'l': {
554-
unsigned long long int arg_value = va_arg(args, unsigned long long int);
555-
++fmt;
556-
assert(*fmt == 'u' || *fmt == 'd' || !"unsupported fmt char");
557-
chrs += mp_print_int(print, arg_value, *fmt == 'd', 10, 'a', flags, fill, width);
558-
break;
559-
}
560571
#endif
561572
default:
562573
// if it's not %% then it's an unsupported format character

0 commit comments

Comments
 (0)
0