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