2 Copyright (C) 2001-2004, 2006-2007, 2009 Free Software Foundation, Inc.
3 Written by Bruno Haible <haible@clisp.cons.org>, 2001.
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.
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.
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/>. */
28 #include "xvasprintf.h"
29 #include "format-invalid.h"
32 #define _(str) gettext (str)
34 /* C format strings are described in POSIX (IEEE P1003.1 2001), section
35 XSH 3 fprintf(). See also Linux fprintf(3) manual page.
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
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'
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
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.
76 FAT_COUNT_POINTER = 7,
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,
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,
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)
137 typedef int format_arg_type_t;
139 typedef enum format_arg_type format_arg_type_t;
145 format_arg_type_t type;
148 struct unnumbered_arg
150 format_arg_type_t type;
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;
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'.) */
168 #define isdigit(c) ((unsigned int) ((c) - '0') < 10)
172 numbered_arg_compare (const void *p1, const void *p2)
174 unsigned int n1 = ((const struct numbered_arg *) p1)->number;
175 unsigned int n2 = ((const struct numbered_arg *) p2)->number;
177 return (n1 > n2 ? 1 : n1 < n2 ? -1 : 0);
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)
184 format_parse (const char *format, bool translated, bool objc_extensions,
185 char *fdi, char **invalid_reason)
187 const char *const format_start = format;
189 unsigned int numbered_arg_count;
190 struct numbered_arg *numbered;
194 numbered_arg_count = 0;
195 spec.unnumbered_arg_count = 0;
198 spec.unnumbered = NULL;
199 spec.unlikely_intentional = false;
200 spec.sysdep_directives_count = 0;
201 spec.sysdep_directives = NULL;
203 for (; *format != '\0';)
204 if (*format++ == '%')
207 unsigned int number = 0;
208 format_arg_type_t type;
209 format_arg_type_t size;
211 FDI_SET (format - 1, FMTDIR_START);
214 if (isdigit (*format))
216 const char *f = format;
221 m = 10 * m + (*f - '0');
224 while (isdigit (*f));
230 *invalid_reason = INVALID_ARGNO_0 (spec.directives);
231 FDI_SET (f, FMTDIR_ERROR);
242 if (*format == ' ' || *format == '+' || *format == '-'
243 || *format == '#' || *format == '0' || *format == '\'')
245 else if (translated && *format == 'I')
247 spec.sysdep_directives =
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++;
264 unsigned int width_number = 0;
268 if (isdigit (*format))
270 const char *f = format;
275 m = 10 * m + (*f - '0');
278 while (isdigit (*f));
285 INVALID_WIDTH_ARGNO_0 (spec.directives);
286 FDI_SET (f, FMTDIR_ERROR);
296 /* Numbered argument. */
298 /* Numbered and unnumbered specifications are exclusive. */
299 if (spec.unnumbered_arg_count > 0)
301 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
302 FDI_SET (format - 1, FMTDIR_ERROR);
306 if (spec.allocated == numbered_arg_count)
308 spec.allocated = 2 * spec.allocated + 1;
309 numbered = (struct numbered_arg *) xrealloc (numbered, spec.allocated * sizeof (struct numbered_arg));
311 numbered[numbered_arg_count].number = width_number;
312 numbered[numbered_arg_count].type = FAT_INTEGER;
313 numbered_arg_count++;
317 /* Unnumbered argument. */
319 /* Numbered and unnumbered specifications are exclusive. */
320 if (numbered_arg_count > 0)
322 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
323 FDI_SET (format - 1, FMTDIR_ERROR);
327 if (spec.allocated == spec.unnumbered_arg_count)
329 spec.allocated = 2 * spec.allocated + 1;
330 spec.unnumbered = (struct unnumbered_arg *) xrealloc (spec.unnumbered, spec.allocated * sizeof (struct unnumbered_arg));
332 spec.unnumbered[spec.unnumbered_arg_count].type = FAT_INTEGER;
333 spec.unnumbered_arg_count++;
336 else if (isdigit (*format))
338 do format++; while (isdigit (*format));
341 /* Parse precision. */
348 unsigned int precision_number = 0;
352 if (isdigit (*format))
354 const char *f = format;
359 m = 10 * m + (*f - '0');
362 while (isdigit (*f));
369 INVALID_PRECISION_ARGNO_0 (spec.directives);
370 FDI_SET (f, FMTDIR_ERROR);
373 precision_number = m;
378 if (precision_number)
380 /* Numbered argument. */
382 /* Numbered and unnumbered specifications are exclusive. */
383 if (spec.unnumbered_arg_count > 0)
385 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
386 FDI_SET (format - 1, FMTDIR_ERROR);
390 if (spec.allocated == numbered_arg_count)
392 spec.allocated = 2 * spec.allocated + 1;
393 numbered = (struct numbered_arg *) xrealloc (numbered, spec.allocated * sizeof (struct numbered_arg));
395 numbered[numbered_arg_count].number = precision_number;
396 numbered[numbered_arg_count].type = FAT_INTEGER;
397 numbered_arg_count++;
401 /* Unnumbered argument. */
403 /* Numbered and unnumbered specifications are exclusive. */
404 if (numbered_arg_count > 0)
406 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
407 FDI_SET (format - 1, FMTDIR_ERROR);
411 if (spec.allocated == spec.unnumbered_arg_count)
413 spec.allocated = 2 * spec.allocated + 1;
414 spec.unnumbered = (struct unnumbered_arg *) xrealloc (spec.unnumbered, spec.allocated * sizeof (struct unnumbered_arg));
416 spec.unnumbered[spec.unnumbered_arg_count].type = FAT_INTEGER;
417 spec.unnumbered_arg_count++;
420 else if (isdigit (*format))
422 do format++; while (isdigit (*format));
428 spec.sysdep_directives =
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;
436 /* Parse ISO C 99 section 7.8.1 format string directive.
438 P R I { d | i | o | u | x | X }
439 { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR } */
442 *invalid_reason = INVALID_C99_MACRO (spec.directives);
443 FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR);
449 *invalid_reason = INVALID_C99_MACRO (spec.directives);
450 FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR);
456 *invalid_reason = INVALID_C99_MACRO (spec.directives);
457 FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR);
467 case 'u': case 'o': case 'x': case 'X':
468 type = FAT_INTEGER | FAT_UNSIGNED;
471 *invalid_reason = INVALID_C99_MACRO (spec.directives);
472 FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR);
477 if (format[0] == 'M' && format[1] == 'A' && format[2] == 'X')
479 type |= FAT_SIZE_INTMAX_T;
482 else if (format[0] == 'P' && format[1] == 'T' && format[2] == 'R')
484 type |= FAT_SIZE_INTPTR_T;
489 if (format[0] == 'L' && format[1] == 'E' && format[2] == 'A'
490 && format[3] == 'S' && format[4] == 'T')
493 if (format[0] == '8')
495 type |= FAT_SIZE_LEAST8_T;
498 else if (format[0] == '1' && format[1] == '6')
500 type |= FAT_SIZE_LEAST16_T;
503 else if (format[0] == '3' && format[1] == '2')
505 type |= FAT_SIZE_LEAST32_T;
508 else if (format[0] == '6' && format[1] == '4')
510 type |= FAT_SIZE_LEAST64_T;
515 *invalid_reason = INVALID_C99_MACRO (spec.directives);
516 FDI_SET (*format == '\0' ? format - 1 : format,
521 else if (format[0] == 'F' && format[1] == 'A'
522 && format[2] == 'S' && format[3] == 'T')
525 if (format[0] == '8')
527 type |= FAT_SIZE_FAST8_T;
530 else if (format[0] == '1' && format[1] == '6')
532 type |= FAT_SIZE_FAST16_T;
535 else if (format[0] == '3' && format[1] == '2')
537 type |= FAT_SIZE_FAST32_T;
540 else if (format[0] == '6' && format[1] == '4')
542 type |= FAT_SIZE_FAST64_T;
547 *invalid_reason = INVALID_C99_MACRO (spec.directives);
548 FDI_SET (*format == '\0' ? format - 1 : format,
555 if (format[0] == '8')
557 type |= FAT_SIZE_8_T;
560 else if (format[0] == '1' && format[1] == '6')
562 type |= FAT_SIZE_16_T;
565 else if (format[0] == '3' && format[1] == '2')
567 type |= FAT_SIZE_32_T;
570 else if (format[0] == '6' && format[1] == '4')
572 type |= FAT_SIZE_64_T;
577 *invalid_reason = INVALID_C99_MACRO (spec.directives);
578 FDI_SET (*format == '\0' ? format - 1 : format,
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);
593 spec.sysdep_directives[2 * spec.sysdep_directives_count + 1] = format + 1;
594 spec.sysdep_directives_count++;
604 if (size & (FAT_SIZE_SHORT | FAT_SIZE_CHAR))
605 size = FAT_SIZE_CHAR;
607 size = FAT_SIZE_SHORT;
609 else if (*format == 'l')
611 if (size & (FAT_SIZE_LONG | FAT_SIZE_LONGLONG))
612 size = FAT_SIZE_LONGLONG;
614 size = FAT_SIZE_LONG;
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;
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;
644 case 'm': /* glibc extension */
649 type |= (size & (FAT_SIZE_LONG | FAT_SIZE_LONGLONG)
652 case 'C': /* obsolete */
653 type = FAT_CHAR | FAT_WIDE;
657 type |= (size & (FAT_SIZE_LONG | FAT_SIZE_LONGLONG)
660 case 'S': /* obsolete */
661 type = FAT_STRING | FAT_WIDE;
665 type |= (size & FAT_SIZE_MASK);
667 case 'u': case 'o': case 'x': case 'X':
668 type = FAT_INTEGER | FAT_UNSIGNED;
669 type |= (size & FAT_SIZE_MASK);
671 case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
674 type |= (size & FAT_SIZE_LONGLONG);
679 type = FAT_OBJC_OBJECT;
687 type = FAT_COUNT_POINTER;
688 type |= (size & FAT_SIZE_MASK);
694 *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
695 FDI_SET (format - 1, FMTDIR_ERROR);
700 INVALID_CONVERSION_SPECIFIER (spec.directives, *format);
701 FDI_SET (format, FMTDIR_ERROR);
707 if (type != FAT_NONE)
711 /* Numbered argument. */
713 /* Numbered and unnumbered specifications are exclusive. */
714 if (spec.unnumbered_arg_count > 0)
716 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
717 FDI_SET (format, FMTDIR_ERROR);
721 if (spec.allocated == numbered_arg_count)
723 spec.allocated = 2 * spec.allocated + 1;
724 numbered = (struct numbered_arg *) xrealloc (numbered, spec.allocated * sizeof (struct numbered_arg));
726 numbered[numbered_arg_count].number = number;
727 numbered[numbered_arg_count].type = type;
728 numbered_arg_count++;
732 /* Unnumbered argument. */
734 /* Numbered and unnumbered specifications are exclusive. */
735 if (numbered_arg_count > 0)
737 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
738 FDI_SET (format, FMTDIR_ERROR);
742 if (spec.allocated == spec.unnumbered_arg_count)
744 spec.allocated = 2 * spec.allocated + 1;
745 spec.unnumbered = (struct unnumbered_arg *) xrealloc (spec.unnumbered, spec.allocated * sizeof (struct unnumbered_arg));
747 spec.unnumbered[spec.unnumbered_arg_count].type = type;
748 spec.unnumbered_arg_count++;
752 FDI_SET (format, FMTDIR_END);
757 /* Sort the numbered argument array, and eliminate duplicates. */
758 if (numbered_arg_count > 1)
763 qsort (numbered, numbered_arg_count,
764 sizeof (struct numbered_arg), numbered_arg_compare);
766 /* Remove duplicates: Copy from i to j, keeping 0 <= j <= i. */
768 for (i = j = 0; i < numbered_arg_count; i++)
769 if (j > 0 && numbered[i].number == numbered[j-1].number)
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;
779 /* Incompatible types. */
780 type_both = FAT_NONE;
783 INVALID_INCOMPATIBLE_ARG_TYPES (numbered[i].number);
787 numbered[j-1].type = type_both;
793 numbered[j].number = numbered[i].number;
794 numbered[j].type = numbered[i].type;
798 numbered_arg_count = j;
800 /* *invalid_reason has already been set above. */
804 /* Verify that the format strings uses all arguments up to the highest
806 if (numbered_arg_count > 0)
810 for (i = 0; i < numbered_arg_count; i++)
811 if (numbered[i].number != i + 1)
814 xasprintf (_("The string refers to argument number %u but ignores argument number %u."), numbered[i].number, i + 1);
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;
826 numbered_arg_count = 0;
829 result = XMALLOC (struct spec);
834 if (numbered != NULL)
836 if (spec.unnumbered != NULL)
837 free (spec.unnumbered);
838 if (spec.sysdep_directives != NULL)
839 free (spec.sysdep_directives);
844 format_c_parse (const char *format, bool translated, char *fdi,
845 char **invalid_reason)
847 return format_parse (format, translated, false, fdi, invalid_reason);
851 format_objc_parse (const char *format, bool translated, char *fdi,
852 char **invalid_reason)
854 return format_parse (format, translated, true, fdi, invalid_reason);
858 format_free (void *descr)
860 struct spec *spec = (struct spec *) descr;
862 if (spec->unnumbered != NULL)
863 free (spec->unnumbered);
864 if (spec->sysdep_directives != NULL)
865 free (spec->sysdep_directives);
870 format_is_unlikely_intentional (void *descr)
872 struct spec *spec = (struct spec *) descr;
874 return spec->unlikely_intentional;
878 format_get_number_of_directives (void *descr)
880 struct spec *spec = (struct spec *) descr;
882 return spec->directives;
886 format_check (void *msgid_descr, void *msgstr_descr, bool equality,
887 formatstring_error_logger_t error_logger,
888 const char *pretty_msgid, const char *pretty_msgstr)
890 struct spec *spec1 = (struct spec *) msgid_descr;
891 struct spec *spec2 = (struct spec *) msgstr_descr;
895 /* Check the argument types are the same. */
897 ? spec1->unnumbered_arg_count != spec2->unnumbered_arg_count
898 : spec1->unnumbered_arg_count < spec2->unnumbered_arg_count)
901 error_logger (_("number of format specifications in '%s' and '%s' does not match"),
902 pretty_msgid, pretty_msgstr);
906 for (i = 0; i < spec2->unnumbered_arg_count; i++)
907 if (spec1->unnumbered[i].type != spec2->unnumbered[i].type)
910 error_logger (_("format specifications in '%s' and '%s' for argument %u are not the same"),
911 pretty_msgid, pretty_msgstr, i + 1);
919 struct formatstring_parser formatstring_c =
923 format_get_number_of_directives,
924 format_is_unlikely_intentional,
929 struct formatstring_parser formatstring_objc =
933 format_get_number_of_directives,
934 format_is_unlikely_intentional,
940 get_sysdep_c_format_directives (const char *string, bool translated,
941 struct interval **intervalsp, size_t *lengthp)
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;
949 format_parse (string, translated, true, NULL, &invalid_reason);
951 if (descr != NULL && descr->sysdep_directives_count > 0)
953 unsigned int n = descr->sysdep_directives_count;
954 struct interval *intervals = XNMALLOC (n, struct interval);
957 for (i = 0; i < n; i++)
959 intervals[i].startpos = descr->sysdep_directives[2 * i] - string;
960 intervals[i].endpos = descr->sysdep_directives[2 * i + 1] - string;
962 *intervalsp = intervals;
974 free (invalid_reason);
980 /* Test program: Print the argument list specification returned by
981 format_parse for strings read from standard input. */
986 format_print (void *descr)
988 struct spec *spec = (struct spec *) descr;
998 for (i = 0; i < spec->unnumbered_arg_count; i++)
1002 if (spec->unnumbered[i].type & FAT_UNSIGNED)
1003 printf ("[unsigned]");
1004 switch (spec->unnumbered[i].type & FAT_SIZE_MASK)
1008 case FAT_SIZE_SHORT:
1017 case FAT_SIZE_LONGLONG:
1018 printf ("[long long]");
1021 printf ("[int8_t]");
1024 printf ("[int16_t]");
1027 printf ("[int32_t]");
1030 printf ("[int64_t]");
1032 case FAT_SIZE_LEAST8_T:
1033 printf ("[int_least8_t]");
1035 case FAT_SIZE_LEAST16_T:
1036 printf ("[int_least16_t]");
1038 case FAT_SIZE_LEAST32_T:
1039 printf ("[int_least32_t]");
1041 case FAT_SIZE_LEAST64_T:
1042 printf ("[int_least64_t]");
1044 case FAT_SIZE_FAST8_T:
1045 printf ("[int_fast8_t]");
1047 case FAT_SIZE_FAST16_T:
1048 printf ("[int_fast16_t]");
1050 case FAT_SIZE_FAST32_T:
1051 printf ("[int_fast32_t]");
1053 case FAT_SIZE_FAST64_T:
1054 printf ("[int_fast64_t]");
1056 case FAT_SIZE_INTMAX_T:
1057 printf ("[intmax_t]");
1059 case FAT_SIZE_INTPTR_T:
1060 printf ("[intptr_t]");
1062 case FAT_SIZE_SIZE_T:
1063 printf ("[size_t]");
1065 case FAT_SIZE_PTRDIFF_T:
1066 printf ("[ptrdiff_t]");
1071 switch (spec->unnumbered[i].type & ~(FAT_UNSIGNED | FAT_SIZE_MASK))
1085 case FAT_OBJC_OBJECT:
1091 case FAT_COUNT_POINTER:
1107 size_t line_size = 0;
1109 char *invalid_reason;
1112 line_len = getline (&line, &line_size, stdin);
1115 if (line_len > 0 && line[line_len - 1] == '\n')
1116 line[--line_len] = '\0';
1118 invalid_reason = NULL;
1119 descr = format_c_parse (line, false, NULL, &invalid_reason);
1121 format_print (descr);
1124 printf ("%s\n", invalid_reason);
1126 free (invalid_reason);
1134 * For Emacs M-x compile
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"