summaryrefslogtreecommitdiffstats
path: root/gl/printf-parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/printf-parse.c')
-rw-r--r--gl/printf-parse.c516
1 files changed, 300 insertions, 216 deletions
diff --git a/gl/printf-parse.c b/gl/printf-parse.c
index 3040749a..34d241a6 100644
--- a/gl/printf-parse.c
+++ b/gl/printf-parse.c
@@ -1,5 +1,5 @@
1/* Formatted output to strings. 1/* Formatted output to strings.
2 Copyright (C) 1999-2000, 2002-2003, 2006-2023 Free Software Foundation, Inc. 2 Copyright (C) 1999-2000, 2002-2003, 2006-2026 Free Software Foundation, Inc.
3 3
4 This file is free software: you can redistribute it and/or modify 4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as 5 it under the terms of the GNU Lesser General Public License as
@@ -323,229 +323,316 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
323 } 323 }
324 324
325 { 325 {
326 arg_type type;
327
328 /* Parse argument type/size specifiers. */ 326 /* Parse argument type/size specifiers. */
329 { 327 /* Relevant for the conversion characters d, i. */
330 int flags = 0; 328 arg_type signed_type = TYPE_INT;
331 329 /* Relevant for the conversion characters b, o, u, x, X. */
332 for (;;) 330 arg_type unsigned_type = TYPE_UINT;
333 { 331 /* Relevant for the conversion characters n. */
334 if (*cp == 'h') 332 arg_type pointer_type = TYPE_COUNT_INT_POINTER;
335 { 333 /* Relevant for the conversion characters a, A, e, E, f, F, g, G. */
336 flags |= (1 << (flags & 1)); 334 arg_type floatingpoint_type = TYPE_DOUBLE;
337 cp++; 335
338 } 336 if (*cp == 'h')
339 else if (*cp == 'L') 337 {
340 { 338 if (cp[1] == 'h')
341 flags |= 4; 339 {
342 cp++; 340 signed_type = TYPE_SCHAR;
343 } 341 unsigned_type = TYPE_UCHAR;
344 else if (*cp == 'l') 342 pointer_type = TYPE_COUNT_SCHAR_POINTER;
345 { 343 cp += 2;
346 flags += 8; 344 }
347 cp++; 345 else
348 } 346 {
349 else if (*cp == 'j') 347 signed_type = TYPE_SHORT;
350 { 348 unsigned_type = TYPE_USHORT;
351 if (sizeof (intmax_t) > sizeof (long)) 349 pointer_type = TYPE_COUNT_SHORT_POINTER;
352 { 350 cp++;
353 /* intmax_t = long long */ 351 }
354 flags += 16; 352 }
355 } 353 else if (*cp == 'l')
356 else if (sizeof (intmax_t) > sizeof (int)) 354 {
357 { 355 if (cp[1] == 'l')
358 /* intmax_t = long */ 356 {
359 flags += 8; 357 signed_type = TYPE_LONGLONGINT;
360 } 358 unsigned_type = TYPE_ULONGLONGINT;
361 cp++; 359 pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
362 } 360 /* For backward compatibility only. */
363 else if (*cp == 'z' || *cp == 'Z') 361 floatingpoint_type = TYPE_LONGDOUBLE;
364 { 362 cp += 2;
365 /* 'z' is standardized in ISO C 99, but glibc uses 'Z' 363 }
366 because the warning facility in gcc-2.95.2 understands 364 else
367 only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */ 365 {
368 if (sizeof (size_t) > sizeof (long)) 366 signed_type = TYPE_LONGINT;
369 { 367 unsigned_type = TYPE_ULONGINT;
370 /* size_t = long long */ 368 pointer_type = TYPE_COUNT_LONGINT_POINTER;
371 flags += 16; 369 cp++;
372 } 370 }
373 else if (sizeof (size_t) > sizeof (int)) 371 }
374 { 372 else if (*cp == 'j')
375 /* size_t = long */ 373 {
376 flags += 8; 374 if (sizeof (intmax_t) > sizeof (long))
377 } 375 {
378 cp++; 376 /* intmax_t = long long */
379 } 377 signed_type = TYPE_LONGLONGINT;
380 else if (*cp == 't') 378 unsigned_type = TYPE_ULONGLONGINT;
381 { 379 pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
382 if (sizeof (ptrdiff_t) > sizeof (long)) 380 /* For backward compatibility only. */
383 { 381 floatingpoint_type = TYPE_LONGDOUBLE;
384 /* ptrdiff_t = long long */ 382 }
385 flags += 16; 383 else if (sizeof (intmax_t) > sizeof (int))
386 } 384 {
387 else if (sizeof (ptrdiff_t) > sizeof (int)) 385 /* intmax_t = long */
388 { 386 signed_type = TYPE_LONGINT;
389 /* ptrdiff_t = long */ 387 unsigned_type = TYPE_ULONGINT;
390 flags += 8; 388 pointer_type = TYPE_COUNT_LONGINT_POINTER;
391 } 389 }
392 cp++; 390 cp++;
393 } 391 }
392 else if (*cp == 'z' || *cp == 'Z')
393 {
394 /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
395 because the warning facility in gcc-2.95.2 understands
396 only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
397 if (sizeof (size_t) > sizeof (long))
398 {
399 /* size_t = unsigned long long */
400 signed_type = TYPE_LONGLONGINT;
401 unsigned_type = TYPE_ULONGLONGINT;
402 pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
403 /* For backward compatibility only. */
404 floatingpoint_type = TYPE_LONGDOUBLE;
405 }
406 else if (sizeof (size_t) > sizeof (int))
407 {
408 /* size_t = unsigned long */
409 signed_type = TYPE_LONGINT;
410 unsigned_type = TYPE_ULONGINT;
411 pointer_type = TYPE_COUNT_LONGINT_POINTER;
412 }
413 cp++;
414 }
415 else if (*cp == 't')
416 {
417 if (sizeof (ptrdiff_t) > sizeof (long))
418 {
419 /* ptrdiff_t = long long */
420 signed_type = TYPE_LONGLONGINT;
421 unsigned_type = TYPE_ULONGLONGINT;
422 pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
423 /* For backward compatibility only. */
424 floatingpoint_type = TYPE_LONGDOUBLE;
425 }
426 else if (sizeof (ptrdiff_t) > sizeof (int))
427 {
428 /* ptrdiff_t = long */
429 signed_type = TYPE_LONGINT;
430 unsigned_type = TYPE_ULONGINT;
431 pointer_type = TYPE_COUNT_LONGINT_POINTER;
432 }
433 cp++;
434 }
435 else if (*cp == 'w')
436 {
437 /* wN and wfN are standardized in ISO C 23. */
438 if (cp[1] == 'f')
439 {
440 if (cp[2] == '8')
441 {
442 signed_type = TYPE_INT_FAST8_T;
443 unsigned_type = TYPE_UINT_FAST8_T;
444 pointer_type = TYPE_COUNT_INT_FAST8_T_POINTER;
445 cp += 3;
446 }
447 else if (cp[2] == '1' && cp[3] == '6')
448 {
449 signed_type = TYPE_INT_FAST16_T;
450 unsigned_type = TYPE_UINT_FAST16_T;
451 pointer_type = TYPE_COUNT_INT_FAST16_T_POINTER;
452 cp += 4;
453 }
454 else if (cp[2] == '3' && cp[3] == '2')
455 {
456 signed_type = TYPE_INT_FAST32_T;
457 unsigned_type = TYPE_UINT_FAST32_T;
458 pointer_type = TYPE_COUNT_INT_FAST32_T_POINTER;
459 cp += 4;
460 }
461 else if (cp[2] == '6' && cp[3] == '4')
462 {
463 signed_type = TYPE_INT_FAST64_T;
464 unsigned_type = TYPE_UINT_FAST64_T;
465 pointer_type = TYPE_COUNT_INT_FAST64_T_POINTER;
466 cp += 4;
467 }
468 }
469 else
470 {
471 if (cp[1] == '8')
472 {
473 signed_type = TYPE_INT8_T;
474 unsigned_type = TYPE_UINT8_T;
475 pointer_type = TYPE_COUNT_INT8_T_POINTER;
476 cp += 2;
477 }
478 else if (cp[1] == '1' && cp[2] == '6')
479 {
480 signed_type = TYPE_INT16_T;
481 unsigned_type = TYPE_UINT16_T;
482 pointer_type = TYPE_COUNT_INT16_T_POINTER;
483 cp += 3;
484 }
485 else if (cp[1] == '3' && cp[2] == '2')
486 {
487 signed_type = TYPE_INT32_T;
488 unsigned_type = TYPE_UINT32_T;
489 pointer_type = TYPE_COUNT_INT32_T_POINTER;
490 cp += 3;
491 }
492 else if (cp[1] == '6' && cp[2] == '4')
493 {
494 signed_type = TYPE_INT64_T;
495 unsigned_type = TYPE_UINT64_T;
496 pointer_type = TYPE_COUNT_INT64_T_POINTER;
497 cp += 3;
498 }
499 }
500 }
501 else if (*cp == 'L')
502 {
503 signed_type = TYPE_LONGLONGINT;
504 unsigned_type = TYPE_ULONGLONGINT;
505 pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
506 floatingpoint_type = TYPE_LONGDOUBLE;
507 cp++;
508 }
394#if defined __APPLE__ && defined __MACH__ 509#if defined __APPLE__ && defined __MACH__
395 /* On Mac OS X 10.3, PRIdMAX is defined as "qd". 510 /* On Mac OS X 10.3, PRIdMAX is defined as "qd".
396 We cannot change it to "lld" because PRIdMAX must also 511 We cannot change it to "lld" because PRIdMAX must also
397 be understood by the system's printf routines. */ 512 be understood by the system's printf routines. */
398 else if (*cp == 'q') 513 else if (*cp == 'q')
399 { 514 {
400 if (64 / 8 > sizeof (long)) 515 if (64 / 8 > sizeof (long))
401 { 516 {
402 /* int64_t = long long */ 517 /* int64_t = long long */
403 flags += 16; 518 signed_type = TYPE_LONGLONGINT;
404 } 519 unsigned_type = TYPE_ULONGLONGINT;
405 else 520 pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
406 { 521 /* For backward compatibility only. */
407 /* int64_t = long */ 522 floatingpoint_type = TYPE_LONGDOUBLE;
408 flags += 8; 523 }
409 } 524 else
410 cp++; 525 {
411 } 526 /* int64_t = long */
527 signed_type = TYPE_LONGINT;
528 unsigned_type = TYPE_ULONGINT;
529 pointer_type = TYPE_COUNT_LONGINT_POINTER;
530 }
531 cp++;
532 }
412#endif 533#endif
413#if defined _WIN32 && ! defined __CYGWIN__ 534#if defined _WIN32 && ! defined __CYGWIN__
414 /* On native Windows, PRIdMAX is defined as "I64d". 535 /* On native Windows, PRIdMAX is defined as "I64d".
415 We cannot change it to "lld" because PRIdMAX must also 536 We cannot change it to "lld" because PRIdMAX must also
416 be understood by the system's printf routines. */ 537 be understood by the system's printf routines. */
417 else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4') 538 else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4')
418 { 539 {
419 if (64 / 8 > sizeof (long)) 540 if (64 / 8 > sizeof (long))
420 { 541 {
421 /* __int64 = long long */ 542 /* __int64_t = long long */
422 flags += 16; 543 signed_type = TYPE_LONGLONGINT;
423 } 544 unsigned_type = TYPE_ULONGLONGINT;
424 else 545 pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
425 { 546 /* For backward compatibility only. */
426 /* __int64 = long */ 547 floatingpoint_type = TYPE_LONGDOUBLE;
427 flags += 8; 548 }
428 } 549 else
429 cp += 3; 550 {
430 } 551 /* __int64_t = long */
552 signed_type = TYPE_LONGINT;
553 unsigned_type = TYPE_ULONGINT;
554 pointer_type = TYPE_COUNT_LONGINT_POINTER;
555 }
556 cp += 3;
557 }
431#endif 558#endif
432 else 559 (void) pointer_type;
433 break;
434 }
435 560
436 /* Read the conversion character. */ 561 /* Read the conversion character. */
437 c = *cp++; 562 arg_type type;
438 switch (c) 563 c = *cp++;
439 { 564 switch (c)
440 case 'd': case 'i': 565 {
441 /* If 'long long' is larger than 'long': */ 566 case 'd': case 'i':
442 if (flags >= 16 || (flags & 4)) 567 type = signed_type;
443 type = TYPE_LONGLONGINT; 568 break;
444 else 569 case 'b': case 'o': case 'u': case 'x': case 'X':
445 /* If 'long long' is the same as 'long', we parse "lld" into 570 #if SUPPORT_GNU_PRINTF_DIRECTIVES \
446 TYPE_LONGINT. */ 571 || (__GLIBC__ + (__GLIBC_MINOR__ >= 35) > 2)
447 if (flags >= 8) 572 case 'B':
448 type = TYPE_LONGINT; 573 #endif
449 else if (flags & 2) 574 type = unsigned_type;
450 type = TYPE_SCHAR; 575 break;
451 else if (flags & 1) 576 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
452 type = TYPE_SHORT; 577 case 'a': case 'A':
453 else 578 type = floatingpoint_type;
454 type = TYPE_INT; 579 break;
455 break; 580 case 'c':
456 case 'o': case 'u': case 'x': case 'X': 581 if (signed_type == TYPE_LONGINT
457 /* If 'unsigned long long' is larger than 'unsigned long': */ 582 /* For backward compatibility only. */
458 if (flags >= 16 || (flags & 4)) 583 || signed_type == TYPE_LONGLONGINT)
459 type = TYPE_ULONGLONGINT;
460 else
461 /* If 'unsigned long long' is the same as 'unsigned long', we
462 parse "llu" into TYPE_ULONGINT. */
463 if (flags >= 8)
464 type = TYPE_ULONGINT;
465 else if (flags & 2)
466 type = TYPE_UCHAR;
467 else if (flags & 1)
468 type = TYPE_USHORT;
469 else
470 type = TYPE_UINT;
471 break;
472 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
473 case 'a': case 'A':
474 if (flags >= 16 || (flags & 4))
475 type = TYPE_LONGDOUBLE;
476 else
477 type = TYPE_DOUBLE;
478 break;
479 case 'c':
480 if (flags >= 8)
481#if HAVE_WINT_T 584#if HAVE_WINT_T
482 type = TYPE_WIDE_CHAR; 585 type = TYPE_WIDE_CHAR;
483#else 586#else
484 goto error; 587 goto error;
485#endif 588#endif
486 else 589 else
487 type = TYPE_CHAR; 590 type = TYPE_CHAR;
488 break; 591 break;
489#if HAVE_WINT_T 592#if HAVE_WINT_T
490 case 'C': 593 case 'C':
491 type = TYPE_WIDE_CHAR; 594 type = TYPE_WIDE_CHAR;
492 c = 'c'; 595 c = 'c';
493 break; 596 break;
494#endif
495 case 's':
496 if (flags >= 8)
497#if HAVE_WCHAR_T
498 type = TYPE_WIDE_STRING;
499#else
500 goto error;
501#endif 597#endif
502 else 598 case 's':
503 type = TYPE_STRING; 599 if (signed_type == TYPE_LONGINT
504 break; 600 /* For backward compatibility only. */
505#if HAVE_WCHAR_T 601 || signed_type == TYPE_LONGLONGINT)
506 case 'S':
507 type = TYPE_WIDE_STRING; 602 type = TYPE_WIDE_STRING;
508 c = 's'; 603 else
509 break; 604 type = TYPE_STRING;
605 break;
606 case 'S':
607 type = TYPE_WIDE_STRING;
608 c = 's';
609 break;
610 case 'p':
611 type = TYPE_POINTER;
612 break;
613#if NEED_PRINTF_WITH_N_DIRECTIVE
614 case 'n':
615 type = pointer_type;
616 break;
510#endif 617#endif
511 case 'p':
512 type = TYPE_POINTER;
513 break;
514 case 'n':
515 /* If 'long long' is larger than 'long': */
516 if (flags >= 16 || (flags & 4))
517 type = TYPE_COUNT_LONGLONGINT_POINTER;
518 else
519 /* If 'long long' is the same as 'long', we parse "lln" into
520 TYPE_COUNT_LONGINT_POINTER. */
521 if (flags >= 8)
522 type = TYPE_COUNT_LONGINT_POINTER;
523 else if (flags & 2)
524 type = TYPE_COUNT_SCHAR_POINTER;
525 else if (flags & 1)
526 type = TYPE_COUNT_SHORT_POINTER;
527 else
528 type = TYPE_COUNT_INT_POINTER;
529 break;
530#if ENABLE_UNISTDIO 618#if ENABLE_UNISTDIO
531 /* The unistdio extensions. */ 619 /* The unistdio extensions. */
532 case 'U': 620 case 'U':
533 if (flags >= 16) 621 if (signed_type == TYPE_LONGLONGINT)
534 type = TYPE_U32_STRING; 622 type = TYPE_U32_STRING;
535 else if (flags >= 8) 623 else if (signed_type == TYPE_LONGINT)
536 type = TYPE_U16_STRING; 624 type = TYPE_U16_STRING;
537 else 625 else
538 type = TYPE_U8_STRING; 626 type = TYPE_U8_STRING;
539 break; 627 break;
540#endif 628#endif
541 case '%': 629 case '%':
542 type = TYPE_NONE; 630 type = TYPE_NONE;
543 break; 631 break;
544 default: 632 default:
545 /* Unknown conversion character. */ 633 /* Unknown conversion character. */
546 goto error; 634 goto error;
547 } 635 }
548 }
549 636
550 if (type != TYPE_NONE) 637 if (type != TYPE_NONE)
551 { 638 {
@@ -566,17 +653,14 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
566 d->count++; 653 d->count++;
567 if (d->count >= d_allocated) 654 if (d->count >= d_allocated)
568 { 655 {
569 size_t memory_size;
570 DIRECTIVE *memory;
571
572 d_allocated = xtimes (d_allocated, 2); 656 d_allocated = xtimes (d_allocated, 2);
573 memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); 657 size_t memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
574 if (size_overflow_p (memory_size)) 658 if (size_overflow_p (memory_size))
575 /* Overflow, would lead to out of memory. */ 659 /* Overflow, would lead to out of memory. */
576 goto out_of_memory; 660 goto out_of_memory;
577 memory = (DIRECTIVE *) (d->dir != d->direct_alloc_dir 661 DIRECTIVE *memory = (DIRECTIVE *) (d->dir != d->direct_alloc_dir
578 ? realloc (d->dir, memory_size) 662 ? realloc (d->dir, memory_size)
579 : malloc (memory_size)); 663 : malloc (memory_size));
580 if (memory == NULL) 664 if (memory == NULL)
581 /* Out of memory. */ 665 /* Out of memory. */
582 goto out_of_memory; 666 goto out_of_memory;