1/* C format strings. 2 Copyright (C) 2001-2004, 2006-2007 Free Software Foundation, Inc. 3 Written by Bruno Haible <haible@clisp.cons.org>, 2001. 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18#ifdef HAVE_CONFIG_H 19# include <config.h> 20#endif 21 22#include <stdbool.h> 23#include <stdlib.h> 24 25#include "format.h" 26#include "c-ctype.h" 27#include "xalloc.h" 28#include "xvasprintf.h" 29#include "format-invalid.h" 30#include "gettext.h" 31 32#define _(str) gettext (str) 33 34/* C format strings are described in POSIX (IEEE P1003.1 2001), section 35 XSH 3 fprintf(). See also Linux fprintf(3) manual page. 36 A directive 37 - starts with '%' or '%m$' where m is a positive integer, 38 - is optionally followed by any of the characters '#', '0', '-', ' ', '+', 39 "'", or - only in msgstr strings - the string "I", each of which acts as 40 a flag, 41 - is optionally followed by a width specification: '*' (reads an argument) 42 or '*m$' or a nonempty digit sequence, 43 - is optionally followed by '.' and a precision specification: '*' (reads 44 an argument) or '*m$' or a nonempty digit sequence, 45 - is either continued like this: 46 - is optionally followed by a size specifier, one of 'hh' 'h' 'l' 'll' 47 'L' 'q' 'j' 'z' 't', 48 - is finished by a specifier 49 - '%', that needs no argument, 50 - 'c', 'C', that need a character argument, 51 - 's', 'S', that need a string argument, 52 - 'i', 'd', that need a signed integer argument, 53 - 'o', 'u', 'x', 'X', that need an unsigned integer argument, 54 - 'e', 'E', 'f', 'F', 'g', 'G', 'a', 'A', that need a floating-point 55 argument, 56 - 'p', that needs a 'void *' argument, 57 - 'n', that needs a pointer to integer. 58 or is finished by a specifier '<' inttypes-macro '>' where inttypes-macro 59 is an ISO C 99 section 7.8.1 format directive. 60 Numbered ('%m$' or '*m$') and unnumbered argument specifications cannot 61 be used in the same string. When numbered argument specifications are 62 used, specifying the Nth argument requires that all the leading arguments, 63 from the first to the (N-1)th, are specified in the format string. 64 */ 65 66enum format_arg_type 67{ 68 FAT_NONE = 0, 69 /* Basic types */ 70 FAT_INTEGER = 1, 71 FAT_DOUBLE = 2, 72 FAT_CHAR = 3, 73 FAT_STRING = 4, 74 FAT_OBJC_OBJECT = 5, 75 FAT_POINTER = 6, 76 FAT_COUNT_POINTER = 7, 77 /* Flags */ 78 FAT_UNSIGNED = 1 << 3, 79 FAT_SIZE_SHORT = 1 << 4, 80 FAT_SIZE_CHAR = 2 << 4, 81 FAT_SIZE_LONG = 1 << 6, 82 FAT_SIZE_LONGLONG = 2 << 6, 83 FAT_SIZE_8_T = 1 << 8, 84 FAT_SIZE_16_T = 1 << 9, 85 FAT_SIZE_32_T = 1 << 10, 86 FAT_SIZE_64_T = 1 << 11, 87 FAT_SIZE_LEAST8_T = 1 << 12, 88 FAT_SIZE_LEAST16_T = 1 << 13, 89 FAT_SIZE_LEAST32_T = 1 << 14, 90 FAT_SIZE_LEAST64_T = 1 << 15, 91 FAT_SIZE_FAST8_T = 1 << 16, 92 FAT_SIZE_FAST16_T = 1 << 17, 93 FAT_SIZE_FAST32_T = 1 << 18, 94 FAT_SIZE_FAST64_T = 1 << 19, 95 FAT_SIZE_INTMAX_T = 1 << 20, 96 FAT_SIZE_INTPTR_T = 1 << 21, 97 FAT_SIZE_SIZE_T = 1 << 22, 98 FAT_SIZE_PTRDIFF_T = 1 << 23, 99 FAT_WIDE = FAT_SIZE_LONG, 100 /* Meaningful combinations of basic types and flags: 101 'signed char' = FAT_INTEGER | FAT_SIZE_CHAR, 102 'unsigned char' = FAT_INTEGER | FAT_SIZE_CHAR | FAT_UNSIGNED, 103 'short' = FAT_INTEGER | FAT_SIZE_SHORT, 104 'unsigned short' = FAT_INTEGER | FAT_SIZE_SHORT | FAT_UNSIGNED, 105 'int' = FAT_INTEGER, 106 'unsigned int' = FAT_INTEGER | FAT_UNSIGNED, 107 'long int' = FAT_INTEGER | FAT_SIZE_LONG, 108 'unsigned long int' = FAT_INTEGER | FAT_SIZE_LONG | FAT_UNSIGNED, 109 'long long int' = FAT_INTEGER | FAT_SIZE_LONGLONG, 110 'unsigned long long int' = FAT_INTEGER | FAT_SIZE_LONGLONG | FAT_UNSIGNED, 111 'double' = FAT_DOUBLE, 112 'long double' = FAT_DOUBLE | FAT_SIZE_LONGLONG, 113 'char'/'int' = FAT_CHAR, 114 'wchar_t'/'wint_t' = FAT_CHAR | FAT_SIZE_LONG, 115 'const char *' = FAT_STRING, 116 'const wchar_t *' = FAT_STRING | FAT_SIZE_LONG, 117 'void *' = FAT_POINTER, 118 FAT_COUNT_SCHAR_POINTER = FAT_COUNT_POINTER | FAT_SIZE_CHAR, 119 FAT_COUNT_SHORT_POINTER = FAT_COUNT_POINTER | FAT_SIZE_SHORT, 120 FAT_COUNT_INT_POINTER = FAT_COUNT_POINTER, 121 FAT_COUNT_LONGINT_POINTER = FAT_COUNT_POINTER | FAT_SIZE_LONG, 122 FAT_COUNT_LONGLONGINT_POINTER = FAT_COUNT_POINTER | FAT_SIZE_LONGLONG, 123 */ 124 /* Bitmasks */ 125 FAT_SIZE_MASK = (FAT_SIZE_SHORT | FAT_SIZE_CHAR 126 | FAT_SIZE_LONG | FAT_SIZE_LONGLONG 127 | FAT_SIZE_8_T | FAT_SIZE_16_T 128 | FAT_SIZE_32_T | FAT_SIZE_64_T 129 | FAT_SIZE_LEAST8_T | FAT_SIZE_LEAST16_T 130 | FAT_SIZE_LEAST32_T | FAT_SIZE_LEAST64_T 131 | FAT_SIZE_FAST8_T | FAT_SIZE_FAST16_T 132 | FAT_SIZE_FAST32_T | FAT_SIZE_FAST64_T 133 | FAT_SIZE_INTMAX_T | FAT_SIZE_INTPTR_T 134 | FAT_SIZE_SIZE_T | FAT_SIZE_PTRDIFF_T) 135}; 136#ifdef __cplusplus 137typedef int format_arg_type_t; 138#else 139typedef enum format_arg_type format_arg_type_t; 140#endif 141 142struct numbered_arg 143{ 144 unsigned int number; 145 format_arg_type_t type; 146}; 147 148struct unnumbered_arg 149{ 150 format_arg_type_t type; 151}; 152 153struct spec 154{ 155 unsigned int directives; 156 unsigned int unnumbered_arg_count; 157 unsigned int allocated; 158 struct unnumbered_arg *unnumbered; 159 bool unlikely_intentional; 160 unsigned int sysdep_directives_count; 161 const char **sysdep_directives; 162}; 163 164/* Locale independent test for a decimal digit. 165 Argument can be 'char' or 'unsigned char'. (Whereas the argument of 166 <ctype.h> isdigit must be an 'unsigned char'.) */ 167#undef isdigit 168#define isdigit(c) ((unsigned int) ((c) - '0') < 10) 169 170 171static int 172numbered_arg_compare (const void *p1, const void *p2) 173{ 174 unsigned int n1 = ((const struct numbered_arg *) p1)->number; 175 unsigned int n2 = ((const struct numbered_arg *) p2)->number; 176 177 return (n1 > n2 ? 1 : n1 < n2 ? -1 : 0); 178} 179 180#define INVALID_C99_MACRO(directive_number) \ 181 xasprintf (_("In the directive number %u, the token after '<' is not the name of a format specifier macro. The valid macro names are listed in ISO C 99 section 7.8.1."), directive_number) 182 183static void * 184format_parse (const char *format, bool translated, bool objc_extensions, 185 char *fdi, char **invalid_reason) 186{ 187 const char *const format_start = format; 188 struct spec spec; 189 unsigned int numbered_arg_count; 190 struct numbered_arg *numbered; 191 struct spec *result; 192 193 spec.directives = 0; 194 numbered_arg_count = 0; 195 spec.unnumbered_arg_count = 0; 196 spec.allocated = 0; 197 numbered = NULL; 198 spec.unnumbered = NULL; 199 spec.unlikely_intentional = false; 200 spec.sysdep_directives_count = 0; 201 spec.sysdep_directives = NULL; 202 203 for (; *format != '\0';) 204 if (*format++ == '%') 205 { 206 /* A directive. */ 207 unsigned int number = 0; 208 format_arg_type_t type; 209 format_arg_type_t size; 210 211 FDI_SET (format - 1, FMTDIR_START); 212 spec.directives++; 213 214 if (isdigit (*format)) 215 { 216 const char *f = format; 217 unsigned int m = 0; 218 219 do 220 { 221 m = 10 * m + (*f - '0'); 222 f++; 223 } 224 while (isdigit (*f)); 225 226 if (*f == '$') 227 { 228 if (m == 0) 229 { 230 *invalid_reason = INVALID_ARGNO_0 (spec.directives); 231 FDI_SET (f, FMTDIR_ERROR); 232 goto bad_format; 233 } 234 number = m; 235 format = ++f; 236 } 237 } 238 239 /* Parse flags. */ 240 for (;;) 241 { 242 if (*format == ' ' || *format == '+' || *format == '-' 243 || *format == '#' || *format == '0' || *format == '\'') 244 format++; 245 else if (translated && *format == 'I') 246 { 247 spec.sysdep_directives = 248 (const char **) 249 xrealloc (spec.sysdep_directives, 250 2 * (spec.sysdep_directives_count + 1) 251 * sizeof (const char *)); 252 spec.sysdep_directives[2 * spec.sysdep_directives_count] = format; 253 spec.sysdep_directives[2 * spec.sysdep_directives_count + 1] = format + 1; 254 spec.sysdep_directives_count++; 255 format++; 256 } 257 else 258 break; 259 } 260 261 /* Parse width. */ 262 if (*format == '*') 263 { 264 unsigned int width_number = 0; 265 266 format++; 267 268 if (isdigit (*format)) 269 { 270 const char *f = format; 271 unsigned int m = 0; 272 273 do 274 { 275 m = 10 * m + (*f - '0'); 276 f++; 277 } 278 while (isdigit (*f)); 279 280 if (*f == '$') 281 { 282 if (m == 0) 283 { 284 *invalid_reason = 285 INVALID_WIDTH_ARGNO_0 (spec.directives); 286 FDI_SET (f, FMTDIR_ERROR); 287 goto bad_format; 288 } 289 width_number = m; 290 format = ++f; 291 } 292 } 293 294 if (width_number) 295 { 296 /* Numbered argument. */ 297 298 /* Numbered and unnumbered specifications are exclusive. */ 299 if (spec.unnumbered_arg_count > 0) 300 { 301 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); 302 FDI_SET (format - 1, FMTDIR_ERROR); 303 goto bad_format; 304 } 305 306 if (spec.allocated == numbered_arg_count) 307 { 308 spec.allocated = 2 * spec.allocated + 1; 309 numbered = (struct numbered_arg *) xrealloc (numbered, spec.allocated * sizeof (struct numbered_arg)); 310 } 311 numbered[numbered_arg_count].number = width_number; 312 numbered[numbered_arg_count].type = FAT_INTEGER; 313 numbered_arg_count++; 314 } 315 else 316 { 317 /* Unnumbered argument. */ 318 319 /* Numbered and unnumbered specifications are exclusive. */ 320 if (numbered_arg_count > 0) 321 { 322 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); 323 FDI_SET (format - 1, FMTDIR_ERROR); 324 goto bad_format; 325 } 326 327 if (spec.allocated == spec.unnumbered_arg_count) 328 { 329 spec.allocated = 2 * spec.allocated + 1; 330 spec.unnumbered = (struct unnumbered_arg *) xrealloc (spec.unnumbered, spec.allocated * sizeof (struct unnumbered_arg)); 331 } 332 spec.unnumbered[spec.unnumbered_arg_count].type = FAT_INTEGER; 333 spec.unnumbered_arg_count++; 334 } 335 } 336 else if (isdigit (*format)) 337 { 338 do format++; while (isdigit (*format)); 339 } 340 341 /* Parse precision. */ 342 if (*format == '.') 343 { 344 format++; 345 346 if (*format == '*') 347 { 348 unsigned int precision_number = 0; 349 350 format++; 351 352 if (isdigit (*format)) 353 { 354 const char *f = format; 355 unsigned int m = 0; 356 357 do 358 { 359 m = 10 * m + (*f - '0'); 360 f++; 361 } 362 while (isdigit (*f)); 363 364 if (*f == '$') 365 { 366 if (m == 0) 367 { 368 *invalid_reason = 369 INVALID_PRECISION_ARGNO_0 (spec.directives); 370 FDI_SET (f, FMTDIR_ERROR); 371 goto bad_format; 372 } 373 precision_number = m; 374 format = ++f; 375 } 376 } 377 378 if (precision_number) 379 { 380 /* Numbered argument. */ 381 382 /* Numbered and unnumbered specifications are exclusive. */ 383 if (spec.unnumbered_arg_count > 0) 384 { 385 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); 386 FDI_SET (format - 1, FMTDIR_ERROR); 387 goto bad_format; 388 } 389 390 if (spec.allocated == numbered_arg_count) 391 { 392 spec.allocated = 2 * spec.allocated + 1; 393 numbered = (struct numbered_arg *) xrealloc (numbered, spec.allocated * sizeof (struct numbered_arg)); 394 } 395 numbered[numbered_arg_count].number = precision_number; 396 numbered[numbered_arg_count].type = FAT_INTEGER; 397 numbered_arg_count++; 398 } 399 else 400 { 401 /* Unnumbered argument. */ 402 403 /* Numbered and unnumbered specifications are exclusive. */ 404 if (numbered_arg_count > 0) 405 { 406 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); 407 FDI_SET (format - 1, FMTDIR_ERROR); 408 goto bad_format; 409 } 410 411 if (spec.allocated == spec.unnumbered_arg_count) 412 { 413 spec.allocated = 2 * spec.allocated + 1; 414 spec.unnumbered = (struct unnumbered_arg *) xrealloc (spec.unnumbered, spec.allocated * sizeof (struct unnumbered_arg)); 415 } 416 spec.unnumbered[spec.unnumbered_arg_count].type = FAT_INTEGER; 417 spec.unnumbered_arg_count++; 418 } 419 } 420 else if (isdigit (*format)) 421 { 422 do format++; while (isdigit (*format)); 423 } 424 } 425 426 if (*format == '<') 427 { 428 spec.sysdep_directives = 429 (const char **) 430 xrealloc (spec.sysdep_directives, 431 2 * (spec.sysdep_directives_count + 1) 432 * sizeof (const char *)); 433 spec.sysdep_directives[2 * spec.sysdep_directives_count] = format; 434 435 format++; 436 /* Parse ISO C 99 section 7.8.1 format string directive. 437 Syntax: 438 P R I { d | i | o | u | x | X } 439 { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR } */ 440 if (*format != 'P') 441 { 442 *invalid_reason = INVALID_C99_MACRO (spec.directives); 443 FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR); 444 goto bad_format; 445 } 446 format++; 447 if (*format != 'R') 448 { 449 *invalid_reason = INVALID_C99_MACRO (spec.directives); 450 FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR); 451 goto bad_format; 452 } 453 format++; 454 if (*format != 'I') 455 { 456 *invalid_reason = INVALID_C99_MACRO (spec.directives); 457 FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR); 458 goto bad_format; 459 } 460 format++; 461 462 switch (*format) 463 { 464 case 'i': case 'd': 465 type = FAT_INTEGER; 466 break; 467 case 'u': case 'o': case 'x': case 'X': 468 type = FAT_INTEGER | FAT_UNSIGNED; 469 break; 470 default: 471 *invalid_reason = INVALID_C99_MACRO (spec.directives); 472 FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR); 473 goto bad_format; 474 } 475 format++; 476 477 if (format[0] == 'M' && format[1] == 'A' && format[2] == 'X') 478 { 479 type |= FAT_SIZE_INTMAX_T; 480 format += 3; 481 } 482 else if (format[0] == 'P' && format[1] == 'T' && format[2] == 'R') 483 { 484 type |= FAT_SIZE_INTPTR_T; 485 format += 3; 486 } 487 else 488 { 489 if (format[0] == 'L' && format[1] == 'E' && format[2] == 'A' 490 && format[3] == 'S' && format[4] == 'T') 491 { 492 format += 5; 493 if (format[0] == '8') 494 { 495 type |= FAT_SIZE_LEAST8_T; 496 format++; 497 } 498 else if (format[0] == '1' && format[1] == '6') 499 { 500 type |= FAT_SIZE_LEAST16_T; 501 format += 2; 502 } 503 else if (format[0] == '3' && format[1] == '2') 504 { 505 type |= FAT_SIZE_LEAST32_T; 506 format += 2; 507 } 508 else if (format[0] == '6' && format[1] == '4') 509 { 510 type |= FAT_SIZE_LEAST64_T; 511 format += 2; 512 } 513 else 514 { 515 *invalid_reason = INVALID_C99_MACRO (spec.directives); 516 FDI_SET (*format == '\0' ? format - 1 : format, 517 FMTDIR_ERROR); 518 goto bad_format; 519 } 520 } 521 else if (format[0] == 'F' && format[1] == 'A' 522 && format[2] == 'S' && format[3] == 'T') 523 { 524 format += 4; 525 if (format[0] == '8') 526 { 527 type |= FAT_SIZE_FAST8_T; 528 format++; 529 } 530 else if (format[0] == '1' && format[1] == '6') 531 { 532 type |= FAT_SIZE_FAST16_T; 533 format += 2; 534 } 535 else if (format[0] == '3' && format[1] == '2') 536 { 537 type |= FAT_SIZE_FAST32_T; 538 format += 2; 539 } 540 else if (format[0] == '6' && format[1] == '4') 541 { 542 type |= FAT_SIZE_FAST64_T; 543 format += 2; 544 } 545 else 546 { 547 *invalid_reason = INVALID_C99_MACRO (spec.directives); 548 FDI_SET (*format == '\0' ? format - 1 : format, 549 FMTDIR_ERROR); 550 goto bad_format; 551 } 552 } 553 else 554 { 555 if (format[0] == '8') 556 { 557 type |= FAT_SIZE_8_T; 558 format++; 559 } 560 else if (format[0] == '1' && format[1] == '6') 561 { 562 type |= FAT_SIZE_16_T; 563 format += 2; 564 } 565 else if (format[0] == '3' && format[1] == '2') 566 { 567 type |= FAT_SIZE_32_T; 568 format += 2; 569 } 570 else if (format[0] == '6' && format[1] == '4') 571 { 572 type |= FAT_SIZE_64_T; 573 format += 2; 574 } 575 else 576 { 577 *invalid_reason = INVALID_C99_MACRO (spec.directives); 578 FDI_SET (*format == '\0' ? format - 1 : format, 579 FMTDIR_ERROR); 580 goto bad_format; 581 } 582 } 583 } 584 585 if (*format != '>') 586 { 587 *invalid_reason = 588 xasprintf (_("In the directive number %u, the token after '<' is not followed by '>'."), spec.directives); 589 FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR); 590 goto bad_format; 591 } 592 593 spec.sysdep_directives[2 * spec.sysdep_directives_count + 1] = format + 1; 594 spec.sysdep_directives_count++; 595 } 596 else 597 { 598 /* Parse size. */ 599 size = 0; 600 for (;; format++) 601 { 602 if (*format == 'h') 603 { 604 if (size & (FAT_SIZE_SHORT | FAT_SIZE_CHAR)) 605 size = FAT_SIZE_CHAR; 606 else 607 size = FAT_SIZE_SHORT; 608 } 609 else if (*format == 'l') 610 { 611 if (size & (FAT_SIZE_LONG | FAT_SIZE_LONGLONG)) 612 size = FAT_SIZE_LONGLONG; 613 else 614 size = FAT_SIZE_LONG; 615 } 616 else if (*format == 'L') 617 size = FAT_SIZE_LONGLONG; 618 else if (*format == 'q') 619 /* Old BSD 4.4 convention. */ 620 size = FAT_SIZE_LONGLONG; 621 else if (*format == 'j') 622 size = FAT_SIZE_INTMAX_T; 623 else if (*format == 'z' || *format == 'Z') 624 /* 'z' is standardized in ISO C 99, but glibc uses 'Z' 625 because the warning facility in gcc-2.95.2 understands 626 only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */ 627 size = FAT_SIZE_SIZE_T; 628 else if (*format == 't') 629 size = FAT_SIZE_PTRDIFF_T; 630 else 631 break; 632 } 633 634 switch (*format) 635 { 636 case '%': 637 /* Programmers writing _("%2%") most often will not want to 638 use this string as a c-format string, but rather as a 639 literal or as a different kind of format string. */ 640 if (format[-1] != '%') 641 spec.unlikely_intentional = true; 642 type = FAT_NONE; 643 break; 644 case 'm': /* glibc extension */ 645 type = FAT_NONE; 646 break; 647 case 'c': 648 type = FAT_CHAR; 649 type |= (size & (FAT_SIZE_LONG | FAT_SIZE_LONGLONG) 650 ? FAT_WIDE : 0); 651 break; 652 case 'C': /* obsolete */ 653 type = FAT_CHAR | FAT_WIDE; 654 break; 655 case 's': 656 type = FAT_STRING; 657 type |= (size & (FAT_SIZE_LONG | FAT_SIZE_LONGLONG) 658 ? FAT_WIDE : 0); 659 break; 660 case 'S': /* obsolete */ 661 type = FAT_STRING | FAT_WIDE; 662 break; 663 case 'i': case 'd': 664 type = FAT_INTEGER; 665 type |= (size & FAT_SIZE_MASK); 666 break; 667 case 'u': case 'o': case 'x': case 'X': 668 type = FAT_INTEGER | FAT_UNSIGNED; 669 type |= (size & FAT_SIZE_MASK); 670 break; 671 case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': 672 case 'a': case 'A': 673 type = FAT_DOUBLE; 674 type |= (size & FAT_SIZE_LONGLONG); 675 break; 676 case '@': 677 if (objc_extensions) 678 { 679 type = FAT_OBJC_OBJECT; 680 break; 681 } 682 goto other; 683 case 'p': 684 type = FAT_POINTER; 685 break; 686 case 'n': 687 type = FAT_COUNT_POINTER; 688 type |= (size & FAT_SIZE_MASK); 689 break; 690 other: 691 default: 692 if (*format == '\0') 693 { 694 *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); 695 FDI_SET (format - 1, FMTDIR_ERROR); 696 } 697 else 698 { 699 *invalid_reason = 700 INVALID_CONVERSION_SPECIFIER (spec.directives, *format); 701 FDI_SET (format, FMTDIR_ERROR); 702 } 703 goto bad_format; 704 } 705 } 706 707 if (type != FAT_NONE) 708 { 709 if (number) 710 { 711 /* Numbered argument. */ 712 713 /* Numbered and unnumbered specifications are exclusive. */ 714 if (spec.unnumbered_arg_count > 0) 715 { 716 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); 717 FDI_SET (format, FMTDIR_ERROR); 718 goto bad_format; 719 } 720 721 if (spec.allocated == numbered_arg_count) 722 { 723 spec.allocated = 2 * spec.allocated + 1; 724 numbered = (struct numbered_arg *) xrealloc (numbered, spec.allocated * sizeof (struct numbered_arg)); 725 } 726 numbered[numbered_arg_count].number = number; 727 numbered[numbered_arg_count].type = type; 728 numbered_arg_count++; 729 } 730 else 731 { 732 /* Unnumbered argument. */ 733 734 /* Numbered and unnumbered specifications are exclusive. */ 735 if (numbered_arg_count > 0) 736 { 737 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); 738 FDI_SET (format, FMTDIR_ERROR); 739 goto bad_format; 740 } 741 742 if (spec.allocated == spec.unnumbered_arg_count) 743 { 744 spec.allocated = 2 * spec.allocated + 1; 745 spec.unnumbered = (struct unnumbered_arg *) xrealloc (spec.unnumbered, spec.allocated * sizeof (struct unnumbered_arg)); 746 } 747 spec.unnumbered[spec.unnumbered_arg_count].type = type; 748 spec.unnumbered_arg_count++; 749 } 750 } 751 752 FDI_SET (format, FMTDIR_END); 753 754 format++; 755 } 756 757 /* Sort the numbered argument array, and eliminate duplicates. */ 758 if (numbered_arg_count > 1) 759 { 760 unsigned int i, j; 761 bool err; 762 763 qsort (numbered, numbered_arg_count, 764 sizeof (struct numbered_arg), numbered_arg_compare); 765 766 /* Remove duplicates: Copy from i to j, keeping 0 <= j <= i. */ 767 err = false; 768 for (i = j = 0; i < numbered_arg_count; i++) 769 if (j > 0 && numbered[i].number == numbered[j-1].number) 770 { 771 format_arg_type_t type1 = numbered[i].type; 772 format_arg_type_t type2 = numbered[j-1].type; 773 format_arg_type_t type_both; 774 775 if (type1 == type2) 776 type_both = type1; 777 else 778 { 779 /* Incompatible types. */ 780 type_both = FAT_NONE; 781 if (!err) 782 *invalid_reason = 783 INVALID_INCOMPATIBLE_ARG_TYPES (numbered[i].number); 784 err = true; 785 } 786 787 numbered[j-1].type = type_both; 788 } 789 else 790 { 791 if (j < i) 792 { 793 numbered[j].number = numbered[i].number; 794 numbered[j].type = numbered[i].type; 795 } 796 j++; 797 } 798 numbered_arg_count = j; 799 if (err) 800 /* *invalid_reason has already been set above. */ 801 goto bad_format; 802 } 803 804 /* Verify that the format strings uses all arguments up to the highest 805 numbered one. */ 806 if (numbered_arg_count > 0) 807 { 808 unsigned int i; 809 810 for (i = 0; i < numbered_arg_count; i++) 811 if (numbered[i].number != i + 1) 812 { 813 *invalid_reason = 814 xasprintf (_("The string refers to argument number %u but ignores argument number %u."), numbered[i].number, i + 1); 815 goto bad_format; 816 } 817 818 /* So now the numbered arguments array is equivalent to a sequence 819 of unnumbered arguments. */ 820 spec.unnumbered_arg_count = numbered_arg_count; 821 spec.allocated = spec.unnumbered_arg_count; 822 spec.unnumbered = XNMALLOC (spec.allocated, struct unnumbered_arg); 823 for (i = 0; i < spec.unnumbered_arg_count; i++) 824 spec.unnumbered[i].type = numbered[i].type; 825 free (numbered); 826 numbered_arg_count = 0; 827 } 828 829 result = XMALLOC (struct spec); 830 *result = spec; 831 return result; 832 833 bad_format: 834 if (numbered != NULL) 835 free (numbered); 836 if (spec.unnumbered != NULL) 837 free (spec.unnumbered); 838 if (spec.sysdep_directives != NULL) 839 free (spec.sysdep_directives); 840 return NULL; 841} 842 843static void * 844format_c_parse (const char *format, bool translated, char *fdi, 845 char **invalid_reason) 846{ 847 return format_parse (format, translated, false, fdi, invalid_reason); 848} 849 850static void * 851format_objc_parse (const char *format, bool translated, char *fdi, 852 char **invalid_reason) 853{ 854 return format_parse (format, translated, true, fdi, invalid_reason); 855} 856 857static void 858format_free (void *descr) 859{ 860 struct spec *spec = (struct spec *) descr; 861 862 if (spec->unnumbered != NULL) 863 free (spec->unnumbered); 864 if (spec->sysdep_directives != NULL) 865 free (spec->sysdep_directives); 866 free (spec); 867} 868 869static bool 870format_is_unlikely_intentional (void *descr) 871{ 872 struct spec *spec = (struct spec *) descr; 873 874 return spec->unlikely_intentional; 875} 876 877static int 878format_get_number_of_directives (void *descr) 879{ 880 struct spec *spec = (struct spec *) descr; 881 882 return spec->directives; 883} 884 885static bool 886format_check (void *msgid_descr, void *msgstr_descr, bool equality, 887 formatstring_error_logger_t error_logger, 888 const char *pretty_msgstr) 889{ 890 struct spec *spec1 = (struct spec *) msgid_descr; 891 struct spec *spec2 = (struct spec *) msgstr_descr; 892 bool err = false; 893 unsigned int i; 894 895 /* Check the argument types are the same. */ 896 if (equality 897 ? spec1->unnumbered_arg_count != spec2->unnumbered_arg_count 898 : spec1->unnumbered_arg_count < spec2->unnumbered_arg_count) 899 { 900 if (error_logger) 901 error_logger (_("number of format specifications in 'msgid' and '%s' does not match"), 902 pretty_msgstr); 903 err = true; 904 } 905 else 906 for (i = 0; i < spec2->unnumbered_arg_count; i++) 907 if (spec1->unnumbered[i].type != spec2->unnumbered[i].type) 908 { 909 if (error_logger) 910 error_logger (_("format specifications in 'msgid' and '%s' for argument %u are not the same"), 911 pretty_msgstr, i + 1); 912 err = true; 913 } 914 915 return err; 916} 917 918 919struct formatstring_parser formatstring_c = 920{ 921 format_c_parse, 922 format_free, 923 format_get_number_of_directives, 924 format_is_unlikely_intentional, 925 format_check 926}; 927 928 929struct formatstring_parser formatstring_objc = 930{ 931 format_objc_parse, 932 format_free, 933 format_get_number_of_directives, 934 format_is_unlikely_intentional, 935 format_check 936}; 937 938 939void 940get_sysdep_c_format_directives (const char *string, bool translated, 941 struct interval **intervalsp, size_t *lengthp) 942{ 943 /* Parse the format string with all possible extensions turned on. (The 944 caller has already verified that the format string is valid for the 945 particular language.) */ 946 char *invalid_reason = NULL; 947 struct spec *descr = 948 (struct spec *) 949 format_parse (string, translated, true, NULL, &invalid_reason); 950 951 if (descr != NULL && descr->sysdep_directives_count > 0) 952 { 953 unsigned int n = descr->sysdep_directives_count; 954 struct interval *intervals = XNMALLOC (n, struct interval); 955 unsigned int i; 956 957 for (i = 0; i < n; i++) 958 { 959 intervals[i].startpos = descr->sysdep_directives[2 * i] - string; 960 intervals[i].endpos = descr->sysdep_directives[2 * i + 1] - string; 961 } 962 *intervalsp = intervals; 963 *lengthp = n; 964 } 965 else 966 { 967 *intervalsp = NULL; 968 *lengthp = 0; 969 } 970 971 if (descr != NULL) 972 format_free (descr); 973 else 974 free (invalid_reason); 975} 976 977 978#ifdef TEST 979 980/* Test program: Print the argument list specification returned by 981 format_parse for strings read from standard input. */ 982 983#include <stdio.h> 984 985static void 986format_print (void *descr) 987{ 988 struct spec *spec = (struct spec *) descr; 989 unsigned int i; 990 991 if (spec == NULL) 992 { 993 printf ("INVALID"); 994 return; 995 } 996 997 printf ("("); 998 for (i = 0; i < spec->unnumbered_arg_count; i++) 999 { 1000 if (i > 0) 1001 printf (" "); 1002 if (spec->unnumbered[i].type & FAT_UNSIGNED) 1003 printf ("[unsigned]"); 1004 switch (spec->unnumbered[i].type & FAT_SIZE_MASK) 1005 { 1006 case 0: 1007 break; 1008 case FAT_SIZE_SHORT: 1009 printf ("[short]"); 1010 break; 1011 case FAT_SIZE_CHAR: 1012 printf ("[char]"); 1013 break; 1014 case FAT_SIZE_LONG: 1015 printf ("[long]"); 1016 break; 1017 case FAT_SIZE_LONGLONG: 1018 printf ("[long long]"); 1019 break; 1020 case FAT_SIZE_8_T: 1021 printf ("[int8_t]"); 1022 break; 1023 case FAT_SIZE_16_T: 1024 printf ("[int16_t]"); 1025 break; 1026 case FAT_SIZE_32_T: 1027 printf ("[int32_t]"); 1028 break; 1029 case FAT_SIZE_64_T: 1030 printf ("[int64_t]"); 1031 break; 1032 case FAT_SIZE_LEAST8_T: 1033 printf ("[int_least8_t]"); 1034 break; 1035 case FAT_SIZE_LEAST16_T: 1036 printf ("[int_least16_t]"); 1037 break; 1038 case FAT_SIZE_LEAST32_T: 1039 printf ("[int_least32_t]"); 1040 break; 1041 case FAT_SIZE_LEAST64_T: 1042 printf ("[int_least64_t]"); 1043 break; 1044 case FAT_SIZE_FAST8_T: 1045 printf ("[int_fast8_t]"); 1046 break; 1047 case FAT_SIZE_FAST16_T: 1048 printf ("[int_fast16_t]"); 1049 break; 1050 case FAT_SIZE_FAST32_T: 1051 printf ("[int_fast32_t]"); 1052 break; 1053 case FAT_SIZE_FAST64_T: 1054 printf ("[int_fast64_t]"); 1055 break; 1056 case FAT_SIZE_INTMAX_T: 1057 printf ("[intmax_t]"); 1058 break; 1059 case FAT_SIZE_INTPTR_T: 1060 printf ("[intptr_t]"); 1061 break; 1062 case FAT_SIZE_SIZE_T: 1063 printf ("[size_t]"); 1064 break; 1065 case FAT_SIZE_PTRDIFF_T: 1066 printf ("[ptrdiff_t]"); 1067 break; 1068 default: 1069 abort (); 1070 } 1071 switch (spec->unnumbered[i].type & ~(FAT_UNSIGNED | FAT_SIZE_MASK)) 1072 { 1073 case FAT_INTEGER: 1074 printf ("i"); 1075 break; 1076 case FAT_DOUBLE: 1077 printf ("f"); 1078 break; 1079 case FAT_CHAR: 1080 printf ("c"); 1081 break; 1082 case FAT_STRING: 1083 printf ("s"); 1084 break; 1085 case FAT_OBJC_OBJECT: 1086 printf ("@"); 1087 break; 1088 case FAT_POINTER: 1089 printf ("p"); 1090 break; 1091 case FAT_COUNT_POINTER: 1092 printf ("n"); 1093 break; 1094 default: 1095 abort (); 1096 } 1097 } 1098 printf (")"); 1099} 1100 1101int 1102main () 1103{ 1104 for (;;) 1105 { 1106 char *line = NULL; 1107 size_t line_size = 0; 1108 int line_len; 1109 char *invalid_reason; 1110 void *descr; 1111 1112 line_len = getline (&line, &line_size, stdin); 1113 if (line_len < 0) 1114 break; 1115 if (line_len > 0 && line[line_len - 1] == '\n') 1116 line[--line_len] = '\0'; 1117 1118 invalid_reason = NULL; 1119 descr = format_c_parse (line, false, NULL, &invalid_reason); 1120 1121 format_print (descr); 1122 printf ("\n"); 1123 if (descr == NULL) 1124 printf ("%s\n", invalid_reason); 1125 1126 free (invalid_reason); 1127 free (line); 1128 } 1129 1130 return 0; 1131} 1132 1133/* 1134 * For Emacs M-x compile 1135 * Local Variables: 1136 * compile-command: "/bin/sh ../libtool --tag=CC --mode=link gcc -o a.out -static -O -g -Wall -I.. -I../gnulib-lib -I../intl -DHAVE_CONFIG_H -DTEST format-c.c ../gnulib-lib/libgettextlib.la" 1137 * End: 1138 */ 1139 1140#endif /* TEST */ 1141