@@ -446,16 +446,36 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
446
446
}
447
447
}
448
448
449
- // parse long specifiers (only for LP64 model where they make a difference)
450
- #ifndef __LP64__
451
- const
449
+ // parse long and long long specifiers (only where they make a difference)
450
+ #if defined(MICROPY_UNIX_COVERAGE ) || (LONG_MAX > INT_MAX )
451
+ #define SUPPORT_L_FORMAT (1)
452
+ #else
453
+ #define SUPPORT_L_FORMAT (0)
452
454
#endif
455
+ #if SUPPORT_L_FORMAT
453
456
bool long_arg = false;
457
+ #endif
458
+
459
+ #if (MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D ) || defined(_WIN64 ) || defined(MICROPY_UNIX_COVERAGE )
460
+ #define SUPPORT_LL_FORMAT (1)
461
+ #else
462
+ #define SUPPORT_LL_FORMAT (0)
463
+ #endif
464
+ #if SUPPORT_LL_FORMAT
465
+ bool long_long_arg = false;
466
+ #endif
467
+
454
468
if (* fmt == 'l' ) {
455
469
++ fmt ;
456
- #ifdef __LP64__
470
+ #if SUPPORT_L_FORMAT
457
471
long_arg = true;
458
472
#endif
473
+ #if SUPPORT_LL_FORMAT
474
+ if (* fmt == 'l' ) {
475
+ ++ fmt ;
476
+ long_long_arg = true;
477
+ }
478
+ #endif
459
479
}
460
480
461
481
if (* fmt == '\0' ) {
@@ -501,35 +521,50 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
501
521
chrs += mp_print_strn (print , str , len , flags , fill , width );
502
522
break ;
503
523
}
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
- }
524
+ case 'd' :
525
+ case 'p' :
526
+ case 'P' :
514
527
case 'u' :
515
528
case 'x' :
516
529
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
530
+ char fmt_chr = * fmt ;
519
531
mp_uint_t val ;
520
- if (long_arg ) {
521
- val = va_arg (args , unsigned long int );
532
+ if (fmt_chr == 'p' || fmt_chr == 'P' ) {
533
+ val = va_arg (args , intptr_t );
534
+ }
535
+ #if SUPPORT_LL_FORMAT
536
+ else if (long_long_arg ) {
537
+ val = va_arg (args , unsigned long long);
538
+ }
539
+ #endif
540
+ #if SUPPORT_L_FORMAT
541
+ else if (long_arg ) {
542
+ if (sizeof (long ) != sizeof (mp_uint_t ) && fmt_chr == 'd' ) {
543
+ val = va_arg (args , long );
544
+ } else {
545
+ val = va_arg (args , unsigned long );
546
+ }
547
+ }
548
+ #endif
549
+ else {
550
+ if (sizeof (int ) != sizeof (mp_uint_t ) && fmt_chr == 'd' ) {
551
+ val = va_arg (args , int );
552
+ } else {
553
+ val = va_arg (args , unsigned );
554
+ }
555
+ }
556
+ int base ;
557
+ // Map format char x/p/X/P to a/a/A/A for hex letters.
558
+ // It doesn't matter what d/u map to.
559
+ char fmt_c = (fmt_chr & 0xf0 ) - 'P' + 'A' ;
560
+ if (fmt_chr == 'd' || fmt_chr == 'u' ) {
561
+ base = 10 ;
522
562
} else {
523
- val = va_arg ( args , unsigned int ) ;
563
+ base = 16 ;
524
564
}
525
- chrs += mp_print_int (print , val , 0 , base , fmt_c , flags , fill , width );
565
+ chrs += mp_print_int (print , val , fmt_chr == 'd' , base , fmt_c , flags , fill , width );
526
566
break ;
527
567
}
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 ;
533
568
#if MICROPY_PY_BUILTINS_FLOAT
534
569
case 'e' :
535
570
case 'E' :
@@ -545,18 +580,6 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
545
580
#endif
546
581
break ;
547
582
}
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
- }
560
583
#endif
561
584
default :
562
585
// if it's not %% then it's an unsupported format character
0 commit comments